diff --git a/checkin_notes b/checkin_notes index 91f46951ee..0d3f5ae8a1 100755 --- a/checkin_notes +++ b/checkin_notes @@ -5243,3 +5243,21 @@ Karl 2003/07/02 configure.ac client/ Makefile.am + +Karl 2003/07/02 + - changed when "deferring communication" messages are printed so that user + sees them on client startup and every hour. Also format the message as + "X hours, X minutes, X seconds", etc. + + lib/ + util.h + util.c + + client/ + client_types.C + client_types.h + cs_scheduler.C + scheduler_op.C + scheduler_op.h + + diff --git a/client/client_types.C b/client/client_types.C index 40db2dc84a..8616ec7737 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -56,6 +56,7 @@ void PROJECT::init() { strcpy(code_sign_key, ""); nrpc_failures = 0; min_rpc_time = 0; + min_report_min_rpc_time = 0; master_fetch_failures = 0; resource_debt = 0; debt_order = 0; @@ -179,6 +180,7 @@ int PROJECT::parse_state(FILE* in) { exp_avg_cpu = 0; exp_avg_mod_time = 0; min_rpc_time = 0; + min_report_min_rpc_time = 0; nrpc_failures = 0; master_url_fetch_pending = false; sched_rpc_pending = false; @@ -214,7 +216,7 @@ int PROJECT::parse_state(FILE* in) { } else if (parse_int(buf, "", nrpc_failures)) continue; else if (parse_int(buf, "", master_fetch_failures)) continue; - else if (parse_int(buf, "", min_rpc_time)) continue; + else if (parse_int(buf, "", (int&)min_rpc_time)) continue; else if (match_tag(buf, "")) master_url_fetch_pending = true; else if (match_tag(buf, "")) sched_rpc_pending = true; else fprintf(stderr, "PROJECT::parse_state(): unrecognized: %s\n", buf); diff --git a/client/client_types.h b/client/client_types.h index 280b21b4c8..5250d1e462 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -2,18 +2,18 @@ // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://boinc.berkeley.edu/license_1.0.txt -// +// // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// +// University of California at Berkeley. All Rights Reserved. +// // Contributor(s): // @@ -71,14 +71,16 @@ public: int hostid; double host_total_credit; // as reported by server double host_expavg_credit; // as reported by server - unsigned int host_create_time; // as reported by server + unsigned int host_create_time; // as reported by server double exp_avg_cpu; // exponentially weighted CPU time int exp_avg_mod_time; // last time average was changed int nrpc_failures; // # of consecutive times we've failed to // contact all scheduling servers int master_fetch_failures; - int min_rpc_time; // earliest time to contact any server - // of this project (or zero) + time_t min_rpc_time; // earliest time to contact any server + // of this project (or zero) + time_t min_report_min_rpc_time; // when to next report on min_rpc_time + // (or zero) bool master_url_fetch_pending; // need to fetch and parse the master URL bool sched_rpc_pending; // contact scheduling server for preferences @@ -99,6 +101,11 @@ public: int parse_account(FILE*); int parse_state(FILE*); int write_state(FILE*); + + // set min_rpc_time and have_reported_min_rpc_time + void set_min_rpc_time(time_t future_time); + // returns true if min_rpc_time > now; may print a message + bool waiting_until_min_rpc_time(time_t now); }; struct APP { @@ -212,9 +219,9 @@ struct RESULT { vector output_files; bool is_active; // an app is currently running for this bool ready_to_ack; // all the files have been uploaded or there - // was an error and we are ready to report this to + // was an error and we are ready to report this to // the server - bool server_ack; // received the ack for the report of + bool server_ack; // received the ack for the report of // the status of the result from server double final_cpu_time; int state; // state of this result, see above @@ -223,7 +230,7 @@ struct RESULT { // defined only if active_task_state is PROCESS_SIGNALED int active_task_state; // the state of the active task corresponding to this result string stderr_out; - + APP* app; WORKUNIT* wup; PROJECT* project; diff --git a/client/cs_scheduler.C b/client/cs_scheduler.C index d9b032991b..04e2244d3a 100644 --- a/client/cs_scheduler.C +++ b/client/cs_scheduler.C @@ -44,6 +44,8 @@ // #define EXP_DECAY_RATE (1./(SECONDS_PER_DAY*7)) +const int SECONDS_BEFORE_REPORTING_MIN_RPC_TIME_AGAIN = 60*60; + // estimate the days of work remaining // double CLIENT_STATE::current_work_buf_days() { @@ -82,6 +84,28 @@ void CLIENT_STATE::update_avg_cpu(PROJECT* p) { } } +void PROJECT::set_min_rpc_time(time_t future_time) +{ + min_rpc_time = future_time; + min_report_min_rpc_time = 0; // report immediately +} + +// Return true iff we should not contact the project yet. Print a message to +// the user if we haven't recently +bool PROJECT::waiting_until_min_rpc_time(time_t now) +{ + if (min_rpc_time > now ) { + if (now >= min_report_min_rpc_time) { + min_report_min_rpc_time = now + SECONDS_BEFORE_REPORTING_MIN_RPC_TIME_AGAIN; + msg_printf(this, MSG_ERROR, + "Deferring communication with project for %s\n", + timediff_format(min_rpc_time - now).c_str()); + } + return true; + } + return false; +} + // find a project that needs its master file parsed // PROJECT* CLIENT_STATE::next_project_master_pending() { @@ -91,7 +115,7 @@ PROJECT* CLIENT_STATE::next_project_master_pending() { for (i=0; imin_rpc_time > now ) continue; + if (p->waiting_until_min_rpc_time(now)) continue; if (p->master_url_fetch_pending) { return p; } @@ -106,7 +130,7 @@ PROJECT* CLIENT_STATE::next_project_sched_rpc_pending() { time_t now = time(0); for (i=0; imin_rpc_time > now) continue; + if (projects[i]->waiting_until_min_rpc_time(now)) continue; if (projects[i]->sched_rpc_pending) { return projects[i]; } @@ -128,7 +152,7 @@ PROJECT* CLIENT_STATE::next_project(PROJECT* old) { for (i=0; imaster_url_fetch_pending) continue; - if (p->min_rpc_time > now ) continue; + if (p->waiting_until_min_rpc_time(now)) continue; if (old && p->debt_order <= old->debt_order) continue; if (p->debt_order < best) { pbest = p; @@ -258,7 +282,8 @@ PROJECT* CLIENT_STATE::find_project_with_overdue_results() { r = results[i]; // If we've completed computation but haven't finished reporting the // results to the server, return the project for this result - if (r->ready_to_ack && (r->project->min_rpc_time < now)) { + if (r->project->waiting_until_min_rpc_time(now)) continue; + if (r->ready_to_ack) { return r->project; } } diff --git a/client/scheduler_op.C b/client/scheduler_op.C index 17ae366231..f57363c72f 100644 --- a/client/scheduler_op.C +++ b/client/scheduler_op.C @@ -154,10 +154,9 @@ int SCHEDULER_OP::set_min_rpc_time(PROJECT* p) { gstate.retry_base_period ); } - p->min_rpc_time = time(0) + exp_backoff; - msg_printf(p, MSG_ERROR, - "Deferring communication with project for %d seconds\n", exp_backoff - ); + p->set_min_rpc_time(time(0) + exp_backoff); + // note: we don't need to print a message now, it will be printed the + // next time p->waiting_until_min_rpc_time() is called. return 0; } diff --git a/client/scheduler_op.h b/client/scheduler_op.h index 4c2de145b1..404ff1b300 100644 --- a/client/scheduler_op.h +++ b/client/scheduler_op.h @@ -2,18 +2,18 @@ // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://boinc.berkeley.edu/license_1.0.txt -// +// // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// +// University of California at Berkeley. All Rights Reserved. +// // Contributor(s): // diff --git a/lib/util.C b/lib/util.C index e75cfc912d..a1743f00c9 100755 --- a/lib/util.C +++ b/lib/util.C @@ -2,18 +2,18 @@ // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://boinc.berkeley.edu/license_1.0.txt -// +// // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// +// University of California at Berkeley. All Rights Reserved. +// // Contributor(s): // @@ -445,3 +445,39 @@ int calculate_exponential_backoff(const char* debug_descr, int n, double MIN, do return (int) rand_range(MIN, rmax); } + +string timediff_format(long tdiff) +{ + char buf[256]; + + int sex = tdiff % 60; + tdiff /= 60; + if (!tdiff) { + sprintf(buf, "%d seconds", sex); + return buf; + } + + int min = tdiff % 60; + tdiff /= 60; + if (!tdiff) { + sprintf(buf, "%d minutes and %d seconds", min, sex); + return buf; + } + + int hours = tdiff % 24; + tdiff /= 24; + if (!tdiff) { + sprintf(buf, "%d hours, %d minutes, and %d seconds", hours, min, sex); + return buf; + } + + int days = tdiff % 7; + tdiff /= 7; + if (!tdiff) { + sprintf(buf, "%d days, %d hours, %d minutes, and %d seconds", days, hours, min, sex); + return buf; + } + + sprintf(buf, "%d weeks, %d days, %d hours, %d minutes, and %d seconds", tdiff, days, hours, min, sex); + return buf; +} diff --git a/lib/util.h b/lib/util.h index 918a25ed80..78730a18fc 100755 --- a/lib/util.h +++ b/lib/util.h @@ -25,6 +25,8 @@ #include #include #include +#include +using std::string; extern int double_to_ydhms (double x, int smallest_timescale, char *buf); extern void get_byte_string(double nbytes, double total_bytes, char* str, int len); @@ -42,14 +44,9 @@ extern void safe_strncpy(char*, char*, int); #define safe_strcpy(x, y) safe_strncpy(x, y, sizeof(x)) #define safe_strcat(x, y) if (strlen(x)+strlen(y) (b)) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif +// NOTE: use #include to get max,min // the __attribute((format...)) tags are GCC extensions that let the compiler // do like-checking on printf-like arguments