otsdaq  v1_01_03
 All Classes Namespaces Functions
ConfigurationManager.cc
1 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
2 #include "otsdaq-core/ConfigurationInterface/ConfigurationInterface.h"//All configurable objects are included here
3 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationGroupKey.h"
4 #include "otsdaq-core/ProgressBar/ProgressBar.h"
5 
6 #include <fstream> // std::ofstream
7 
8 
9 using namespace ots;
10 
11 
12 #undef __MF_SUBJECT__
13 #define __MF_SUBJECT__ "ConfigurationManager"
14 
15 const std::string ConfigurationManager::READONLY_USER = "READONLY_USER";
16 
17 const std::string ConfigurationManager::XDAQ_CONTEXT_CONFIG_NAME = "XDAQContextConfiguration";
18 
19 //added env check for otsdaq_flatten_active_to_version to function
20 const std::string ConfigurationManager::ACTIVE_GROUP_FILENAME = ((getenv("SERVICE_DATA_PATH") == NULL)?(std::string(getenv("USER_DATA"))+"/ServiceData"):(std::string(getenv("SERVICE_DATA_PATH")))) + "/ActiveConfigurationGroups.cfg";
21 const std::string ConfigurationManager::ALIAS_VERSION_PREAMBLE = "ALIAS:";
22 const std::string ConfigurationManager::SCRATCH_VERSION_ALIAS = "Scratch";
23 
24 #define CORE_TABLE_INFO_FILENAME ((getenv("SERVICE_DATA_PATH") == NULL)?(std::string(getenv("USER_DATA"))+"/ServiceData"):(std::string(getenv("SERVICE_DATA_PATH")))) + "/CoreTableInfoNames.dat"
25 
26 
27 const std::string ConfigurationManager::ACTIVE_GROUP_NAME_CONTEXT = "Context";
28 const std::string ConfigurationManager::ACTIVE_GROUP_NAME_BACKBONE = "Backbone";
29 const std::string ConfigurationManager::ACTIVE_GROUP_NAME_CONFIGURATION = "Configuration";
30 
31 
32 //==============================================================================
33 ConfigurationManager::ConfigurationManager()
34 : username_ (ConfigurationManager::READONLY_USER)
35 , theInterface_ (0)
36 , theConfigurationGroupKey_ (0)
37 , theContextGroupKey_ (0)
38 , theBackboneGroupKey_ (0)
39 , theConfigurationGroup_ ("")
40 , theContextGroup_ ("")
41 , theBackboneGroup_ ("")
42 , contextMemberNames_ ({XDAQ_CONTEXT_CONFIG_NAME,"XDAQApplicationConfiguration","DesktopIconConfiguration","MessageFacilityConfiguration","TheSupervisorConfiguration","StateMachineConfiguration","DesktopWindowParameterConfiguration"})
43 , backboneMemberNames_ ({"GroupAliasesConfiguration","VersionAliasesConfiguration"})
44 {
45  theInterface_ = ConfigurationInterface::getInstance(false); //false to use artdaq DB
46  //NOTE: in ConfigurationManagerRW using false currently.. think about consistency! FIXME
47 
48  //initialize special group metadata table
49  {
50  //Note: "ConfigurationGroupMetadata" should never be in conflict
51  // because all other tables end in "...Configuration"
52 
53  //This is a table called ConfigurationGroupMetadata
54  // with 3 fields:
55  // - GroupAuthor
56  // - GroupCreationTime
57  // - CommentDescription
58 
59  groupMetadataTable_.setConfigurationName(ConfigurationInterface::GROUP_METADATA_TABLE_NAME);
60  //ConfigurationView* mockup = configurationGroupMetadataTable_.getMockupViewP();
61  std::vector<ViewColumnInfo>* colInfo =
62  groupMetadataTable_.getMockupViewP()->getColumnsInfoP();
63 
64 
65  colInfo->push_back(ViewColumnInfo(
66  ViewColumnInfo::TYPE_UID, //just to make init() happy
67  "UnusedUID",
68  "UNUSED_UID",
69  ViewColumnInfo::DATATYPE_NUMBER,
70  "",0
71  ));
72  colInfo->push_back(ViewColumnInfo(
73  ViewColumnInfo::TYPE_COMMENT, //just to make init() happy
74  "CommentDescription",
75  "COMMENT_DESCRIPTION",
76  ViewColumnInfo::DATATYPE_STRING,
77  "",0
78  ));
79  colInfo->push_back(ViewColumnInfo(
80  ViewColumnInfo::TYPE_AUTHOR, //just to make init() happy
81  "GroupAuthor",
82  "AUTHOR",
83  ViewColumnInfo::DATATYPE_STRING,
84  "",0
85  ));
86  colInfo->push_back(ViewColumnInfo(
87  ViewColumnInfo::TYPE_TIMESTAMP,
88  "GroupCreationTime",
89  "GROUP_CREATION_TIME",
90  ViewColumnInfo::DATATYPE_TIME,
91  "",0
92  ));
93  auto tmpVersion = groupMetadataTable_.createTemporaryView();
94  groupMetadataTable_.setActiveView(tmpVersion);
95  //only need this one and only row for all time
96  groupMetadataTable_.getViewP()->addRow();
97  }
98 
99  //dump names of core tables (so UpdateOTS.sh can copy core tables for user)
100  {
101  FILE * fp = fopen((CORE_TABLE_INFO_FILENAME).c_str(),"w");
102  if(fp)
103  {
104  for(const auto &name:contextMemberNames_)
105  fprintf(fp,"%s\n",name.c_str());
106  for(const auto &name:backboneMemberNames_)
107  fprintf(fp,"%s\n",name.c_str());
108  fclose(fp);
109  }
110  else
111  __MOUT__ << "Failed to open core table info file: " << CORE_TABLE_INFO_FILENAME << std::endl;
112  }
113 
114  init();
115 }
116 
117 //==============================================================================
118 ConfigurationManager::ConfigurationManager(const std::string& username)
120 {
121  username_ = username;
122 }
123 
124 //==============================================================================
125 ConfigurationManager::~ConfigurationManager()
126 {
127  destroy();
128 }
129 
130 //==============================================================================
131 //init
132 // if accumulatedErrors is not null.. fill it with errors
133 // else throw errors (but do not ask restoreActiveConfigurationGroups to throw errors)
134 void ConfigurationManager::init(std::string *accumulatedErrors)
135 {
136  if(accumulatedErrors) *accumulatedErrors = "";
137 
138  //destroy();
139 
140  // once Interface is false (using artdaq db) .. then can call
141  if(theInterface_->getMode() == false)
142  {
143  try
144  {
145  restoreActiveConfigurationGroups(accumulatedErrors?true:false);
146  }
147  catch(std::runtime_error &e)
148  {
149  if(accumulatedErrors) *accumulatedErrors = e.what();
150  else throw;
151  }
152  }
153 }
154 
155 //==============================================================================
156 //restoreActiveConfigurationGroups
157 // load the active groups from file
158 // Note: this should be used by the Supervisor to maintain
159 // the same configurationGroups surviving software system restarts
160 void ConfigurationManager::restoreActiveConfigurationGroups(bool throwErrors)
161 {
162  destroyConfigurationGroup("",true); //deactivate all
163 
164  std::string fn = ACTIVE_GROUP_FILENAME;
165  FILE *fp = fopen(fn.c_str(),"r");
166 
167  __MOUT__ << "ACTIVE_GROUP_FILENAME = " << ACTIVE_GROUP_FILENAME << std::endl;
168  __MOUT__ << "ARTDAQ_DATABASE_URI = " << std::string(getenv("ARTDAQ_DATABASE_URI")) << std::endl;
169 
170  if(!fp) return;
171 
172  __MOUT__ << "throwErrors: " << throwErrors << std::endl;
173 
174  char tmp[500];
175  char strVal[500];
176 
177  std::string groupName;
178  std::string errorStr = "";
179  bool skip;
180 
181  __SS__;
182 
183  for(int i=0;i<3;++i)
184  {
185  skip = false;
186  fgets(tmp,500,fp);
187  sscanf(tmp,"%s",strVal); //sscanf to remove '\n'
188  for(unsigned int j=0;j<strlen(strVal);++j)
189  if(!(
190  (strVal[j] >= 'a' && strVal[j] <= 'z') ||
191  (strVal[j] >= 'A' && strVal[j] <= 'Z') ||
192  (strVal[j] >= '0' && strVal[j] <= '9')))
193  {
194  strVal[j] = '\0';
195  __MOUT_INFO__ << "Illegal character found, so skipping!" << std::endl;
196 
197  skip = true;
198  break;
199  }
200 
201  if(skip) continue;
202 
203  groupName = strVal;
204  fgets(tmp,500,fp);
205  sscanf(tmp,"%s",strVal); //sscanf to remove '\n'
206 
207  for(unsigned int j=0;j<strlen(strVal);++j)
208  if(!(
209  (strVal[j] >= '0' && strVal[j] <= '9')))
210  {
211  strVal[j] = '\0';
212  __MOUT_INFO__ << "Illegal character found, so skipping!" << std::endl;
213 
214  skip = true;
215  break;
216  }
217 
218  if(skip) continue;
219 
220  try
221  {
222  //load and doActivate
223  loadConfigurationGroup(groupName,ConfigurationGroupKey(strVal),true);
224  }
225  catch(std::runtime_error &e)
226  {
227  ss << "Failed to load config group in ConfigurationManager::init() with name '" <<
228  groupName << "_v" << strVal << "'" << std::endl;
229  ss << e.what() << std::endl;
230 
231  errorStr += ss.str();
232  }
233  catch(...)
234  {
235  ss << "Failed to load config group in ConfigurationManager::init() with name '" <<
236  groupName << "_v" << strVal << "'" << std::endl;
237 
238  errorStr += ss.str();
239  }
240  }
241 
242  fclose(fp);
243 
244  if(throwErrors && errorStr != "")
245  {
246  __MOUT_INFO__ << "\n" << ss.str();
247  throw std::runtime_error(errorStr);
248  }
249 }
250 
251 //==============================================================================
252 //destroyConfigurationGroup
253 // destroy all if theGroup == ""
254 // else destroy that group
255 // if onlyDeactivate, then don't delete, just deactivate view
256 void ConfigurationManager::destroyConfigurationGroup(const std::string& theGroup, bool onlyDeactivate)
257 {
258  //delete
259  bool isContext = theGroup == "" || theGroup == theContextGroup_;
260  bool isBackbone = theGroup == "" || theGroup == theBackboneGroup_;
261  bool isConfiguration = theGroup == "" || theGroup == theConfigurationGroup_;
262 
263  if(!isContext && !isBackbone && !isConfiguration)
264  {
265  __MOUT__ << "Invalid configuration group to destroy: " << theGroup << std::endl;
266  throw std::runtime_error("Invalid configuration group to destroy!");
267  }
268 
269  std::string dbgHeader = onlyDeactivate?"Deactivating":"Destroying";
270  if(theGroup != "")
271  {
272  if(isContext)
273  __MOUT__ << dbgHeader << " Context group: " << theGroup << std::endl;
274  if(isBackbone)
275  __MOUT__ << dbgHeader << " Backbone group: " << theGroup << std::endl;
276  if(isConfiguration)
277  __MOUT__ << dbgHeader << " Configuration group: " << theGroup << std::endl;
278  }
279 
280  std::set<std::string>::const_iterator contextFindIt, backboneFindIt;
281  for(auto it = nameToConfigurationMap_.begin(); it != nameToConfigurationMap_.end(); /*no increment*/)
282  {
283  contextFindIt = contextMemberNames_.find(it->first);
284  backboneFindIt = backboneMemberNames_.find(it->first);
285  if(theGroup == "" || ( (isContext && contextFindIt != contextMemberNames_.end()) ||
286  (isBackbone && backboneFindIt != backboneMemberNames_.end()) ||
287  (!isContext && !isBackbone &&
288  contextFindIt == contextMemberNames_.end() &&
289  backboneFindIt == backboneMemberNames_.end())))
290  {
291  //__MOUT__ << "\t" << it->first << std::endl;
292  //if(it->second->isActive())
293  // __MOUT__ << "\t\t..._v" << it->second->getViewVersion() << std::endl;
294 
295 
296  if(onlyDeactivate) //only deactivate
297  {
298  it->second->deactivate();
299  ++it;
300  }
301  else //else, delete/erase
302  {
303  delete it->second;
304  nameToConfigurationMap_.erase(it++);
305  }
306  }
307  else
308  ++it;
309  }
310 
311  if(isConfiguration)
312  {
313  theConfigurationGroup_ = "";
314  if(theConfigurationGroupKey_ != 0)
315  {
316  __MOUT__ << "Destroying Configuration Key: " << *theConfigurationGroupKey_ << std::endl;
317  theConfigurationGroupKey_.reset();
318  }
319 
320  // theDACStreams_.clear();
321  }
322  if(isBackbone)
323  {
324  theBackboneGroup_ = "";
325  if(theBackboneGroupKey_ != 0)
326  {
327  __MOUT__ << "Destroying Backbone Key: " << *theBackboneGroupKey_ << std::endl;
328  theBackboneGroupKey_.reset();
329  }
330  }
331  if(isContext)
332  {
333  theContextGroup_ = "";
334  if(theContextGroupKey_ != 0)
335  {
336  __MOUT__ << "Destroying Context Key: " << *theContextGroupKey_ << std::endl;
337  theContextGroupKey_.reset();
338  }
339  }
340 }
341 
342 //==============================================================================
343 void ConfigurationManager::destroy(void)
344 {
345  //NOTE: Moved to ConfigurationGUISupervisor [FIXME is this correct?? should we use shared_ptr??]
346  // if( ConfigurationInterface::getInstance(true) != 0 )
347  // delete theInterface_;
348  destroyConfigurationGroup();
349 }
350 
351 
352 //==============================================================================
353 //convertGroupTypeIdToName
354 // return translation:
355 // 0 for context
356 // 1 for backbone
357 // 2 for configuration (others)
358 const std::string& ConfigurationManager::convertGroupTypeIdToName(int groupTypeId)
359 {
360  return groupTypeId==CONTEXT_TYPE?
361  ConfigurationManager::ACTIVE_GROUP_NAME_CONTEXT:
362  (groupTypeId==BACKBONE_TYPE?
363  ConfigurationManager::ACTIVE_GROUP_NAME_BACKBONE:
364  ConfigurationManager::ACTIVE_GROUP_NAME_CONFIGURATION);
365 }
366 
367 //==============================================================================
368 //getTypeOfGroup
369 // return
370 // 0 for context
371 // 1 for backbone
372 // 2 for configuration (others)
373 int ConfigurationManager::getTypeOfGroup(
374  const std::map<std::string /*name*/, ConfigurationVersion /*version*/> &memberMap)
375 {
376 
377  bool isContext = true;
378  bool isBackbone = true;
379  bool inGroup;
380  bool inContext = false;
381  bool inBackbone = false;
382  unsigned int matchCount = 0;
383 
384  for(auto &memberPair:memberMap)
385  {
386  //__MOUT__ << "Member name: = "<< memberPair.first << std::endl;
387  inGroup = false; //check context
388  for(auto &contextMemberString:contextMemberNames_)
389  if(memberPair.first == contextMemberString)
390  {
391  inGroup = true;
392  inContext = true;
393  ++matchCount;
394  break;
395  }
396  if(!inGroup)
397  {
398  isContext = false;
399  if(inContext) //there was a member in context!
400  {
401  __SS__ << "This group is an incomplete match to a Context group.\n";
402  ss << "\nTo be a Context group, the members must exactly match" <<
403  "the following members:\n";
404  int i = 0;
405  for(auto &memberName:contextMemberNames_)
406  ss << ++i << ". " << memberName << "\n";
407  __MOUT_ERR__ << "\n" << ss.str();
408  throw std::runtime_error(ss.str());
409  }
410  }
411 
412  inGroup = false; //check backbone
413  for(auto &backboneMemberString:backboneMemberNames_)
414  if(memberPair.first == backboneMemberString)
415  {
416  inGroup = true;
417  inBackbone = true;
418  ++matchCount;
419  break;
420  }
421  if(!inGroup)
422  {
423  isBackbone = false;
424  if(inBackbone) //there was a member in backbone!
425  {
426  __SS__ << "This group is an incomplete match to a Backbone group.\n";
427  ss << "\nTo be a Backbone group, the members must exactly match" <<
428  "the following members:\n";
429  int i = 0;
430  for(auto &memberName:backboneMemberNames_)
431  ss << ++i << ". " << memberName << "\n";
432  __MOUT_ERR__ << "\n" << ss.str();
433  throw std::runtime_error(ss.str());
434  }
435  }
436 
437  }
438 
439  if(isContext && matchCount != contextMemberNames_.size())
440  {
441  __SS__ << "This group is an incomplete match to a Context group: " <<
442  " Size=" << matchCount << " but should be " << contextMemberNames_.size() <<
443  std::endl;
444  ss << "\nThe members currently are...\n";
445  int i = 0;
446  for(auto &memberPair:memberMap)
447  ss << ++i << ". " << memberPair.first << "\n";
448  ss << "\nThe expected Context members are...\n";
449  i = 0;
450  for(auto &memberName:contextMemberNames_)
451  ss << ++i << ". " << memberName << "\n";
452  __MOUT_ERR__ << "\n" << ss.str();
453  throw std::runtime_error(ss.str());
454  }
455 
456  if(isBackbone && matchCount != backboneMemberNames_.size())
457  {
458  __SS__ << "This group is an incomplete match to a Backbone group: " <<
459  " Size=" << matchCount << " but should be " << backboneMemberNames_.size() <<
460  std::endl;
461  ss << "\nThe members currently are...\n";
462  int i = 0;
463  for(auto &memberPair:memberMap)
464  ss << ++i << ". " << memberPair.first << "\n";
465  ss << "\nThe expected Backbone members are...\n";
466  i = 0;
467  for(auto &memberName:backboneMemberNames_)
468  ss << ++i << ". " << memberName << "\n";
469  __MOUT_ERR__ << "\n" << ss.str();
470  throw std::runtime_error(ss.str());
471  }
472 
473  return isContext?CONTEXT_TYPE:(isBackbone?BACKBONE_TYPE:CONFIGURATION_TYPE);
474 }
475 
476 //==============================================================================
477 //getTypeNameOfGroup
478 // return string for
479 // 0 for context
480 // 1 for backbone
481 // 2 for configuration (others)
482 const std::string& ConfigurationManager::getTypeNameOfGroup(
483  const std::map<std::string /*name*/, ConfigurationVersion /*version*/> &memberMap)
484 {
485  return convertGroupTypeIdToName(getTypeOfGroup(memberMap));
486 }
487 //==============================================================================
488 //loadMemberMap
489 // loads tables given by name/version pairs in memberMap
490 // Note: does not activate them.
491 void ConfigurationManager::dumpActiveConfiguration(
492  const std::string &filePath, const std::string &dumpType) const
493 {
494  time_t rawtime = time(0);
495  __MOUT__ << "filePath = " << filePath << std::endl;
496  __MOUT__ << "dumpType = " << dumpType << std::endl;
497 
498 
499  std::ofstream fs;
500  fs.open(filePath, std::fstream::out | std::fstream::trunc);
501 
502  std::ostream *out;
503 
504  //if file was valid use it, else default to cout
505  if(fs.is_open())
506  out = &fs;
507  else
508  out = &(std::cout);
509 
510 
511  (*out) << "#################################" << std::endl;
512  (*out) << "This is an ots configuration dump.\n\n" << std::endl;
513  (*out) << "Source database is $ARTDAQ_DATABASE_URI = \t" << getenv("ARTDAQ_DATABASE_URI") << std::endl;
514  (*out) << "\nOriginal location of dump: \t" << filePath << std::endl;
515  (*out) << "Type of dump: \t" << dumpType << std::endl;
516  (*out) << "Linux time for dump: \t" << rawtime << std::endl;
517 
518  {
519  struct tm * timeinfo = localtime (&rawtime);
520  char buffer [100];
521  strftime(buffer,100,"%c %Z",timeinfo);
522  (*out) << "Display time for dump: \t" << buffer << std::endl;
523  }
524 
525 
526  //define local "lambda" functions
527  // active groups
528  // active tables
529  // active group members
530  // active table contents
531 
532  auto localDumpActiveGroups = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
533  std::map<std::string, std::pair<std::string, ConfigurationGroupKey>> activeGroups =
534  cfgMgr->getActiveConfigurationGroups();
535 
536  (*out) << "\n\n************************" << std::endl;
537  (*out) << "Active Groups:" << std::endl;
538  for(auto &group:activeGroups)
539  {
540  (*out) << "\t" << group.first << " := " <<
541  group.second.first << " (" <<
542  group.second.second << ")" << std::endl;
543  }
544  };
545 
546  auto localDumpActiveTables = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
547  std::map<std::string, ConfigurationVersion> activeTables =
548  cfgMgr->getActiveVersions();
549 
550  (*out) << "\n\n************************" << std::endl;
551  (*out) << "Active Tables:" << std::endl;
552  (*out) << "Active Tables count = " << activeTables.size() << std::endl;
553 
554  unsigned int i = 0;
555  for(auto &table:activeTables)
556  {
557  (*out) << "\t" << ++i << ". " << table.first << "-v" <<
558  table.second << std::endl;
559  }
560  };
561 
562  auto localDumpActiveGroupMembers = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
563  std::map<std::string, std::pair<std::string, ConfigurationGroupKey>> activeGroups =
564  cfgMgr->getActiveConfigurationGroups();
565  (*out) << "\n\n************************" << std::endl;
566  (*out) << "Active Group Members:" << std::endl;
567  int tableCount = 0;
568  for(auto &group:activeGroups)
569  {
570  (*out) << "\t" << group.first << " := " <<
571  group.second.first << " (" <<
572  group.second.second << ")" << std::endl;
573 
574  std::map<std::string /*name*/, ConfigurationVersion /*version*/> memberMap =
575  cfgMgr->theInterface_->getConfigurationGroupMembers(
576  ConfigurationGroupKey::getFullGroupString(
577  group.second.first,
578  group.second.second));
579 
580  (*out) << "\tMember table count = " << memberMap.size() << std::endl;
581  tableCount += memberMap.size();
582 
583  unsigned int i = 0;
584  for(auto &member:memberMap)
585  {
586  (*out) << "\t\t" << ++i << ". " << member.first << "-v" <<
587  member.second << std::endl;
588  }
589  }
590  (*out) << "\nActive Group Members total table count = " << tableCount << std::endl;
591  };
592 
593  auto localDumpActiveTableContents = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
594  std::map<std::string, ConfigurationVersion> activeTables =
595  cfgMgr->getActiveVersions();
596 
597  (*out) << "\n\n************************" << std::endl;
598  (*out) << "Active Table Contents (table count = " << activeTables.size()
599  << "):" << std::endl;
600  unsigned int i = 0;
601  for(auto &table:activeTables)
602  {
603  (*out) << "\n\n==============================================================================" << std::endl;
604  (*out) << "==============================================================================" << std::endl;
605  (*out) << "\t" << ++i << ". " << table.first << "-v" <<
606  table.second << std::endl;
607 
608  cfgMgr->nameToConfigurationMap_.find(table.first)->second->print(*out);
609  }
610  };
611 
612 
613 
614  if(dumpType == "GroupKeys")
615  {
616  localDumpActiveGroups(this,out);
617  }
618  else if(dumpType == "TableVersions")
619  {
620  localDumpActiveTables(this,out);
621  }
622  else if(dumpType == "GroupKeysAndTableVersions")
623  {
624  localDumpActiveGroups(this,out);
625  localDumpActiveTables(this,out);
626  }
627  else if(dumpType == "All")
628  {
629  localDumpActiveGroups(this,out);
630  localDumpActiveGroupMembers(this,out);
631  localDumpActiveTables(this,out);
632  localDumpActiveTableContents(this,out);
633  }
634  else
635  {
636  __SS__ << "Invalid dump type '" << dumpType <<
637  "' given during dumpActiveConfiguration(). Valid types are as follows:\n" <<
638 
639  //List all choices
640  "GroupKeys" << ", " <<
641  "TableVersions" << ", " <<
642  "GroupsKeysAndTableVersions" << ", " <<
643  "All" <<
644 
645  "\n\nPlease change the State Machine configuration to a valid dump type." <<
646  std::endl;
647  throw std::runtime_error(ss.str());
648  }
649 
650  if(fs.is_open())
651  fs.close();
652 }
653 
654 //==============================================================================
655 //loadMemberMap
656 // loads tables given by name/version pairs in memberMap
657 // Note: does not activate them.
658 void ConfigurationManager::loadMemberMap(
659  const std::map<std::string /*name*/, ConfigurationVersion /*version*/> &memberMap)
660 {
661  ConfigurationBase *tmpConfigBasePtr;
662  // for each member
663  // get()
664  for(auto &memberPair:memberMap)
665  {
666  //__MOUT__ << "\tMember config " << memberPair.first << ":" <<
667  // memberPair.second << std::endl;
668 
669  //get the proper temporary pointer
670  // use 0 if doesn't exist yet.
671  // Note: do not want to give nameToConfigurationMap_[memberPair.first]
672  // in case there is failure in get... (exceptions may be thrown)
673  //Note: Default constructor is called by Map, i.e. nameToConfigurationMap_[memberPair.first] = 0; //create pointer and set to 0
674  tmpConfigBasePtr = 0;
675  if(nameToConfigurationMap_.find(memberPair.first) != nameToConfigurationMap_.end())
676  tmpConfigBasePtr = nameToConfigurationMap_[memberPair.first];
677 
678  theInterface_->get(tmpConfigBasePtr, //configurationPtr
679  memberPair.first, //configurationName
680  0, //ConfigurationGroupKey
681  0, //configurations
682  false, //dontFill=false to fill
683  memberPair.second, //version
684  false //resetConfiguration
685  );
686 
687  nameToConfigurationMap_[memberPair.first] = tmpConfigBasePtr;
688  if(nameToConfigurationMap_[memberPair.first]->getViewP())
689  {
690  //__MOUT__ << "\t\tActivated version: " << nameToConfigurationMap_[memberPair.first]->getViewVersion() << std::endl;
691  }
692  else
693  {
694  __SS__ << nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
695  ": View version not activated properly!";
696  throw std::runtime_error(ss.str());
697  }
698  }
699 }
700 
701 //==============================================================================
702 //loadConfigurationGroup
703 // load all members of configuration group
704 // if doActivate
705 // DOES NOT theConfigurationGroup_, theContextGroup_, or theBackboneGroup_ on success
706 // this happens with ConfigurationManagerRW::activateConfigurationGroup
707 // for each member
708 // configBase->init()
709 //
710 // if progressBar != 0, then do step handling, for finer granularity
711 //
712 // if(doNotLoadMember) return memberMap; //this is useful if just getting group metadata
713 //
714 // throws exception on failure.
715 // map<name , ConfigurationVersion >
716 std::map<std::string, ConfigurationVersion> ConfigurationManager::loadConfigurationGroup(
717  const std::string &configGroupName,
718  ConfigurationGroupKey configGroupKey,
719  bool doActivate,
720  ProgressBar *progressBar,
721  std::string *accumulatedTreeErrors,
722  std::string *groupComment,
723  std::string *groupAuthor,
724  std::string *groupCreateTime,
725  bool doNotLoadMember,
726  std::string *groupTypeString)
727 {
728  if(accumulatedTreeErrors) *accumulatedTreeErrors = "";
729  if(groupComment) *groupComment = "";
730  if(groupAuthor) *groupAuthor = "";
731  if(groupCreateTime) *groupCreateTime = "";
732  if(groupTypeString) *groupTypeString = "";
733 
734  // load all members of configuration group
735  // if doActivate
736  // determine the type configuration
737  // deactivate all of that type (invalidate active view)
738  //
739  // for each member
740  // get()
741  // if doActivate, configBase->init()
742  //
743  // if doActivate
744  // set theConfigurationGroup_, theContextGroup_, or theBackboneGroup_ on success
745 
746  __MOUT_INFO__ << "Loading Configuration Group: " << configGroupName <<
747  "(" << configGroupKey << ")" << std::endl;
748 
749  std::map<std::string /*name*/, ConfigurationVersion /*version*/> memberMap =
750  theInterface_->getConfigurationGroupMembers(
751  ConfigurationGroupKey::getFullGroupString(configGroupName,configGroupKey),
752  true); //include meta data table
753 
754 
755  if(progressBar) progressBar->step();
756 
757  //remove meta data table and extract info
758  auto metaTablePair = memberMap.find(groupMetadataTable_.getConfigurationName());
759  if(metaTablePair !=
760  memberMap.end())
761  {
762  //__MOUT__ << "Found group meta data. v" << metaTablePair->second << std::endl;
763 
764  //clear table
765  while(groupMetadataTable_.getView().getNumberOfRows())
766  groupMetadataTable_.getViewP()->deleteRow(0);
767  theInterface_->fill(&groupMetadataTable_,metaTablePair->second);
768  //check that there is only 1 row
769  if(groupMetadataTable_.getView().getNumberOfRows() != 1)
770  {
771  groupMetadataTable_.print();
772  __SS__ << "groupMetadataTable_ has wrong number of rows! Must be 1." << std::endl;
773  __MOUT_ERR__ << "\n" << ss.str();
774  throw std::runtime_error(ss.str());
775  }
776  //groupMetadataTable_.print();
777 
778  memberMap.erase(metaTablePair);
779 
780  //extract fields
781  if(groupComment) *groupComment = groupMetadataTable_.getView().getValueAsString(0,1);
782  if(groupAuthor) *groupAuthor = groupMetadataTable_.getView().getValueAsString(0,2);
783  if(groupCreateTime) *groupCreateTime = groupMetadataTable_.getView().getValueAsString(0,3);
784  }
785 
786  if(progressBar) progressBar->step();
787 
788  //__MOUT__ << "memberMap loaded size = " << memberMap.size() << std::endl;
789 
790  if(doNotLoadMember) return memberMap; //this is useful if just getting group metadata
791 
792  int groupType = -1;
793 
794  //determine the type configuration group
795  groupType = getTypeOfGroup(memberMap);
796  if(groupTypeString) *groupTypeString = convertGroupTypeIdToName(groupType);
797 
798  if(doActivate)
799  {
800  std::string groupToDeactivate =
801  groupType==CONTEXT_TYPE?theContextGroup_:
802  (groupType==BACKBONE_TYPE?theBackboneGroup_:theConfigurationGroup_);
803 
804  // deactivate all of that type (invalidate active view)
805  if(groupToDeactivate != "") //deactivate only if pre-existing group
806  {
807  __MOUT__ << "groupToDeactivate '" << groupToDeactivate << "'" << std::endl;
808  destroyConfigurationGroup(groupToDeactivate,true);
809  }
810 // else
811 // {
812 // //Getting here, is kind of strange:
813 // // - this group may have only been partially loaded before?
814 // }
815  }
816 
817  if(progressBar) progressBar->step();
818 
819  //__MOUT__ << "Activating chosen group:" << std::endl;
820 
821 
822  loadMemberMap(memberMap);
823 
824  if(progressBar) progressBar->step();
825 
826  if(accumulatedTreeErrors)
827  {
828  __MOUT__ << "Checking chosen group for tree errors..." << std::endl;
829 
830  getChildren(&memberMap, accumulatedTreeErrors);
831  if(*accumulatedTreeErrors != "")
832  {
833  __MOUT_ERR__ << "Errors detected while loading Configuration Group: " << configGroupName <<
834  "(" << configGroupKey << "). Aborting." << std::endl;
835  return memberMap; //return member name map to version
836  }
837  }
838 
839  if(progressBar) progressBar->step();
840 
841  // for each member
842  // if doActivate, configBase->init()
843  if(doActivate)
844  for(auto &memberPair:memberMap)
845  {
846  //do NOT allow activating Scratch versions if tracking is ON!
847  if(ConfigurationInterface::isVersionTrackingEnabled() &&
848  memberPair.second.isScratchVersion())
849  {
850  __SS__ << "Error while activating member Table '" <<
851  nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
852  "-v" << memberPair.second <<
853  " for Configuration Group '" << configGroupName <<
854  "(" << configGroupKey << ")'. When version tracking is enabled, Scratch views" <<
855  " are not allowed! Please only use unique, persistent versions when version tracking is enabled."
856  << std::endl;
857  __MOUT_ERR__ << "\n" << ss.str();
858  throw std::runtime_error(ss.str());
859  }
860 
861 
862  //attempt to init using the configuration's specific init
863  // this could be risky user code, try and catch
864  try
865  {
866  nameToConfigurationMap_[memberPair.first]->init(this);
867  }
868  catch(std::runtime_error& e)
869  {
870  __SS__ << "Error detected calling " <<
871  nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
872  ".init()!\n\n " << e.what() << std::endl;
873  throw std::runtime_error(ss.str());
874  }
875  catch(...)
876  {
877  __SS__ << "Error detected calling " <<
878  nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
879  ".init()!\n\n " << std::endl;
880  throw std::runtime_error(ss.str());
881  }
882 
883  }
884 
885  if(progressBar) progressBar->step();
886 
887 
888  // if doActivate
889  // set theConfigurationGroup_, theContextGroup_, or theBackboneGroup_ on success
890 
891  if(doActivate)
892  {
893  if(groupType == CONTEXT_TYPE) //
894  {
895  __MOUT_INFO__ << "Context Configuration Group loaded: " << configGroupName <<
896  "(" << configGroupKey << ")" << std::endl;
897  theContextGroup_ = configGroupName;
898  theContextGroupKey_ = std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(configGroupKey));
899  }
900  else if(groupType == BACKBONE_TYPE)
901  {
902  __MOUT_INFO__ << "Backbone Configuration Group loaded: " << configGroupName <<
903  "(" << configGroupKey << ")" << std::endl;
904  theBackboneGroup_ = configGroupName;
905  theBackboneGroupKey_ = std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(configGroupKey));
906  }
907  else //is theConfigurationGroup_
908  {
909  __MOUT_INFO__ << "The Configuration Group loaded: " << configGroupName <<
910  "(" << configGroupKey << ")" << std::endl;
911  theConfigurationGroup_ = configGroupName;
912  theConfigurationGroupKey_ = std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(configGroupKey));
913  }
914  }
915 
916  if(progressBar) progressBar->step();
917  //__MOUT__ << "Load complete." << std::endl;
918  return memberMap;
919 }
920 
921 
922 //==============================================================================
923 //setActiveGlobalConfiguration
924 // get theActiveGlobalConfig_
925 // map<type, pair <groupName , ConfigurationGroupKey> >
926 //
927 // Note: invalid ConfigurationGroupKey means no active group currently
928 std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > ConfigurationManager::getActiveConfigurationGroups(void) const
929 {
930  // map<type, pair <groupName , ConfigurationGroupKey> >
931  std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > retMap;
932 
933  retMap[ConfigurationManager::ACTIVE_GROUP_NAME_CONTEXT] =
934  std::pair<std::string,ConfigurationGroupKey>(theContextGroup_ ,theContextGroupKey_ ?*theContextGroupKey_ : ConfigurationGroupKey());
935  retMap[ConfigurationManager::ACTIVE_GROUP_NAME_BACKBONE] =
936  std::pair<std::string,ConfigurationGroupKey>(theBackboneGroup_ ,theBackboneGroupKey_ ?*theBackboneGroupKey_ : ConfigurationGroupKey());
937  retMap[ConfigurationManager::ACTIVE_GROUP_NAME_CONFIGURATION] =
938  std::pair<std::string,ConfigurationGroupKey>(theConfigurationGroup_,theConfigurationGroupKey_?*theConfigurationGroupKey_: ConfigurationGroupKey());
939  return retMap;
940 }
941 
942 //==============================================================================
943 ConfigurationTree ConfigurationManager::getSupervisorConfigurationNode(
944  const std::string &contextUID, const std::string &applicationUID) const
945 {
946  return getNode(
947  "/" + getConfigurationByName(XDAQ_CONTEXT_CONFIG_NAME)->getConfigurationName() +
948  "/" + contextUID +
949  "/LinkToApplicationConfiguration/" + applicationUID +
950  "/LinkToSupervisorConfiguration");
951 }
952 
953 //==============================================================================
954 ConfigurationTree ConfigurationManager::getNode(const std::string& nodeString,
955  bool doNotThrowOnBrokenUIDLinks) const
956 {
957  //__MOUT__ << "nodeString=" << nodeString << " " << nodeString.length() << std::endl;
958 
959  //get nodeName (in case of / syntax)
960  if(nodeString.length() < 1) throw std::runtime_error("Invalid empty node name");
961 
962  bool startingSlash = (nodeString[0] == '/');
963 
964  std::string nodeName = nodeString.substr(startingSlash?1:0, nodeString.find('/',1)-(startingSlash?1:0));
965  //__MOUT__ << "nodeName=" << nodeName << " " << nodeName.length() << std::endl;
966  if(nodeName.length() < 1) throw std::runtime_error("Invalid node name: " + nodeName);
967 
968  std::string childPath = nodeString.substr(nodeName.length() + (startingSlash?1:0));
969 
970  //__MOUT__ << "childPath=" << childPath << " " << childPath.length() << std::endl;
971 
972  ConfigurationTree configTree(this, getConfigurationByName(nodeName));
973 
974  if(childPath.length() > 1)
975  return configTree.getNode(childPath,doNotThrowOnBrokenUIDLinks);
976  else
977  return configTree;
978 }
979 
980 //==============================================================================
981 //getFirstPathToNode
982 std::string ConfigurationManager::getFirstPathToNode(const ConfigurationTree &node, const std::string &startPath) const
983 //void ConfigurationManager::getFirstPathToNode(const ConfigurationTree &node, const ConfigurationTree &startNode) const
984 {
985  std::string path = "/";
986  return path;
987 }
988 
989 //==============================================================================
990 //getChildren
991 // if memberMap is passed then only consider children in the map
992 //
993 // if accumulatedTreeErrors is non null, check for disconnects occurs.
994 // check is 2 levels deep which should get to the links starting at tables.
995 std::vector<std::pair<std::string,ConfigurationTree> > ConfigurationManager::getChildren(
996  std::map<std::string, ConfigurationVersion> *memberMap,
997  std::string *accumulatedTreeErrors) const
998 {
999  std::vector<std::pair<std::string,ConfigurationTree> > retMap;
1000  if(accumulatedTreeErrors) *accumulatedTreeErrors = "";
1001 
1002  if(!memberMap || memberMap->empty()) //return all present active members
1003  {
1004  for(auto &configPair:nameToConfigurationMap_)
1005  {
1006  //__MOUT__ << configPair.first << " " << (int)(configPair.second?1:0) << std::endl;
1007 
1008  if(configPair.second->isActive()) //only consider if active
1009  {
1010  ConfigurationTree newNode(this, configPair.second);
1011 
1012 
1013  if(accumulatedTreeErrors) //check for disconnects
1014  {
1015  try
1016  {
1017  std::vector<std::pair<std::string,ConfigurationTree> > newNodeChildren =
1018  newNode.getChildren();
1019  for(auto &newNodeChild: newNodeChildren)
1020  {
1021  std::vector<std::pair<std::string,ConfigurationTree> > twoDeepChildren =
1022  newNodeChild.second.getChildren();
1023 
1024  for(auto &twoDeepChild: twoDeepChildren)
1025  {
1026  //__MOUT__ << configPair.first << " " << newNodeChild.first << " " <<
1027  // twoDeepChild.first << std::endl;
1028  if(twoDeepChild.second.isLinkNode() &&
1029  twoDeepChild.second.isDisconnected() &&
1030  twoDeepChild.second.getDisconnectedTableName() !=
1031  ViewColumnInfo::DATATYPE_LINK_DEFAULT)
1032  *accumulatedTreeErrors += "\n\nAt node '" +
1033  configPair.first + "' with entry UID '" +
1034  newNodeChild.first + "' there is a disconnected child node at link column '" +
1035  twoDeepChild.first + "'" +
1036  " that points to table named '" +
1037  twoDeepChild.second.getDisconnectedTableName() +
1038  "' ...";
1039  }
1040  }
1041  }
1042  catch(std::runtime_error &e)
1043  {
1044  *accumulatedTreeErrors += "\n\nAt node '" +
1045  configPair.first + "' error detected descending through children:\n" +
1046  e.what();
1047  }
1048  }
1049 
1050  retMap.push_back(std::pair<std::string,ConfigurationTree>(configPair.first,
1051  newNode));
1052  }
1053 
1054  //__MOUT__ << configPair.first << std::endl;
1055  }
1056  }
1057  else //return only members from the member map (they must be present and active!)
1058  {
1059 
1060  for(auto &memberPair: *memberMap)
1061  {
1062  auto mapIt = nameToConfigurationMap_.find(memberPair.first);
1063  if(mapIt == nameToConfigurationMap_.end())
1064  {
1065  __SS__ << "Get Children with member map requires a child '" <<
1066  memberPair.first << "' that is not present!" << std::endl;
1067  throw std::runtime_error(ss.str());
1068  }
1069  if(!(*mapIt).second->isActive())
1070  {
1071  __SS__ << "Get Children with member map requires a child '" <<
1072  memberPair.first << "' that is not active!" << std::endl;
1073  throw std::runtime_error(ss.str());
1074  }
1075 
1076  ConfigurationTree newNode(this, (*mapIt).second);
1077 
1078  if(accumulatedTreeErrors) //check for disconnects
1079  {
1080  try
1081  {
1082  std::vector<std::pair<std::string,ConfigurationTree> > newNodeChildren =
1083  newNode.getChildren();
1084  for(auto &newNodeChild: newNodeChildren)
1085  {
1086  std::vector<std::pair<std::string,ConfigurationTree> > twoDeepChildren =
1087  newNodeChild.second.getChildren();
1088 
1089  for(auto &twoDeepChild: twoDeepChildren)
1090  {
1091  //__MOUT__ << memberPair.first << " " << newNodeChild.first << " " <<
1092  // twoDeepChild.first << std::endl;
1093  if(twoDeepChild.second.isLinkNode() &&
1094  twoDeepChild.second.isDisconnected() &&
1095  twoDeepChild.second.getDisconnectedTableName() !=
1096  ViewColumnInfo::DATATYPE_LINK_DEFAULT)
1097  {
1098  *accumulatedTreeErrors += "\n\nAt node '" +
1099  memberPair.first + "' with entry UID '" +
1100  newNodeChild.first + "' there is a disconnected child node at link column '" +
1101  twoDeepChild.first + "'" +
1102  " that points to table named '" +
1103  twoDeepChild.second.getDisconnectedTableName() +
1104  "' ...";
1105 
1106  //check if disconnected table is in group, if not software error
1107 
1108  bool found = false;
1109  for(auto &searchMemberPair: *memberMap)
1110  if(searchMemberPair.first ==
1111  twoDeepChild.second.getDisconnectedTableName())
1112  { found = true; break;}
1113  if(!found)
1114  *accumulatedTreeErrors +=
1115  std::string("\nNote: It may be safe to ignore this error ") +
1116  "since the link's target table " +
1117  twoDeepChild.second.getDisconnectedTableName() +
1118  " is not a member of this group (and may not be loaded yet).";
1119  }
1120  }
1121  }
1122  }
1123  catch(std::runtime_error &e)
1124  {
1125  *accumulatedTreeErrors += "\n\nAt node '" +
1126  memberPair.first + "' error detected descending through children:\n" +
1127  e.what();
1128  }
1129  }
1130 
1131  retMap.push_back(std::pair<std::string,ConfigurationTree>(memberPair.first,
1132  newNode));
1133  }
1134  }
1135 
1136  return retMap;
1137 }
1138 
1139 //==============================================================================
1140 //getConfigurationByName
1141 // Get read-only pointer to configuration.
1142 // If Read/Write access is needed use ConfigurationManagerWithWriteAccess
1143 // (For general use, Write access should be avoided)
1144 const ConfigurationBase* ConfigurationManager::getConfigurationByName(const std::string &configurationName) const
1145 {
1146  std::map<std::string, ConfigurationBase*>::const_iterator it;
1147  if((it = nameToConfigurationMap_.find(configurationName)) == nameToConfigurationMap_.end())
1148  {
1149  __SS__ << "\n\nCan not find configuration named '" <<
1150  configurationName <<
1151  "'\n\n\n\nYou need to load the configuration before it can be used." <<
1152  " It probably is missing from the member list of the Configuration Group that was loaded.\n" <<
1153  "\nYou may need to enter wiz mode to remedy the situation, use the following:\n" <<
1154  "\n\t StartOTS.sh --wiz" <<
1155  "\n\n\n\n"
1156  << std::endl;
1157  //prints out too often
1158  //if(configurationName != ViewColumnInfo::DATATYPE_LINK_DEFAULT)
1159  // __MOUT_WARN__ << "\n" << ss.str();
1160  throw std::runtime_error(ss.str());
1161  }
1162  return it->second;
1163 }
1164 
1165 //==============================================================================
1166 //loadConfigurationBackbone
1167 // loads the active backbone configuration group
1168 // returns the active group key that was loaded
1169 ConfigurationGroupKey ConfigurationManager::loadConfigurationBackbone()
1170 {
1171  if(!theBackboneGroupKey_) //no active backbone
1172  {
1173  __MOUT_WARN__ << "getConfigurationGroupKey() Failed! No active backbone currently." << std::endl;
1174  return ConfigurationGroupKey();
1175  }
1176 
1177  //may already be loaded, but that's ok, load anyway to be sure
1178  loadConfigurationGroup(theBackboneGroup_,*theBackboneGroupKey_);
1179 
1180  return *theBackboneGroupKey_;
1181 }
1182 
1183 //=============================================================ConfigurationManager=================
1184 // verifies that all backbone members are loaded and have the same version
1186 //ConfigurationVersion ConfigurationManager::getConfigurationBackboneVersion(void)
1187 //{
1188 // //check versions match
1189 // //check all except version aliases since it is always latest
1190 // ConfigurationVersion v = getConfigurationByName(*(backboneMemberNames_.begin()))->getViewVersion();
1191 // for(const auto& name : backboneMemberNames_)
1192 // {
1193 // if(name == "VersionAliases" )
1194 // break;
1195 // if(v != getConfigurationByName(name)->getViewVersion())
1196 // {
1197 // __MOUT__ << "Backbone Versions do no match! " << v << " vs " <<
1198 // name << ":" <<
1199 // getConfigurationByName(name)->getViewVersion() << std::endl;
1200 // throw std::runtime_error("Backbone Versions do no match!");
1201 // }
1202 // }
1203 // return v;
1204 //}
1205 
1206 
1207 
1208 
1209 //Getters
1210 //==============================================================================
1211 //getConfigurationGroupKey
1212 // use backbone to determine default key for runType.
1213 // - runType translates to group key alias,
1214 // which maps to a group name and key pair
1215 // set
1216 //
1217 // return INVALID on failure
1218 // pair<group name , ConfigurationGroupKey>
1219 std::pair<std::string, ConfigurationGroupKey> ConfigurationManager::getConfigurationGroupFromAlias(std::string runType, ProgressBar* progressBar)
1220 {
1221  //steps
1222  // load active backbone
1223  // find runType in GroupAliasesConfiguration
1224  // return key
1225 
1226  if(progressBar) progressBar->step();
1227 
1228  loadConfigurationBackbone();
1229 
1230  if(progressBar) progressBar->step();
1231 
1232  try
1233  {
1234  // find runType in GroupAliasesConfiguration
1235  ConfigurationTree entry = getNode("GroupAliasesConfiguration").getNode(runType);
1236  return std::pair<std::string, ConfigurationGroupKey>(entry.getNode("GroupName").getValueAsString(), ConfigurationGroupKey(entry.getNode("GroupKey").getValueAsString()));
1237  }
1238  catch(...)
1239  {}
1240 
1241  if(progressBar) progressBar->step();
1242 
1243  return std::pair<std::string, ConfigurationGroupKey>("",ConfigurationGroupKey());
1244 }
1245 
1246 //==============================================================================
1247 // map<alias , pair<group name, ConfigurationGroupKey> >
1248 std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > ConfigurationManager::getGroupAliasesConfiguration(void)
1249 {
1250  restoreActiveConfigurationGroups(); //make sure the active configuration backbone is loaded!
1251  //loadConfigurationBackbone();
1252 
1253  std::map<std::string /*alias*/,
1254  std::pair<std::string /*group name*/, ConfigurationGroupKey> > retMap;
1255 
1256  std::vector<std::pair<std::string,ConfigurationTree> > entries = getNode("GroupAliasesConfiguration").getChildren();
1257  for(auto &entryPair: entries)
1258  {
1259  retMap[entryPair.first] = std::pair<std::string, ConfigurationGroupKey>(
1260  entryPair.second.getNode("GroupName").getValueAsString(),
1261  ConfigurationGroupKey(entryPair.second.getNode("GroupKey").getValueAsString()));
1262 
1263  }
1264  return retMap;
1265 }
1266 
1267 //==============================================================================
1268 //getActiveVersions
1269 std::map<std::string, ConfigurationVersion> ConfigurationManager::getActiveVersions(void) const
1270 {
1271  std::map<std::string, ConfigurationVersion> retMap;
1272  for(auto &config:nameToConfigurationMap_)
1273  {
1274  //__MOUT__ << config.first << std::endl;
1275 
1276  //check configuration pointer is not null and that there is an active view
1277  if(config.second && config.second->isActive())
1278  {
1279  //__MOUT__ << config.first << "_v" << config.second->getViewVersion() << std::endl;
1280  retMap.insert(std::pair<std::string, ConfigurationVersion>(config.first, config.second->getViewVersion()));
1281  }
1282  }
1283  return retMap;
1284 }
1285 
1287 //const DACStream& ConfigurationManager::getDACStream(std::string fecName)
1288 //{
1289 //
1290 // //fixme/todo this is called before setupAll so it breaks!
1291 // //====================================================
1292 // const DetectorConfiguration* detectorConfiguration = __GET_CONFIG__(DetectorConfiguration);
1293 // for(auto& type : detectorConfiguration->getDetectorTypes())
1294 // theDACsConfigurations_[type] = (DACsConfigurationBase*)(getConfigurationByName(type + "DACsConfiguration"));
1295 // //====================================================
1296 //
1297 // theDACStreams_[fecName].makeStream(fecName,
1298 // __GET_CONFIG__(DetectorConfiguration),
1299 // __GET_CONFIG__(DetectorToFEConfiguration),
1300 // theDACsConfigurations_,
1301 // __GET_CONFIG__(MaskConfiguration));//, theTrimConfiguration_);
1302 //
1303 // __MOUT__ << "Done with DAC stream!" << std::endl;
1304 // return theDACStreams_[fecName];
1305 //}
1306 
1307 //==============================================================================
1308 std::shared_ptr<ConfigurationGroupKey> ConfigurationManager::makeTheConfigurationGroupKey(ConfigurationGroupKey key)
1309 {
1310  if(theConfigurationGroupKey_)
1311  {
1312  if(*theConfigurationGroupKey_ != key)
1313  destroyConfigurationGroup();
1314  else
1315  return theConfigurationGroupKey_;
1316  }
1317  return std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(key));
1318 }
1319 
1320 //==============================================================================
1321 std::string ConfigurationManager::encodeURIComponent(const std::string &sourceStr)
1322 {
1323  std::string retStr = "";
1324  char encodeStr[4];
1325  for(const auto &c:sourceStr)
1326  if(
1327  (c >= 'a' && c <= 'z') ||
1328  (c >= 'A' && c <= 'Z') ||
1329  (c >= '0' && c <= '9') )
1330  retStr += c;
1331  else
1332  {
1333  sprintf(encodeStr,"%%%2.2X",c);
1334  retStr += encodeStr;
1335  }
1336  return retStr;
1337 }
1338 
1339 
1340 
1341 
1342 
1343 
1344 
1345 
1346 
1347