otsdaq  3.03.00
ConfigurationManager.cc
1 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
2 #include "artdaq/Application/LoadParameterSet.hh"
3 #include "otsdaq/ConfigurationInterface/ConfigurationInterface.h" //All configurable objects are included here
4 #include "otsdaq/ProgressBar/ProgressBar.h"
5 #include "otsdaq/TablePlugins/XDAQContextTable/XDAQContextTable.h"
6 
7 #include <fstream> // std::ofstream
8 
9 #include "otsdaq/TableCore/TableGroupKey.h"
10 #include "otsdaq/TablePlugins/DesktopIconTable.h" //for dynamic desktop icon change
11 
12 using namespace ots;
13 
14 #undef __MF_SUBJECT__
15 #define __MF_SUBJECT__ "ConfigurationManager"
16 
18 const unsigned int ConfigurationManager::PROCESSOR_COUNT =
19  std::thread::hardware_concurrency();
20 
21 const std::string ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH =
22  ((getenv("SERVICE_DATA_PATH") == NULL)
23  ? (std::string(__ENV__("USER_DATA")) + "/ServiceData")
24  : (std::string(__ENV__("SERVICE_DATA_PATH")))) +
25  "/RunControlData/";
26 const std::string ConfigurationManager::LAST_ACTIVATED_CONFIG_GROUP_FILE =
27  "CFGLastActivatedConfigGroup.hist";
28 const std::string ConfigurationManager::LAST_ACTIVATED_CONTEXT_GROUP_FILE =
29  "CFGLastActivatedContextGroup.hist";
30 const std::string ConfigurationManager::LAST_ACTIVATED_BACKBONE_GROUP_FILE =
31  "CFGLastActivatedBackboneGroup.hist";
32 const std::string ConfigurationManager::LAST_ACTIVATED_ITERATOR_GROUP_FILE =
33  "CFGLastActivatedIteratorGroup.hist";
34 
35 const std::string ConfigurationManager::READONLY_USER = "READONLY_USER";
36 
37 const std::string ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME = "XDAQContextTable";
38 const std::string ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME =
39  "XDAQApplicationTable";
40 const std::string ConfigurationManager::XDAQ_APP_PROPERTY_TABLE_NAME =
41  "XDAQApplicationPropertyTable";
42 const std::string ConfigurationManager::GROUP_ALIASES_TABLE_NAME = "GroupAliasesTable";
43 const std::string ConfigurationManager::VERSION_ALIASES_TABLE_NAME =
44  "VersionAliasesTable";
45 const std::string ConfigurationManager::ARTDAQ_TOP_TABLE_NAME = "ARTDAQSupervisorTable";
46 const std::string ConfigurationManager::DESKTOP_ICON_TABLE_NAME = "DesktopIconTable";
47 
50  ((getenv("SERVICE_DATA_PATH") == NULL)
51  ? (std::string(__ENV__("USER_DATA")) + "/ServiceData")
52  : (std::string(__ENV__("SERVICE_DATA_PATH")))) +
53  "/ActiveTableGroups.cfg";
54 const std::string ConfigurationManager::ALIAS_VERSION_PREAMBLE = "ALIAS:";
55 const std::string ConfigurationManager::SCRATCH_VERSION_ALIAS = "Scratch";
56 
57 const std::string ConfigurationManager::GROUP_TYPE_NAME_CONTEXT = "Context";
58 const std::string ConfigurationManager::GROUP_TYPE_NAME_BACKBONE = "Backbone";
59 const std::string ConfigurationManager::GROUP_TYPE_NAME_ITERATE = "Iterate";
60 const std::string ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION = "Configuration";
61 const std::string ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN = "UNKNOWN";
62 
63 const std::string ConfigurationManager::UNKNOWN_INFO = "UNKNOWN";
64 const std::string ConfigurationManager::UNKNOWN_TIME = "0";
65 
66 const uint8_t ConfigurationManager::METADATA_COL_ALIASES = 1;
67 const uint8_t ConfigurationManager::METADATA_COL_COMMENT = 2;
68 const uint8_t ConfigurationManager::METADATA_COL_AUTHOR = 3;
69 const uint8_t ConfigurationManager::METADATA_COL_TIMESTAMP = 4;
70 
71 const std::string ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE =
72  "SubsystemUserDataPathsTable";
73 const std::set<std::string> ConfigurationManager::fixedContextMemberNames_ = {
74  ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME,
75  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME,
76  "XDAQApplicationPropertyTable",
77  ConfigurationManager::DESKTOP_ICON_TABLE_NAME,
78  "MessageFacilityTable",
79  "GatewaySupervisorTable",
80  "StateMachineTable",
81  "DesktopWindowParameterTable",
82  "SlowControlsDashboardSupervisorTable"};
83 const std::set<std::string> ConfigurationManager::backboneMemberNames_ = {
84  ConfigurationManager::GROUP_ALIASES_TABLE_NAME,
85  ConfigurationManager::VERSION_ALIASES_TABLE_NAME};
86 const std::set<std::string> ConfigurationManager::iterateMemberNames_ = {
87  "IterateTable",
88  "IterationPlanTable",
89  "IterationTargetTable",
90  /*command specific tables*/ "IterationCommandBeginLabelTable",
91  "IterationCommandChooseFSMTable",
92  "IterationCommandConfigureAliasTable",
93  "IterationCommandConfigureGroupTable",
94  "IterationCommandExecuteFEMacroTable",
95  "IterationCommandExecuteMacroTable",
96  "IterationCommandMacroDimensionalLoopTable",
97  "IterationCommandMacroDimensionalLoopParameterTable",
98  "IterationCommandModifyGroupTable",
99  "IterationCommandRepeatLabelTable",
100  "IterationCommandRunTable"};
101 
102 //==============================================================================
103 ConfigurationManager::ConfigurationManager(bool initForWriteAccess /*=false*/,
104  bool doInitializeFromFhicl /*=false*/)
105  : startClockTime_(std::chrono::steady_clock::now())
106  , deltaClockTime_(std::chrono::steady_clock::now())
107  , mfSubject_(ConfigurationManager::READONLY_USER)
108  , username_(ConfigurationManager::READONLY_USER)
109  , theInterface_(0)
110  , theConfigurationTableGroupKey_(0)
111  , theContextTableGroupKey_(0)
112  , theBackboneTableGroupKey_(0)
113  , theConfigurationTableGroup_("")
114  , theContextTableGroup_("")
115  , theBackboneTableGroup_("")
116  , groupMetadataTable_(true /*special table*/, TableBase::GROUP_METADATA_TABLE_NAME)
117 {
118  __GEN_COUTTV__(runTimeSeconds());
119  theInterface_ = ConfigurationInterface::getInstance(
120  ConfigurationInterface::CONFIGURATION_MODE::
121  ARTDAQ_DATABASE); // false to use artdaq DB
122 
123  __GEN_COUTTV__(runTimeSeconds());
124 
125  // // initialize special group metadata table
126  // {
127  // // Note: "TableGroupMetadata" should never be in conflict
128  // // because all other tables end in "...Table"
129 
130  // // This is a table called TableGroupMetadata
131  // // with 4 fields:
132  // // - GroupAliases
133  // // - GroupAuthor
134  // // - GroupCreationTime
135  // // - CommentDescription
136 
137  // groupMetadataTable_.setTableName(
138  // TableBase::GROUP_METADATA_TABLE_NAME);
139  // std::vector<TableViewColumnInfo>* colInfo =
140  // groupMetadataTable_.getMockupViewP()->getColumnsInfoP();
141  // colInfo->push_back(TableViewColumnInfo(
142  // TableViewColumnInfo::TYPE_UID, // just to make init() happy
143  // "UnusedUID",
144  // "UNUSED_UID",
145  // TableViewColumnInfo::DATATYPE_NUMBER,
146  // 0 /*Default*/,
147  // "",
148  // 0 /*Min*/,
149  // 0 /*Max*/,
150  // 0));
151  // colInfo->push_back(TableViewColumnInfo(TableViewColumnInfo::TYPE_DATA,
152  // "GroupAliases",
153  // "GROUP_ALIASES",
154  // TableViewColumnInfo::DATATYPE_STRING,
155  // 0 /*Default*/,
156  // "",
157  // 0 /*Min*/,
158  // 0 /*Max*/,
159  // 0));
160  // colInfo->push_back(TableViewColumnInfo(
161  // TableViewColumnInfo::TYPE_COMMENT, // just to make init() happy
162  // TableViewColumnInfo::COL_NAME_COMMENT,
163  // "COMMENT_DESCRIPTION",
164  // TableViewColumnInfo::DATATYPE_STRING,
165  // 0 /*Default*/,
166  // "",
167  // 0 /*Min*/,
168  // 0 /*Max*/,
169  // 0));
170  // colInfo->push_back(TableViewColumnInfo(
171  // TableViewColumnInfo::TYPE_AUTHOR, // just to make init() happy
172  // "GroupAuthor",
173  // "AUTHOR",
174  // TableViewColumnInfo::DATATYPE_STRING,
175  // 0 /*Default*/,
176  // "",
177  // 0 /*Min*/,
178  // 0 /*Max*/,
179  // 0));
180  // colInfo->push_back(TableViewColumnInfo(TableViewColumnInfo::TYPE_TIMESTAMP,
181  // "GroupCreationTime",
182  // "GROUP_CREATION_TIME",
183  // TableViewColumnInfo::DATATYPE_TIME,
184  // 0 /*Default*/,
185  // "",
186  // 0 /*Min*/,
187  // 0 /*Max*/,
188  // 0));
189  // auto tmpVersion = groupMetadataTable_.createTemporaryView();
190  // groupMetadataTable_.setActiveView(tmpVersion);
191  // // only need this one and only row for all time
192  // groupMetadataTable_.getViewP()->addRow();
193  // }
194 
195  if(doInitializeFromFhicl)
196  {
197  // create tables and fill based on fhicl
198  initializeFromFhicl(__ENV__("CONFIGURATION_INIT_FCL"));
199  return;
200  }
201  // else do normal init
202 
203  __GEN_COUTTV__(runTimeSeconds());
204  if(!initForWriteAccess) //ConfigurationManagerRW can do manual init later when it calls getAllTableInfo(true)
205  init(0 /*accumulatedErrors*/, initForWriteAccess);
206  __GEN_COUTTV__(runTimeSeconds());
207 
208 } // end constructor()
209 
210 //==============================================================================
211 ConfigurationManager::ConfigurationManager(const std::string& username)
212  : ConfigurationManager(true /*initForWriteAccess*/)
213 {
214  __GEN_COUT__ << "Private constructor for write access called." << __E__;
215  // overwrite read-only username initialization with write-access username:
216  mfSubject_ = username;
217  username_ = username;
218 } // end constructor(username)
219 
220 //==============================================================================
221 ConfigurationManager::~ConfigurationManager() { destroy(); }
222 
223 //==============================================================================
229 void ConfigurationManager::init(std::string* accumulatedErrors /*=0*/,
230  bool initForWriteAccess /*= false*/,
231  std::string* accumulatedWarnings /*=0*/)
232 {
233  // if(accumulatedErrors)
234  // *accumulatedErrors = "";
235 
236  // destroy();
237 
238  // once Interface is false (using artdaq db) ..
239  // then can test (configurationInterface_->getMode() == false)
240  {
241  try
242  {
243  __GEN_COUTTV__(username_);
244 
245  // if write access, then load all specified table groups (including configuration group),
246  // otherwise skip configuration group. Important to consider initForWriteAccess
247  // because this may be called before username_ is properly initialized
248  ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext =
249  ConfigurationManager::LoadGroupType::ALL_TYPES;
250  if(username_ == ConfigurationManager::READONLY_USER && !initForWriteAccess)
251  onlyLoadIfBackboneOrContext =
252  ConfigurationManager::LoadGroupType::ONLY_BACKBONE_OR_CONTEXT_TYPES;
253 
254  // clang-format off
255  restoreActiveTableGroups(accumulatedErrors ? true : false /*throwErrors*/,
256  "" /*pathToActiveGroupsFile*/,
257  onlyLoadIfBackboneOrContext,
258  accumulatedWarnings);
259  // clang-format on
260  }
261  catch(std::runtime_error& e)
262  {
263  __GEN_COUT_ERR__ << "Error caught in init(): " << e.what();
264  if(accumulatedErrors)
265  *accumulatedErrors += e.what();
266  else
267  {
268  __SS__ << e.what(); // add line number of rethrow
269  __SS_ONLY_THROW__;
270  }
271  }
272  }
273 } // end init()
274 
275 //==============================================================================
281  bool throwErrors /*=false*/,
282  const std::string& pathToActiveGroupsFile /*=""*/,
283  ConfigurationManager::LoadGroupType
284  onlyLoadIfBackboneOrContext /*= ConfigurationManager::LoadGroupType::ALL_TYPES */,
285  std::string* accumulatedWarnings /*=0*/)
286 {
287  destroyTableGroup("", true); // deactivate all
288 
289  std::string fn =
290  pathToActiveGroupsFile == "" ? ACTIVE_GROUPS_FILENAME : pathToActiveGroupsFile;
291  FILE* fp = fopen(fn.c_str(), "r");
292 
293  __GEN_COUT__ << "ACTIVE_GROUPS_FILENAME = " << fn << __E__;
294  __GEN_COUT__ << "ARTDAQ_DATABASE_URI = "
295  << std::string(__ENV__("ARTDAQ_DATABASE_URI")) << __E__;
296 
297  if(!fp)
298  {
299  __GEN_COUT_WARN__ << "No active groups file found at " << fn << __E__;
300  return;
301  }
302 
303  //__GEN_COUT__ << "throwErrors: " << throwErrors << __E__;
304 
305  char tmp[500];
306  char strVal[500];
307 
308  std::string groupName;
309  std::string errorStr = "";
310  bool skip;
311 
312  __SS__;
313 
314  while(fgets(tmp, 500, fp))
315  {
316  // do check for out of sync.. i.e. name is a number
317  {
318  int numberCheck = 0;
319  sscanf(tmp, "%d", &numberCheck);
320  if(numberCheck)
321  {
322  __GEN_COUT__
323  << "Out of sync with active groups file lines, attempting to resync."
324  << __E__;
325  continue;
326  }
327  }
328 
329  skip = false;
330  sscanf(tmp, "%s", strVal); // sscanf to remove '\n'
331  for(unsigned int j = 0; j < strlen(strVal); ++j)
332  if(!((strVal[j] >= 'a' && strVal[j] <= 'z') ||
333  (strVal[j] >= 'A' && strVal[j] <= 'Z') ||
334  (strVal[j] >= '0' && strVal[j] <= '9')))
335  {
336  strVal[j] = '\0';
337  __GEN_COUT_INFO__ << "Illegal character found in group name '" << strVal
338  << "', so skipping! Check active groups file: " << fn
339  << __E__;
340 
341  skip = true;
342  break;
343  }
344 
345  if(skip)
346  continue;
347 
348  groupName = strVal;
349  fgets(tmp, 500, fp);
350  sscanf(tmp, "%s", strVal); // sscanf to remove '\n'
351 
352  for(unsigned int j = 0; j < strlen(strVal); ++j)
353  if(!((strVal[j] >= '0' && strVal[j] <= '9')))
354  {
355  strVal[j] = '\0';
356 
357  if(groupName.size() > 3) // notify if seems like a real group name
358  __GEN_COUT_INFO__
359  << "Skipping active group with illegal character in group key '"
360  << strVal << ".' Check active groups file: " << fn << __E__;
361 
362  skip = true;
363  break;
364  }
365 
366  if(groupName.size() <= 3)
367  continue; //skip illegal group names
368 
369  if(skip)
370  continue;
371 
372  try
373  {
375  }
376  catch(...)
377  {
378  __GEN_COUT__
379  << "illegal group according to TableGroupKey::getFullGroupString... "
380  "Check active groups file: "
381  << fn << __E__;
382  skip = true;
383  }
384 
385  if(skip)
386  continue;
387 
388  try
389  {
390  // load and doActivate
391  std::string groupAccumulatedErrors = "";
392 
393  if(accumulatedWarnings)
394  __GEN_COUT__ << "Ignoring warnings while loading and activating group '"
395  << groupName << "(" << strVal << ")'" << __E__;
396 
398  groupName,
399  TableGroupKey(strVal),
400  true /*doActivate*/,
401  0 /*groupMembers*/,
402  0 /*progressBar*/,
403  (accumulatedWarnings ? &groupAccumulatedErrors
404  : 0) /*accumulateWarnings = 0*/,
405  0 /*groupComment = 0*/,
406  0 /*groupAuthor = 0*/,
407  0 /*groupCreateTime = 0*/,
408  0 /*doNotLoadMembers = false*/,
409  0 /*groupTypeString = 0*/,
410  0 /*groupAliases = 0*/,
411  onlyLoadIfBackboneOrContext /*onlyLoadIfBackboneOrContext = false*/
412  );
413 
414  if(accumulatedWarnings)
415  *accumulatedWarnings += groupAccumulatedErrors;
416  }
417  catch(std::runtime_error& e)
418  {
419  ss << "Failed to load group in ConfigurationManager::init() with name '"
420  << groupName << "(" << strVal
421  << ")' specified active by active groups file: " << fn << __E__;
422  ss << e.what() << __E__;
423 
424  errorStr += ss.str();
425  }
426  catch(...)
427  {
428  ss << "Failed to load group in ConfigurationManager::init() with name '"
429  << groupName << "(" << strVal
430  << ")' specified active by active groups file: " << fn << __E__;
431  try
432  {
433  throw;
434  } //one more try to printout extra info
435  catch(const std::exception& e)
436  {
437  ss << "Exception message: " << e.what();
438  }
439  catch(...)
440  {
441  }
442  errorStr += ss.str();
443  }
444  }
445 
446  fclose(fp);
447 
448  if(throwErrors && errorStr != "")
449  {
450  __SS__ << "\n" << errorStr;
451  __SS_ONLY_THROW__;
452  }
453  else if(errorStr != "")
454  __GEN_COUT_INFO__ << "\n" << errorStr;
455 
456 } // end restoreActiveTableGroups()
457 
458 //==============================================================================
463 void ConfigurationManager::destroyTableGroup(const std::string& theGroup,
464  bool onlyDeactivate)
465 {
466  // delete
467  bool isContext = theGroup == "" || theGroup == theContextTableGroup_;
468  bool isBackbone = theGroup == "" || theGroup == theBackboneTableGroup_;
469  bool isIterate = theGroup == "" || theGroup == theIterateTableGroup_;
470  bool isConfiguration = theGroup == "" || theGroup == theConfigurationTableGroup_;
471 
472  if(!isContext && !isBackbone && !isIterate && !isConfiguration)
473  {
474  __SS__ << "Invalid configuration group to destroy: " << theGroup << __E__;
475  __GEN_COUT_ERR__ << ss.str();
476  __SS_THROW__;
477  }
478 
479  std::string dbgHeader = onlyDeactivate ? "Deactivating" : "Destroying";
480  if(theGroup != "")
481  {
482  if(isContext)
483  __GEN_COUT__ << dbgHeader << " Context group: " << theGroup << __E__;
484  if(isBackbone)
485  __GEN_COUT__ << dbgHeader << " Backbone group: " << theGroup << __E__;
486  if(isIterate)
487  __GEN_COUT__ << dbgHeader << " Iterate group: " << theGroup << __E__;
488  if(isConfiguration)
489  __GEN_COUT__ << dbgHeader << " Configuration group: " << theGroup << __E__;
490  }
491 
492  getActiveContextMemberNames(); // make sure active contextMemberNames_ are up to date
493 
494  std::set<std::string>::const_iterator contextFindIt, backboneFindIt, iterateFindIt;
495  for(auto it = nameToTableMap_.begin(); it != nameToTableMap_.end();
496  /*no increment*/)
497  {
498  contextFindIt = contextMemberNames_.find(it->first);
499  backboneFindIt = backboneMemberNames_.find(it->first);
500  iterateFindIt = iterateMemberNames_.find(it->first);
501 
502  __GEN_COUTT__ << "Considering table: " << it->first << " contextFindIt:"
503  << (contextFindIt != contextMemberNames_.end() ? "Y" : "N")
504  << " backboneFindIt:"
505  << (backboneFindIt != backboneMemberNames_.end() ? "Y" : "N")
506  << " iterateFindIt:"
507  << (iterateFindIt != iterateMemberNames_.end() ? "Y" : "N")
508  << __E__;
509  if(theGroup == "" ||
510  ((isContext &&
511  contextFindIt !=
512  contextMemberNames_
513  .end()) || //for context group, deactivate context members AND optional member
514  (isContext &&
515  it->first ==
517  CONTEXT_SUBSYSTEM_OPTIONAL_TABLE) || //optional context member
518  (isBackbone && backboneFindIt != backboneMemberNames_.end()) ||
519  (isIterate && iterateFindIt != iterateMemberNames_.end()) ||
520  (isConfiguration && //for configuration group, deactivate all tables not specified in other group types
521  contextFindIt == contextMemberNames_.end() &&
522  it->first != ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE &&
523  backboneFindIt == backboneMemberNames_.end() &&
524  iterateFindIt == iterateMemberNames_.end())))
525  {
526  __GEN_COUTT__ << "\t" << dbgHeader << ".. " << it->first
527  << (it->second->isActive()
528  ? "_v" + it->second->getViewVersion().str()
529  : "")
530  << __E__;
531 
532  if(onlyDeactivate) // only deactivate
533  {
534  it->second->deactivate();
535  ++it;
536  }
537  else // else, delete/erase
538  {
539  delete it->second;
540  nameToTableMap_.erase(it++);
541  }
542  }
543  else
544  ++it;
545  }
546 
547  if(isConfiguration)
548  {
549  theConfigurationTableGroup_ = "";
550  if(theConfigurationTableGroupKey_ != 0)
551  {
552  __GEN_COUT__ << "Destroying Configuration Key: "
553  << *theConfigurationTableGroupKey_ << __E__;
554  theConfigurationTableGroupKey_.reset();
555  }
556  }
557  if(isBackbone)
558  {
559  theBackboneTableGroup_ = "";
560  if(theBackboneTableGroupKey_ != 0)
561  {
562  __GEN_COUT__ << "Destroying Backbone Key: " << *theBackboneTableGroupKey_
563  << __E__;
564  theBackboneTableGroupKey_.reset();
565  }
566  }
567  if(isIterate)
568  {
569  theIterateTableGroup_ = "";
570  if(theIterateTableGroupKey_ != 0)
571  {
572  __GEN_COUT__ << "Destroying Iterate Key: " << *theIterateTableGroupKey_
573  << __E__;
574  theIterateTableGroupKey_.reset();
575  }
576  }
577  if(isContext)
578  {
579  theContextTableGroup_ = "";
580  if(theContextTableGroupKey_ != 0)
581  {
582  __GEN_COUT__ << "Destroying Context Key: " << *theContextTableGroupKey_
583  << __E__;
584  theContextTableGroupKey_.reset();
585  }
586  }
587 } //end destroyTableGroup()
588 
589 //==============================================================================
590 void ConfigurationManager::destroy(void) { destroyTableGroup(); } //end destroy()
591 
592 //==============================================================================
599  const ConfigurationManager::GroupType& groupTypeId)
600 {
601  return groupTypeId == ConfigurationManager::GroupType::CONTEXT_TYPE
602  ? ConfigurationManager::GROUP_TYPE_NAME_CONTEXT
603  : (groupTypeId == ConfigurationManager::GroupType::BACKBONE_TYPE
604  ? ConfigurationManager::GROUP_TYPE_NAME_BACKBONE
605  : (groupTypeId == ConfigurationManager::GroupType::ITERATE_TYPE
606  ? ConfigurationManager::GROUP_TYPE_NAME_ITERATE
607  : (groupTypeId == ConfigurationManager::GroupType::
608  CONFIGURATION_TYPE
609  ? ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION
610  : ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN)));
611 } // end convertGroupTypeToName()
612 
613 //==============================================================================
620 ConfigurationManager::GroupType ConfigurationManager::getTypeOfGroup(
621  const std::map<std::string /*name*/, TableVersion /*version*/>& memberMap)
622 {
623  bool isContext = true;
624  bool isBackbone = true;
625  bool isIterate = true;
626  bool inGroup;
627  bool inContext = false;
628  bool inBackbone = false;
629  bool inIterate = false;
630  unsigned int matchCount = 0;
631 
632  for(auto& memberPair : memberMap)
633  {
634  //__COUT__ << "Member name: = "<< memberPair.first << __E__;
636  inGroup = false; // check context
637  if(memberPair.first == CONTEXT_SUBSYSTEM_OPTIONAL_TABLE)
638  {
639  inGroup = true;
640  inContext = true;
641  }
642  else
643  for(auto& contextMemberString : fixedContextMemberNames_)
644  if(memberPair.first == contextMemberString)
645  {
646  inGroup = true;
647  inContext = true;
648  ++matchCount;
649  break;
650  }
651  if(!inGroup)
652  {
653  isContext = false;
654  if(inContext) // there was a member in context!
655  {
656  __SS__ << "This group is an incomplete match to a Context group.\n";
657  ss << "\nTo be a Context group, the members must exactly match "
658  << "the following members (w/ or wo/ the optional table "
659  << CONTEXT_SUBSYSTEM_OPTIONAL_TABLE << "):\n";
660  int i = 0;
661  for(const auto& memberName : fixedContextMemberNames_)
662  ss << ++i << ". " << memberName << "\n";
663  ss << "\nThe members are as follows::\n";
664  i = 0;
665  for(const auto& memberPairTmp : memberMap)
666  ss << ++i << ". " << memberPairTmp.first << "\n";
667  __SS_ONLY_THROW__;
668  }
669  }
670 
672  inGroup = false; // check backbone
673  for(auto& backboneMemberString : backboneMemberNames_)
674  if(memberPair.first == backboneMemberString)
675  {
676  inGroup = true;
677  inBackbone = true;
678  ++matchCount;
679  break;
680  }
681  if(!inGroup)
682  {
683  isBackbone = false;
684  if(inBackbone) // there was a member in backbone!
685  {
686  __SS__ << "This group is an incomplete match to a Backbone group.\n";
687  ss << "\nTo be a Backbone group, the members must exactly match "
688  << "the following members:\n";
689  int i = 0;
690  for(auto& memberName : backboneMemberNames_)
691  ss << ++i << ". " << memberName << "\n";
692  ss << "\nThe members are as follows::\n";
693  i = 0;
694  for(const auto& memberPairTmp : memberMap)
695  ss << ++i << ". " << memberPairTmp.first << "\n";
696  //__COUT_ERR__ << "\n" << ss.str();
697  __SS_ONLY_THROW__;
698  }
699  }
700 
702  inGroup = false; // check iterate
703  for(auto& iterateMemberString : iterateMemberNames_)
704  if(memberPair.first == iterateMemberString)
705  {
706  inGroup = true;
707  inIterate = true;
708  ++matchCount;
709  break;
710  }
711  if(!inGroup)
712  {
713  isIterate = false;
714  if(inIterate) // there was a member in iterate!
715  {
716  __SS__ << "This group is an incomplete match to a Iterate group.\n";
717  ss << "\nTo be a Iterate group, the members must exactly match "
718  << "the following members:\n";
719  int i = 0;
720  for(auto& memberName : iterateMemberNames_)
721  ss << ++i << ". " << memberName << "\n";
722  ss << "\nThe members are as follows::\n";
723  i = 0;
724  for(const auto& memberPairTmp : memberMap)
725  ss << ++i << ". " << memberPairTmp.first << "\n";
726  //__COUT_ERR__ << "\n" << ss.str();
727  __SS_ONLY_THROW__;
728  }
729  }
730  }
731 
732  if((isContext || inContext) && matchCount != fixedContextMemberNames_.size())
733  {
734  __SS__ << "This group is an incomplete match to a Context group: "
735  << " Size=" << matchCount << " but should be "
736  << fixedContextMemberNames_.size() << __E__;
737  ss << "\nThe members currently are...\n";
738  int i = 0;
739  for(auto& memberPair : memberMap)
740  ss << ++i << ". " << memberPair.first << "\n";
741  ss << "\nThe expected Context members are...\n";
742  i = 0;
743  for(auto& memberName : fixedContextMemberNames_)
744  ss << ++i << ". " << memberName << "\n";
745  ss << "optional. (" << CONTEXT_SUBSYSTEM_OPTIONAL_TABLE << ")\n";
746  //__COUT_ERR__ << "\n" << ss.str();
747  __SS_ONLY_THROW__;
748  }
749 
750  if((isBackbone || inBackbone) && matchCount != backboneMemberNames_.size())
751  {
752  __SS__ << "This group is an incomplete match to a Backbone group: "
753  << " Size=" << matchCount << " but should be "
754  << backboneMemberNames_.size() << __E__;
755  ss << "\nThe members currently are...\n";
756  int i = 0;
757  for(auto& memberPair : memberMap)
758  ss << ++i << ". " << memberPair.first << "\n";
759  ss << "\nThe expected Backbone members are...\n";
760  i = 0;
761  for(auto& memberName : backboneMemberNames_)
762  ss << ++i << ". " << memberName << "\n";
763  //__COUT_ERR__ << "\n" << ss.str();
764  __SS_ONLY_THROW__;
765  }
766 
767  if((isIterate || inIterate) && matchCount != iterateMemberNames_.size())
768  {
769  __SS__ << "This group is an incomplete match to a Iterate group: "
770  << " Size=" << matchCount << " but should be "
771  << iterateMemberNames_.size() << __E__;
772  ss << "\nThe members currently are...\n";
773  int i = 0;
774  for(auto& memberPair : memberMap)
775  ss << ++i << ". " << memberPair.first << "\n";
776  ss << "\nThe expected Iterate members are...\n";
777  i = 0;
778  for(auto& memberName : iterateMemberNames_)
779  ss << ++i << ". " << memberName << "\n";
780  //__COUT_ERR__ << "\n" << ss.str();
781  __SS_ONLY_THROW__;
782  }
783 
784  return isContext
785  ? ConfigurationManager::GroupType::CONTEXT_TYPE
786  : (isBackbone
787  ? ConfigurationManager::GroupType::BACKBONE_TYPE
788  : (isIterate
789  ? ConfigurationManager::GroupType::ITERATE_TYPE
790  : ConfigurationManager::GroupType::CONFIGURATION_TYPE));
791 } // end getTypeOfGroup()
792 
793 //==============================================================================
797  const std::map<std::string /*name*/, TableVersion /*version*/>& memberMap)
798 {
799  return convertGroupTypeToName(getTypeOfGroup(memberMap));
800 } // end getTypeNameOfGroup()
801 
802 //==============================================================================
808 #define OUT out << tabStr << commentStr
809 #define PUSHTAB tabStr += "\t"
810 #define POPTAB tabStr.resize(tabStr.size() - 1)
811 #define PUSHCOMMENT commentStr += "# "
812 #define POPCOMMENT commentStr.resize(commentStr.size() - 2)
813 
814 void ConfigurationManager::dumpMacroMakerModeFhicl()
815 {
816  std::string filepath =
817  __ENV__("USER_DATA") + std::string("/") + "MacroMakerModeConfigurations";
818  mkdir(filepath.c_str(), 0755);
819  filepath += "/MacroMakerModeFhiclDump.fcl";
820  __GEN_COUT__ << "dumpMacroMakerModeFhicl: " << filepath << __E__;
821 
823  // generate MacroMaker mode fhicl file
824  std::fstream out;
825 
826  std::string tabStr = "";
827  std::string commentStr = "";
828 
829  out.open(filepath, std::fstream::out | std::fstream::trunc);
830  if(out.fail())
831  {
832  __SS__ << "Failed to open MacroMaker mode fcl file for configuration dump: "
833  << filepath << __E__;
834  __SS_THROW__;
835  }
836 
837  try
838  {
839  std::vector<std::pair<std::string, ConfigurationTree>> fes =
840  getNode("FEInterfaceTable").getChildren();
841 
842  for(auto& fe : fes)
843  {
844  // skip status false
845  if(!fe.second.status())
846  continue;
847 
848  //__GEN_COUTV__(fe.first);
849 
850  OUT << fe.first << ": {" << __E__;
851  PUSHTAB;
852 
853  // only do FEInterfacePluginName and LinkToFETypeTable at top level
854 
855  OUT << "FEInterfacePluginName"
856  << ": \t"
857  << "\"" << fe.second.getNode("FEInterfacePluginName").getValueAsString()
858  << "\"" << __E__;
859 
860  recursiveTreeToFhicl(
861  fe.second.getNode("LinkToFETypeTable"), out, tabStr, commentStr);
862 
863  POPTAB;
864  OUT << "} //end " << fe.first << __E__ << __E__;
865 
866  } // end fe handling
867  }
868  catch(...)
869  {
870  __SS__ << "Failed to complete MacroMaker mode fcl "
871  "file configuration dump due to error."
872  << __E__;
873  try
874  {
875  throw;
876  } //one more try to printout extra info
877  catch(const std::runtime_error& e)
878  {
879  ss << "Exception message: " << e.what();
880  }
881  catch(const std::exception& e)
882  {
883  ss << "Exception message: " << e.what();
884  }
885  __GEN_COUT_ERR__ << ss.str();
886  }
887 
888  out.close();
889  // end fhicl output
890 } // end dumpMacroMakerModeFhicl()
891 
892 //==============================================================================
901 void ConfigurationManager::recursiveTreeToFhicl(ConfigurationTree node,
902  std::ostream& out /* = std::cout */,
903  std::string& tabStr /* = "" */,
904  std::string& commentStr /* = "" */,
905  unsigned int depth /* = -1 */)
906 {
907  if(depth == 0)
908  {
909  __COUT__ << __COUT_HDR_P__ << "Depth limit reached. Ending recursion." << __E__;
910  return;
911  }
912 
913  //__COUT__ << __COUT_HDR_P__ << "Adding tree record '" << node.getValueAsString() << "' fields..." << __E__;
914 
915  if(depth == (unsigned int)-1)
916  depth = 10;
917 
918  // decorate link node with link_table {} wrapper
919  if(node.isLinkNode())
920  {
921  if(node.isDisconnected())
922  {
923  //__COUT__ << node.getFieldName() << " field is a disconnected link." << __E__;
924  return;
925  }
926 
927  OUT << node.getFieldName() << "_"
928  << node.getValueAsString(true /* returnLinkTableValue */) << ": \t{" << __E__;
929  PUSHTAB;
930  } // end link preamble decoration
931 
932  if(node.isGroupLinkNode())
933  {
934  // for group link, handle each as a UID record
935  std::vector<std::pair<std::string, ConfigurationTree>> children =
936  node.getChildren();
937  for(auto& child : children)
938  recursiveTreeToFhicl(child.second, out, tabStr, commentStr, depth - 1);
939 
940  POPTAB;
941  OUT << "} //end " << node.getValueAsString(true /* returnLinkTableValue */)
942  << " group link record" << __E__;
943  return;
944  } // end group link handling
945 
946  // treat as UID record now
947  // give UID decoration, then contents
948 
949  // open UID decoration
950  OUT << node.getValueAsString() << ": \t{" << __E__;
951  PUSHTAB;
952  { // open UID content
953 
954  std::vector<std::pair<std::string, ConfigurationTree>> fields =
955  node.getChildren();
956 
957  // skip last 3 fields that are always common
958  for(unsigned int i = 0; i < fields.size() - 3; ++i)
959  {
960  //__COUT__ << fields[i].first << __E__;
961 
962  if(fields[i].second.isLinkNode())
963  {
964  recursiveTreeToFhicl(
965  fields[i].second, out, tabStr, commentStr, depth - 1);
966  continue;
967  }
968  // else a normal field
969 
970  OUT << fields[i].second.getFieldName() << ": \t";
971  if(fields[i].second.isValueNumberDataType())
972  OUT << fields[i].second.getValueAsString() << __E__;
973  else
974  OUT << "\"" << fields[i].second.getValueAsString() << "\"" << __E__;
975 
976  } // end fe fields
977 
978  } // close UID content
979  POPTAB; // close UID decoration
980  OUT << "} //end " << node.getValueAsString() << " record" << __E__;
981 
982  // handle link closing decoration
983  if(node.isLinkNode())
984  {
985  POPTAB;
986  OUT << "} //end " << node.getValueAsString(true /* returnLinkTableValue */)
987  << " link record" << __E__;
988  } // end link closing decoration
989 
990 } // end recursiveTreeToFhicl
991 
992 //==============================================================================
995 void ConfigurationManager::dumpActiveConfiguration(const std::string& filePath,
996  const std::string& dumpType,
997  const std::string& configurationAlias,
998  const std::string& logEntry,
999  const std::string& activeUsers,
1000  std::ostream& altOut /* = std::cout */)
1001 {
1002  time_t rawtime = time(0);
1003  __GEN_COUT__ << "filePath = " << filePath << __E__;
1004  __GEN_COUT__ << "dumpType = " << dumpType << __E__;
1005 
1006  std::ofstream fs;
1007  if(filePath != "")
1008  fs.open(filePath, std::fstream::out | std::fstream::trunc);
1009 
1010  std::ostream* out;
1011 
1012  // if file was valid use it, else default to cout
1013  if(fs.is_open())
1014  out = &fs;
1015  else
1016  {
1017  if(filePath != "")
1018  {
1019  __SS__ << "Invalid file path to dump active configuration. File " << filePath
1020  << " could not be opened!" << __E__;
1021  __GEN_COUT_ERR__ << ss.str();
1022  __SS_THROW__;
1023  }
1024  out = &(altOut);
1025  }
1026 
1027  (*out) << "#################################" << __E__;
1028  (*out) << "This is an ots configuration dump.\n" << __E__;
1029  (*out) << "Source database is $ARTDAQ_DATABASE_URI: "
1030  << __ENV__("ARTDAQ_DATABASE_URI") << __E__;
1031  if(fs.is_open())
1032  (*out) << "Original location of dump: " << __ENV__("HOSTNAME")
1033  << ":" << filePath << __E__;
1034  (*out) << "\nActive ots users: \t"
1035  << (activeUsers.size() ? activeUsers : "no active users") << __E__;
1036  (*out) << "Type of dump: \t\t" << dumpType << __E__;
1037  (*out) << "Time of dump: \t\t" << rawtime;
1038  {
1039  struct tm* timeinfo = localtime(&rawtime);
1040  char buffer[100];
1041  strftime(buffer, 100, "%c %Z", timeinfo);
1042  (*out) << " \t" << buffer << __E__;
1043  }
1044 
1045  //determine configurationAlias tranlation
1046  std::pair<std::string, ots::TableGroupKey> configurationTableGroup =
1047  getTableGroupFromAlias(configurationAlias);
1048  (*out) << "Configuration Alias: \t\t\t" << configurationAlias << "\n";
1049  (*out) << "Configuration Alias translation: \t" << configurationTableGroup.first
1050  << "(" << configurationTableGroup.second << ")\n\n";
1051 
1052  if(logEntry.size())
1053  (*out) << "User Log Entry (" << logEntry.size() << " chars):\n"
1054  << logEntry << __E__;
1055 
1056  // define local "lambda" functions
1057  // active groups
1058  // active tables
1059  // active group members
1060  // active table contents
1061 
1062  auto localDumpActiveGroups = [](const ConfigurationManager* cfgMgr,
1063  std::ostream* out) {
1064  std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroups =
1065  cfgMgr->getActiveTableGroups();
1066 
1067  (*out) << "\n\n************************" << __E__;
1068  (*out) << "Active Groups:" << __E__;
1069  for(auto& group : activeGroups)
1070  {
1071  (*out) << "\t" << group.first << " := " << group.second.first << " ("
1072  << group.second.second << ")" << __E__;
1073  }
1074  };
1075 
1076  auto localDumpActiveTables = [](const ConfigurationManager* cfgMgr,
1077  std::ostream* out) {
1078  std::map<std::string, TableVersion> activeTables = cfgMgr->getActiveVersions();
1079 
1080  (*out) << "\n\n************************" << __E__;
1081  (*out) << "Active Tables:" << __E__;
1082  (*out) << "Active Tables count = " << activeTables.size() << __E__;
1083 
1084  unsigned int i = 0;
1085  for(auto& table : activeTables)
1086  {
1087  (*out) << "\t" << ++i << ". " << table.first << "-v" << table.second << __E__;
1088  }
1089  };
1090 
1091  auto localDumpActiveGroupMembers = [](ConfigurationManager* cfgMgr,
1092  std::ostream* out) {
1093  std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroups =
1094  cfgMgr->getActiveTableGroups();
1095  (*out) << "\n\n************************" << __E__;
1096  (*out) << "Active Group Members:" << __E__;
1097  int tableCount = 0;
1098  for(auto& group : activeGroups)
1099  {
1100  (*out) << "\t" << group.first << " := " << group.second.first << " ("
1101  << group.second.second << ")" << __E__;
1102 
1103  if(group.second.first == "")
1104  {
1105  (*out) << "\t"
1106  << "Empty group name. Assuming no active group." << __E__;
1107  continue;
1108  }
1109 
1110  std::map<std::string /*name*/, TableVersion /*version*/> memberMap;
1111  std::map<std::string /*name*/, std::string /*alias*/> groupAliases;
1112  std::string groupComment;
1113  std::string groupAuthor;
1114  std::string groupCreateTime;
1115  time_t groupCreateTime_t;
1116 
1117  cfgMgr->loadTableGroup(group.second.first,
1118  group.second.second,
1119  false /*doActivate*/,
1120  &memberMap /*memberMap*/,
1121  0 /*progressBar*/,
1122  0 /*accumulateErrors*/,
1123  &groupComment,
1124  &groupAuthor,
1125  &groupCreateTime,
1126  true /*doNotLoadMembers*/,
1127  0 /*groupTypeString*/,
1128  &groupAliases);
1129 
1130  (*out) << "\t\tGroup Comment: \t" << groupComment << __E__;
1131  (*out) << "\t\tGroup Author: \t" << groupAuthor << __E__;
1132 
1133  sscanf(groupCreateTime.c_str(), "%ld", &groupCreateTime_t);
1134  (*out) << "\t\tGroup Create Time: \t" << ctime(&groupCreateTime_t) << __E__;
1135  (*out) << "\t\tGroup Aliases: \t" << StringMacros::mapToString(groupAliases)
1136  << __E__;
1137 
1138  (*out) << "\t\tMember table count = " << memberMap.size() << __E__;
1139  tableCount += memberMap.size();
1140 
1141  unsigned int i = 0;
1142  for(auto& member : memberMap)
1143  {
1144  (*out) << "\t\t\t" << ++i << ". " << member.first << "-v" << member.second
1145  << __E__;
1146  }
1147  }
1148  (*out) << "\nActive Group Members total table count = " << tableCount << __E__;
1149  };
1150 
1151  auto localDumpActiveTableContents = [](const ConfigurationManager* cfgMgr,
1152  std::ostream* out) {
1153  std::map<std::string, TableVersion> activeTables = cfgMgr->getActiveVersions();
1154 
1155  (*out) << "\n\n************************" << __E__;
1156  (*out) << "Active Table Contents (table count = " << activeTables.size()
1157  << "):" << __E__;
1158  unsigned int i = 0;
1159  for(auto& table : activeTables)
1160  {
1161  (*out) << "\n\n=============================================================="
1162  "================"
1163  << __E__;
1164  (*out) << "=================================================================="
1165  "============"
1166  << __E__;
1167  (*out) << "\t" << ++i << ". " << table.first << "-v" << table.second << __E__;
1168 
1169  cfgMgr->nameToTableMap_.find(table.first)->second->print(*out);
1170  }
1171  };
1172 
1173  if(dumpType == "GroupKeys")
1174  {
1175  localDumpActiveGroups(this, out);
1176  }
1177  else if(dumpType == "TableVersions")
1178  {
1179  localDumpActiveTables(this, out);
1180  }
1181  else if(dumpType == "GroupKeysAndTableVersions")
1182  {
1183  localDumpActiveGroups(this, out);
1184  localDumpActiveTables(this, out);
1185  }
1186  else if(dumpType == "All")
1187  {
1188  localDumpActiveGroups(this, out);
1189  localDumpActiveGroupMembers(this, out);
1190  localDumpActiveTables(this, out);
1191  localDumpActiveTableContents(this, out);
1192  }
1193  else
1194  {
1195  __SS__
1196  << "Invalid dump type '" << dumpType
1197  << "' given during dumpActiveConfiguration(). Valid types are as follows:\n"
1198  <<
1199 
1200  // List all choices
1201  "GroupKeys"
1202  << ", "
1203  << "TableVersions"
1204  << ", "
1205  << "GroupsKeysAndTableVersions"
1206  << ", "
1207  << "All"
1208  <<
1209 
1210  "\n\nPlease change the State Machine configuration to a valid dump type."
1211  << __E__;
1212  __SS_THROW__;
1213  }
1214 
1215  if(fs.is_open())
1216  fs.close();
1217 
1218 } //end dumpActiveConfiguration()
1219 
1220 //==============================================================================
1227  const std::map<std::string /*name*/, TableVersion /*version*/>& memberMap,
1228  std::string* accumulatedWarnings /* =0 */)
1229 {
1230  __GEN_COUTTV__(runTimeSeconds());
1231 
1232  TableBase* tmpTableBasePtr;
1233 
1234  //detect if using cache, and decide if multi-threading
1235  bool usingCache = false;
1236  if(memberMap.size() > 10 && nameToTableMap_.size() &&
1237  nameToTableMap_.find(memberMap.begin()->first) != nameToTableMap_.end() &&
1238  nameToTableMap_.at(memberMap.begin()->first)->isStored(memberMap.begin()->second))
1239  {
1240  usingCache = true;
1241  }
1242  if(usingCache)
1243  __GEN_COUTT__ << "Using cache!" << __E__;
1244 
1245  //Note: mongodb crashing from too many connections was resolved by increasing ulimit at mongodb launch
1246  // i.e. ulimit -n 64000 && ./start_mongod.sh
1247  const int numOfThreads =
1248  PROCESSOR_COUNT / 2 > memberMap.size() ? (PROCESSOR_COUNT / 2) : memberMap.size();
1249  if(memberMap.size() <= 2 /* i.e. is Context group */ || usingCache ||
1250  numOfThreads < 2) // no multi-threading
1251  {
1252  // for each member
1253  // get()
1254  for(auto& memberPair : memberMap)
1255  {
1256  // if(accumulatedWarnings)
1257  // __GEN_COUT__ << "\tFilling member table " << memberPair.first << ":" <<
1258  // memberPair.second << __E__;
1259 
1260  // get the proper temporary pointer
1261  // use 0 if doesn't exist yet.
1262  // Note: do not want to give nameToTableMap_[memberPair.first]
1263  // in case there is failure in get... (exceptions may be thrown)
1264  // Note: Default constructor is called by Map, i.e.
1265  // nameToTableMap_[memberPair.first] = 0; //create pointer and set to 0
1266  tmpTableBasePtr = nullptr;
1267  if(nameToTableMap_.find(memberPair.first) != nameToTableMap_.end())
1268  tmpTableBasePtr = nameToTableMap_.at(memberPair.first);
1269 
1270  std::string getError = "";
1271  try
1272  {
1273  theInterface_->get(tmpTableBasePtr, // tablePtr
1274  memberPair.first, // tableName
1275  0, // groupKey
1276  0, // groupName
1277  false, // dontFill=false to fill
1278  memberPair.second, // version
1279  false // resetTable
1280  );
1281  }
1282  catch(const std::runtime_error& e)
1283  {
1284  __SS__ << "Failed to load member table '" << memberPair.first << "-v"
1285  << memberPair.second << "' - here is the error: \n\n"
1286  << e.what() << __E__;
1287 
1288  ss << "\nIf the table '" << memberPair.first
1289  << "' should not exist, then please remove it from the group. If it "
1290  "should exist, then it "
1291  << "seems to have a problem; use the Table Editor to fix the table "
1292  "definition, or "
1293  "edit the table content to match the table definition."
1294  << __E__;
1295 
1296  // if accumulating warnings and table view was created, then continue
1297  if(accumulatedWarnings)
1298  getError = ss.str();
1299  else
1300  __SS_ONLY_THROW__;
1301  }
1302  catch(...)
1303  {
1304  __SS__ << "Failed to load member table '" << memberPair.first << " -v"
1305  << memberPair.second << "' due to unknown error!" << __E__;
1306  try
1307  {
1308  throw;
1309  } //one more try to printout extra info
1310  catch(const std::exception& e)
1311  {
1312  ss << "Exception message: " << e.what();
1313  }
1314  catch(...)
1315  {
1316  }
1317 
1318  ss << "\nIf the table '" << memberPair.first
1319  << "' should not exist, then please remove it from the group. If it "
1320  "should exist, then it "
1321  << "seems to have a problem; use the Table Editor to fix the table "
1322  "definition, or "
1323  "edit the table content to match the table definition."
1324  << __E__;
1325 
1326  // if accumulating warnings and table view was created, then continue
1327  if(accumulatedWarnings)
1328  getError = ss.str();
1329  else
1330  __SS_THROW__;
1331  }
1332 
1333  //__GEN_COUT__ << "Checking ptr.. " << (tmpTableBasePtr?"GOOD":"BAD") << __E__;
1334  if(!tmpTableBasePtr)
1335  {
1336  __SS__ << "Null pointer returned for table '" << memberPair.first << " -v"
1337  << memberPair.second << ".' Was the table info deleted?" << __E__;
1338  __GEN_COUT_ERR__ << ss.str();
1339 
1340  nameToTableMap_.erase(memberPair.first);
1341  if(accumulatedWarnings)
1342  {
1343  *accumulatedWarnings += ss.str();
1344  continue;
1345  }
1346  else
1347  __SS_ONLY_THROW__;
1348  }
1349 
1350  nameToTableMap_[memberPair.first] = tmpTableBasePtr;
1351  if(nameToTableMap_[memberPair.first]->getViewP())
1352  {
1353  //__GEN_COUT__ << "Activated version: " <<
1354  // nameToTableMap_[memberPair.first]->getViewVersion() << __E__;
1355 
1356  if(accumulatedWarnings && getError != "")
1357  {
1358  __SS__ << "Error caught during '" << memberPair.first << " -v"
1359  << memberPair.second << "' table retrieval: \n"
1360  << getError << __E__;
1361  __GEN_COUT_ERR__ << ss.str();
1362  *accumulatedWarnings += ss.str();
1363  }
1364  }
1365  else
1366  {
1367  __SS__ << nameToTableMap_[memberPair.first]->getTableName() << " -v"
1368  << memberPair.second << ": View version not activated properly!";
1369  __SS_THROW__;
1370  }
1371  } // end member map loop
1372  }
1373  else //multi-threading
1374  {
1375  __GEN_COUT__ << " PROCESSOR_COUNT " << PROCESSOR_COUNT << " ==> " << numOfThreads
1376  << " threads for loading member map of size " << memberMap.size()
1377  << __E__;
1378 
1379  int threadsLaunched = 0;
1380  int foundThreadIndex = 0;
1381  std::string threadErrors;
1382  std::mutex threadMutex; // to protect accumulatedWarnings
1383  std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
1384  for(int i = 0; i < numOfThreads; ++i)
1385  threadDone.push_back(std::make_shared<std::atomic<bool>>(true));
1386  std::vector<TableBase*> tmpTableBasePtrs;
1387  for(int i = 0; i < numOfThreads; ++i)
1388  tmpTableBasePtrs.push_back(nullptr);
1389 
1390  for(auto& memberPair : memberMap)
1391  {
1392  if(threadsLaunched >= numOfThreads)
1393  {
1394  //find availableThreadIndex
1395  foundThreadIndex = -1;
1396  while(foundThreadIndex == -1)
1397  {
1398  for(int i = 0; i < numOfThreads; ++i)
1399  if(*(threadDone[i]))
1400  {
1401  foundThreadIndex = i;
1402  break;
1403  }
1404  if(foundThreadIndex == -1)
1405  {
1406  __GEN_COUTT__ << "Waiting for available thread..." << __E__;
1407  usleep(10000);
1408  }
1409  } //end thread search loop
1410  threadsLaunched = numOfThreads - 1;
1411  }
1412  __GEN_COUTT__ << "Starting filling thread... " << foundThreadIndex << " for "
1413  << memberPair.first << " -v" << memberPair.second << __E__;
1414  *(threadDone[foundThreadIndex]) = false;
1415 
1416  // get the proper temporary pointer
1417  // use 0 if doesn't exist yet.
1418  // Note: do not want to give nameToTableMap_[memberPair.first]
1419  // in case there is failure in get... (exceptions may be thrown)
1420  // Note: Default constructor is called by Map, i.e.
1421  // nameToTableMap_[memberPair.first] = 0; //create pointer and set to 0
1422  tmpTableBasePtrs[foundThreadIndex] = nullptr;
1423  if(nameToTableMap_.find(memberPair.first) != nameToTableMap_.end())
1424  tmpTableBasePtrs[foundThreadIndex] = nameToTableMap_.at(memberPair.first);
1425 
1426  std::thread(
1427  [](ConfigurationInterface* theInterface,
1428  std::map<std::string, ots::TableBase*>* theNameToTableMap,
1429  ots::TableBase* theTable,
1430  std::string theTableName,
1431  ots::TableVersion version,
1432  std::string* theThreadErrors,
1433  std::mutex* theThreadMutex,
1434  std::shared_ptr<std::atomic<bool>> theThreadDone) {
1435  ConfigurationManager::fillTableThread(theInterface,
1436  theNameToTableMap,
1437  theTable,
1438  theTableName,
1439  version,
1440  theThreadErrors,
1441  theThreadMutex,
1442  theThreadDone);
1443  },
1444  theInterface_,
1445  &nameToTableMap_,
1446  tmpTableBasePtrs[foundThreadIndex],
1447  memberPair.first,
1448  memberPair.second,
1449  &threadErrors,
1450  &threadMutex,
1451  threadDone[foundThreadIndex])
1452  .detach();
1453 
1454  ++threadsLaunched;
1455  ++foundThreadIndex;
1456  } //end table init thread loop
1457 
1458  //check for all threads done
1459  do
1460  {
1461  foundThreadIndex = -1;
1462  for(int i = 0; i < numOfThreads; ++i)
1463  if(!*(threadDone[i]))
1464  {
1465  foundThreadIndex = i;
1466  break;
1467  }
1468  if(foundThreadIndex != -1)
1469  {
1470  __GEN_COUT_TYPE__(TLVL_DEBUG + 2)
1471  << __COUT_HDR__ << "Waiting for thread to finish... "
1472  << foundThreadIndex << __E__;
1473  usleep(10000);
1474  }
1475  } while(foundThreadIndex != -1); //end thread done search loop
1476  __GEN_COUTT__ << "All threads done." << __E__;
1477 
1478  if(threadErrors != "")
1479  {
1480  __SS__ << "Error identified in threads during loading of member map: \n"
1481  << threadErrors << __E__;
1482  __GEN_COUTT__ << "\n" << ss.str() << __E__;
1483  if(accumulatedWarnings)
1484  *accumulatedWarnings += ss.str();
1485  else
1486  __SS_THROW__;
1487  }
1488  } //end multi-thread handling
1489 
1490  __GEN_COUTT__ << "loadMemberMap end runTimeSeconds()=" << runTimeSeconds() << __E__;
1491 } // end loadMemberMap()
1492 
1493 //==============================================================================
1516  const std::string& groupName,
1517  const TableGroupKey& groupKey,
1518  bool doActivate /*=false*/,
1519  std::map<std::string /*table name*/, TableVersion>*
1520  groupMembers /*=0 , note: db time intensive! */,
1521  ProgressBar* progressBar /*=0*/,
1522  std::string* accumulatedWarnings /*=0*/,
1523  std::string* groupComment /*=0 , note: in metadata */,
1524  std::string* groupAuthor /*=0 , note: in metadata */,
1525  std::string* groupCreateTime /*=0 , note: in metadata */,
1526  bool doNotLoadMembers /*=false*/,
1527  std::string* groupTypeString /*=0 , note: db time intensive! */,
1528  std::map<std::string /*name*/, std::string /*alias*/>*
1529  groupAliases /*=0 , note: in metadata */,
1530  ConfigurationManager::LoadGroupType
1531  groupTypeToLoad /*=ConfigurationManager::LoadGroupType::ALL_TYPES*/,
1532  bool ignoreVersionTracking /*=false*/)
1533 {
1534  // clear to defaults
1535  if(groupComment)
1536  *groupComment = ConfigurationManager::UNKNOWN_INFO;
1537  if(groupAuthor)
1538  *groupAuthor = ConfigurationManager::UNKNOWN_INFO;
1539  if(groupCreateTime)
1540  *groupCreateTime = ConfigurationManager::UNKNOWN_TIME;
1541  if(groupTypeString)
1542  *groupTypeString = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
1543  else
1544  __GEN_COUTT__ << "No group type requested." << __E__;
1545 
1546  // if(groupName == "defaultConfig")
1547  // { //debug active versions
1548  // std::map<std::string, TableVersion> allActivePairs = getActiveVersions();
1549  // for(auto& activePair: allActivePairs)
1550  // {
1551  // __GEN_COUT__ << "Active table = " <<
1552  // activePair.first << "-v" <<
1553  // getTableByName(activePair.first)->getView().getVersion() <<
1554  // __E__;
1555  // }
1556  // }
1557 
1558  // load all members of configuration group
1559  // if doActivate
1560  // determine the type configuration
1561  // deactivate all of that type (invalidate active view)
1562  //
1563  // for each member
1564  // get()
1565  // if doActivate, configBase->init()
1566  //
1567  // if doActivate
1568  // set theConfigurationTableGroup_, theContextTableGroup_, or
1569  // theBackboneTableGroup_ on success
1570 
1571  __GEN_COUTT__ << "Loading Table Group: " << groupName << "(" << groupKey << ")"
1572  << " accumulatedWarnings=" << (accumulatedWarnings ? 1 : 0) << __E__;
1573 
1574  //failing member map load should be an exception!
1575 
1576  std::map<std::string /*name*/, TableVersion /*version*/> memberMap =
1577  theInterface_->getTableGroupMembers(
1578  TableGroupKey::getFullGroupString(groupName, groupKey),
1579  true /*include meta data table*/);
1580 
1581  try
1582  {
1583  if(progressBar)
1584  progressBar->step();
1585 
1586  // remove meta data table and extract info
1587  auto metaTablePair = memberMap.find(TableBase::GROUP_METADATA_TABLE_NAME);
1588  if(metaTablePair != memberMap.end())
1589  {
1590  //only lock metadata table if metadata is needed
1591  if(groupAliases || groupComment || groupAuthor || groupCreateTime)
1592  {
1593  std::lock_guard<std::mutex> lock(metaDataTableMutex_);
1594 
1595  // clear table
1596  while(groupMetadataTable_.getView().getNumberOfRows())
1597  groupMetadataTable_.getViewP()->deleteRow(0);
1598 
1599  // retrieve metadata from database
1600  try
1601  {
1602  theInterface_->fill(&groupMetadataTable_, metaTablePair->second);
1603  }
1604  catch(const std::runtime_error& e)
1605  {
1606  __GEN_COUT_WARN__
1607  << "Failed to load " << groupMetadataTable_.getTableName() << "-v"
1608  << metaTablePair->second << ". Metadata error: " << e.what()
1609  << __E__;
1610  }
1611  catch(...)
1612  {
1613  __GEN_COUT_WARN__
1614  << "Failed to load " << groupMetadataTable_.getTableName() << "-v"
1615  << metaTablePair->second << ". Ignoring unknown metadata error. "
1616  << __E__;
1617  }
1618 
1619  // check that there is only 1 row
1620  if(groupMetadataTable_.getView().getNumberOfRows() != 1)
1621  {
1622  groupMetadataTable_.print();
1623  __GEN_COUT_ERR__ << "Ignoring that groupMetadataTable_ has wrong "
1624  "number of rows for '"
1625  << groupName << "(" << groupKey
1626  << ")!' Must "
1627  "be 1. Going with anonymous defaults."
1628  << __E__;
1629 
1630  // fix metadata table
1631  while(groupMetadataTable_.getViewP()->getNumberOfRows() > 1)
1632  groupMetadataTable_.getViewP()->deleteRow(0);
1633  if(groupMetadataTable_.getViewP()->getNumberOfRows() == 0)
1634  groupMetadataTable_.getViewP()->addRow();
1635  }
1636  else
1637  {
1638  // extract metadata fields
1639 
1640  if(groupAliases)
1642  groupMetadataTable_.getView().getValueAsString(
1643  0, ConfigurationManager::METADATA_COL_ALIASES),
1644  *groupAliases);
1645  if(groupComment)
1646  *groupComment = groupMetadataTable_.getView().getValueAsString(
1647  0, ConfigurationManager::METADATA_COL_COMMENT);
1648  if(groupAuthor)
1649  *groupAuthor = groupMetadataTable_.getView().getValueAsString(
1650  0, ConfigurationManager::METADATA_COL_AUTHOR);
1651  if(groupCreateTime)
1652  *groupCreateTime = groupMetadataTable_.getView().getValueAsString(
1653  0, ConfigurationManager::METADATA_COL_TIMESTAMP);
1654  }
1655  }
1656 
1657  memberMap.erase(metaTablePair); // remove from member map that is returned
1658 
1659  } // end metadata handling
1660  else
1661  {
1662  __GEN_COUT_ERR__ << "Ignoring that groupMetadataTable_ is missing for group '"
1663  << groupName << "(" << groupKey
1664  << "). Going with anonymous defaults." << __E__;
1665  }
1666 
1667  //NEVER modify members based on aliases
1668  // Regarding Member Table Aliases: alias names are tracked in the metadata table,
1669  // however! The group member versions are decided at group save time
1670  // (loadTableGroup should always return the same groupName -> memberMap translation).
1671  // The group member versions do not undergo alias translation at load time (i.e. loadTableGroup).
1672  // The alias map can be retrieved using the groupAliases parameter.
1673  if(0)
1674  {
1675  std::map<std::string, std::string>& aliasMap = *groupAliases;
1676  std::map<std::string /*table*/, std::map<std::string /*alias*/, TableVersion>>
1677  versionAliases;
1678  if(aliasMap.size()) // load version aliases
1679  {
1680  __GEN_COUTV__(StringMacros::mapToString(aliasMap));
1681  versionAliases = ConfigurationManager::getVersionAliases();
1682  __GEN_COUTV__(StringMacros::mapToString(versionAliases));
1683  }
1684 
1685  // convert alias to version
1686  for(auto& aliasPair : aliasMap)
1687  {
1688  // check for alias table in member names
1689  if(memberMap.find(aliasPair.first) != memberMap.end())
1690  {
1691  __GEN_COUT__ << "Group member '" << aliasPair.first
1692  << "' was found in group member map!" << __E__;
1693  __GEN_COUT__ << "Looking for alias '" << aliasPair.second
1694  << "' in active version aliases..." << __E__;
1695 
1696  if(versionAliases.find(aliasPair.first) == versionAliases.end() ||
1697  versionAliases[aliasPair.first].find(aliasPair.second) ==
1698  versionAliases[aliasPair.first].end())
1699  {
1700  __SS__ << "Group '" << groupName << "(" << groupKey
1701  << ")' requires table version alias '" << aliasPair.first
1702  << ":" << aliasPair.second
1703  << ",' which was not found in the active Backbone!"
1704  << __E__;
1705  __SS_ONLY_THROW__;
1706  }
1707 
1708  memberMap[aliasPair.first] =
1709  versionAliases[aliasPair.first][aliasPair.second];
1710  __GEN_COUT__ << "Version alias translated to " << aliasPair.first
1711  << __E__;
1712  }
1713  }
1714  } // end modify members based on aliases
1715 
1716  if(groupMembers)
1717  *groupMembers = memberMap; // copy map for return
1718 
1719  if(progressBar)
1720  progressBar->step();
1721 
1722  ConfigurationManager::GroupType groupType =
1723  ConfigurationManager::GroupType::CONFIGURATION_TYPE;
1724  try
1725  {
1726  if(groupTypeString) // do before exit case
1727  {
1728  groupType = getTypeOfGroup(memberMap);
1729  *groupTypeString = convertGroupTypeToName(groupType);
1730  }
1731  else
1732  __GEN_COUTT__ << "No group type requested." << __E__;
1733 
1734  if(doNotLoadMembers)
1735  return; //this is useful if just getting group metadata
1736 
1737  // if not already done, determine the type configuration group
1738  if(!groupTypeString)
1739  groupType = getTypeOfGroup(memberMap);
1740 
1741  if(groupTypeToLoad ==
1742  ConfigurationManager::LoadGroupType::ONLY_BACKBONE_OR_CONTEXT_TYPES &&
1743  groupType != ConfigurationManager::GroupType::CONTEXT_TYPE &&
1744  groupType != ConfigurationManager::GroupType::BACKBONE_TYPE)
1745  {
1746  __GEN_COUT__ << "Not loading group because it is not of type Context or "
1747  "Backbone (it is type '"
1748  << convertGroupTypeToName(groupType) << "')." << __E__;
1749  return;
1750  }
1751  else if(groupTypeToLoad ==
1752  ConfigurationManager::LoadGroupType::ONLY_BACKBONE_TYPE &&
1753  groupType != ConfigurationManager::GroupType::BACKBONE_TYPE)
1754  {
1755  __GEN_COUT__ << "Not loading group because it is not of type "
1756  "Backbone (it is type '"
1757  << convertGroupTypeToName(groupType) << "')." << __E__;
1758  return;
1759  }
1760 
1761  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
1762  if(doActivate)
1763  __GEN_COUT__
1764  << "------------------------------------- init start \t [for all "
1765  "plug-ins in "
1766  << convertGroupTypeToName(groupType) << " group '" << groupName << "("
1767  << groupKey << ")"
1768  << "']" << __E__;
1769 
1770  if(doActivate)
1771  {
1772  std::string groupToDeactivate =
1773  groupType == ConfigurationManager::GroupType::CONTEXT_TYPE
1774  ? theContextTableGroup_
1775  : (groupType == ConfigurationManager::GroupType::BACKBONE_TYPE
1776  ? theBackboneTableGroup_
1777  : (groupType ==
1778  ConfigurationManager::GroupType::ITERATE_TYPE
1779  ? theIterateTableGroup_
1780  : theConfigurationTableGroup_));
1781 
1782  // deactivate all of that type (invalidate active view)
1783  if(groupToDeactivate != "") // deactivate only if pre-existing group
1784  {
1785  __GEN_COUT__ << "groupToDeactivate '" << groupToDeactivate
1786  << "' of type " << convertGroupTypeToName(groupType)
1787  << __E__;
1788  destroyTableGroup(groupToDeactivate, true);
1789  }
1790  else
1791  {
1792  //Getting here, is kind of strange:
1793  // - this group may have only been partially loaded before?
1794  __GEN_COUT__ << "no group to deactivate of type "
1795  << convertGroupTypeToName(groupType) << __E__;
1796  }
1797  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
1798  }
1799 
1800  if(progressBar)
1801  progressBar->step();
1802 
1803  loadMemberMap(memberMap, accumulatedWarnings);
1804 
1805  if(progressBar)
1806  progressBar->step();
1807 
1808  __GEN_COUTT__ << "loadMemberMap() completed." << __E__;
1809 
1810  if(accumulatedWarnings)
1811  {
1812  __GEN_COUTT__ << "Checking chosen group for tree errors... here are the "
1813  "current warnings: "
1814  << *accumulatedWarnings << __E__;
1815 
1816  getChildren(&memberMap, accumulatedWarnings);
1817  if(*accumulatedWarnings != "")
1818  {
1819  __GEN_COUT_WARN__
1820  << "Errors detected while loading Table Group: " << groupName
1821  << "(" << groupKey << "). Ignoring the following errors: "
1822  << "\n"
1823  << *accumulatedWarnings << __E__;
1824  }
1825  __GEN_COUTT__ << "After checking children warnings: "
1826  << *accumulatedWarnings << __E__;
1827  }
1828 
1829  if(progressBar)
1830  progressBar->step();
1831 
1832  __GEN_COUTT__ << "Tree view check complete." << __E__;
1833 
1834  // for each member
1835  // if doActivate, configBase->init()
1836  if(doActivate)
1837  {
1838  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
1839 
1840  const int numOfThreads = PROCESSOR_COUNT / 2;
1841  __GEN_COUT__ << " PROCESSOR_COUNT " << PROCESSOR_COUNT << " ==> "
1842  << numOfThreads
1843  << " threads for initializing tables for Table Group '"
1844  << groupName << "(" << groupKey << ")'." << __E__;
1845  if(groupType != ConfigurationManager::GroupType::CONFIGURATION_TYPE ||
1846  numOfThreads < 2) // no multi-threading
1847  {
1848  for(auto& memberPair : memberMap)
1849  {
1850  // do NOT allow activating Scratch versions if tracking is ON!
1851  if(!ignoreVersionTracking &&
1852  ConfigurationInterface::isVersionTrackingEnabled() &&
1853  memberPair.second.isScratchVersion())
1854  {
1855  __SS__
1856  << "Error while activating member Table '"
1857  << nameToTableMap_[memberPair.first]->getTableName()
1858  << "-v" << memberPair.second << " for Table Group '"
1859  << groupName << "(" << groupKey
1860  << ")'. When version tracking is enabled, Scratch views"
1861  << " are not allowed! Please only use unique, persistent "
1862  "versions when version tracking is enabled."
1863  << __E__;
1864  __SS_ONLY_THROW__;
1865  }
1866 
1867  // attempt to init using the configuration's specific init
1868  // this could be risky user code, try and catch
1869  try
1870  {
1871  nameToTableMap_.at(memberPair.first)->init(this);
1872  }
1873  catch(std::runtime_error& e)
1874  {
1875  __SS__ << "Error detected calling " << memberPair.first
1876  << ".init()!\n\n " << e.what() << __E__;
1877 
1878  if(accumulatedWarnings)
1879  {
1880  *accumulatedWarnings += ss.str();
1881  }
1882  else
1883  {
1884  ss << StringMacros::stackTrace();
1885  __SS_ONLY_THROW__;
1886  }
1887  }
1888  catch(...)
1889  {
1890  __SS__ << "Unknown Error detected calling "
1891  << memberPair.first << ".init()!\n\n " << __E__;
1892  try
1893  {
1894  throw;
1895  } //one more try to printout extra info
1896  catch(const std::exception& e)
1897  {
1898  ss << "Exception message: " << e.what();
1899  }
1900  catch(...)
1901  {
1902  }
1903  //__SS_THROW__;
1904 
1905  if(accumulatedWarnings)
1906  {
1907  *accumulatedWarnings += ss.str();
1908  }
1909  else // ignore error
1910  __GEN_COUT_WARN__ << ss.str();
1911  }
1912  }
1913  }
1914  else //multi-threading
1915  {
1916  int threadsLaunched = 0;
1917  int foundThreadIndex = 0;
1918  std::string threadErrors;
1919  std::mutex threadMutex; // to protect accumulatedWarnings
1920  std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
1921  for(int i = 0; i < numOfThreads; ++i)
1922  threadDone.push_back(std::make_shared<std::atomic<bool>>(true));
1923 
1924  if(!ignoreVersionTracking &&
1925  ConfigurationInterface::isVersionTrackingEnabled())
1926  for(auto& memberPair : memberMap)
1927  {
1928  // do NOT allow activating Scratch versions if tracking is ON!
1929  if(memberPair.second.isScratchVersion())
1930  {
1931  __SS__
1932  << "Error while activating member Table '"
1933  << nameToTableMap_[memberPair.first]->getTableName()
1934  << "-v" << memberPair.second << " for Table Group '"
1935  << groupName << "(" << groupKey
1936  << ")'. When version tracking is enabled, Scratch "
1937  "views"
1938  << " are not allowed! Please only use unique, "
1939  "persistent "
1940  "versions when version tracking is enabled."
1941  << __E__;
1942  __SS_ONLY_THROW__;
1943  }
1944  }
1945 
1946  for(auto& memberPair : memberMap)
1947  {
1948  if(threadsLaunched >= numOfThreads)
1949  {
1950  //find availableThreadIndex
1951  foundThreadIndex = -1;
1952  while(foundThreadIndex == -1)
1953  {
1954  for(int i = 0; i < numOfThreads; ++i)
1955  if(*(threadDone[i]))
1956  {
1957  foundThreadIndex = i;
1958  break;
1959  }
1960  if(foundThreadIndex == -1)
1961  {
1962  __GEN_COUTT__ << "Waiting for available thread..."
1963  << __E__;
1964  usleep(10000);
1965  }
1966  } //end thread search loop
1967  threadsLaunched = numOfThreads - 1;
1968  }
1969  __GEN_COUTT__ << "Starting init table thread... "
1970  << foundThreadIndex << " for " << memberPair.first
1971  << __E__;
1972  *(threadDone[foundThreadIndex]) = false;
1973 
1974  std::thread(
1975  [](ConfigurationManager* cfgMgr,
1976  ots::TableBase* theTable,
1977  std::string* theThreadErrors,
1978  std::mutex* theThreadMutex,
1979  std::shared_ptr<std::atomic<bool>> theThreadDone) {
1980  ConfigurationManager::initTableThread(cfgMgr,
1981  theTable,
1982  theThreadErrors,
1983  theThreadMutex,
1984  theThreadDone);
1985  },
1986  this,
1987  nameToTableMap_.at(memberPair.first),
1988  &threadErrors,
1989  &threadMutex,
1990  threadDone[foundThreadIndex])
1991  .detach();
1992 
1993  ++threadsLaunched;
1994  ++foundThreadIndex;
1995  } //end table init thread loop
1996 
1997  //check for all threads done
1998  do
1999  {
2000  foundThreadIndex = -1;
2001  for(int i = 0; i < numOfThreads; ++i)
2002  if(!*(threadDone[i]))
2003  {
2004  foundThreadIndex = i;
2005  break;
2006  }
2007  if(foundThreadIndex != -1)
2008  {
2009  __GEN_COUTT__ << "Waiting for thread to finish... "
2010  << foundThreadIndex << __E__;
2011  usleep(10000);
2012  }
2013  } while(foundThreadIndex != -1); //end thread done search loop
2014  __GEN_COUTT__ << "All threads done." << __E__;
2015 
2016  if(threadErrors != "")
2017  {
2018  __SS__ << "Error identified in threads during init of table "
2019  "group: \n"
2020  << threadErrors << __E__;
2021  __GEN_COUTT__ << "\n" << ss.str() << __E__;
2022  if(accumulatedWarnings)
2023  *accumulatedWarnings += ss.str();
2024  else
2025  __SS_THROW__;
2026  }
2027  } //end multi-thread handling
2028 
2029  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
2030  } //end activate/init of member tables
2031 
2032  if(progressBar)
2033  progressBar->step();
2034 
2035  // if doActivate
2036  // set theConfigurationTableGroup_, theContextTableGroup_, or
2037  // theBackboneTableGroup_ on
2038  // success
2039 
2040  if(doActivate)
2041  {
2042  if(groupType == ConfigurationManager::GroupType::CONTEXT_TYPE) //
2043  {
2044  // __GEN_COUT_INFO__ << "Type=Context, Group loaded: " <<
2045  // groupName
2046  //<<
2047  // "(" << groupKey << ")" << __E__;
2048  theContextTableGroup_ = groupName;
2049  theContextTableGroupKey_ =
2050  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2051  }
2052  else if(groupType == ConfigurationManager::GroupType::BACKBONE_TYPE)
2053  {
2054  // __GEN_COUT_INFO__ << "Type=Backbone, Group loaded: " <<
2055  // groupName <<
2056  // "(" << groupKey << ")" << __E__;
2057  theBackboneTableGroup_ = groupName;
2058  theBackboneTableGroupKey_ =
2059  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2060  }
2061  else if(groupType == ConfigurationManager::GroupType::ITERATE_TYPE)
2062  {
2063  // __GEN_COUT_INFO__ << "Type=Iterate, Group loaded: " <<
2064  // groupName
2065  //<<
2066  // "(" << groupKey << ")" << __E__;
2067  theIterateTableGroup_ = groupName;
2068  theIterateTableGroupKey_ =
2069  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2070  }
2071  else // is theConfigurationTableGroup_
2072  {
2073  // __GEN_COUT_INFO__ << "Type=Configuration, Group loaded: " <<
2074  // groupName <<
2075  // "(" << groupKey << ")" << __E__;
2076  theConfigurationTableGroup_ = groupName;
2077  theConfigurationTableGroupKey_ =
2078  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2079  }
2080  }
2081 
2082  if(progressBar)
2083  progressBar->step();
2084 
2085  if(doActivate)
2086  __GEN_COUT__
2087  << "------------------------------------- init complete \t [for all "
2088  "plug-ins in "
2089  << convertGroupTypeToName(groupType) << " group '" << groupName << "("
2090  << groupKey << ")"
2091  << "']" << __E__;
2092  } // end failed group load try
2093  catch(...)
2094  {
2095  // save group name and key of failed load attempt
2096  lastFailedGroupLoad_[convertGroupTypeToName(groupType)] =
2097  std::pair<std::string, TableGroupKey>(groupName, TableGroupKey(groupKey));
2098 
2099  try
2100  {
2101  throw;
2102  }
2103  catch(const std::runtime_error& e)
2104  {
2105  __SS__ << "Error occurred while loading table group '" << groupName << "("
2106  << groupKey << ")': \n"
2107  << e.what() << __E__;
2108 
2109  if(accumulatedWarnings)
2110  *accumulatedWarnings += ss.str();
2111  else
2112  __SS_ONLY_THROW__;
2113  }
2114  catch(...)
2115  {
2116  __SS__ << "An unknown error occurred while loading table group '"
2117  << groupName << "(" << groupKey << ")." << __E__;
2118  try
2119  {
2120  throw;
2121  } //one more try to printout extra info
2122  catch(const std::exception& e)
2123  {
2124  ss << "Exception message: " << e.what();
2125  }
2126  catch(...)
2127  {
2128  }
2129  if(accumulatedWarnings)
2130  *accumulatedWarnings += ss.str();
2131  else
2132  __SS_ONLY_THROW__;
2133  }
2134  }
2135 
2136  __GEN_COUTT__ << "loadTableGroup() complete for Table Group '" << groupName << "("
2137  << groupKey << ")'." << __E__;
2138  lastGroupLoad_[convertGroupTypeToName(groupType)] =
2139  std::make_pair(std::make_pair(groupName, TableGroupKey(groupKey)), memberMap);
2140  return;
2141  }
2142  catch(...)
2143  {
2144  __GEN_COUTT__ << "loadTableGroup() failed." << __E__;
2145 
2146  // save group name and key of failed load attempt
2147  lastFailedGroupLoad_[ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN] =
2148  std::pair<std::string, TableGroupKey>(groupName, TableGroupKey(groupKey));
2149 
2150  try
2151  {
2152  throw;
2153  }
2154  catch(const std::runtime_error& e)
2155  {
2156  __SS__ << "Error occurred while loading table group '" << groupName << "("
2157  << groupKey << ")': \n"
2158  << e.what() << __E__;
2159 
2160  if(accumulatedWarnings)
2161  *accumulatedWarnings += ss.str();
2162  else
2163  __SS_ONLY_THROW__;
2164  }
2165  catch(...)
2166  {
2167  __SS__ << "An unknown error occurred while loading table group '" << groupName
2168  << "(" << groupKey << ")." << __E__;
2169  try
2170  {
2171  throw;
2172  } //one more try to printout extra info
2173  catch(const std::exception& e)
2174  {
2175  ss << "Exception message: " << e.what();
2176  }
2177  catch(...)
2178  {
2179  }
2180  __GEN_COUT__ << StringMacros::stackTrace();
2181 
2182  if(accumulatedWarnings)
2183  *accumulatedWarnings += ss.str();
2184  else
2185  __SS_ONLY_THROW__;
2186  }
2187  }
2188 } // end loadTableGroup()
2189 
2190 //==============================================================================
2194  const ConfigurationManager& cacheConfigMgr,
2195  const std::map<std::string, TableVersion>& memberMap,
2196  const std::string& groupName /* = "" */,
2197  const TableGroupKey& groupKey /* = TableGroupKey::Invalid */,
2198  bool doActivate /* = false */,
2199  bool ignoreVersionTracking /* = false */)
2200 {
2201  //Note: mostly copied from onfigurationManager::loadTableGroup()
2202 
2203  // determine the type table group type for activation and to save last loaded types
2204  ConfigurationManager::GroupType groupType = getTypeOfGroup(memberMap);
2205  try
2206  {
2207  if(doActivate)
2208  __GEN_COUT__ << "------------------------------------- cacheCopy init start "
2209  " \t [for all "
2210  "plug-ins in member map"
2211  << "']" << __E__;
2212 
2213  if(doActivate)
2214  {
2215  std::string groupToDeactivate =
2216  groupType == ConfigurationManager::GroupType::CONTEXT_TYPE
2217  ? theContextTableGroup_
2218  : (groupType == ConfigurationManager::GroupType::BACKBONE_TYPE
2219  ? theBackboneTableGroup_
2220  : (groupType == ConfigurationManager::GroupType::ITERATE_TYPE
2221  ? theIterateTableGroup_
2222  : theConfigurationTableGroup_));
2223 
2224  // deactivate all of that type (invalidate active view)
2225  if(groupToDeactivate != "") // deactivate only if pre-existing group
2226  {
2227  //__GEN_COUT__ << "groupToDeactivate '" << groupToDeactivate << "'" <<
2228  // __E__;
2229  destroyTableGroup(groupToDeactivate, true);
2230  }
2231  // else
2232  // {
2233  // //Getting here, is kind of strange:
2234  // // - this group may have only been partially loaded before?
2235  // }
2236  }
2237 
2238  //Now load member map, copied from ConfigurationManager::loadMemberMap
2239  // loadMemberMap(memberMap, accumulatedWarnings);
2240  // for each member
2241  // get()
2242  for(auto& memberPair : memberMap)
2243  {
2244  __GEN_COUTT__ << "Copying " << memberPair.first << "-v" << memberPair.second
2245  << __E__;
2246 
2247  //if table does not exist, create it
2248  if(nameToTableMap_.find(memberPair.first) == nameToTableMap_.end())
2249  {
2250  TableBase* table = 0;
2251  theInterface_->get(table, // configurationPtr
2252  memberPair.first, // tableName
2253  0, // groupKey
2254  0, // groupName
2255  true // dontFill=false to fill
2256  );
2257 
2258  nameToTableMap_[memberPair.first] = table;
2259  }
2260  nameToTableMap_.at(memberPair.first)
2261  ->copyView(cacheConfigMgr.getTableByName(memberPair.first)
2262  ->getView(memberPair.second),
2263  memberPair.second,
2264  cacheConfigMgr.getTableByName(memberPair.first)
2265  ->getView(memberPair.second)
2266  .getAuthor(),
2267  true /* looseColumnMatching */);
2268 
2269  //Note: copyView does not make the new view the active view,
2270  // to make the new view the active view do this:
2271  // nameToTableMap_.at(memberPair.first)->setActiveView(memberPair.second);
2272  } //end member map copy loop
2273  __GEN_COUTT__ << "Done with member copy loop." << __E__;
2274 
2275  // for each member
2276  // if doActivate, configBase->init()
2277  if(doActivate)
2278  {
2279  std::string accumulatedWarnings;
2280  const int numOfThreads = PROCESSOR_COUNT / 2;
2281  __GEN_COUT__ << " PROCESSOR_COUNT " << PROCESSOR_COUNT << " ==> "
2282  << numOfThreads << " threads for initializing tables." << __E__;
2283  if(groupType != ConfigurationManager::GroupType::CONFIGURATION_TYPE ||
2284  numOfThreads < 2) // no multi-threading
2285  {
2286  for(auto& memberPair : memberMap)
2287  {
2288  // do NOT allow activating Scratch versions if tracking is ON!
2289  if(!ignoreVersionTracking &&
2290  ConfigurationInterface::isVersionTrackingEnabled() &&
2291  memberPair.second.isScratchVersion())
2292  {
2293  __SS__ << "Error while activating member Table '"
2294  << nameToTableMap_[memberPair.first]->getTableName()
2295  << "-v" << memberPair.second
2296  << " for member map. When version tracking is enabled, "
2297  "Scratch views"
2298  << " are not allowed! Please only use unique, persistent "
2299  "versions when version tracking is enabled."
2300  << __E__;
2301  __SS_ONLY_THROW__;
2302  }
2303 
2304  // attempt to init using the configuration's specific init
2305  // this could be risky user code, try and catch
2306  try
2307  {
2308  nameToTableMap_.at(memberPair.first)->init(this);
2309  }
2310  catch(std::runtime_error& e)
2311  {
2312  __SS__ << "Error detected calling " << memberPair.first
2313  << ".init()!\n\n " << e.what() << __E__;
2314  accumulatedWarnings += ss.str();
2315  }
2316  catch(...)
2317  {
2318  __SS__ << "Unknown Error detected calling " << memberPair.first
2319  << ".init()!\n\n " << __E__;
2320  try
2321  {
2322  throw;
2323  } //one more try to printout extra info
2324  catch(const std::exception& e)
2325  {
2326  ss << "Exception message: " << e.what();
2327  }
2328  catch(...)
2329  {
2330  }
2331  accumulatedWarnings += ss.str();
2332  }
2333  }
2334  }
2335  else //multi-threading
2336  {
2337  int threadsLaunched = 0;
2338  int foundThreadIndex = 0;
2339  std::mutex threadMutex; // to protect accumulatedWarnings
2340  std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
2341  for(int i = 0; i < numOfThreads; ++i)
2342  threadDone.push_back(std::make_shared<std::atomic<bool>>(true));
2343 
2344  if(!ignoreVersionTracking &&
2345  ConfigurationInterface::isVersionTrackingEnabled())
2346  for(auto& memberPair : memberMap)
2347  {
2348  // do NOT allow activating Scratch versions if tracking is ON!
2349  if(memberPair.second.isScratchVersion())
2350  {
2351  __SS__
2352  << "Error while activating member Table '"
2353  << nameToTableMap_[memberPair.first]->getTableName()
2354  << "-v" << memberPair.second
2355  << " for member map. When version tracking is enabled, "
2356  "Scratch views"
2357  << " are not allowed! Please only use unique, persistent "
2358  "versions when version tracking is enabled."
2359  << __E__;
2360  __SS_ONLY_THROW__;
2361  }
2362  }
2363 
2364  for(auto& memberPair : memberMap)
2365  {
2366  if(threadsLaunched >= numOfThreads)
2367  {
2368  //find availableThreadIndex
2369  foundThreadIndex = -1;
2370  while(foundThreadIndex == -1)
2371  {
2372  for(int i = 0; i < numOfThreads; ++i)
2373  if(*(threadDone[i]))
2374  {
2375  foundThreadIndex = i;
2376  break;
2377  }
2378  if(foundThreadIndex == -1)
2379  {
2380  __GEN_COUTT__ << "Waiting for available thread..."
2381  << __E__;
2382  usleep(10000);
2383  }
2384  } //end thread search loop
2385  threadsLaunched = numOfThreads - 1;
2386  }
2387  __GEN_COUTT__ << "Starting init table thread... " << foundThreadIndex
2388  << " for " << memberPair.first << __E__;
2389  *(threadDone[foundThreadIndex]) = false;
2390 
2391  std::thread(
2392  [](ConfigurationManager* cfgMgr,
2393  ots::TableBase* theTable,
2394  std::string* theAccumulatedWarnings,
2395  std::mutex* theThreadMutex,
2396  std::shared_ptr<std::atomic<bool>> theThreadDone) {
2397  ConfigurationManager::initTableThread(cfgMgr,
2398  theTable,
2399  theAccumulatedWarnings,
2400  theThreadMutex,
2401  theThreadDone);
2402  },
2403  this,
2404  nameToTableMap_.at(memberPair.first),
2405  &accumulatedWarnings,
2406  &threadMutex,
2407  threadDone[foundThreadIndex])
2408  .detach();
2409 
2410  ++threadsLaunched;
2411  ++foundThreadIndex;
2412  } //end table init thread loop
2413 
2414  //check for all threads done
2415  do
2416  {
2417  foundThreadIndex = -1;
2418  for(int i = 0; i < numOfThreads; ++i)
2419  if(!*(threadDone[i]))
2420  {
2421  foundThreadIndex = i;
2422  break;
2423  }
2424  if(foundThreadIndex != -1)
2425  {
2426  __GEN_COUTT__ << "Waiting for thread to finish... "
2427  << foundThreadIndex << __E__;
2428  usleep(10000);
2429  }
2430  } while(foundThreadIndex != -1); //end thread done search loop
2431 
2432  } //end multi-thread handling
2433 
2434  if(accumulatedWarnings != "")
2435  {
2436  __GEN_COUT__ << "Activating the member map after copying cache had the "
2437  "following warnings: "
2438  << accumulatedWarnings << __E__;
2439  }
2440  } //end activate/init of member tables
2441 
2442  // if doActivate
2443  // set theConfigurationTableGroup_, theContextTableGroup_, or
2444  // theBackboneTableGroup_ on
2445  // success
2446 
2447  if(doActivate)
2448  {
2449  if(groupType == ConfigurationManager::GroupType::CONTEXT_TYPE) //
2450  {
2451  // __GEN_COUT_INFO__ << "Type=Context, Group loaded: " <<
2452  // groupName
2453  //<<
2454  // "(" << groupKey << ")" << __E__;
2455  theContextTableGroup_ = groupName;
2456  theContextTableGroupKey_ =
2457  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2458  }
2459  else if(groupType == ConfigurationManager::GroupType::BACKBONE_TYPE)
2460  {
2461  // __GEN_COUT_INFO__ << "Type=Backbone, Group loaded: " <<
2462  // groupName <<
2463  // "(" << groupKey << ")" << __E__;
2464  theBackboneTableGroup_ = groupName;
2465  theBackboneTableGroupKey_ =
2466  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2467  }
2468  else if(groupType == ConfigurationManager::GroupType::ITERATE_TYPE)
2469  {
2470  // __GEN_COUT_INFO__ << "Type=Iterate, Group loaded: " <<
2471  // groupName
2472  //<<
2473  // "(" << groupKey << ")" << __E__;
2474  theIterateTableGroup_ = groupName;
2475  theIterateTableGroupKey_ =
2476  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2477  }
2478  else // is theConfigurationTableGroup_
2479  {
2480  // __GEN_COUT_INFO__ << "Type=Configuration, Group loaded: " <<
2481  // groupName <<
2482  // "(" << groupKey << ")" << __E__;
2483  theConfigurationTableGroup_ = groupName;
2484  theConfigurationTableGroupKey_ =
2485  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2486  }
2487  }
2488 
2489  if(doActivate)
2490  __GEN_COUT__ << "------------------------------------- cacheCopy init "
2491  "complete \t [for all "
2492  "plug-ins in member map"
2493  << "']" << __E__;
2494 
2495  __GEN_COUTT__ << "Completed cache copy." << __E__;
2496  if(groupName != "" && !TableGroupKey(groupKey).isInvalid())
2497  lastGroupLoad_[convertGroupTypeToName(groupType)] =
2498  make_pair(make_pair(groupName, TableGroupKey(groupKey)), memberMap);
2499  } // end failed group load try
2500  catch(...)
2501  {
2502  __GEN_COUT__ << "Unknown failure in cache copy." << __E__;
2503  // save group name and key of failed load attempt
2504  lastFailedGroupLoad_[convertGroupTypeToName(groupType)] =
2505  std::pair<std::string, TableGroupKey>(groupName, TableGroupKey(groupKey));
2506  throw;
2507  } //end unknown failure handling
2508 } // end copyTableGroupFromCache()
2509 
2510 //==============================================================================
2511 std::pair<std::string /* groupName */, TableGroupKey>
2512 ConfigurationManager::getGroupOfLoadedTable(const std::string& tableName) const
2513 {
2514  for(const auto& loadedGroup : lastGroupLoad_) //search the loaded group member map
2515  if(loadedGroup.second.second.find(tableName) != loadedGroup.second.second.end())
2516  return loadedGroup.second.first; //found! so return group name/key
2517  return std::make_pair("", TableGroupKey(TableGroupKey::INVALID));
2518 } // end getGroupOfLoadedTable()
2519 
2520 //==============================================================================
2522 void ConfigurationManager::initTableThread(ConfigurationManager* cfgMgr,
2523  ots::TableBase* table,
2524  std::string* threadErrors,
2525  std::mutex* threadMutex,
2526  std::shared_ptr<std::atomic<bool>> threadDone)
2527 try
2528 {
2529  __COUTT__ << "Thread init of " << table->getTableName() << "-v"
2530  << table->getViewVersion() << " threadErrors=" << (threadErrors ? 1 : 0)
2531  << __E__;
2532 
2533  // attempt to init using the configuration's specific init
2534  // this could be risky user code, try and catch
2535  try
2536  {
2537  __COUTTV__(StringMacros::mapToString(cfgMgr->getActiveVersions()));
2538  table->init(cfgMgr);
2539  }
2540  catch(std::runtime_error& e)
2541  {
2542  __SS__ << "Error detected calling " << table->getTableName() << ".init()!\n\n "
2543  << e.what() << __E__;
2544 
2545  if(threadErrors)
2546  {
2547  std::lock_guard<std::mutex> lock(*threadMutex);
2548  *threadErrors += ss.str();
2549  }
2550  else
2551  {
2552  ss << StringMacros::stackTrace();
2553  __SS_ONLY_THROW__;
2554  }
2555  }
2556  catch(...)
2557  {
2558  __SS__ << "Unknown Error detected calling " << table->getTableName()
2559  << ".init()!\n\n " << __E__;
2560  try
2561  {
2562  throw;
2563  } //one more try to printout extra info
2564  catch(const std::exception& e)
2565  {
2566  ss << "Exception message: " << e.what();
2567  }
2568  catch(...)
2569  {
2570  }
2571 
2572  if(threadErrors)
2573  {
2574  std::lock_guard<std::mutex> lock(*threadMutex);
2575  *threadErrors += ss.str();
2576  }
2577  else
2578  {
2579  ss << StringMacros::stackTrace();
2580  __SS_ONLY_THROW__;
2581  }
2582  }
2583 
2584  *(threadDone) = true;
2585 } // end initTableThread()
2586 catch(...)
2587 {
2588  __SS__ << "Error occurred initializing table '" << table->getTableName() << "-v"
2589  << table->getViewVersion() << "'..." << __E__;
2590  try
2591  {
2592  throw;
2593  }
2594  catch(const std::runtime_error& e)
2595  {
2596  ss << " Run-time Exception message: " << e.what();
2597  }
2598  catch(const std::exception& e)
2599  {
2600  ss << " Exception message: " << e.what();
2601  }
2602  __COUT_WARN__ << ss.str() << __E__;
2603 
2604  if(threadErrors)
2605  {
2606  std::lock_guard<std::mutex> lock(*threadMutex);
2607  *threadErrors += ss.str();
2608  }
2609 
2610  *(threadDone) = true;
2611 } // end initTableThread catch
2612 
2613 //==============================================================================
2615 void ConfigurationManager::fillTableThread(
2616  ConfigurationInterface* theInterface,
2617  std::map<std::string, ots::TableBase*>* nameToTableMap,
2618  ots::TableBase* table,
2619  std::string tableName,
2620  ots::TableVersion version,
2621  std::string* threadErrors,
2622  std::mutex* threadMutex,
2623  std::shared_ptr<std::atomic<bool>> threadDone)
2624 try
2625 {
2626  __COUTT__ << "Thread fill of " << tableName << "-v" << version << __E__;
2627 
2628  // std::map<std::string, ots::TableBase *> n;
2629  // std::map<std::string, ots::TableBase *>*nameToTableMap = &n;
2630  // ots::TableBase* table;
2631  // // ots::TableVersion v;
2632  // // ots::TableVersion* version = &v;
2633  // std::string a;
2634  // std::string* accumulatedWarnings = &a;
2635  // std::string tableName = "";
2636  std::string getError = "";
2637  // attempt to init using the configuration's specific init
2638  // this could be risky user code, try and catch
2639  try
2640  {
2641  theInterface->get(table, // tablePtr
2642  tableName, // tableName
2643  0, // groupKey
2644  0, // groupName
2645  false, // dontFill=false to fill
2646  version, // version
2647  false // resetTable
2648  );
2649  }
2650  catch(const std::runtime_error& e)
2651  {
2652  __SS__ << "Failed to load member table '" << tableName << "-v" << version
2653  << "' - here is the error: \n\n"
2654  << e.what() << __E__;
2655 
2656  ss << "\nIf the table '" << tableName
2657  << "' should not exist, then please remove it from the group. If it "
2658  "should exist, then it "
2659  << "seems to have a problem; use the Table Editor to fix the table "
2660  "definition, or "
2661  "edit the table content to match the table definition."
2662  << __E__;
2663 
2664  // if accumulating warnings and table view was created, then continue
2665  if(threadErrors)
2666  getError = ss.str();
2667  else
2668  __SS_ONLY_THROW__;
2669  }
2670  catch(...)
2671  {
2672  __SS__ << "Failed to load member table '" << tableName << "-v" << version
2673  << "' due to unknown error!" << __E__;
2674  try
2675  {
2676  throw;
2677  } //one more try to printout extra info
2678  catch(const std::exception& e)
2679  {
2680  ss << "Exception message: " << e.what();
2681  }
2682  catch(...)
2683  {
2684  }
2685  ss << "\nIf the table '" << tableName
2686  << "' should not exist, then please remove it from the group. If it "
2687  "should exist, then it "
2688  << "seems to have a problem; use the Table Editor to fix the table "
2689  "definition, or "
2690  "edit the table content to match the table definition."
2691  << __E__;
2692 
2693  // if accumulating warnings and table view was created, then continue
2694  if(threadErrors)
2695  getError = ss.str();
2696  else
2697  __SS_THROW__;
2698  }
2699 
2700  if(getError != "")
2701  __COUTV__(getError);
2702 
2703  __COUT_TYPE__(TLVL_TRACE + 1)
2704  << __COUT_HDR__ << "Checking ptr.. " << (table ? "GOOD" : "BAD") << __E__;
2705  if(!table)
2706  {
2707  __SS__ << "Null pointer returned for table '" << tableName
2708  << ".' Was the table info deleted?" << __E__;
2709  __COUT_ERR__ << ss.str();
2710 
2711  std::lock_guard<std::mutex> lock(*threadMutex);
2712  nameToTableMap->erase(tableName);
2713 
2714  if(threadErrors)
2715  {
2716  *threadErrors += ss.str();
2717  *(threadDone) = true;
2718  return;
2719  }
2720  else
2721  __SS_ONLY_THROW__;
2722  }
2723  else
2724  {
2725  std::lock_guard<std::mutex> lock(*threadMutex);
2726  (*nameToTableMap)[tableName] = table;
2727  }
2728 
2729  if(nameToTableMap->at(tableName)->getViewP())
2730  {
2731  __COUT_TYPE__(TLVL_TRACE + 1)
2732  << __COUT_HDR__
2733  << "Activated version: " << nameToTableMap->at(tableName)->getViewVersion()
2734  << __E__;
2735 
2736  if(threadErrors && getError != "")
2737  {
2738  __SS__ << "Error caught during '" << tableName << "' table retrieval: \n"
2739  << getError << __E__;
2740  __COUT_ERR__ << ss.str();
2741  std::lock_guard<std::mutex> lock(*threadMutex);
2742  *threadErrors += ss.str();
2743  }
2744  }
2745  else
2746  {
2747  __SS__ << tableName << ": View version not activated properly!";
2748  __SS_THROW__;
2749  }
2750 
2751  __COUTT__ << "end Thread fill of " << tableName << "-v" << version << __E__;
2752  *(threadDone) = true;
2753 } // end fillTableThread()
2754 catch(const std::runtime_error& e)
2755 {
2756  __SS__ << "Error occurred filling table '" << tableName << "-v" << version
2757  << "': " << e.what() << __E__;
2758  __COUT_ERR__ << ss.str();
2759 
2760  if(threadErrors)
2761  {
2762  std::lock_guard<std::mutex> lock(*threadMutex);
2763  *threadErrors += ss.str();
2764  }
2765 
2766  *(threadDone) = true;
2767 }
2768 catch(...)
2769 {
2770  __SS__ << "Unknwon error occurred filling table '" << tableName << "-v" << version
2771  << "'..." << __E__;
2772  try
2773  {
2774  throw;
2775  } //one more try to printout extra info
2776  catch(const std::exception& e)
2777  {
2778  ss << "Exception message: " << e.what();
2779  }
2780  catch(...)
2781  {
2782  }
2783  __COUT_ERR__ << ss.str();
2784 
2785  if(threadErrors)
2786  {
2787  std::lock_guard<std::mutex> lock(*threadMutex);
2788  *threadErrors += ss.str();
2789  }
2790 
2791  *(threadDone) = true;
2792 } // end fillTableThread catch
2793 
2794 //==============================================================================
2800 std::map<std::string, std::pair<std::string, TableGroupKey>>
2802 {
2803  // map<type, pair <groupName , TableGroupKey> >
2804  std::map<std::string, std::pair<std::string, TableGroupKey>> retMap;
2805 
2806  retMap[ConfigurationManager::GROUP_TYPE_NAME_CONTEXT] =
2807  std::pair<std::string, TableGroupKey>(
2808  theContextTableGroup_,
2809  theContextTableGroupKey_ ? *theContextTableGroupKey_ : TableGroupKey());
2810  retMap[ConfigurationManager::GROUP_TYPE_NAME_BACKBONE] =
2811  std::pair<std::string, TableGroupKey>(
2812  theBackboneTableGroup_,
2813  theBackboneTableGroupKey_ ? *theBackboneTableGroupKey_ : TableGroupKey());
2814  retMap[ConfigurationManager::GROUP_TYPE_NAME_ITERATE] =
2815  std::pair<std::string, TableGroupKey>(
2816  theIterateTableGroup_,
2817  theIterateTableGroupKey_ ? *theIterateTableGroupKey_ : TableGroupKey());
2818  retMap[ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION] =
2819  std::pair<std::string, TableGroupKey>(theConfigurationTableGroup_,
2820  theConfigurationTableGroupKey_
2821  ? *theConfigurationTableGroupKey_
2822  : TableGroupKey());
2823  return retMap;
2824 } // end getActiveTableGroups()
2825 
2826 //==============================================================================
2827 const std::string& ConfigurationManager::getActiveGroupName(
2828  const ConfigurationManager::GroupType& type) const
2829 {
2830  if(type == ConfigurationManager::GroupType::CONFIGURATION_TYPE)
2831  return theConfigurationTableGroup_;
2832  else if(type == ConfigurationManager::GroupType::CONTEXT_TYPE)
2833  return theContextTableGroup_;
2834  else if(type == ConfigurationManager::GroupType::BACKBONE_TYPE)
2835  return theBackboneTableGroup_;
2836  else if(type == ConfigurationManager::GroupType::ITERATE_TYPE)
2837  return theIterateTableGroup_;
2838 
2839  __SS__ << "IMPOSSIBLE! Invalid type requested '" << (int)type << "'" << __E__;
2840  __SS_THROW__;
2841 } // end getActiveGroupName()
2842 
2843 //==============================================================================
2844 TableGroupKey ConfigurationManager::getActiveGroupKey(
2845  const ConfigurationManager::GroupType& type) const
2846 {
2847  if(type == ConfigurationManager::GroupType::CONFIGURATION_TYPE)
2848  return theConfigurationTableGroupKey_ ? *theConfigurationTableGroupKey_
2849  : TableGroupKey();
2850  else if(type == ConfigurationManager::GroupType::CONTEXT_TYPE)
2851  return theContextTableGroupKey_ ? *theContextTableGroupKey_ : TableGroupKey();
2852  else if(type == ConfigurationManager::GroupType::BACKBONE_TYPE)
2853  return theBackboneTableGroupKey_ ? *theBackboneTableGroupKey_ : TableGroupKey();
2854  else if(type == ConfigurationManager::GroupType::ITERATE_TYPE)
2855  return theIterateTableGroupKey_ ? *theIterateTableGroupKey_ : TableGroupKey();
2856 
2857  __SS__ << "IMPOSSIBLE! Invalid type requested '" << (int)type << "'" << __E__;
2858  __SS_THROW__;
2859 } // end getActiveGroupKey()
2860 
2861 //==============================================================================
2862 ConfigurationTree ConfigurationManager::getContextNode(
2863  const std::string& contextUID, const std::string& /*applicationUID*/) const
2864 {
2865  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
2866  contextUID);
2867 } // end getContextNode()
2868 
2869 //==============================================================================
2870 ConfigurationTree ConfigurationManager::getSupervisorNode(
2871  const std::string& contextUID, const std::string& applicationUID) const
2872 {
2873  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
2874  contextUID + "/LinkToApplicationTable/" + applicationUID);
2875 } // end getSupervisorNode()
2876 
2877 //==============================================================================
2878 ConfigurationTree ConfigurationManager::getSupervisorTableNode(
2879  const std::string& contextUID, const std::string& applicationUID) const
2880 {
2881  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
2882  contextUID + "/LinkToApplicationTable/" + applicationUID +
2883  "/LinkToSupervisorTable");
2884 } // end getSupervisorTableNode()
2885 
2886 //==============================================================================
2889 {
2890  auto contextChildren =
2891  getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName())
2892  .getChildren();
2893  for(const auto& contextChild : contextChildren)
2894  {
2895  auto appChildren = contextChild.second.getNode("LinkToApplicationTable")
2896  .getChildren(); //colContext_.colLinkToApplicationTable_
2897  for(const auto& appChild : appChildren)
2898  {
2899  if(appChild.second.getNode("Class").getValue() ==
2900  "ots::GatewaySupervisor") //colApplication_.colClass_ ... XDAQContextTable::GATEWAY_SUPERVISOR_CLASS)
2901  return appChild.second;
2902  }
2903  }
2904  __SS__ << "No Gateway Supervisor node found!" << __E__;
2905  __SS_THROW__;
2906 } // end getGatewaySupervisorNode()
2907 
2908 //==============================================================================
2909 ConfigurationTree ConfigurationManager::getNode(const std::string& nodeString,
2910  bool doNotThrowOnBrokenUIDLinks) const
2911 {
2912  // __GEN_COUT__ << "nodeString=" << nodeString << " len=" << nodeString.length() << __E__;
2913 
2914  // get nodeName (in case of / syntax)
2915  if(nodeString.length() < 1)
2916  {
2917  __SS__ << ("Invalid empty node name") << __E__;
2918  __GEN_SS_THROW__;
2919  }
2920 
2921  // ignore multiple starting slashes
2922  size_t startingIndex = 0;
2923  while(startingIndex < nodeString.length() && nodeString[startingIndex] == '/')
2924  ++startingIndex;
2925  size_t endingIndex = nodeString.find('/', startingIndex);
2926  if(endingIndex == std::string::npos)
2927  endingIndex = nodeString.length();
2928 
2929  std::string nodeName = nodeString.substr(startingIndex, endingIndex - startingIndex);
2930  // __GEN_COUT__ << "nodeName=" << nodeName << " len" << nodeName.length() << __E__;
2931  if(nodeName.length() < 1)
2932  {
2933  // return root node
2934  return ConfigurationTree(this, 0);
2935 
2936  // __SS__ << "Invalid node name: " << nodeName << __E__;
2937  // __GEN_COUT_ERR__ << ss.str();
2938  // __SS_THROW__;
2939  }
2940  ++endingIndex;
2941  std::string childPath =
2942  (endingIndex >= nodeString.length() ? "" : nodeString.substr(endingIndex));
2943 
2944  // __GEN_COUT__ << "childPath=" << childPath << " len=" << childPath.length() << " endingIndex=" << endingIndex << " nodeString.length()=" << nodeString.length() << __E__;
2945 
2946  ConfigurationTree configTree(this, getTableByName(nodeName));
2947 
2948  if(childPath.length() > 1)
2949  return configTree.getNode(childPath, doNotThrowOnBrokenUIDLinks);
2950  else
2951  return configTree;
2952 } // end getNode()
2953 
2954 //==============================================================================
2955 std::map<std::string, ConfigurationTree> ConfigurationManager::getNodes(
2956  const std::string& nodeString) const
2957 {
2958  return getNode(nodeString).getChildrenMap();
2959 }
2960 
2961 //==============================================================================
2964  const ConfigurationTree& /*node*/, const std::string& /*startPath*/) const
2967 {
2968  std::string path = "/";
2969  return path;
2970 } // end getFirstPathToNode()
2971 
2972 //==============================================================================
2978 std::vector<std::pair<std::string, ConfigurationTree>> ConfigurationManager::getChildren(
2979  std::map<std::string, TableVersion>* memberMap,
2980  std::string* accumulatedTreeErrors) const
2981 {
2982  std::vector<std::pair<std::string, ConfigurationTree>> retVector;
2983 
2984  // if(accumulatedTreeErrors)
2985  // *accumulatedTreeErrors = "";
2986 
2987  bool filtering = memberMap && memberMap->size();
2988 
2989  //from root node, want active tables:
2990  for(auto& tablePair : nameToTableMap_)
2991  {
2992  if(filtering)
2993  {
2994  //if not in member map, ignore
2995  if(memberMap->find(tablePair.first) == memberMap->end())
2996  continue;
2997 
2998  //if in member map, and not active - that is a problem!
2999  try
3000  {
3001  if(!tablePair.second->isActive())
3002  {
3003  __SS__ << "Get Children with member map requires a child '"
3004  << tablePair.first << "' that is not active!" << __E__;
3005  __SS_THROW__;
3006  }
3007  }
3008  catch(const std::runtime_error& e)
3009  {
3010  if(accumulatedTreeErrors)
3011  {
3012  *accumulatedTreeErrors += e.what();
3013  __GEN_COUT_ERR__ << "Skipping " << tablePair.first
3014  << " since the table "
3015  "is not active."
3016  << __E__;
3017  continue;
3018  }
3019  throw;
3020  }
3021  }
3022 
3023  if(!tablePair.second->isActive()) // only consider if active
3024  continue;
3025 
3026  ConfigurationTree newNode(this, tablePair.second);
3027  if(accumulatedTreeErrors) // check for disconnects
3028  {
3029  try
3030  {
3031  std::vector<std::pair<std::string, ConfigurationTree>> newNodeChildren =
3032  newNode.getChildren();
3033  for(auto& newNodeChild : newNodeChildren)
3034  {
3035  if(newNodeChild.second.getTableName() ==
3036  ConfigurationManager::DESKTOP_ICON_TABLE_NAME &&
3037  !newNodeChild.second.isEnabled())
3038  continue; //skip check for Desktop Icons that are disabled.
3039 
3040  std::vector<std::pair<std::string, ConfigurationTree>>
3041  twoDeepChildren = newNodeChild.second.getChildren();
3042 
3043  for(auto& twoDeepChild : twoDeepChildren)
3044  {
3045  //__GEN_COUT__ << tablePair.first << " " <<
3046  // newNodeChild.first << " " << twoDeepChild.first
3047  // << __E__;
3048  if(twoDeepChild.second.isLinkNode() &&
3049  twoDeepChild.second.isDisconnected() &&
3050  twoDeepChild.second.getDisconnectedTableName() !=
3051  TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3052  {
3053  __SS__ << "At node '" + tablePair.first +
3054  "' with entry UID '" + newNodeChild.first +
3055  "' there is a disconnected child node at link "
3056  "column '" +
3057  twoDeepChild.first + "'" +
3058  " that points to table named '" +
3059  twoDeepChild.second.getDisconnectedTableName() +
3060  "' ...";
3061  *accumulatedTreeErrors += ss.str();
3062  }
3063  }
3064  }
3065  }
3066  catch(std::runtime_error& e)
3067  {
3068  __SS__ << "At node '" + tablePair.first +
3069  "' error detected descending through children:\n" +
3070  e.what();
3071  *accumulatedTreeErrors += ss.str();
3072  }
3073  } // done checking for disconnects
3074 
3075  retVector.push_back(
3076  std::pair<std::string, ConfigurationTree>(tablePair.first, newNode));
3077  } //end active table loop
3078 
3079  return retVector;
3080 } // end getChildren()
3081 
3082 //==============================================================================
3088 std::map<std::string /* childName */, ConfigurationTree>
3089 ConfigurationManager::getChildrenMap(std::map<std::string, TableVersion>* memberMap,
3090  std::string* accumulatedTreeErrors) const
3091 {
3092  std::map<std::string /* childName */, ConfigurationTree> retMap;
3093 
3094  // if(accumulatedTreeErrors)
3095  // *accumulatedTreeErrors = "";
3096 
3097  bool filtering = memberMap && memberMap->size();
3098 
3099  //from root node, want active tables:
3100  for(auto& tablePair : nameToTableMap_)
3101  {
3102  if(filtering)
3103  {
3104  //if not in member map, ignore
3105  if(memberMap->find(tablePair.first) == memberMap->end())
3106  continue;
3107 
3108  //if in member map, and not active - that is a problem!
3109  try
3110  {
3111  if(!tablePair.second->isActive())
3112  {
3113  __SS__ << "Get Children with member map requires a child '"
3114  << tablePair.first << "' that is not active!" << __E__;
3115  __SS_THROW__;
3116  }
3117  }
3118  catch(const std::runtime_error& e)
3119  {
3120  if(accumulatedTreeErrors)
3121  {
3122  *accumulatedTreeErrors += e.what();
3123  __GEN_COUT_ERR__ << "Skipping " << tablePair.first
3124  << " since the table "
3125  "is not active."
3126  << __E__;
3127  continue;
3128  }
3129  throw;
3130  }
3131  }
3132 
3133  if(!tablePair.second->isActive()) // only consider if active
3134  continue;
3135 
3136  ConfigurationTree newNode(this, tablePair.second);
3137  if(accumulatedTreeErrors) // check for disconnects
3138  {
3139  try
3140  {
3141  std::vector<std::pair<std::string, ConfigurationTree>> newNodeChildren =
3142  newNode.getChildren();
3143  for(auto& newNodeChild : newNodeChildren)
3144  {
3145  if(newNodeChild.second.getTableName() ==
3146  ConfigurationManager::DESKTOP_ICON_TABLE_NAME &&
3147  !newNodeChild.second.isEnabled())
3148  continue; //skip check for Desktop Icons that are disabled.
3149 
3150  std::vector<std::pair<std::string, ConfigurationTree>>
3151  twoDeepChildren = newNodeChild.second.getChildren();
3152 
3153  for(auto& twoDeepChild : twoDeepChildren)
3154  {
3155  //__GEN_COUT__ << tablePair.first << " " <<
3156  // newNodeChild.first << " " << twoDeepChild.first
3157  // << __E__;
3158  if(twoDeepChild.second.isLinkNode() &&
3159  twoDeepChild.second.isDisconnected() &&
3160  twoDeepChild.second.getDisconnectedTableName() !=
3161  TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3162  {
3163  __SS__ << "At node '" + tablePair.first +
3164  "' with entry UID '" + newNodeChild.first +
3165  "' there is a disconnected child node at link "
3166  "column '" +
3167  twoDeepChild.first + "'" +
3168  " that points to table named '" +
3169  twoDeepChild.second.getDisconnectedTableName() +
3170  "' ...";
3171  *accumulatedTreeErrors += ss.str();
3172  }
3173  }
3174  }
3175  }
3176  catch(std::runtime_error& e)
3177  {
3178  __SS__ << "At node '" + tablePair.first +
3179  "' error detected descending through children:\n" +
3180  e.what();
3181  *accumulatedTreeErrors += ss.str();
3182  }
3183  } // done checking for disconnects
3184 
3185  retMap.emplace(
3186  std::pair<std::string, ConfigurationTree>(tablePair.first, newNode));
3187  } //end active table loop
3188 
3189  return retMap;
3190 } // end getChildrenMap()
3191 
3192 //==============================================================================
3197 const TableBase* ConfigurationManager::getTableByName(const std::string& tableName) const
3198 {
3199  std::map<std::string, TableBase*>::const_iterator it;
3200  if((it = nameToTableMap_.find(tableName)) == nameToTableMap_.end())
3201  {
3202  __SS__ << "Can not find table named '" << tableName
3203  << "' - you need to load the table before it can be used.";
3204 
3205  if(nameToTableMap_.size() == 0)
3206  ss << "\n\nAll tables are missing. Your configuration database connection "
3207  "may have been interrupted. Did an ssh tunnel disconnect?"
3208  << __E__;
3209  else
3210  {
3211  ss << " It probably is missing from the member list of the Table "
3212  "Group that was loaded.\n"
3213  << "\nYou may need to enter wiz mode to remedy the situation, use the "
3214  "following:\n"
3215  << "\n\t ots --wiz"
3216  << "\n\n\n\n"
3217  << __E__;
3218 
3219  ss << __E__ << StringMacros::stackTrace() << __E__;
3220  }
3221 
3222  // prints out too often, so only throw
3223  // if(tableName != TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3224  // __GEN_COUT_WARN__ << "\n" << ss.str();
3225  __SS_ONLY_THROW__;
3226  }
3227  // TLOG_DEBUG(30) << "Table " << tableName << " is at " << static_cast<void*>(it->second);
3228  return it->second;
3229 } // end getTableByName()
3230 
3231 //==============================================================================
3236 {
3237  if(!theBackboneTableGroupKey_) // no active backbone
3238  {
3239  __GEN_COUT_WARN__ << "getTableGroupKey() Failed! No active backbone currently."
3240  << __E__;
3241  return TableGroupKey();
3242  }
3243 
3244  // may already be loaded, but that's ok, load anyway to be sure
3245  loadTableGroup(theBackboneTableGroup_, *theBackboneTableGroupKey_);
3246 
3247  return *theBackboneTableGroupKey_;
3248 } // end loadConfigurationBackbone()
3249 
3251 //==============================================================================
3263 std::pair<std::string, TableGroupKey> ConfigurationManager::getTableGroupFromAlias(
3264  std::string systemAlias, ProgressBar* progressBar)
3265 {
3266  // steps
3267  // check if special alias
3268  // if so, parse and return name/key
3269  // else, load active backbone
3270  // find runType in Group Aliases table
3271  // return key
3272 
3273  if(progressBar)
3274  progressBar->step();
3275 
3276  if(systemAlias.find("GROUP:") == 0)
3277  {
3278  if(progressBar)
3279  progressBar->step();
3280 
3281  unsigned int i = strlen("GROUP:");
3282  unsigned int j = systemAlias.find(':', i);
3283 
3284  if(progressBar)
3285  progressBar->step();
3286  if(j > i) // success
3287  return std::pair<std::string, TableGroupKey>(
3288  systemAlias.substr(i, j - i), TableGroupKey(systemAlias.substr(j + 1)));
3289  else // failure
3290  return std::pair<std::string, TableGroupKey>("", TableGroupKey());
3291  }
3292 
3294 
3295  if(progressBar)
3296  progressBar->step();
3297 
3298  try
3299  {
3300  // find runType in Group Aliases table
3301  ConfigurationTree entry =
3302  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getNode(systemAlias);
3303 
3304  if(progressBar)
3305  progressBar->step();
3306 
3307  return std::pair<std::string, TableGroupKey>(
3308  entry.getNode("GroupName").getValueAsString(),
3309  TableGroupKey(entry.getNode("GroupKey").getValueAsString()));
3310  }
3311  catch(...)
3312  {
3313  }
3314 
3315  // on failure, here
3316 
3317  if(progressBar)
3318  progressBar->step();
3319 
3320  return std::pair<std::string, TableGroupKey>("", TableGroupKey());
3321 } // end getTableGroupFromAlias()
3322 
3323 //==============================================================================
3326 std::map<std::string /*groupAlias*/, std::pair<std::string /*groupName*/, TableGroupKey>>
3328 {
3330  false /* throwErrors */,
3331  "" /* pathToActiveGroupsFile */,
3332  ConfigurationManager::LoadGroupType::
3333  ONLY_BACKBONE_TYPE); // make sure the active configuration backbone is
3334  // loaded from disk (i.e. the latest activated at the ConfigurationGUISupervisor)!
3335 
3336  std::map<std::string /*groupAlias*/,
3337  std::pair<std::string /*groupName*/, TableGroupKey>>
3338  retMap;
3339 
3340  std::vector<std::pair<std::string, ConfigurationTree>> entries =
3341  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
3342  for(auto& entryPair : entries)
3343  {
3344  retMap[entryPair.first] = std::pair<std::string, TableGroupKey>(
3345  entryPair.second.getNode("GroupName").getValueAsString(),
3346  TableGroupKey(entryPair.second.getNode("GroupKey").getValueAsString()));
3347  }
3348  return retMap;
3349 } // end getActiveGroupAliases()
3350 
3351 //==============================================================================
3354 std::map<std::string /*table name*/,
3355  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
3357 {
3358  //__GEN_COUT__ << "getVersionAliases()" << __E__;
3359 
3360  std::map<std::string /*table name*/,
3361  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
3362  retMap;
3363 
3364  std::map<std::string, TableVersion> activeVersions = getActiveVersions();
3365  std::string versionAliasesTableName =
3366  ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
3367  if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
3368  {
3369  __SS__ << "Active version of VersionAliases missing!"
3370  << " Make sure you have a valid active Backbone Group." << __E__;
3371  __GEN_COUT_WARN__ << "\n" << ss.str();
3372  return retMap;
3373  }
3374 
3375  //__GEN_COUT__ << "activeVersions[\"" << versionAliasesTableName << "\"]=" << activeVersions[versionAliasesTableName] << __E__;
3376 
3377  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
3378  getNode(versionAliasesTableName).getChildren();
3379 
3380  // create map
3381  // add the first of each tableName, versionAlias pair encountered
3382  // ignore any repeats (Note: this also prevents overwriting of Scratch alias)
3383  std::string tableName, versionAlias;
3384  for(auto& aliasNodePair : aliasNodePairs)
3385  {
3386  tableName = aliasNodePair.second.getNode("TableName").getValueAsString();
3387  versionAlias = aliasNodePair.second.getNode("VersionAlias").getValueAsString();
3388 
3389  if(retMap.find(tableName) != retMap.end() &&
3390  retMap[tableName].find(versionAlias) != retMap[tableName].end())
3391  continue; // skip repeats (Note: this also prevents overwriting of Scratch
3392  // alias)
3393 
3394  // else add version to map
3395  retMap[tableName][versionAlias] =
3396  TableVersion(aliasNodePair.second.getNode("Version").getValueAsString());
3397  }
3398 
3399  return retMap;
3400 } // end getVersionAliases()
3401 
3402 //==============================================================================
3404 std::map<std::string, TableVersion> ConfigurationManager::getActiveVersions(void) const
3405 {
3406  std::map<std::string, TableVersion> retMap;
3407  for(auto& table : nameToTableMap_)
3408  {
3409  __GEN_COUTS__(2) << table.first << __E__;
3410 
3411  // check configuration pointer is not null and that there is an active view
3412  if(table.second && table.second->isActive())
3413  {
3414  __GEN_COUTS__(2) << table.first << "_v" << table.second->getViewVersion()
3415  << __E__;
3416  retMap.insert(std::pair<std::string, TableVersion>(
3417  table.first, table.second->getViewVersion()));
3418  }
3419  }
3420 
3421  return retMap;
3422 } // end getActiveVersions()
3423 
3426 //{
3427 //
3428 // //fixme/todo this is called before setupAll so it breaks!
3429 // //====================================================
3430 // const DetectorConfiguration* detectorConfiguration =
3431 //__GET_CONFIG__(DetectorConfiguration); for(auto& type :
3432 // detectorConfiguration->getDetectorTypes()) theDACsConfigurations_[type] =
3433 //(DACsTableBase*)(getTableByName(type + "DACsConfiguration"));
3434 // //====================================================
3435 //
3436 // theDACStreams_[fecName].makeStream(fecName,
3437 // __GET_CONFIG__(DetectorConfiguration),
3438 // __GET_CONFIG__(DetectorToFEConfiguration),
3439 // theDACsConfigurations_,
3440 // __GET_CONFIG__(MaskConfiguration));//, theTrimConfiguration_);
3441 //
3442 // __GEN_COUT__ << "Done with DAC stream!" << __E__;
3443 // return theDACStreams_[fecName];
3444 //}
3445 
3446 //==============================================================================
3447 std::shared_ptr<TableGroupKey> ConfigurationManager::makeTheTableGroupKey(
3448  TableGroupKey key)
3449 {
3450  if(theConfigurationTableGroupKey_)
3451  {
3452  if(*theConfigurationTableGroupKey_ != key)
3454  else
3455  return theConfigurationTableGroupKey_;
3456  }
3457  return std::shared_ptr<TableGroupKey>(new TableGroupKey(key));
3458 } // end makeTheTableGroupKey()
3459 
3460 //==============================================================================
3461 const std::set<std::string>& ConfigurationManager::getActiveContextMemberNames()
3462 {
3463  //copy fixed context tables, then add optional tables if active
3464  contextMemberNames_ = ConfigurationManager::fixedContextMemberNames_;
3465 
3466  auto it =
3467  nameToTableMap_.find(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
3468  if(it == nameToTableMap_.end())
3469  return contextMemberNames_;
3470 
3471  if(!it->second->isActive()) //if optional table is active, add it
3472  {
3473  contextMemberNames_.emplace(
3474  ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
3475  }
3476  return contextMemberNames_;
3477 } // end getContextMemberNames()
3478 
3479 //==============================================================================
3480 const std::set<std::string>& ConfigurationManager::getFixedContextMemberNames()
3481 {
3482  return ConfigurationManager::fixedContextMemberNames_;
3483 } // end getContextMemberNames()
3484 
3485 //==============================================================================
3486 const std::set<std::string>& ConfigurationManager::getBackboneMemberNames()
3487 {
3488  return ConfigurationManager::backboneMemberNames_;
3489 } // end getBackboneMemberNames()
3490 
3491 //==============================================================================
3492 const std::set<std::string>& ConfigurationManager::getIterateMemberNames()
3493 {
3494  return ConfigurationManager::iterateMemberNames_;
3495 } // end getIterateMemberNames()
3496 
3497 //==============================================================================
3498 const std::set<std::string>& ConfigurationManager::getConfigurationMemberNames(void)
3499 {
3500  configurationMemberNames_.clear();
3501 
3502  std::map<std::string, TableVersion> activeTables = getActiveVersions();
3503 
3504  for(auto& tablePair : activeTables)
3505  if(
3506  //check if not context table
3507  ConfigurationManager::fixedContextMemberNames_.find(tablePair.first) ==
3508  ConfigurationManager::fixedContextMemberNames_.end() &&
3509  tablePair.first != ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE &&
3510 
3511  //check if not backbone table
3512  ConfigurationManager::backboneMemberNames_.find(tablePair.first) ==
3513  ConfigurationManager::backboneMemberNames_.end() &&
3514 
3515  //check if not iterate table
3516  ConfigurationManager::iterateMemberNames_.find(tablePair.first) ==
3517  ConfigurationManager::iterateMemberNames_.end())
3518  {
3519  // else, it is a configuration table
3520  configurationMemberNames_.emplace(tablePair.first);
3521  }
3522 
3523  return configurationMemberNames_;
3524 } // end getConfigurationMemberNames()
3525 
3526 //==============================================================================
3527 void ConfigurationManager::initializeFromFhicl(const std::string& fhiclPath)
3528 {
3529  __GEN_COUT__ << "Initializing from fhicl: " << fhiclPath << __E__;
3530 
3531  // https://cdcvs.fnal.gov/redmine/projects/fhicl-cpp/wiki
3532 
3533  // LoadParameterSet() ... from $ARTDAQ_INC/artdaq/Application/LoadParameterSet.hh
3534  fhicl::ParameterSet pset = LoadParameterSet(fhiclPath);
3535 
3536  if(pset.get_names().size() == 0)
3537  {
3538  __GEN_SS__ << "Empty fcl configuration parameter set found! File: " << fhiclPath
3539  << __E__;
3540  __SS_THROW__;
3541  }
3542 
3543  //===========================
3544  // fcl should be FE record(s):
3545  // interface0: {
3546  // FEInterfacePluginName: "FEOtsUDPTemplateInterface"
3547  // LinkToFETypeTable_FEOtsUDPTemplateInterfaceTable: {
3548  // OtsInterface0: {
3549  // InterfaceIPAddress: "127.0.0.1"
3550  // InterfacePort: 4000
3551  // HostIPAddress: "127.0.0.1"
3552  // HostPort: 4020
3553  // StreamToIPAddress: "127.0.0.1"
3554  // StreamToPort: 4021
3555  // }
3556  // } //end FEOtsUDPTemplateInterfaceTable link record
3557  // } //end interface0
3558  //===========================
3559 
3560  // Steps:
3561  // Create one context with one FE supervisor
3562  // and one/many FEs specified by fcl
3563  //
3564 
3565  TableBase* table;
3566 
3567  // create context and add context record
3568  {
3569  table = 0;
3570  theInterface_->get(table, // configurationPtr
3571  ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME, // tableName
3572  0, // groupKey
3573  0, // groupName
3574  true // dontFill=false to fill
3575  );
3576 
3577  nameToTableMap_[ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME] = table;
3578 
3579  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
3580  table->setActiveView(TableVersion(TableVersion::DEFAULT));
3581 
3582  TableView* view = table->getViewP();
3583  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
3584  // view->print();
3585 
3586  // add context record ---------------------
3587  view->addRow();
3588  auto colMap = view->getColumnNamesMap();
3589 
3590  view->setValue("MacroMakerFEContext", 0, colMap["ContextUID"]);
3591  view->setValue("XDAQApplicationTable", 0, colMap["LinkToApplicationTable"]);
3592  view->setValue("MacroMakerFEContextApps", 0, colMap["LinkToApplicationGroupID"]);
3593  view->setValue("1", 0, colMap[TableViewColumnInfo::COL_NAME_STATUS]);
3594 
3595  __GEN_COUT__ << "Done adding context record..." << __E__;
3596  view->print();
3597 
3598  } // done with context record
3599 
3600  // create app table and add application record
3601  {
3602  table = 0;
3603  theInterface_->get(
3604  table, // configurationPtr
3605  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME, // tableName
3606  0, // groupKey
3607  0, // groupName
3608  true // dontFill=false to fill
3609  );
3610 
3611  nameToTableMap_[ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME] = table;
3612 
3613  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
3614  table->setActiveView(TableVersion(TableVersion::DEFAULT));
3615 
3616  TableView* view = table->getViewP();
3617  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
3618  // view->print();
3619 
3620  // add application record ---------------------
3621  view->addRow();
3622  auto colMap = view->getColumnNamesMap();
3623 
3624  view->setValue("MacroMakerFEContextApps", 0, colMap["ApplicationGroupID"]);
3625  view->setValue("MacroMakerFESupervisor", 0, colMap["ApplicationUID"]);
3626  view->setValue("FESupervisorTable", 0, colMap["LinkToSupervisorTable"]);
3627  view->setValue("MacroMakerFESupervisor", 0, colMap["LinkToSupervisorUID"]);
3628  view->setValue("1", 0, colMap[TableViewColumnInfo::COL_NAME_STATUS]);
3629  view->setValue(__ENV__("FE_SUPERVISOR_ID"), 0, colMap["Id"]); // XDAQ LID
3630 
3631  __GEN_COUT__ << "Done adding application record..." << __E__;
3632  view->print();
3633  } // done with app record
3634 
3635  // create FE Supervisor table and Supervisor record
3636  {
3637  table = 0;
3638  theInterface_->get(table, // configurationPtr
3639  "FESupervisorTable", // tableName
3640  0, // groupKey
3641  0, // groupName
3642  true // dontFill=false to fill
3643  );
3644 
3645  nameToTableMap_["FESupervisorTable"] = table;
3646 
3647  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
3648  table->setActiveView(TableVersion(TableVersion::DEFAULT));
3649 
3650  TableView* view = table->getViewP();
3651  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
3652  // view->print();
3653 
3654  // add application record ---------------------
3655  view->addRow();
3656  auto colMap = view->getColumnNamesMap();
3657 
3658  view->setValue("MacroMakerFESupervisor", 0, colMap["SupervisorUID"]);
3659  view->setValue("FEInterfaceTable", 0, colMap["LinkToFEInterfaceTable"]);
3660  view->setValue(
3661  "MacroMakerFESupervisorInterfaces", 0, colMap["LinkToFEInterfaceGroupID"]);
3662 
3663  __GEN_COUT__ << "Done adding supervisor record..." << __E__;
3664  view->print();
3665  } // done with app record
3666 
3667  // create FE Interface table and interface record(s)
3668  recursiveInitFromFhiclPSet("FEInterfaceTable" /*tableName*/,
3669  pset /*fhicl parameter set*/,
3670  "" /*uid*/,
3671  "MacroMakerFESupervisorInterfaces" /*groupID*/,
3672  "FE" /*childLinkIndex*/);
3673 
3674  // init every table after modifications
3675  for(auto& table : nameToTableMap_)
3676  {
3677  table.second->getViewP()->init();
3678  }
3679 
3680  // verify extraction
3681  if(0)
3682  {
3683  __GEN_COUT__ << "================================================" << __E__;
3684  nameToTableMap_["FESupervisorTable"]->getViewP()->print();
3685  nameToTableMap_["FEInterfaceTable"]->getViewP()->print();
3686 
3687  auto sups = getNode("FESupervisorTable").getChildrenNames();
3688  __GEN_COUT__ << "Supervisors extracted from fhicl: " << sups.size() << __E__;
3689  auto fes = getNode("FEInterfaceTable").getChildrenNames();
3690  __GEN_COUT__ << "Front-ends extracted from fhicl: " << fes.size() << __E__;
3691  {
3692  auto a = getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME);
3693  __GEN_COUTV__(a.getValueAsString());
3694 
3695  auto b = a.getNode("MacroMakerFEContext");
3696  __GEN_COUTV__(b.getValueAsString());
3697 
3698  auto c = b.getNode("LinkToApplicationTable");
3699  __GEN_COUTV__(c.getValueAsString());
3700 
3701  auto d = c.getNode("MacroMakerFESupervisor");
3702  __GEN_COUTV__(d.getValueAsString());
3703 
3704  auto e = d.getNode("LinkToSupervisorTable");
3705  __GEN_COUTV__(e.getValueAsString());
3706 
3707  auto f = e.getNode("LinkToFEInterfaceTable");
3708  __GEN_COUTV__(f.getValueAsString());
3709 
3710  auto z = f.getChildrenNames();
3711  __GEN_COUTV__(StringMacros::vectorToString(z));
3712  __GEN_COUTV__(z.size());
3713  auto y = f.getChildrenNames(false /*byPriority*/, true /*onlyStatusTrue*/);
3714  __GEN_COUTV__(StringMacros::vectorToString(y));
3715  __GEN_COUTV__(y.size());
3716  auto x = f.getChildrenNames(true /*byPriority*/, true /*onlyStatusTrue*/);
3717  __GEN_COUTV__(StringMacros::vectorToString(x));
3718  __GEN_COUTV__(x.size());
3719 
3720  auto g = f.getNode("dtc0");
3721  __GEN_COUTV__(g.getValueAsString());
3722  auto h = f.getNode("interface0");
3723  __GEN_COUTV__(h.getValueAsString());
3724 
3725  auto fes =
3726  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
3727  .getNode(
3728  "MacroMakerFEContext/LinkToApplicationTable/"
3729  "MacroMakerFESupervisor/LinkToSupervisorTable")
3730  .getNode("LinkToFEInterfaceTable")
3731  .getChildrenNames(true /*byPriority*/, true /*onlyStatusTrue*/);
3732  __GEN_COUTV__(fes.size());
3733  __GEN_COUTV__(StringMacros::vectorToString(fes));
3734  }
3735  }
3736 
3737 } // end initializeFromFhicl()
3738 
3739 //==============================================================================
3744 void ConfigurationManager::recursiveInitFromFhiclPSet(const std::string& tableName,
3745  const fhicl::ParameterSet& pset,
3746  const std::string& recordName,
3747  const std::string& groupName,
3748  const std::string& groupLinkIndex)
3749 {
3750  __GEN_COUT__ << __COUT_HDR_P__ << "Adding table '" << tableName << "' record(s)..."
3751  << __E__;
3752 
3753  TableBase* table;
3754  // create context and add context record
3755  {
3756  table = 0;
3757  if(nameToTableMap_.find(tableName) == nameToTableMap_.end())
3758  {
3759  __GEN_COUT__ << "Table not found, so making '" << tableName << "' instance..."
3760  << __E__;
3761  theInterface_->get(table, // configurationPtr
3762  tableName, // tableName
3763  0, // groupKey
3764  0, // groupName
3765  true // dontFill=false to fill
3766  );
3767 
3768  nameToTableMap_[tableName] = table;
3769  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
3770  }
3771  else
3772  {
3773  __GEN_COUT__ << "Existing table found, so using '" << tableName
3774  << "'instance..." << __E__;
3775  table = nameToTableMap_[tableName];
3776  }
3777 
3778  table->setActiveView(TableVersion(TableVersion::DEFAULT));
3779 
3780  TableView* view = table->getViewP();
3781  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
3782  // view->print();
3783 
3784  if(recordName != "") // then add this record
3785  {
3786  // Steps:
3787  // - add row
3788  // - set UID and enable (if possible)
3789  // - set values for parameter columns
3790  // - define links
3791 
3792  __GEN_COUTV__(recordName);
3793 
3794  // add row and get column map
3795  unsigned int r = view->addRow();
3796  auto colMap = view->getColumnNamesMap();
3797 
3798  // set UID and enable (if possible)
3799  view->setValue(recordName, r, view->getColUID());
3800  try
3801  {
3802  view->setValue("1", r, view->getColStatus());
3803  }
3804  catch(...)
3805  {
3806  __GEN_COUT__ << "No status column to set for '" << recordName << "'"
3807  << __E__;
3808  }
3809 
3810  if(groupName != "") // then set groupID for this record
3811  {
3812  __GEN_COUT__ << "Setting group ID for group link index '"
3813  << groupLinkIndex << "'" << __E__;
3814 
3815  int groupIDCol = view->getLinkGroupIDColumn(groupLinkIndex);
3816  __GEN_COUT__ << "Setting group ID for group link index '"
3817  << groupLinkIndex << "' at column " << groupIDCol << " to '"
3818  << groupName << ".'" << __E__;
3819 
3820  view->setValue(groupName, r, groupIDCol);
3821  }
3822 
3823  // then set parameters
3824  auto names = pset.get_names();
3825  for(const auto& colName : names)
3826  {
3827  if(!pset.is_key_to_atom(colName))
3828  continue;
3829 
3830  auto colIt = colMap.find(colName);
3831  if(colIt == colMap.end())
3832  {
3833  __SS__ << "Field '" << colName << "' of record '" << recordName
3834  << "' in table '" << tableName << "' was not found in columns."
3835  << "\n\nHere are the existing column names:\n";
3836  unsigned int i = 0;
3837  for(const auto& col : colMap)
3838  ss << "\n" << ++i << ".\t" << col.first;
3839  ss << __E__;
3840  __SS_THROW__;
3841  }
3842  // skip overwriting group ID - already setup by parent group link
3843  if(view->getColumnInfo(colIt->second).isGroupID())
3844  continue;
3845 
3846  const std::string value = pset.get<std::string>(colName);
3847  __GEN_COUT__ << "Setting '" << recordName << "' parameter at column "
3848  << colIt->second << ", '" << colName << "'\t = " << value
3849  << __E__;
3850  view->setValueAsString(value, r, colIt->second);
3851  } // end set parameters
3852 
3853  // then define links
3854  for(const auto& linkName : names)
3855  {
3856  if(pset.is_key_to_atom(linkName))
3857  continue;
3858 
3859  __GEN_COUTV__(linkName);
3860 
3861  // split into column name and table
3862  unsigned int c = linkName.size() - 1;
3863  for(; c >= 1; --c)
3864  if(linkName[c] == '_') // find first underscore to split linkName
3865  break;
3866 
3867  if(c == 0)
3868  {
3869  __SS__ << "Illegal link name '" << linkName
3870  << "' found. The format must be <Column name>_<Target table "
3871  "name>,.. for example '"
3872  << "LinkToFETypeTable_FEOtsUDPTemplateInterfaceTable'"
3873  << __E__;
3874  __SS_THROW__;
3875  }
3876  std::string colName = linkName.substr(0, c);
3877  __GEN_COUTV__(colName);
3878 
3879  auto colIt = colMap.find(colName);
3880  if(colIt == colMap.end())
3881  {
3882  __SS__ << "Link '" << colName << "' of record '" << recordName
3883  << "' in table '" << tableName << "' was not found in columns."
3884  << "\n\nHere are the existing column names:\n";
3885  unsigned int i = 0;
3886  for(const auto& col : colMap)
3887  ss << "\n" << i << ".\t" << col.first << __E__;
3888  __SS_THROW__;
3889  }
3890  //__GEN_COUT__ << "Setting link at column " << colIt->second << __E__;
3891 
3892  std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>
3893  linkPair;
3894  bool isGroupLink;
3895  view->getChildLink(colIt->second, isGroupLink, linkPair);
3896 
3897  //__GEN_COUTV__(isGroupLink);
3898  //__GEN_COUTV__(linkPair.first);
3899  //__GEN_COUTV__(linkPair.second);
3900 
3901  std::string linkTableName = linkName.substr(c + 1);
3902  __GEN_COUTV__(linkTableName);
3903 
3904  auto linkPset = pset.get<fhicl::ParameterSet>(linkName);
3905  auto linkRecords = linkPset.get_pset_names();
3906  if(!isGroupLink && linkRecords.size() > 1)
3907  {
3908  __SS__ << "A Unique Link can only point to one record. "
3909  << "The specified link '" << colName << "' of record '"
3910  << recordName << "' in table '" << tableName << "' has "
3911  << linkRecords.size() << " children records specified. "
3912  << __E__;
3913  __SS_THROW__;
3914  }
3915 
3916  if(linkRecords.size() == 0)
3917  {
3918  __GEN_COUT__ << "No child records, so leaving link disconnected."
3919  << __E__;
3920  continue;
3921  }
3922 
3923  __GEN_COUT__ << "Setting Link at columns [" << linkPair.first << ","
3924  << linkPair.second << "]" << __E__;
3925  view->setValue(linkTableName, r, linkPair.first);
3926 
3927  if(!isGroupLink)
3928  {
3929  __GEN_COUT__ << "Setting up Unique link to " << linkRecords[0]
3930  << __E__;
3931 
3932  view->setValue(linkRecords[0], r, linkPair.second);
3933 
3934  recursiveInitFromFhiclPSet(
3935  linkTableName /*tableName*/,
3936  linkPset.get<fhicl::ParameterSet>(
3937  linkRecords[0]) /*fhicl parameter set*/,
3938  linkRecords[0] /*uid*/,
3939  "" /*groupID*/);
3940  }
3941  else
3942  {
3943  std::string childLinkIndex =
3944  view->getColumnInfo(linkPair.first).getChildLinkIndex();
3945  std::string groupName = recordName + "Group";
3946 
3947  view->setValue(groupName, r, linkPair.second);
3948 
3949  for(const auto& groupRecord : linkRecords)
3950  {
3951  __GEN_COUT__ << "Setting '" << childLinkIndex
3952  << "' Group link to '" << groupName << "' record '"
3953  << groupRecord << "'" << __E__;
3954 
3955  recursiveInitFromFhiclPSet(
3956  linkTableName /*tableName*/,
3957  linkPset.get<fhicl::ParameterSet>(
3958  groupRecord) /*fhicl parameter set*/,
3959  groupRecord /*uid*/,
3960  groupName /*groupID*/,
3961  childLinkIndex /*groupLinkIndex*/);
3962  }
3963  }
3964 
3965  } // end link handling
3966  }
3967  else if(groupName != "") // then add group of records
3968  {
3969  // get_pset_names();
3970  // get_names
3971  __GEN_COUTV__(groupName);
3972  auto psets = pset.get_pset_names();
3973  for(const auto& ps : psets)
3974  {
3975  __GEN_COUTV__(ps);
3976  recursiveInitFromFhiclPSet(
3977  tableName /*tableName*/,
3978  pset.get<fhicl::ParameterSet>(ps) /*fhicl parameter set*/,
3979  ps /*uid*/,
3980  groupName /*groupID*/,
3981  groupLinkIndex /*groupLinkIndex*/);
3982  }
3983  }
3984  else
3985  {
3986  __SS__ << "Illegal recursive parameters!" << __E__;
3987  __SS_THROW__;
3988  }
3989  __GEN_COUT__ << __COUT_HDR_P__ << "Done adding table '" << tableName
3990  << "' record(s)..." << __E__;
3991  view->print();
3992  }
3993 
3994 } // end recursiveInitFromFhiclPSet()
3995 
3996 //==============================================================================
3997 bool ConfigurationManager::isOwnerFirstAppInContext()
3998 {
3999  //__GEN_COUT__ << "Checking if owner is first App in Context." << __E__;
4000  if(ownerContextUID_ == "" || ownerAppUID_ == "")
4001  return true; // default to 'yes'
4002 
4003  //__GEN_COUTV__(ownerContextUID_);
4004  //__GEN_COUTV__(ownerAppUID_);
4005 
4006  try
4007  {
4008  auto contextChildren = getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME +
4009  "/" + ownerContextUID_)
4010  .getChildrenNames();
4011 
4012  bool isFirstAppInContext =
4013  contextChildren.size() == 0 || contextChildren[0] == ownerAppUID_;
4014 
4015  //__GEN_COUTV__(isFirstAppInContext);
4016 
4017  return isFirstAppInContext;
4018  }
4019  catch(...)
4020  {
4021  return true; // default to 'yes' if XDAQ Context doesn't exist
4022  }
4023 } // end isOwnerFirstAppInContext()
4024 
4025 //==============================================================================
4026 void ConfigurationManager::getOtherSubsystemInstanceInfo(
4027  const std::string& otherSubsystemUID,
4028  std::string* userDataPathPtr /* = nullptr */,
4029  std::string* hostnamePtr /* = nullptr */,
4030  std::string* usernamePtr /* = nullptr */,
4031  std::string* fullNamePtr /* = nullptr */)
4032 {
4033  __GEN_COUTTV__(otherSubsystemUID);
4034 
4035  ConfigurationTree node =
4036  getNode(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE)
4037  .getNode(otherSubsystemUID);
4038  std::string userPath = node.getNode("SubsystemUserDataPath").getValue();
4039  if(fullNamePtr)
4040  *fullNamePtr = node.getNode("SubsystemFullName").getValue();
4041 
4042  auto splitPath = StringMacros::getVectorFromString(userPath, {':'});
4043  __GEN_COUTTV__(StringMacros::vectorToString(splitPath));
4044 
4045  if(!splitPath.size() || splitPath.size() > 2)
4046  {
4047  __GEN_SS__ << "Illegal user data path specified for subsystem '"
4048  << otherSubsystemUID << "': " << userPath << __E__;
4049  __SS_ONLY_THROW__;
4050  }
4051  std::string userDataPath = splitPath[splitPath.size() - 1];
4052 
4053  //since we are running exec, cleanse the filename path for alphanumeric,_,-,/ only
4054  for(unsigned int i = 0; i < userDataPath.length(); ++i)
4055  if(!((userDataPath[i] >= 'a' && userDataPath[i] <= 'z') ||
4056  (userDataPath[i] >= 'A' && userDataPath[i] <= 'Z') ||
4057  (userDataPath[i] >= '0' && userDataPath[i] <= '9') ||
4058  userDataPath[i] == '-' || userDataPath[i] == '_' || userDataPath[i] == '/'))
4059  {
4060  __GEN_SS__ << "Illegal user data path specified (no special characters "
4061  "allowed) for subsystem '"
4062  << otherSubsystemUID << "': " << userPath << __E__;
4063  __SS_ONLY_THROW__;
4064  } // end filename cleanse
4065 
4066  if(userDataPathPtr)
4067  *userDataPathPtr = userDataPath;
4068 
4069  std::string username, hostname;
4070  if(splitPath.size() == 2) //then need to scp the file
4071  {
4072  //since we are running exec, cleanse the username@host path for alphanumeric,_,-,/ only
4073  std::vector<std::string> userHostSplit =
4074  StringMacros::getVectorFromString(splitPath[0], {'@'});
4075  __GEN_COUTTV__(userHostSplit.size());
4076  if(userHostSplit.size() == 1)
4077  hostname = userHostSplit[0];
4078  else if(userHostSplit.size() == 2)
4079  {
4080  username = userHostSplit[0];
4081  hostname = userHostSplit[1];
4082  }
4083  else
4084  {
4085  __GEN_SS__ << "Illegal remote username/host specified for subsystem '"
4086  << otherSubsystemUID << "': " << userPath << __E__;
4087  __SS_ONLY_THROW__;
4088  }
4089 
4090  for(unsigned int i = 0; userHostSplit.size() == 2 && i < username.length(); ++i)
4091  if(!((username[i] >= 'a' && username[i] <= 'z') ||
4092  (username[i] >= 'A' && username[i] <= 'Z') ||
4093  (username[i] >= '0' && username[i] <= '9') || username[i] == '-' ||
4094  username[i] == '_'))
4095  {
4096  __GEN_SS__ << "Illegal remote username specified for subsystem '"
4097  << otherSubsystemUID << "': " << userPath << __E__;
4098  __SS_ONLY_THROW__;
4099  }
4100  unsigned int ii = 0; //track last . to prevent weird . usage
4101  for(unsigned int i = 0; i < hostname.length(); ++i)
4102  if(!((hostname[i] >= 'a' && hostname[i] <= 'z') ||
4103  (hostname[i] >= 'A' && hostname[i] <= 'Z') ||
4104  (hostname[i] >= '0' && hostname[i] <= '9') || hostname[i] == '-' ||
4105  hostname[i] == '_'))
4106  {
4107  if(hostname[i] == '.' && i > ii + 1)
4108  {
4109  //its ok to have this . so track position
4110  ii = i;
4111  }
4112  else //else not ok to have .. or other characters
4113  {
4114  __GEN_SS__ << "Illegal remote hostname '" << hostname
4115  << "' specified for subsystem '" << otherSubsystemUID
4116  << "': " << userPath << __E__;
4117  __SS_ONLY_THROW__;
4118  }
4119  }
4120  }
4121  else if(splitPath.size() == 1) //then can just directly access the file
4122  {
4123  __GEN_COUT__ << "Local user date path identified." << __E__;
4124  }
4125  else
4126  {
4127  __GEN_SS__ << "Illegal user data path specified for subsystem '"
4128  << otherSubsystemUID << "': " << userPath << __E__;
4129  __SS_ONLY_THROW__;
4130  }
4131 
4132  if(hostnamePtr)
4133  *hostnamePtr = hostname;
4134  if(usernamePtr)
4135  *usernamePtr = username;
4136 
4137 } // end getOtherSubsystemInstanceInfo()
4138 
4139 //==============================================================================
4140 std::map<std::string /*groupType*/, std::pair<std::string /*groupName*/, TableGroupKey>>
4141 ConfigurationManager::getOtherSubsystemActiveTableGroups(
4142  const std::string& otherSubsystemUID,
4143  std::string* userDataPathPtr /* = nullptr */,
4144  std::string* hostnamePtr /* = nullptr */,
4145  std::string* usernamePtr /* = nullptr */)
4146 {
4147  std::map<std::string /*groupType*/,
4148  std::pair<std::string /*groupName*/, TableGroupKey>>
4149  retMap;
4150 
4151  __GEN_COUTTV__(otherSubsystemUID);
4152 
4153  std::string userDataPath;
4154  std::string username, hostname;
4155 
4156  getOtherSubsystemInstanceInfo(otherSubsystemUID, &userDataPath, &hostname, &username);
4157 
4158  __GEN_COUTTV__(userDataPath);
4159  __GEN_COUTTV__(username);
4160  __GEN_COUTTV__(hostname);
4161 
4162  if(userDataPathPtr)
4163  *userDataPathPtr = userDataPath;
4164  if(hostnamePtr)
4165  *hostnamePtr = hostname;
4166  if(usernamePtr)
4167  *usernamePtr = username;
4168 
4169  //enforce filename ends correctly
4170  std::string filename = userDataPath + "/ServiceData/ActiveTableGroups.cfg";
4171 
4172  std::string cmdResult;
4173 
4174  if(hostname != "")
4175  {
4176  std::string tmpSubsystemFilename =
4177  ConfigurationManager::ACTIVE_GROUPS_FILENAME + "." + otherSubsystemUID;
4178  __GEN_COUTTV__(tmpSubsystemFilename);
4179  if(username != "") //has username
4180  {
4181  cmdResult = StringMacros::exec(
4182  ("rm " + tmpSubsystemFilename + " 2>/dev/null; scp " + username + "@" +
4183  hostname + ":" + filename + " " + tmpSubsystemFilename + " 2>&1; cat " +
4184  tmpSubsystemFilename + " 2>&1")
4185  .c_str());
4186  }
4187  else
4188  cmdResult = StringMacros::exec(
4189  ("rm " + tmpSubsystemFilename + " 2>/dev/null; scp " + hostname + ":" +
4190  filename + " " + tmpSubsystemFilename + " 2>&1; cat " +
4191  tmpSubsystemFilename + " 2>&1")
4192  .c_str());
4193  }
4194  else //then can just directly access the file
4195  {
4196  __GEN_COUT__ << "Local user date path identified." << __E__;
4197  cmdResult = StringMacros::exec(("cat " + filename + " 2>&1").c_str());
4198  }
4199 
4200  __GEN_COUTTV__(cmdResult);
4201  if(cmdResult.find("Permission denied") != std::string::npos)
4202  {
4203  __GEN_SS__
4204  << "Permission denied accessing user data path specified for subsystem '"
4205  << otherSubsystemUID << "': ";
4206  if(username != "")
4207  ss << username << "@";
4208  if(hostname != "")
4209  ss << hostname << ":";
4210  ss << userDataPath << __E__;
4211  __SS_ONLY_THROW__;
4212  }
4213 
4214  auto subsystemActiveGroupMap = StringMacros::getVectorFromString(
4215  cmdResult, {'\n'} /* delimieter*/, {' ', '\t'} /* whitespace*/);
4216  __GEN_COUTTV__(StringMacros::vectorToString(subsystemActiveGroupMap));
4217  __GEN_COUTTV__(subsystemActiveGroupMap.size());
4218 
4219  std::string //groupComment, groupAuthor, groupCreationTime,
4220  groupType;
4221  for(unsigned int i = 0; i + 1 < subsystemActiveGroupMap.size(); i += 2)
4222  {
4223  if(subsystemActiveGroupMap[i] == "" || subsystemActiveGroupMap[i + 1] == "-1")
4224  continue;
4225 
4226  __GEN_COUTT__ << "Loading type of subsystem '" << otherSubsystemUID << "' group "
4227  << subsystemActiveGroupMap[i] << "("
4228  << subsystemActiveGroupMap[i + 1] << ")" << __E__;
4229 
4230  try
4231  {
4232  loadTableGroup(subsystemActiveGroupMap[i] /*groupName*/,
4233  TableGroupKey(subsystemActiveGroupMap[i + 1]),
4234  false /*doActivate*/,
4235  0 /*groupMembers*/,
4236  0 /*progressBar*/,
4237  0 /*accumulateErrors*/,
4238  0, // &groupComment,
4239  0, //&groupAuthor,
4240  0, //&groupCreationTime,
4241  true /*doNotLoadMember*/,
4242  &groupType);
4243  }
4244  catch(const std::runtime_error& e)
4245  {
4246  __GEN_COUT__ << "Ignoring error loading subsystem '" << otherSubsystemUID
4247  << "' group " << subsystemActiveGroupMap[i] << "("
4248  << subsystemActiveGroupMap[i + 1] << "): " << __E__ << e.what()
4249  << __E__;
4250  groupType = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
4251  }
4252  retMap[groupType] = std::make_pair(subsystemActiveGroupMap[i],
4253  TableGroupKey(subsystemActiveGroupMap[i + 1]));
4254  }
4255 
4256  __GEN_COUTTV__(StringMacros::mapToString(retMap));
4257  return retMap;
4258 } //end getOtherSubsystemActiveTableGroups()
4259 
4260 //==============================================================================
4262 std::set<std::string /* configAlias */>
4263 ConfigurationManager::getOtherSubsystemConfigAliases(const std::string& otherSubsystemUID)
4264 {
4265  std::set<std::string> retSet;
4266 
4267  std::map<std::string /*groupType*/,
4268  std::pair<std::string /*groupName*/, TableGroupKey>>
4269  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
4270 
4271  //load backbone
4272  auto it = retMap.find(
4273  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
4274  if(it == retMap.end())
4275  {
4276  __GEN_SS__
4277  << "No active Backbone group found in the active groups of remote subsystem '"
4278  << otherSubsystemUID << "!'" << __E__;
4279  __GEN_SS_THROW__;
4280  }
4281  auto it2 = retMap.find(
4282  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
4283  if(it2 == retMap.end())
4284  {
4285  __GEN_SS__
4286  << "No active Context group found in the active groups of remote subsystem '"
4287  << otherSubsystemUID << "!'" << __E__;
4288  __GEN_SS_THROW__;
4289  }
4290 
4291  std::string accumulatedWarnings;
4292 
4293  // be careful to not activate! which calls init() and then generates output files to disk
4294  // and changes the system active group; instead only setActiveView
4295  loadTableGroup(it->second.first,
4296  it->second.second,
4297  false /*doActivate*/,
4298  0 /*groupMembers*/,
4299  0 /*progressBar*/,
4300  &accumulatedWarnings /*accumulateWarnings = 0*/
4301  );
4302  __GEN_COUTTV__(accumulatedWarnings);
4303 
4304  //get aliases (a la ConfigurationManager::getActiveGroupAliases:2888)
4305  std::vector<std::pair<std::string, ConfigurationTree>> entries =
4306  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
4307 
4308  for(auto& entry : entries)
4309  {
4310  if(entry.first.find("Context") == std::string::npos &&
4311  entry.first.find("Iterat") == std::string::npos)
4312  retSet.emplace(entry.first);
4313  }
4314  return retSet;
4315 } //end getOtherSubsystemActiveTableGroups()
4316 
4317 //==============================================================================
4319 std::set<std::string /* configAlias */>
4321  const std::string& otherSubsystemUID, const std::string& otherSubsystemFsmName)
4322 {
4323  std::set<std::string> retSet;
4324 
4325  std::map<std::string /*groupType*/,
4326  std::pair<std::string /*groupName*/, TableGroupKey>>
4327  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
4328 
4329  //load backbone
4330  auto it = retMap.find(
4331  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
4332  if(it == retMap.end())
4333  {
4334  __GEN_SS__
4335  << "No active Backbone group found in the active groups of remote subsystem '"
4336  << otherSubsystemUID << "!'" << __E__;
4337  __GEN_SS_THROW__;
4338  }
4339  auto it2 = retMap.find(
4340  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
4341  if(it2 == retMap.end())
4342  {
4343  __GEN_SS__
4344  << "No active Context group found in the active groups of remote subsystem '"
4345  << otherSubsystemUID << "!'" << __E__;
4346  __GEN_SS_THROW__;
4347  }
4348 
4349  std::string accumulatedWarnings;
4350 
4351  // be careful to not activate! which calls init() and then generates output files to disk
4352  // and changes the system active group; instead only setActiveView
4353  loadTableGroup(it->second.first,
4354  it->second.second,
4355  false /*doActivate*/,
4356  0 /*groupMembers*/,
4357  0 /*progressBar*/,
4358  &accumulatedWarnings /*accumulateWarnings = 0*/
4359  );
4360  loadTableGroup(it2->second.first,
4361  it2->second.second,
4362  false /*doActivate*/,
4363  0 /*groupMembers*/,
4364  0 /*progressBar*/,
4365  &accumulatedWarnings /*accumulateWarnings = 0*/
4366  );
4367  __GEN_COUTTV__(accumulatedWarnings);
4368 
4369  //get aliases (a la ConfigurationManager::getActiveGroupAliases:2888)
4370  std::vector<std::pair<std::string, ConfigurationTree>> entries =
4371  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
4372 
4373  //apply filter (a la GatewaySupervisor::addFilteredConfigAliasesToXML:5357)
4374 
4375  std::string stateMachineAliasFilter = "*"; // default to all
4376  try // if cant find alias, default to all
4377  {
4378  ConfigurationTree otherGatewayNode = getGatewaySupervisorNode();
4379  ConfigurationTree fsmFilterNode =
4380  otherGatewayNode.getNode("LinkToStateMachineTable")
4381  .getNode(otherSubsystemFsmName + "/SystemAliasFilter");
4382  if(!fsmFilterNode.isDefaultValue())
4383  stateMachineAliasFilter = fsmFilterNode.getValue<std::string>();
4384  else
4385  __GEN_COUT_INFO__ << "FSM has no SystemAliasFilter value." << __E__;
4386  }
4387  catch(std::runtime_error& e)
4388  {
4389  __COUT__ << "Ignoring unsetup SystemAliasFilter value: " << e.what() << __E__;
4390  }
4391  catch(...)
4392  {
4393  __COUT__ << "Ignoring unsetup SystemAliasFilter value." << __E__;
4394  }
4395 
4396  __COUT__ << "Applying alias filter for other user_data path FSM '"
4397  << otherSubsystemFsmName
4398  << "' and stateMachineAliasFilter = " << stateMachineAliasFilter << __E__;
4399 
4400  // filter list of aliases based on stateMachineAliasFilter
4401  // ! as first character means choose those that do NOT match filter
4402  // * can be used as wild card.
4403  {
4404  bool invertFilter =
4405  stateMachineAliasFilter.size() && stateMachineAliasFilter[0] == '!';
4406  std::vector<std::string> filterArr;
4407 
4408  size_t i = 0;
4409  if(invertFilter)
4410  ++i;
4411  size_t f;
4412  std::string tmp;
4413  while((f = stateMachineAliasFilter.find('*', i)) != std::string::npos)
4414  {
4415  tmp = stateMachineAliasFilter.substr(i, f - i);
4416  i = f + 1;
4417  filterArr.push_back(tmp);
4418  __COUTS__(20) << filterArr[filterArr.size() - 1] << " " << i << " of "
4419  << stateMachineAliasFilter.size() << __E__;
4420  }
4421  if(i <= stateMachineAliasFilter.size())
4422  {
4423  tmp = stateMachineAliasFilter.substr(i);
4424  filterArr.push_back(tmp);
4425  __COUTS__(20) << filterArr[filterArr.size() - 1] << " last." << __E__;
4426  }
4427 
4428  bool filterMatch;
4429 
4430  for(auto& aliasMapPair : entries)
4431  {
4432  __COUTS__(20) << "aliasMapPair.first: " << aliasMapPair.first << __E__;
4433 
4434  filterMatch = true;
4435 
4436  if(filterArr.size() == 1)
4437  {
4438  if(filterArr[0] != "" && filterArr[0] != "*" &&
4439  aliasMapPair.first != filterArr[0])
4440  filterMatch = false;
4441  }
4442  else
4443  {
4444  i = -1;
4445  for(f = 0; f < filterArr.size(); ++f)
4446  {
4447  if(!filterArr[f].size())
4448  continue; // skip empty filters
4449 
4450  if(f == 0) // must start with this filter
4451  {
4452  if((i = aliasMapPair.first.find(filterArr[f])) != 0)
4453  {
4454  filterMatch = false;
4455  break;
4456  }
4457  }
4458  else if(f == filterArr.size() - 1) // must end with this filter
4459  {
4460  if(aliasMapPair.first.rfind(filterArr[f]) !=
4461  aliasMapPair.first.size() - filterArr[f].size())
4462  {
4463  filterMatch = false;
4464  break;
4465  }
4466  }
4467  else if((i = aliasMapPair.first.find(filterArr[f])) ==
4468  std::string::npos)
4469  {
4470  filterMatch = false;
4471  break;
4472  }
4473  }
4474  }
4475 
4476  if(invertFilter)
4477  filterMatch = !filterMatch;
4478 
4479  __COUTS__(20) << "filterMatch=" << filterMatch << __E__;
4480 
4481  if(!filterMatch)
4482  continue;
4483 
4484  retSet.emplace(aliasMapPair.first);
4485 
4486  //If need more alias details, see ConfigurationGUISupervisor::handleGroupAliasesXML
4487  }
4488  }
4489 
4490  return retSet;
4491 } //end getOtherSubsystemFilteredConfigAliases()
4492 
4493 //==============================================================================
4496  const std::string& otherSubsystemUID,
4497  const std::string& configAlias,
4498  std::pair<std::string, TableGroupKey>& groupTranslation,
4499  std::string& groupComment,
4500  std::string& groupAuthor,
4501  std::string& groupCreationTime)
4502 {
4503  __GEN_COUTV__(otherSubsystemUID);
4504 
4505  std::map<std::string /*groupType*/,
4506  std::pair<std::string /*groupName*/, TableGroupKey>>
4507  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
4508 
4509  //load backbone
4510  auto it = retMap.find(
4511  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
4512  if(it == retMap.end())
4513  {
4514  __GEN_SS__
4515  << "No active Backbone group found in the active groups of remote subsystem '"
4516  << otherSubsystemUID << "!'" << __E__;
4517  __GEN_SS_THROW__;
4518  }
4519  auto it2 = retMap.find(
4520  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
4521  if(it2 == retMap.end())
4522  {
4523  __GEN_SS__
4524  << "No active Context group found in the active groups of remote subsystem '"
4525  << otherSubsystemUID << "!'" << __E__;
4526  __GEN_SS_THROW__;
4527  }
4528 
4529  std::string accumulatedWarnings;
4530 
4531  // be careful to not activate! which calls init() and then generates output files to disk
4532  // and changes the system active group; instead only setActiveView
4533  loadTableGroup(it->second.first,
4534  it->second.second,
4535  false /*doActivate*/,
4536  0 /*groupMembers*/,
4537  0 /*progressBar*/,
4538  &accumulatedWarnings /*accumulateWarnings = 0*/
4539  );
4540  __GEN_COUTTV__(accumulatedWarnings);
4541 
4542  // (a la ConfigurationManager::getTableGroupFromAlias)
4543  try
4544  {
4545  // find runType in Group Aliases table
4546  ConfigurationTree entry =
4547  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getNode(configAlias);
4548 
4549  groupTranslation = std::pair<std::string, TableGroupKey>(
4550  entry.getNode("GroupName").getValueAsString(),
4551  TableGroupKey(entry.getNode("GroupKey").getValueAsString()));
4552  __COUT__ << "Found " << configAlias << " translates to " << groupTranslation.first
4553  << "(" << groupTranslation.second << ")" << __E__;
4554 
4555  //get comment, author, creationTime
4556  try
4557  {
4558  loadTableGroup(groupTranslation.first,
4559  groupTranslation.second,
4560  false /*doActivate*/,
4561  0 /*groupMembers*/,
4562  0 /*progressBar*/,
4563  &accumulatedWarnings,
4564  &groupComment,
4565  &groupAuthor,
4566  &groupCreationTime,
4567  true /*doNotLoadMembers*/);
4568  }
4569  catch(...)
4570  {
4571  __COUT_WARN__ << "Failed to load group metadata." << __E__;
4572  }
4573  __COUT__ << "Found " << configAlias << " author: " << groupAuthor
4574  << ", createTime: " << groupCreationTime << ", comment: " << groupComment
4575  << __E__;
4576  }
4577  catch(...)
4578  {
4579  __GEN_SS__ << "Did not find the Configuration Alias '" << configAlias
4580  << "' in the active Backbone group of remote subsystem '"
4581  << otherSubsystemUID << "!'" << __E__;
4582  __GEN_SS_THROW__;
4583  }
4584 
4585 } //end getOtherSubsystemConfigAliasInfo()
4586 
4587 //==============================================================================
4589 TableBase* ConfigurationManager::getDesktopIconTable(void)
4590 {
4591  if(nameToTableMap_.find(DESKTOP_ICON_TABLE_NAME) == nameToTableMap_.end())
4592  {
4593  __SS__ << "Desktop icon table not found!" << __E__;
4594  ss << StringMacros::stackTrace() << __E__;
4595  __SS_THROW__;
4596  }
4597 
4598  return nameToTableMap_.at(DESKTOP_ICON_TABLE_NAME);
4599 } // end dynamicDesktopIconChange()
4600 
4601 //==============================================================================
4602 void ConfigurationManager::saveGroupNameAndKey(
4603  const std::pair<std::string /*group name*/, TableGroupKey>& theGroup,
4604  const std::string& fileName,
4605  bool appendMode /* = false */)
4606 {
4607  std::string fullPath =
4608  ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/" + fileName;
4609 
4610  std::ofstream groupFile;
4611  if(appendMode)
4612  groupFile.open(fullPath.c_str(), std::ios::app);
4613  else
4614  groupFile.open(fullPath.c_str());
4615  if(!groupFile.is_open())
4616  {
4617  __SS__ << "Error. Can't open file to save group activity: " << fullPath << __E__;
4618  __SS_THROW__;
4619  }
4620  std::stringstream outss;
4621  outss << theGroup.first << "\n" << theGroup.second << "\n" << time(0);
4622  groupFile << outss.str().c_str();
4623  groupFile.close();
4624 } // end saveGroupNameAndKey()
4625 
4626 //==============================================================================
4632 std::pair<std::string /*group name*/, TableGroupKey>
4633 ConfigurationManager::loadGroupNameAndKey(const std::string& fileName,
4634  std::string& returnedTimeString)
4635 {
4636  std::string fullPath =
4637  ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/" + fileName;
4638 
4639  FILE* groupFile = fopen(fullPath.c_str(), "r");
4640  if(!groupFile)
4641  {
4642  __COUT__ << "Can't open file: " << fullPath << __E__;
4643 
4644  __COUT__ << "Returning empty groupName and key -1" << __E__;
4645 
4646  return std::pair<std::string /*group name*/, TableGroupKey>("", TableGroupKey());
4647  }
4648 
4649  char line[500]; // assuming no group names longer than 500 chars
4650  // name and then key
4651  std::pair<std::string /*group name*/, TableGroupKey> theGroup;
4652 
4653  fgets(line, 500, groupFile); // name
4654  if(strlen(line) && line[strlen(line) - 1] == '\n')
4655  line[strlen(line) - 1] = '\0'; // remove trailing newline
4656  theGroup.first = line;
4657 
4658  fgets(line, 500, groupFile); // key
4659  int key;
4660  sscanf(line, "%d", &key);
4661  theGroup.second = key;
4662 
4663  fgets(line, 500, groupFile); // time
4664  time_t timestamp;
4665  sscanf(line, "%ld", &timestamp); // type long int
4666  // struct tm tmstruct;
4667  // ::localtime_r(&timestamp, &tmstruct);
4668  // ::strftime(line, 30, "%c %Z", &tmstruct);
4669  returnedTimeString = StringMacros::getTimestampString(timestamp); // line;
4670  fclose(groupFile);
4671 
4672  __COUT__ << "theGroup.first=" << theGroup.first
4673  << " theGroup.second=" << theGroup.second << __E__;
4674 
4675  return theGroup;
4676 } // end loadGroupNameAndKey()
virtual std::map< std::string, TableVersion > getTableGroupMembers(std::string const &, bool=false) const
std::map< std::string, std::map< std::string, TableVersion > > getVersionAliases(void) const
static const unsigned int PROCESSOR_COUNT
Static members.
static const std::string & convertGroupTypeToName(const ConfigurationManager::GroupType &groupTypeId)
void restoreActiveTableGroups(bool throwErrors=false, const std::string &pathToActiveGroupsFile="", ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, std::string *accumulatedWarnings=0)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveTableGroups(void) const
std::set< std::string > getOtherSubsystemConfigAliases(const std::string &otherSubsystemUID)
Ignore any System Aliases with "Context" or "Iterat" in the name.
void loadMemberMap(const std::map< std::string, TableVersion > &memberMap, std::string *accumulateWarnings=0)
void dumpActiveConfiguration(const std::string &filePath, const std::string &dumpType, const std::string &configurationAlias, const std::string &logEntry, const std::string &activeUsers, std::ostream &altOut=std::cout)
std::map< std::string, TableVersion > getActiveVersions(void) const
getActiveVersions
ConfigurationManager(bool initForWriteAccess=false, bool initializeFromFhicl=false)
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType groupTypeToLoad=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false)
std::shared_ptr< TableGroupKey > makeTheTableGroupKey(TableGroupKey key)
Setters/Modifiers.
void copyTableGroupFromCache(const ConfigurationManager &cacheConfigMgr, const std::map< std::string, TableVersion > &groupMembers, const std::string &configGroupName="", const TableGroupKey &tableGroupKey=TableGroupKey(TableGroupKey::INVALID), bool doActivate=false, bool ignoreVersionTracking=false)
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
void init(std::string *accumulatedErrors=0, bool initForWriteAccess=false, std::string *accumulatedWarnings=0)
std::string getFirstPathToNode(const ConfigurationTree &node, const std::string &startPath="/") const
getFirstPathToNode
static ConfigurationManager::GroupType getTypeOfGroup(const std::map< std::string, TableVersion > &memberMap)
static const std::string & getTypeNameOfGroup(const std::map< std::string, TableVersion > &memberMap)
void destroyTableGroup(const std::string &theGroup="", bool onlyDeactivate=false)
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
std::pair< std::string, TableGroupKey > getTableGroupFromAlias(std::string systemAlias, ProgressBar *progressBar=0)
Getters.
void getOtherSubsystemConfigAliasInfo(const std::string &otherSubsystemUID, const std::string &configAlias, std::pair< std::string, TableGroupKey > &groupTranslation, std::string &groupComment, std::string &groupAuthor, std::string &groupCreationTime)
returns configAlias translation group info by reference
ConfigurationTree getGatewaySupervisorNode(void) const
There can only be one active Gateway Superivsor app, so find it.
static const std::string ACTIVE_GROUPS_FILENAME
added env check for otsdaq_flatten_active_to_version to function
std::set< std::string > getOtherSubsystemFilteredConfigAliases(const std::string &otherSubsystemUID, const std::string &otherSubsystemFsmName)
Ignore any System Aliases with "Context" or "Iterat" in the name.
TableGroupKey loadConfigurationBackbone(void)
const TableBase * getTableByName(const std::string &configurationName) const
static std::pair< std::string, TableGroupKey > loadGroupNameAndKey(const std::string &fileName, std::string &returnedTimeString)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveGroupAliases(void)
bool isDisconnected(void) const
std::vector< std::string > getChildrenNames(bool byPriority=false, bool onlyStatusTrue=false) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool onlyStatusTrue=false) const
const std::string & getValueAsString(bool returnLinkTableValue=false) const
void getValue(T &value) const
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
const std::string & getFieldName(void) const
alias for getValueName
bool isGroupLinkNode(void) const
bool isDefaultValue(void) const
boolean info
void step()
thread safe
Definition: ProgressBar.cc:74
const std::string & getTableName(void) const
Getters.
Definition: TableBase.cc:814
void setupMockupView(TableVersion version)
Definition: TableBase.cc:292
bool isActive(void)
isActive
Definition: TableBase.cc:950
const TableVersion & getViewVersion(void) const
always the active one
Definition: TableBase.cc:823
void print(std::ostream &out=std::cout) const
always prints active view
Definition: TableBase.cc:277
static std::string getFullGroupString(const std::string &groupName, const TableGroupKey &key, const std::string &preKey="_v", const std::string &postKey="")
std::string getChildLinkIndex(void) const
getChildLinkIndex
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
Definition: TableView.cc:1090
void deleteRow(int r)
Definition: TableView.cc:3602
unsigned int getColStatus(void) const
Definition: TableView.cc:1407
unsigned int getLinkGroupIDColumn(const std::string &childLinkIndex) const
Definition: TableView.cc:1837
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
Definition: TableView.cc:3632
void init(void)
Definition: TableView.cc:195
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
Definition: TableView.cc:975
unsigned int getColUID(void) const
Definition: TableView.cc:1322
void setValue(const T &value, unsigned int row, unsigned int col)
< in included .icc source
unsigned int addRow(const std::string &author="", unsigned char incrementUniqueData=false, const std::string &baseNameAutoUID="", unsigned int rowToAdd=(unsigned int) -1, std::string childLinkIndex="", std::string groupId="")
Definition: TableView.cc:3517
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
static std::string exec(const char *cmd)
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
vectorToString ~
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
getMapFromString ~
static std::string stackTrace(void)