mirror of https://github.com/BOINC/boinc.git
172 lines
4.7 KiB
PHP
172 lines
4.7 KiB
PHP
|
<?php
|
||
|
// This file is part of BOINC.
|
||
|
// http://boinc.berkeley.edu
|
||
|
// Copyright (C) 2011 University of California
|
||
|
//
|
||
|
// BOINC 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 3 of the License, or (at your option) any later version.
|
||
|
//
|
||
|
// BOINC 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.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Lesser General Public License
|
||
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
// 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 "<error>\n<message>$s</message>\n</error>\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 "<estimate>\n<seconds>$e</seconds>\n</estimate>\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(), "<uldl_dir_fanout>");
|
||
|
|
||
|
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>$batch_id</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");
|
||
|
}
|
||
|
|
||
|
?>
|