1
// This file is part of BOINC.
2
// http://boinc.berkeley.edu
3
// Copyright (C) 2008 University of California
5
// BOINC is free software; you can redistribute it and/or modify it
6
// under the terms of the GNU Lesser General Public License
7
// as published by the Free Software Foundation,
8
// either version 3 of the License, or (at your option) any later version.
10
// BOINC is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
// See the GNU Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public License
16
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
26
#include "error_numbers.h"
30
#include "sched_util.h"
31
#include "sched_msgs.h"
32
#include "time_stats_log.h"
33
#include "server_types.h"
36
#include "boinc_fcgi.h"
39
// remove (by truncating) any quotes from the given string.
40
// This is for things (e.g. authenticator) that will be used in
41
// a SQL query, to prevent SQL injection attacks
43
void remove_quotes(char* p) {
46
if (p[i]=='\'' || p[i]=='"') {
53
int CLIENT_APP_VERSION::parse(FILE* f) {
56
while (fgets(buf, sizeof(buf), f)) {
57
if (match_tag(buf, "</app_version>")) return 0;
58
if (parse_str(buf, "<app_name>", app_name, 256)) continue;
59
if (parse_int(buf, "<version_num>", version_num)) continue;
64
int FILE_INFO::parse(FILE* f) {
67
memset(this, 0, sizeof(FILE_INFO));
68
while (fgets(buf, sizeof(buf), f)) {
69
if (match_tag(buf, "</file_info>")) {
70
if (!strlen(name)) return ERR_XML_PARSE;
73
if (parse_str(buf, "<name>", name, 256)) continue;
78
int OTHER_RESULT::parse(FILE* f) {
82
while (fgets(buf, sizeof(buf), f)) {
83
if (match_tag(buf, "</other_result>")) {
84
if (name=="") return ERR_XML_PARSE;
87
if (parse_str(buf, "<name>", name)) continue;
92
int IP_RESULT::parse(FILE* f) {
96
cpu_time_remaining = 0;
98
while (fgets(buf, sizeof(buf), f)) {
99
if (match_tag(buf, "</ip_result>")) return 0;
100
if (parse_str(buf, "<name>", name, sizeof(name))) continue;
101
if (parse_double(buf, "<report_deadline>", report_deadline)) continue;
102
if (parse_double(buf, "<cpu_time_remaining>", cpu_time_remaining)) continue;
104
return ERR_XML_PARSE;
107
int CLIENT_PLATFORM::parse(FILE* fin) {
110
while (fgets(buf, sizeof(buf), fin)) {
111
if (match_tag(buf, "</alt_platform>")) return 0;
112
if (parse_str(buf, "<name>", name, sizeof(name))) continue;
114
return ERR_XML_PARSE;
118
void WORK_REQ::insert_no_work_message(USER_MESSAGE& um) {
120
for (unsigned int i=0; i<no_work_messages.size(); i++) {
121
if (!strcmp(um.message.c_str(), no_work_messages.at(i).message.c_str())){
126
if (!found) no_work_messages.push_back(um);
130
SCHEDULER_REQUEST::SCHEDULER_REQUEST() {
133
SCHEDULER_REQUEST::~SCHEDULER_REQUEST() {
136
// return an error message or NULL
138
const char* SCHEDULER_REQUEST::parse(FILE* fin) {
143
strcpy(authenticator, "");
144
strcpy(platform.name, "");
145
strcpy(cross_project_id, "");
147
core_client_major_version = 0;
148
core_client_minor_version = 0;
149
core_client_release = 0;
151
work_req_seconds = 0;
152
resource_share_fraction = 1.0;
156
strcpy(global_prefs_xml, "");
157
strcpy(working_global_prefs_xml, "");
158
strcpy(code_sign_key, "");
159
anonymous_platform = false;
160
memset(&global_prefs, 0, sizeof(global_prefs));
161
memset(&host, 0, sizeof(host));
162
have_other_results_list = false;
163
have_ip_results_list = false;
164
have_time_stats_log = false;
165
client_cap_plan_class = false;
168
fgets(buf, sizeof(buf), fin);
169
if (!match_tag(buf, "<scheduler_request>")) return "no start tag";
170
while (fgets(buf, sizeof(buf), fin)) {
171
// If a line is too long, ignore it.
172
// This can happen e.g. if the client has bad global_prefs.xml
173
// This won't be necessary if we rewrite this using XML_PARSER
175
if (!strchr(buf, '\n')) {
176
while (fgets(buf, sizeof(buf), fin)) {
177
if (strchr(buf, '\n')) break;
182
if (match_tag(buf, "</scheduler_request>")) {
183
core_client_version = 100*core_client_major_version + core_client_minor_version;
186
if (parse_str(buf, "<authenticator>", authenticator, sizeof(authenticator))) {
187
remove_quotes(authenticator);
190
if (parse_str(buf, "<cross_project_id>", cross_project_id, sizeof(cross_project_id))) continue;
191
if (parse_int(buf, "<hostid>", hostid)) continue;
192
if (parse_int(buf, "<rpc_seqno>", rpc_seqno)) continue;
193
if (parse_str(buf, "<platform_name>", platform.name, sizeof(platform.name))) continue;
194
if (match_tag(buf, "<alt_platform>")) {
196
retval = cp.parse(fin);
198
alt_platforms.push_back(cp);
202
if (match_tag(buf, "<app_versions>")) {
203
while (fgets(buf, sizeof(buf), fin)) {
204
if (match_tag(buf, "</app_versions>")) break;
205
if (match_tag(buf, "<app_version>")) {
206
CLIENT_APP_VERSION cav;
208
client_app_versions.push_back(cav);
213
if (parse_int(buf, "<core_client_major_version>", core_client_major_version)) continue;
214
if (parse_int(buf, "<core_client_minor_version>", core_client_minor_version)) continue;
215
if (parse_int(buf, "<core_client_release>", core_client_release)) continue;
216
if (parse_double(buf, "<work_req_seconds>", work_req_seconds)) continue;
217
if (parse_double(buf, "<resource_share_fraction>", resource_share_fraction)) continue;
218
if (parse_double(buf, "<rrs_fraction>", rrs_fraction)) continue;
219
if (parse_double(buf, "<prrs_fraction>", prrs_fraction)) continue;
220
if (parse_double(buf, "<estimated_delay>", estimated_delay)) continue;
221
if (parse_double(buf, "<duration_correction_factor>", host.duration_correction_factor)) continue;
222
if (match_tag(buf, "<global_preferences>")) {
223
strcpy(global_prefs_xml, "<global_preferences>\n");
224
while (fgets(buf, sizeof(buf), fin)) {
225
if (strstr(buf, "</global_preferences>")) break;
226
safe_strcat(global_prefs_xml, buf);
228
safe_strcat(global_prefs_xml, "</global_preferences>\n");
231
if (match_tag(buf, "<working_global_preferences>")) {
232
while (fgets(buf, sizeof(buf), fin)) {
233
if (strstr(buf, "</working_global_preferences>")) break;
234
safe_strcat(working_global_prefs_xml, buf);
238
if (parse_str(buf, "<global_prefs_source_email_hash>", global_prefs_source_email_hash, sizeof(global_prefs_source_email_hash))) continue;
239
if (match_tag(buf, "<host_info>")) {
243
if (match_tag(buf, "<time_stats>")) {
244
host.parse_time_stats(fin);
247
if (match_tag(buf, "<time_stats_log>")) {
248
handle_time_stats_log(fin);
249
have_time_stats_log = true;
252
if (match_tag(buf, "<net_stats>")) {
253
host.parse_net_stats(fin);
256
if (match_tag(buf, "<disk_usage>")) {
257
host.parse_disk_usage(fin);
260
if (match_tag(buf, "<result>")) {
261
result.parse_from_client(fin);
262
results.push_back(result);
265
if (match_tag(buf, "<code_sign_key>")) {
266
copy_element_contents(fin, "</code_sign_key>", code_sign_key, sizeof(code_sign_key));
269
if (match_tag(buf, "<msg_from_host>")) {
270
MSG_FROM_HOST_DESC md;
271
retval = md.parse(fin);
273
msgs_from_host.push_back(md);
277
if (match_tag(buf, "<file_info>")) {
279
retval = fi.parse(fin);
281
file_infos.push_back(fi);
285
if (match_tag(buf, "<host_venue>")) {
288
if (match_tag(buf, "<other_results>")) {
289
have_other_results_list = true;
290
while (fgets(buf, sizeof(buf), fin)) {
291
if (match_tag(buf, "</other_results>")) break;
292
if (match_tag(buf, "<other_result>")) {
294
retval = o_r.parse(fin);
296
other_results.push_back(o_r);
302
if (match_tag(buf, "<in_progress_results>")) {
303
have_ip_results_list = true;
305
double now = time(0);
306
while (fgets(buf, sizeof(buf), fin)) {
307
if (match_tag(buf, "</in_progress_results>")) break;
308
if (match_tag(buf, "<ip_result>")) {
310
retval = ir.parse(fin);
312
if (!strlen(ir.name)) {
313
sprintf(ir.name, "ip%d", i++);
315
ir.report_deadline -= now;
316
ip_results.push_back(ir);
322
if (match_tag(buf, "coprocs")) {
326
if (parse_bool(buf, "client_cap_plan_class", client_cap_plan_class)) continue;
327
if (parse_int(buf, "<sandbox>", sandbox)) continue;
329
if (match_tag(buf, "<active_task_set>")) continue;
330
if (match_tag(buf, "<app>")) continue;
331
if (match_tag(buf, "<app_version>")) continue;
332
if (match_tag(buf, "<duration_variability>")) continue;
333
if (match_tag(buf, "<new_version_check_time>")) continue;
334
if (match_tag(buf, "<newer_version>")) continue;
335
if (match_tag(buf, "<project>")) continue;
336
if (match_tag(buf, "<project_files>")) continue;
337
if (match_tag(buf, "<proxy_info>")) continue;
338
if (match_tag(buf, "<user_network_request>")) continue;
339
if (match_tag(buf, "<user_run_request>")) continue;
340
if (match_tag(buf, "<master_url>")) continue;
341
if (match_tag(buf, "<project_name>")) continue;
342
if (match_tag(buf, "<user_name>")) continue;
343
if (match_tag(buf, "<team_name>")) continue;
344
if (match_tag(buf, "<email_hash>")) continue;
345
if (match_tag(buf, "<user_total_credit>")) continue;
346
if (match_tag(buf, "<user_expavg_credit>")) continue;
347
if (match_tag(buf, "<user_create_time>")) continue;
348
if (match_tag(buf, "<host_total_credit>")) continue;
349
if (match_tag(buf, "<host_expavg_credit>")) continue;
350
if (match_tag(buf, "<host_create_time>")) continue;
351
if (match_tag(buf, "<nrpc_failures>")) continue;
352
if (match_tag(buf, "<master_fetch_failures>")) continue;
353
if (match_tag(buf, "<min_rpc_time>")) continue;
354
if (match_tag(buf, "<short_term_debt>")) continue;
355
if (match_tag(buf, "<long_term_debt>")) continue;
356
if (match_tag(buf, "<resource_share>")) continue;
357
if (match_tag(buf, "<scheduler_url>")) continue;
358
if (match_tag(buf, "</project>")) continue;
359
if (match_tag(buf, "<?xml")) continue;
360
strip_whitespace(buf);
361
if (!strlen(buf)) continue;
363
log_messages.printf(MSG_NORMAL,
364
"SCHEDULER_REQUEST::parse(): unrecognized: %s\n", buf
368
retval = skip_unrecognized(buf, mf);
369
if (retval) return "unterminated unrecognized XML";
374
int SCHEDULER_REQUEST::write(FILE* fout) {
378
"<scheduler_request>\n"
379
" <authenticator>%s</authentiicator>\n"
380
" <platform_name>%s</platform_name>\n"
381
" <cross_project_id>%s</cross_project_id>\n"
382
" <hostid>%d</hostid>\n"
383
" <core_client_major_version>%d</core_client_major_version>\n"
384
" <core_client_minor_version>%d</core_client_minor_version>\n"
385
" <core_client_release>%d</core_client_release>\n"
386
" <rpc_seqno>%d</rpc_seqno>\n"
387
" <work_req_seconds>%.15f</work_req_seconds>\n"
388
" <resource_share_fraction>%.15f</resource_share_fraction>\n"
389
" <rrs_fraction>%.15f</rrs_fraction>\n"
390
" <prrs_fraction>%.15f</prrs_fraction>\n"
391
" <estimated_delay>%.15f</estimated_delay>\n"
392
" <code_sign_key>%s</code_sign_key>\n"
393
" <anonymous_platform>%s</anonymous_platform>\n",
398
core_client_major_version,
399
core_client_minor_version,
403
resource_share_fraction,
408
anonymous_platform?"true":"false"
411
for (i=0; i<client_app_versions.size(); i++) {
414
" <app_name>%s</app_name>\n"
415
" <version_num>%d</version_num>\n"
417
client_app_versions[i].app_name,
418
client_app_versions[i].version_num
423
" <global_prefs_xml>\n"
425
" </globals_prefs_xml>\n",
430
" <global_prefs_source_email_hash>%s</global_prefs_source_email_hash>\n",
431
global_prefs_source_email_hash
437
" <rpc_time>%d</rpc_time>\n"
438
" <timezone>%d</timezone>\n"
439
" <d_total>%.15f</d_total>\n"
440
" <d_free>%.15f</d_free>\n"
441
" <d_boinc_used_total>%.15f</d_boinc_used_total>\n"
442
" <d_boinc_used_project>%.15f</d_boinc_used_project>\n"
443
" <d_boinc_max>%.15f</d_boinc_max>\n",
449
host.d_boinc_used_total,
450
host.d_boinc_used_project,
454
for (i=0; i<results.size(); i++) {
458
" <client_state>%d</client_state>\n"
459
" <cpu_time>%.15f</cpu_time>\n"
460
" <exit_status>%d</exit_status>\n"
461
" <app_version_num>%d</app_version_num>\n"
464
results[i].client_state,
466
results[i].exit_status,
467
results[i].app_version_num
471
for (i=0; i<msgs_from_host.size(); i++) {
474
" <variety>%s</variety>\n"
475
" <msg_text>%s</msg_text>\n"
476
" </msg_from_host>\n",
477
msgs_from_host[i].variety,
478
msgs_from_host[i].msg_text.c_str()
482
for (i=0; i<file_infos.size(); i++) {
489
fprintf(fout, "</scheduler_request>\n");
494
int MSG_FROM_HOST_DESC::parse(FILE* fin) {
498
while (fgets(buf, sizeof(buf), fin)) {
499
if (match_tag(buf, "</msg_from_host>")) return 0;
500
if (parse_str(buf, "<variety>", variety, sizeof(variety))) continue;
503
return ERR_XML_PARSE;
506
SCHEDULER_REPLY::SCHEDULER_REPLY() {
507
memset(&wreq, 0, sizeof(wreq));
508
memset(&disk_limits, 0, sizeof(disk_limits));
511
send_global_prefs = false;
512
strcpy(code_sign_key, "");
513
strcpy(code_sign_key_signature, "");
514
memset(&user, 0, sizeof(user));
515
memset(&host, 0, sizeof(host));
516
memset(&team, 0, sizeof(team));
517
nucleus_only = false;
518
project_is_down = false;
519
send_msg_ack = false;
520
strcpy(email_hash, "");
523
SCHEDULER_REPLY::~SCHEDULER_REPLY() {
526
int SCHEDULER_REPLY::write(FILE* fout, SCHEDULER_REQUEST& sreq) {
530
// Note: at one point we had
531
// "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
532
// after the Content-type (to make it legit XML),
533
// but this broke 4.19 clients
536
"Content-type: text/xml\n\n"
537
"<scheduler_reply>\n"
538
"<scheduler_version>%d</scheduler_version>\n",
539
BOINC_MAJOR_VERSION*100+BOINC_MINOR_VERSION
541
if (strlen(config.master_url)) {
543
"<master_url>%s</master_url>\n",
548
fprintf(fout, " <ended>1</ended>\n");
551
// if the scheduler has requested a delay OR the sysadmin has configured
552
// the scheduler with a minimum time between RPCs, send a delay request.
553
// Make it 1% larger than the min required to take care of time skew.
554
// If this is less than one second bigger, bump up by one sec.
556
if (request_delay || config.min_sendwork_interval) {
557
double min_delay_needed = 1.01*config.min_sendwork_interval;
558
if (min_delay_needed < config.min_sendwork_interval+1) {
559
min_delay_needed = config.min_sendwork_interval+1;
561
if (request_delay<min_delay_needed) {
562
request_delay=min_delay_needed;
564
fprintf(fout, "<request_delay>%f</request_delay>\n", request_delay);
566
log_messages.printf(MSG_NORMAL,
567
"Sending reply to [HOST#%d]: %d results, delay req %f [scheduler ran %f seconds]\n",
568
host.id, wreq.nresults, request_delay, elapsed_wallclock_time()
571
if (sreq.core_client_version <= 419) {
573
std::string pri = "low";
574
for (i=0; i<messages.size(); i++) {
575
USER_MESSAGE& um = messages[i];
576
msg += um.message + std::string(" ");
577
if (um.priority == "high") {
581
if (messages.size()>0) {
582
// any newlines will break message printing under 4.19 and under!
583
// replace them with spaces.
586
string::size_type pos = msg.find("\n", 0);
587
if (pos == string::npos) break;
588
msg.replace(pos, 1, " ");
591
"<message priority=\"%s\">%s</message>\n",
592
pri.c_str(), msg.c_str()
596
for (i=0; i<messages.size(); i++) {
597
USER_MESSAGE& um = messages[i];
599
"<message priority=\"%s\">%s</message>\n",
606
"<project_name>%s</project_name>\n",
610
if (config.request_time_stats_log) {
611
if (!have_time_stats_log(*this)) {
612
fprintf(fout, "<send_time_stats_log>1</send_time_stats_log>\n");
616
if (project_is_down) {
617
fprintf(fout,"<project_is_down/>\n");
621
if (nucleus_only) goto end;
623
if (strlen(config.symstore)) {
624
fprintf(fout, "<symstore>%s</symstore>\n", config.symstore);
626
if (config.next_rpc_delay) {
627
fprintf(fout, "<next_rpc_delay>%f</next_rpc_delay>\n", config.next_rpc_delay);
630
xml_escape(user.name, buf, sizeof(buf));
632
"<user_name>%s</user_name>\n"
633
"<user_total_credit>%f</user_total_credit>\n"
634
"<user_expavg_credit>%f</user_expavg_credit>\n"
635
"<user_create_time>%d</user_create_time>\n",
641
// be paranoid about the following to avoid sending null
643
if (strlen(email_hash)) {
645
"<email_hash>%s</email_hash>\n",
649
if (strlen(user.cross_project_id)) {
651
"<cross_project_id>%s</cross_project_id>\n",
652
user.cross_project_id
656
if (send_global_prefs) {
657
fputs(user.global_prefs, fout);
661
// always send project prefs
663
fputs(user.project_prefs, fout);
669
"<hostid>%d</hostid>\n",
674
"<host_total_credit>%f</host_total_credit>\n"
675
"<host_expavg_credit>%f</host_expavg_credit>\n"
676
"<host_venue>%s</host_venue>\n"
677
"<host_create_time>%d</host_create_time>\n",
684
// might want to send team credit too.
687
xml_escape(team.name, buf, sizeof(buf));
689
"<team_name>%s</team_name>\n",
694
"<team_name></team_name>\n"
698
// acknowledge results
700
for (i=0; i<result_acks.size(); i++) {
705
result_acks[i].c_str()
711
for (i=0; i<result_aborts.size(); i++) {
716
result_aborts[i].c_str()
720
// abort results not started
722
for (i=0; i<result_abort_if_not_starteds.size(); i++) {
724
"<result_abort_if_not_started>\n"
726
"</result_abort_if_not_started>\n",
727
result_abort_if_not_starteds[i].c_str()
731
for (i=0; i<apps.size(); i++) {
735
for (i=0; i<app_versions.size(); i++) {
736
app_versions[i].write(fout);
739
for (i=0; i<wus.size(); i++) {
740
fputs(wus[i].xml_doc, fout);
743
for (i=0; i<results.size(); i++) {
744
results[i].write_to_client(fout);
747
if (strlen(code_sign_key)) {
748
fputs("<code_sign_key>\n", fout);
749
fputs(code_sign_key, fout);
750
fputs("</code_sign_key>\n", fout);
753
if (strlen(code_sign_key_signature)) {
754
fputs("<code_sign_key_signature>\n", fout);
755
fputs(code_sign_key_signature, fout);
756
fputs("</code_sign_key_signature>\n", fout);
760
fputs("<message_ack/>\n", fout);
763
for (i=0; i<msgs_to_host.size(); i++) {
764
MSG_TO_HOST& md = msgs_to_host[i];
765
fprintf(fout, "%s\n", md.xml);
768
if (config.non_cpu_intensive) {
769
fprintf(fout, "<non_cpu_intensive/>\n");
772
if (config.verify_files_on_app_start) {
773
fprintf(fout, "<verify_files_on_app_start/>\n");
776
for (i=0; i<file_deletes.size(); i++) {
778
"<delete_file_info>%s</delete_file_info>\n",
783
gui_urls.get_gui_urls(user, host, team, buf);
785
if (project_files.text) {
786
fputs(project_files.text, fout);
792
"</scheduler_reply>\n"
797
// set delay to the MAX of the existing value or the requested value
798
// never send a delay request longer than two days.
800
void SCHEDULER_REPLY::set_delay(double delay) {
801
if (request_delay < delay) {
802
request_delay = delay;
804
if (request_delay > DELAY_MAX) {
805
request_delay = DELAY_MAX;
810
void SCHEDULER_REPLY::insert_app_unique(APP& app) {
812
for (i=0; i<apps.size(); i++) {
813
if (app.id == apps[i].id) return;
818
void SCHEDULER_REPLY::insert_app_version_unique(APP_VERSION& av) {
820
for (i=0; i<app_versions.size(); i++) {
821
if (av.id == app_versions[i].id) return;
823
app_versions.push_back(av);
826
void SCHEDULER_REPLY::insert_workunit_unique(WORKUNIT& wu) {
828
for (i=0; i<wus.size(); i++) {
829
if (wu.id == wus[i].id) return;
834
void SCHEDULER_REPLY::insert_result(RESULT& result) {
835
results.push_back(result);
838
void SCHEDULER_REPLY::insert_message(USER_MESSAGE& um) {
839
messages.push_back(um);
842
USER_MESSAGE::USER_MESSAGE(const char* m, const char* p) {
847
int APP::write(FILE* fout) {
851
" <user_friendly_name>%s</user_friendly_name>\n"
853
name, user_friendly_name
858
int APP_VERSION::write(FILE* fout) {
859
char buf[APP_VERSION_XML_BLOB_SIZE];
862
strcpy(buf, xml_doc);
863
char* p = strstr(buf, "</app_version>");
865
fprintf(stderr, "ERROR: app version %d XML has no end tag!\n", id);
870
PLATFORM* pp = ssp->lookup_platform_id(platformid);
871
fprintf(fout, " <platform>%s</platform>\n", pp->name);
872
if (strlen(plan_class)) {
873
fprintf(fout, " <plan_class>%s</plan_class>\n", plan_class);
876
" <avg_ncpus>%f</avg_ncpus>\n"
877
" <max_ncpus>%f</max_ncpus>\n"
878
" <flops>%f</flops>\n",
879
bavp->host_usage.avg_ncpus,
880
bavp->host_usage.max_ncpus,
881
bavp->host_usage.flops
883
if (strlen(bavp->host_usage.cmdline)) {
885
" <cmdline>%s</cmdline>\n",
886
bavp->host_usage.cmdline
889
for (i=0; i<bavp->host_usage.coprocs.coprocs.size(); i++) {
890
COPROC* cp = bavp->host_usage.coprocs.coprocs[i];
894
" <count>%d</count>\n"
900
fputs("</app_version>\n", fout);
904
int RESULT::write_to_client(FILE* fout) {
907
strcpy(buf, xml_doc_in);
908
char* p = strstr(buf, "</result>");
910
fprintf(stderr, "ERROR: result %d XML has no end tag!\n", id);
916
APP_VERSION* avp = bavp->avp;
917
if (avp == (APP_VERSION*)1) avp = NULL;
919
PLATFORM* pp = ssp->lookup_platform_id(avp->platformid);
921
" <platform>%s</platform>\n"
922
" <version_num>%d</version_num>\n"
923
" <plan_class>%s</plan_class>\n",
924
pp->name, avp->version_num, avp->plan_class
927
fputs("</result>\n", fout);
931
int RESULT::parse_from_client(FILE* fin) {
934
// should be non-zero if exit_status is not found
935
exit_status = ERR_NO_EXIT_STATUS;
936
memset(this, 0, sizeof(RESULT));
937
while (fgets(buf, sizeof(buf), fin)) {
938
if (match_tag(buf, "</result>")) return 0;
939
if (parse_str(buf, "<name>", name, sizeof(name))) continue;
940
if (parse_int(buf, "<state>", client_state)) continue;
941
if (parse_double(buf, "<final_cpu_time>", cpu_time)) continue;
942
if (parse_int(buf, "<exit_status>", exit_status)) continue;
943
if (parse_int(buf, "<app_version_num>", app_version_num)) continue;
944
if (parse_double(buf, "<fpops_per_cpu_sec>", fpops_per_cpu_sec)) continue;
945
if (parse_double(buf, "<fpops_cumulative>", fpops_cumulative)) continue;
946
if (parse_double(buf, "<intops_per_cpu_sec>", intops_per_cpu_sec)) continue;
947
if (parse_double(buf, "<intops_cumulative>", intops_cumulative)) continue;
948
if (match_tag(buf, "<file_info>")) {
949
safe_strcat(xml_doc_out, buf);
950
while (fgets(buf, sizeof(buf), fin)) {
951
safe_strcat(xml_doc_out, buf);
952
if (match_tag(buf, "</file_info>")) break;
956
if (match_tag(buf, "<stderr_out>" )) {
957
while (fgets(buf, sizeof(buf), fin)) {
958
if (match_tag(buf, "</stderr_out>")) break;
959
safe_strcat(stderr_out, buf);
963
if (match_tag(buf, "<platform>")) continue;
964
if (match_tag(buf, "<version_num>")) continue;
965
if (match_tag(buf, "<plan_class>")) continue;
966
if (match_tag(buf, "<completed_time>")) continue;
967
if (match_tag(buf, "<file_name>")) continue;
968
if (match_tag(buf, "<file_ref>")) continue;
969
if (match_tag(buf, "</file_ref>")) continue;
970
if (match_tag(buf, "<open_name>")) continue;
971
if (match_tag(buf, "<ready_to_report>")) continue;
972
if (match_tag(buf, "<ready_to_report/>")) continue;
973
if (match_tag(buf, "<report_deadline>")) continue;
974
if (match_tag(buf, "<wu_name>")) continue;
976
log_messages.printf(MSG_NORMAL,
977
"RESULT::parse_from_client(): unrecognized: %s\n",
981
return ERR_XML_PARSE;
984
int HOST::parse(FILE* fin) {
988
while (fgets(buf, sizeof(buf), fin)) {
989
if (match_tag(buf, "</host_info>")) return 0;
990
if (parse_int(buf, "<timezone>", timezone)) continue;
991
if (parse_str(buf, "<domain_name>", domain_name, sizeof(domain_name))) continue;
992
if (parse_str(buf, "<serialnum>", serialnum, sizeof(serialnum))) continue;
993
if (parse_str(buf, "<ip_addr>", last_ip_addr, sizeof(last_ip_addr))) continue;
994
if (parse_str(buf, "<host_cpid>", host_cpid, sizeof(host_cpid))) continue;
995
if (parse_int(buf, "<p_ncpus>", p_ncpus)) continue;
996
if (parse_str(buf, "<p_vendor>", p_vendor, sizeof(p_vendor))) continue;
997
if (parse_str(buf, "<p_model>", p_model, sizeof(p_model))) continue;
998
if (parse_double(buf, "<p_fpops>", p_fpops)) continue;
999
if (parse_double(buf, "<p_iops>", p_iops)) continue;
1000
if (parse_double(buf, "<p_membw>", p_membw)) continue;
1001
if (parse_str(buf, "<os_name>", os_name, sizeof(os_name))) continue;
1002
if (parse_str(buf, "<os_version>", os_version, sizeof(os_version))) continue;
1003
if (parse_double(buf, "<m_nbytes>", m_nbytes)) continue;
1004
if (parse_double(buf, "<m_cache>", m_cache)) continue;
1005
if (parse_double(buf, "<m_swap>", m_swap)) continue;
1006
if (parse_double(buf, "<d_total>", d_total)) continue;
1007
if (parse_double(buf, "<d_free>", d_free)) continue;
1008
if (parse_double(buf, "<n_bwup>", n_bwup)) continue;
1009
if (parse_double(buf, "<n_bwdown>", n_bwdown)) continue;
1011
// parse deprecated fields to avoid error messages
1013
if (match_tag(buf, "<p_calculated>")) continue;
1014
if (match_tag(buf, "<p_fpop_err>")) continue;
1015
if (match_tag(buf, "<p_iop_err>")) continue;
1016
if (match_tag(buf, "<p_membw_err>")) continue;
1018
// fields reported by 5.5+ clients, not currently used
1020
if (match_tag(buf, "<p_features>")) continue;
1021
if (match_tag(buf, "<p_capabilities>")) continue;
1022
if (match_tag(buf, "<accelerators>")) continue;
1025
// not sure where thees fields belong in the above
1028
if (match_tag(buf, "<cpu_caps>")) continue;
1029
if (match_tag(buf, "<cache_l1>")) continue;
1030
if (match_tag(buf, "<cache_l2>")) continue;
1031
if (match_tag(buf, "<cache_l3>")) continue;
1034
log_messages.printf(MSG_NORMAL,
1035
"HOST::parse(): unrecognized: %s\n", buf
1038
return ERR_XML_PARSE;
1042
int HOST::parse_time_stats(FILE* fin) {
1045
while (fgets(buf, sizeof(buf), fin)) {
1046
if (match_tag(buf, "</time_stats>")) return 0;
1047
if (parse_double(buf, "<on_frac>", on_frac)) continue;
1048
if (parse_double(buf, "<connected_frac>", connected_frac)) continue;
1049
if (parse_double(buf, "<active_frac>", active_frac)) continue;
1050
if (match_tag(buf, "<outages>")) continue;
1051
if (match_tag(buf, "<outage>")) continue;
1052
if (match_tag(buf, "<start>")) continue;
1053
if (match_tag(buf, "<end>")) continue;
1054
log_messages.printf(MSG_NORMAL,
1055
"HOST::parse_time_stats(): unrecognized: %s\n",
1059
return ERR_XML_PARSE;
1062
int HOST::parse_net_stats(FILE* fin) {
1065
while (fgets(buf, sizeof(buf), fin)) {
1066
if (match_tag(buf, "</net_stats>")) return 0;
1067
if (parse_double(buf, "<bwup>", n_bwup)) continue;
1068
if (parse_double(buf, "<bwdown>", n_bwdown)) continue;
1070
// items reported by 5.10+ clients, not currently used
1072
if (match_tag(buf, "<avg_time_up>")) continue;
1073
if (match_tag(buf, "<avg_up>")) continue;
1074
if (match_tag(buf, "<avg_time_down>")) continue;
1075
if (match_tag(buf, "<avg_down>")) continue;
1077
log_messages.printf(MSG_NORMAL,
1078
"HOST::parse_net_stats(): unrecognized: %s\n",
1082
return ERR_XML_PARSE;
1085
int HOST::parse_disk_usage(FILE* fin) {
1088
while (fgets(buf, sizeof(buf), fin)) {
1089
if (match_tag(buf, "</disk_usage>")) return 0;
1090
if (parse_double(buf, "<d_boinc_used_total>", d_boinc_used_total)) continue;
1091
if (parse_double(buf, "<d_boinc_used_project>", d_boinc_used_project)) continue;
1092
log_messages.printf(MSG_NORMAL,
1093
"HOST::parse_disk_usage(): unrecognized: %s\n",
1097
return ERR_XML_PARSE;
1100
void GLOBAL_PREFS::parse(const char* buf, const char* venue) {
1101
char buf2[BLOB_SIZE];
1106
if (parse_double(buf, "<mod_time>", mod_time)) {
1107
// mod_time is outside of venue
1108
if (mod_time > dtime()) mod_time = dtime();
1110
extract_venue(buf, venue, buf2);
1111
parse_double(buf2, "<disk_max_used_gb>", disk_max_used_gb);
1112
parse_double(buf2, "<disk_max_used_pct>", disk_max_used_pct);
1113
parse_double(buf2, "<disk_min_free_gb>", disk_min_free_gb);
1114
parse_double(buf2, "<work_buf_min_days>", work_buf_min_days);
1115
if (parse_double(buf2, "<ram_max_used_busy_pct>", dtemp)) {
1116
ram_max_used_busy_frac = dtemp/100.;
1118
if (parse_double(buf2, "<ram_max_used_idle_pct>", dtemp)) {
1119
ram_max_used_idle_frac = dtemp/100.;
1121
parse_double(buf2, "<max_ncpus_pct>", max_ncpus_pct);
1124
void GLOBAL_PREFS::defaults() {
1125
memset(this, 0, sizeof(GLOBAL_PREFS));
1128
void GUI_URLS::init() {
1130
read_file_malloc("../gui_urls.xml", text);
1133
void GUI_URLS::get_gui_urls(USER& user, HOST& host, TEAM& team, char* buf) {
1135
char userid[256], teamid[256], hostid[256];
1140
sprintf(userid, "%d", user.id);
1141
sprintf(hostid, "%d", host.id);
1143
sprintf(teamid, "%d", team.id);
1145
strcpy(teamid, "0");
1146
while (remove_element(buf, "<ifteam>", "</ifteam>")) {
1153
found |= str_replace(buf, "<userid/>", userid);
1154
found |= str_replace(buf, "<user_name/>", user.name);
1155
found |= str_replace(buf, "<hostid/>", hostid);
1156
found |= str_replace(buf, "<teamid/>", teamid);
1157
found |= str_replace(buf, "<team_name/>", team.name);
1158
found |= str_replace(buf, "<authenticator/>", user.authenticator);
1163
void PROJECT_FILES::init() {
1165
read_file_malloc("../project_files.xml", text);
1168
const char *BOINC_RCSID_ea659117b3 = "$Id: server_types.cpp 16611 2008-12-03 20:55:22Z romw $";