2004-06-09 19:09:16 +00:00
|
|
|
<?php
|
2003-08-19 06:44:58 +00:00
|
|
|
require_once("docutil.php");
|
|
|
|
page_head("Generating work");
|
|
|
|
echo "
|
2005-01-02 07:44:40 +00:00
|
|
|
|
|
|
|
As described earlier, a <a href=work.php>workunit</a>
|
|
|
|
represents the inputs to a computation.
|
|
|
|
The steps in creating a workunit are:
|
|
|
|
<ul>
|
|
|
|
|
|
|
|
<li> Write XML 'template files' that describe the workunit
|
|
|
|
and its corresponding results.
|
|
|
|
Generally the same templates will be used for
|
|
|
|
a large number work of workunits.
|
|
|
|
|
|
|
|
<li> Create the workunit's input file(s)
|
|
|
|
and place them in the download directory.
|
|
|
|
|
2005-12-21 21:46:22 +00:00
|
|
|
<li> Invoke a BOINC function or script that creates a
|
2005-01-02 07:44:40 +00:00
|
|
|
database record for the workunit.
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
Once this is done, BOINC takes over:
|
|
|
|
it creates one or more results for the workunit,
|
|
|
|
distributes them to client hosts,
|
|
|
|
collects the output files,
|
|
|
|
finds a canonical result,
|
|
|
|
assimilates the canonical result,
|
|
|
|
and deletes files.
|
|
|
|
|
2002-05-24 04:29:10 +00:00
|
|
|
<p>
|
2005-01-02 07:44:40 +00:00
|
|
|
During the testing phase of a project,
|
2005-01-10 20:46:33 +00:00
|
|
|
you can use the <a href=busy_work.php>make_work</a> daemon
|
2005-01-02 07:44:40 +00:00
|
|
|
to replicate a given workunit as needed to maintain
|
|
|
|
a constant supply of work.
|
|
|
|
This is useful while testing and debugging the application.
|
|
|
|
|
2004-02-15 19:22:01 +00:00
|
|
|
|
2005-01-02 07:44:40 +00:00
|
|
|
<h2>Workunit and result template files</h2>
|
2006-10-11 16:32:59 +00:00
|
|
|
<a name=wu_template></a>
|
2002-05-24 04:29:10 +00:00
|
|
|
<p>
|
2005-01-02 07:44:40 +00:00
|
|
|
A workunit template file has the form
|
2004-02-09 05:11:05 +00:00
|
|
|
<pre>",htmlspecialchars("
|
2004-02-15 19:22:01 +00:00
|
|
|
<file_info>
|
|
|
|
<number>0</number>
|
2004-04-13 23:55:05 +00:00
|
|
|
[ <sticky/>, other attributes]
|
2004-02-15 19:22:01 +00:00
|
|
|
</file_info>
|
2003-08-15 22:19:25 +00:00
|
|
|
[ ... ]
|
2004-02-09 05:11:05 +00:00
|
|
|
<workunit>
|
2004-02-15 19:22:01 +00:00
|
|
|
<file_ref>
|
2004-04-13 23:55:05 +00:00
|
|
|
<file_number>0</file_number>
|
2004-02-15 19:22:01 +00:00
|
|
|
<open_name>NAME</open_name>
|
|
|
|
</file_ref>
|
|
|
|
[ ... ]
|
2004-02-09 05:11:05 +00:00
|
|
|
[ <command_line>-flags xyz</command_line> ]
|
2004-04-13 23:55:05 +00:00
|
|
|
[ <rsc_fpops_est>x</rsc_fpops_est> ]
|
|
|
|
[ <rsc_fpops_bound>x</rsc_fpops_bound> ]
|
2005-10-14 04:41:53 +00:00
|
|
|
[ <rsc_memory_bound>x</rsc_memory_bound> ]
|
|
|
|
[ <rsc_disk_bound>x</rsc_disk_bound> ]
|
2004-04-13 23:55:05 +00:00
|
|
|
[ <delay_bound>x</delay_bound> ]
|
|
|
|
[ <min_quorum>x</min_quorum> ]
|
|
|
|
[ <target_nresults>x</target_nresults> ]
|
|
|
|
[ <max_error_results>x</max_error_results> ]
|
|
|
|
[ <max_total_results>x</max_total_results> ]
|
2004-11-22 19:17:13 +00:00
|
|
|
[ <max_success_results>x</max_success_results> ]
|
2007-01-30 18:19:30 +00:00
|
|
|
[ <credit>X</credit> ]
|
2004-02-09 05:11:05 +00:00
|
|
|
</workunit>
|
|
|
|
"), "
|
2003-08-15 22:19:25 +00:00
|
|
|
</pre>
|
|
|
|
The components are:
|
2004-02-09 05:11:05 +00:00
|
|
|
";
|
|
|
|
list_start();
|
2007-01-30 18:19:30 +00:00
|
|
|
list_item_func("<file_info>, <file_ref>",
|
|
|
|
"Each pair describes an <a href=files.php#file>input file</a>
|
|
|
|
and <a href=files.php#file_ref>the way it's referenced</a>."
|
|
|
|
);
|
|
|
|
list_item_func("<command_line>",
|
|
|
|
"The command-line arguments to be passed to the main program."
|
|
|
|
);
|
|
|
|
list_item_func("<credit>",
|
|
|
|
"The amount of credit to be granted for successful completion
|
|
|
|
of this workunit.
|
|
|
|
Use this only if you know in advance
|
|
|
|
how many FLOPs it will take.
|
|
|
|
Your <a href=validate_simple.php>validator</a> must
|
|
|
|
use get_credit_from_wu() as its compute_granted_credit() function."
|
|
|
|
);
|
2004-04-13 23:55:05 +00:00
|
|
|
list_item("Other elements",
|
|
|
|
"<a href=work.php>Work unit attributes</a>"
|
|
|
|
);
|
2004-02-09 05:11:05 +00:00
|
|
|
list_end();
|
|
|
|
echo"
|
2005-12-21 21:46:22 +00:00
|
|
|
Workunit database records include a field, 'xml_doc',
|
|
|
|
that is an XML-format description of the workunit's input files.
|
|
|
|
This is derived from the workunit template as follows:
|
2002-05-24 04:29:10 +00:00
|
|
|
<ul>
|
2002-08-19 18:43:10 +00:00
|
|
|
<li>
|
2002-12-12 01:07:24 +00:00
|
|
|
Within a <file_info> element,
|
|
|
|
<number>x</number> identifies the order of the file.
|
|
|
|
It is replaced with elements giving
|
|
|
|
the filename, download URL, MD5 checksum, and size.
|
2002-08-19 18:43:10 +00:00
|
|
|
<li>
|
2002-12-12 01:07:24 +00:00
|
|
|
Within a <file_ref> element,
|
2004-04-13 23:55:05 +00:00
|
|
|
<file_number>x</file_number> is replaced with an element
|
|
|
|
giving the filename.
|
2002-05-24 04:29:10 +00:00
|
|
|
</ul>
|
2005-01-02 07:44:40 +00:00
|
|
|
|
2006-10-11 16:32:59 +00:00
|
|
|
<a name=result_template></a>
|
2004-02-15 19:22:01 +00:00
|
|
|
<p>
|
|
|
|
A result template file has the form
|
|
|
|
<pre>", htmlspecialchars("
|
|
|
|
<file_info>
|
|
|
|
<name><OUTFILE_0/></name>
|
|
|
|
<generated_locally/>
|
|
|
|
<upload_when_present/>
|
|
|
|
<max_nbytes>32768</max_nbytes>
|
|
|
|
<url><UPLOAD_URL/></url>
|
|
|
|
</file_info>
|
|
|
|
<result>
|
|
|
|
<file_ref>
|
|
|
|
<file_name><OUTFILE_0/></file_name>
|
|
|
|
<open_name>result.sah</open_name>
|
|
|
|
</file_ref>
|
|
|
|
</result>
|
|
|
|
"), "</pre>
|
2002-05-24 04:29:10 +00:00
|
|
|
<p>
|
2005-12-21 21:46:22 +00:00
|
|
|
Result database records include a field, 'xml_doc_in',
|
|
|
|
that is an XML-format description of the result's output files.
|
|
|
|
This is derived from the result template as follows:
|
2002-05-24 04:29:10 +00:00
|
|
|
<ul>
|
2002-08-19 18:43:10 +00:00
|
|
|
<li>
|
2002-11-07 19:31:34 +00:00
|
|
|
<OUTFILE_n> is replaced with a string of the form
|
2003-08-19 06:44:58 +00:00
|
|
|
'wuname_resultnum_n' where wuname is the workunit name and resultnum is
|
2002-07-29 19:01:38 +00:00
|
|
|
the ordinal number of the result (0, 1, ...).
|
2002-08-19 18:43:10 +00:00
|
|
|
<li>
|
2004-12-01 05:03:53 +00:00
|
|
|
<UPLOAD_URL/> is replaced with the upload URL.
|
2002-05-24 04:29:10 +00:00
|
|
|
</ul>
|
|
|
|
<p>
|
2005-01-02 07:44:40 +00:00
|
|
|
|
2005-01-02 08:19:43 +00:00
|
|
|
<h2>Moving input files to the download directory</h2>
|
2005-01-02 07:44:40 +00:00
|
|
|
|
2005-12-21 21:46:22 +00:00
|
|
|
If you're using a flat download directory,
|
|
|
|
just put input files in that directory.
|
2005-01-02 07:44:40 +00:00
|
|
|
If you're using <a href=hier_dir.php>hierarchical upload/download directories</a>,
|
2005-01-02 08:19:43 +00:00
|
|
|
you must put each input file in the appropriate directory;
|
2005-01-02 07:44:40 +00:00
|
|
|
the directory is determined by the file's name.
|
|
|
|
To find this directory, call the C++ function
|
|
|
|
<pre>
|
|
|
|
dir_hier_path(
|
2005-01-02 08:19:43 +00:00
|
|
|
const char* filename,
|
|
|
|
const char* root, // root of download directory
|
|
|
|
int fanout, // from config.xml
|
2006-04-04 20:03:59 +00:00
|
|
|
char* result, // path of file in hierarchy
|
|
|
|
bool create_dir=false // create dir if it's not there
|
2005-01-02 08:19:43 +00:00
|
|
|
);
|
2005-01-02 07:44:40 +00:00
|
|
|
</pre>
|
|
|
|
If you're using scripts, you can invoke the program
|
|
|
|
<pre>
|
2005-01-02 08:19:43 +00:00
|
|
|
dir_hier_path filename
|
2005-01-02 07:44:40 +00:00
|
|
|
</pre>
|
2006-04-04 20:03:59 +00:00
|
|
|
It prints the full pathname and creates the directory if needed.
|
2005-01-02 08:19:43 +00:00
|
|
|
Run this in the project's root directory.
|
2005-02-01 21:11:08 +00:00
|
|
|
For example:
|
|
|
|
<pre>
|
|
|
|
cp test_workunits/12ja04aa `bin/dir_hier_path 12ja04aa`
|
|
|
|
</pre>
|
|
|
|
copies an input file from the test_workunits directory
|
|
|
|
to the download directory hierarchy.
|
2005-01-02 07:44:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
<h2>Creating workunit records</h2>
|
|
|
|
<p>
|
|
|
|
Workunits can be created using either a script
|
2005-02-01 21:11:08 +00:00
|
|
|
(using the <code>create_work</code> program)
|
2005-01-02 07:44:40 +00:00
|
|
|
or a program (using the <code>create_work()</code> function).
|
2005-06-14 20:31:15 +00:00
|
|
|
The input files must already be in the download hierarchy.
|
|
|
|
|
2004-02-09 05:11:05 +00:00
|
|
|
<p>
|
|
|
|
The utility program is
|
|
|
|
<pre>
|
|
|
|
create_work
|
2004-07-10 07:27:00 +00:00
|
|
|
-appname name // application name
|
|
|
|
-wu_name name // workunit name
|
|
|
|
-wu_template filename // WU template filename
|
2005-12-21 21:46:22 +00:00
|
|
|
// relative to project root; usually in templates/
|
2004-07-10 07:27:00 +00:00
|
|
|
-result_template filename // result template filename
|
2005-12-21 21:46:22 +00:00
|
|
|
// relative to project root; usually in templates/
|
2004-11-25 07:47:52 +00:00
|
|
|
[ -batch n ]
|
|
|
|
[ -priority n ]
|
2004-04-13 23:55:05 +00:00
|
|
|
|
2005-12-21 21:46:22 +00:00
|
|
|
// The following may be passed in the WU template,
|
|
|
|
// or as command-line arguments to create_work,
|
|
|
|
// or not passed at all (defaults will be used)
|
|
|
|
|
|
|
|
[ -command_line \"-flags foo\" ]
|
2004-02-15 19:22:01 +00:00
|
|
|
[ -rsc_fpops_est x ]
|
|
|
|
[ -rsc_fpops_bound x ]
|
|
|
|
[ -rsc_memory_bound x ]
|
|
|
|
[ -rsc_disk_bound x ]
|
|
|
|
[ -delay_bound x ]
|
|
|
|
[ -min_quorum x ]
|
|
|
|
[ -target_nresults x ]
|
|
|
|
[ -max_error_results x ]
|
|
|
|
[ -max_total_results x ]
|
|
|
|
[ -max_success_results x ]
|
2007-01-30 18:19:30 +00:00
|
|
|
[ -additional_xml 'x' ]
|
2004-04-13 23:55:05 +00:00
|
|
|
|
2004-02-09 05:11:05 +00:00
|
|
|
infile_1 ... infile_m // input files
|
|
|
|
</pre>
|
2005-02-01 21:11:08 +00:00
|
|
|
The program must be run in the project root directory.
|
2007-01-30 18:19:30 +00:00
|
|
|
The workunit parameters are documented <a href=work.php>here</a>.
|
|
|
|
The -additional_xml argument can be used to supply, for example,
|
|
|
|
<credit>12.4</credit>.
|
2004-02-15 19:22:01 +00:00
|
|
|
|
2002-05-24 04:29:10 +00:00
|
|
|
<p>
|
2005-12-21 21:46:22 +00:00
|
|
|
BOINC's library (backend_lib.C,h) provides the functions:
|
2002-05-24 04:29:10 +00:00
|
|
|
<pre>
|
|
|
|
int create_work(
|
2004-07-10 07:27:00 +00:00
|
|
|
DB_WORKUNIT&,
|
|
|
|
const char* wu_template, // contents, not path
|
|
|
|
const char* result_template_filename, // relative to project root
|
2005-10-29 20:16:07 +00:00
|
|
|
const char* result_template_filepath, // absolute or relative to current dir
|
2004-07-10 07:27:00 +00:00
|
|
|
const char** infiles, // array of input file names
|
2002-05-24 04:29:10 +00:00
|
|
|
int ninfiles
|
2005-10-29 20:16:07 +00:00
|
|
|
SCHED_CONFIG&,
|
2007-01-30 18:19:30 +00:00
|
|
|
const char* command_line = NULL,
|
|
|
|
const char* additional_xml = NULL
|
2002-05-24 04:29:10 +00:00
|
|
|
);
|
2002-11-07 19:31:34 +00:00
|
|
|
</pre>
|
2002-05-24 04:29:10 +00:00
|
|
|
<p>
|
2005-10-29 20:16:07 +00:00
|
|
|
<b>create_work()</b> creates a workunit.
|
2002-11-07 19:31:34 +00:00
|
|
|
The arguments are similar to those of the utility program;
|
2005-10-29 20:16:07 +00:00
|
|
|
some of the information is passed in the DB_WORKUNIT structure,
|
2003-01-09 21:48:33 +00:00
|
|
|
namely the following fields:
|
|
|
|
<pre>
|
|
|
|
name
|
2003-01-14 23:50:33 +00:00
|
|
|
appid
|
2005-10-29 20:16:07 +00:00
|
|
|
</pre>
|
|
|
|
The following may be passed either in the DB_WORKUNIT structure
|
|
|
|
or in the workunit template file:
|
|
|
|
<pre>
|
|
|
|
rsc_fpops_est
|
|
|
|
rsc_fpops_bound
|
|
|
|
rsc_memory_bound
|
|
|
|
rsc_disk_bound
|
2003-01-14 23:50:33 +00:00
|
|
|
batch
|
2003-01-09 21:48:33 +00:00
|
|
|
delay_bound
|
2005-10-29 20:16:07 +00:00
|
|
|
min_quorum
|
|
|
|
target_nresults
|
|
|
|
max_error_results
|
|
|
|
max_total_results
|
|
|
|
max_success_results
|
2003-01-09 21:48:33 +00:00
|
|
|
</pre>
|
2004-04-13 21:31:55 +00:00
|
|
|
|
2005-12-21 21:46:22 +00:00
|
|
|
<h2>Examples</h2>
|
|
|
|
<h3>Making one workunit</h3>
|
2005-10-29 20:16:07 +00:00
|
|
|
<p>
|
2005-12-21 21:46:22 +00:00
|
|
|
Here's a program that generates one workunit
|
|
|
|
(error-checking is omitted for clarity):
|
2006-06-05 04:30:16 +00:00
|
|
|
"; block_start(); echo "
|
2005-10-29 20:16:07 +00:00
|
|
|
#include \"backend_lib.h\"
|
|
|
|
|
|
|
|
main() {
|
|
|
|
DB_APP app;
|
|
|
|
DB_WORKUNIT wu;
|
|
|
|
char wu_template[LARGE_BLOB_SIZE];
|
|
|
|
char* infiles[] = {\"infile\"};
|
|
|
|
|
|
|
|
SCHED_CONFIG config;
|
|
|
|
config.parse_file();
|
|
|
|
|
|
|
|
boinc_db.open(config.db_name, config.db_host, config.db_passwd);
|
|
|
|
app.lookup(\"where name='myappname'\");
|
|
|
|
|
|
|
|
wu.clear(); // zeroes all fields
|
|
|
|
wu.appid = app.id;
|
|
|
|
wu.min_quorum = 2;
|
|
|
|
wu.target_nresults = 2;
|
|
|
|
wu.max_error_results = 5;
|
|
|
|
wu.max_total_results = 5;
|
|
|
|
wu.max_success_results = 5;
|
|
|
|
wu.rsc_fpops_est = 1e10;
|
|
|
|
wu.rsc_fpops_bound = 1e11;
|
|
|
|
wu.rsc_memory_bound = 1e8;
|
|
|
|
wu.rsc_disk_bound = 1e8;
|
|
|
|
wu.delay_bound = 7*86400;
|
|
|
|
read_filename(\"templates/wu_template.xml\", wu_template, sizeof(wu_template));
|
|
|
|
create_work(
|
|
|
|
wu,
|
|
|
|
wu_template,
|
|
|
|
\"templates/results_template.xml\",
|
|
|
|
\"templates/results_template.xml\",
|
|
|
|
infiles,
|
|
|
|
1,
|
|
|
|
config
|
|
|
|
);
|
|
|
|
}
|
2006-06-05 04:30:16 +00:00
|
|
|
"; block_end(); echo "
|
2005-10-29 20:16:07 +00:00
|
|
|
|
|
|
|
This program must be run in the project directory
|
|
|
|
since it expects to find the config.xml file in the current directory.
|
2005-12-21 21:46:22 +00:00
|
|
|
|
|
|
|
<h3>Making lots of workunits</h3>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
If you're making lots of workunits
|
|
|
|
(e.g. to do the various parts of a parallel computation)
|
|
|
|
you'll want the workunits to differ either in
|
|
|
|
their input files, their command-line arguments, or both.
|
|
|
|
|
|
|
|
<p>
|
|
|
|
For example, let's say you want to run a program
|
2006-01-16 06:23:14 +00:00
|
|
|
on ten input files 'file0', 'file1', ..., 'file9'.
|
2005-12-21 21:46:22 +00:00
|
|
|
You might modify the above program with the following code:
|
2006-06-05 04:30:16 +00:00
|
|
|
"; block_start(); echo "
|
2005-12-21 21:46:22 +00:00
|
|
|
char filename[256];
|
|
|
|
char* infiles[1];
|
|
|
|
infiles[0] = filename;
|
|
|
|
...
|
|
|
|
for (i=0; i<10; i++) {
|
|
|
|
sprintf(filename, \"file%d\", i);
|
|
|
|
create_work(
|
|
|
|
wu,
|
|
|
|
wu_template,
|
|
|
|
\"templates/results_template.xml\",
|
|
|
|
\"templates/results_template.xml\",
|
|
|
|
infiles,
|
|
|
|
1,
|
|
|
|
config
|
|
|
|
);
|
|
|
|
}
|
2006-06-05 04:30:16 +00:00
|
|
|
"; block_end(); echo "
|
2005-12-21 21:46:22 +00:00
|
|
|
Note that you only need one workunit template file
|
|
|
|
and one result template file.
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Now suppose you want to run a program against
|
|
|
|
a single input file, but with ten command lines,
|
|
|
|
'-flag 0', '-flag 1', ..., '-flag 9'.
|
|
|
|
You might modify the above program with the following code:
|
2006-06-05 04:30:16 +00:00
|
|
|
"; block_start(); echo "
|
2005-12-21 21:46:22 +00:00
|
|
|
char command_line[256];
|
|
|
|
...
|
|
|
|
for (i=0; i<10; i++) {
|
|
|
|
sprintf(command_line, \"-flag %d\", i);
|
|
|
|
create_work(
|
|
|
|
wu,
|
|
|
|
wu_template,
|
|
|
|
\"templates/results_template.xml\",
|
|
|
|
\"templates/results_template.xml\",
|
|
|
|
infiles,
|
|
|
|
1,
|
|
|
|
config,
|
|
|
|
command_line
|
|
|
|
);
|
|
|
|
}
|
2006-06-05 04:30:16 +00:00
|
|
|
"; block_end(); echo "
|
2005-12-21 21:46:22 +00:00
|
|
|
Again, you only need one workunit template file
|
|
|
|
and one result template file.
|
2003-08-19 06:44:58 +00:00
|
|
|
";
|
2004-04-13 21:31:55 +00:00
|
|
|
|
2003-08-19 06:44:58 +00:00
|
|
|
page_tail();
|
|
|
|
?>
|