~ubuntu-branches/ubuntu/precise/boinc/precise

« back to all changes in this revision

Viewing changes to client/cs_statefile.cpp

Tags: 6.12.8+dfsg-1
* New upstream release.
* Simplified debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include "boinc_win.h"
20
20
#else
21
21
#include "config.h"
22
 
#endif
23
 
 
24
22
#include <cstring>
25
23
#include <errno.h>
 
24
#endif
26
25
 
27
26
#include "parse.h"
28
27
#include "str_util.h"
29
28
#include "util.h"
30
29
#include "error_numbers.h"
31
30
#include "filesys.h"
 
31
 
 
32
#include "cs_proxy.h"
32
33
#include "file_names.h"
33
34
#include "client_msgs.h"
34
35
#include "client_state.h"
36
37
#define MAX_STATE_FILE_WRITE_ATTEMPTS 2
37
38
 
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);
41
42
    }
42
43
    client_state_dirty = true;
43
44
}
64
65
    return false;
65
66
}
66
67
 
 
68
// return true if r0 arrived before r1
 
69
// used to sort result list
 
70
//
 
71
static inline bool arrived_first(RESULT* r0, RESULT* r1) {
 
72
    if (r0->received_time < r1->received_time) {
 
73
        return true;
 
74
    }
 
75
    if (r0->received_time > r1->received_time) {
 
76
        return false;
 
77
    }
 
78
    return (strcmp(r0->name, r1->name) > 0);
 
79
        // arbitrary but deterministic
 
80
}
 
81
 
67
82
// Parse the client_state.xml file
68
83
//
69
84
int CLIENT_STATE::parse_state_file() {
83
98
    } else if (valid_state_file(STATE_FILE_PREV)) {
84
99
        fname = STATE_FILE_PREV;
85
100
    } else {
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"
89
104
            );
90
105
        }
91
106
 
113
128
            if (retval) {
114
129
                msg_printf(NULL, MSG_INTERNAL_ERROR, "Can't parse project in state file");
115
130
            } else {
 
131
#ifdef SIM
 
132
                project = new PROJECT;
 
133
                *project = temp_project;
 
134
                projects.push_back(project);
 
135
#else
116
136
                project = lookup_project(temp_project.master_url);
117
137
                if (project) {
118
138
                    project->copy_state_fields(temp_project);
122
142
                        temp_project.get_project_name()
123
143
                    );
124
144
                }
 
145
#endif
125
146
            }
126
147
            continue;
127
148
        }
155
176
                );
156
177
                delete app;
157
178
                continue;
158
 
                    }
 
179
            }
159
180
            apps.push_back(app);
160
181
            continue;
161
182
        }
190
211
                continue;
191
212
            }
192
213
            file_infos.push_back(fip);
 
214
#ifndef SIM
193
215
            // If the file had a failure before,
194
216
            // don't start another file transfer
195
217
            //
215
237
                    );
216
238
                }
217
239
            }
 
240
#endif
218
241
            continue;
219
242
        }
220
243
        if (match_tag(buf, "<app_version>")) {
247
270
                    // and then reverted to a 32-bit client.
248
271
                    // Let's not throw away the app version and its WUs
249
272
                    //
 
273
#ifndef SIM
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()
253
277
                    );
 
278
#endif
254
279
                    strcpy(avp->platform, get_primary_platform());
255
280
                }
256
281
            }
 
282
            if (avp->missing_coproc()) {
 
283
                msg_printf(project, MSG_INFO,
 
284
                    "Application uses missing %s GPU",
 
285
                    avp->ncudas?"NVIDIA":"ATI"
 
286
                );
 
287
            }
257
288
            retval = link_app_version(project, avp);
258
289
            if (retval) {
259
290
                delete avp;
317
348
                delete rp;
318
349
                continue;
319
350
            }
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);
 
357
                }
323
358
            }
324
359
            rp->avp = lookup_app_version(
325
360
                rp->wup->app, rp->platform, rp->version_num, rp->plan_class
326
361
            );
327
362
            if (!rp->avp) {
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
331
366
                );
332
367
                delete rp;
333
368
                continue;
334
369
            }
 
370
            if (rp->avp->missing_coproc()) {
 
371
                msg_printf(project, MSG_INFO,
 
372
                    "Missing coprocessor for task %s", rp->name
 
373
                );
 
374
                rp->coproc_missing = true;
 
375
            }
335
376
            rp->wup->version_num = rp->version_num;
336
377
            results.push_back(rp);
337
378
            continue;
349
390
            continue;
350
391
        }
351
392
        if (match_tag(buf, "<host_info>")) {
352
 
            retval = host_info.parse(mf);
 
393
#ifdef SIM
 
394
            retval = host_info.parse(mf, false);
 
395
#else
 
396
            retval = host_info.parse(mf, true);
 
397
#endif
353
398
            if (retval) {
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);
395
440
            continue;
396
441
        }
 
442
        if (parse_int(buf, "<user_gpu_request>", retval)) {
 
443
            gpu_mode.set(retval, 0);
 
444
            continue;
 
445
        }
397
446
        if (parse_int(buf, "<user_network_request>", retval)) {
398
447
            network_mode.set(retval, 0);
399
448
            continue;
411
460
            run_cpu_benchmarks = true;
412
461
            continue;
413
462
        }
414
 
        if (match_tag(buf, "<work_fetch_no_new_work/>")) {
415
 
            work_fetch_no_new_work = true;
416
 
            continue;
417
 
        }
418
463
        if (match_tag(buf, "<proxy_info>")) {
419
 
            retval = proxy_info.parse(mf);
 
464
            retval = gui_proxy_info.parse(mf);
420
465
            if (retval) {
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)) {
437
482
            continue;
438
483
        }
 
484
#ifndef SIM
439
485
        if (match_tag(buf, "<auto_update>")) {
440
486
            if (!project) {
441
487
                msg_printf(NULL, MSG_INTERNAL_ERROR,
449
495
            }
450
496
            continue;
451
497
        }
 
498
#endif
 
499
#ifdef SIM
 
500
        if (parse_double(buf, "<connection_interval>", connection_interval)) {
 
501
            continue;
 
502
        }
 
503
        if (match_tag(buf, "<available>")) {
 
504
            XML_PARSER xp(&mf);
 
505
            available.parse(xp, "/available");
 
506
            available.init(START_TIME);
 
507
            continue;
 
508
        }
 
509
        if (match_tag(buf, "<idle>")) {
 
510
            XML_PARSER xp(&mf);
 
511
            idle.parse(xp, "/idle");
 
512
            idle.init(START_TIME);
 
513
            continue;
 
514
        }
 
515
#endif
452
516
        if (log_flags.unparsed_xml) {
453
517
            msg_printf(0, MSG_INFO,
454
518
                "[unparsed_xml] state_file: unrecognized: %s", buf
456
520
        }
457
521
        skip_unrecognized(buf, mf);
458
522
    }
 
523
    sort_results();
459
524
    fclose(f);
 
525
    
 
526
    // if total resource share is zero, set all shares to 1
 
527
    //
 
528
    if (projects.size()) {
 
529
        unsigned int i;
 
530
        double x=0;
 
531
        for (i=0; i<projects.size(); i++) {
 
532
            x += projects[i]->resource_share;
 
533
        }
 
534
        if (!x) {
 
535
            msg_printf(NULL, MSG_INFO,
 
536
                "All projects have zero resource share; setting to 100"
 
537
            );
 
538
            for (i=0; i<projects.size(); i++) {
 
539
                projects[i]->resource_share = 100;
 
540
            }
 
541
        }
 
542
    }
460
543
    return 0;
461
544
}
462
545
 
 
546
void CLIENT_STATE::sort_results() {
 
547
    std::sort(
 
548
        results.begin(),
 
549
        results.end(),
 
550
        arrived_first
 
551
    );
 
552
}
 
553
 
 
554
#ifndef SIM
463
555
 
464
556
// Write the client_state.xml file
465
557
//
473
565
    for (attempt=1; attempt<=MAX_STATE_FILE_WRITE_ATTEMPTS; attempt++) {
474
566
        if (attempt > 1) boinc_sleep(1.0);
475
567
            
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"
479
571
            );
480
572
        }
481
573
#ifdef _WIN32
484
576
        retval = mf.open(STATE_FILE_NEXT, "w");
485
577
#endif
486
578
        if (retval) {
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();
500
592
        if (ret1) {
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)
504
596
                );
517
609
            if (boinc_file_exists(STATE_FILE_PREV)) {
518
610
                retval = boinc_delete_file(STATE_FILE_PREV);
519
611
                if (retval) {
520
 
                    if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
 
612
                    if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
521
613
#ifdef _WIN32
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))
525
617
                        );
526
618
#else
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",
 
621
                            strerror(errno)
530
622
                        );
531
623
#endif
532
624
                    }
536
628
            
537
629
            retval = boinc_rename(STATE_FILE_NAME, STATE_FILE_PREV);
538
630
            if (retval) {
539
 
                if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
 
631
                if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
540
632
#ifdef _WIN32
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))
544
636
                    );
545
637
#else
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", 
 
640
                        strerror(errno)
549
641
                    );
550
642
#endif
551
643
                }
554
646
        }
555
647
 
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"
560
652
            );
561
653
        }
562
654
        if (!retval) break;     // Success!
563
655
        
564
 
         if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.state_debug) {
 
656
        if ((attempt == MAX_STATE_FILE_WRITE_ATTEMPTS) || log_flags.statefile_debug) {
565
657
#ifdef _WIN32
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"
569
 
                );
570
 
            } else {
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))
574
 
                );
575
 
            }
 
658
            msg_printf(0, MSG_INFO,
 
659
                "rename error: %s",
 
660
                windows_error_string(win_error_msg, sizeof(win_error_msg))
 
661
            );
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)
581
 
            );
582
 
            if (log_flags.state_debug) {
 
663
            if (log_flags.statefile_debug) {
583
664
                system("ls -al /Library/Application\\ Support/BOINC\\ Data/client*.*");
584
665
            }
585
 
#else
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
589
 
        );
590
666
#endif
591
667
        }
592
668
        if (attempt < MAX_STATE_FILE_WRITE_ATTEMPTS) continue;
599
675
    unsigned int i, j;
600
676
    int retval;
601
677
 
 
678
#ifdef SIM
 
679
    fprintf(stderr, "simulator shouldn't write state file\n");
 
680
    exit(1);
 
681
#endif
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;
617
697
            }
618
698
        }
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
 
703
            //
 
704
            if (p->anonymous_platform && (fip->urls.size()==0)) {
 
705
                continue;
623
706
            }
 
707
            retval = fip->write(f, false);
 
708
            if (retval) return retval;
624
709
        }
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"
649
735
        "%s"
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(),
 
743
        gpu_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());
667
754
    }
668
 
    proxy_info.write(f);
 
755
    if (gui_proxy_info.present) {
 
756
        gui_proxy_info.write(f);
 
757
    }
669
758
    if (strlen(main_host_venue)) {
670
759
        f.printf("<host_venue>%s</host_venue>\n", main_host_venue);
671
760
    }
686
775
    return 0;
687
776
}
688
777
 
 
778
#endif // ifndef SIM
 
779
 
689
780
// look for app_versions.xml file in project dir.
690
781
// If find, get app versions from there,
691
782
// and use "anonymous platform" mechanism for this project
710
801
            // flag as anonymous even if can't parse file
711
802
        retval = parse_app_info(p, f);
712
803
        if (retval) {
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",
 
806
                "%s",
 
807
                _("Syntax error in app_info.xml")
715
808
            );
716
809
        }
717
810
        fclose(f);
718
811
    }
719
812
}
720
813
 
 
814
// parse a project's app_info.xml (anonymous platform) file
 
815
//
721
816
int CLIENT_STATE::parse_app_info(PROJECT* p, FILE* in) {
722
 
    char buf[256];
 
817
    char buf[256], path[1024];
723
818
    MIOFILE mf;
724
819
    mf.init_file(in);
725
820
 
732
827
                delete fip;
733
828
                continue;
734
829
            }
 
830
            if (fip->urls.size()) {
 
831
                msg_printf(p, MSG_INFO,
 
832
                    "Can't specify URLs in app_info.xml"
 
833
                );
 
834
                delete fip;
 
835
                continue;
 
836
            }
735
837
            if (link_file_info(p, fip)) {
736
838
                delete fip;
737
839
                continue;
738
840
            }
 
841
            // check that the file is actually there
 
842
            //
 
843
            get_pathname(fip, path, sizeof(path));
 
844
            if (!boinc_file_exists(path)) {
 
845
                strcpy(buf,
 
846
                    _("File referenced in app_info.xml does not exist: ")
 
847
                );
 
848
                strcat(buf, fip->name);
 
849
                msg_printf(p, MSG_USER_ALERT, buf);
 
850
                delete fip;
 
851
                continue;
 
852
            }
739
853
            fip->status = FILE_PRESENT;
740
854
            file_infos.push_back(fip);
741
855
            continue;
771
885
            continue;
772
886
        }
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",
 
890
                buf
776
891
            );
777
892
        }
778
893
    }
779
894
    return ERR_XML_PARSE;
780
895
}
781
896
 
 
897
#ifndef SIM
 
898
 
782
899
int CLIENT_STATE::write_state_gui(MIOFILE& f) {
783
900
    unsigned int i, j;
784
901
    int retval;
785
902
 
786
903
    f.printf("<client_state>\n");
787
904
 
788
 
    retval = host_info.write(f, false);
 
905
#if 1
 
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
 
909
    //
 
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;
 
916
#endif
794
917
 
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"
820
 
        "%s"
821
 
        "%s",
 
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
828
953
    );
 
954
    for (i=0; i<platforms.size(); i++) {
 
955
        f.printf(
 
956
            "<platform>%s</platform>\n", platforms[i].name.c_str()
 
957
        );
 
958
    }
829
959
 
830
960
    global_prefs.write(f);
831
961
 
 
962
    // the following used by BoincView - don't remove
 
963
    //
832
964
    if (strlen(main_host_venue)) {
833
965
        f.printf("<host_venue>%s</host_venue>\n", main_host_venue);
834
966
    }
837
969
    return 0;
838
970
}
839
971
 
840
 
int CLIENT_STATE::write_tasks_gui(MIOFILE& f) {
 
972
int CLIENT_STATE::write_tasks_gui(MIOFILE& f, bool active_only) {
841
973
    unsigned int i;
842
 
    
843
 
    for (i=0; i<results.size(); i++) {
844
 
        RESULT* rp = results[i];
845
 
        rp->write_gui(f);
 
974
 
 
975
    if (active_only) {
 
976
        for (i=0; i<active_tasks.active_tasks.size(); i++) {
 
977
            RESULT* rp = active_tasks.active_tasks[i]->result;
 
978
            rp->write_gui(f);
 
979
        }
 
980
    } else {
 
981
        for (i=0; i<results.size(); i++) {
 
982
            RESULT* rp = results[i];
 
983
            rp->write_gui(f);
 
984
        }
846
985
    }
847
986
    return 0;
848
987
}
864
1003
    return 0;
865
1004
}
866
1005
 
867
 
const char *BOINC_RCSID_375ec798cc = "$Id: cs_statefile.cpp 16069 2008-09-26 18:20:24Z davea $";
 
1006
#endif