The BOINC Application Programming Interface
Porting Your Application to BOINC
Porting an application to function on the BOINC platform is fairly
easy. The BOINC API provides a set of C/C++ functions which should be
called as described below to ensure proper integration with the BOINC
core client. If the provided BOINC API is not used, users should
write their own. The only aspect of the API that is required is
to resolve BOINC soft links, ignoring the rest of the features should
still allow the application to function, albeit somewhat unpredictably.
-
BOINC Initialization
Functions:
-
void boinc_init(APP_IN& ai, int opengl_support);
When the application starts, it should call boinc_init before
performing any computation. boinc_init performs several important
functions necessary for proper communication between the application and
the core client. First, it reads the general preferences from the BOINC
core client, which contain information about graphics, checkpointing,
and CPU time. Based on these preferences, it initializes timers for
graphics redraw and checkpoint purposes, and prepares the OpenGL window
(if desired) for graphics display. If the application supports OpenGL
graphics, opengl_support should be 1 and an appropriate draw_gl
function should be included in the application. If the application does not
support OpenGL graphics, opengl_support should be 0 and an empty
draw_gl should be included.
-
Resolving BOINC Soft Links
Functions:
-
int boinc_resolve_link(char *file_name, char *resolved_name);
Because there are many different ways of creating file links depending on
the platform and file system, BOINC uses a simple XML based linking scheme.
An example of a link would be a file containing only the following XML tag:
<soft_link>../../myproject.com/workunit_12345</soft_link>
As an example, if the code currently uses fopen in this manner:
file = fopen("my_file", "r");
then the proper way to use boinc_resolve_link would be as follows:
char resolved_name[512];
boinc_resolve_link("my_file",resolved_name);
file = fopen(resolved_name,"r");
The application should call boinc_resolve_link every time it needs
to access a file.
-
OpenGL Graphics in BOINC
Functions:
-
void draw_opengl();
-
void gl_done();
BOINC provides functionality which automatically sets up an OpenGL window, the
application porter needs only write a draw_gl function. The draw_gl
function is called when graphics need to be drawn to the screen. At the completion
of the draw_gl function, gl_done should be called to ensure the
graphics are properly blitted to the screen. If a non-OpenGL graphics library
is to be used, it is the applications responsibility to set it up and use the
refresh period passed via boinc_init in APP_IN.
-
The APP_IN Structure
Members:
-
char app_prefrences[4096];
-
APP_IN_GRAPHICS graphics;
-
double checkpoint_period;
-
double poll_period;
-
double cpu_time;
The APP_IN structure is passed via boinc_init() on initialization.
The app_preferences string contains any user preferences. The graphics structure
contains information about the OpenGL graphics settings. The api will initialize
timers such that the period of time_to_checkpoint() is checkpoint_period. The poll_period states how often the core client will poll the application for state information. The cpu_time member contains the number of seconds previously spent working on the current work unit.
-
The APP_OUT Structure
Members:
-
double percent_done;
-
double cpu_time_at_checkpoint;
-
bool checkpoint_completed;
The APP_OUT structure is passed via checkpoint_completed() and app_completed(). The only member expected to be filled in by the application is percent_done. THe other members will be filled in by the api. The cpu_time_at_checkpoint contains the cpu time elapsed in this instance of the application, which can be combined with the cpu_time from the APP_IN structure for total cpu time spent on this work unit.
-
The MFILE Class
Functions:
-
int MFILE::open(char* path, char* mode);
-
int MFILE::_putchar(char);
-
int MFILE::puts(char*);
-
int MFILE::printf(char* format, ...);
-
size_t MFILE::write(const void *,size_t,size_t);
-
int MFILE::close();
-
int MFILE::flush();
The MFILE class provides (nearly) atomic file writing. Most modern operating systems
do not write information to files immediately, it is often buffered for a period and
parts of the buffer are slowly written out. If an application unexpectedly quits
(due to power failure, a crash, etc), the
contents of a file may be missing or partially complete. It is also wise to call
flush for each MFILE when checkpointing, since the application state
at a checkpoint should be restartable.
-
Checkpointing and Saving State
Functions:
-
bool time_to_checkpoint( void );
-
void checkpoint_completed(APP_OUT&);
Most distributed computations require a significant amount of time
(several hours or more) for each unit of work. For this reason, it is
wise to periodically write out the current
state of the computation to disk in case of an unexpected quit or
shutdown. This is known as "checkpointing". Your application should
call time_to_checkpoint whenever it reaches a point where it can safely
save the state of the
computation, usually (indicate common places here). The state of the computation
should include everything required to start the computation again at the same
place it was checkpointed. For example, if the application contains a main loop
which is run many times during the course of the computation, checkpointing could
simply save the current iteration of the loop (reword this). If time_to_checkpoint
returns true, then go ahead and save the state, flush the MFILEs, etc. When the
checkpoint is complete call checkpoint_completed, which will take care of
extra housecleaning and communication with the core client. If possible, the APP_OUT
structure passed to checkpoint_completed should contain a rough estimate of the
percentage complete. When your
application starts up, it should read the state file to determine where
to begin computation. The period between checkpoints is user controllable (though
the default is x seconds), so it is
unwise to write your application assuming a specific checkpointing period.
-
Cleaning Up
Functions:
-
int app_completed(APP_OUT& ao);
When the application has completed it should call app_completed(), then exit.
app_completed() will take care of BOINC related housekeeping, such as telling
the core client that the application has completed, and closing OpenGL windows.