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 }
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.
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.
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.
dyn_string exceptionInfo, recipeList; fwConfigurationDB_getRecipesInCache ( recipeList,exceptionInfo); if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;} RecipeSelector.items=recipeList;
dyn_string exceptionInfo, recipeList; fwConfigurationDB_getRecipesInCache ( recipeList,exceptionInfo,"MyDCS/SubSys1/device1"); if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;} RecipeSelector.items=recipeList;
dyn_string exceptionInfo, recipeList; fwConfigurationDB_getRecipesInDB(recipeList, exceptionInfo); if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;} RecipeSelector.items=recipeList;
dyn_string exceptionInfo, recipeList; fwConfigurationDB_getRecipesInDB ( recipeList,exceptionInfo,"MyDCS/SubSys1/device1"); if (dynlen(exceptionInfo)) {fwExceptionHandling_display(exceptionInfo); return;} RecipeSelector.items=recipeList;
// 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;}
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
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;}
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! fwConfigurationDB_loadRecipeFromCache("hv_ramp", 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...
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);
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!
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.
# | 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 .
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.
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.