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