| Version 10 (modified by , 17 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.
