. // web interface to client simulator // // to use this, symlink to it from the html/user dir of a BOINC project, // create an apache-writable dir called "scenarios" there, // and symlink from html/inc to sim_util.inc require_once("../inc/util.inc"); require_once("../inc/sim_util.inc"); function get_comments($dir) { $d = "$dir/comments"; if (!is_dir($d)) return null; $dd = opendir($d); $x = ""; while (false !== ($f = readdir($dd))) { if ($f == ".") continue; if ($f == "..") continue; if (strlen($x)) $x .= "
\n"; $userid = (int)file_get_contents("$d/$f/userid"); $user = BoincUser::lookup_id($userid); $comment = file_get_contents("$d/$f/comment"); $date = date_str(filemtime("$d/$f/comment")); $x .= "By $user->name ($date):
$comment\n"; } return $x; } function nsims($scen) { $d = opendir("scenarios/$scen/simulations"); $n = 0; while (false !== ($f = readdir($d))) { if ($f == ".") continue; if ($f == "..") continue; $n++; } return $n; } function show_scenario_summary($f) { $desc = file_get_contents("scenarios/$f/description"); $userid = (int)file_get_contents("scenarios/$f/userid"); $user = BoincUser::lookup_id($userid); $date = date_str(filemtime("scenarios/$f")); $nsims = nsims($f); echo " Scenario $f $user->name $date $nsims $desc "; } // show existing scenarios, "create scenario" button // function show_scenarios() { page_head("The BOINC Client Emulator"); echo " Welcome to the BOINC Client Emulator (BCE). BCE emulates a BOINC client attached to one or more projects. It predicts, in a few seconds, what the BOINC client will do over a period of day or months. This makes it easier for BOINC developers to fix bugs and improve performance.

The inputs to BCE, called scenarios, describe a particular computer and the project to which it's attached. A scenario consists of 4 files:

You can use the files from a running BOINC client to emulate that client. You can modify these files, or create new ones, to study hypothetical hosts (e.g. ones with a large number of CPUs, attached to a large number of projects, and so on). See The BCE documentation for details.

You create a scenario by uploading these files to the BOINC server. You can then run any number of simulations based on the scenario. The parameters of a simulation include

The outputs of a simulation include
"; show_button( "sim_web.php?action=create_scenario_form", "Create a scenario", "Create a new scenario" ); echo "

Existing scenarios

"; start_table(); echo " Name Who When # Simulations Description "; $d = opendir("scenarios"); while (false !== ($f = readdir($d))) { if ($f === ".") continue; if ($f === "..") continue; show_scenario_summary($f); } echo "\n"; page_tail(); } // show form for creating a scenario // function create_scenario_form() { get_logged_in_user(); page_head("Create a scenario"); echo " To create a scenario: choose the input files, enter a short description, and click OK (items with * are required).
"; row2("* client_state.xml", ""); row2("global_prefs.xml", ""); row2("global_prefs_override.xml", ""); row2("cc_config.xml", ""); row2("* Description", ""); row2("", ""); echo "
"; page_tail(); } // create a subdir $dir/N for the first available N // function create_dir_seqno($dir) { $i = -1; $d = opendir($dir); while (false !== ($f = readdir($d))) { $j = -1; $n = sscanf($f, "%d", $j); if ($n == 1 && $j >= 0) { if ($j > $i) { $i = $j; } } } $i++; $p = "$dir/$i"; mkdir($p); return "$i"; } // choose scenario name // create dir, put files there // create meta-data file // redirect to show scenario // function create_scenario() { $user = get_logged_in_user(); $csname = $_FILES['client_state']['tmp_name']; if (!is_uploaded_file($csname)) { error_page("You must specify a client_state.xml file."); } $desc = post_str("description", true); if (!strlen($desc)) { error_page("You must supply a description."); } $desc = strip_tags($desc); $sname = create_dir_seqno("scenarios"); $d = "scenarios/$sname"; move_uploaded_file($csname, "$d/client_state.xml"); $gp = $_FILES['global_prefs']['tmp_name']; if (is_uploaded_file($gp)) { move_uploaded_file($gp, "$d/global_prefs.xml"); } $gpo = $_FILES['global_prefs_override']['tmp_name']; if (is_uploaded_file($gpo)) { move_uploaded_file($gpo, "$d/global_prefs_override.xml"); } $cc = $_FILES['cc_config']['tmp_name']; if (is_uploaded_file($cc)) { move_uploaded_file($cc, "$d/cc_config.xml"); } file_put_contents("$d/userid", "$user->id"); file_put_contents("$d/description", $desc); mkdir("$d/simulations"); header("Location: sim_web.php?action=show_scenario&name=$sname"); } function show_simulation_summary($scen, $sim) { $dir = "scenarios/$scen/simulations/$sim"; $userid = (int)file_get_contents("$dir/userid"); $user = BoincUser::lookup_id($userid); $date = date_str(filemtime($dir)); echo " $sim $user->name $date
".file_get_contents("$dir/inputs.txt")."
        
".file_get_contents("$dir/results.txt")."
        ".get_comments($dir)."
        
    ";
}

// show:
// links to files
// list of existing simulations
// link for new simulation
//
function show_scenario() {
    $name = get_str("name");
    $d = "scenarios/$name";
    if (!is_dir($d)) {
        error_page("No such scenario");
    }
    page_head("Scenario $name");
    $desc = file_get_contents("scenarios/$name/description");
    $userid = (int)file_get_contents("scenarios/$name/userid");
    $user = BoincUser::lookup_id($userid);
    $date = date_str(filemtime("scenarios/$name"));
    start_table();
    row2("Creator", $user->name);
    row2("When", $date);
    row2("Description", $desc);
    $x = "client_state.xml";
    if (file_exists("$d/global_prefs.xml")) {
        $x .= "
global_prefs.xml\n"; } if (file_exists("$d/global_prefs_override.xml")) { $x .= "
global_prefs_override.xml\n"; } if (file_exists("$d/cc_config.xml")) { $x .= "
cc_config.xml\n"; } row2("Input files", $x); end_table(); show_button("sim_web.php?action=simulation_form&scen=$name", "Do new simulation", "Do new simulation" ); echo "

Simulations

"; start_table(); echo " ID
Click for details Who When Parameters Results Comments "; $s = opendir("$d/simulations"); while (false !== ($f = readdir($s))) { if (!is_numeric($f)) continue; show_simulation_summary($name, $f); } end_table(); page_tail(); } // form for simulation parameters: // duration, time step, policy options // function simulation_form() { $scen = get_str("scen"); page_head("Do simulation"); echo "
"; start_table(); row2("Duration", " seconds"); row2("Time step", " seconds"); row2("Use Recent Estimated Credit
If checked, scheduling policies will be based on Recent Estimated Credit (REC) rather than short- and long-term debt.", "" ); row2("Use hysteresis work fetch?
If checked, the client will wait until the work buffer falls below X, then fill it to X+Y. Otherwise it will keep it filled to X+Y.", "" ); row2("Scheduler does detailed deadline check?
If checked, the scheduler's deadline decisions will use a detailed EDF simulation rather than an approximation.", "" ); row2("Client uses pure Round-robin?
If checked, CPU scheduling will use a simple round-robin policy.", "" ); row2("", ""); end_table(); page_tail(); } // create directory for simulation, // run simulation, // redirect to simulation page // function simulation_action() { $user = get_logged_in_user(); $scen = get_str("scen"); if (!is_dir("scenarios/$scen")) { error_page("no such scenario"); } $sim_dir = "scenarios/$scen/simulations"; $sim_name = create_dir_seqno($sim_dir); $sim_path = "$sim_dir/$sim_name"; $policy = new POLICY(""); $policy->use_rec = get_str("use_rec", true); $policy->use_hyst_fetch = get_str("use_hyst_fetch", true); $policy->cpu_sched_rr_only = get_str("cpu_sched_rr_only", true); $policy->server_uses_workload = get_str("server_uses_workload", true); file_put_contents("$sim_path/userid", "$user->id"); do_sim("scenarios/$scen", $sim_path, $policy); header("Location: sim_web.php?action=show_simulation&scen=$scen&sim=$sim_name"); } // show links to files in simulation directory // function show_simulation() { $scen = get_str("scen"); $sim = get_str("sim"); $dir = "scenarios/$scen/simulations/$sim"; if (!is_dir($dir)) { error_page("No such simulation"); } page_head("Simulation $sim"); start_table(); $userid = (int)file_get_contents("$dir/userid"); $user = BoincUser::lookup_id($userid); $date = date_str(filemtime($dir)); row2("Scenario", "$scen"); row2("Who", $user->name); row2("When", $date); row2("Parameters", "
".file_get_contents("$dir/inputs.txt")."
"); row2("Results", "
".file_get_contents("$dir/results.txt")."
"); $x = file_get_contents("$dir/index.html"); $x = str_replace("

Output files

", "", $x); $x = str_replace("href=", "href=scenarios/$scen/simulations/$sim/", $x); row2("Output files", $x); $x = get_comments($dir); if ($x) { row2("Comments", $x); } echo " "; row2("", "" ); echo "
"; end_table(); page_tail(); } function add_comment() { $user = get_logged_in_user(); $scen = get_str("scen"); $sim = get_str("sim"); $dir = "scenarios/$scen/simulations/$sim"; if (!is_dir($dir)) { error_page("No such simulation"); } $cdir = "$dir/comments"; @mkdir($cdir); $c = create_dir_seqno($cdir); $p = "$cdir/$c"; file_put_contents("$p/userid", "$user->id"); file_put_contents("$p/comment", get_str("comment")); header("Location: sim_web.php?action=show_simulation?scen=$scen&sim=$sim"); } $action = get_str("action", true); if (!$action) $action = post_str("action", true); switch ($action) { case "create_scenario_form": create_scenario_form(); break; case "create_scenario": create_scenario(); break; case "show_scenario": show_scenario(); break; case "simulation_form": simulation_form(); break; case "simulation_action": simulation_action(); break; case "show_simulation": show_simulation(); break; case "add_comment": add_comment(); break; default: show_scenarios(); } ?>