36
37
#define MAX_STATE_FILE_WRITE_ATTEMPTS 2
38
39
void CLIENT_STATE::set_client_state_dirty(const char* source) {
39
if (log_flags.state_debug) {
40
msg_printf(0, MSG_INFO, "[state_debug] set dirty: %s\n", source);
40
if (log_flags.statefile_debug) {
41
msg_printf(0, MSG_INFO, "[statefile] set dirty: %s\n", source);
42
43
client_state_dirty = true;
68
// return true if r0 arrived before r1
69
// used to sort result list
71
static inline bool arrived_first(RESULT* r0, RESULT* r1) {
72
if (r0->received_time < r1->received_time) {
75
if (r0->received_time > r1->received_time) {
78
return (strcmp(r0->name, r1->name) > 0);
79
// arbitrary but deterministic
67
82
// Parse the client_state.xml file
69
84
int CLIENT_STATE::parse_state_file() {
83
98
} else if (valid_state_file(STATE_FILE_PREV)) {
84
99
fname = STATE_FILE_PREV;
86
if (log_flags.state_debug) {
101
if (log_flags.statefile_debug) {
87
102
msg_printf(0, MSG_INFO,
88
"[state_debug] CLIENT_STATE::parse_state_file(): No state file; will create one"
103
"[statefile] CLIENT_STATE::parse_state_file(): No state file; will create one"
114
129
msg_printf(NULL, MSG_INTERNAL_ERROR, "Can't parse project in state file");
132
project = new PROJECT;
133
*project = temp_project;
134
projects.push_back(project);
116
136
project = lookup_project(temp_project.master_url);
118
138
project->copy_state_fields(temp_project);
247
270
// and then reverted to a 32-bit client.
248
271
// Let's not throw away the app version and its WUs
250
274
msg_printf(project, MSG_INTERNAL_ERROR,
251
275
"App version has unsupported platform %s; changing to %s",
252
276
avp->platform, get_primary_platform()
254
279
strcpy(avp->platform, get_primary_platform());
282
if (avp->missing_coproc()) {
283
msg_printf(project, MSG_INFO,
284
"Application uses missing %s GPU",
285
avp->ncudas?"NVIDIA":"ATI"
257
288
retval = link_app_version(project, avp);
320
if (!strlen(rp->platform) || !is_supported_platform(rp->platform)) {
321
strcpy(rp->platform, get_primary_platform());
322
rp->version_num = latest_version(rp->wup->app, rp->platform);
351
// handle transition from old clients which didn't store result.platform;
352
// skip for anon platform
353
if (!project->anonymous_platform) {
354
if (!strlen(rp->platform) || !is_supported_platform(rp->platform)) {
355
strcpy(rp->platform, get_primary_platform());
356
rp->version_num = latest_version(rp->wup->app, rp->platform);
324
359
rp->avp = lookup_app_version(
325
360
rp->wup->app, rp->platform, rp->version_num, rp->plan_class
328
363
msg_printf(project, MSG_INTERNAL_ERROR,
329
"No app version for result: %s %d %s",
364
"No application found for task: %s %d %s; discarding",
330
365
rp->platform, rp->version_num, rp->plan_class
370
if (rp->avp->missing_coproc()) {
371
msg_printf(project, MSG_INFO,
372
"Missing coprocessor for task %s", rp->name
374
rp->coproc_missing = true;
335
376
rp->wup->version_num = rp->version_num;
336
377
results.push_back(rp);
351
392
if (match_tag(buf, "<host_info>")) {
352
retval = host_info.parse(mf);
394
retval = host_info.parse(mf, false);
396
retval = host_info.parse(mf, true);
354
399
msg_printf(NULL, MSG_INTERNAL_ERROR,
355
400
"Can't parse host info in state file"
394
439
run_mode.set(retval, 0);
442
if (parse_int(buf, "<user_gpu_request>", retval)) {
443
gpu_mode.set(retval, 0);
397
446
if (parse_int(buf, "<user_network_request>", retval)) {
398
447
network_mode.set(retval, 0);
411
460
run_cpu_benchmarks = true;
414
if (match_tag(buf, "<work_fetch_no_new_work/>")) {
415
work_fetch_no_new_work = true;
418
463
if (match_tag(buf, "<proxy_info>")) {
419
retval = proxy_info.parse(mf);
464
retval = gui_proxy_info.parse(mf);
421
466
msg_printf(NULL, MSG_INTERNAL_ERROR,
422
467
"Can't parse proxy info in state file"
436
481
if (parse_str(buf, "<newer_version>", newer_version)) {
439
485
if (match_tag(buf, "<auto_update>")) {
441
487
msg_printf(NULL, MSG_INTERNAL_ERROR,
500
if (parse_double(buf, "<connection_interval>", connection_interval)) {
503
if (match_tag(buf, "<available>")) {
505
available.parse(xp, "/available");
506
available.init(START_TIME);
509
if (match_tag(buf, "<idle>")) {
511
idle.parse(xp, "/idle");
512
idle.init(START_TIME);
452
516
if (log_flags.unparsed_xml) {
453
517
msg_printf(0, MSG_INFO,
454
518
"[unparsed_xml] state_file: unrecognized: %s", buf
457
521
skip_unrecognized(buf, mf);
526
// if total resource share is zero, set all shares to 1
528
if (projects.size()) {
531
for (i=0; i<projects.size(); i++) {
532
x += projects[i]->resource_share;
535
msg_printf(NULL, MSG_INFO,
536
"All projects have zero resource share; setting to 100"
538
for (i=0; i<projects.size(); i++) {
539
projects[i]->resource_share = 100;
546
void CLIENT_STATE::sort_results() {
464
556
// Write the client_state.xml file
473
565
for (attempt=1; attempt<=MAX_STATE_FILE_WRITE_ATTEMPTS; attempt++) {
474
566
if (attempt > 1) boinc_sleep(1.0);
476
if (log_flags.state_debug) {
568
if (log_flags.statefile_debug) {
477
569
msg_printf(0, MSG_INFO,
478
"[status_debug] CLIENT_STATE::write_state_file(): Writing state file"
570
"[statefile] Writing state file"
484
576
retval = mf.open(STATE_FILE_NEXT, "w");
487
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
579
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
488
580
msg_printf(0, MSG_INTERNAL_ERROR,
489
581
"Can't open %s: %s",
490
582
STATE_FILE_NEXT, boincerror(retval)
498
590
ret1 = write_state(miof);
499
591
ret2 = mf.close();
501
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
593
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
502
594
msg_printf(NULL, MSG_INTERNAL_ERROR,
503
595
"Couldn't write state file: %s", boincerror(retval)
517
609
if (boinc_file_exists(STATE_FILE_PREV)) {
518
610
retval = boinc_delete_file(STATE_FILE_PREV);
520
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
612
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
522
msg_printf(0, MSG_USER_ERROR,
614
msg_printf(0, MSG_INFO,
523
615
"Can't delete previous state file; %s",
524
616
windows_error_string(win_error_msg, sizeof(win_error_msg))
527
msg_printf(0, MSG_USER_ERROR,
528
"Can't delete previous state file; error %d: %s",
529
errno, strerror(errno)
619
msg_printf(0, MSG_INFO,
620
"Can't delete previous state file: %s",
537
629
retval = boinc_rename(STATE_FILE_NAME, STATE_FILE_PREV);
539
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
631
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
541
msg_printf(0, MSG_USER_ERROR,
633
msg_printf(0, MSG_INFO,
542
634
"Can't rename current state file to previous state file; %s",
543
635
windows_error_string(win_error_msg, sizeof(win_error_msg))
546
msg_printf(0, MSG_USER_ERROR,
547
"rename current state file to previous state file returned error %d: %s",
548
errno, strerror(errno)
638
msg_printf(0, MSG_INFO,
639
"Can't rename current state file to previous state file: %s",
556
648
retval = boinc_rename(STATE_FILE_NEXT, STATE_FILE_NAME);
557
if (log_flags.state_debug) {
649
if (log_flags.statefile_debug) {
558
650
msg_printf(0, MSG_INFO,
559
"[status_debug] CLIENT_STATE::write_state_file(): Done writing state file"
651
"[statefile] Done writing state file"
562
654
if (!retval) break; // Success!
564
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
656
if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
566
if (retval == ERROR_ACCESS_DENIED) {
567
msg_printf(0, MSG_USER_ERROR,
568
"Can't rename state file; access denied; check file and directory permissions"
571
msg_printf(0, MSG_USER_ERROR,
572
"Can't rename state file; %s",
573
windows_error_string(win_error_msg, sizeof(win_error_msg))
658
msg_printf(0, MSG_INFO,
660
windows_error_string(win_error_msg, sizeof(win_error_msg))
576
662
#elif defined (__APPLE__)
577
msg_printf(0, MSG_USER_ERROR,
578
"Can't rename %s to %s; check file and directory permissions\n"
579
"rename returned error %d: %s",
580
STATE_FILE_NEXT, STATE_FILE_NAME, errno, strerror(errno)
582
if (log_flags.state_debug) {
663
if (log_flags.statefile_debug) {
583
664
system("ls -al /Library/Application\\ Support/BOINC\\ Data/client*.*");
586
msg_printf(0, MSG_USER_ERROR,
587
"Can't rename %s to %s; check file and directory permissions",
588
STATE_FILE_NEXT, STATE_FILE_NAME
592
668
if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue;
599
675
unsigned int i, j;
679
fprintf(stderr, "simulator shouldn't write state file\n");
602
682
f.printf("<client_state>\n");
603
retval = host_info.write(f, false);
683
retval = host_info.write(f, true, true);
604
684
if (retval) return retval;
605
685
retval = time_stats.write(f, false);
606
686
if (retval) return retval;
619
699
for (i=0; i<file_infos.size(); i++) {
620
if (file_infos[i]->project == p) {
621
retval = file_infos[i]->write(f, false);
622
if (retval) return retval;
700
if (file_infos[i]->project != p) continue;
701
FILE_INFO* fip = file_infos[i];
702
// don't write file infos for anonymous platform app files
704
if (p->anonymous_platform && (fip->urls.size()==0)) {
707
retval = fip->write(f, false);
708
if (retval) return retval;
625
710
for (i=0; i<app_versions.size(); i++) {
626
711
if (app_versions[i]->project == p) {
645
730
"<core_client_minor_version>%d</core_client_minor_version>\n"
646
731
"<core_client_release>%d</core_client_release>\n"
647
732
"<user_run_request>%d</user_run_request>\n"
733
"<user_gpu_request>%d</user_gpu_request>\n"
648
734
"<user_network_request>%d</user_network_request>\n"
650
736
"<new_version_check_time>%f</new_version_check_time>\n"
654
740
core_client_version.minor,
655
741
core_client_version.release,
656
742
run_mode.get_perm(),
657
744
network_mode.get_perm(),
658
745
cpu_benchmarks_pending?"<cpu_benchmarks_pending/>\n":"",
659
746
new_version_check_time,
665
752
for (i=1; i<platforms.size(); i++) {
666
753
f.printf("<alt_platform>%s</alt_platform>\n", platforms[i].name.c_str());
755
if (gui_proxy_info.present) {
756
gui_proxy_info.write(f);
669
758
if (strlen(main_host_venue)) {
670
759
f.printf("<host_venue>%s</host_venue>\n", main_host_venue);
710
801
// flag as anonymous even if can't parse file
711
802
retval = parse_app_info(p, f);
713
msg_printf(p, MSG_USER_ERROR,
714
"parse error in app_info.xml; check XML syntax"
804
msg_printf_notice(p, false,
805
"http://boinc.berkeley.edu/manager_links.php?target=notice&controlid=app_info",
807
_("Syntax error in app_info.xml")
814
// parse a project's app_info.xml (anonymous platform) file
721
816
int CLIENT_STATE::parse_app_info(PROJECT* p, FILE* in) {
817
char buf[256], path[1024];
724
819
mf.init_file(in);
830
if (fip->urls.size()) {
831
msg_printf(p, MSG_INFO,
832
"Can't specify URLs in app_info.xml"
735
837
if (link_file_info(p, fip)) {
841
// check that the file is actually there
843
get_pathname(fip, path, sizeof(path));
844
if (!boinc_file_exists(path)) {
846
_("File referenced in app_info.xml does not exist: ")
848
strcat(buf, fip->name);
849
msg_printf(p, MSG_USER_ALERT, buf);
739
853
fip->status = FILE_PRESENT;
740
854
file_infos.push_back(fip);
773
887
if (log_flags.unparsed_xml) {
774
msg_printf(p, MSG_USER_ERROR,
775
"Unparsed line in app_info.xml: %s", buf
888
msg_printf(p, MSG_INFO,
889
"Unparsed line in app_info.xml: %s",
779
894
return ERR_XML_PARSE;
782
899
int CLIENT_STATE::write_state_gui(MIOFILE& f) {
783
900
unsigned int i, j;
786
903
f.printf("<client_state>\n");
788
retval = host_info.write(f, false);
906
// NOTE: the following stuff is not in CC_STATE.
907
// However, BoincView (which does its own parsing) expects it
908
// to be in the get_state() reply, so leave it in for now
910
retval = host_info.write(f, true, false);
789
911
if (retval) return retval;
790
912
retval = time_stats.write(f, false);
791
913
if (retval) return retval;
792
914
retval = net_stats.write(f);
793
915
if (retval) return retval;
795
918
for (j=0; j<projects.size(); j++) {
796
919
PROJECT* p = projects[j];
817
940
"<core_client_major_version>%d</core_client_major_version>\n"
818
941
"<core_client_minor_version>%d</core_client_minor_version>\n"
819
942
"<core_client_release>%d</core_client_release>\n"
943
"<executing_as_daemon>%d</executing_as_daemon>\n"
944
"<have_cuda>%d</have_cuda>\n"
945
"<have_ati>%d</have_ati>\n",
822
946
get_primary_platform(),
823
947
core_client_version.major,
824
948
core_client_version.minor,
825
949
core_client_version.release,
826
executing_as_daemon?"<executing_as_daemon/>\n":"",
827
work_fetch_no_new_work?"<work_fetch_no_new_work/>\n":""
950
executing_as_daemon?1:0,
951
host_info.have_cuda()?1:0,
952
host_info.have_ati()?1:0
954
for (i=0; i<platforms.size(); i++) {
956
"<platform>%s</platform>\n", platforms[i].name.c_str()
830
960
global_prefs.write(f);
962
// the following used by BoincView - don't remove
832
964
if (strlen(main_host_venue)) {
833
965
f.printf("<host_venue>%s</host_venue>\n", main_host_venue);
840
int CLIENT_STATE::write_tasks_gui(MIOFILE& f) {
972
int CLIENT_STATE::write_tasks_gui(MIOFILE& f, bool active_only) {
843
for (i=0; i<results.size(); i++) {
844
RESULT* rp = results[i];
976
for (i=0; i<active_tasks.active_tasks.size(); i++) {
977
RESULT* rp = active_tasks.active_tasks[i]->result;
981
for (i=0; i<results.size(); i++) {
982
RESULT* rp = results[i];