wiki:BossaImplementation

Version 10 (modified by davea, 16 years ago) (diff)

--

Bossa implementation notes

Database tables

Until Bossa has good web-based administration tools, you'll often need to directly examine and modify its MySQL database, using the command-line tool 'mysql' or a web-based interface such as phpMyAdmin.

The database tables used by Bossa (in addition to BOINC's tables for users, teams, etc.) are as follows:

bossa_app:

field name type meaning
id integer row ID, assigned by MySQL
create_time integer row creation time
name varchar(255) short name (internal use; no spaces)
user_friendly_name varchar(255) user-visible name (spaces OK)
long_jobs tinyint nonzero if user can have > 1 active job
start_url varchar(255) name (relative to project URL) of start script
deprecated tinyint nonzero if deprecated (don't show)
info text information (typically encoded in JSON) such as the criteria for which users to issue jobs to

bossa_job:

field name type meaning
id integer row ID, assigned by MySQL
create_time integer row creation time
name varchar(255) a unique name for this job
app_id integer ID of bossa_app
info text job-specific info (file names etc.) typically JSON-encoded
batch integer batch number (use to group jobs)
time_estimate integer number of seconds this job is likely to take
time_limit integer give up if not completed after this number of seconds
more_needed tinyint nonzero if more completed instances of this job are needed
npending integer number of pending instances
nsuccess integer number of successfully completed instances
nsuccess_needed integer required number of successfully completed instances

bossa_job_inst:

field name type meaning
id integer row ID, assigned by MySQL
create_time integer row creation time
job_id integer ID of bossa_job
user_id integer ID of user
finish_time integer time when finished, or zero
info text outcome info (usually JSON-encoded)

bossa_app_user:

app_id integer ID of bossa_app
user_id integer ID of user
info text description of the user's skill or ranking at a given app, typically JSON-encoded

Bossa PHP classes

Bossa provides the following classes (in html/inc/bossa.inc and html/inc/bossa_db.inc):

BossaApp, BossaJob, BossaJobInst
These correspond to the above tables, and have fields corresponding to each database field. They offer functions to insert, look up, and modify database rows.
Bossa
Utility functions.

Creating a Bossa project

First, set up a BOINC server and create a project. You'll need PHP 5.2 or later (for JSON functions). Say your project is called test_project, your BOINC source directory is ~/boinc, and your BOINC projects directory is ~/projects.

Create Bossa's database tables as follows:

cd ~/boinc/db
mysql test_project < bossa_schema.sql
mysql test_project < bossa_constraints.sql

Create a Bossa application as follows:

cd ~/projects/test_project/html/ops
php bossa_setup_example.php

bossa_setup_example.php contains:

$ba = new BossaApp();
$ba->name = 'bossa_test';
$ba->user_friendly_name = 'Simple pattern recognition';
$ba->start_url = 'bossa_example.php';

if ($ba->insert($ba)) {
    echo "Added application '$ba->name'\n";
} else {
    echo "Couldn't add '$ba->name': ", mysql_error(), "\n";
}

You can edit this to change the application name and front-end script name, if you like.

Adding jobs

Typically you'll add jobs using a script. Here's an example (html/ops/bossa_make_jobs_example.php):

     1  <?php
     2
     3  require_once("../inc/bossa_db.inc");
     4  require_once("../inc/db.inc");
     5
     6  db_init();
     7
     8  function make_jobs() {
     9      $appname = 'bossa_test';
    10      $app = BossaApp::lookup_name($appname);
    11      if (!$app) {
    12          echo "Application $appname not found\n";
    13          exit(1);
    14      }
    15      $job = new BossaJob;
    16      $job->app_id = $app->id;
    17      $job->batch = 0;
    18      $job->time_estimate = 30;
    19      $job->time_limit = 600;
    20      $job->nsuccess_needed = 3;
    21      for ($i=0; $i<10; $i++) {
    22          $job->name = "job_$i";
    23          $info = null;
    24          $info->number = $i % 2;
    25          $job->info = json_encode($info);
    26          if (!$job->insert()) {
    27              echo "BossaJob::insert failed: ", mysql_error(), "\n";
    28              exit(1);
    29          }
    30      }
    31  }
    32
    33  make_jobs();
    34  echo "All done.\n";
    35
    36  ?>

This creates 10 jobs. Each job has an info field consisting of a JSON-encoded structure consisting of an integer (0 or 1).

Front-end scripts

You develop a front-end script to show a job instance to a user, and to handle a completed instance. It's handy to put both of these functions in a single file. A front-end script is called with the URL parameter bji set to a job instance ID. Here's an example (html/user/bossa_example.php):

     1  <?php
     2
     3  require_once("../inc/bossa.inc");
     4
     5  echo "foo";
     6
     7  // Bossa example.
     8  // Show the user an image and ask them whether it's a zero or one.
     9
    10  function show_job($bj, $bji) {
    11      if ($bji->finish_time) {
    12          error_page("You already finished this job");
    13      }
    14      $info = json_decode($bj->info);
    15      $img_url = "http://boinc.berkeley.edu/images/number_".$info->number.".jpg";
    16      echo "
    17          <form method=get action=bossa_example.php>
    18          <input type=hidden name=bji value=$bji->id>
    19          <img src=$img_url>
    20          <br>
    21          The picture shows a
    22          <br><input type=radio name=response value=0> zero
    23          <br><input type=radio name=response value=1> one
    24          <br><input type=radio name=response value=2 checked> not sure
    25          <br><br><input type=submit name=submit value=OK>
    26          </form>
    27      ";
    28  }
    29
    30  function handle_job_completion($bj, $bji) {
    31      $response = null;
    32      $response->number = get_int('response');
    33      $bji->info = json_encode($response);
    34      $bji->completed($bj);
    35
    36      // show another job immediately
    37      //
    38      Bossa::show_next_job($bj);
    39  }
    40
    41  Bossa::script_init($user, $bj, $bji);
    42
    43  if ($_GET['submit']) {
    44      handle_job_completion($bj, $bji);
    45  } else {
    46      show_job($bj, $bji);
    47  }
    48
    49  ?>
Line 41
Call a Bossa utility function to look up the job instance and make sure that it was issued to the logged-in user. The job instance, job, and user are returned.
Line 43
Branch according to whether we are showing a job or handling the completion of a job.
Line 14
If we're showing a job, decode its info structure to decide whether to show which picture to show.
Lines 17-18
Task completion will be handled by this script; arrange to pass the job instance ID.
Lines 31-33
Get the user's response, and encode it in JSON.
Line 34
Call a utility function that marks the job instance as completed and updates its database record.
Line 38
Call a utility function that gets another job (if one is available) and shows it to the user.