. // Handler for remote job submission. // See http://boinc.berkeley.edu/trac/wiki/RemoteJobs require_once("../inc/boinc_db.inc"); require_once("../inc/submit_db.inc"); require_once("../inc/xml.inc"); require_once("../inc/dir_hier.inc"); function error($s) { echo "\n$s\n\n"; exit; } function authenticate_user($r, $app) { $auth = (string)$r->authenticator; if (!$auth) error("no authenticator"); $user = BoincUser::lookup("authenticator='$auth'"); if (!$user) error("bad authenticator"); $user_submit = BoincUserSubmit::lookup_userid($user->id); if (!$user_submit) error("no submit access"); if (!$user_submit->all_apps) { $usa = BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$app->id"); if (!$usa) { error("no submit access"); } } return array($user, $user_submit); } function get_app($r) { $name = (string)($r->batch->app_name); $app = BoincApp::lookup("name='$name'"); if (!$app) error("no app"); return $app; } function batch_flop_count($r) { $x = 0; foreach($r->batch->job as $job) { $x += (double)$job->rsc_fpops_est; } return $x; } // estimate project FLOPS based on recent average credit // function project_flops() { $x = BoincUser::sum("expavg_credit"); $y = 1e9*$x/200; return $y; } function batch_estimate($r) { $app = get_app($r); list($user, $user_submit) = authenticate_user($r, $app); // crude estimate: batch FLOPs / project FLOPS // $e = batch_flop_count($r) / project_flops(); echo "\n$e\n\n"; } function read_input_template($app) { $path = "../../templates/$app->name"."_in"; return simplexml_load_file($path); } function validate_batch($r, $template) { $i = 0; foreach($r->batch->job as $job) { $n = count($template->file_info); $m = count($job->input_file); if ($n != $m) { error("wrong # of input files for job $i: need $n, got $m"); } $i++; } } $fanout = parse_config(get_config(), ""); function stage_file($file) { global $fanout; $physical_name = (string)$file->physical_name; $source = (string)$file->source; $path = dir_hier_path($physical_name, "../../download", $fanout); if (file_exists($path)) return; if (!copy($source, $path)) { error("can't copy file from $source"); } } function stage_files($r, $template) { foreach($r->batch->job as $job) { foreach ($job->input_file as $file) { stage_file($file); } } } function submit_job($job, $template, $app, $batch_id, $i) { $cmd = "cd ../..; ./bin/create_work --appname $app->name --batch $batch_id"; $cmd .= " --wu_name batch_".$batch_id."_".$i; foreach ($job->input_file as $file) { $name = (string)$file->physical_name; $cmd .= " $name"; system($cmd); } } function batch_submit($r) { $app = get_app($r); list($user, $user_submit) = authenticate_user($r, $app); $template = read_input_template($app); validate_batch($r, $template); stage_files($r, $template); $njobs = count($r->batch->job); $now = time(); $batch_id = BoincBatch::insert("(user_id, create_time, njobs) values ($user->id, $now, $njobs)"); $i = 0; foreach($r->batch->job as $job) { submit_job($job, $template, $app, $batch_id, $i++); } echo "$batch_id\n"; } function query_job($r) { } function query_batch($r) { } function abort_batch($r) { } xml_header(); $r = simplexml_load_string($_POST['request']); if (!$r) { error("can't parse request message"); } switch ($r->getName()) { case 'batch_estimate': batch_estimate($r); break; case 'batch_submit': batch_submit($r); break; case 'query_job': query_job($r); break; case 'query_batch': query_batch($r); break; case 'abort_batch': abort_batch($r); break; default: error("bad command"); } ?>