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