diff --git a/api/boinc_api.C b/api/boinc_api.C index 23c757c67d..fca1dacfa6 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -120,6 +120,7 @@ static int want_network = 0; static int have_network = 1; bool g_sleep = false; // simulate unresponsive app by setting to true (debugging) +static FUNC_PTR timer_callback = 0; #define TIMER_PERIOD 1 // period of worker-thread timer interrupts. @@ -176,14 +177,14 @@ static int setup_shared_mem() { return 0; } -// Return CPU time of worker thread. +// Return CPU time of worker thread (and optionally others) // This may be called from other threads // -static int boinc_worker_thread_cpu_time(double& cpu) { +double boinc_worker_thread_cpu_time() { static double last_cpu=0; static time_t last_time=0; time_t now = time(0); - double time_diff = now-last_time; + double cpu, time_diff = now - last_time; #ifdef _WIN32 int retval; if (options.all_threads_cpu_time) { @@ -195,24 +196,23 @@ static int boinc_worker_thread_cpu_time(double& cpu) { cpu = nrunning_ticks * TIMER_PERIOD; // for Win9x } #else - if (!pthread_mutex_lock(&getrusage_mutex)) { - cpu = (double)worker_thread_ru.ru_utime.tv_sec - + (((double)worker_thread_ru.ru_utime.tv_usec)/1000000.0); - cpu += (double)worker_thread_ru.ru_stime.tv_sec - + (((double)worker_thread_ru.ru_stime.tv_usec)/1000000.0); - pthread_mutex_unlock(&getrusage_mutex); - } + if (pthread_mutex_lock(&getrusage_mutex)) return last_cpu; + cpu = (double)worker_thread_ru.ru_utime.tv_sec + + (((double)worker_thread_ru.ru_utime.tv_usec)/1000000.0); + cpu += (double)worker_thread_ru.ru_stime.tv_sec + + (((double)worker_thread_ru.ru_stime.tv_usec)/1000000.0); + pthread_mutex_unlock(&getrusage_mutex); #endif double cpu_diff = cpu - last_cpu; - if (cpu_diff>(time_diff+1)) { + if (cpu_diff>(time_diff + 1)) { // fprintf(stderr,"CPU time incrementing faster than real time. Correcting.\n"); - cpu = last_cpu+time_diff; + cpu = last_cpu + time_diff; } - if (time_diff != 0) { - last_cpu=cpu; - last_time=now; + if (time_diff) { + last_cpu = cpu; + last_time = now; } - return 0; + return cpu; } // communicate to the core client (via shared mem) @@ -382,7 +382,7 @@ static void send_trickle_up_msg() { int boinc_finish(int status) { if (options.send_status_msgs) { double total_cpu; - boinc_worker_thread_cpu_time(total_cpu); + total_cpu = boinc_worker_thread_cpu_time(); total_cpu += initial_wu_cpu_time; // NOTE: the app_status slot may already contain a message. @@ -693,7 +693,10 @@ static void handle_process_control_msg() { } } -static void worker_timer(int /*a*/) { +// once-a-second timer. +// Runs in a separate thread (not the worker thread) +// +static void timer_handler() { if (g_sleep) return; interrupt_count++; if (!ready_to_checkpoint) { @@ -740,7 +743,7 @@ static void worker_timer(int /*a*/) { time_until_fraction_done_update -= TIMER_PERIOD; if (time_until_fraction_done_update <= 0) { double cur_cpu; - boinc_worker_thread_cpu_time(cur_cpu); + cur_cpu = boinc_worker_thread_cpu_time(); last_wu_cpu_time = cur_cpu + initial_wu_cpu_time; update_app_progress(last_wu_cpu_time, last_checkpoint_cpu_time); time_until_fraction_done_update = (int)aid.fraction_done_update_period; @@ -749,6 +752,9 @@ static void worker_timer(int /*a*/) { if (options.handle_trickle_ups) { send_trickle_up_msg(); } + if (timer_callback) { + timer_callback(); + } } #ifdef _WIN32 @@ -756,41 +762,17 @@ static void worker_timer(int /*a*/) { static HANDLE timer_quit_event; UINT WINAPI timer_thread(void *) { - DWORD dwEvent = NULL; - BOOL bContinue = TRUE; - diagnostics_set_thread_name("Timer"); + while (1) { + Sleep(TIMER_PERIOD*1000); + timer_handler(); - // Create the event that can be used to shutdown the timer thread. - // - timer_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!timer_quit_event) { - fprintf(stderr, "timer_thread(): CreateEvent() failed, GLE %d.\n", GetLastError()); - } - - while (bContinue) { - dwEvent = WaitForSingleObject( - timer_quit_event, - TIMER_PERIOD*1000 - ); - switch(dwEvent) { - case WAIT_OBJECT_0: - // timer_quit_event was signaled. - bContinue = FALSE; - break; - case WAIT_TIMEOUT: - // process any shared memory messages. - worker_timer(0); - - // poor man's CPU time accounting for Win9x - // - if (!boinc_status.suspended) { - nrunning_ticks++; - } - break; + // poor man's CPU time accounting for Win9x + // + if (!boinc_status.suspended) { + nrunning_ticks++; } } - return 0; } @@ -800,11 +782,15 @@ void* timer_thread(void*) { block_sigalrm(); while(1) { boinc_sleep(TIMER_PERIOD); - worker_timer(0); + timer_handler(); } return 0; } +// This SIGALRM handler gets handled only by the worker thread. +// It gets CPU time and implements sleeping. +// It must call only signal-safe functions, and must not do FP math +// void worker_signal_handler(int) { if (!pthread_mutex_trylock(&getrusage_mutex)) { getrusage(RUSAGE_SELF, &worker_thread_ru); @@ -828,7 +814,7 @@ int set_worker_timer() { #ifdef _WIN32 - // as long as we're here, get the worker thread handle + // get the worker thread handle // DuplicateHandle( GetCurrentProcess(), @@ -840,13 +826,12 @@ int set_worker_timer() { DUPLICATE_SAME_ACCESS ); - // Initialize the worker thread info for diagnostic purposes. // diagnostics_set_thread_name("Worker"); diagnostics_set_thread_worker(); - // Create the timer thread to deal with shared memory control messages. + // Create the timer thread // uintptr_t thread; UINT uiThreadId; @@ -865,7 +850,7 @@ int set_worker_timer() { return retval; } - // lower our priority here + // lower our priority // SetThreadPriority(worker_thread_handle, THREAD_PRIORITY_IDLE); @@ -877,6 +862,8 @@ int set_worker_timer() { return retval; } + // set up a periodic SIGALRM, to be hanled by the worker thread + // struct sigaction sa; itimerval value; sa.sa_handler = worker_signal_handler; @@ -924,7 +911,7 @@ int boinc_time_to_checkpoint() { int boinc_checkpoint_completed() { double cur_cpu; - boinc_worker_thread_cpu_time(cur_cpu); + cur_cpu = boinc_worker_thread_cpu_time(); last_wu_cpu_time = cur_cpu + aid.wu_cpu_time; last_checkpoint_cpu_time = last_wu_cpu_time; if (options.send_status_msgs) { @@ -1039,4 +1026,8 @@ void block_sigalrm() { } #endif +void boinc_register_timer_callback(FUNC_PTR p) { + timer_callback = p; +} + const char *BOINC_RCSID_0fa0410386 = "$Id$"; diff --git a/api/boinc_api.h b/api/boinc_api.h index bc4a65b3b2..9fdbb2ccb6 100755 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -67,6 +67,8 @@ typedef struct BOINC_STATUS { double max_working_set_size; } BOINC_STATUS; +typedef void (*FUNC_PTR)(); + struct APP_INIT_DATA; extern int boinc_init(void); @@ -94,6 +96,8 @@ extern int boinc_receive_trickle_down(char* buf, int len); extern int boinc_init_options(BOINC_OPTIONS*); extern int boinc_get_status(BOINC_STATUS*); extern double boinc_get_fraction_done(); +extern void boinc_register_timer_callback(FUNC_PTR); +extern double boinc_worker_thread_cpu_time(); #ifdef __APPLE__ extern int setMacPList(void); diff --git a/api/graphics2.h b/api/graphics2.h index 99d372c6b9..327d851db8 100644 --- a/api/graphics2.h +++ b/api/graphics2.h @@ -1,29 +1,20 @@ #ifndef _GRAPHICS2_H_ #define _GRAPHICS2_H_ -#ifdef __cplusplus -extern "C" { -#endif - // Functions that must be supplied by the app // extern void app_graphics_render(int xs, int ys, double time_of_day); extern void app_graphics_init(void); - // called each time a window is opened; - // called in the graphics thread extern void app_graphics_reread_prefs(void); // called when get REREAD_PREFS message from core client. - // called in the graphics thread extern void app_graphics_resize(int width, int height); extern void boinc_app_mouse_button(int x, int y, int which, int is_down); extern void boinc_app_mouse_move(int x, int y, int left, int middle, int right); extern void boinc_app_key_press(int, int); extern void boinc_app_key_release(int, int); -// C++ API follows here -#ifdef __cplusplus -} // end extern "C" - +// Functions that the app can call +// extern void boinc_graphics_loop(int, char**); extern void* boinc_graphics_make_shmem(char*, int); extern void* boinc_graphics_get_shmem(char*); @@ -35,7 +26,4 @@ extern double boinc_max_gfx_cpu_frac; extern void get_window_title(char* buf, int len); extern bool throttled_app_render(int, int, double); -#endif // C++ API - - #endif diff --git a/api/graphics2_win.C b/api/graphics2_win.C index 1710fcd561..4767251031 100755 --- a/api/graphics2_win.C +++ b/api/graphics2_win.C @@ -317,8 +317,13 @@ static VOID CALLBACK timer_handler(HWND, UINT, UINT, DWORD) { } } -void win_graphics_event_loop() { +void boinc_graphics_loop(int argc, char** argv) { MSG msg; + for (int i=1; ifoobar + + blah + + where "" is unrecognized. + We'd skip the , but parse the within it. + This wrong. + New: skip the entire unrecognized element + NOTE: I implemented this in the new parser (XML_PARSER) + and added it for everything that uses XML_PARSER. + The old parser still isn't quite right: + it will skip until the next , + but not necessarily the matching instance of that tag. + - client: added error messages for unparsed XML in several places + - client/lib: use "else-less" syntax in XML parsing code + + api/ + boinc_api.C,h + graphics2.h + greaphic2_win.C + client/ + acct_mgr.C + cs_statefile + gui_rpc_server_ops.C + log_flags.C + net_stats.C + lib/ + app_ipc.C + gui_rpc_client_ops.C + parse.C,h + prefs.C + diff --git a/client/acct_mgr.C b/client/acct_mgr.C index 7ec518b7bd..f3cf8f9a1b 100644 --- a/client/acct_mgr.C +++ b/client/acct_mgr.C @@ -228,13 +228,22 @@ int AM_ACCOUNT::parse(XML_PARSER& xp) { if (xp.parse_bool(tag, "update", update)) continue; if (xp.parse_bool(tag, "dont_request_more_work", btemp)) { dont_request_more_work.set(btemp); + continue; } if (xp.parse_bool(tag, "detach_when_done", btemp)) { detach_when_done.set(btemp); + continue; } if (xp.parse_double(tag, "resource_share", dtemp)) { resource_share.set(dtemp); + continue; } + if (log_flags.unparsed_xml) { + msg_printf(NULL, MSG_INFO, + "[unparsed_xml] AM_ACCOUNT: unrecognized %s", tag + ); + } + xp.skip_unexpected(tag); } return ERR_XML_PARSE; } @@ -306,6 +315,12 @@ int ACCT_MGR_OP::parse(FILE* f) { continue; } if (xp.parse_str(tag, "host_venue", host_venue, sizeof(host_venue))) continue; + if (log_flags.unparsed_xml) { + msg_printf(NULL, MSG_INFO, + "[unparsed_xml] ACCT_MGR_OP::parse: unrecognized %s", tag + ); + } + xp.skip_unexpected(tag); } return ERR_XML_PARSE; } @@ -586,6 +601,12 @@ int ACCT_MGR_INFO::parse_login_file(FILE* p) { retval = xp.element_contents("", opaque, sizeof(opaque)); continue; } + if (log_flags.unparsed_xml) { + msg_printf(NULL, MSG_INFO, + "[unparsed_xml] ACCT_MGR_INFO::parse_login: unrecognized %s", tag + ); + } + xp.skip_unexpected(tag); } return 0; } @@ -618,6 +639,12 @@ int ACCT_MGR_INFO::init() { retval = xp.element_contents("", signing_key, sizeof(signing_key)); continue; } + if (log_flags.unparsed_xml) { + msg_printf(NULL, MSG_INFO, + "[unparsed_xml] ACCT_MGR_INFO::init: unrecognized %s", tag + ); + } + xp.skip_unexpected(tag); } fclose(p); diff --git a/client/cs_statefile.C b/client/cs_statefile.C index fe766340e5..d5aecfb1e9 100644 --- a/client/cs_statefile.C +++ b/client/cs_statefile.C @@ -317,7 +317,7 @@ int CLIENT_STATE::parse_state_file() { msg_printf(NULL, MSG_INTERNAL_ERROR, "Project files outside project in state file" ); - skip_unrecognized(buf, f); + skip_unrecognized(buf, mf); continue; } project->parse_project_files(mf, false); @@ -383,7 +383,7 @@ int CLIENT_STATE::parse_state_file() { msg_printf(NULL, MSG_INTERNAL_ERROR, "auto update outside project in state file" ); - skip_unrecognized(buf, f); + skip_unrecognized(buf, mf); continue; } if (!auto_update.parse(mf) && !auto_update.validate_and_link(project)) { @@ -395,6 +395,7 @@ int CLIENT_STATE::parse_state_file() { "[unparsed_xml] state_file: unrecognized: %s", buf ); } + skip_unrecognized(buf, mf); } } fclose(f); diff --git a/client/gui_rpc_server_ops.C b/client/gui_rpc_server_ops.C index 00dd52f6cf..933a7fdb08 100644 --- a/client/gui_rpc_server_ops.C +++ b/client/gui_rpc_server_ops.C @@ -890,6 +890,12 @@ static int set_debt(XML_PARSER& xp) { got_ltd = true; continue; } + if (log_flags.unparsed_xml) { + msg_printf(NULL, MSG_INFO, + "[unparsed_xml] set_debt: unrecognized %s", tag + ); + } + xp.skip_unexpected(tag); } return 0; } @@ -916,6 +922,12 @@ static void handle_set_debts(char* buf, MIOFILE& fout) { return; } } + if (log_flags.unparsed_xml) { + msg_printf(NULL, MSG_INFO, + "[unparsed_xml] handle_set_debts: unrecognized %s", tag + ); + } + xp.skip_unexpected(tag); } } diff --git a/client/log_flags.C b/client/log_flags.C index 9f6de063cb..03b0cbc339 100644 --- a/client/log_flags.C +++ b/client/log_flags.C @@ -95,37 +95,36 @@ int LOG_FLAGS::parse(XML_PARSER& xp) { continue; } if (!strcmp(tag, "/log_flags")) return 0; - else if (xp.parse_bool(tag, "task", task)) continue; - else if (xp.parse_bool(tag, "file_xfer", file_xfer)) continue; - else if (xp.parse_bool(tag, "sched_ops", sched_ops)) continue; - else if (xp.parse_bool(tag, "cpu_sched", cpu_sched)) continue; - else if (xp.parse_bool(tag, "cpu_sched_debug", cpu_sched_debug)) continue; - else if (xp.parse_bool(tag, "rr_simulation", rr_simulation)) continue; - else if (xp.parse_bool(tag, "debt_debug", debt_debug)) continue; - else if (xp.parse_bool(tag, "task_debug", task_debug)) continue; - else if (xp.parse_bool(tag, "work_fetch_debug", work_fetch_debug)) continue; - else if (xp.parse_bool(tag, "unparsed_xml", unparsed_xml)) continue; - else if (xp.parse_bool(tag, "state_debug", state_debug)) continue; - else if (xp.parse_bool(tag, "file_xfer_debug", file_xfer_debug)) continue; - else if (xp.parse_bool(tag, "sched_op_debug", sched_op_debug)) continue; - else if (xp.parse_bool(tag, "http_debug", http_debug)) continue; - else if (xp.parse_bool(tag, "proxy_debug", proxy_debug)) continue; - else if (xp.parse_bool(tag, "time_debug", time_debug)) continue; - else if (xp.parse_bool(tag, "http_xfer_debug", http_xfer_debug)) continue; - else if (xp.parse_bool(tag, "benchmark_debug", benchmark_debug)) continue; - else if (xp.parse_bool(tag, "poll_debug", poll_debug)) continue; - else if (xp.parse_bool(tag, "guirpc_debug", guirpc_debug)) continue; - else if (xp.parse_bool(tag, "scrsave_debug", scrsave_debug)) continue; - else if (xp.parse_bool(tag, "app_msg_send", app_msg_send)) continue; - else if (xp.parse_bool(tag, "app_msg_receive", app_msg_receive)) continue; - else if (xp.parse_bool(tag, "mem_usage_debug", mem_usage_debug)) continue; - else if (xp.parse_bool(tag, "network_status_debug", network_status_debug)) continue; - else if (xp.parse_bool(tag, "checkpoint_debug", checkpoint_debug)) continue; - else { - msg_printf(NULL, MSG_USER_ERROR, "Unrecognized tag in %s: <%s>\n", - CONFIG_FILE, tag - ); - } + if (xp.parse_bool(tag, "task", task)) continue; + if (xp.parse_bool(tag, "file_xfer", file_xfer)) continue; + if (xp.parse_bool(tag, "sched_ops", sched_ops)) continue; + if (xp.parse_bool(tag, "cpu_sched", cpu_sched)) continue; + if (xp.parse_bool(tag, "cpu_sched_debug", cpu_sched_debug)) continue; + if (xp.parse_bool(tag, "rr_simulation", rr_simulation)) continue; + if (xp.parse_bool(tag, "debt_debug", debt_debug)) continue; + if (xp.parse_bool(tag, "task_debug", task_debug)) continue; + if (xp.parse_bool(tag, "work_fetch_debug", work_fetch_debug)) continue; + if (xp.parse_bool(tag, "unparsed_xml", unparsed_xml)) continue; + if (xp.parse_bool(tag, "state_debug", state_debug)) continue; + if (xp.parse_bool(tag, "file_xfer_debug", file_xfer_debug)) continue; + if (xp.parse_bool(tag, "sched_op_debug", sched_op_debug)) continue; + if (xp.parse_bool(tag, "http_debug", http_debug)) continue; + if (xp.parse_bool(tag, "proxy_debug", proxy_debug)) continue; + if (xp.parse_bool(tag, "time_debug", time_debug)) continue; + if (xp.parse_bool(tag, "http_xfer_debug", http_xfer_debug)) continue; + if (xp.parse_bool(tag, "benchmark_debug", benchmark_debug)) continue; + if (xp.parse_bool(tag, "poll_debug", poll_debug)) continue; + if (xp.parse_bool(tag, "guirpc_debug", guirpc_debug)) continue; + if (xp.parse_bool(tag, "scrsave_debug", scrsave_debug)) continue; + if (xp.parse_bool(tag, "app_msg_send", app_msg_send)) continue; + if (xp.parse_bool(tag, "app_msg_receive", app_msg_receive)) continue; + if (xp.parse_bool(tag, "mem_usage_debug", mem_usage_debug)) continue; + if (xp.parse_bool(tag, "network_status_debug", network_status_debug)) continue; + if (xp.parse_bool(tag, "checkpoint_debug", checkpoint_debug)) continue; + msg_printf(NULL, MSG_USER_ERROR, "Unrecognized tag in %s: <%s>\n", + CONFIG_FILE, tag + ); + xp.skip_unexpected(tag); } return ERR_XML_PARSE; } @@ -207,21 +206,20 @@ int CONFIG::parse_options(XML_PARSER& xp) { if (!strcmp(tag, "/options")) { return 0; } - else if (xp.parse_int(tag, "save_stats_days", save_stats_days)) continue; - else if (xp.parse_bool(tag, "dont_check_file_sizes", dont_check_file_sizes)) continue; - else if (xp.parse_bool(tag, "http_1_0", http_1_0)) continue; - else if (xp.parse_int(tag, "ncpus", ncpus)) continue; - else if (xp.parse_int(tag, "max_file_xfers", max_file_xfers)) continue; - else if (xp.parse_int(tag, "max_file_xfers_per_project", max_file_xfers_per_project)) continue; - else if (xp.parse_bool(tag, "suppress_net_info", suppress_net_info)) continue; - else if (xp.parse_bool(tag, "disallow_attach", disallow_attach)) continue; - else if (xp.parse_bool(tag, "os_random_only", os_random_only)) continue; - else if (xp.parse_bool(tag, "no_alt_platform", no_alt_platform)) continue; - else { - msg_printf(NULL, MSG_USER_ERROR, "Unparsed tag in %s: <%s>\n", - CONFIG_FILE, tag - ); - } + if (xp.parse_int(tag, "save_stats_days", save_stats_days)) continue; + if (xp.parse_bool(tag, "dont_check_file_sizes", dont_check_file_sizes)) continue; + if (xp.parse_bool(tag, "http_1_0", http_1_0)) continue; + if (xp.parse_int(tag, "ncpus", ncpus)) continue; + if (xp.parse_int(tag, "max_file_xfers", max_file_xfers)) continue; + if (xp.parse_int(tag, "max_file_xfers_per_project", max_file_xfers_per_project)) continue; + if (xp.parse_bool(tag, "suppress_net_info", suppress_net_info)) continue; + if (xp.parse_bool(tag, "disallow_attach", disallow_attach)) continue; + if (xp.parse_bool(tag, "os_random_only", os_random_only)) continue; + if (xp.parse_bool(tag, "no_alt_platform", no_alt_platform)) continue; + msg_printf(NULL, MSG_USER_ERROR, "Unparsed tag in %s: <%s>\n", + CONFIG_FILE, tag + ); + xp.skip_unexpected(tag); } return ERR_XML_PARSE; } @@ -254,6 +252,7 @@ int CONFIG::parse(FILE* f) { msg_printf(NULL, MSG_USER_ERROR, "Unparsed tag in %s: <%s>\n", CONFIG_FILE, tag ); + xp.skip_unexpected(tag); } } msg_printf(NULL, MSG_USER_ERROR, "Missing end tag in %s", CONFIG_FILE); diff --git a/client/net_stats.C b/client/net_stats.C index 209eb6288b..0bd6c96f3a 100644 --- a/client/net_stats.C +++ b/client/net_stats.C @@ -172,16 +172,13 @@ int NET_STATUS::network_status() { if (gstate.lookup_website_op.error_num == ERR_IN_PROGRESS) { retval = NETWORK_STATUS_LOOKUP_PENDING; } else if (gstate.now - last_comm_time < 10) { - //msg_printf(0, MSG_INFO, "nops %d; return 0", http_ops->nops()); retval = NETWORK_STATUS_ONLINE; } else if (need_physical_connection) { - //msg_printf(0, MSG_INFO, "need phys conn; return 1"); retval = NETWORK_STATUS_WANT_CONNECTION; } else if (gstate.active_tasks.want_network()) { retval = NETWORK_STATUS_WANT_CONNECTION; } else { have_sporadic_connection = false; - //msg_printf(0, MSG_INFO, "returning 2"); retval = NETWORK_STATUS_WANT_DISCONNECT; } if (log_flags.network_status_debug) { diff --git a/lib/app_ipc.C b/lib/app_ipc.C index 51644c65bd..9c6cc6e279 100755 --- a/lib/app_ipc.C +++ b/lib/app_ipc.C @@ -202,47 +202,49 @@ int parse_init_data_file(FILE* f, APP_INIT_DATA& ai) { if (retval) return retval; continue; } - else if (!strcmp(tag, "host_info")) { + if (!strcmp(tag, "host_info")) { ai.host_info.parse(mf); continue; } - else if (!strcmp(tag, "proxy_info")) { + if (!strcmp(tag, "proxy_info")) { ai.proxy_info.parse(mf); + continue; } - else if (xp.parse_int(tag, "major_version", ai.major_version)) continue; - else if (xp.parse_int(tag, "minor_version", ai.minor_version)) continue; - else if (xp.parse_int(tag, "release", ai.release)) continue; - else if (xp.parse_int(tag, "app_version", ai.app_version)) continue; - else if (xp.parse_str(tag, "app_name", ai.app_name, sizeof(ai.app_name))) continue; - else if (xp.parse_str(tag, "symstore", ai.symstore, sizeof(ai.symstore))) continue; - else if (xp.parse_str(tag, "acct_mgr_url", ai.acct_mgr_url, sizeof(ai.acct_mgr_url))) continue; - else if (xp.parse_str(tag, "user_name", ai.user_name, sizeof(ai.user_name))) continue; - else if (xp.parse_str(tag, "team_name", ai.team_name, sizeof(ai.team_name))) continue; - else if (xp.parse_str(tag, "project_dir", ai.project_dir, sizeof(ai.project_dir))) continue; - else if (xp.parse_str(tag, "boinc_dir", ai.boinc_dir, sizeof(ai.boinc_dir))) continue; - else if (xp.parse_str(tag, "authenticator", ai.authenticator, sizeof(ai.authenticator))) continue; - else if (xp.parse_str(tag, "wu_name", ai.wu_name, sizeof(ai.wu_name))) continue; + if (xp.parse_int(tag, "major_version", ai.major_version)) continue; + if (xp.parse_int(tag, "minor_version", ai.minor_version)) continue; + if (xp.parse_int(tag, "release", ai.release)) continue; + if (xp.parse_int(tag, "app_version", ai.app_version)) continue; + if (xp.parse_str(tag, "app_name", ai.app_name, sizeof(ai.app_name))) continue; + if (xp.parse_str(tag, "symstore", ai.symstore, sizeof(ai.symstore))) continue; + if (xp.parse_str(tag, "acct_mgr_url", ai.acct_mgr_url, sizeof(ai.acct_mgr_url))) continue; + if (xp.parse_str(tag, "user_name", ai.user_name, sizeof(ai.user_name))) continue; + if (xp.parse_str(tag, "team_name", ai.team_name, sizeof(ai.team_name))) continue; + if (xp.parse_str(tag, "project_dir", ai.project_dir, sizeof(ai.project_dir))) continue; + if (xp.parse_str(tag, "boinc_dir", ai.boinc_dir, sizeof(ai.boinc_dir))) continue; + if (xp.parse_str(tag, "authenticator", ai.authenticator, sizeof(ai.authenticator))) continue; + if (xp.parse_str(tag, "wu_name", ai.wu_name, sizeof(ai.wu_name))) continue; #ifdef _WIN32 - else if (xp.parse_str(tag, "comm_obj_name", ai.shmem_seg_name, sizeof(ai.shmem_seg_name))) continue; + if (xp.parse_str(tag, "comm_obj_name", ai.shmem_seg_name, sizeof(ai.shmem_seg_name))) continue; #else - else if (xp.parse_int(tag, "shm_key", ai.shmem_seg_name)) continue; + if (xp.parse_int(tag, "shm_key", ai.shmem_seg_name)) continue; #endif - else if (xp.parse_int(tag, "slot", ai.slot)) continue; - else if (xp.parse_double(tag, "user_total_credit", ai.user_total_credit)) continue; - else if (xp.parse_double(tag, "user_expavg_credit", ai.user_expavg_credit)) continue; - else if (xp.parse_double(tag, "host_total_credit", ai.host_total_credit)) continue; - else if (xp.parse_double(tag, "host_expavg_credit", ai.host_expavg_credit)) continue; - else if (xp.parse_double(tag, "resource_share_fraction", ai.resource_share_fraction)) continue; - else if (xp.parse_double(tag, "rsc_fpops_est", ai.rsc_fpops_est)) continue; - else if (xp.parse_double(tag, "rsc_fpops_bound", ai.rsc_fpops_bound)) continue; - else if (xp.parse_double(tag, "rsc_memory_bound", ai.rsc_memory_bound)) continue; - else if (xp.parse_double(tag, "rsc_disk_bound", ai.rsc_disk_bound)) continue; - else if (xp.parse_double(tag, "wu_cpu_time", ai.wu_cpu_time)) continue; - else if (xp.parse_double(tag, "checkpoint_period", ai.checkpoint_period)) continue; - else if (xp.parse_double(tag, "fraction_done_update_period", ai.fraction_done_update_period)) continue; - else if (xp.parse_double(tag, "fraction_done_start", ai.fraction_done_start)) continue; - else if (xp.parse_double(tag, "fraction_done_end", ai.fraction_done_end)) continue; - //else fprintf(stderr, "parse_init_data_file: unrecognized %s", tag); + if (xp.parse_int(tag, "slot", ai.slot)) continue; + if (xp.parse_double(tag, "user_total_credit", ai.user_total_credit)) continue; + if (xp.parse_double(tag, "user_expavg_credit", ai.user_expavg_credit)) continue; + if (xp.parse_double(tag, "host_total_credit", ai.host_total_credit)) continue; + if (xp.parse_double(tag, "host_expavg_credit", ai.host_expavg_credit)) continue; + if (xp.parse_double(tag, "resource_share_fraction", ai.resource_share_fraction)) continue; + if (xp.parse_double(tag, "rsc_fpops_est", ai.rsc_fpops_est)) continue; + if (xp.parse_double(tag, "rsc_fpops_bound", ai.rsc_fpops_bound)) continue; + if (xp.parse_double(tag, "rsc_memory_bound", ai.rsc_memory_bound)) continue; + if (xp.parse_double(tag, "rsc_disk_bound", ai.rsc_disk_bound)) continue; + if (xp.parse_double(tag, "wu_cpu_time", ai.wu_cpu_time)) continue; + if (xp.parse_double(tag, "checkpoint_period", ai.checkpoint_period)) continue; + if (xp.parse_double(tag, "fraction_done_update_period", ai.fraction_done_update_period)) continue; + if (xp.parse_double(tag, "fraction_done_start", ai.fraction_done_start)) continue; + if (xp.parse_double(tag, "fraction_done_end", ai.fraction_done_end)) continue; + // fprintf(stderr, "parse_init_data_file: unrecognized %s", tag); + xp.skip_unexpected(tag); } return 0; } diff --git a/lib/gui_rpc_client_ops.C b/lib/gui_rpc_client_ops.C index c300af6e89..dd4e71ed8b 100644 --- a/lib/gui_rpc_client_ops.C +++ b/lib/gui_rpc_client_ops.C @@ -107,27 +107,14 @@ int PROJECT_LIST_ENTRY::parse(XML_PARSER& xp) { while (!xp.get(tag, sizeof(tag), is_tag)) { if (!strcmp(tag, "/project")) return 0; - else if (xp.parse_string(tag, "name", name)) { - continue; - } - else if (xp.parse_string(tag, "url", url)) { - continue; - } - else if (xp.parse_string(tag, "general_area", general_area)) { - continue; - } - else if (xp.parse_string(tag, "specific_area", specific_area)) { - continue; - } - else if (xp.parse_string(tag, "description", description)) { - continue; - } - else if (xp.parse_string(tag, "home", home)) { - continue; - } - else if (xp.parse_string(tag, "image", image)) { - continue; - } + 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; } @@ -1136,24 +1123,23 @@ int RPC_CLIENT::get_state(CC_STATE& state) { // the following are to handle responses from pre-5.6 core clients // remove them 6/07 - else if (parse_int(buf, "", state.version_info.major)) continue; - else if (parse_int(buf, "", state.version_info.minor)) continue; - else if (parse_int(buf, "", state.version_info.release)) continue; - - else if (match_tag(buf, "")) { + if (parse_int(buf, "", state.version_info.major)) continue; + if (parse_int(buf, "", state.version_info.minor)) continue; + if (parse_int(buf, "", state.version_info.release)) continue; + if (match_tag(buf, "")) { project = new PROJECT(); project->parse(rpc.fin); state.projects.push_back(project); continue; } - else if (match_tag(buf, "")) { + if (match_tag(buf, "")) { APP* app = new APP(); app->parse(rpc.fin); app->project = project; state.apps.push_back(app); continue; } - else if (match_tag(buf, "")) { + if (match_tag(buf, "")) { APP_VERSION* app_version = new APP_VERSION(); app_version->parse(rpc.fin); app_version->project = project; @@ -1161,7 +1147,7 @@ int RPC_CLIENT::get_state(CC_STATE& state) { state.app_versions.push_back(app_version); continue; } - else if (match_tag(buf, "")) { + if (match_tag(buf, "")) { WORKUNIT* wu = new WORKUNIT(); wu->parse(rpc.fin); wu->project = project; @@ -1170,7 +1156,7 @@ int RPC_CLIENT::get_state(CC_STATE& state) { state.wus.push_back(wu); continue; } - else if (match_tag(buf, "")) { + if (match_tag(buf, "")) { RESULT* result = new RESULT(); result->parse(rpc.fin); result->project = project; @@ -1179,13 +1165,14 @@ int RPC_CLIENT::get_state(CC_STATE& state) { state.results.push_back(result); continue; } - else if (match_tag(buf, "")) { + if (match_tag(buf, "")) { bool flag = false; GLOBAL_PREFS_MASK mask; XML_PARSER xp(&rpc.fin); state.global_prefs.parse(xp, "", flag, mask); continue; } + skip_unrecognized(buf, rpc.fin); } } return retval; diff --git a/lib/parse.C b/lib/parse.C index b0b5ff35ab..d0abd7de66 100644 --- a/lib/parse.C +++ b/lib/parse.C @@ -391,7 +391,7 @@ void xml_unescape(const char* in, char* out) { // If it's of the form then scan for and return 0. // Otherwise return ERR_XML_PARSE // -int skip_unrecognized(char* buf, FILE* in) { +int skip_unrecognized(char* buf, MIOFILE& fin) { char* p, *q, buf2[256]; std::string close_tag; @@ -408,7 +408,7 @@ int skip_unrecognized(char* buf, FILE* in) { } *q = 0; close_tag = string(""); - while (fgets(buf2, 256, in)) { + while (fin.fgets(buf2, 256)) { if (strstr(buf2, close_tag.c_str())) { return 0; } @@ -697,6 +697,23 @@ int XML_PARSER::element_contents(const char* end_tag, char* buf, int buflen) { return retval; } +// We got an unexpected tag. +// If it's an end tag, do nothing. +// Otherwise skip until the end tag, if any +// +void XML_PARSER::skip_unexpected(const char* start_tag) { + char tag[256], end_tag[256]; + bool eof, is_tag; + + if (start_tag[0] == '/') return; + sprintf(end_tag, "/%s", start_tag); + while (!get(tag, sizeof(tag), is_tag)) { + if (!is_tag) continue; + if (!strcmp(tag, end_tag)) return; + skip_unexpected(tag); + } +} + // sample use is shown below #if 0 @@ -732,7 +749,7 @@ void parse(FILE* f) { printf("got bool: %d\n", flag); } else { printf("unparsed tag: %s\n", tag); - return; + xp.skip_unexpected(tag); } } printf("unexpected EOF\n"); @@ -742,5 +759,21 @@ int main() { FILE* f = fopen("foo.xml", "r"); parse(f); } + +... and run it against, e.g.: + + + + + asdlfkj + fj + + blah + 6 + + 6.555 + 0 + + #endif const char *BOINC_RCSID_3f3de9eb18 = "$Id$"; diff --git a/lib/parse.h b/lib/parse.h index 9f3f89cd71..4dc0269438 100644 --- a/lib/parse.h +++ b/lib/parse.h @@ -50,6 +50,7 @@ public: bool parse_double(char*, const char*, double&); bool parse_bool(char*, const char*, bool&); int element_contents(const char*, char*, int); + void skip_unexpected(const char*); }; /////////////// START DEPRECATED XML PARSER @@ -117,6 +118,6 @@ extern char* sgets(char* buf, int len, char* &in); extern void xml_escape(const char*, char*); extern void xml_unescape(const char*, char*); extern void extract_venue(const char*, const char*, char*); -extern int skip_unrecognized(char* buf, FILE*); +extern int skip_unrecognized(char* buf, MIOFILE&); #endif diff --git a/lib/prefs.C b/lib/prefs.C index 25fdf6a5a8..55133ce8fe 100644 --- a/lib/prefs.C +++ b/lib/prefs.C @@ -214,16 +214,13 @@ int DAY_PREFS::parse(XML_PARSER& xp) { if (!strcmp(tag, "/day_prefs")) { if (day_of_week < 0 || day_of_week > 6) return ERR_XML_PARSE; return 0; - } else if (xp.parse_int(tag, "day_of_week", day_of_week)) { - } else if (xp.parse_double(tag, "start_hour", time_prefs.start_hour)) { - continue; - } else if (xp.parse_double(tag, "end_hour", time_prefs.end_hour)) { - continue; - } else if (xp.parse_double(tag, "net_start_hour", time_prefs.net_start_hour)) { - continue; - } else if (xp.parse_double(tag, "net_end_hour", time_prefs.net_end_hour)) { - continue; } + if (xp.parse_int(tag, "day_of_week", day_of_week)) continue; + if (xp.parse_double(tag, "start_hour", time_prefs.start_hour)) continue; + if (xp.parse_double(tag, "end_hour", time_prefs.end_hour)) continue; + if (xp.parse_double(tag, "net_start_hour", time_prefs.net_start_hour)) continue; + if (xp.parse_double(tag, "net_end_hour", time_prefs.net_end_hour)) continue; + xp.skip_unexpected(tag); } return ERR_XML_PARSE; } @@ -277,33 +274,37 @@ int GLOBAL_PREFS::parse_override( continue; } } - if (xp.parse_str(tag, "source_project", source_project, sizeof(source_project))) { + if (xp.parse_str(tag, "source_project", source_project, sizeof(source_project))) continue; + if (xp.parse_str(tag, "source_scheduler", source_scheduler, sizeof(source_scheduler))) { continue; - } else if (xp.parse_str(tag, "source_scheduler", source_scheduler, sizeof(source_scheduler))) { - continue; - } else if (xp.parse_int(tag, "mod_time", mod_time)) { - continue; - } else if (!strcmp(tag, "/global_preferences")) { - return 0; - } else if (xp.parse_bool(tag, "run_on_batteries", run_on_batteries)) { + } + if (xp.parse_int(tag, "mod_time", mod_time)) continue; + if (!strcmp(tag, "/global_preferences")) return 0; + if (xp.parse_bool(tag, "run_on_batteries", run_on_batteries)) { mask.run_on_batteries = true; continue; - } else if (xp.parse_bool(tag, "run_if_user_active", run_if_user_active)) { + } + if (xp.parse_bool(tag, "run_if_user_active", run_if_user_active)) { mask.run_if_user_active = true; continue; - } else if (xp.parse_double(tag, "start_hour", time_prefs.start_hour)) { + } + if (xp.parse_double(tag, "start_hour", time_prefs.start_hour)) { mask.start_hour = true; continue; - } else if (xp.parse_double(tag, "end_hour", time_prefs.end_hour)) { + } + if (xp.parse_double(tag, "end_hour", time_prefs.end_hour)) { mask.end_hour = true; continue; - } else if (xp.parse_double(tag, "net_start_hour", time_prefs.net_start_hour)) { + } + if (xp.parse_double(tag, "net_start_hour", time_prefs.net_start_hour)) { mask.net_start_hour = true; continue; - } else if (xp.parse_double(tag, "net_end_hour", time_prefs.net_end_hour)) { + } + if (xp.parse_double(tag, "net_end_hour", time_prefs.net_end_hour)) { mask.net_end_hour = true; continue; - } else if (!strcmp(tag, "day_prefs")) { + } + if (!strcmp(tag, "day_prefs")) { DAY_PREFS dp; retval = dp.parse(xp); if (!retval) { @@ -311,82 +312,102 @@ int GLOBAL_PREFS::parse_override( week_prefs.present = true; week_prefs.days[dp.day_of_week] = dp; } - } else if (xp.parse_bool(tag, "leave_apps_in_memory", leave_apps_in_memory)) { + } + if (xp.parse_bool(tag, "leave_apps_in_memory", leave_apps_in_memory)) { mask.leave_apps_in_memory = true; continue; - } else if (xp.parse_bool(tag, "confirm_before_connecting", confirm_before_connecting)) { + } + if (xp.parse_bool(tag, "confirm_before_connecting", confirm_before_connecting)) { mask.confirm_before_connecting = true; continue; - } else if (xp.parse_bool(tag, "hangup_if_dialed", hangup_if_dialed)) { + } + if (xp.parse_bool(tag, "hangup_if_dialed", hangup_if_dialed)) { mask.hangup_if_dialed = true; continue; - } else if (xp.parse_bool(tag, "dont_verify_images", dont_verify_images)) { + } + if (xp.parse_bool(tag, "dont_verify_images", dont_verify_images)) { mask.dont_verify_images = true; continue; - } else if (xp.parse_double(tag, "work_buf_min_days", work_buf_min_days)) { + } + if (xp.parse_double(tag, "work_buf_min_days", work_buf_min_days)) { if (work_buf_min_days < 0.00001) work_buf_min_days = 0.00001; mask.work_buf_min_days = true; continue; - } else if (xp.parse_double(tag, "work_buf_additional_days", work_buf_additional_days)) { + } + if (xp.parse_double(tag, "work_buf_additional_days", work_buf_additional_days)) { if (work_buf_additional_days < 0) work_buf_additional_days = 0; mask.work_buf_additional_days = true; continue; - } else if (xp.parse_int(tag, "max_cpus", max_cpus)) { + } + if (xp.parse_int(tag, "max_cpus", max_cpus)) { if (max_cpus < 1) max_cpus = 1; mask.max_cpus = true; continue; - } else if (xp.parse_double(tag, "disk_interval", disk_interval)) { + } + if (xp.parse_double(tag, "disk_interval", disk_interval)) { if (disk_interval<0) disk_interval = 0; mask.disk_interval = true; continue; - } else if (xp.parse_double(tag, "cpu_scheduling_period_minutes", cpu_scheduling_period_minutes)) { + } + if (xp.parse_double(tag, "cpu_scheduling_period_minutes", cpu_scheduling_period_minutes)) { if (cpu_scheduling_period_minutes < 0.0001) cpu_scheduling_period_minutes = 60; mask.cpu_scheduling_period_minutes = true; continue; - } else if (xp.parse_double(tag, "disk_max_used_gb", disk_max_used_gb)) { + } + if (xp.parse_double(tag, "disk_max_used_gb", disk_max_used_gb)) { mask.disk_max_used_gb = true; continue; - } else if (xp.parse_double(tag, "disk_max_used_pct", disk_max_used_pct)) { + } + if (xp.parse_double(tag, "disk_max_used_pct", disk_max_used_pct)) { mask.disk_max_used_pct = true; continue; - } else if (xp.parse_double(tag, "disk_min_free_gb", disk_min_free_gb)) { + } + if (xp.parse_double(tag, "disk_min_free_gb", disk_min_free_gb)) { mask.disk_min_free_gb = true; continue; - } else if (xp.parse_double(tag, "vm_max_used_pct", dtemp)) { + } + if (xp.parse_double(tag, "vm_max_used_pct", dtemp)) { vm_max_used_frac = dtemp/100; mask.vm_max_used_frac = true; continue; - } else if (xp.parse_double(tag, "ram_max_used_busy_pct", dtemp)) { + } + if (xp.parse_double(tag, "ram_max_used_busy_pct", dtemp)) { if (!dtemp) dtemp = 100; ram_max_used_busy_frac = dtemp/100; mask.ram_max_used_busy_frac = true; continue; - } else if (xp.parse_double(tag, "ram_max_used_idle_pct", dtemp)) { + } + if (xp.parse_double(tag, "ram_max_used_idle_pct", dtemp)) { if (!dtemp) dtemp = 100; ram_max_used_idle_frac = dtemp/100; mask.ram_max_used_idle_frac = true; continue; - } else if (xp.parse_double(tag, "idle_time_to_run", idle_time_to_run)) { + } + if (xp.parse_double(tag, "idle_time_to_run", idle_time_to_run)) { mask.idle_time_to_run = true; continue; - } else if (xp.parse_double(tag, "max_bytes_sec_up", max_bytes_sec_up)) { + } + if (xp.parse_double(tag, "max_bytes_sec_up", max_bytes_sec_up)) { if (max_bytes_sec_up < 0) max_bytes_sec_up = 0; mask.max_bytes_sec_up = true; continue; - } else if (xp.parse_double(tag, "max_bytes_sec_down", max_bytes_sec_down)) { + } + if (xp.parse_double(tag, "max_bytes_sec_down", max_bytes_sec_down)) { if (max_bytes_sec_down < 0) max_bytes_sec_down = 0; mask.max_bytes_sec_down = true; continue; - } else if (xp.parse_double(tag, "cpu_usage_limit", dtemp)) { + } + if (xp.parse_double(tag, "cpu_usage_limit", dtemp)) { if (dtemp > 0 && dtemp <= 100) { cpu_usage_limit = dtemp; mask.cpu_usage_limit = true; } continue; - } else if (xp.parse_bool(tag, "host_specific", host_specific)) { - + } + if (xp.parse_bool(tag, "host_specific", host_specific)) { continue; } + xp.skip_unexpected(tag); } return ERR_XML_PARSE; }