diff --git a/checkin_notes b/checkin_notes
index e5d0ec5513..c03b71a90c 100755
--- a/checkin_notes
+++ b/checkin_notes
@@ -23583,3 +23583,17 @@ Janus 31 Jan 05
user/
apps.php
+David 31 Jan 2005
+ - Make it possible for a scheduler RPC reply to include several "messages",
+ each with its own message body and priority.
+ This involved changes to both scheduler and core client.
+ If the current core client gets several messages,
+ it will display only the last one.
+
+ client/
+ cs_scheduler.C
+ scheduler_op.C,h
+ sched/
+ handle_request.C
+ sched_send.C
+ server_types.C,h
diff --git a/client/cs_scheduler.C b/client/cs_scheduler.C
index 90280152e0..fe49d801f0 100644
--- a/client/cs_scheduler.C
+++ b/client/cs_scheduler.C
@@ -517,9 +517,10 @@ int CLIENT_STATE::handle_scheduler_reply(
fclose(f);
if (retval) return retval;
- if (strlen(sr.message)) {
- sprintf(buf, "Message from server: %s", sr.message);
- int prio = (!strcmp(sr.message_priority, "high"))?MSG_ERROR:MSG_INFO;
+ for (i=0; i")) {
message_ack = true;
@@ -759,4 +760,9 @@ int SCHEDULER_REPLY::parse(FILE* in, PROJECT* project) {
return ERR_XML_PARSE;
}
+USER_MESSAGE::USER_MESSAGE(char* m, char* p) {
+ message = m;
+ priority = p;
+}
+
const char *BOINC_RCSID_11c806525b = "$Id$";
diff --git a/client/scheduler_op.h b/client/scheduler_op.h
index 4f88bf8962..f4aa676bf4 100644
--- a/client/scheduler_op.h
+++ b/client/scheduler_op.h
@@ -30,6 +30,8 @@
// to get work as a side-effect
//
+#include
+
#include "client_types.h"
#include "http.h"
#include "prefs.h"
@@ -84,11 +86,16 @@ struct SCHEDULER_OP {
int parse_master_file(std::vector&);
};
+struct USER_MESSAGE {
+ std::string message;
+ std::string priority;
+ USER_MESSAGE(char*, char*);
+};
+
struct SCHEDULER_REPLY {
int hostid;
double request_delay;
- char message[1024];
- char message_priority[256];
+ std::vector messages;
char* global_prefs_xml;
// not including tags;
// may include elements
diff --git a/sched/handle_request.C b/sched/handle_request.C
index f3896cec5d..cbb4f5fa58 100644
--- a/sched/handle_request.C
+++ b/sched/handle_request.C
@@ -68,8 +68,8 @@ int authenticate_user(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& reply) {
if (sreq.hostid) {
retval = host.lookup_id(sreq.hostid);
if (retval) {
- strcpy(reply.message, "Can't find host record");
- strcpy(reply.message_priority, "low");
+ USER_MESSAGE um("Can't find host record", "low");
+ reply.insert_message(um);
log_messages.printf(
SCHED_MSG_LOG::NORMAL,
"[HOST#%d?] can't find host\n",
@@ -87,11 +87,11 @@ int authenticate_user(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& reply) {
sprintf(buf, "where authenticator='%s'", user.authenticator);
retval = user.lookup(buf);
if (retval) {
- strcpy(reply.message,
- "Invalid or missing account key. "
- "Visit this project's web site to get an account key."
+ USER_MESSAGE um("Invalid or missing account key. "
+ "Visit this project's web site to get an account key.",
+ "low"
);
- strcpy(reply.message_priority, "low");
+ reply.insert_message(um);
reply.request_delay = 3600;
reply.nucleus_only = true;
log_messages.printf(
@@ -142,11 +142,12 @@ lookup_user_and_make_new_host:
sprintf(buf, "where authenticator='%s'", user.authenticator);
retval = user.lookup(buf);
if (retval) {
- strcpy(reply.message,
+ USER_MESSAGE um(
"Invalid or missing account key. "
- "Visit this project's web site to get an account key."
+ "Visit this project's web site to get an account key.",
+ "low"
);
- strcpy(reply.message_priority, "low");
+ reply.insert_message(um);
reply.request_delay = 3600;
log_messages.printf(
SCHED_MSG_LOG::CRITICAL,
@@ -168,8 +169,8 @@ make_new_host:
host.fix_nans();
retval = host.insert();
if (retval) {
- strcpy(reply.message, "Couldn't create host record in database");
- strcpy(reply.message_priority, "low");
+ USER_MESSAGE um("Couldn't create host record in database", "low");
+ reply.insert_message(um);
boinc_db.print_error("host.insert()");
log_messages.printf(SCHED_MSG_LOG::CRITICAL, "host.insert() failed\n");
return retval;
@@ -372,16 +373,16 @@ int handle_results(
//
reply.result_acks.push_back(*rp);
- // get the result with the same name that came back from the
- // database and point srip to it. Quantities that MUST be
- // read from the DB are those where srip appears as an rval.
- // These are: id, name, server_state, received_time, hostid.
- // // Quantities that must be WRITTEN to the DB are those for
- // which srip appears as an lval. These are:
+ // get the result with the same name that came back from the
+ // database and point srip to it. Quantities that MUST be
+ // read from the DB are those where srip appears as an rval.
+ // These are: id, name, server_state, received_time, hostid.
+ // // Quantities that must be WRITTEN to the DB are those for
+ // which srip appears as an lval. These are:
// hostid,
- // teamid, received_time, client_state, cpu_time, exit_status,
- // app_version_num, claimed_credit, server_state, stderr_out,
- // xml_doc_out, outcome, validate_state
+ // teamid, received_time, client_state, cpu_time, exit_status,
+ // app_version_num, claimed_credit, server_state, stderr_out,
+ // xml_doc_out, outcome, validate_state
retval = result_handler.lookup_result(rp->name, &srip);
if (retval) {
@@ -578,22 +579,26 @@ void send_code_sign_key(
sprintf(path, "%s/old_key_%d", config.key_dir, i);
retval = read_file_malloc(path, oldkey);
if (retval) {
- strcpy(reply.message,
+ USER_MESSAGE um(
"You may have an outdated code verification key. "
"This may prevent you from accepting new executables. "
- "If the problem persists, detach/attach the project. "
+ "If the problem persists, detach/attach the project. ",
+ "high"
);
+ reply.insert_message(um);
return;
}
if (!strcmp(oldkey, sreq.code_sign_key)) {
sprintf(path, "%s/signature_%d", config.key_dir, i);
retval = read_file_malloc(path, signature);
if (retval) {
- strcpy(reply.message,
+ USER_MESSAGE um(
"You may have an outdated code verification key. "
"This may prevent you from accepting new executables. "
- "If the problem persists, detach/attach the project. "
+ "If the problem persists, detach/attach the project. ",
+ "high"
);
+ reply.insert_message(um);
} else {
safe_strcpy(reply.code_sign_key, code_sign_key);
safe_strcpy(reply.code_sign_key_signature, signature);
@@ -612,11 +617,12 @@ void send_code_sign_key(
bool wrong_core_client_version(
SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& reply
) {
+ char msg[256];
bool wrong_version = false;
if (sreq.core_client_major_version != BOINC_MAJOR_VERSION) {
// TODO: check for user-agent not empty and not BOINC
wrong_version = true;
- sprintf(reply.message,
+ sprintf(msg,
"To participate in this project, "
"you must use major version %d of the BOINC core client. "
"Your core client is major version %d.",
@@ -634,7 +640,7 @@ bool wrong_core_client_version(
int minor = config.min_core_client_version % 100;
if (sreq.core_client_minor_version < minor) {
wrong_version = true;
- sprintf(reply.message,
+ sprintf(msg,
"To participate in this project, "
"you must use version %d.02%d or higher of the BOINC core client. "
"Your core client is version %d.02%d.",
@@ -650,8 +656,9 @@ bool wrong_core_client_version(
}
}
if (wrong_version) {
+ USER_MESSAGE um(msg, "low");
+ reply.insert_message(um);
reply.probable_user_browser = true;
- strcpy(reply.message_priority, "low");
reply.request_delay = 3600*24;
return true;
}
@@ -740,6 +747,7 @@ void process_request(
int current_rpc_dayofyear;
bool ok_to_send_work = true;
bool have_no_work;
+ char buf[256];
// if different major version of BOINC, just send a message
//
@@ -766,8 +774,8 @@ void process_request(
&& (sreq.results.size() == 0)
&& (sreq.hostid != 0)
) {
- strcat(reply.message, "No work available");
- strcpy(reply.message_priority, "low");
+ USER_MESSAGE um("No work available", "low");
+ reply.insert_message(um);
reply.request_delay = 3600;
if (!config.msg_to_host) {
log_messages.printf(
@@ -820,8 +828,9 @@ void process_request(
//
platform = ss.lookup_platform(sreq.platform_name);
if (!platform) {
- sprintf(reply.message, "platform '%s' not found", sreq.platform_name);
- strcpy(reply.message_priority, "low");
+ sprintf(buf, "platform '%s' not found", sreq.platform_name);
+ USER_MESSAGE um(buf, "low");
+ reply.insert_message(um);
log_messages.printf(
SCHED_MSG_LOG::CRITICAL, "[HOST#%d] platform '%s' not found\n",
reply.host.id, sreq.platform_name
@@ -860,10 +869,11 @@ void process_request(
SCHED_MSG_LOG::NORMAL,
"Not sending work - last RPC too recent: %f\n", diff
);
- sprintf(reply.message,
+ sprintf(buf,
"Not sending work - last RPC too recent: %d sec", (int)diff
);
- strcpy(reply.message_priority, "low");
+ USER_MESSAGE um(buf, "low");
+ reply.insert_message(um);
reply.request_delay = config.min_sendwork_interval;
}
}
@@ -897,7 +907,7 @@ extern double watch_diskspace[3];
//
int delete_file_from_host(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& sreply) {
int nfiles = (int)sreq.file_infos.size();
- char helpful_hint[256];
+ char buf[256];
if (!nfiles) {
log_messages.printf(
@@ -905,25 +915,22 @@ int delete_file_from_host(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& sreply) {
"[HOST#%d]: no disk space but no files we can delete!\n", sreply.host.id
);
- sprintf(helpful_hint,
- "\nNo disk space (BOINC needs %.1f MB more)\n", max_allowable_disk(sreq)/1.e6);
- strcat(sreply.message, helpful_hint);
+ sprintf(buf,
+ "No disk space (BOINC needs %.1f MB more). ",
+ max_allowable_disk(sreq)/1.e6
+ );
- if (watch_diskspace[0] != 0.0) {
- strcat(sreply.message,
- "Review preferences for maximum disk space used\n");
- }
- else if (watch_diskspace[1] != 0.0) {
- strcat(sreply.message,
- "Review preferences for maximum disk percentage used\n");
- }
- else if (watch_diskspace[2] != 0.0) {
- strcat(sreply.message,
- "Review preferences for minimum disk free space allowed\n");
- }
- strcpy(sreply.message_priority, "high");
- sreply.request_delay = 24*3600;
- return 1;
+ if (watch_diskspace[0] != 0.0) {
+ strcat(buf, "Review preferences for maximum disk space used.");
+ } else if (watch_diskspace[1] != 0.0) {
+ strcat(buf, "Review preferences for maximum disk percentage used.");
+ } else if (watch_diskspace[2] != 0.0) {
+ strcat(buf, "Review preferences for minimum disk free space allowed.");
+ }
+ USER_MESSAGE um(buf, "high");
+ sreply.insert_message(um);
+ sreply.request_delay = 24*3600;
+ return 1;
}
// pick a data file to delete. Do this deterministically
@@ -947,10 +954,9 @@ int delete_file_from_host(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& sreply) {
// that depends upon this file, before it will be removed by core client.
//
- strcat(sreply.message, "\nRemoving file ");
- strcat(sreply.message, fi.name);
- strcat(sreply.message, " to free up disk space\n");
- strcpy(sreply.message_priority, "low");
+ sprintf(buf, "Removing file %s to free up disk space", fi.name);
+ USER_MESSAGE um(buf, "low");
+ sreply.insert_message(um);
sreply.request_delay = 4*3600;
return 0;
}
@@ -959,8 +965,9 @@ void debug_sched(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& sreply, const char *t
char tmpfilename[256];
FILE *fp;
- if (!boinc_file_exists(trigger))
- return;
+ if (!boinc_file_exists(trigger)) {
+ return;
+ }
sprintf(tmpfilename, "sched_reply_%06d_%06d", sreq.hostid, sreq.rpc_seqno);
// use _XXXXXX if you want random filenames rather than deterministic
@@ -971,35 +978,38 @@ void debug_sched(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& sreply, const char *t
if (!fp) {
log_messages.printf(
SCHED_MSG_LOG::CRITICAL,
- "Found %s, but can't open %s\n", trigger, tmpfilename);
+ "Found %s, but can't open %s\n", trigger, tmpfilename
+ );
return;
}
log_messages.printf(
SCHED_MSG_LOG::DEBUG,
- "Found %s, so writing %s\n", trigger, tmpfilename);
+ "Found %s, so writing %s\n", trigger, tmpfilename
+ );
sreply.write(fp);
fclose(fp);
sprintf(tmpfilename, "sched_request_%06d_%06d", sreq.hostid, sreq.rpc_seqno);
- fp=fopen(tmpfilename, "w");
-
+ fp=fopen(tmpfilename, "w");
+
if (!fp) {
log_messages.printf(
SCHED_MSG_LOG::CRITICAL,
- "Found %s, but can't open %s\n", trigger, tmpfilename);
+ "Found %s, but can't open %s\n", trigger, tmpfilename
+ );
return;
}
-
+
log_messages.printf(
SCHED_MSG_LOG::DEBUG,
- "Found %s, so writing %s\n", trigger, tmpfilename);
-
+ "Found %s, so writing %s\n", trigger, tmpfilename
+ );
+
sreq.write(fp);
fclose(fp);
-
return;
}
@@ -1026,8 +1036,8 @@ void handle_request(
get_remote_addr(), sreq.authenticator, sreq.platform_name,
sreq.core_client_major_version, sreq.core_client_minor_version
);
- strcpy(sreply.message, "Incomplete request received.");
- strcpy(sreply.message_priority, "low");
+ USER_MESSAGE um("Incomplete request received.", "low");
+ sreply.insert_message(um);
sreply.nucleus_only = true;
}
@@ -1040,8 +1050,9 @@ void handle_request(
}
#if 1
- if (sreply.results.size()==0)
+ if (sreply.results.size()==0) {
debug_sched(sreq, sreply, "../debug_sched");
+ }
#endif
sreply.write(fout);
diff --git a/sched/sched_send.C b/sched/sched_send.C
index d774704ab4..69e65e64d4 100644
--- a/sched/sched_send.C
+++ b/sched/sched_send.C
@@ -795,37 +795,47 @@ int send_work(
if (wreq.nresults == 0) {
reply.request_delay = 3600;
- strcpy(reply.message, "No work available");
+ USER_MESSAGE um("No work available", "high");
+ reply.insert_message(um);
if (wreq.no_app_version) {
- strcat(reply.message,
- " (there was work for other platforms)"
- );
+ USER_MESSAGE um("(there was work for other platforms)", "high");
+ reply.insert_message(um);
reply.request_delay = 3600*24;
}
if (wreq.insufficient_disk) {
- strcat(reply.message,
- " (there was work but you don't have enough disk space allocated)"
+ USER_MESSAGE um(
+ "(there was work but you don't have enough disk space allocated)",
+ "high"
);
+ reply.insert_message(um);
}
if (wreq.insufficient_mem) {
- strcat(reply.message,
- " (there was work but your computer doesn't have enough memory)"
+ USER_MESSAGE um(
+ "(there was work but your computer doesn't have enough memory)",
+ "high"
);
+ reply.insert_message(um);
}
if (wreq.insufficient_speed) {
- strcat(reply.message,
- " (there was work but your computer would not finish it before it is due"
+ USER_MESSAGE um(
+ "(there was work but your computer would not finish it before it is due",
+ "high"
);
+ reply.insert_message(um);
}
if (wreq.homogeneous_redundancy_reject) {
- strcat(reply.message,
- " (there was work but it was committed to other platforms"
+ USER_MESSAGE um(
+ "(there was work but it was committed to other platforms",
+ "high"
);
+ reply.insert_message(um);
}
if (wreq.outdated_core) {
- strcat(reply.message,
- " (your core client is out of date - please upgrade)"
+ USER_MESSAGE um(
+ " (your core client is out of date - please upgrade)",
+ "high"
);
+ reply.insert_message(um);
reply.request_delay = 3600*24;
log_messages.printf(
SCHED_MSG_LOG::NORMAL,
@@ -833,20 +843,14 @@ int send_work(
);
}
if (wreq.daily_result_quota_exceeded) {
- strcat(reply.message, " (daily quota exceeded)");
+ USER_MESSAGE um("(daily quota exceeded)", "high");
+ reply.insert_message(um);
log_messages.printf(
SCHED_MSG_LOG::NORMAL,
"Daily result quota exceeded for host %d\n",
reply.host.id
);
}
-
- strcpy(reply.message_priority, "high");
-
- log_messages.printf(
- SCHED_MSG_LOG::NORMAL, "[HOST#%d] %s\n",
- reply.host.id, reply.message
- );
}
return 0;
}
diff --git a/sched/server_types.C b/sched/server_types.C
index d228ecbcd6..ceed036a96 100644
--- a/sched/server_types.C
+++ b/sched/server_types.C
@@ -300,8 +300,6 @@ int MSG_FROM_HOST_DESC::parse(FILE* fin) {
SCHEDULER_REPLY::SCHEDULER_REPLY() {
request_delay = 0;
hostid = 0;
- strcpy(message, "");
- strcpy(message_priority, "");
send_global_prefs = false;
strcpy(code_sign_key, "");
strcpy(code_sign_key_signature, "");
@@ -333,11 +331,12 @@ int SCHEDULER_REPLY::write(FILE* fout) {
fprintf(fout, "%d\n", request_delay);
log_messages.printf(SCHED_MSG_LOG::NORMAL, "sending delay request %d\n", request_delay);
}
- if (strlen(message)) {
+ for (i=0; i%s\n",
- message_priority,
- message
+ um.priority.c_str(),
+ um.message.c_str()
);
}
if (nucleus_only) goto end;
@@ -533,6 +532,15 @@ void SCHEDULER_REPLY::insert_result(RESULT& result) {
results.push_back(result);
}
+void SCHEDULER_REPLY::insert_message(USER_MESSAGE& um) {
+ messages.push_back(um);
+}
+
+USER_MESSAGE::USER_MESSAGE(char* m, char* p) {
+ message = m;
+ priority = p;
+}
+
int APP::write(FILE* fout) {
fprintf(fout,
"\n"
diff --git a/sched/server_types.h b/sched/server_types.h
index dbb465c5a2..ae77cf7bd1 100644
--- a/sched/server_types.h
+++ b/sched/server_types.h
@@ -135,13 +135,20 @@ struct SCHEDULER_REQUEST {
int write(FILE*); // write request info to file: not complete
};
+// message intended for human eyes
+//
+struct USER_MESSAGE {
+ std::string message;
+ std::string priority;
+ USER_MESSAGE(char* m, char*p);
+};
+
// NOTE: if any field requires initialization,
// you must do it in the constructor. Nothing is zeroed by default.
//
struct SCHEDULER_REPLY {
int request_delay; // don't request again until this time elapses
- char message[1024];
- char message_priority[256];
+ std::vector messages;
int hostid;
// nonzero only if a new host record was created.
// this tells client to reset rpc_seqno
@@ -173,6 +180,7 @@ struct SCHEDULER_REPLY {
void insert_app_version_unique(APP_VERSION&);
void insert_workunit_unique(WORKUNIT&);
void insert_result(RESULT&);
+ void insert_message(USER_MESSAGE&);
};
#endif