otsdaq  v1_01_02
 All Classes Namespaces Functions
ConfigurationManagerRW.cc
1 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
2 
3 //backbone includes
4 //#include "otsdaq-core/ConfigurationPluginDataFormats/ConfigurationAliases.h"
5 //#include "otsdaq-core/ConfigurationPluginDataFormats/Configurations.h"
6 //#include "otsdaq-core/ConfigurationPluginDataFormats/DefaultConfigurations.h"
7 //#include "otsdaq-core/ConfigurationPluginDataFormats/VersionAliases.h"
8 
9 //#include "otsdaq-core/ConfigurationInterface/ConfigurationInterface.h"//All configurable objects are included here
10 
11 
12 //
13 //#include "otsdaq-core/ConfigurationPluginDataFormats/DetectorConfiguration.h"
14 //#include "otsdaq-core/ConfigurationPluginDataFormats/MaskConfiguration.h"
15 //#include "otsdaq-core/ConfigurationPluginDataFormats/DetectorToFEConfiguration.h"
16 //
17 
18 //#include "otsdaq-core/ConfigurationInterface/DACStream.h"
19 //#include "otsdaq-core/ConfigurationDataFormats/ConfigurationGroupKey.h"
20 //
21 //#include "otsdaq-core/ConfigurationInterface/FileConfigurationInterface.h"
22 //
23 //#include <cassert>
24 
25 #include<dirent.h>
26 
27 using namespace ots;
28 
29 
30 #undef __MF_SUBJECT__
31 #define __MF_SUBJECT__ "ConfigurationManagerRW"
32 
33 #define CONFIGURATION_INFO_PATH std::string(getenv("CONFIGURATION_INFO_PATH")) + "/"
34 #define CONFIGURATION_INFO_EXT "Info.xml"
35 
36 //==============================================================================
37 //ConfigurationManagerRW
38 ConfigurationManagerRW::ConfigurationManagerRW(std::string username)
39 : ConfigurationManager(username) //for use as author of new views
40 {
41  __MOUT__ << "Using Config Mgr with Write Access! (for " << username << ")" << std::endl;
42 
43 
44  //FIXME only necessarily temporarily while Lore is still using fileSystem xml
45  theInterface_ = ConfigurationInterface::getInstance(false); //false to use artdaq DB
46  // FIXME -- can delete this change of interface once RW and regular use same interface instance
47 }
48 
49 //==============================================================================
50 //getAllConfigurationInfo()
51 // Used by ConfigurationGUISupervisor to get all the info for the existing configurations
52 //
53 //if(accumulatedErrors)
54 // this implies allowing column errors and accumulating such errors in given string
55 const std::map<std::string, ConfigurationInfo>& ConfigurationManagerRW::getAllConfigurationInfo(
56  bool refresh, std::string *accumulatedErrors, const std::string &errorFilterName)
57 {
58  //allConfigurationInfo_ is container to be returned
59 
60  if(accumulatedErrors) *accumulatedErrors = "";
61 
62  if(!refresh) return allConfigurationInfo_;
63 
64  //else refresh!
65  allConfigurationInfo_.clear();
66 
67  ConfigurationBase* configuration;
68 
69  //existing configurations are defined by which infos are in CONFIGURATION_INFO_PATH
70  //can test that the class exists based on this
71  //and then which versions
72  __MOUT__ << "Extracting list of Configuration tables" << std::endl;
73  DIR *pDIR;
74  struct dirent *entry;
75  std::string path = CONFIGURATION_INFO_PATH;
76  char fileExt[] = CONFIGURATION_INFO_EXT;
77  const unsigned char MIN_CONFIG_NAME_SZ = 3;
78  if( (pDIR=opendir( path.c_str() )) != 0 )
79  {
80  while((entry = readdir(pDIR)) != 0)
81  {
82  //enforce configuration name length
83  if(strlen(entry->d_name) < strlen(fileExt)+MIN_CONFIG_NAME_SZ)
84  continue;
85 
86  //find file names with correct file extenstion
87  if( strcmp(
88  &(entry->d_name[strlen(entry->d_name) - strlen(fileExt)]),
89  fileExt) != 0)
90  continue; //skip different extentions
91 
92 
93  entry->d_name[strlen(entry->d_name) - strlen(fileExt)] = '\0'; //remove file extension to get config name
94 
95  //__MOUT__ << entry->d_name << std::endl;
96 
97  //0 will force the creation of new instance (and reload from Info)
98  configuration = 0;
99 
100  try //only add valid configuration instances to maps
101  {
102  theInterface_->get(configuration,
103  entry->d_name,
104  0, 0,
105  true); //dont fill
106  }
107  catch(cet::exception)
108  {
109  if(configuration) delete configuration;
110  configuration = 0;
111 
112  __MOUT__ << "Skipping! No valid class found for... " << entry->d_name << "\n";
113  continue;
114  }
115  catch(std::runtime_error &e)
116  {
117  if(configuration) delete configuration;
118  configuration = 0;
119 
120  __MOUT__ << "Skipping! No valid class found for... " << entry->d_name << "\n";
121  __MOUT__ << "Error: " << e.what() << std::endl;
122 
123 
124  //for a runtime_error, it is likely that columns are the problem
125  // the Table Editor needs to still fix these.. so attempt to
126  // proceed.
127  if(accumulatedErrors)
128  {
129 
130  if(errorFilterName == "" ||
131  errorFilterName == entry->d_name)
132  {
133  *accumulatedErrors += std::string("\nIn table '") + entry->d_name +
134  "'..." + e.what(); //global accumulate
135 
136  __SS__ << "Attempting to allow illegal columns!" << std::endl;
137  *accumulatedErrors += ss.str();
138  }
139 
140  //attempt to recover and build a mock-up
141  __MOUT__ << "Attempting to allow illegal columns!" << std::endl;
142 
143 
144  std::string returnedAccumulatedErrors;
145  try
146  {
147  //configuration = new ConfigurationBase(entry->d_name, &returnedAccumulatedErrors);
148  configuration = new ConfigurationBase(entry->d_name, &returnedAccumulatedErrors);
149  }
150  catch(...)
151  {
152  __MOUT__ << "Skipping! Allowing illegal columns didn't work either... " <<
153  entry->d_name << "\n";
154  continue;
155  }
156  __MOUT__ << "Error (but allowed): " << returnedAccumulatedErrors << std::endl;
157 
158  if(errorFilterName == "" ||
159  errorFilterName == entry->d_name)
160  *accumulatedErrors += std::string("\nIn table '") + entry->d_name +
161  "'..." + returnedAccumulatedErrors; //global accumulate
162  }
163  else
164  continue;
165  }
166 
167  //__MOUT__ << "Instance created: " << entry->d_name << "\n"; //found!
168 
169  if(nameToConfigurationMap_[entry->d_name]) //handle if instance existed
170  {
171  //copy the temporary versions! (or else all is lost)
172  std::set<ConfigurationVersion> versions =
173  nameToConfigurationMap_[entry->d_name]->getStoredVersions();
174  for(auto &version:versions)
175  if(version.isTemporaryVersion())
176  {
177  __MOUT__ << "copying tmp = " << version << std::endl;
178 
179  try //do NOT let ConfigurationView::init() throw here
180  {
181  nameToConfigurationMap_[entry->d_name]->setActiveView(version);
182  configuration->copyView( //this calls ConfigurationView::init()
183  nameToConfigurationMap_[entry->d_name]->getView(),
184  version,
185  username_);
186  }
187  catch(...) //do NOT let invalid temporary version throw at this point
188  {} //just trust configurationBase throws out the failed version
189  }
190  //__MOUT__ << "deleting: " << entry->d_name << "\n"; //found!
191  delete nameToConfigurationMap_[entry->d_name];
192  nameToConfigurationMap_[entry->d_name] = 0;
193  }
194 
195  nameToConfigurationMap_[entry->d_name] = configuration;
196 
197  allConfigurationInfo_[entry->d_name].configurationPtr_ = configuration;
198  allConfigurationInfo_[entry->d_name].versions_ = theInterface_->getVersions(configuration);
199 
200  //also add any existing temporary versions to all config info
201  // because the interface wont find those versions
202  std::set<ConfigurationVersion> versions =
203  nameToConfigurationMap_[entry->d_name]->getStoredVersions();
204  for(auto &version:versions)
205  if(version.isTemporaryVersion())
206  {
207  __MOUT__ << "surviving tmp = " << version << std::endl;
208  allConfigurationInfo_[entry->d_name].versions_.emplace(version);
209  }
210  }
211  closedir(pDIR);
212  }
213  __MOUT__ << "Extracting list of Configuration tables complete" << std::endl;
214 
215  //call init to load active versions by default
216  init(accumulatedErrors);
217 
218  return allConfigurationInfo_;
219 }
220 
221 //==============================================================================
222 //getActiveAliases()
223 // get active version aliases organized by table
224 std::map<std::string,std::map<std::string,ConfigurationVersion> >
225 ConfigurationManagerRW::getActiveVersionAliases(void) const
226 {
227  __MOUT__ << "getActiveVersionAliases()" << std::endl;
228  std::map<std::string,std::map<std::string,ConfigurationVersion> > retMap;
229 
230  std::map<std::string, ConfigurationVersion> activeVersions = getActiveVersions();
231  std::string versionAliasesTableName = "VersionAliasesConfiguration";
232  if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
233  {
234  __SS__ << "Active version of VersionAliases missing!" <<
235  "Make sure you have a valid active Backbone Group." << std::endl;
236  __MOUT_WARN__ << "\n" << ss.str();
237  return retMap;
238  }
239 
240  __MOUT__ << "activeVersions[\"VersionAliasesConfiguration\"]=" <<
241  activeVersions[versionAliasesTableName] << std::endl;
242 
243  //always have scratch alias for each table that has a scratch version
244  if(!ConfigurationInterface::isVersionTrackingEnabled())
245  for(const auto &tableInfo:allConfigurationInfo_)
246  for(const auto &version:tableInfo.second.versions_)
247  if(version.isScratchVersion())
248  retMap[tableInfo.first][ConfigurationManager::SCRATCH_VERSION_ALIAS] =
249  ConfigurationVersion(ConfigurationVersion::SCRATCH);
250 
251  std::vector<std::pair<std::string,ConfigurationTree> > aliasNodePairs =
252  getNode(versionAliasesTableName).getChildren();
253 
254  //create map
255  // add the first of each configName, versionAlias pair encountered
256  // ignore any repeats (Note: this also prevents overwriting of Scratch alias)
257  std::string configName, versionAlias;
258  for(auto& aliasNodePair:aliasNodePairs)
259  {
260  configName = aliasNodePair.second.getNode(
261  "ConfigurationName").getValueAsString();
262  versionAlias = aliasNodePair.second.getNode(
263  "VersionAlias").getValueAsString();
264 
265  if(retMap.find(configName) != retMap.end() &&
266  retMap[configName].find(versionAlias) != retMap[configName].end())
267  continue; //skip repeats (Note: this also prevents overwriting of Scratch alias)
268 
269  //else add version to map
270  retMap[configName][versionAlias] = ConfigurationVersion(
271  aliasNodePair.second.getNode("Version").getValueAsString());
272  }
273 
274  return retMap;
275 }
276 
277 //==============================================================================
278 //setActiveGlobalConfiguration
279 // load config group and activate
280 // deactivates previous config group of same type if necessary
281 void ConfigurationManagerRW::activateConfigurationGroup(const std::string &configGroupName,
282  ConfigurationGroupKey configGroupKey, std::string *accumulatedTreeErrors)
283 {
284  loadConfigurationGroup(configGroupName,configGroupKey,
285  true, //loads and activates
286  0, //no progress bar
287  accumulatedTreeErrors); //accumulate warnings or not
288 
289  if(accumulatedTreeErrors &&
290  *accumulatedTreeErrors != "")
291  {
292  __MOUT_ERR__ << "Errors were accumulated so de-activating group: " <<
293  configGroupName << " (" << configGroupKey << ")" << std::endl;
294  try //just in case any lingering pieces, lets deactivate
295  { destroyConfigurationGroup(configGroupName,true); }
296  catch(...){}
297  }
298 
299  __MOUT_INFO__ << "Updating persistent active groups to " <<
300  ConfigurationManager::ACTIVE_GROUP_FILENAME << " ..." << std::endl;
301 
302  std::string fn = ConfigurationManager::ACTIVE_GROUP_FILENAME;
303  FILE *fp = fopen(fn.c_str(),"w");
304  if(!fp) return;
305 
306  fprintf(fp,"%s\n",theContextGroup_.c_str());
307  fprintf(fp,"%s\n",theContextGroupKey_?theContextGroupKey_->toString().c_str():"-1");
308  fprintf(fp,"%s\n",theBackboneGroup_.c_str());
309  fprintf(fp,"%s\n",theBackboneGroupKey_?theBackboneGroupKey_->toString().c_str():"-1");
310  fprintf(fp,"%s\n",theConfigurationGroup_.c_str());
311  fprintf(fp,"%s\n",theConfigurationGroupKey_?theConfigurationGroupKey_->toString().c_str():"-1");
312  fclose(fp);
313 }
314 
315 //==============================================================================
316 //createTemporaryBackboneView
317 // sourceViewVersion of INVALID is from MockUp, else from valid view version
318 // returns temporary version number (which is always negative)
319 ConfigurationVersion ConfigurationManagerRW::createTemporaryBackboneView(ConfigurationVersion sourceViewVersion)
320 {
321  __MOUT_INFO__ << "Creating temporary backbone view from version " <<
322  sourceViewVersion << std::endl;
323 
324  //find common available temporary version among backbone members
325  ConfigurationVersion tmpVersion = ConfigurationVersion::getNextTemporaryVersion(); //get the default temporary version
326  ConfigurationVersion retTmpVersion;
327  auto backboneMemberNames = ConfigurationManager::getBackboneMemberNames();
328  for (auto& name : backboneMemberNames)
329  {
330  retTmpVersion = ConfigurationManager::getConfigurationByName(name)->getNextTemporaryVersion();
331  if(retTmpVersion < tmpVersion)
332  tmpVersion = retTmpVersion;
333  }
334 
335  __MOUT__ << "Common temporary backbone version found as " <<
336  tmpVersion << std::endl;
337 
338  //create temporary views from source version to destination temporary version
339  for (auto& name : backboneMemberNames)
340  {
341  retTmpVersion = getConfigurationByName(name)->createTemporaryView(sourceViewVersion, tmpVersion);
342  if(retTmpVersion != tmpVersion)
343  {
344  __MOUT_ERR__ << "Failure! Temporary view requested was " <<
345  tmpVersion << ". Mismatched temporary view created: " << retTmpVersion << std::endl;
346  throw std::runtime_error("Mismatched temporary view created!");
347  }
348  }
349 
350  return tmpVersion;
351 }
352 
353 
354 
355 //==============================================================================
356 ConfigurationBase* ConfigurationManagerRW::getConfigurationByName(const std::string &configurationName)
357 {
358  if(nameToConfigurationMap_.find(configurationName) == nameToConfigurationMap_.end())
359  {
360  __MOUT_ERR__ << "\nConfiguration not found with name: " << configurationName << std::endl;
361  throw std::runtime_error("Configuration not found with name '" + configurationName + ".'");
362  }
363  return nameToConfigurationMap_[configurationName];
364 }
365 
366 //==============================================================================
367 //getVersionedConfigurationByName
368 // Used by configuration GUI to load a particular configuration-version pair as the active version.
369 // This configuration instance must already exist and be owned by ConfigurationManager.
370 // return null pointer on failure, on success return configuration pointer.
371 ConfigurationBase* ConfigurationManagerRW::getVersionedConfigurationByName(const std::string &configurationName,
372  ConfigurationVersion version, bool looseColumnMatching)
373 {
374  auto it = nameToConfigurationMap_.find(configurationName);
375  if(it == nameToConfigurationMap_.end())
376  {
377  __SS__ << "\nCan not find configuration named '" <<
378  configurationName <<
379  "'\n\n\n\nYou need to load the configuration before it can be used." <<
380  "It probably is missing from the member list of the Configuration Group that was loaded?\n\n\n\n\n"
381  << std::endl;
382  throw std::runtime_error(ss.str());
383  }
384  ConfigurationBase* configuration = it->second;
385  theInterface_->get(configuration, configurationName, 0 , 0,
386  false, //fill w/version
387  version,
388  false, //do not reset
389  looseColumnMatching);
390  return configuration;
391 }
392 
393 //==============================================================================
394 //saveNewConfiguration
395 // saves version, makes the new version the active version, and returns new version
396 ConfigurationVersion ConfigurationManagerRW::saveNewConfiguration(const std::string &configurationName,
397  ConfigurationVersion temporaryVersion, bool makeTemporary)
398 {
399  ConfigurationVersion newVersion(temporaryVersion);
400 
401  //set author of version
402  ConfigurationBase *config = getConfigurationByName(configurationName);
403  config->getTemporaryView(temporaryVersion)->setAuthor(username_);
404  //NOTE: somehow? author is assigned to permanent versions when saved to DBI?
405 
406  if(!makeTemporary) //saveNewVersion makes the new version the active version
407  newVersion = theInterface_->saveNewVersion(config, temporaryVersion);
408  else //make the temporary version active
409  config->setActiveView(newVersion);
410 
411  //if there is a problem, try to recover
412  while(!newVersion.isScratchVersion() && allConfigurationInfo_[configurationName].versions_.find(newVersion) !=
413  allConfigurationInfo_[configurationName].versions_.end())
414  {
415  __MOUT_ERR__ << "What happenened!?? ERROR::: newVersion v" << newVersion <<
416  " already exists!? How is it possible? Retrace your steps and tell an admin." << std::endl;
417 
418  //create a new temporary version of the target view
419  temporaryVersion = config->createTemporaryView(newVersion);
420 
421  if(newVersion.isTemporaryVersion())
422  newVersion = temporaryVersion;
423  else
424  newVersion = ConfigurationVersion::getNextVersion(newVersion);
425 
426  __MOUT_WARN__ << "Attempting to recover and use v" << newVersion << std::endl;
427 
428 
429  if(!makeTemporary) //saveNewVersion makes the new version the active version
430  newVersion = theInterface_->saveNewVersion(config, temporaryVersion, newVersion);
431  else //make the temporary version active
432  config->setActiveView(newVersion);
433  }
434 
435  if(newVersion.isInvalid())
436  {
437  __SS__ << "Something went wrong saving the new version v" << newVersion <<
438  ". What happened?! (duplicates? database error?)" << std::endl;
439  __MOUT_ERR__ << "\n" << ss.str();
440  throw std::runtime_error(ss.str());
441  }
442 
443  //update allConfigurationInfo_ with the new version
444  allConfigurationInfo_[configurationName].versions_.insert(newVersion);
445 
446  __MOUT__ << "New version added to info " << newVersion << std::endl;
447 
448  return newVersion;
449 }
450 
451 //==============================================================================
452 //eraseTemporaryVersion
453 // if version is invalid then erases ALL temporary versions
454 //
455 // maintains allConfigurationInfo_ also while erasing
456 void ConfigurationManagerRW::eraseTemporaryVersion(const std::string &configurationName,
457  ConfigurationVersion targetVersion)
458 {
459  ConfigurationBase* config = getConfigurationByName(configurationName);
460 
461  config->trimTemporary(targetVersion);
462 
463  //if allConfigurationInfo_ is not setup, then done
464  if(allConfigurationInfo_.find(configurationName) ==
465  allConfigurationInfo_.end()) return;
466  //else cleanup config info
467 
468  if(targetVersion.isInvalid())
469  {
470  //erase all temporary versions!
471  for(auto it = allConfigurationInfo_[configurationName].versions_.begin();
472  it != allConfigurationInfo_[configurationName].versions_.end(); /*no increment*/)
473  {
474  if(it->isTemporaryVersion())
475  {
476  __MOUT__ << "Removing version info: " << *it << std::endl;
477  allConfigurationInfo_[configurationName].versions_.erase(it++);
478  }
479  else
480  ++it;
481  }
482  }
483  else //erase target version only
484  {
485  __MOUT__ << "Removing version info: " << targetVersion << std::endl;
486  auto it = allConfigurationInfo_[configurationName].versions_.find(targetVersion);
487  if(it == allConfigurationInfo_[configurationName].versions_.end())
488  {
489  __MOUT__ << "Target version was not found in info versions..." << std::endl;
490  return;
491  }
492  allConfigurationInfo_[configurationName].versions_.erase(
493  allConfigurationInfo_[configurationName].versions_.find(targetVersion));
494  __MOUT__ << "Target version was erased from info." << std::endl;
495  }
496 }
497 
498 //==============================================================================
499 //clearCachedVersions
500 // clear ALL cached persistent versions (does not erase temporary versions)
501 //
502 // maintains allConfigurationInfo_ also while erasing (trivial, do nothing)
503 void ConfigurationManagerRW::clearCachedVersions(const std::string &configurationName)
504 {
505  ConfigurationBase* config = getConfigurationByName(configurationName);
506 
507  config->trimCache(0);
508 }
509 
510 //==============================================================================
511 //clearAllCachedVersions
512 // clear ALL cached persistent versions (does not erase temporary versions)
513 //
514 // maintains allConfigurationInfo_ also while erasing (trivial, do nothing)
515 void ConfigurationManagerRW::clearAllCachedVersions()
516 {
517  for(auto configInfo: allConfigurationInfo_)
518  configInfo.second.configurationPtr_->trimCache(0);
519 }
520 
521 //==============================================================================
522 //copyViewToCurrentColumns
523 ConfigurationVersion ConfigurationManagerRW::copyViewToCurrentColumns(const std::string &configurationName,
524  ConfigurationVersion sourceVersion)
525 {
526  getConfigurationByName(configurationName)->reset();
527 
528  //make sure source version is loaded
529  //need to load with loose column rules!
530  ConfigurationBase *config = getVersionedConfigurationByName(configurationName,
531  ConfigurationVersion(sourceVersion), true);
532 
533  //copy from source version to a new temporary version
534  ConfigurationVersion newTemporaryVersion = config->copyView(config->getView(),
535  ConfigurationVersion(),username_);
536 
537  //update allConfigurationInfo_ with the new version
538  allConfigurationInfo_[configurationName].versions_.insert(newTemporaryVersion);
539 
540  return newTemporaryVersion;
541 }
542 
543 
544 
545 //==============================================================================
546 //findConfigurationGroup
547 // return group with same name and same members
548 // else return invalid key
549 //
550 // FIXME -- this is taking too long when there are a ton of groups.
551 // Change to going back only 20 or so.. (but the order also comes in alpha order from
552 // theInterface_->getAllConfigurationGroupNames which is a problem for choosing the
553 // most recent to check.
554 ConfigurationGroupKey ConfigurationManagerRW::findConfigurationGroup(const std::string &groupName,
555  const std::map<std::string, ConfigurationVersion> &groupMemberMap)
556 {
557  std::set<std::string /*name*/> groupNames =
558  theInterface_->getAllConfigurationGroupNames(groupName);
559  std::string name;
561  std::map<std::string /*name*/, ConfigurationVersion /*version*/> compareToMemberMap;
562  bool isDifferent;
563  for(auto &fullName: groupNames)
564  {
565  ConfigurationGroupKey::getGroupNameAndKey(fullName,name,key);
566 
567  __MOUT__ << fullName << " has name " << name << " ==? " << groupName << std::endl;
568  if( name != groupName) continue;
569 
570  __MOUT__ << name << " == " << groupName << std::endl;
571  compareToMemberMap = theInterface_->getConfigurationGroupMembers(fullName);
572 
573  isDifferent = false;
574  for(auto &memberPair: groupMemberMap)
575  {
576  __MOUT__ << memberPair.first << " - " << memberPair.second << std::endl;
577  if(compareToMemberMap.find(memberPair.first) == compareToMemberMap.end() || //name is missing
578  memberPair.second != compareToMemberMap[memberPair.first]) //or version mismatch
579  { //then different
580  __MOUT__ << "mismatch found!" << std::endl;
581  isDifferent = true;
582  break;
583  }
584  }
585  if(isDifferent) continue;
586 
587  //check member size for exact match
588  if(groupMemberMap.size() != compareToMemberMap.size()) continue; //different size, so not same (groupMemberMap is a subset of memberPairs)
589 
590  __MOUT__ << "Found exact match with key: " << key << std::endl;
591  //else found an exact match!
592  return key;
593  }
594  __MOUT__ << "no match found!" << std::endl;
595  //if here, then no match found
596  return ConfigurationGroupKey(); //return invalid key
597 }
598 
599 
600 //==============================================================================
601 //saveNewConfigurationGroup
602 // saves new group and returns the new group key
603 // if previousVersion is provided, attempts to just bump that version
604 // else, bumps latest version found in db
605 //
606 // Note: groupMembers map will get modified with group metadata table version
607 ConfigurationGroupKey ConfigurationManagerRW::saveNewConfigurationGroup(const std::string &groupName,
608  std::map<std::string, ConfigurationVersion> &groupMembers,
609  ConfigurationGroupKey previousVersion, const std::string &groupComment)
610 {
611  //steps:
612  // determine new group key
613  // verify group members
614  // verify groupNameWithKey
615  // verify store
616 
617  __MOUT__ << std::endl;
618  //determine new group key
619  ConfigurationGroupKey newKey;
620  if(!previousVersion.isInvalid()) //if previous provided, bump that
621  newKey = ConfigurationGroupKey::getNextKey(previousVersion);
622  else //get latest key from db, and bump
623  {
624  std::set<ConfigurationGroupKey> keys = theInterface_->getKeys(groupName);
625  if(keys.size()) //if keys exist, bump the last
626  newKey = ConfigurationGroupKey::getNextKey(*(keys.crbegin()));
627  else //else, take default
628  newKey = ConfigurationGroupKey::getDefaultKey();
629  }
630 
631  __MOUT__ << "New Key for group: " << groupName << " found as " << newKey << std::endl;
632 
633  // verify group members
634  // - use all config info
635  std::map<std::string, ConfigurationInfo> allCfgInfo = getAllConfigurationInfo();
636  for(auto &memberPair : groupMembers )
637  {
638  //check member name
639  if(allCfgInfo.find(memberPair.first) == allCfgInfo.end())
640  {
641  __MOUT_ERR__ << "Group member \"" << memberPair.first << "\" not found in configuration!";
642 
643  if(groupMetadataTable_.getConfigurationName() ==
644  memberPair.first)
645  {
646  __MOUT_WARN__ << "Looks like this is the groupMetadataTable_. " <<
647  "Note that this table is added to the member map when groups are saved." <<
648  "It should not be part of member map when calling this function." << std::endl;
649  __MOUT__ << "Attempting to recover." << std::endl;
650  groupMembers.erase(groupMembers.find(memberPair.first));
651  }
652  else
653  throw std::runtime_error("Group member not found!");
654  }
655  //check member version
656  if(allCfgInfo[memberPair.first].versions_.find(memberPair.second) ==
657  allCfgInfo[memberPair.first].versions_.end())
658  {
659  __MOUT_ERR__ << "Group member \"" << memberPair.first << "\" version \"" <<
660  memberPair.second << "\" not found in configuration!";
661  throw std::runtime_error("Group member version not found!");
662  }
663  }
664 
665  // verify groupNameWithKey and attempt to store
666  try
667  {
668  //save meta data for group; reuse groupMetadataTable_
669 
670  //__MOUT__ << username_ << " " << time(0) << " " << groupComment << std::endl;
671  //columns are uid,comment,author,time
672  groupMetadataTable_.getViewP()->setValue(groupComment,0,1);
673  groupMetadataTable_.getViewP()->setValue(username_,0,2);
674  groupMetadataTable_.getViewP()->setValue(time(0),0,3);
675 
676  //set version to first available persistent version
677  groupMetadataTable_.getViewP()->setVersion(
678  ConfigurationVersion::getNextVersion(theInterface_->findLatestVersion(&groupMetadataTable_))
679  );
680 
681  //groupMetadataTable_.print();
682 
683  theInterface_->saveActiveVersion(&groupMetadataTable_);
684 
685  //force groupMetadataTable_ to be a member for the group
686  groupMembers[groupMetadataTable_.getConfigurationName()] =
687  groupMetadataTable_.getViewVersion();
688 
689  theInterface_->saveConfigurationGroup(groupMembers,
690  ConfigurationGroupKey::getFullGroupString(groupName,newKey));
691  __MOUT__ << "Created config group: " << groupName << ":" << newKey << std::endl;
692  }
693  catch(std::runtime_error &e)
694  {
695  __MOUT_ERR__ << "Failed to create config group: " << groupName << ":" << newKey << std::endl;
696  __MOUT_ERR__ << "\n\n" << e.what() << std::endl;
697  throw;
698  }
699  catch(...)
700  {
701  __MOUT_ERR__ << "Failed to create config group: " << groupName << ":" << newKey << std::endl;
702  throw;
703  }
704 
705  // at this point succeeded!
706  return newKey;
707 }
708 
709 //==============================================================================
710 //saveNewBackbone
711 // makes the new version the active version and returns new version number
712 // INVALID will give a new backbone from mockup
713 ConfigurationVersion ConfigurationManagerRW::saveNewBackbone(ConfigurationVersion temporaryVersion)
714 {
715  __MOUT_INFO__ << "Creating new backbone from temporary version " <<
716  temporaryVersion << std::endl;
717 
718  //find common available temporary version among backbone members
719  ConfigurationVersion newVersion(ConfigurationVersion::DEFAULT);
720  ConfigurationVersion retNewVersion;
721  auto backboneMemberNames = ConfigurationManager::getBackboneMemberNames();
722  for (auto& name : backboneMemberNames)
723  {
724  retNewVersion = ConfigurationManager::getConfigurationByName(name)->getNextVersion();
725  __MOUT__ << "New version for backbone member (" << name << "): " <<
726  retNewVersion << std::endl;
727  if(retNewVersion > newVersion)
728  newVersion = retNewVersion;
729  }
730 
731  __MOUT__ << "Common new backbone version found as " <<
732  newVersion << std::endl;
733 
734  //create new views from source temporary version
735  for (auto& name : backboneMemberNames)
736  {
737  //saveNewVersion makes the new version the active version
738  retNewVersion = getConfigurationInterface()->saveNewVersion(
739  getConfigurationByName(name), temporaryVersion, newVersion);
740  if(retNewVersion != newVersion)
741  {
742  __MOUT_ERR__ << "Failure! New view requested was " <<
743  newVersion << ". Mismatched new view created: " << retNewVersion << std::endl;
744  throw std::runtime_error("Mismatched temporary view created!");
745  }
746  }
747 
748  return newVersion;
749 }
750 
751 //==============================================================================
752 void ConfigurationManagerRW::testXDAQContext()
753 {
754 // //test creating config group with author, create time, and comment
755 // {
756 // __MOUT__ << std::endl;
757 //
758 // std::string groupName = "testGroup";
759 // ConfigurationGroupKey newKey;
760 // //ConfigurationGroupMetadata
761 //
762 // try
763 // {
764 // {
765 // std::map<std::string, ConfigurationVersion> members;
766 // members["ARTDAQAggregatorConfiguration"] = ConfigurationVersion(1);
767 //
768 // //ConfigurationGroupKey
769 // // saveNewConfigurationGroup
770 // // (const std::string &groupName, const std::map<std::string,
771 // // ConfigurationVersion> &groupMembers, ConfigurationGroupKey previousVersion=ConfigurationGroupKey());
772 // newKey =
773 // saveNewConfigurationGroup(groupName,members);
774 // }
775 //
776 // //std::map<std::string, ConfigurationVersion >
777 // // loadConfigurationGroup
778 // // (const std::string &configGroupName,
779 // // ConfigurationGroupKey configGroupKey, bool doActivate=false, ProgressBar* progressBar=0, std::string *accumulateWarnings=0);
780 // {
781 // std::map<std::string, ConfigurationVersion > memberMap =
782 // loadConfigurationGroup(groupName,newKey);
783 // __MOUT__ << "Group members:" << std::endl;
784 // for(const auto &member: memberMap)
785 // __MOUT__ << member.first << " " << member.second << std::endl;
786 // }
787 //
788 //
789 //
790 // //do it again
791 // {
792 // std::map<std::string, ConfigurationVersion> members;
793 // members["ARTDAQAggregatorConfiguration"] = ConfigurationVersion(1);
794 //
795 // //ConfigurationGroupKey
796 // // saveNewConfigurationGroup
797 // // (const std::string &groupName, const std::map<std::string,
798 // // ConfigurationVersion> &groupMembers, ConfigurationGroupKey previousVersion=ConfigurationGroupKey());
799 // newKey =
800 // saveNewConfigurationGroup(groupName,members);
801 // }
802 //
803 // //std::map<std::string, ConfigurationVersion >
804 // // loadConfigurationGroup
805 // // (const std::string &configGroupName,
806 // // ConfigurationGroupKey configGroupKey, bool doActivate=false, ProgressBar* progressBar=0, std::string *accumulateWarnings=0);
807 // {
808 // std::map<std::string, ConfigurationVersion > memberMap =
809 // loadConfigurationGroup(groupName,newKey);
810 // __MOUT__ << "Group members:" << std::endl;
811 // for(const auto &member: memberMap)
812 // __MOUT__ << member.first << " " << member.second << std::endl;
813 // }
814 //
815 //
816 // }
817 // catch(std::runtime_error &e)
818 // {
819 // __MOUT_ERR__ << "Failed to create config group: " << groupName << ":" << newKey << std::endl;
820 // __MOUT_ERR__ << "\n\n" << e.what() << std::endl;
821 // }
822 // catch(...)
823 // {
824 // __MOUT_ERR__ << "Failed to create config group: " << groupName << ":" << newKey << std::endl;
825 // }
826 //
827 // return;
828 // }
829 
830 // //test creating config group and reading
831 // {
832 // __MOUT__ << std::endl;
833 //
834 // auto gcfgs = theInterface_->getAllConfigurationGroupNames();
835 // __MOUT__ << "Global config size: " << gcfgs.size() << std::endl;
836 // for(auto &g:gcfgs)
837 // {
838 // __MOUT__ << "Global config " << g << std::endl;
839 // auto gcMap = theInterface_->getConfigurationGroupMembers(g);
840 //
841 // for(auto &cv:gcMap)
842 // __MOUT__ << "\tMember config " << cv.first << ":" << cv.second << std::endl;
843 // }
844 //
845 // auto cfgs = theInterface_->getAllConfigurationNames();
846 // __MOUT__ << "Sub-config size: " << cfgs.size() << std::endl;
847 // for(auto &c:cfgs)
848 // {
849 // __MOUT__ << "config " << c << std::endl;
850 // auto vs = theInterface_->getVersions(getConfigurationByName(c));
851 // for(auto &v:vs)
852 // __MOUT__ << "\tversion " << v << std::endl;
853 // }
854 //
855 // if(0) //create a global config group (storeGlobalConfiguration)
856 // {
857 // //storeGlobalConfiguration with latest of each
858 // std::map<std::string /*name*/, ConfigurationVersion /*version*/> gcMap;
859 //
860 // for(auto &c:cfgs) //for each sub-config, take latest version
861 // {
862 // auto vs = theInterface_->getVersions(getConfigurationByName(c));
863 // if(1 && vs.rbegin() != vs.rend()) //create latest!
864 // {
865 // gcMap[c] = *(vs.rbegin());
866 // __MOUT__ << "Adding config " << c << ":" << gcMap[c] << std::endl;
867 // }
868 // else if(vs.begin() != vs.end()) //create oldest!
869 // {
870 // gcMap[c] = *(vs.begin());
871 // __MOUT__ << "Adding config " << c << ":" << gcMap[c] << std::endl;
872 // }
873 // }
874 //
875 // int i = 0;
876 // bool done = false;
877 // char gcname[100];
878 // bool found;
879 // while(!done && i<1)
880 // {
881 // do //avoid conflicting global config names
882 // {
883 // found = false;
884 // sprintf(gcname,"GConfig_v%d",i++);
885 // for(auto &g:gcfgs)
886 // if(g == gcname) {found = true; break;}
887 // }
888 // while(found);
889 // __MOUT__ << "Trying Global config: " << gcname<< std::endl;
890 //
891 // try
892 // {
893 // theInterface_->saveConfigurationGroup(gcMap,gcname);
894 // done = true;
895 // __MOUT__ << "Created Global config: " << gcname<< std::endl;
896 // }
897 // catch(...) {++i;} //repeat names are not allowed, so increment name
898 // }
899 //
900 // }
901 //
902 // //return;
903 // }
904 //
905  //this is to test config tree
906  try
907  {
908  __MOUT__ << "Loading config..." << std::endl;
909  loadConfigurationGroup("FETest",ConfigurationGroupKey(2)); // Context_1
910  ConfigurationTree t = getNode("/FEConfiguration/DEFAULT/FrontEndType");
911 
912  std::string v;
913 
914  __MOUT__ << std::endl;
915  t.getValue(v);
916  __MOUT__ << "Value: " << v << std::endl;
917  __MOUT__ << "Value index: " << t.getValue<int>() << std::endl;
918 
919  return;
920 
921  //ConfigurationTree t = getNode("XDAQContextConfiguration");
922  //ConfigurationTree t = getNode("/FEConfiguration/OtsUDPFSSR3/FrontEndType");
923  //ConfigurationTree t = getNode("/FEConfiguration").getNode("OtsUDPFSSR3");
924 // ConfigurationTree t = getNode("/XDAQContextConfiguration/testContext/");
925 //
926 // __MOUT__ << std::endl;
927 // t.getValue(v);
928 // __MOUT__ << "Value: " << v << std::endl;
929 //
930 // if(!t.isValueNode())
931 // {
932 // auto C = t.getChildrenNames();
933 // for(auto &c: C)
934 // __MOUT__ << "\t+ " << c << std::endl;
935 //
936 // std::stringstream ss;
937 // t.print(-1,ss);
938 // __MOUT__ << "\n" << ss.str() << std::endl;
939 //
940 // try
941 // {
942 // ConfigurationTree tt = t.getNode("OtsUDPFSSR3");
943 // tt.getValue(v);
944 // __MOUT__ << "Value: " << v << std::endl;
945 //
946 // C = tt.getChildrenNames();
947 // for(auto &c: C)
948 // __MOUT__ << "\t+ " << c << std::endl;
949 // }
950 // catch(...)
951 // {
952 // __MOUT__ << "Failed to find extra node." << std::endl;
953 // }
954 // }
955 
956  }
957  catch(...)
958  {
959  __MOUT__ << "Failed to load config..." << std::endl;
960  }
961 
962 
963 }
964 
965 
966 
967 
968 
969 
970 
971 
972 
973 
974 
975 
976