// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . // This file contains: // 1) functions to clear and parse the various structs // 2) actual GUI RPCs // The core client expects all data to be formatted in the "C" locale, // so each GUI RPC should get the current locale, then switch to the // "C" locale before formatting messages or parsing results. // After all work is completed, revert back to the original locale. // // Template: // // int RPC_CLIENT::template_function( args ) { // int retval; // SET_LOCALE sl; // char buf[256]; // RPC rpc(this); // // // // return retval; // } // // NOTE: Failing to revert back to the original locale will cause // formatting failures for any software that has been localized or // displays localized data. #if defined(_WIN32) && !defined(__STDWX_H__) && !defined(_BOINC_WIN_) && !defined(_AFX_STDAFX_H_) #include "boinc_win.h" #endif #ifdef _WIN32 #include "../version.h" #else #include "config.h" #include #include #include #include #include #include #include #include #endif #include "diagnostics.h" #include "parse.h" #include "str_util.h" #include "util.h" #include "error_numbers.h" #include "miofile.h" #include "md5_file.h" #include "network.h" #include "common_defs.h" #include "gui_rpc_client.h" using std::string; using std::vector; using std::sort; DISPLAY_INFO::DISPLAY_INFO() { memset(this, 0, sizeof(DISPLAY_INFO)); } int GUI_URL::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (match_tag(buf, "")) break; if (parse_str(buf, "", name)) continue; if (parse_str(buf, "", description)) continue; if (parse_str(buf, "", url)) continue; } return ERR_XML_PARSE; } PROJECT_LIST_ENTRY::PROJECT_LIST_ENTRY() { clear(); } PROJECT_LIST_ENTRY::~PROJECT_LIST_ENTRY() { clear(); } int PROJECT_LIST_ENTRY::parse(XML_PARSER& xp) { string platform; while (!xp.get_tag()) { if (xp.match_tag("/project")) return 0; if (xp.parse_string("name", name)) continue; if (xp.parse_string("url", url)) { continue; } if (xp.parse_string("general_area", general_area)) continue; if (xp.parse_string("specific_area", specific_area)) continue; if (xp.parse_string("description", description)) { continue; } if (xp.parse_string("home", home)) continue; if (xp.parse_string("image", image)) continue; if (xp.match_tag("platforms")) { while (!xp.get_tag()) { if (xp.match_tag("/platforms")) break; if (xp.parse_string("name", platform)) { platforms.push_back(platform); } } } xp.skip_unexpected(false, ""); } return ERR_XML_PARSE; } void PROJECT_LIST_ENTRY::clear() { name.clear(); url.clear(); general_area.clear(); specific_area.clear(); description.clear(); platforms.clear(); home.clear(); image.clear(); } AM_LIST_ENTRY::AM_LIST_ENTRY() { clear(); } AM_LIST_ENTRY::~AM_LIST_ENTRY() { clear(); } int AM_LIST_ENTRY::parse(XML_PARSER& xp) { while (!xp.get_tag()) { if (xp.match_tag("/account_manager")) return 0; if (xp.parse_string("name", name)) continue; if (xp.parse_string("url", url)) continue; if (xp.parse_string("description", description)) continue; if (xp.parse_string("image", image)) continue; } return 0; } void AM_LIST_ENTRY::clear() { name.clear(); url.clear(); description.clear(); image.clear(); } ALL_PROJECTS_LIST::ALL_PROJECTS_LIST() { } ALL_PROJECTS_LIST::~ALL_PROJECTS_LIST() { clear(); } bool compare_project_list_entry(const PROJECT_LIST_ENTRY* a, const PROJECT_LIST_ENTRY* b) { #ifdef _WIN32 return _stricmp(a->name.c_str(), b->name.c_str()) < 0; #else return strcasecmp(a->name.c_str(), b->name.c_str()) < 0; #endif } bool compare_am_list_entry(const AM_LIST_ENTRY* a, const AM_LIST_ENTRY* b) { #ifdef _WIN32 return _stricmp(a->name.c_str(), b->name.c_str()) < 0; #else return strcasecmp(a->name.c_str(), b->name.c_str()) < 0; #endif } void ALL_PROJECTS_LIST::shuffle() { sort(projects.begin(), projects.end(), compare_project_list_entry); sort(account_managers.begin(), account_managers.end(), compare_am_list_entry); } void ALL_PROJECTS_LIST::clear() { unsigned int i; for (i=0; i")) return 0; if (parse_str(buf, "", master_url, sizeof(master_url))) continue; if (parse_double(buf, "", resource_share)) continue; if (parse_str(buf, "", project_name)) continue; if (parse_str(buf, "", user_name)) { xml_unescape(user_name); continue; } if (parse_str(buf, "", team_name)) { xml_unescape(team_name); continue; } if (parse_int(buf, "", hostid)) continue; if (parse_double(buf, "", user_total_credit)) continue; if (parse_double(buf, "", user_expavg_credit)) continue; if (parse_double(buf, "", host_total_credit)) continue; if (parse_double(buf, "", host_expavg_credit)) continue; if (parse_double(buf, "", disk_usage)) continue; if (parse_int(buf, "", nrpc_failures)) continue; if (parse_int(buf, "", master_fetch_failures)) continue; if (parse_double(buf, "", min_rpc_time)) continue; if (parse_double(buf, "", download_backoff)) continue; if (parse_double(buf, "", upload_backoff)) continue; if (parse_double(buf, "", sched_priority)) continue; if (parse_double(buf, "", cpu_backoff_time)) continue; if (parse_double(buf, "", cpu_backoff_interval)) continue; if (parse_double(buf, "", cuda_backoff_time)) continue; if (parse_double(buf, "", cuda_backoff_interval)) continue; if (parse_double(buf, "", ati_backoff_time)) continue; if (parse_double(buf, "", ati_backoff_interval)) continue; if (parse_double(buf, "", duration_correction_factor)) continue; if (parse_bool(buf, "anonymous_platform", anonymous_platform)) continue; if (parse_bool(buf, "master_url_fetch_pending", master_url_fetch_pending)) continue; if (parse_int(buf, "", sched_rpc_pending)) continue; if (parse_bool(buf, "non_cpu_intensive", non_cpu_intensive)) continue; if (parse_bool(buf, "suspended_via_gui", suspended_via_gui)) continue; if (parse_bool(buf, "dont_request_more_work", dont_request_more_work)) continue; if (parse_bool(buf, "ended", ended)) continue; if (parse_bool(buf, "scheduler_rpc_in_progress", scheduler_rpc_in_progress)) continue; if (parse_bool(buf, "attached_via_acct_mgr", attached_via_acct_mgr)) continue; if (parse_bool(buf, "detach_when_done", detach_when_done)) continue; if (parse_bool(buf, "trickle_up_pending", trickle_up_pending)) continue; if (match_tag(buf, "")) { while (in.fgets(buf, 256)) { if (match_tag(buf, "")) break; if (match_tag(buf, "")) { GUI_URL gu; retval = gu.parse(xp); if (retval) break; gui_urls.push_back(gu); continue; } } continue; } if (parse_double(buf, "", project_files_downloaded_time)) continue; if (parse_double(buf, "", last_rpc_time)) continue; if (parse_bool(buf, "no_cpu_pref", no_cpu_pref)) continue; if (parse_bool(buf, "no_cuda_pref", no_cuda_pref)) continue; if (parse_bool(buf, "no_ati_pref", no_ati_pref)) continue; if (parse_str(buf, "venue", venue, sizeof(venue))) continue; } return ERR_XML_PARSE; } void PROJECT::clear() { strcpy(master_url, ""); resource_share = 0; project_name.clear(); user_name.clear(); team_name.clear(); user_total_credit = 0; user_expavg_credit = 0; host_total_credit = 0; host_expavg_credit = 0; disk_usage = 0; nrpc_failures = 0; master_fetch_failures = 0; min_rpc_time = 0; download_backoff = 0; upload_backoff = 0; cpu_backoff_time = 0; cpu_backoff_interval = 0; cuda_backoff_time = 0; cuda_backoff_interval = 0; ati_backoff_time = 0; ati_backoff_interval = 0; duration_correction_factor = 0; anonymous_platform = false; master_url_fetch_pending = false; sched_rpc_pending = 0; ended = false; non_cpu_intensive = false; suspended_via_gui = false; dont_request_more_work = false; scheduler_rpc_in_progress = false; attached_via_acct_mgr = false; detach_when_done = false; trickle_up_pending = false; project_files_downloaded_time = 0; last_rpc_time = 0; gui_urls.clear(); statistics.clear(); no_cpu_pref = false; no_cuda_pref = false; no_ati_pref = false; strcpy(venue, ""); } APP::APP() { clear(); } APP::~APP() { clear(); } int APP::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (parse_str(buf, "", name, sizeof(name))) continue; if (parse_str(buf, "", user_friendly_name, sizeof(user_friendly_name))) continue; } return ERR_XML_PARSE; } void APP::clear() { strcpy(name, ""); strcpy(user_friendly_name, ""); project = NULL; } APP_VERSION::APP_VERSION() { clear(); } APP_VERSION::~APP_VERSION() { clear(); } int APP_VERSION::parse_coproc(MIOFILE& in) { char buf[256], type_buf[256]; double count = 0; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) { if (!strcmp(type_buf, "CUDA")) { ncudas = count; } else if (!strcmp(type_buf, GPU_TYPE_ATI)) { natis = count; } return 0; } if (parse_str(buf, "", type_buf, sizeof(type_buf))) continue; if (parse_double(buf, "", count)) continue; } return ERR_XML_PARSE; } int APP_VERSION::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (parse_str(buf, "", app_name, sizeof(app_name))) continue; if (parse_int(buf, "", version_num)) continue; if (parse_str(buf, "", plan_class, sizeof(plan_class))) continue; if (parse_str(buf, "", platform, sizeof(platform))) continue; if (parse_double(buf, "", avg_ncpus)) continue; if (parse_double(buf, "", gpu_ram)) continue; if (parse_double(buf, "", flops)) continue; if (match_tag(buf, "")) { parse_coproc(in); continue; } } return ERR_XML_PARSE; } void APP_VERSION::clear() { memset(this, 0, sizeof(*this)); } WORKUNIT::WORKUNIT() { clear(); } WORKUNIT::~WORKUNIT() { clear(); } int WORKUNIT::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (parse_str(buf, "", name, sizeof(name))) continue; if (parse_str(buf, "", app_name, sizeof(app_name))) continue; if (parse_int(buf, "", version_num)) continue; if (parse_double(buf, "", rsc_fpops_est)) continue; if (parse_double(buf, "", rsc_fpops_bound)) continue; if (parse_double(buf, "", rsc_memory_bound)) continue; if (parse_double(buf, "", rsc_disk_bound)) continue; } return ERR_XML_PARSE; } void WORKUNIT::clear() { strcpy(name, ""); strcpy(app_name, ""); version_num = 0; rsc_fpops_est = 0; rsc_fpops_bound = 0; rsc_memory_bound = 0; rsc_disk_bound = 0; project = NULL; app = NULL; } RESULT::RESULT() { clear(); } RESULT::~RESULT() { clear(); } int RESULT::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) { // if CPU time is nonzero but elapsed time is zero, // we must be talking to an old client. // Set elapsed = CPU // (easier to deal with this here than in the manager) // if (current_cpu_time && !elapsed_time) { elapsed_time = current_cpu_time; } if (final_cpu_time && !final_elapsed_time) { final_elapsed_time = final_cpu_time; } return 0; } if (parse_str(buf, "", name, sizeof(name))) continue; if (parse_str(buf, "", wu_name, sizeof(wu_name))) continue; if (parse_int(buf, "", version_num)) continue; if (parse_str(buf, "", plan_class, sizeof(plan_class))) continue; if (parse_str(buf, "", project_url, sizeof(project_url))) continue; if (parse_double(buf, "", report_deadline)) continue; if (parse_double(buf, "", received_time)) continue; if (parse_bool(buf, "ready_to_report", ready_to_report)) continue; if (parse_bool(buf, "got_server_ack", got_server_ack)) continue; if (parse_bool(buf, "suspended_via_gui", suspended_via_gui)) continue; if (parse_bool(buf, "project_suspended_via_gui", project_suspended_via_gui)) continue; if (parse_bool(buf, "coproc_missing", coproc_missing)) continue; if (parse_bool(buf, "gpu_mem_wait", gpu_mem_wait)) continue; if (match_tag(buf, "")) { active_task = true; continue; } if (parse_bool(buf, "supports_graphics", supports_graphics)) continue; if (parse_int(buf, "", graphics_mode_acked)) continue; if (parse_double(buf, "", final_cpu_time)) continue; if (parse_double(buf, "", final_elapsed_time)) continue; if (parse_int(buf, "", state)) continue; if (parse_int(buf, "", scheduler_state)) continue; if (parse_int(buf, "", exit_status)) continue; if (parse_int(buf, "", signal)) continue; if (parse_int(buf, "", active_task_state)) continue; #if 0 if (match_tag(buf, "")) { copy_element_contents(in, "", stderr_out); continue; } #endif if (parse_int(buf, "", app_version_num)) continue; if (parse_int(buf, "", slot)) continue; if (parse_int(buf, "", pid)) continue; if (parse_double(buf, "", checkpoint_cpu_time)) continue; if (parse_double(buf, "", current_cpu_time)) continue; if (parse_double(buf, "", elapsed_time)) continue; if (parse_double(buf, "", swap_size)) continue; if (parse_double(buf, "", working_set_size_smoothed)) continue; if (parse_double(buf, "", fraction_done)) continue; if (parse_double(buf, "", estimated_cpu_time_remaining)) continue; if (parse_bool(buf, "too_large", too_large)) continue; if (parse_bool(buf, "needs_shmem", needs_shmem)) continue; if (parse_bool(buf, "edf_scheduled", edf_scheduled)) continue; if (parse_str(buf, "graphics_exec_path", graphics_exec_path, sizeof(graphics_exec_path))) continue; if (parse_str(buf, "slot_path", slot_path, sizeof(slot_path))) continue; if (parse_str(buf, "resources", resources, sizeof(resources))) continue; } return ERR_XML_PARSE; } void RESULT::clear() { strcpy(name, ""); strcpy(wu_name, ""); version_num = 0; strcpy(plan_class, ""); strcpy(project_url, ""); strcpy(graphics_exec_path, ""); strcpy(slot_path, ""); strcpy(resources, ""); report_deadline = 0; received_time = 0; ready_to_report = false; got_server_ack = false; final_cpu_time = 0; final_elapsed_time = 0; state = 0; scheduler_state = 0; exit_status = 0; signal = 0; //stderr_out.clear(); suspended_via_gui = false; project_suspended_via_gui = false; coproc_missing = false; gpu_mem_wait = false; active_task = false; active_task_state = 0; app_version_num = 0; slot = -1; pid = 0; checkpoint_cpu_time = 0; current_cpu_time = 0; fraction_done = 0; elapsed_time = 0; swap_size = 0; working_set_size_smoothed = 0; estimated_cpu_time_remaining = 0; supports_graphics = false; graphics_mode_acked = 0; too_large = false; needs_shmem = false; edf_scheduled = false; app = NULL; wup = NULL; project = NULL; avp = NULL; } FILE_TRANSFER::FILE_TRANSFER() { clear(); } FILE_TRANSFER::~FILE_TRANSFER() { clear(); } int FILE_TRANSFER::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (parse_str(buf, "", name)) continue; if (parse_str(buf, "", project_url)) continue; if (parse_str(buf, "", project_name)) continue; if (parse_double(buf, "", nbytes)) continue; if (parse_bool(buf, "sticky", sticky)) continue; if (match_tag(buf, "")) { pers_xfer_active = true; continue; } if (match_tag(buf, "")) { xfer_active = true; continue; } if (parse_bool(buf, "is_upload", is_upload)) { generated_locally = is_upload; continue; } if (parse_bool(buf, "generated_locally", generated_locally)) { is_upload = generated_locally; } if (parse_int(buf, "", num_retries)) continue; if (parse_int(buf, "", first_request_time)) continue; if (parse_int(buf, "", next_request_time)) continue; if (parse_int(buf, "", status)) continue; if (parse_double(buf, "", time_so_far)) continue; if (parse_double(buf, "", bytes_xferred)) continue; if (parse_double(buf, "", file_offset)) continue; if (parse_double(buf, "", xfer_speed)) continue; if (parse_str(buf, "", hostname)) continue; if (parse_double(buf, "", project_backoff)) continue; } return ERR_XML_PARSE; } void FILE_TRANSFER::clear() { name.clear(); project_url.clear(); project_name.clear(); nbytes = 0; sticky = false; pers_xfer_active = false; xfer_active = false; num_retries = 0; first_request_time = 0; next_request_time = 0; status = 0; time_so_far = 0; bytes_xferred = 0; file_offset = 0; xfer_speed = 0; hostname.clear(); project = NULL; project_backoff = 0; } MESSAGE::MESSAGE() { clear(); } MESSAGE::~MESSAGE() { clear(); } int MESSAGE::parse(XML_PARSER& xp) { char buf[256]; MIOFILE& in = *(xp.f); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (parse_str(buf, "", project)) continue; if (match_tag(buf, "" )) { copy_element_contents(in, "", body); continue; } if (parse_int(buf, "", priority)) continue; if (parse_int(buf, "