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 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.