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.

  1. BOINC Initialization
    Functions:
    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.

  2. Resolving BOINC Soft Links
    Functions:
    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.

  3. OpenGL Graphics in BOINC
    Functions:
    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.

  4. The APP_IN Structure
    Members:
    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.

  5. The APP_OUT Structure
    Members:
    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.

  6. The MFILE Class
    Functions:
    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.

  7. Checkpointing and Saving State
    Functions:
    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.

  8. Cleaning Up
    Functions:
    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.