svn path=/trunk/boinc/; revision=14730

This commit is contained in:
David Anderson 2008-02-13 04:25:52 +00:00
parent 51764d5abc
commit b543bcc3c4
12 changed files with 224 additions and 67 deletions

View File

@ -1335,3 +1335,7 @@ David Feb 12 2008
lib/
common_defs.h
util.C,h
David Feb 12 2008
lib/
str_util.h

View File

@ -296,6 +296,7 @@ language("Slovak", array(
site("http://www.boinc.sk/", "www.boinc.sk")
));
language("Spanish", array(
site("http://foro.noticias3d.com/vbulletin/showthread.php?t=192297", "Noticias3D"),
site("http://elmajo.blogspot.com", "Computación Distribuida"),
site("http://efren-canarias.blogcindario.com/", "El Pais De La Computacion"),
site("http://www.canalboinc.org/modules/news/", "Canal BOINC"),

View File

@ -43,7 +43,7 @@ The colors are based on U.C. Berkeley's blue-and-gold colors.
<li> <a href=logo/boinc_logo.ai>Adobe Illustrator (.ai)</a>
<li> <a href=logo/boinc_logo.cdr>Vector graphics (.cdr)</a>
<li> <a href=logo/boinc_logo.pdf>Adobe PDF (.cdr)</a>
<li> <a href=logo/boinc_logo.svg>Scalable Vector Graphics (.svg)</a>
<li> <a href=logo/boinc_logo_ai.svg>Scalable Vector Graphics (.svg)</a>
<li> <a href=logo/boinc_logo.png>1280x535, transparent background (.png)</a>
<li> <a href=logo/boinc_logo.wmf>Windows meta-file (.wmf)</a>
<li> <a href=logo/favicon.gif>Favicon (GIFF)</a>

View File

@ -70,7 +70,7 @@ class BoltDb extends DbConn {
class BoltUser {
static $cache;
static function lookup_userid($id) {
$db = BoincDb::get();
$db = BoltDb::get();
return $db->lookup('bolt_user', 'BoltUser', "user_id=$id");
}
static function insert($clause) {

View File

@ -3,6 +3,10 @@
require_once("../inc/db_conn.inc");
require_once("../inc/util.inc");
define ('VALIDATE_STATE_INIT', 0);
define ('VALIDATE_STATE_VALID', 1);
define ('VALIDATE_STATE_INVALID', 2);
class BossaDb extends DbConn {
public static $instance;
@ -28,15 +32,47 @@ class BossaDb extends DbConn {
}
}
class BossaUser {
static $cache;
static function lookup_userid($id) {
$db = BossaDb::get();
return $db->lookup('bossa_user', 'BossaUser', "user_id=$id");
}
static function insert($clause) {
$db = BossaDb::get();
return $db->insert('bossa_user', $clause);
}
static function lookup(&$user) {
if (!$user) return;
if (isset($user->bossa)) return;
if (isset(self::$cache[$user->id])) {
$bossa = self::$cache[$user->id];
} else {
$bossa = self::lookup_userid($user->id);
if (!$bossa) {
self::insert("(user_id) values ($user->id)");
$bossa = self::lookup_userid($user->id);
}
self::$cache[$user->id] = $bossa;
}
$user->bossa = $bossa;
}
function update($clause) {
$db = BossaDb::get();
$clause = "$clause where user_id=$this->user_id";
return $db->update_aux('bossa_user', $clause);
}
}
class BossaApp {
function insert($clause) {
$db = BossaDb::get();
return $db->insert('bossa_app', $clause);
}
static function lookup_name($name) {
static function lookup_short_name($name) {
$db = BossaDb::get();
return $db->lookup('bossa_app', 'BossaApp', "name='$name'");
return $db->lookup('bossa_app', 'BossaApp', "short_name='$name'");
}
static function lookup_id($id) {
@ -54,7 +90,7 @@ class BossaJob {
function insert() {
$db = BossaDb::get();
$now = time();
$query = "insert into DBNAME.bossa_job (create_time, name, app_id, info, batch, time_estimate, time_limit, nneeded) values ($now, '$this->name', $this->app_id, '$this->info', $this->batch, $this->time_estimate, $this->time_limit, $this->nneeded)";
$query = "insert into DBNAME.bossa_job (create_time, name, app_id, info, batch, time_estimate, time_limit, conf_needed) values ($now, '$this->name', $this->app_id, '$this->info', $this->batch, $this->time_estimate, $this->time_limit, $this->conf_needed)";
$result = $db->do_query($query);
if (!$result) {
echo "$query\n";
@ -114,7 +150,7 @@ class BossaJobInst {
//
// TODO: put the following in a transaction
$db = BossaDb::get();
$query = "select bossa_job.* from DBNAME.bossa_job left join DBNAME.bossa_job_inst on bossa_job_inst.job_id = bossa_job.id where bossa_job.nneeded>0 and bossa_job_inst.user_id is null limit 1";
$query = "select bossa_job.* from DBNAME.bossa_job left join DBNAME.bossa_job_inst on bossa_job_inst.job_id = bossa_job.id where bossa_job.conf_needed>0 and bossa_job_inst.user_id is null limit 1";
$result = $db->do_query($query);
if (!$result) return null;
$job = mysql_fetch_object($result, 'BossaJob');
@ -130,7 +166,8 @@ class BossaJobInst {
return null;
}
$job->update("nneeded=nneeded-1");
// TODO: replace "1"
$job->update("conf_needed=conf_needed-1");
return $ji;
}

View File

@ -31,7 +31,7 @@ function ellipse_handle($bj, $c) {
$res->cy /= count($c);
}
$info = json_decode[$bj->info);
$info = json_decode($bj->info);
$info->result = $res;
$i = json_encode($info);
$bj->update("info='$i'");

View File

@ -13,17 +13,19 @@ function show_bapp($app) {
<td>
";
if ($app->hidden) {
show_button("bossa_ops.php?action=unhide&app_id=$app->id", "Unhide", "Unhide this app");
show_button("bossa_admin.php?action=unhide&app_id=$app->id", "Unhide", "Unhide this app");
} else {
show_button("bossa_ops.php?action=hide&app_id=$app->id", "Hide", "Hide this app");
show_button("bossa_admin.php?action=hide&app_id=$app->id", "Hide", "Hide this app");
echo "<br>";
show_button($app->short_name."_workgen.php?njobs=10", "Create jobs", "Create 10 new jobs");
}
}
function show_apps() {
$apps = BossaApp::enum();
start_table();
row1("Existing apps", 4);
table_header("Name/description", "Display script", "Backend script", "");
row1("Existing apps", 2);
table_header("Name/description", "");
foreach ($apps as $app) {
show_bapp($app);
}
@ -32,7 +34,7 @@ function show_apps() {
function add_app_form() {
echo "
<form action=bossa_ops.php method=get>
<form action=bossa_admin.php method=get>
";
start_table();
row1("Add app");
@ -50,7 +52,7 @@ function add_app_form() {
function user_settings() {
global $user;
$flags = $user->bossa->flags;
echo "<form action=bossa_ops.php method=get>";
echo "<form action=bossa_admin.php method=get>";
start_table();
row1("User settings");
$x = ($flags&BOLT_FLAGS_SHOW_ALL)?"checked":"";
@ -72,20 +74,45 @@ function show_all() {
admin_page_tail();
}
function show_jobs($app_id) {
$app = BossaApp::lookup_id($app_id);
echo "<h2>Jobs for $app->user_friendly_name</h2>";
$jobs = BossaJob::enum("app_id=$app_id");
foreach ($jobs as $job) {
echo "<pre>\n";
print_r($job);
echo "</pre>\n";
echo "
<a href=bossa_admin.php?cmd=show_insts&job_id=$job->id>Show instances</a>
<hr>
";
}
}
function show_insts($job_id) {
echo "<h2>Job instances</h2>";
$jis = BossaJobInst::enum("job_id=$job_id");
foreach ($jis as $ji) {
echo "<pre>\n";
print_r($ji);
echo "</pre><hr>\n";
}
}
$user = get_logged_in_user();
$submit = get_str('submit', true);
if ($submit == 'Create app') {
$name = BossaDb::escape_string(get_str('app_name'));
$short_name = get_str('short_name');
$description = BossaDb::escape_string(get_str('description'));
$display_script = get_str('display_script');
$backend_script = get_str('backend_script');
$min_conf_sum = get_str('min_conf_sum');
$min_conf_frac = get_str('min_conf_frac');
$max_instances = get_str('max_instances');
$now = time();
BossaApp::insert("(create_time, name, description, display_script, backend_script, min_conf_sum, min_conf_frac, max_instances) values ($now, '$name', '$description', '$display_script', '$backend_script', $min_conf_sum, $min_conf_frac, $max_instances)");
Header('Location: bossa_ops.php');
BossaApp::insert("(create_time, name, short_name, description, min_conf_sum, min_conf_frac, max_instances) values ($now, '$name', '$short_name', '$description', $min_conf_sum, $min_conf_frac, $max_instances)");
Header('Location: bossa_admin.php');
exit();
} else if ($submit == 'Update user') {
$flags = 0;
@ -93,8 +120,14 @@ if ($submit == 'Create app') {
if (get_str('debug', true)) $flags |= BOLT_FLAGS_DEBUG;
$user->bossa->update("flags=$flags");
$user->bossa->flags = $flags;
Header('Location: bossa_ops.php');
Header('Location: bossa_admin.php');
exit();
} else if ($cmd == 'show_jobs') {
$app_id = $_GET['app_id'];
show_jobs($app_id);
} else if ($cmd == 'show_insts') {
$job_id = $_GET['job_id'];
show_insts($job_id);
} else {
$action = get_str('action', true);
if ($action) {
@ -111,7 +144,7 @@ if ($submit == 'Create app') {
default:
error_page("unknown action $action");
}
Header('Location: bossa_ops.php');
Header('Location: bossa_admin.php');
exit();
}
}

View File

@ -0,0 +1,119 @@
<?php
require_once("../inc/util.inc");
require_once("../inc/bossa_db.inc");
require_once("../inc/dir_hier.inc");
function rand_color($im, $range) {
$mid = 200;
$lo = $mid - $range;
$hi = $mid + $range;
return imagecolorallocate($im, rand($lo,$hi), rand($lo,$hi), rand($lo,$hi));
}
function add_ellipse($im, $case) {
imagefilledellipse(
$im, $case->cx, $case->cy, $case->w, $case->h, rand_color($im, 50)
);
}
function add_rect($im) {
$cx = rand(-100, 600);
$cy = rand(-100, 400);
$w = rand(50, 100);
$h = rand(50, 100);
imagefilledrectangle($im, $cx, $cy, $cx+$w, $cy+$h, rand_color($im, 50));
}
function make_image($case) {
$im = imagecreatetruecolor(600, 400);
imagefill($im, 0, 0, imagecolorallocate($im, 255, 255, 255));
for ($i=0; $i<400; $i++) {
add_rect($im);
}
$im2 = imagecreatetruecolor(600, 400);
imagefill($im2, 0, 0, rand_color($im2, 0));
if ($case->have_ellipse) {
add_ellipse($im2, $case);
}
imagecopymerge($im, $im2, 0, 0, 0, 0, 600, 400, 30);
return $im;
}
function make_test_case() {
$case = null;
$case->have_ellipse = rand(0, 1);
if ($case->have_ellipse) {
$case->cx = rand(50, 550);
$case->cy = rand(50, 350);
$case->w = rand(50, 100);
$case->h = rand(50, 100);
}
return $case;
}
function make_job($app, $batch, $i, $config) {
// create the image file;
// store it in the download directory hierarchy
//
$jobname = "job_$batch_$i";
$filename = "$jobname.png";
$path = dir_hier_path(
$filename, $config->download_dir, $config->uldl_dir_fanout
);
$url = dir_hier_url(
$filename, $config->download_url, $config->uldl_dir_fanout
);
$case = make_test_case();
imagepng(make_image($case), $path);
$case->url = $url;
// make a job record in the Bossa database
//
$job = new BossaJob;
$job->app_id = $app->id;
$job->batch = $batch;
$job->time_estimate = 30;
$job->time_limit = 600;
$job->name = $jobname;
$job->info = json_encode($case);
$job->conf_needed = $app->min_conf_sum;
if (!$job->insert()) {
echo "BossaJob::insert failed: ", mysql_error(), "\n";
exit(1);
}
}
function make_jobs($njobs) {
$c = get_config();
$config = null;
$config->download_dir = parse_config($c, "<download_dir>");
$config->download_url = parse_config($c, "<download_url>");
$config->uldl_dir_fanout = parse_config($c, "<uldl_dir_fanout>");
$appname = "bossa_example";
$app = BossaApp::lookup_short_name($appname);
if (!$app) {
echo "Application $appname not found\n";
exit(1);
}
$batch = time();
for ($i=0; $i<$njobs; $i++) {
make_job($app, $batch, $i, $config);
}
echo "Created $njobs jobs
<p>
<a href=bossa_admin.php>Bossa Admin</a>
";
}
$njobs = get_int('njobs', true);
if ($njobs) {
make_jobs($njobs);
} else {
header ("Content-type: image/png");
imagepng(make_image(make_test_case()));
}
?>

View File

@ -1,33 +0,0 @@
<?php
require_once("../inc/bossa_db.inc");
function make_jobs() {
$appname = 'bossa_test';
$app = BossaApp::lookup_name($appname);
if (!$app) {
echo "Application $appname not found\n";
exit(1);
}
$job = new BossaJob;
$job->app_id = $app->id;
$job->batch = 0;
$job->time_estimate = 30;
$job->time_limit = 600;
$job->nsuccess_needed = 3;
for ($i=0; $i<10; $i++) {
$job->name = "job_$i";
$info = null;
$info->number = $i % 2;
$job->info = json_encode($info);
if (!$job->insert()) {
echo "BossaJob::insert failed: ", mysql_error(), "\n";
exit(1);
}
}
}
make_jobs();
echo "All done.\n";
?>

View File

@ -2,9 +2,7 @@
require_once("../inc/bossa_db.inc");
var $apps;
function lookup_app($id) {
function lookup_bapp($id) {
global $apps;
foreach ($apps as $app) {
if ($app->id == $id) return $app;
@ -33,6 +31,7 @@ function total_confidence($instances) {
if (!$i->finished_time) continue;
$sum += $i->conf;
}
return $sum;
}
// See if there's a canonical instance.
@ -55,7 +54,7 @@ function find_canonical($instances, $total_conf, &$max_conf) {
return $best;
}
function get_confidence(&$instances) {
function get_confidences(&$instances) {
foreach ($instances as $inst) {
$user = BoincUser::lookup_id($inst->user_id);
BossaUser::lookup($user);
@ -68,7 +67,7 @@ function get_confidence(&$instances) {
// 2) an instance has timed out
//
function handle_job($job) {
$app = lookup_app($job->app_id);
$app = lookup_bapp($job->app_id);
if (!$app) {
echo "Missing app: $job->app_id\n";
return;
@ -95,7 +94,7 @@ function handle_job($job) {
// If we have enough total confidence, check for consensus
//
get_confidences($instances);
$total_conf = total_confidence(instances);
$total_conf = total_confidence($instances);
if ($total_conf >= $app->min_conf_sum) {
$inst = find_canonical($instances, $total_conf, $max_conf);
}
@ -114,7 +113,7 @@ function main() {
global $apps;
$apps = BossaApp::enum();
foreach ($apps as $app) {
$bs = "../lib/".$app->short_name."_backend.inc";
$bs = "../inc/".$app->short_name.".inc";
require_once($bs);
}
while (1) {
@ -123,4 +122,5 @@ function main() {
}
main();
echo "foo";
?>

View File

@ -17,7 +17,7 @@ if (!$app) {
$ji = BossaJobInst::assign($app, $user);
if ($ji) {
$url = $app->display_script."?bji=$ji->id";
$url = $app->short_name.".php?bji=$ji->id";
Header("Location: $url");
} else {
page_head("No jobs available");

View File

@ -70,13 +70,9 @@ inline bool starts_with(std::string const& s, std::string const& prefix) {
}
inline void downcase_string(std::string& w) {
char buf[1024];
strlcpy(buf, w.c_str(), sizeof(buf));
size_t n = strlen(buf);
for (size_t i=0; i<n; i++) {
buf[i] = tolower(buf[i]);
for (std::string::iterator p = w.begin(); p != w.end(); ++p) {
*p = tolower(*p);
}
w = buf;
}
// convert UNIX time to MySQL timestamp (yyyymmddhhmmss)