diff --git a/checkin_notes b/checkin_notes index c5cdde6e24..6a5bdbf94d 100644 --- a/checkin_notes +++ b/checkin_notes @@ -7187,3 +7187,15 @@ David 7 Oct 2010 network.cpp client/ boinc_cmd.cpp + +David 7 Oct 2010 + - client simulator: updates. Fix web interface. + + client/ + client_state.h + cpu_sched.cpp + cs_prefs.cpp + cs_statefile.cpp + log_flags.cpp,h + sim.cpp + work_fetch.cpp diff --git a/client/client_state.h b/client/client_state.h index 77ea912e59..b13a83d0e1 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -34,6 +34,7 @@ using std::vector; #include "app.h" #include "client_types.h" #include "file_xfer.h" +#include "file_names.h" #include "gui_rpc_server.h" #include "gui_http.h" #include "hostinfo.h" @@ -366,7 +367,10 @@ struct CLIENT_STATE { int allowed_project_disk_usage(double&); int suspend_tasks(int reason); int resume_tasks(int reason=0); - void read_global_prefs(); + void read_global_prefs( + const char* fname = GLOBAL_PREFS_FILE_NAME, + const char* override_fname = GLOBAL_PREFS_OVERRIDE_FILE + ); int save_global_prefs(char* prefs, char* url, char* sched); double available_ram(); double max_available_ram(); @@ -398,6 +402,7 @@ struct CLIENT_STATE { // --------------- cs_statefile.cpp: void set_client_state_dirty(const char*); int parse_state_file(); + int parse_state_file_aux(const char*); int write_state(MIOFILE&); int write_state_file(); int write_state_file_if_needed(); @@ -460,9 +465,9 @@ struct CLIENT_STATE { double connection_interval; // don't connect more often than this - void html_start(bool); + void html_start(); void html_rec(); - void html_end(bool); + void html_end(); std::string html_msg; double share_violation(); double monotony(); diff --git a/client/cpu_sched.cpp b/client/cpu_sched.cpp index 02141bccf3..9c24763f80 100644 --- a/client/cpu_sched.cpp +++ b/client/cpu_sched.cpp @@ -1872,16 +1872,6 @@ void CLIENT_STATE::set_ncpus() { // void PROJECT::update_duration_correction_factor(ACTIVE_TASK* atp) { RESULT* rp = atp->result; -#ifdef SIM - if (dcf_dont_use) { - duration_correction_factor = 1.0; - return; - } - if (dcf_stats) { - update_dcf_stats(rp); - return; - } -#endif double raw_ratio = atp->elapsed_time/rp->estimated_duration_uncorrected(); double adj_ratio = atp->elapsed_time/rp->estimated_duration(false); double old_dcf = duration_correction_factor; diff --git a/client/cs_prefs.cpp b/client/cs_prefs.cpp index 38a6db5567..adfc54e01c 100644 --- a/client/cs_prefs.cpp +++ b/client/cs_prefs.cpp @@ -371,23 +371,27 @@ int PROJECT::parse_preferences_for_user_files() { // - on completion of a scheduler or AMS RPC, if they sent prefs // - in response to read_global_prefs_override GUI RPC // -void CLIENT_STATE::read_global_prefs() { +void CLIENT_STATE::read_global_prefs( + const char* fname, const char* override_fname +) { bool found_venue; bool venue_specified_in_override = false; int retval; FILE* f; string foo; - retval = read_file_string(GLOBAL_PREFS_OVERRIDE_FILE, foo); - if (!retval) { - parse_str(foo.c_str(), "", main_host_venue, sizeof(main_host_venue)); - if (strlen(main_host_venue)) { - venue_specified_in_override = true; + if (override_fname) { + retval = read_file_string(override_fname, foo); + if (!retval) { + parse_str(foo.c_str(), "", main_host_venue, sizeof(main_host_venue)); + if (strlen(main_host_venue)) { + venue_specified_in_override = true; + } } } retval = global_prefs.parse_file( - GLOBAL_PREFS_FILE_NAME, main_host_venue, found_venue + fname, main_host_venue, found_venue ); if (retval) { if (retval == ERR_FOPEN) { @@ -398,7 +402,7 @@ void CLIENT_STATE::read_global_prefs() { msg_printf(NULL, MSG_INFO, "Couldn't parse preferences file - using BOINC defaults" ); - boinc_delete_file(GLOBAL_PREFS_FILE_NAME); + boinc_delete_file(fname); } global_prefs.init(); } else { @@ -410,7 +414,7 @@ void CLIENT_STATE::read_global_prefs() { PROJECT* p = global_prefs_source_project(); if (p && strcmp(main_host_venue, p->host_venue)) { strcpy(main_host_venue, p->host_venue); - global_prefs.parse_file(GLOBAL_PREFS_FILE_NAME, main_host_venue, found_venue); + global_prefs.parse_file(fname, main_host_venue, found_venue); } } show_global_prefs_source(found_venue); @@ -418,15 +422,17 @@ void CLIENT_STATE::read_global_prefs() { // read the override file // - f = fopen(GLOBAL_PREFS_OVERRIDE_FILE, "r"); - if (f) { - MIOFILE mf; - GLOBAL_PREFS_MASK mask; - mf.init_file(f); - XML_PARSER xp(&mf); - global_prefs.parse_override(xp, "", found_venue, mask); - msg_printf(NULL, MSG_INFO, "Reading preferences override file"); - fclose(f); + if (override_fname) { + f = fopen(override_fname, "r"); + if (f) { + MIOFILE mf; + GLOBAL_PREFS_MASK mask; + mf.init_file(f); + XML_PARSER xp(&mf); + global_prefs.parse_override(xp, "", found_venue, mask); + msg_printf(NULL, MSG_INFO, "Reading preferences override file"); + fclose(f); + } } msg_printf(NULL, MSG_INFO, "Preferences:"); diff --git a/client/cs_statefile.cpp b/client/cs_statefile.cpp index 36fc033d06..d2666872db 100644 --- a/client/cs_statefile.cpp +++ b/client/cs_statefile.cpp @@ -82,10 +82,6 @@ static inline bool arrived_first(RESULT* r0, RESULT* r1) { // Parse the client_state.xml file // int CLIENT_STATE::parse_state_file() { - PROJECT *project=NULL; - char buf[256]; - int retval=0; - int failnum; const char *fname; // Look for a valid state file: @@ -111,6 +107,14 @@ int CLIENT_STATE::parse_state_file() { old_release = BOINC_RELEASE; return ERR_FOPEN; } + return parse_state_file_aux(fname); +} + +int CLIENT_STATE::parse_state_file_aux(const char* fname) { + PROJECT *project=NULL; + char buf[256]; + int retval=0; + int failnum; FILE* f = fopen(fname, "r"); MIOFILE mf; diff --git a/client/log_flags.cpp b/client/log_flags.cpp index 8d51d8a389..400a58dea1 100644 --- a/client/log_flags.cpp +++ b/client/log_flags.cpp @@ -479,14 +479,12 @@ int CONFIG::parse(FILE* f) { return ERR_XML_PARSE; } -int read_config_file(bool init) { - FILE* f; - +int read_config_file(bool init, const char* fname) { if (!init) { - msg_printf(NULL, MSG_INFO, "Re-reading cc_config.xml"); + msg_printf(NULL, MSG_INFO, "Re-reading %s", fname); config.clear(); } - f = boinc_fopen(CONFIG_FILE, "r"); + FILE* f = boinc_fopen(fname, "r"); if (!f) return ERR_FOPEN; config.parse(f); fclose(f); diff --git a/client/log_flags.h b/client/log_flags.h index b447932cad..83770a0646 100644 --- a/client/log_flags.h +++ b/client/log_flags.h @@ -31,6 +31,8 @@ #include #endif +#include "file_names.h" + #define MAX_FILE_XFERS_PER_PROJECT 2 #define MAX_FILE_XFERS 8 // kind of arbitrary @@ -163,6 +165,6 @@ struct CONFIG { extern LOG_FLAGS log_flags; extern CONFIG config; -extern int read_config_file(bool init); +extern int read_config_file(bool init, const char* fname=CONFIG_FILE); #endif diff --git a/client/sim.cpp b/client/sim.cpp index 0e623574c4..e11a3b321d 100644 --- a/client/sim.cpp +++ b/client/sim.cpp @@ -17,23 +17,35 @@ // BOINC client simulator. // -// usage: -// sim [--duration x] [--delta x] [--dirs dir ...] -// duration = simulation duration (default 86400) -// delta = simulation time step (default 10) +// usage: sim options // -// If no dirs are specified: -// reads input files -// sim_projects.xml, sim_host.xml, sim_prefs.xml, cc_config.xml -// and does simulation, generating output files -// sim_log.txt, sim_out.html +// Input files: +// [--state_file filename] +// name of main input file; default client_state.xml +// [--prefs_file filename] +// name of prefs file; default global_prefs.xml +// [--config_file filename] +// name of config file; default cc_config.xml // -// If dirs are specified, chdir into each directory in sequence, -// do the above for each one, and write summary info to stdout - -#ifdef _MSC_VER -#define chdir _chdir -#endif +// Output files: +// [--timeline_file filename] +// name of timeline file (default sim_timeline.html) +// [--log_file filename] +// name of log file (default sim_log.txt) +// [--summary_file filename] +// name of summary file (default sim_summary.xml) +// +// Simulation params: +// [--duration x] +// simulation duration (default 86400) +// [--delta x] +// delta = simulation time step (default 10) +// +// Policy options: +// [--server_uses_workload] +// simulate use of EDF sim by scheduler +// [--cpu_sched_rr_only] +// use only RR scheduling #include "error_numbers.h" #include "str_util.h" @@ -48,11 +60,13 @@ #define SCHED_RETRY_DELAY_MIN 60 // 1 minute #define SCHED_RETRY_DELAY_MAX (60*60*4) // 4 hours -#ifdef _WIN32 -#define SIM_EXEC "..\\boincsim" -#else -#define SIM_EXEC "../sim" -#endif +const char* state_fname = STATE_FILE_NAME; +const char* prefs_fname = GLOBAL_PREFS_FILE_NAME; +const char* config_fname = CONFIG_FILE; + +const char* timeline_fname = "sim_timeline.html"; +const char* log_fname = "sim_log.txt"; +const char* summary_fname = "sim_summary.xml"; bool user_active; double duration = 86400, delta = 60; @@ -60,32 +74,19 @@ FILE* logfile; bool running; double running_time = 0; bool server_uses_workload = false; -bool dcf_dont_use; -bool dcf_stats; -bool dual_dcf; bool cpu_sched_rr_only; -bool work_fetch_old; -int line_limit = 1000000; SIM_RESULTS sim_results; -void PROJECT::update_dcf_stats(RESULT* rp) { - double raw_ratio = rp->final_cpu_time/rp->estimated_duration_uncorrected(); - // see http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_III - ++completed_task_count; - double delta = raw_ratio - completions_ratio_mean; - completions_ratio_mean += delta / completed_task_count; - completions_ratio_s += delta * ( raw_ratio - completions_ratio_mean); - if (completed_task_count > 1) { - completions_ratio_stdev = sqrt(completions_ratio_s / (completed_task_count - 1)); - double required_stdev = (raw_ratio - completions_ratio_mean) / completions_ratio_stdev; - if (required_stdev > completions_required_stdevs) { - completions_required_stdevs = std::min(required_stdev, 7.0); - } - } - duration_correction_factor = completions_ratio_mean + - completions_required_stdevs * completions_ratio_stdev; - return; +void usage(char* prog) { + fprintf(stderr, "usage: %s\n" + "[--duration X]\n" + "[--delta X]\n" + "[--server_uses_workload]\n" + "[--cpu_sched_rr_only]\n", + prog + ); + exit(1); } APP* choose_app(vector& apps) { @@ -599,8 +600,6 @@ const char* colors[] = { "#ffdddd", }; -static int outfile_num=0; - bool uses_coproc(RESULT*, COPROC*) { // TODO return false; @@ -649,30 +648,23 @@ void gpu_on_aux(COPROC* cp) { } } } + void gpu_on() { gpu_on_aux(&gstate.host_info.coprocs.cuda); gpu_on_aux(&gstate.host_info.coprocs.ati); } -void CLIENT_STATE::html_start(bool show_prev) { +void CLIENT_STATE::html_start() { char buf[256]; - sprintf(buf, "sim_out_%d.html", outfile_num++); - html_out = fopen(buf, "w"); + html_out = fopen(timeline_fname, "w"); if (!html_out) { - fprintf(stderr, "can't open %s for writing\n", buf); + fprintf(stderr, "can't open %s for writing\n", timeline_fname); exit(1); } setbuf(html_out, 0); fprintf(html_out, "

Simulator output

\n"); - if (show_prev) { - fprintf(html_out, - "Previous file

\n", - outfile_num-2 - ); - } fprintf(html_out, - "message log

" "\n" ); for (int i=0; i%s\n", html_msg.c_str() ); html_msg = ""; - - if (++line_num == line_limit) { - line_num = 0; - html_end(true); - html_start(true); - } } -void CLIENT_STATE::html_end(bool show_next) { +void CLIENT_STATE::html_end() { fprintf(html_out, "
Time
"); - if (show_next) { - fprintf(html_out, - "

Next file\n", - outfile_num - ); - } else { - fprintf(html_out, "

\n");
-        sim_results.compute();
-        sim_results.print(html_out);
-        print_project_results(html_out);
-        fprintf(html_out, "
\n"); - } - if (show_next) { - fprintf(html_out, "

Last file\n"); - } else { - char buf[256]; - sprintf(buf, "sim_out_%d.html", outfile_num-1); -#ifndef _WIN32 - symlink(buf, "sim_out_last.html"); -#endif - } + fprintf(html_out, "

\n");
+    sim_results.compute();
+    sim_results.print(html_out);
+    print_project_results(html_out);
+    fprintf(html_out, "
\n"); fclose(html_out); } @@ -757,7 +727,7 @@ void CLIENT_STATE::simulate() { bool action; double start = START_TIME; now = start; - html_start(false); + html_start(); msg_printf(0, MSG_INFO, "starting simulation. delta %f duration %f", delta, duration ); @@ -785,7 +755,7 @@ void CLIENT_STATE::simulate() { html_rec(); if (now > start + duration) break; } - html_end(false); + html_end(); } void parse_error(char* file, int retval) { @@ -793,26 +763,10 @@ void parse_error(char* file, int retval) { exit(1); } -void help(char* prog) { - fprintf(stderr, "usage: %s\n" - "[--duration X]\n" - "[--delta X]\n" - "[--server_uses_workload]\n" - "[--dcf_dont_user]\n" - "[--dcf_stats]\n" - "[--dual_dcf]\n" - "[--cpu_sched_rr_only]\n" - "[--work_fetch_old]\n" - "[--dirs ...]\n", - prog - ); - exit(1); -} - char* next_arg(int argc, char** argv, int& i) { if (i >= argc) { fprintf(stderr, "Missing command-line argument\n"); - help(argv[0]); + usage(argv[0]); } return argv[i++]; } @@ -899,17 +853,14 @@ void cull_projects() { } } -#define SUMMARY_FILE "sim_summary.txt" -#define LOG_FILE "sim_log.txt" - void CLIENT_STATE::do_client_simulation() { msg_printf(0, MSG_INFO, "SIMULATION START"); - read_config_file(true); + read_config_file(true, config_fname); config.show(); add_platform("client simulator"); - parse_state_file(); - read_global_prefs(); + parse_state_file_aux(state_fname); + read_global_prefs(prefs_fname); cull_projects(); int j=0; for (unsigned int i=0; i dirs; - - logfile = fopen("sim_log.txt", "w"); - if (!logfile) { - fprintf(stderr, "Can't open sim_log.txt\n"); - exit(1); - } - setbuf(logfile, 0); sim_results.clear(); for (i=1; i %s", - SIM_EXEC, duration, delta, SUMMARY_FILE - ); - retval = system(buf); - if (retval) { - printf("simulation in %s failed\n", dir.c_str()); - exit(1); - } - FILE* f = fopen(SUMMARY_FILE, "r"); - sim_results.parse(f); - fclose(f); - sim_results.print(stdout, dir.c_str()); - total_results.add(sim_results); - chdir(".."); - } - total_results.divide((int)(dirs.size())); - total_results.print(stdout, "Total"); - } else { - gstate.do_client_simulation(); + logfile = fopen(log_fname, "w"); + if (!logfile) { + fprintf(stderr, "Can't open %s\n", log_fname); + exit(1); } + setbuf(logfile, 0); + gstate.do_client_simulation(); } diff --git a/client/work_fetch.cpp b/client/work_fetch.cpp index f651fb2118..52f17372d9 100644 --- a/client/work_fetch.cpp +++ b/client/work_fetch.cpp @@ -1305,18 +1305,9 @@ double RESULT::estimated_duration_uncorrected() { // estimate how long a result will take on this host // -#ifdef SIM -double RESULT::estimated_duration(bool for_work_fetch) { - if (dual_dcf && for_work_fetch && project->completions_ratio_mean) { - return estimated_duration_uncorrected()*project->completions_ratio_mean; - } - return estimated_duration_uncorrected()*project->duration_correction_factor; -} -#else double RESULT::estimated_duration(bool) { return estimated_duration_uncorrected()*project->duration_correction_factor; } -#endif double RESULT::estimated_time_remaining(bool for_work_fetch) { if (computing_done()) return 0; diff --git a/doc/sim_form.php b/doc/sim_form.php index 1d767be569..cc44479bb7 100644 --- a/doc/sim_form.php +++ b/doc/sim_form.php @@ -33,8 +33,7 @@ function show_form() {

The following controls enable various experimental policies. - The standard policy (as of 5.10.13) is no checkboxes enabled, - and the 'Normal' DCF policy. + The standard policy is no checkboxes enabled.

@@ -42,33 +41,46 @@ function show_form() {

Client uses Round-Robin (old-style) CPU scheduling?

- Client uses old work fetch policy? -

- Duration correction factor: Normal - : Stats - : Dual - : None -

- HTML output lines per file: -

"; } +// ?? the actual function doesn't seem to work here +function file_put_contents_aux($fname, $str) { + $f = fopen($fname, "w"); + if (!$f) die("fopen"); + $x = fwrite($f, $str); + if (!$x) die("fwrite"); + fclose($f); +} + if ($_POST['submit']) { chdir("sim"); - if (!file_put_contents("client_state.xml", $_POST['client_state'])) { - echo "Can't write client_state.xml - check permissions\n"; exit(); + $x = $_POST['client_state']; + if (!strlen($x)) { + die("missing state"); } - if (!file_put_contents("global_prefs.xml", $_POST['global_prefs'])) { - echo "Can't write global_prefs.xml - check permissions\n"; exit(); + $state_fname = tempnam("/tmp", "sim"); + file_put_contents_aux($state_fname, $x); + + $prefs_name = null; + $config_name = null; + + $x = $_POST['global_prefs']; + if (strlen($x)) { + $prefs_fname = tempnam("/tmp", "sim"); + file_put_contents_aux($prefs_fname, $x); } - if (!file_put_contents("cc_config.xml", $_POST['cc_config'])) { - echo "Can't write cc_config.xml - check permissions\n"; exit(); + + $x = $_POST['cc_config']; + if (strlen($x)) { + $config_fname = tempnam("/tmp", "sim"); + file_put_contents_aux($config_fname, $x); } + $duration = $_POST['duration']; $delta = $_POST['delta']; @@ -91,31 +103,35 @@ if ($_POST['submit']) { if ($_POST['rr_only']) { $rr_only = '--cpu_sched_rr_only'; } - $work_fetch_old = ''; - if ($_POST['work_fetch_old']) { - $work_fetch_old = '--work_fetch_old'; - } - $dcfflag = ""; - $dcf = ($_POST['dcf']); - if ($dcf == "stats") { - $dcfflag = '--dcf_stats'; - } else if ($dcf == 'none') { - $dcfflag = '--dcf_dont_use'; - } else if ($dcf == 'dual') { - $dcfflag = '--dual_dcf'; - } + $timeline_fname = tempnam("/tmp", "sim"); + $log_fname = tempnam("/tmp", "sim"); + $summary_fname = tempnam("/tmp", "sim"); - $llflag = ''; - $line_limit = $_POST['line_limit']; - if ($line_limit) { - $llflag = "--line_limit $line_limit"; + $cmd = "./sim --duration $duration --delta $delta $suw --state_file $state_fname --timeline_file $timeline_fname --log_file $log_fname --summary_file $summary_fname $rr_only $llflag"; + if ($prefs_fname) { + $cmd .= " --prefs_file $prefs_fname"; } + if ($config_fname) { + $cmd .= " --config_file $config_fname"; + } + echo "cmd: $cmd\n"; - Header("Location: sim/sim_out_0.html"); - $cmd = "./sim --duration $duration --delta $delta $suw $dcfflag $rr_only $work_fetch_old $llflag"; - system("/bin/rm sim_log.txt sim_out_*.html"); - system($cmd); + $x = system($cmd); + + echo $x; + readfile($timeline_fname); + echo "\n

\n";
+    readfile($log_fname);
+    echo "\n
\n"; + readfile($summary_fname); + + unlink($state_fname); + unlink($prefs_fname); + unlink($config_fname); + unlink($timeline_fname); + unlink($log_fname); + unlink($summary_fname); } else { page_head("BOINC client simulator"); echo "