diff --git a/checkin_notes b/checkin_notes index 2e98fa88b9..28e19a1779 100755 --- a/checkin_notes +++ b/checkin_notes @@ -5982,3 +5982,20 @@ Rom 3 May 2005 clientgui/ ViewStatistics.cpp + +David 3 May 2005 + - scheduler: fixed a bug where host::update() + could potentially overwrite a credit update + happening around the same time. + Did this by adding a function HOST::update_diff(HOST& initial) + which does an update only of those fields that have + changed relative to the given initial values. + (from Bruce Allen) + - removed unused "p_calculated" from HOST + - removed code to parse non-existent fields p_fpop_err etc. in HOST + + db/ + boinc_db.C,h + sched/ + handle_request.C + server_types.C diff --git a/db/boinc_db.C b/db/boinc_db.C index 319dd4e597..ca6e476802 100644 --- a/db/boinc_db.C +++ b/db/boinc_db.C @@ -409,6 +409,161 @@ void DB_HOST::db_parse(MYSQL_ROW &r) { max_results_day = atoi(r[i++]); } +// update fields that differ from the argument HOST +// +int DB_HOST::update_diff(HOST& h) { + char buf[LARGE_BLOB_SIZE], updates[LARGE_BLOB_SIZE], query[LARGE_BLOB_SIZE]; + strcpy(updates, ""); + if (rpc_seqno != h.rpc_seqno) { + sprintf(buf, " rpc_seqno=%d,", rpc_seqno); + strcat(updates, buf); + } + if (rpc_time != h.rpc_time) { + sprintf(buf, " rpc_time=%d,", rpc_time); + strcat(updates, buf); + } + if (timezone != h.timezone) { + sprintf(buf, " timezone=%d,", timezone); + strcat(updates, buf); + } + if (strcmp(domain_name, h.domain_name)) { + sprintf(buf, " domain_name='%s',", domain_name); + strcat(updates, buf); + } + if (strcmp(serialnum, h.serialnum)) { + sprintf(buf, " serialnum='%s',", serialnum); + strcat(updates, buf); + } + if (strcmp(last_ip_addr, h.last_ip_addr)) { + sprintf(buf, " last_ip_addr='%s',", last_ip_addr); + strcat(updates, buf); + } + if (nsame_ip_addr != h.nsame_ip_addr) { + sprintf(buf, " nsame_ip_addr=%d,", nsame_ip_addr); + strcat(updates, buf); + } + if (on_frac != h.on_frac) { + sprintf(buf, " on_frac=%f,", on_frac); + strcat(updates, buf); + } + if (connected_frac != h.connected_frac) { + sprintf(buf, " connected_frac=%f,", connected_frac); + strcat(updates, buf); + } + if (active_frac != h.active_frac) { + sprintf(buf, " active_frac=%f,", active_frac); + strcat(updates, buf); + } + if (p_ncpus != h.p_ncpus) { + sprintf(buf, " p_ncpus=%d,", p_ncpus); + strcat(updates, buf); + } + if (strcmp(p_vendor, h.p_vendor)) { + sprintf(buf, " p_vendor='%s',", p_vendor); + strcat(updates, buf); + } + if (strcmp(p_model, h.p_model)) { + sprintf(buf, " p_model='%s',", p_model); + strcat(updates, buf); + } + if (p_fpops != h.p_fpops) { + sprintf(buf, " p_fpops=%f,", p_fpops); + strcat(updates, buf); + } + if (p_iops != h.p_iops) { + sprintf(buf, " p_iops=%f,", p_iops); + strcat(updates, buf); + } + if (p_membw != h.p_membw) { + sprintf(buf, " p_membw=%f,", p_membw); + strcat(updates, buf); + } + if (strcmp(os_name, h.os_name)) { + sprintf(buf, " os_name='%s',", os_name); + strcat(updates, buf); + } + if (strcmp(os_version, h.os_version)) { + sprintf(buf, " os_version='%s',", os_version); + strcat(updates, buf); + } + if (m_nbytes != h.m_nbytes) { + sprintf(buf, " m_nbytes=%f,", m_nbytes); + strcat(updates, buf); + } + if (m_cache != h.m_cache) { + sprintf(buf, " m_cache=%f,", m_cache); + strcat(updates, buf); + } + if (m_swap != h.m_swap) { + sprintf(buf, " m_swap=%f,", m_swap); + strcat(updates, buf); + } + if (d_total != h.d_total) { + sprintf(buf, " d_total=%f,", d_total); + strcat(updates, buf); + } + if (d_free != h.d_free) { + sprintf(buf, " d_free=%f,", d_free); + strcat(updates, buf); + } + if (d_boinc_used_total != h.d_boinc_used_total) { + sprintf(buf, " d_boinc_used_total=%f,", d_boinc_used_total); + strcat(updates, buf); + } + if (d_boinc_used_project != h.d_boinc_used_project) { + sprintf(buf, " d_boinc_used_project=%f,", d_boinc_used_project); + strcat(updates, buf); + } + if (d_boinc_max != h.d_boinc_max) { + sprintf(buf, " d_boinc_max=%f,", d_boinc_max); + strcat(updates, buf); + } + if (n_bwup != h.n_bwup) { + sprintf(buf, " n_bwup=%f,", n_bwup); + strcat(updates, buf); + } + if (credit_per_cpu_sec != h.credit_per_cpu_sec) { + sprintf(buf, " credit_per_cpu_sec=%f,", credit_per_cpu_sec); + strcat(updates, buf); + } + if (strcmp(venue, h.venue)) { + sprintf(buf, " venue='%s',", venue); + strcat(updates, buf); + } + if (nresults_today != h.nresults_today) { + sprintf(buf, " nresults_today=%d,", nresults_today); + strcat(updates, buf); + } + if (avg_turnaround != h.avg_turnaround) { + sprintf(buf, " avg_turnaround=%f,", avg_turnaround); + strcat(updates, buf); + } + if (strcmp(host_cpid, h.host_cpid)) { + sprintf(buf, " host_cpid='%s',", host_cpid); + strcat(updates, buf); + } + if (strcmp(external_ip_addr, h.external_ip_addr)) { + sprintf(buf, " external_ip_addr='%s',", external_ip_addr); + strcat(updates, buf); + } + if (max_results_day != h.max_results_day) { + sprintf(buf, " max_results_day=%d,", max_results_day); + strcat(updates, buf); + } + + int n = strlen(updates); + if (n == 0) { + return 0; + } + + // trim the final comma + // + updates[n-1] = 0; + + sprintf(query, "update host set %s where id=%d", updates, id); + return db->do_query(query); +} + void DB_WORKUNIT::db_print(char* buf){ sprintf(buf, "create_time=%d, appid=%d, " diff --git a/db/boinc_db.h b/db/boinc_db.h index 820e8bc727..2c179b3b82 100755 --- a/db/boinc_db.h +++ b/db/boinc_db.h @@ -215,7 +215,6 @@ struct HOST { double p_iops; // measured integer ops/sec of CPU double p_membw; // measured memory bandwidth (bytes/sec) of CPU // The above are per CPU, not total - double p_calculated; // when the above were calculated char os_name[256]; // Name of operating system char os_version[256]; // Version of operating system @@ -525,6 +524,7 @@ class DB_HOST : public DB_BASE, public HOST { public: DB_HOST(DB_CONN* p=0); int get_id(); + int update_diff(HOST&); void db_print(char*); void db_parse(MYSQL_ROW &row); void operator=(HOST& r) {HOST::operator=(r);} diff --git a/doc/credit.php b/doc/credit.php index d755331e43..2eda2df7ce 100644 --- a/doc/credit.php +++ b/doc/credit.php @@ -70,29 +70,35 @@ Each time new credit is granted, the following function is used to update the recent average credit of the host, user and team:
",htmlspecialchars(" -#define CREDIT_HALF_LIFE (SECONDS_IN_DAY*7) -// Update an estimate of \"units per day\" of something (credit or CPU time). -// The estimate is exponentially averaged with a given half-life -// (i.e. if no new work is done, the average will decline by 50% in this time). -// This function can be called either with new work, -// or with zero work to decay an existing average. -// void update_average( - double now, // current time double work_start_time, // when new work was started // (or zero if no new work) double work, // amount of new work + double half_life, double& avg, // average work per day (in and out) double& avg_time // when average was last computed ) { + double now = dtime(); + if (avg_time) { - double diff = now - avg_time; - double diff_days = diff/SECONDS_PER_DAY; - double weight = exp(-diff*M_LN2/CREDIT_HALF_LIFE); + double diff, diff_days, weight; + + diff = now - avg_time; + if (diff<0) diff=0; + + diff_days = diff/SECONDS_PER_DAY; + weight = exp(-diff*M_LN2/half_life); + avg *= weight; - avg += (1-weight)*(work/diff_days); - } else { + + if ((1.0-weight) > 1.e-6) { + avg += (1-weight)*(work/diff_days); + } + else { + avg += M_LN2*work*SECONDS_PER_DAY/half_life; + } + } else if (work) { double dd = (now - work_start_time)/SECONDS_PER_DAY; avg = work/dd; } diff --git a/sched/handle_request.C b/sched/handle_request.C index 515ab66e1d..090a1e166a 100644 --- a/sched/handle_request.C +++ b/sched/handle_request.C @@ -302,7 +302,6 @@ static int modify_host_struct(SCHEDULER_REQUEST& sreq, HOST& host) { host.p_fpops = sreq.host.p_fpops; host.p_iops = sreq.host.p_iops; host.p_membw = sreq.host.p_membw; - host.p_calculated = sreq.host.p_calculated; strncpy(host.os_name, sreq.host.os_name, sizeof(host.os_name)); strncpy(host.os_version, sreq.host.os_version, sizeof(host.os_version)); host.m_nbytes = sreq.host.m_nbytes; @@ -312,13 +311,16 @@ static int modify_host_struct(SCHEDULER_REQUEST& sreq, HOST& host) { host.d_free = sreq.host.d_free; host.n_bwup = sreq.host.n_bwup; host.n_bwdown = sreq.host.n_bwdown; + if (strlen(sreq.host.host_cpid)) { + strcpy(host.host_cpid, sreq.host.host_cpid); + } host.fix_nans(); compute_credit_rating(host); return 0; } -static int update_host_record(HOST& xhost, USER& user) { +static int update_host_record(HOST& initial_host, HOST& xhost, USER& user) { DB_HOST host; int retval; char buf[1024]; @@ -333,7 +335,7 @@ static int update_host_record(HOST& xhost, USER& user) { if (p) { strlcpy(host.external_ip_addr, p, sizeof(host.external_ip_addr)); } - retval = host.update(); + retval = host.update_diff(initial_host); if (retval) { log_messages.printf(SCHED_MSG_LOG::CRITICAL, "host.update() failed: %d\n", retval); } @@ -881,6 +883,7 @@ void process_request( bool ok_to_send_work = true; bool have_no_work; char buf[256]; + HOST initial_host; // if different major version of BOINC, just send a message // @@ -942,6 +945,7 @@ void process_request( if (reply.user.id == 0) { log_messages.printf(SCHED_MSG_LOG::CRITICAL, "No user ID!\n"); } + initial_host = reply.host; log_messages.printf( SCHED_MSG_LOG::NORMAL, @@ -1031,7 +1035,7 @@ void process_request( handle_msgs_to_host(reply); } - update_host_record(reply.host, reply.user); + update_host_record(initial_host, reply.host, reply.user); leave: if (!have_no_work) { diff --git a/sched/server_types.C b/sched/server_types.C index 55262952a6..4b59007885 100644 --- a/sched/server_types.C +++ b/sched/server_types.C @@ -639,7 +639,6 @@ int RESULT::parse_from_client(FILE* fin) { // int HOST::parse(FILE* fin) { char buf[256]; - int p_fpop_err, p_iop_err, p_membw_err; p_ncpus = 1; while (fgets(buf, 256, fin)) { @@ -655,10 +654,6 @@ int HOST::parse(FILE* fin) { else if (parse_double(buf, "", p_fpops)) continue; else if (parse_double(buf, " ", p_iops)) continue; else if (parse_double(buf, " ", p_membw)) continue; - else if (parse_int(buf, " ", p_fpop_err)) continue; - else if (parse_int(buf, " ", p_iop_err)) continue; - else if (parse_int(buf, " ", p_membw_err)) continue; - else if (parse_double(buf, " ", p_calculated)) continue; else if (parse_str(buf, " ", os_name, sizeof(os_name))) continue; else if (parse_str(buf, " ", os_version, sizeof(os_version))) continue; else if (parse_double(buf, " ", m_nbytes)) continue; @@ -669,7 +664,9 @@ int HOST::parse(FILE* fin) { else if (parse_double(buf, " ", n_bwup)) continue; else if (parse_double(buf, " ", n_bwdown)) continue; else { - log_messages.printf(SCHED_MSG_LOG::NORMAL, "HOST::parse(): unrecognized: %s\n", buf); + log_messages.printf(SCHED_MSG_LOG::NORMAL, + "HOST::parse(): unrecognized: %s\n", buf + ); } } return ERR_XML_PARSE;