Important Changes: no more obsolete configuration constructors!

Obsolete Configuration constructors and helper function are no more supported. See release notes from tdaq-01-04-00 release explaining details of new plug-in based constructors and required changes in user's code: http://lnxatd01.cern.ch/cmt/releases/download/tdaq-01-04-00/RELEASE_NOTES.html#config

If your code does anything listed below, it has to be modified:

Caching of config implementation objects

Before only template objects were stored in the client's cache and the implementation objects were read from the database each time when Configuration::get(..., ConfigObject&) methods were used. If rdbconfig implementation was used, this caused new network operation per call. Now all implementation objects are also stored in the Configuration object's cache.

Local cast()

Before the Configuration::cast() method asked database implementation, if given object can be casted to an object of target class (i.e. if the target class is one of the database object's super-classes). Now the information about super-classes hierarchy is stored by the Configuration object and any cast() operation is local to client, i.e. no any network operations are required in case of rdbconfig usage.

Also fix bug when null pointer was passed to the cast() method: now Configuration::cast<T>(0) always returns 0.

Read several implementation objects at one call

An object may have several references to other objects. In general, our configuration is the directed graph built from interlinked objects, where the partition object is the entry point to navigate to any other object used in the configuration. By the other words any object used in the configuration can be accessed via references starting from the partition object.

Before each new implementation object was read in a separate call, that required in case of the rdbconfig implementation new network operation. This significantly slowed down performance of database service, when some type of applications tried to scan most of the objects in the database, e.g. to find an object with certain parameters going through hierarchy of all partition/segments/resources&applications objects. Partly this problem was solved using path-queries introduced in summer 2005.

Now, when an object is read from the database, it is possible to define, if the implementation objects referenced by it are also have to be read and stored in the client's cache by the same call. For the moment it is done via new [optional] parameter called "references-level", that can be defined for any sort of Configuration::get() methods dealing with ConfigObjects and template objects. This parameter defines how many levels of references between objects we want to follow starting from the object(s) returned by the method, e.g. for ConfigObject API:

Configuration db;
ConfigObject partition;

db.get("Partition", "be_test", partition, 0 /*rlevel*/);  // (1) read ONLY partition object
db.get("Partition", "be_test", partition, 1 /*rlevel*/);  // (2) read partition object and all objects directly referenced by it (i.e. segments of first level)
db.get("Partition", "be_test", partition, 2 /*rlevel*/);  // (3) read partition object, all objects referenced by it and all objects directly referenced by them (i.e. segments of first level & their applications and segments of second level)
db.get("Partition", "be_test", partition, 10 /*rlevel*/); // (4) very probably read ALL objects used for given configuration

In a similar way, this can be used for template objects:

Configuration db;
daq::core::Partition * p;
p = db.get<daq::core::Partition>("be_test", false, true, 0 /*rlevel*/); 
// (5) read ONLY partition object
p = db.get<daq::core::Partition>("be_test", false, true, 10 /*rlevel*/); // (6) very probably read ALL objects used for given configuration

In addition to above, a user may decide that he needs to read referenced objects belonging to certain classes only. To do this there is one extra optional parameter not shown in above examples, that is called "referenced-classes". It is a pointer to vector of string defined names of base classes. If it is not 0, then only objects of such classes or derived from them will be cached. Example:

Configuration db;
daq::core::Partition * p;
std::vector<std::string> rc;
rc.push_back("BaseApplication");
rc.push_back("Computer");
p = db.get<daq::core::Partition>("be_test", false, true, 10, &rc); 
// (7) read applications and computers used in partition

Also such parameters are available in the algorithm from dal package used to get partition object:

const daq::core::Partition * daq::core::get_partition(
  ::Configuration& conf, const std::string& pname, unsigned long rlevel = 7, const std::vector<std::string> * rclasses = 0);

It is up to user to decide, if above parameter has to be set to values different from default ones. If the reference level is too small, there is a risk for too many additional network calls in case of rdbconfig implementation. If it is too big, there is a risk the user's application will read too much data, which it does not use (e.g. detector specific config objects, which can be quite big). In any case, avoid a setting of such parameter to big numbers if many Configuration::get() methods are used, since this will increase total amount of the same data read multiple times. Ideally one should to prepare right set of parameters once when top-level configuration object is accessed using get() method and read all other configuration objects via navigation from the top-level object.

Profiling config objects access

It is possible to get information about effectiveness of database service usage by setting TDAQ_DUMP_CONFIG_PROFILER_INFO variable. For example:

export TDAQ_DUMP_CONFIG_PROFILER_INFO=1
ipc_server &
rdb_server -d be_test -D daq/partitions/be_test.data.xml &
dal_dump -d rdbconfig:be_test -c Segment
... skip several hundreds of lines of segments descriptions
Configuration profiler report:
number of created template objects: 54
number of read template objects: 13
number of cache hits: 57
Configuration implementation profiler report:
number of read objects: 49
number of cache hits: 46
RdbConfiguration profiler report:
number of xget_object() calls: 0
number of xget_all_objects() calls: 1
number of xget_objects_by_query() calls: 0
number of get_objects_by_path() calls: 0
number of get_object_values() calls: 0

From above one can see, that:

The same from tdaq-01-04-01 requires several tens of rdb network operations.

Access deleted template objects

When a template object is deleted (e.g. via subscription mechanism or by explicit user call), it is marked as deleted. When user accesses it, the config::DeletedObject exception is thrown. Note, deletion of an object may cause several deleted template objects, e.g. via inheritance (deletion an object results deletion of all template objects built from it) or via dependent composite references (deletion of parent may cause deletion of it's dependent children). If user keeps pointers on template objects, which can be deleted by any of above means, it is necessary to catch the config::DeletedObject or more general exceptions, from which it is derived. Below there is example:
Crate * crate = db.create<Crate>("/tmp/data.xml", "");    // create crate
vector<Module*> modules(1, db.create<Module>(*crate, ""); // create array containg one module
crate->set_Modules(modules);            // set modules of crate; the relationship Crate->Modules is DEPENDENT
std::cout << "1. The module's name is " << modules[0].get_Name() << std::endl;    // OK, print the module's name
db.destroy(*crate);                     // destroy crate and all it's modules
try {
  std::cout << "2. The module's name is " << modules[0].get_Name() << std::endl;  // ERROR, the module was removed !!!!
}
catch ( config::GenericException& e ) {
  std::cerr << "Caught config exception: \"" << e.what() << '\"' << std::endl;
}

Other Changes

Add method to get super-class hierarchy
const std::map<std::string, std::set<std::string> >& Configuration::superclasses() const;

If a class has super-classes, it's name is stored as key that points to names of super-classes via value.

Add parameter to check if database exists

Set silent mode to true to check if database exists or not:

bool Configuration::load(const std::string& db_name, bool silent = false);