This chapter describes the organization of the libraries.
The first question a user might reasonbly ask is how a library can hide the format differences between the versions of NSCLDAQ from a program. This can be done mostly by understanding that each version layers on additional fields and capabilities on the base of fields and capabilities supplied by the prior version. For example V11 adds the ability to have a body header used in event building to the V10 format. V12, makes a slight change to the value that indicates there is no body header and provides the ability to track the original source id of objects whose body headers are otherwise overwritten during event building.
The format libary:
Provides a set of classes that is derived from a base class that completely hides the actual layout of each item, only providing constructors and accessors to retrieve/set fields in the underlying data of each object.
Where capabilities dont' yet exist, the library either hands off reasonable defaults or throws exceptions.
Provides a set of object factories, one for each supported NSCLDAQ version to generate objects either from parameterization, undifferentiated items or from sources of data (e.g. ringbuffers, file descriptors or c++ streams). The factories also provide support for serializing objects to these entities.
Given information about the version of NSCLDAQ used (either an explicit version number or a data format item, the library can provide an instance of the appropriate factory.
In this way a program is not looking at the actual data but simply getting or setting properties of the data based on an interface that can accomodate the maximal capabilities of a ring item over all versions.
The next sections describe and give examples of
Ring Item classes. The ring item classes which encapsulate the data from each ring item type.
Factories. The factory classes see, however Factories and the Abstract Factory Pattern for more.
Ring item contents are hidden from users behind a family of classes. A set of base classes, abstract ring items define a interfaces for each type of ring item. For each supported version of NSCLDAQ a set of subclasses exists that actually provide those interfaces for that specific data format. In the next section we'll see how we can then use the factory classes and factory selector to produce items without knowing the detailed format of those items.
The headers for the abstract ring items types are located in the include subdirectory of the library's installation directory root. Subdirectories named vnn where nn is the NSCLDAQ version number host the headers for specific NSCLDAQ versions. For example include/v11 holds the headers for version 11.
Since each of the version dependent headers will reference the abstract headers, it's important to only add the top level include directory to the header search path. Here's a code fragment that shows how to create and fill in a physics data item with event builder information for version 11 (note that in practice you'll do this using a ring item factory as described in the next section).
Example 2-1. Generating a Physics item for NSCLDAQ-11
#include <v11/CPhysicsEventItem.h>... v11::CPhysicsEventItem item;
item.setBodyHeader(someTimestamp, someSourceId);
uint16_t* pBody = reinterpret_cast<uint16_t*>(item.getBodyCursor);
... item.setBodyCursor(pBody);
item.updateSize();
...
We'll still need to fill in the header's size field as we'll see later on.
setBodyHeader
sets the body header
of the item, if necessary sliding down any existing body data
to accomodate it. The barrier type argumetn of
setBodyHeader
defaults to
0 which implies the event is not an
event builder barrier.
getBodyCursor
method retrieves a
void* pointer to this storage in a format
independent manner. This provides us a pointer which we
can use to fill in the data from the physics trigger.
Note that the code in the section marked ...
below is assumed to fill in the physics data and advance
the pBody
pointer to point past the
body data we put in.