- web: remote job submission:

- add fields to batch table, extend APIs accordingly
    - require that example web interface run on BOINC server
        (this makes many things easier;
        an actual remote interface would require a bit more work)


svn path=/trunk/boinc/; revision=23881
This commit is contained in:
David Anderson 2011-07-27 06:20:48 +00:00
parent 17e947f543
commit 6e5acbbe60
10 changed files with 399 additions and 141 deletions

View File

@ -4376,3 +4376,25 @@ David 26 July 2011
forum_thread.php
submit_example.php
submit.php
David 26 July 2011
- web: remote job submission:
- add fields to batch table, extend APIs accordingly
- require that example web interface run on BOINC server
(this makes many things easier;
an actual remote interface would require a bit more work)
db/
boinc_db.h
schema.sql
html/
ops/
db_update.php
inc/
submit_db.inc
submit.inc
util.inc
result.inc
user/
submit_example.php
submit.php

View File

@ -563,6 +563,48 @@ struct RESULT {
void clear();
};
struct BATCH {
int id;
int user_id;
// submitter
int create_time;
double logical_start_time;
double logical_end_time;
double est_completion_time;
// current estimate of completion time
int njobs;
// # of workunits
double fraction_done;
// based on workunits completed
int nerror_jobs;
// # of workunits with error
int state;
// see below
double completion_time;
// when state became >= COMPLETE
double credit_estimate;
// initial estimate of required credit, counting replicas
double credit_canonical;
// the sum of credits of canonical results
double credit_total;
// the sum of credits of all results
char name[256];
// user-assigned name; need not be unique
int app_id;
}
// values of batch.state
//
#define BATCH_STATE_INIT 0
#define BATCH_STATE_IN_PROGRESS 1
#define BATCH_STATE_COMPLETE 2
// "complete" means all workunits have either
// a canonical result or an error
#define BATCH_STATE_ABORTED 3
#define BATCH_STATE_CLEANED_UP 4
// input/output files can be deleted,
// result and workunit records can be purged.
struct MSG_FROM_HOST {
int id;
int create_time;

View File

@ -282,6 +282,42 @@ create table result (
primary key (id)
) engine=InnoDB;
-- see boinc_db.h for doc
create table batch (
id serial primary key,
user_id integer not null,
create_time integer not null,
logical_start_time double not null,
logical_end_time double not null,
est_completion_time double not null,
njobs integer not null,
fraction_done double not null,
nerror_jobs integer not null,
state integer not null,
completion_time double not null,
credit_estimate double not null,
credit_canonical double not null,
credit_total double not null,
name varchar(255) not null,
app_id integer not null
) engine = InnoDB;
-- permissions for job submission
--
create table user_submit (
user_id integer not null,
quota double not null,
logical_start_time double not null,
all_apps tinyint not null
) engine = InnoDB;
-- (user, app) submit permissions
--
create table user_submit_app (
user_id integer not null,
app_id integer not null
) engine = InnoDB;
-- the following are used to implement trickle messages
create table msg_from_host (
@ -638,29 +674,3 @@ create table notify (
opaque integer not null
-- some other ID, e.g. that of the thread, user or PM record
);
create table batch (
id serial primary key,
user_id integer not null,
create_time integer not null,
logical_start_time double not null,
logical_end_time double not null,
est_completion_time double not null,
njobs integer not null
) engine = InnoDB;
-- permissions for job submission
--
create table user_submit (
user_id integer not null,
quota double not null,
logical_start_time double not null,
all_apps tinyint not null
) engine = InnoDB;
-- (user, app) submit permissions
--
create table user_submit_app (
user_id integer not null,
app_id integer not null
) engine = InnoDB;

View File

@ -567,7 +567,7 @@ function get_outfile_paths($result) {
function abort_workunit($wu) {
BoincResult::update_aux(
"server_state=5, outcome=5 where server_state=2 and workunit=$wu->id"
"server_state=5, outcome=5 where server_state=2 and workunitid=$wu->id"
);
$wu->update("error_mask=error_mask|16");
}

View File

@ -25,6 +25,7 @@ function req_to_xml($req, $op) {
<authenticator>$req->authenticator</authenticator>
<batch>
<app_name>$req->app_name</app_name>
<batch_name>$req->batch_name</batch_name>
";
foreach ($req->jobs as $job) {
$x .= " <job>
@ -107,6 +108,24 @@ function boinc_submit_batch($req) {
}
}
function batch_xml_to_object($batch) {
$b = null;
$b->id = (int)($batch->id);
$b->create_time = (double)($batch->create_time);
$b->est_completion_time = (double)($batch->est_completion_time);
$b->njobs = (int)($batch->njobs);
$b->fraction_done = (double) $batch->fraction_done;
$b->nerror_jobs = (int)($batch->nerror_jobs);
$b->state = (int)($batch->state);
$b->completion_time = (double)($batch->completion_time);
$b->credit_estimate = (double)($batch->credit_estimate);
$b->credit_canonical = (double)($batch->credit_canonical);
$b->credit_total = (double)($batch->credit_total);
$b->name = (string)($batch->name);
$b->app_name = (string)($batch->app_name);
return $b;
}
function boinc_query_batches($req) {
$req_xml = "<query_batches>
<authenticator>$req->authenticator</authenticator>
@ -116,14 +135,7 @@ function boinc_query_batches($req) {
if ($errmsg) return array(null, $errmsg);
$batches = array();
foreach ($reply->batch as $batch) {
$b = null;
$b->id = (int)($batch->id);
$b->completed = (int)($batch->completed);
$b->njobs = (int)($batch->njobs);
$b->create_time = (double)($batch->create_time);
if (!$b->completed) {
$b->fraction_done = (double) $batch->fraction_done;
}
$b = batch_xml_to_object($batch);
$batches[] = $b;
}
return array($batches, null);
@ -144,11 +156,7 @@ function boinc_query_batch($req) {
$j->canonical_instance_id = (int)($job->canonical_instance_id);
$jobs[] = $j;
}
$r = null;
$r->fraction_done = (double)($reply->fraction_done);
$r->completed = (int)($reply->completed);
$r->create_time = (double)($reply->create_time);
$r->est_completion_time = (double)($reply->est_completion_time);
$r = batch_xml_to_object($reply);
$r->jobs = $jobs;
return array($r, null);
}
@ -208,11 +216,11 @@ function boinc_get_output_files($req) {
return $req->project."/get_output.php?batch_id=$batch_id&auth_str=$auth_str";
}
function boinc_cleanup_batch($req) {
$req_xml = "<cleanup_batch>
function boinc_retire_batch($req) {
$req_xml = "<retire_batch>
<authenticator>$req->authenticator</authenticator>
<batch_id>$req->batch_id</batch_id>
</cleanup_batch>
</retire_batch>
";
list($reply, $errmsg) = do_http_op($req->project, $req_xml);
if ($errmsg) return $errmsg;
@ -223,6 +231,17 @@ function boinc_cleanup_batch($req) {
return null;
}
function batch_state_string($state) {
switch ($state) {
case BATCH_STATE_INIT: return "New";
case BATCH_STATE_IN_PROGRESS: return "In progress";
case BATCH_STATE_COMPLETE: return "Completed";
case BATCH_STATE_ABORTED: return "Aborted";
case BATCH_STATE_RETIRED: return "Retired";
}
return "Unknown state $state";
}
//// example usage follows
$req->project = "http://isaac.ssl.berkeley.edu/test/";

View File

@ -33,8 +33,20 @@ class BoincBatch {
if (!$ret) return $ret;
return $db->insert_id();
}
function update($clause) {
$db = BoincDb::get();
return $db->update($this, 'batch', $clause);
}
}
// see db/boinc_db.h
//
define('BATCH_STATE_INIT', 0);
define('BATCH_STATE_IN_PROGRESS', 1);
define('BATCH_STATE_COMPLETE', 2);
define('BATCH_STATE_ABORTED', 3);
define('BATCH_STATE_RETIRED', 4);
class BoincUserSubmit {
static function enum($clause) {
$db = BoincDb::get();

View File

@ -32,8 +32,6 @@ if (array_key_exists("PATH_INFO", $_SERVER)) {
ini_set("memory_limit", "64M");
date_default_timezone_set("UTC");
if (!defined('SECURE_URL_BASE')) {
define('SECURE_URL_BASE', URL_BASE);
}
@ -261,6 +259,11 @@ function time_str($x) {
return gmdate('j M Y | G:i:s', $x) . " UTC";
}
function local_time_str($x) {
if ($x == 0) return "---";
return date('j M Y | H:i:s', $x);
}
function pretty_time_str($x) {
return time_str($x);
}

View File

@ -751,6 +751,21 @@ create table user_submit_app (
) engine = InnoDB");
}
function update_7_26_2011() {
do_query("
alter table batch
add fraction_done double not null,
add nerror_jobs integer not null,
add state integer not null,
add completion_time double not null,
add credit_estimate double not null,
add credit_canonical double not null,
add credit_total double not null,
add name varchar(255) not null,
add app_id integer not null
");
}
// Updates are done automatically if you use "upgrade".
//
// If you need to do updates manually,
@ -770,6 +785,7 @@ $db_updates = array (
array(21728, "update_6_10_2010"),
array(23635, "update_6_3_2011"),
array(23762, "update_6_20_2011"),
array(23881, "update_7_26_2011"),
);
?>

View File

@ -73,13 +73,17 @@ function project_flops() {
return $y;
}
function est_elapsed_time($r) {
// crude estimate: batch FLOPs / project FLOPS
//
return batch_flop_count($r) / project_flops();
}
function estimate_batch($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();
$e = est_elapsed_time($r);
echo "<estimate>\n<seconds>$e</seconds>\n</estimate>\n";
}
@ -142,49 +146,84 @@ function submit_batch($r) {
stage_files($r, $template);
$njobs = count($r->batch->job);
$now = time();
$batch_name = (string)($r->batch->batch_name);
$batch_id = BoincBatch::insert(
"(user_id, create_time, njobs) values ($user->id, $now, $njobs)"
"(user_id, create_time, njobs, name, app_id) values ($user->id, $now, $njobs, '$batch_name', $app->id)"
);
$i = 0;
foreach($r->batch->job as $job) {
submit_job($job, $template, $app, $batch_id, $i++);
}
$batch = BoincBatch::lookup_id($batch_id);
$batch->update("state=".BATCH_STATE_IN_PROGRESS);
echo "<batch_id>$batch_id</batch_id>\n";
}
function fraction_done($batch) {
$wus = BoincWorkunit::enum("batch = $batch->id");
// compute and update params of a batch
// NOTE: eventually this should be done by server components
// (transitioner, validator etc.) as jobs complete or time out
//
// TODO: update est_completion_time
//
function get_batch_params($batch, $wus) {
if ($batch->state > BATCH_STATE_IN_PROGRESS) return $batch;
$fp_total = 0;
$fp_done = 0;
$completed = 1;
$completed = true;
$nerror_jobs = 0;
$credit_canonical = 0;
foreach ($wus as $wu) {
$fp_total += $wu->rsc_fpops_est;
if ($wu->canonical_resultid) {
$fp_done += $wu->rsc_fpops_est;
$credit_canonical += $wu->canonical_credit;
} else if ($wu->error_mask) {
$nerror_jobs++;
} else {
$completed = 0;
$completed = false;
}
}
if (!$fp_total) return array(1, true);;
$fd= $fp_done / $fp_total;
return array($fd, $completed);
if ($fp_total) {
$batch->fraction_done = $fp_done / $fp_total;
}
if ($completed && $batch->state < BATCH_STATE_COMPLETE) {
$batch->state = BATCH_STATE_COMPLETE;
$batch->completion_time = time();
}
$batch->nerror_jobs = $nerror_jobs;
$batch->update("fraction_done = $batch->fraction_done, nerror_jobs = $batch->nerror_jobs, state=$batch->state, completion_time = $batch->completion_time, credit_canonical = $batch->credit_canonical");
return $batch;
}
function print_batch_params($batch) {
$app = BoincApp::lookup_id($batch->app_id);
echo "
<id>$batch->id</id>
<create_time>$batch->create_time</create_time>
<est_completion_time>$batch->est_completion_time</est_completion_time>
<njobs>$batch->njobs</njobs>
<fraction_done>$batch->fraction_done</fraction_done>
<nerror_jobs>$batch->nerror_jobs</nerror_jobs>
<state>$batch->state</state>
<completion_time>$batch->completion_time</completion_time>
<credit_estimate>$batch->credit_estimate</credit_estimate>
<credit_canonical>$batch->credit_canonical</credit_canonical>
<credit_total>$batch->credit_total</credit_total>
<name>$batch->name</name>
<app_name>$app->name</app_name>
";
}
function query_batches($r) {
list($user, $user_submit) = authenticate_user($r, null);
$batches = BoincBatch::enum("user_id = $user->id");
echo "<batches>\n";
foreach ($batches as $b) {
list($fd, $completed) = fraction_done($b);
echo " <batch>
<id>$b->id</id>
<fraction_done>$fd</fraction_done>
<completed>$completed</completed>
<create_time>$b->create_time</create_time>
<est_completion_time>$b->est_completion_time</est_completion_time>
<njobs>$b->njobs</njobs>
</batch>
";
foreach ($batches as $batch) {
$wus = BoincWorkunit::enum("batch = $batch->id");
$batch = get_batch_params($batch, $wus);
echo " <batch>\n";
print_batch_params($batch);
echo " </batch>\n";
}
echo "</batches>\n";
}
@ -199,23 +238,23 @@ function query_batch($r) {
list($user, $user_submit) = authenticate_user($r, null);
$batch_id = (int)($r->batch_id);
$batch = BoincBatch::lookup_id($batch_id);
if (!$batch) {
error("no such batch");
}
if ($batch->user_id != $user->id) {
error("not owner");
}
echo "<batch>\n";
list($fd, $completed) = fraction_done($batch);
echo "
<fraction_done>$fd</fraction_done>
<completed>$completed</completed>
<create_time>$b->create_time</create_time>
<est_completion_time>$b->est_completion_time</est_completion_time>
";
$wus = BoincWorkunit::enum("batch = $batch_id");
$batch = get_batch_params($batch, $wus);
echo "<batch>\n";
print_batch_params($batch);
$n_outfiles = n_outfiles($wus[0]);
foreach ($wus as $wu) {
echo " <job>
<id>$wu->id</id>
<canonical_instance_id>$wu->canonical_resultid</canonical_instance_id>
<n_outfiles>".n_outfiles($wu)."</n_outfiles>
<n_outfiles>$n_outfiles</n_outfiles>
</job>
";
}
@ -267,10 +306,11 @@ function abort_batch($r) {
foreach ($wus as $wu) {
abort_workunit($wu);
}
$batch->update("state=".BATCH_STATE_ABORTED);
echo "<success>1</success>";
}
function cleanup_batch($r) {
function retire_batch($r) {
list($user, $user_submit) = authenticate_user($r, null);
$batch_id = (int)($r->batch_id);
$batch = BoincBatch::lookup_id($batch_id);
@ -282,6 +322,7 @@ function cleanup_batch($r) {
foreach ($wus as $wu) {
$wu->update("assimilate_state=2, transition_time=$now");
}
$batch->update("state=".BATCH_STATE_RETIRED);
echo "<success>1</success>";
}
@ -309,7 +350,7 @@ switch ($r->getName()) {
case 'query_batch': query_batch($r); break;
case 'query_job': query_job($r); break;
case 'abort_batch': abort_batch($r); break;
case 'cleanup_batch': cleanup_batch($r); break;
case 'retire_batch': retire_batch($r); break;
default: error("bad command");
}

View File

@ -20,28 +20,30 @@
// example of a web interface to remote job submission
//
// Notes:
// - You'll need to adapt/extend this considerably;
// e.g. the project URL, app name and user authenticator are hardwired here.
// - This can run on any host, not just the project server
// (that's the "remote" part).
// - You'll need to adapt/extend this considerably,
// especially if you want to run this
// on a server other than the BOINC project serve.
// - For convenience, this uses some functions from BOINC
// (page_head() etc.).
// When you adapt this to your own purposes,
// you can strip out this stuff if the web site doesn't use BOINC
require_once("../inc/submit.inc");
require_once("../inc/submit_db.inc");
require_once("../inc/util.inc");
require_once("../project/project.inc");
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
$project = "http://isaac.ssl.berkeley.edu/test/";
$auth = "157f96a018b0b2f2b466e2ce3c7f54db";
$app_name = "uppercase";
$project = $master_url; // from project.inc
$user = get_logged_in_user();
$auth = $user->authenticator;
function handle_main() {
global $project, $auth, $app_name;
global $project, $auth;
$req->project = $project;
$req->authenticator = $auth;
list($batches, $errmsg) = boinc_query_batches($req);
@ -49,52 +51,119 @@ function handle_main() {
page_head("Job submission and control");
echo date("F j, Y, g:i a");
show_button("submit_example.php?action=create_form", "Create new batch");
echo "<h2>Batches in progress</h2>\n";
start_table();
table_header("ID", "# jobs", "progress", "submitted");
$first = true;
foreach ($batches as $batch) {
if ($batch->completed) continue;
if ($batch->state != BATCH_STATE_IN_PROGRESS) continue;
if ($first) {
$first = false;
echo "<h2>In progress</h2>\n";
start_table();
table_header("name", "ID", "app", "# jobs", "progress", "submitted");
}
$pct_done = (int)($batch->fraction_done*100);
table_row(
"<a href=submit_example.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
"<a href=submit_example.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
$batch->app_name,
$batch->njobs,
"$pct_done%",
time_str($batch->create_time)
local_time_str($batch->create_time)
);
}
end_table();
if (!$first) {
end_table();
}
echo "<h2>Batches completed</h2>\n";
start_table();
table_header("ID", "# jobs", "submitted");
$first = true;
foreach ($batches as $batch) {
if (!$batch->completed) continue;
if ($batch->state != BATCH_STATE_COMPLETE) continue;
if ($first) {
$first = false;
echo "<h2>Completed</h2>\n";
start_table();
table_header("name", "ID", "# jobs", "submitted");
}
table_row(
"<a href=submit_example.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
"<a href=submit_example.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
$batch->njobs,
time_str($batch->create_time)
local_time_str($batch->create_time)
);
}
end_table();
if (!$first) {
end_table();
}
$first = true;
foreach ($batches as $batch) {
if ($batch->state != BATCH_STATE_ABORTED) continue;
if ($first) {
$first = false;
echo "<h2>Aborted</h2>\n";
start_table();
table_header("name", "ID", "# jobs", "submitted");
}
table_row(
"<a href=submit_example.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
"<a href=submit_example.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
$batch->njobs,
local_time_str($batch->create_time)
);
}
if (!$first) {
end_table();
}
page_tail();
}
function handle_create_form() {
global $project, $auth, $app_name;
function eligible_apps() {
global $user;
$apps = BoincApp::enum("deprecated = 0");
$user_submit = BoincUserSubmit::lookup_userid($user->id);
if (!$user_submit) return null;
$a = array();
foreach($apps as $app) {
if ($user_submit->all_apps) {
$a[] = $app;
} else {
if (BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$app->id")) {
$a[] = $app;
}
}
}
return $a;
}
function app_select($apps) {
$x = "<select name=app_name>\n";
foreach ($apps as $app) {
$x .= "<option value=$app->name>$app->user_friendly_name</option>\n";
}
$x .= "</select>\n";
return $x;
}
function handle_create_form() {
global $project, $auth;
$apps = eligible_apps();
if (!$apps) error_page("You are not allowed to submit jobs");
page_head("Create batch");
echo "
<form action=submit_example.php>
<input type=hidden name=action value=create_action>
";
start_table();
row2("Input file URL", "<input name=input_url size=60>");
row2("Parameter low value", "<input name=param_lo>");
row2("Parameter high value", "<input name=param_hi>");
row2("Parameter increment", "<input name=param_inc>");
row2("Name", "<input name=batch_name value=\"enter name\">");
row2("Application", app_select($apps));
row2("Input file URL", "<input name=input_url size=60 value=\"http://google.com/\">");
row2("Parameter low value", "<input name=param_lo value=10>");
row2("Parameter high value", "<input name=param_hi value=20>");
row2("Parameter increment", "<input name=param_inc value=1>");
row2("",
"<input type=submit name=get_estimate value=\"Get completion time estimate\">"
);
@ -109,27 +178,30 @@ function handle_create_form() {
// build a request object for boinc_*_batch() from form variables
//
function form_to_request() {
global $project, $auth, $app_name;
global $project, $auth;
$input_url = get_str('input_url');
if (!$input_url) error_page("missing input URL");
$param_lo = get_str('param_lo');
if (!$param_lo) error_page("missing param lo");
$param_hi = get_str('param_hi');
if (!$param_hi) error_page("missing param hi");
$param_inc = get_str('param_inc');
if (!$param_inc) error_page("missing param inc");
$param_lo = (double)get_str('param_lo');
if ($param_lo<0 || $param_lo>60) error_page("param lo must be in 0..60");
$param_hi = (double)get_str('param_hi');
if ($param_hi<0 || $param_hi>60 || $param_hi <= $param_lo) {
error_page("param hi must be in 0..60 and > param lo");
}
$param_inc = (double)get_str('param_inc');
if ($param_inc < 1) error_page("param inc must be >= 1");
$req->project = $project;
$req->authenticator = $auth;
$req->app_name = $app_name;
$req->app_name = get_str('app_name');
$req->batch_name = get_str('batch_name');
$req->jobs = Array();
$f->source = $input_url;
$f->name = "in";
$job->input_files = Array($f);
for ($x=(double)$param_lo; $x<(double)$param_hi; $x += (double)$param_inc) {
for ($x=$param_lo; $x<$param_hi; $x += $param_inc) {
$job->rsc_fpops_est = $x*1e9;
$job->command_line = "--t $x";
$req->jobs[] = $job;
@ -139,7 +211,7 @@ function form_to_request() {
}
function handle_create_action() {
global $project, $auth, $app_name;
global $project, $auth;
$get_estimate = get_str('get_estimate', true);
if ($get_estimate) {
@ -147,47 +219,68 @@ function handle_create_action() {
list($e, $errmsg) = boinc_estimate_batch($req);
if ($errmsg) error_page($errmsg);
page_head("Batch estimate");
echo "Estimate: $e seconds";
echo sprintf("Estimate: %.0f seconds", $e);
page_tail();
} else {
$req = form_to_request($project, $auth);
list($id, $errmsg) = boinc_submit_batch($req);
if ($errmsg) error_page($errmsg);
page_head("Batch submitted");
echo "Batch ID: $id";
echo "Batch created, ID: $id
<p>
<a href=submit_example.php>Return to job control page</a>
";
page_tail();
}
}
function handle_query_batch() {
global $project, $auth, $app_name;
global $project, $auth;
$req->project = $project;
$req->authenticator = $auth;
$req->batch_id = get_int('batch_id');
list($reply, $errmsg) = boinc_query_batch($req);
list($batch, $errmsg) = boinc_query_batch($req);
if ($errmsg) error_page($errmsg);
page_head("Batch $req->batch_id");
$url = boinc_get_output_files($req);
show_button($url, "Get zipped output files");
if ($reply->completed) {
echo "<br>";
show_button(
"submit_example.php?action=cleanup_batch_confirm&batch_id=$req->batch_id",
"Delete batch"
);
} else {
start_table();
row2("name", $batch->name);
row2("application", $batch->app_name);
row2("state", batch_state_string($batch->state));
row2("# jobs", $batch->njobs);
row2("# error jobs", $batch->nerror_jobs);
row2("progress", sprintf("%.0f%%", $batch->fraction_done*100));
if ($batch->completion_time) {
row2("completed", local_time_str($batch->completion_time));
}
row2("Credit, estimated", $batch->credit_estimate);
row2("Credit, canonical instances", $batch->credit_canonical);
row2("Credit, total", $batch->credit_total);
end_table();
switch ($batch->state) {
case BATCH_STATE_IN_PROGRESS:
echo "<br>";
show_button(
"submit_example.php?action=abort_batch_confirm&batch_id=$req->batch_id",
"Abort batch"
);
break;
case BATCH_STATE_COMPLETE:
case BATCH_STATE_ABORTED:
echo "<br>";
show_button(
"submit_example.php?action=retire_batch_confirm&batch_id=$req->batch_id",
"Retire batch"
);
break;
}
echo "<h2>Jobs</h2>\n";
start_table();
table_header("Job ID", "Canonical instance");
foreach($reply->jobs as $job) {
foreach($batch->jobs as $job) {
$id = (int)$job->id;
$resultid = (int)$job->canonical_instance_id;
if ($resultid) {
@ -206,7 +299,7 @@ function handle_query_batch() {
}
function handle_query_job() {
global $project, $auth, $app_name;
global $project, $auth;
$req->project = $project;
$req->authenticator = $auth;
$req->job_id = get_int('job_id');
@ -252,7 +345,7 @@ function handle_abort_batch_confirm() {
}
function handle_abort_batch() {
global $project, $auth, $app_name;
global $project, $auth;
$req->project = $project;
$req->authenticator = $auth;
$req->batch_id = get_int('batch_id');
@ -265,29 +358,29 @@ function handle_abort_batch() {
page_tail();
}
function handle_cleanup_batch_confirm() {
function handle_retire_batch_confirm() {
$batch_id = get_int('batch_id');
page_head("Confirm delete batch");
page_head("Confirm retire batch");
echo "
Deleting a batch will remove all of its output files.
Retiring a batch will remove all of its output files.
Are you sure you want to do this?
<p>
";
show_button(
"submit_example.php?action=cleanup_batch&batch_id=$batch_id",
"Yes - delete batch"
"submit_example.php?action=retire_batch&batch_id=$batch_id",
"Yes - retire batch"
);
page_tail();
}
function handle_cleanup_batch() {
global $project, $auth, $app_name;
function handle_retire_batch() {
global $project, $auth;
$req->project = $project;
$req->authenticator = $auth;
$req->batch_id = get_int('batch_id');
$errmsg = boinc_cleanup_batch($req);
$errmsg = boinc_retire_batch($req);
if ($errmsg) error_page($errmsg);
page_head("Batch deleted");
page_head("Batch retired");
echo "
<a href=submit_example.php>Return to job control page</a>.
";
@ -318,11 +411,11 @@ case 'abort_batch_confirm':
case 'abort_batch':
handle_abort_batch();
break;
case 'cleanup_batch_confirm':
handle_cleanup_batch_confirm();
case 'retire_batch_confirm':
handle_retire_batch_confirm();
break;
case 'cleanup_batch':
handle_cleanup_batch();
case 'retire_batch':
handle_retire_batch();
break;
default:
error_page('no such action');