// Berkeley Open Infrastructure for Network Computing // http://boinc.berkeley.edu // Copyright (C) 2005 University of California // // This 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 2.1 of the License, or (at your option) any later version. // // This software 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. // // To view the GNU Lesser General Public License visit // http://www.gnu.org/copyleft/lesser.html // or write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // 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 to the "C" locale, // each GUI RPC should retrieve 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; DISPLAY_INFO::DISPLAY_INFO() { memset(this, 0, sizeof(DISPLAY_INFO)); } int GUI_URL::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; if (match_tag(buf, "")) break; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", description)) continue; else 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) { char tag[256]; bool is_tag; while (!xp.get(tag, sizeof(tag), is_tag)) { if (!strcmp(tag, "/project")) return 0; if (xp.parse_string(tag, "name", name)) continue; if (xp.parse_string(tag, "url", url)) continue; if (xp.parse_string(tag, "general_area", general_area)) continue; if (xp.parse_string(tag, "specific_area", specific_area)) continue; if (xp.parse_string(tag, "description", description)) continue; if (xp.parse_string(tag, "home", home)) continue; if (xp.parse_string(tag, "image", image)) continue; xp.skip_unexpected(tag); } return ERR_XML_PARSE; } void PROJECT_LIST_ENTRY::clear() { name.clear(); url.clear(); general_area.clear(); specific_area.clear(); description.clear(); home.clear(); image.clear(); rand = 0.0; } bool PROJECT_LIST_ENTRY::operator<(const PROJECT_LIST_ENTRY& compare) { return rand < compare.rand; } PROJECT::PROJECT() { clear(); } PROJECT::~PROJECT() { clear(); } void PROJECT::get_name(std::string& s) { if (project_name.length() == 0) { s = master_url; } else { s = project_name; } } void PROJECT::copy(PROJECT& p) { resource_share = p.resource_share; project_name = p.project_name; user_name = p.user_name; team_name = p.team_name; gui_urls = p.gui_urls; user_total_credit = p.user_total_credit; user_expavg_credit = p.user_expavg_credit; host_total_credit = p.host_total_credit; host_expavg_credit = p.host_expavg_credit; disk_usage = p.disk_usage; master_fetch_failures = p.master_fetch_failures; nrpc_failures = p.nrpc_failures; min_rpc_time = p.min_rpc_time; short_term_debt = p.short_term_debt; long_term_debt = p.long_term_debt; duration_correction_factor = p.duration_correction_factor; master_url_fetch_pending = p.master_url_fetch_pending; sched_rpc_pending = p.sched_rpc_pending; non_cpu_intensive = p.non_cpu_intensive; suspended_via_gui = p.suspended_via_gui; dont_request_more_work = p.dont_request_more_work; scheduler_rpc_in_progress = p.scheduler_rpc_in_progress; attached_via_acct_mgr = p.attached_via_acct_mgr; detach_when_done = p.detach_when_done; ended = p.ended; project_files_downloaded_time = p.project_files_downloaded_time; last_rpc_time = p.last_rpc_time; } int PROJECT::parse(MIOFILE& in) { char buf[256]; int retval; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", master_url)) continue; else if (parse_double(buf, "", resource_share)) continue; else if (parse_str(buf, "", project_name)) continue; else if (parse_str(buf, "", user_name)) continue; else if (parse_str(buf, "", team_name)) continue; else if (parse_double(buf, "", user_total_credit)) continue; else if (parse_double(buf, "", user_expavg_credit)) continue; else if (parse_double(buf, "", host_total_credit)) continue; else if (parse_double(buf, "", host_expavg_credit)) continue; else if (parse_double(buf, "", disk_usage)) continue; else if (parse_int(buf, "", nrpc_failures)) continue; else if (parse_int(buf, "", master_fetch_failures)) continue; else if (parse_double(buf, "", min_rpc_time)) continue; else if (parse_double(buf, "", short_term_debt)) continue; else if (parse_double(buf, "", long_term_debt)) continue; else if (parse_double(buf, "", duration_correction_factor)) continue; else if (match_tag(buf, "")) { master_url_fetch_pending = true; continue; } else if (parse_int(buf, "", sched_rpc_pending)) continue; else if (parse_int(buf, "", rr_sim_deadlines_missed)) continue; else if (match_tag(buf, "")) { non_cpu_intensive = true; continue; } else if (match_tag(buf, "")) { suspended_via_gui = true; continue; } else if (match_tag(buf, "")) { dont_request_more_work = true; continue; } else if (match_tag(buf, "")) { ended = true; continue; } else if (match_tag(buf, "")) { scheduler_rpc_in_progress = true; continue; } else if (match_tag(buf, "")) { attached_via_acct_mgr = true; continue; } else if (match_tag(buf, "")) { detach_when_done = true; continue; } else if (match_tag(buf, "")) { while (in.fgets(buf, 256)) { if (match_tag(buf, "")) break; else if (match_tag(buf, "")) { GUI_URL gu; retval = gu.parse(in); if (retval) break; gui_urls.push_back(gu); } } continue; } else if (parse_double(buf, "", project_files_downloaded_time)) continue; else if (parse_double(buf, "", last_rpc_time)) continue; } return ERR_XML_PARSE; } void PROJECT::clear() { master_url.clear(); resource_share = 0.0; project_name.clear(); user_name.clear(); team_name.clear(); user_total_credit = 0.0; user_expavg_credit = 0.0; host_total_credit = 0.0; host_expavg_credit = 0.0; disk_usage = 0.0; nrpc_failures = 0; master_fetch_failures = 0; min_rpc_time = 0; short_term_debt = 0; long_term_debt = 0; duration_correction_factor = 0; 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; project_files_downloaded_time = 0; last_rpc_time = 0; gui_urls.clear(); statistics.clear(); } APP::APP() { clear(); } APP::~APP() { clear(); } int APP::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", user_friendly_name)) continue; } return ERR_XML_PARSE; } void APP::clear() { name.clear(); project = NULL; } APP_VERSION::APP_VERSION() { clear(); } APP_VERSION::~APP_VERSION() { clear(); } int APP_VERSION::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", app_name)) continue; else if (parse_int(buf, "", version_num)) continue; } return ERR_XML_PARSE; } void APP_VERSION::clear() { app_name.clear(); version_num = 0; app = NULL; project = NULL; } WORKUNIT::WORKUNIT() { clear(); } WORKUNIT::~WORKUNIT() { clear(); } int WORKUNIT::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", app_name)) continue; else if (parse_int(buf, "", version_num)) continue; else if (parse_double(buf, "", rsc_fpops_est)) continue; else if (parse_double(buf, "", rsc_fpops_bound)) continue; else if (parse_double(buf, "", rsc_memory_bound)) continue; else if (parse_double(buf, "", rsc_disk_bound)) continue; } return ERR_XML_PARSE; } void WORKUNIT::clear() { name.clear(); app_name.clear(); version_num = 0; rsc_fpops_est = 0.0; rsc_fpops_bound = 0.0; rsc_memory_bound = 0.0; rsc_disk_bound = 0.0; project = NULL; app = NULL; avp = NULL; } RESULT::RESULT() { clear(); } RESULT::~RESULT() { clear(); } int RESULT::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", wu_name)) continue; else if (parse_str(buf, "", project_url)) continue; else if (parse_int(buf, "", report_deadline)) continue; else if (match_tag(buf, "")) { ready_to_report = true; continue; } else if (match_tag(buf, "")) { got_server_ack = true; continue; } else if (match_tag(buf, "")) { suspended_via_gui = true; continue; } else if (match_tag(buf, "")) { project_suspended_via_gui = true; continue; } else if (match_tag(buf, "")) { active_task = true; continue; } else if (match_tag(buf, "")) { supports_graphics = true; continue; } else if (parse_int(buf, "", graphics_mode_acked)) continue; else if (parse_double(buf, "", final_cpu_time)) continue; else if (parse_int(buf, "", state)) continue; else if (parse_int(buf, "", scheduler_state)) continue; else if (parse_int(buf, "", exit_status)) continue; else if (parse_int(buf, "", signal)) continue; else if (parse_int(buf, "", active_task_state)) continue; else if (match_tag(buf, "")) { copy_element_contents(in, "", stderr_out); } else if (parse_int(buf, "", app_version_num)) continue; else if (parse_double(buf, "", checkpoint_cpu_time)) continue; else if (parse_double(buf, "", current_cpu_time)) continue; else if (parse_double(buf, "", swap_size)) continue; else if (parse_double(buf, "", working_set_size_smoothed)) continue; else if (parse_double(buf, "", fraction_done)) continue; else if (parse_double(buf, "", estimated_cpu_time_remaining)) continue; else if (match_tag(buf, "")) { too_large = true; continue; } else if (match_tag(buf, "")) { edf_scheduled = true; continue; } } return ERR_XML_PARSE; } void RESULT::clear() { name.clear(); wu_name.clear(); project_url.clear(); report_deadline = 0; ready_to_report = false; got_server_ack = false; final_cpu_time = 0.0; state = 0; scheduler_state = 0; exit_status = 0; signal = 0; stderr_out.clear(); suspended_via_gui = false; project_suspended_via_gui = false; active_task = false; active_task_state = 0; app_version_num = 0; checkpoint_cpu_time = 0.0; current_cpu_time = 0.0; fraction_done = 0.0; swap_size = 0; working_set_size_smoothed = 0; estimated_cpu_time_remaining = 0.0; supports_graphics = false; graphics_mode_acked = 0; too_large = false; edf_scheduled = false; app = NULL; wup = NULL; project = NULL; } FILE_TRANSFER::FILE_TRANSFER() { clear(); } FILE_TRANSFER::~FILE_TRANSFER() { clear(); } int FILE_TRANSFER::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", project_url)) continue; else if (parse_str(buf, "", project_name)) continue; else if (parse_double(buf, "", nbytes)) continue; else if (match_tag(buf, "")) { generated_locally = true; continue; } else if (match_tag(buf, "")) { uploaded = true; continue; } else if (match_tag(buf, "")) { upload_when_present = true; continue; } else if (match_tag(buf, "")) { sticky = true; continue; } else if (match_tag(buf, "")) { pers_xfer_active = true; continue; } else if (match_tag(buf, "")) { xfer_active = true; continue; } else if (parse_int(buf, "", num_retries)) continue; else if (parse_int(buf, "", first_request_time)) continue; else if (parse_int(buf, "", next_request_time)) continue; else if (parse_int(buf, "", status)) continue; else if (parse_double(buf, "", time_so_far)) continue; else if (parse_double(buf, "", bytes_xferred)) continue; else if (parse_double(buf, "", file_offset)) continue; else if (parse_double(buf, "", xfer_speed)) continue; else if (parse_str(buf, "", hostname)) continue; } return ERR_XML_PARSE; } void FILE_TRANSFER::clear() { name.clear(); project_url.clear(); project_name.clear(); nbytes = 0.0; generated_locally = false; uploaded = false; upload_when_present = false; 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.0; bytes_xferred = 0.0; file_offset = 0.0; xfer_speed = 0.0; hostname.clear(); project = NULL; } MESSAGE::MESSAGE() { clear(); } MESSAGE::~MESSAGE() { clear(); } int MESSAGE::parse(MIOFILE& in) { char buf[256]; while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", project)) continue; else if (match_tag(buf, "" )) { copy_element_contents(in, "", body); continue; } else if (parse_int(buf, "", priority)) continue; else if (parse_int(buf, "