Workbook for BaBar Offline Users - Writing Classes for Persistent
Designing classes that work properly in the database.
Persistent classes are those classes used to write data to a
persistent system, e.g. to disk. Classes exist to write data from
online data acquisition and reconstruction to the various levels of
the BaBar event store, as
well as detector conditions and alignment information which is written
to the BaBar Conditions
Persistent classes refer to objects that are stored in the BaBar
Database. Errors in the creation of these classes can mess up the
database and cause many delays for other users. Therefore writers of
persistent classes should remain in contact with database experts and
take care to adhere to BaBar coding guidelines.
Data is stored in the BaBar object-oriented databases in the form of
persistent objects. The data is first read in as a transient
object (the usual type of object in a C++ program, which lives only as
long as the code that created it is being executed). The programmer
then provides classes that create persistent-capable objects from the
transient objects. Objects are stored to, and retrieved from, the
database by proxies. These are also provided by the
programmer, although in many applications there exists code provided
by the expert groups (e.g. database group) for common use.
In general, for a package, Packagename, which creates transient
objects, there will exist another package, PackagenameP which contains
the information to create, store and retrieve the corresponding
You should only write persistent classes for objects which are to be
stored in the database, do not use the same syntax for transient
You should test your persistent classes by setting up your own developer
federation and consult with an expert before writing
persistent data to the BaBar databases.
Database code is written in ddl (database description language) which
is similar to C++. However, ddl provides a more restrictive framework
from which to create persistent objects, and there is no exact mapping
between transient objects and their persistent-capable
One restriction which must be borne in mind when writing persistent
classes is that the database cannot store objects containing
pointers. This means that, for example, arrays of arrays stored using
pointers cannot be trivially stored in the database.
To get started writing persistent classes, the best teacher is
pre-existing code. Look in cvsweb for packages in
which there is a packaged called Packagename with a matching
package called PackagenameP. For example, the SvtPidCalib code which stores calibration data in
the Conditions Database.
To retrieve persistent data, you must create a proxy and register it
with the database. You then use the proxy to retrieve persistent data
from the database and the persistent data held by the proxy is read
into transient objects and then manipulated in your analysis
When designing persistent classes, a number of general software design
strategeies should be adhered to. These rules are generally applicable
for persistent programming. The design strageties and coding rules are
summarized below (information from BAD508, section on
writing persistent classes for the mini database):
- A single transient reconstruction object should be persisted only once
- All transient objects of the same class must be stored in a single.
(composite) persistent object per event, to minimize per-object
- Data sotred in embedded classes should be packed to occupy only
as many bits as required.
- Boolean data should be stored as a single bit.
- Integer data should only use as many bits as required by their range
- Float data should be packed and stored as integers. The Least
Significant Bit should be defined to correspond to roughtly 1%
of the intrinsic detector resolution of the quantity being stored.
- Packed integer and float values should use physically reasonable
ranges, not 'worst possible' ranges. Values beyong the physically
reasonable range should be appropriately truncated.
- Float data with an extreme natural range should be packed logarithmically.
- Float data should be packed using the standard packers defined in
- When the packed size of a piece of information is smaller than a
standard type (char, short, or long), several pieces of information
should be combined (bitwise OR) into a standard type data member.
- Data members of embedded classes should be aligned to the size of
the largest-size data member. This avoids compiler-generated padding
when building arrays of embedded classes.
- Persistent classes should have long-aligned data members.
- Embedded and persistent classes should use ODMG
(platform-independent) types to define their fundamental data members.
- Embedded classes should not have any virtual functions, to avoid
the persistent overhead of storing and retrieving virtual tables.
- Variable Arrays (ooVArrays) used in persistent classes must be
sized only once, either on initialization, or in the obdy of the
constructor of the class which owns them, to avoid creating persistent
memory fragments. Of a class contains more than one ooVArray, they
should be sized in the same order as they are declared in the class
New packages for persistent classes (or new classes within packages)
can be added to the BaBar framework in the same way as new analysis
packages. However, it is the duty of the package/class coordinator to
carefully ensure that the new code will not damage the BaBar database
which could lead to significant delays to users. As such, new code
should be carefully checked with as recent a release as possible, and
in a private federation before being commited to the BaBar code.
To add new classes to existing packages, following the instructions in
the WorkBook Chapter SRT and CVS
Background for Software Contributors. To add entire new classes,
carefully follow the instructions in the WorkBook Chapter New Packages: Getting your package
General Related Documents:
Last modification: 7 May 2003
Last significant update: 7 May 2003