fwConfigurationDB  8.4.2
JCOP Framework Configuration Database component

Getting started

In this section you will find a list of most useful functions.

General Remarks

Exception Handling

Following the general JCOP Framework conventions each function contains a parameter called exceptionInfo of dyn_string& type. This parameter is used to pass the information about errors and exceptions, and should always be used to handle the exception conditions. In normal conditions, when no problems were encountered and a function finished succesfully the contents of the exceptionInfo variable will be empty; otherwise, it will contain the information about the nature of the problem. This information may be displayed to the user in a standard exception handling dialog box (if the function is executed from within a UI manager) or printed to the log file. If the function is executed in non-UI manager the actual method of handling the situation of exception is to be chosen by the application developer. One should always check the contents of the exceptionInfo after each call to the API functions of the ConfigurationDB tool.

Example of error-handling in a panel:

main()
{
dyn_string exceptionInfo;
int param=1;
fwConfigurationDB_someFunction(param,exceptionInfo);
if (dynlen(exceptionInfo)) { fwExceptionHandling_display(exceptionInfo); return; }
// the code goes on ...
}

Example of error handling in a control script:

bool myFunction()
{
// returns TRUE on success...
dyn_string exceptionInfo;
int param=1;
fwConfigurationDB_someFunction(param,exceptionInfo);
if (dynlen(exceptionInfo)) { DebugN(exceptionInfo); return FALSE; }
// the code goes on ...
return TRUE
}

Initialization

Before you start using any of the functions, you need to make sure that the tool is initialized properly. The initialization procedure takes care of opening the connection to the database server, selecting the default recipe types and initialization of internal data structures.

To initialize the tool, place the call to fwConfigurationDB_initialize function. Typicaly, one will use the default setup, hence the empty string will be passed as the setupName parameter. The following code could be used in the initialization of the panel:

dyn_string exceptionInfo;
fwConfigurationDB_initialize("",exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo);return};
// further initializations, as needed...

To simply ensure the initialization was performed, without unnecessary forcing of re-initialization (which involve reopening database connections and hence may be a lengthy process), one may use the fwConfigurationDB_checkInit function instead; it will chech if the tool has already been initialized, and call the fwConfigurationDB_initialize if needed.

Please note, that fwConfigurationDB_checkInit does not allow to specify the setup parameter: the default setup is always used. We therefore suggest that fwConfigurationDB_initialize is always used for the first initialization, and fwConfigurationDB_checkInit is used later, as a "safeguard" function.

Device lists

A number of API functions in the ConfigurationDB requires the list of devices (or items) as one of the parameters of the dyn_string type. The device (item) name is:

  • the DataPoint Name for the HARDWARE view
  • the DataPoint Alias for the LOGICAL view Device (item) name contains system name may be significant. In the case of devices in HARDWARE hierarchy, the names of the devices always need to contain system name; any device name in a list that does not contain system name will automatically get it prepended (the name of current system will be used). For the LOGICAL hierarchy, on the contrary, the presence of system name in the device (item) name is meaningful and specifies the mode of operation (i.e. working without system name).

Some functions consider passing an empty list as "no sub-selection specified", others require that the devices (items) are specified explicitely. To ease the task of building the device lists for the case where devices form a hierarchy, the fwConfigurationDB_getHierarchyFromPVSS may be used. It returns a list of devices (items) that are children (and grand-children, ...) of a specified top-level device (item) in a specified hierarchy. The following example shows the use of this function: the list of all children of the "CAEN" node on the local system will be extracted (i.e. the list of all CAEN crates, their boards, and channels):

string rootNode=getSystemName()+"CAEN";
dyn_string deviceList;
dyn_string exceptionInfo;
fwConfigurationDB_getHierarchyFromPVSS(rootNode, fwDevice_HARDWARE,
deviceList, exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}

For more information about device lists and hierarchies see also Hierarchies section of this Quick Start.

Recipes

Recipes store dynamic configuration data for a set of devices (items): these contain the values of device elements and the settings of alerts. Recipes may be stored either in a database or in a cache (a local datapoint).

  • A recipe is identified by a unique name (below also refered to as "tag" or "cacheName"). It is defined for a set of devices belonging to the same hierarchy.

The use of recipes typicaly involve two steps: retrieving the recipe data from a source, followed by storing these data or applying it to a system. This involves the use of the recipeObject data structure as an intermediate, volatile storage variable, which holds the complete information about a recipe.

Recipe-related operations usually accept the Device lists as parameters, to either specify the list of devices (items) for which a recipe is created, or to make a sub-selection of a recipe.

Remote recipes and Remote Devices

It is possible to handle recipe caches stroed in remote distributed systems, as well as to have devices from remote systems in (local or remote) recipes.

To load or save a recipe from/toa cache in a remote system, it is sufficient to prefix that remote recipe name with system name and a colon, eg. "dist_2:MYRECIPE". Note that this is the recipe cache name in this string, and not the recipe cache datapoint; this naming is purely conventional.

A recipe could be loaded from cache, or a database even though some devices are non-existent (missing datapoints, for HARDWARE hierarchy), or could not be resolved (LOGICAL hierarchy). Such recipe, however, would not work when being applied. In addition, an information message will be printed in the log for every non-resolved device:

WCCOAui (1), 2018.03.26 08:34:50.919, CTRL, INFO, 2002/fwConfigurationDB, fwConfigurationDB_getRecipeFromCache, Cannot resolve device MyDet2/CHN19 in recipe: sys22:Rec22, Settings loaded yet will be skipped when applying recipe.

By default, when resolving LOGICAL devices, only local system's aliases will be taken into account, following the JCOP Framework's locality principle, and to make sure that performance is not affected in large distributed systems possibly containing millions of aliases. However, it is possible to have aliases of remote systems also resolved in the following circumstances:

  • if a recipe is loaded from a remote system, then aliases will be looked up in this system in addition to the local system.
  • if one uses the optional systemName parameter of fwConfigurationDB_loadRecipeFromCache then it is meant to be a comma-separated list of systems in which the aliases will be searched for to resolve logical devices.
  • ultimately, if the global variable fwConfigurationDB_allowResolveRemote is set to TRUE, then all the connected distributed systems will be searched through; note that for large systems this may have impact on performance and resource consumption.

Getting the list of available recipes

To get the list of available recipe caches one should use the functions:

  • fwConfigurationDB_getRecipesInCache
    dyn_string exceptionInfo, recipeList;
    fwConfigurationDB_getRecipesInCache ( recipeList,exceptionInfo);
    if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
    RecipeSelector.items=recipeList;
  • the same function mat be used to get the list of recipes in recipe cache, defined for specified device
    dyn_string exceptionInfo, recipeList;
    fwConfigurationDB_getRecipesInCache ( recipeList,exceptionInfo,"MyDCS/SubSys1/device1");
    if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
    RecipeSelector.items=recipeList;
  • fwConfigurationDB_getRecipesInDB to get the list of all recipes stored in the database:
    dyn_string exceptionInfo, recipeList;
    fwConfigurationDB_getRecipesInDB(recipeList, exceptionInfo);
    if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
    RecipeSelector.items=recipeList;
  • the same function mat be used to get the list of recipes in the database, defined for specified device
    dyn_string exceptionInfo, recipeList;
    fwConfigurationDB_getRecipesInDB ( recipeList,exceptionInfo,"MyDCS/SubSys1/device1");
    if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
    RecipeSelector.items=recipeList;

Loading stored Recipes

To load stored recipe to a recipeObject one should use the functions:

Note that these function do not overwrite the passed recipeObject, but rather perform "append" operations by means of the fwConfigurationDB_combineRecipes function, so combining the recipes is easy...

// combine two recipes, and apply it to running system
dyn_string exceptionInfo;
dyn_dyn_mixed recipeObject;
string hierarchy=fwDevice_LOGICAL
dyn_string deviceList; // empty: get all devices...
// get "coarse" settings from the database
fwConfigurationDB_loadRecipeFromDB("hv_coarse_settings",deviceList, hierarchy,
recipeObject,exceptionName,"");
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
// append "fine-tune" settings stored in the cache
fwConfigurationDB_loadRecipeFromCache("hv_fine_tune_settings", deviceList, hierarchy,
recipeObject,exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
// apply resulting recipe:
fwConfigurationDB_applyRecipe (recipeObject, hierarchy, exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}

Apply Recipes

To apply a recipe stored in recipeObject to the system use the fwConfigurationDB_applyRecipe function.

To get a recipe data into a recipeObject you may load the data from database or a recipe cache using the functions described in Loading stored Recipes . You may also create a recipeObject from a recipe template, create a custom recipeObject following the format of the recipeObject , edit the existing recipe, or aggregate recipes taken from various sources by means of the fwConfigurationDB_combineRecipes function.

See subsection Loading stored Recipes for a code example

Create Recipes

Typically a new recipe is created in two steps: the data needs to be extracted from the running system and stored in recipeObject , then it needs to be stored in the database of the recipe cache.

Before a recipe is extracted from the system, the recipe type needs to be set. By default, when fwConfigurationDB_initialize is created, the default recipe type is preselected. A custom recipe type may be set using fwConfigurationDB_setRecipeType function.

To extract the recipe data from the running system (i.e. take a "snapshot" of the current settings) the fwConfigurationDB_extractRecipe function should be used.

Example:

dyn_dyn_mixed recipeObject; // recipe data will go here
dyn_string deviceList;
dyn_string exceptionInfo;
string hierarchyType=fwDevice_LOGICAL;
// set the recipe type
fwConfigurationDB_setRecipeType("OnlyVoltages", exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
// extract the list of all items below ATLAS/EM/Barel/HV in logical hierarchy
string rootNode=getSystemName()+"ATLAS/EM/Barel/HV";
fwConfigurationDB_getHierarchyFromPVSS(rootNode, fwDevice_HARDWARE,
deviceList, exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
// get the recipe data
fwConfigurationDB_exctractRecipe(deviceList, hierarchyType,
recipeObject, exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}

Storing recipes

The recipes contained in a recipeObject can be permanently stored in the database or, locally, in a recipe cache. The following functions are at programmer's disposal:

Recipe templates

Recipe templates are an effective way of creating a recipes that contain same settings for a number of devices: the idea is to define the configuration data for a single device only, then provide the list of devices which should have this settings applied. Recipe templates are used by means of the fwConfigurationDB_makeRecipeFromTemplate function.

Any recipeObject may play a role of the recipe template; for instance, the settings for one of HV channels, that are stored in recipe cache may be loaded, then used to create a recipe that will use these settings for the whole HV subsystem, or a few boards of a HV crate.

A recipe template (we use this term to refer to templRecipeObject variable of the fwConfigurationDB_makeRecipeFromTemplate function) may contain the settings for more than one device types, e.g. it may contain settings for a CAEN channel, a CAEN board and a CAEN crate. The appropriate settings from the template will then be used (based on the device type information) to select the settings for devices from the device list.

In the example below we will use a part of "hv_ramp" recipe stored in a recipe cache (strictly speaking: the settings for the first channel and the crate) to create recipe template. Then, we will use such template to create a recipe for the whole HV crate called "CAEN/crate1".

dyn_string exceptionInfo;
dyn_dyn_mixed templateRecipeObject, recipeObject;
// load a part of recipe from cache: only two devices are involved!
makeDynString("SubSys/HvChannel001",
"SubSys/HVCrate"),
fwDevice_LOGICAL, templateRecipeObject,exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
// make a device list containing the whole CAEN crate.
string deviceList;
fwConfigurationDB_getHierarchyFromPVSS (getSystemName()+"CAEN/crate01",
fwDevice_HARDWARE, deviceList, exceptionInfo);
// use the template and the device list to create the recipe.
// note that the template used settings for LOGICAL hierarchy,
// and we create recipe for HARDWARE hierarchy!
fwConfigurationDB_makeRecipeFromTemplate (deviceList, fwDevice_HARDWARE,
templateRecipeObject, recipeObject, exceptionInfo);
if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;}
// the recipeObject contains the settings for the whole CAEN crate now...

"Manual" creation of recipes

The recipe data is stored in a dyn_dyn_mixed variable with quite complex structure. Even though it is possible to create an "ad hoc" recipe object by filling in the fields in an array, it is much more convenient to use a dedicated fuction: fwConfigurationDB_saveDiffRecipeToDB to accomplish this task.

To create a recipeObject using this function it is sufficient to provide two lists: one with the list of datapoint element names (with names of devices from any of supported hierarchies), and a list of corresponding settings for these device elements. Note that setting up alerts in this way is not possible at the moment.

The following example demonstrates the use of the function:

dyn_string deviceElements;
dyn_mixed settings;
deviceElements[1]="dist_1:CAEN/crate1.Commands.Kill";
settings[1]=TRUE;
deviceElements[2]="MyDetector/ECAL/HV/channel000.settings.v0";
settings[2]=12.34;
// this device is on remote system, yet it is visible!
deviceElements[3]="dist_2:CAEN/crate1/board00/channel004.settings.v1";
settings[3]=56.78;
// this logical device is again on remote system, yet it is visible...
deviceElements[4]="MyDetector2/ECAL/HV/straw4.settings.i1";
settings[4]=135.7;
dyn_dyn_mixed recipeObject;
fwConfigurationDB_makeRecipe(deviceElements, settings, recipeObject, exceptionInfo, TRUE);

In the example above, the recipe will contain 4 elements, for various devices being in local and also in a remote system. Note that both: HARDWARE and LOGICAL devices may be specified and mixed.

Note that the last parameter passed into the function has the TRUE value. It signifies that the created recipeObject will be filled with maximum of information that may be guessed from the local and remote systems. This, however, requires that all specified devices exist. Such complete recipe (if it contained only local devices, no remote ones) could be immediately applied to a system, stored in a cache or in the database.

However, sometimes one might need to create a recipe (e.g. for future use) that would contain the devices that not yet exist (or devices on remote systems, which are not connected to the current system). In such situation one might specify the last parameter in the call to fwConfigurationDB_makeRecipe to be FALSE. In such situation, only minimal verification of the device list is performed, and in particular the devices do not need to exist. Such recipe is not complete. It may not be applied to a system, or stored in a cache. It may, however, be stored in the database! It is then the database's task to complete the missing parts of recipe - the database may do that because the missing information is stored in the static configuration data!

Other Functions

Let us now enumerate the remaining functions, which may be of general interest.

  • To edit the contents of a recipeObject one may use the fwConfigurationDB_editRecipe function, which opens an appropriate panel.
  • To visualize the contents of a recipeObject, it is not always useful to dump its contents using DebugN(recipeObject);. A much more flexible way is to use the fwConfigurationDB_editRecipe function in the read-only mode.
  • To compare two recipe objects one may use the fwConfigurationDB_compareRecipes function, which returns a recipeObject with differences.
  • To substitute the system name in recipes in HARDWARE hierachy which were stored with another system name one may use the fwConfigurationDB_adoptRecipeObjectToSystem function.
  • To get a meta-information (i.e. description) of a recipe one may use fwConfigurationDB_GetDBRecipeMetaInfo and fwConfigurationDB_GetRecipeCacheMetaInfo functions.
  • To create a new, empty recipe in cache one may use the fwConfigurationDB_createRecipeCache function. This function will return an error if a cache with specified name already exists, hence it may be used to protect the recipe caches from being overwritten by mistake with new values.

Hierarchies

(documentation not yet completed)

Data Structures

PVSS has a limited set of basic data types. Therefore we decided to apply on a naming convention to refer to "objects" passed and returned in functions, using these basic types (dyn_X , dyn_dyn_X or mapping PVSS types).

The convention specifies the name of the variable in the definition of the function parameter. For instance, all the functions that used a recipeObject data structure (described below) will have it listed explicitly as "mapping recipeObject" in the list of the parameters.

recipeObject

The recipeObject data structure contains the data of a recipe. In PVSS it is handled using dyn_dyn_mixed data type. The data concerning recipe for a data point element, is stored in lines. Each column, all of which are the same length, store a part of the recipe data for the data point element; the first column is the "key" column - it stores the full names of the data point elements. The columns are refered to using pre-defined constants, which are described in subsection Indices used to refer to recipeObject variables . The structure of the recipeObject is shown in the figure below:

# Data point element DP Name DP Type element element type has value has alert value alert active ... other alert settings
1 dist1:AnalogDigital/ai1.value dist1:AnalogDigital/ai1 FwAnalogInput .value 22 (DPEL_FLOAT) FALSE TRUE TRUE ...
2 dist1:AnalogDigital/ao1.value dist1:AnalogDigital/ao1 FwAnalogOutput .value 22 (DPEL_FLOAT) TRUE FALSE 3.14

Although the type of each single cell of the table is "mixed", which allows for storing any data type (including dynamic data types), we decided to store the property value in the encoded form. The _fwConfigurationDB_dataToString and _fwConfigurationDB_stringToData functions are used to encode and decode the data into a string. The other parts of data, including lists of alert texts, alert classes, etc are stored using their native types inside the recipeObject. For more information about the conventions, please refer to subsection Conventions for recipe data storage .

connectionInfo

RTData

The RTData object is used as a transient data storage space for Recipe Type data, where the data is edited in RecipeTypeEdit.pnl panel. It is a dyn_dyn_string-typed variable, with the following structure:

  • RTData[i][1] : device type name
  • RTData[i][2] : device dptype name
  • RTData[i][3] : dp element
  • RTData[i][4] : property name
  • RTData[i][5] : save value
  • RTData[i][6] : save alert

the "i" index refers to the entries for subsequent dpes of dpts. Each entry could be uniquely identified by RTData[i][2] and RTData[i][3] entries.

Convention: for the Framework devices RTData[i][1] will store the Framework Device Name according to device definitions, e.g. "CAEN Board", and the RTData[i][2] will store the actual data point type, e.g. FwCaenChannel. For non-framework data poin types, both: RTData[i][1] and RTData[i][2] will contain the data point type. This way one can in fact distinguish the Framework and non-Framework entries by checking if RTData[i][1] and RTData[i][2] are the same.

Conventions

Conventions for recipe data storage

The following conventions for data encoding are used for recipes.

what/where System recipeObject recipe cache database
property value any type as string as string as string
alert active bool bool as string as string
alert limits dyn_float dyn_float as string as string
alert texts dyn_string dyn_string as string as string
alert classes dyn_string dyn_string as string as string

The _fwConfigurationDB_dataToString and _fwConfigurationDB_stringToData functions are used to encode and decode the data into a string. The "|" character is used as a separator when dynamic-list-typed variables are stored.

Others