#!/usr/bin/env php
setenv BOINC_PROJECT_DIR ~/projects/my_project
";
exit(1);
}
}
function usage() {
echo "Usage: boinc_job [boinc-options] program [program-options]
boinc-options:
--platform p
Run the program on platform p
--infile f
The program will use f as an input file
--outfile f
The program will use f as an output file
--stdin f
Direct f to the program's stdin
--stdout f
Direct the program's stdout to f
--help
Print this
";
exit(1);
}
function error($msg) {
echo "$msg\n";
exit(1);
}
function download_path($filename) {
global $project_dir;
return dir_hier_path($filename, "$project_dir/download", 1024);
}
function upload_path($filename) {
global $project_dir;
return dir_hier_path($filename, "$project_dir/upload", 1024);
}
function do_includes() {
global $project_dir;
chdir("$project_dir/html/ops");
require_once("../inc/boinc_db.inc");
require_once("../inc/dir_hier.inc");
BoincDb::get();
}
function check_app_version() {
global $platform, $app_name;
$app_name = "single_job_$platform";
$app = BoincApp::lookup("name='$app_name'");
if (!$app) {
error("This project isn't configured to run single jobs.");
}
}
// make the job.xml file used by the wrapper
//
function make_wrapper_job_file() {
global $program_phys, $stdin_file, $stdout_file, $cmdline_args, $wuid;
global $project_dir, $wrapper_job_filename;
chdir($project_dir);
$wrapper_job_filename = "sj_$wuid.xml";
$path = download_path($wrapper_job_filename);
$f = fopen($path, "w");
if (!$f) {
error("Can't open $path");
}
fwrite($f,
"
$program_phys
");
if ($stdin_file) {
fwrite($f, " $stdin_file\n");
}
if ($stdout_file) {
fwrite($f, " $stdout_file\n");
}
if ($cmdline_args) {
fwrite($f, " $cmdline_args\n");
}
fwrite($f, " \n\n");
fclose($f);
}
function make_wu_template() {
global $wuid, $infiles, $stdin_file, $program_phys, $wu_template_filename;
global $project_dir;
chdir($project_dir);
$wu_template_filename = "templates/sj_wu_template_$wuid";
$f = fopen($wu_template_filename, "w");
if (!$f) {
error("Can't open $wu_template_filename");
}
$n = count($infiles);
$n++; // for job file
if ($stdin_file) {
$n++;
}
for ($i=0; $i<$n; $i++) {
fwrite($f,
"
$i
");
}
// The program file needs to be executable.
// Make it sticky too.
//
fwrite($f,
"
$i
");
fwrite($f, "\n");
$i = 0;
foreach($infiles as $infile) {
fwrite($f,
"
$i
$infile
");
$i++;
}
if ($stdin_file) {
fwrite($f,
"
$i
$stdin_file
");
$i++;
}
fwrite($f,
"
$i
job.xml
");
$i++;
fwrite($f,
"
$i
$program_phys
");
fwrite($f,
" 1e18
1e15
");
fclose($f);
}
function make_result_template() {
global $wuid, $outfiles, $stdout_file, $project_dir;
global $result_template_filename;
chdir($project_dir);
$result_template_filename = "templates/sj_result_template_$wuid";
$f = fopen($result_template_filename, "w");
if (!$f) {
error("Can't open $result_template_filename");
}
$i = 0;
foreach($outfiles as $outfile) {
fwrite($f,
"
1e12
");
$i++;
}
if ($stdout_file) {
fwrite($f,
"
1e12
");
}
fwrite($f, "\n");
$i = 0;
foreach($outfiles as $outfile) {
fwrite($f,
"
$outfile
");
$i++;
}
if ($stdout_file) {
fwrite($f,
"
$stdout_file
");
}
fwrite($f, "\n");
fclose($f);
}
// make the sj_WUID file
//
function make_job_file() {
global $wuid, $job_dir, $project_dir;
chdir($project_dir);
$filename = "sj_$wuid";
$path = upload_path($filename);
$f = fopen($path, "w");
if (!$f) {
error("Can't open $path");
}
fwrite($f,
"$job_dir
");
fclose($f);
}
function create_wu() {
global $wuid;
$name = md5(uniqid(rand(), true));
$wuid = BoincWorkunit::insert("(name, transition_time) values ('$name', ".PHP_INT_MAX.")");
}
function create_job() {
global $wuid, $app_name, $infiles_phys, $program_phys, $project_dir;
global $result_template_filename, $wu_template_filename;
global $wrapper_job_filename, $verbose;
chdir($project_dir);
$cmd = "bin/create_work --min_quorum 1 --target_nresults 1 --appname $app_name --wu_name sj_$wuid --wu_id $wuid --wu_template $wu_template_filename --result_template $result_template_filename";
foreach ($infiles_phys as $infile) {
$cmd .= " $infile";
}
$cmd .= " $wrapper_job_filename";
$cmd .= " $program_phys";
if ($verbose) {
echo "Executing command: $cmd\n";
}
system($cmd);
}
// copy input files and program file to the download hierarchy
//
function copy_files() {
global $infiles, $infiles_phys, $wuid, $job_dir, $program, $program_phys;
global $verbose;
chdir($job_dir);
foreach ($infiles as $infile) {
$filename = $infile.'_'.$wuid;
$infiles_phys[] = $filename;
$path = download_path($filename);
if ($verbose) {
echo "copying $infile to $path\n";
}
copy($infile, $path);
}
$path = download_path($program_phys);
if ($verbose) {
echo "copying $program to $path\n";
}
copy($program, $path);
}
// make sure the program is there, MD5 it, and get physical name
//
function check_program() {
global $program, $job_dir, $program_phys, $platform;
chdir($job_dir);
if (!is_file($program)) {
error("Program file $program not found");
}
$m = md5_file($program);
$m = substr($m, 0, 8);
$program_phys = $program.'_'.$platform.'_'.$m;
}
function parse_args($argc, $argv) {
global $platform, $infiles, $outfiles, $stdin_file, $stdout_file;
global $program, $cmdline_args, $wuid;
for ($i=1; $i<$argc; $i++) {
switch ($argv[$i]) {
case '--help':
usage();
case '--platform':
$platform = $argv[++$i];
break;
case '--infile':
$infiles[] = $argv[++$i];
break;
case '--outfile':
$outfiles[] = $argv[++$i];
break;
case '--stdin':
$stdin_file = $argv[++$i];
break;
case '--stdout':
$stdout_file = $argv[++$i];
break;
case '--verbose':
$verbose = true;
break;
case '--wait':
$wuid = $argv[++$i];
wait();
default:
if ($program) {
$cmdline_args .= ''.$argv[$i];
} else {
$program = $argv[$i];
}
break;
}
}
if (!$program) usage();
}
function show_result($result, $i) {
switch ($result->server_state) {
case 2:
echo " Instance $i: unsent\n";
break;
case 4:
echo " Instance $i: in progress on host $result->hostid\n";
break;
case 5:
echo " Instance $i: completed on host $result->hostid\n";
break;
}
}
function show_wu_status($wu) {
$now = date("F j, Y, g:i a e");
switch ($wu->assimilate_state) {
case 0:
echo "$now: job $wu->id is in progress\n";
$results = BoincResult::enum("workunitid=$wu->id");
$n = count($results);
if ($n) {
$i = 0;
foreach ($results as $result) {
show_result($result, $i);
$i++;
}
} else {
echo " (no instances yet)\n";
}
break;
case 1:
echo "$now: job $wu->id is being assimilated\n";
break;
case 2:
echo "$now: job $wu->id completed\n";
exit;
}
}
function wait() {
global $wuid;
while (1) {
$wu = BoincWorkunit::lookup_id($wuid);
if (!$wu) {
echo "Job $wuid is not in the database\n";
exit;
}
show_wu_status($wu);
sleep(10);
}
}
get_project_dir();
do_includes();
parse_args($argc, $argv);
check_app_version();
check_program();
create_wu();
make_wrapper_job_file();
make_job_file();
make_wu_template();
make_result_template();
copy_files();
create_job();
wait();
?>