otsdaq  3.09.00
ConfigurationManager.cc
1 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
2 #include "artdaq/Application/LoadParameterSet.hh"
3 #include "otsdaq/ConfigurationInterface/ConfigurationInterface.h" //All configurable objects are included here
4 #include "otsdaq/ProgressBar/ProgressBar.h"
5 #include "otsdaq/TablePlugins/XDAQContextTable/XDAQContextTable.h"
6 
7 #include <dirent.h> // DIR and dirent
8 #include <fstream> // std::ofstream
9 #include <sstream> // std::istringstream
10 
11 #include "otsdaq/TableCore/TableGroupKey.h"
12 #include "otsdaq/TablePlugins/DesktopIconTable.h" //for dynamic desktop icon change
13 
14 using namespace ots;
15 
16 #undef __MF_SUBJECT__
17 #define __MF_SUBJECT__ "ConfigurationManager"
18 
19 // clang-format off
20 
22 const unsigned int ConfigurationManager::PROCESSOR_COUNT = std::thread::hardware_concurrency();
23 
24 const std::string ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH = ((getenv("SERVICE_DATA_PATH") == NULL)
25  ? (std::string(__ENV__("USER_DATA")) + "/ServiceData")
26  : (std::string(__ENV__("SERVICE_DATA_PATH")))) +
27  "/RunControlData/";
28 
29 const std::string ConfigurationManager::LAST_ACTIVATED_CONFIG_GROUP_FILE = "CFGLastActivatedConfigGroup.hist";
30 const std::string ConfigurationManager::LAST_ACTIVATED_CONTEXT_GROUP_FILE = "CFGLastActivatedContextGroup.hist";
31 const std::string ConfigurationManager::LAST_ACTIVATED_BACKBONE_GROUP_FILE = "CFGLastActivatedBackboneGroup.hist";
32 const std::string ConfigurationManager::LAST_ACTIVATED_ITERATE_GROUP_FILE = "CFGLastActivatedIterateGroup.hist";
33 
34 const std::string ConfigurationManager::ACTIVATED_CONFIGS_FILE = "CFGActivatedConfigGroups.hist";
35 const std::string ConfigurationManager::ACTIVATED_CONTEXTS_FILE = "CFGActivatedContextGroups.hist";
36 const std::string ConfigurationManager::ACTIVATED_BACKBONES_FILE = "CFGActivatedBackboneGroups.hist";
37 const std::string ConfigurationManager::ACTIVATED_ITERATES_FILE = "CFGActivatedIterateGroups.hist";
38 
39 const std::string ConfigurationManager::LAST_ATTEMPTED_CONFIGURE_CONFIG_ALIAS_FILE = "CFGAttemptedConfigureConfigAlias.hist";
40 const std::string ConfigurationManager::LAST_ATTEMPTED_CONFIGURE_CONFIG_GROUP_FILE = "CFGAttemptedConfigureConfigGroup.hist";
41 
42 const std::string ConfigurationManager::ATTEMPTED_CONFIGURE_CONFIG_ALIASES_FILE = "CFGAttemptedConfigureConfigAliases.hist";
43 const std::string ConfigurationManager::ATTEMPTED_CONFIGURE_CONFIGS_FILE = "CFGAttemptedConfigureConfigGroups.hist";
44 
45 const std::string ConfigurationManager::LAST_CONFIGURED_CONFIG_ALIAS_FILE = "CFGLastConfiguredConfigAlias.hist";
46 const std::string ConfigurationManager::LAST_CONFIGURED_CONFIG_GROUP_FILE = "CFGLastConfiguredConfigGroup.hist";
47 const std::string ConfigurationManager::LAST_CONFIGURED_CONTEXT_GROUP_FILE = "CFGLastConfiguredContextGroup.hist";
48 const std::string ConfigurationManager::LAST_CONFIGURED_BACKBONE_GROUP_FILE = "CFGLastConfiguredBackboneGroup.hist";
49 const std::string ConfigurationManager::LAST_CONFIGURED_ITERATE_GROUP_FILE = "CFGLastConfiguredIterateGroup.hist";
50 
51 const std::string ConfigurationManager::CONFIGURED_CONFIG_ALIASES_FILE = "CFGConfiguredConfigAliases.hist";
52 const std::string ConfigurationManager::CONFIGURED_CONFIGS_FILE = "CFGConfiguredConfigGroups.hist";
53 const std::string ConfigurationManager::CONFIGURED_CONTEXTS_FILE = "CFGConfiguredContextGroups.hist";
54 const std::string ConfigurationManager::CONFIGURED_BACKBONES_FILE = "CFGConfiguredBackboneGroups.hist";
55 const std::string ConfigurationManager::CONFIGURED_ITERATES_FILE = "CFGConfiguredIterateGroups.hist";
56 
57 const std::string ConfigurationManager::LAST_STARTED_CONFIG_ALIAS_FILE = "CFGLastStartedConfigAlias.hist";
58 const std::string ConfigurationManager::LAST_STARTED_CONFIG_GROUP_FILE = "CFGLastStartedConfigGroup.hist";
59 const std::string ConfigurationManager::LAST_STARTED_CONTEXT_GROUP_FILE = "CFGLastStartedContextGroup.hist";
60 const std::string ConfigurationManager::LAST_STARTED_BACKBONE_GROUP_FILE = "CFGLastStartedBackboneGroup.hist";
61 const std::string ConfigurationManager::LAST_STARTED_ITERATE_GROUP_FILE = "CFGLastStartedIterateGroup.hist";
62 
63 const std::string ConfigurationManager::STARTED_CONFIG_ALIASES_FILE = "CFGStartedConfigAliases.hist";
64 const std::string ConfigurationManager::STARTED_CONFIGS_FILE = "CFGStartedConfigGroups.hist";
65 const std::string ConfigurationManager::STARTED_CONTEXTS_FILE = "CFGStartedContextGroups.hist";
66 const std::string ConfigurationManager::STARTED_BACKBONES_FILE = "CFGStartedBackboneGroups.hist";
67 const std::string ConfigurationManager::STARTED_ITERATES_FILE = "CFGStartedIterateGroups.hist";
68 
69 const std::string ConfigurationManager::CONFIGURED_OR_STARTED_CONFIG_ALIASES_FILE = "CFGConfiguredOrStartedConfigAliases.hist";
70 const std::string ConfigurationManager::CONFIGURED_OR_STARTED_CONFIGS_FILE = "CFGConfiguredOrStartedConfigGroups.hist";
71 const std::string ConfigurationManager::CONFIGURED_OR_STARTED_CONTEXTS_FILE = "CFGConfiguredOrStartedContextGroups.hist";
72 const std::string ConfigurationManager::CONFIGURED_OR_STARTED_BACKBONES_FILE = "CFGConfiguredOrStartedBackboneGroups.hist";
73 const std::string ConfigurationManager::CONFIGURED_OR_STARTED_ITERATES_FILE = "CFGConfiguredOrStartedIterateGroups.hist";
74 
75 
76 const std::string ConfigurationManager::READONLY_USER = "READONLY_USER";
77 
78 const std::string ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME = "XDAQContextTable";
79 const std::string ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME = "XDAQApplicationTable";
80 const std::string ConfigurationManager::XDAQ_APP_PROPERTY_TABLE_NAME = "XDAQApplicationPropertyTable";
81 const std::string ConfigurationManager::GROUP_ALIASES_TABLE_NAME = "GroupAliasesTable";
82 const std::string ConfigurationManager::VERSION_ALIASES_TABLE_NAME = "VersionAliasesTable";
83 const std::string ConfigurationManager::ARTDAQ_TOP_TABLE_NAME = "ARTDAQSupervisorTable";
84 const std::string ConfigurationManager::DESKTOP_ICON_TABLE_NAME = "DesktopIconTable";
85 
87 const std::string ConfigurationManager::ACTIVE_GROUPS_FILENAME = ((getenv("SERVICE_DATA_PATH") == NULL)
88  ? (std::string(__ENV__("USER_DATA")) + "/ServiceData")
89  : (std::string(__ENV__("SERVICE_DATA_PATH")))) +
90  "/ActiveTableGroups.cfg";
91 
92 const std::string ConfigurationManager::ALIAS_VERSION_PREAMBLE = "ALIAS:";
93 const std::string ConfigurationManager::SCRATCH_VERSION_ALIAS = "Scratch";
94 const std::string ConfigurationManager::SUBSYSTEM_COMMON_VERSION_ALIAS = "SubsystemCommon";
95 const std::string ConfigurationManager::SUBSYSTEM_COMMON_OVERRIDE_VERSION_ALIAS = "SubsystemCommonOverride";
96 
97 
98 const std::string ConfigurationManager::GROUP_TYPE_NAME_CONTEXT = "Context";
99 const std::string ConfigurationManager::GROUP_TYPE_NAME_BACKBONE = "Backbone";
100 const std::string ConfigurationManager::GROUP_TYPE_NAME_ITERATE = "Iterate";
101 const std::string ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION = "Configuration";
102 const std::string ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN = "UNKNOWN";
103 
104 const std::string ConfigurationManager::UNKNOWN_INFO = "UNKNOWN";
105 const std::string ConfigurationManager::UNKNOWN_TIME = "0";
106 
107 const uint8_t ConfigurationManager::METADATA_COL_ALIASES = 1;
108 const uint8_t ConfigurationManager::METADATA_COL_COMMENT = 2;
109 const uint8_t ConfigurationManager::METADATA_COL_AUTHOR = 3;
110 const uint8_t ConfigurationManager::METADATA_COL_TIMESTAMP = 4;
111 
112 const std::string ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE = "SubsystemUserDataPathsTable";
113 
114 
115 const std::set<std::string> ConfigurationManager::fixedContextMemberNames_ = {
116  ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME,
117  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME,
118  "XDAQApplicationPropertyTable",
119  ConfigurationManager::DESKTOP_ICON_TABLE_NAME,
120  "MessageFacilityTable",
121  "GatewaySupervisorTable",
122  "StateMachineTable",
123  "DesktopWindowParameterTable",
124  "SlowControlsDashboardSupervisorTable"
125  };
126 const std::set<std::string> ConfigurationManager::backboneMemberNames_ = {
127  ConfigurationManager::GROUP_ALIASES_TABLE_NAME,
128  ConfigurationManager::VERSION_ALIASES_TABLE_NAME
129  };
130 const std::set<std::string> ConfigurationManager::iterateMemberNames_ = {
131  "IterateTable",
132  "IterationPlanTable",
133  "IterationTargetTable",
134  /*command specific tables*/ "IterationCommandBeginLabelTable",
135  "IterationCommandChooseFSMTable",
136  "IterationCommandConfigureAliasTable",
137  "IterationCommandConfigureGroupTable",
138  "IterationCommandExecuteFEMacroTable",
139  "IterationCommandExecuteMacroTable",
140  "IterationCommandMacroDimensionalLoopTable",
141  "IterationCommandMacroDimensionalLoopParameterTable",
142  "IterationCommandModifyGroupTable",
143  "IterationCommandRepeatLabelTable",
144  "IterationCommandRunTable"
145  };
146 
147 // clang-format on
148 
149 //==============================================================================
150 ConfigurationManager::ConfigurationManager(bool initForWriteAccess /*=false*/,
151  bool doInitializeFromFhicl /*=false*/,
152  bool forceNotFirstInContext /*=false*/)
153  : startClockTime_(std::chrono::steady_clock::now())
154  , deltaClockTime_(std::chrono::steady_clock::now())
155  , forceNotFirstInContext_(forceNotFirstInContext)
156  , mfSubject_(ConfigurationManager::READONLY_USER)
157  , username_(ConfigurationManager::READONLY_USER)
158  , theInterface_(0)
159  , theConfigurationTableGroupKey_(0)
160  , theContextTableGroupKey_(0)
161  , theBackboneTableGroupKey_(0)
162  , theConfigurationTableGroup_("")
163  , theContextTableGroup_("")
164  , theBackboneTableGroup_("")
165  , groupMetadataTable_(true /*special table*/, TableBase::GROUP_METADATA_TABLE_NAME)
166 {
167  __GEN_COUTTV__(runTimeSeconds());
168  theInterface_ = ConfigurationInterface::getInstance(
169  ConfigurationInterface::CONFIGURATION_MODE::
170  ARTDAQ_DATABASE); // false to use artdaq DB
171 
172  __GEN_COUTTV__(runTimeSeconds());
173 
174  // // initialize special group metadata table
175  // {
176  // // Note: "TableGroupMetadata" should never be in conflict
177  // // because all other tables end in "...Table"
178 
179  // // This is a table called TableGroupMetadata
180  // // with 4 fields:
181  // // - GroupAliases
182  // // - GroupAuthor
183  // // - GroupCreationTime
184  // // - CommentDescription
185 
186  // groupMetadataTable_.setTableName(
187  // TableBase::GROUP_METADATA_TABLE_NAME);
188  // std::vector<TableViewColumnInfo>* colInfo =
189  // groupMetadataTable_.getMockupViewP()->getColumnsInfoP();
190  // colInfo->push_back(TableViewColumnInfo(
191  // TableViewColumnInfo::TYPE_UID, // just to make init() happy
192  // "UnusedUID",
193  // "UNUSED_UID",
194  // TableViewColumnInfo::DATATYPE_NUMBER,
195  // 0 /*Default*/,
196  // "",
197  // 0 /*Min*/,
198  // 0 /*Max*/,
199  // 0));
200  // colInfo->push_back(TableViewColumnInfo(TableViewColumnInfo::TYPE_DATA,
201  // "GroupAliases",
202  // "GROUP_ALIASES",
203  // TableViewColumnInfo::DATATYPE_STRING,
204  // 0 /*Default*/,
205  // "",
206  // 0 /*Min*/,
207  // 0 /*Max*/,
208  // 0));
209  // colInfo->push_back(TableViewColumnInfo(
210  // TableViewColumnInfo::TYPE_COMMENT, // just to make init() happy
211  // TableViewColumnInfo::COL_NAME_COMMENT,
212  // "COMMENT_DESCRIPTION",
213  // TableViewColumnInfo::DATATYPE_STRING,
214  // 0 /*Default*/,
215  // "",
216  // 0 /*Min*/,
217  // 0 /*Max*/,
218  // 0));
219  // colInfo->push_back(TableViewColumnInfo(
220  // TableViewColumnInfo::TYPE_AUTHOR, // just to make init() happy
221  // "GroupAuthor",
222  // "AUTHOR",
223  // TableViewColumnInfo::DATATYPE_STRING,
224  // 0 /*Default*/,
225  // "",
226  // 0 /*Min*/,
227  // 0 /*Max*/,
228  // 0));
229  // colInfo->push_back(TableViewColumnInfo(TableViewColumnInfo::TYPE_TIMESTAMP,
230  // "GroupCreationTime",
231  // "GROUP_CREATION_TIME",
232  // TableViewColumnInfo::DATATYPE_TIME,
233  // 0 /*Default*/,
234  // "",
235  // 0 /*Min*/,
236  // 0 /*Max*/,
237  // 0));
238  // auto tmpVersion = groupMetadataTable_.createTemporaryView();
239  // groupMetadataTable_.setActiveView(tmpVersion);
240  // // only need this one and only row for all time
241  // groupMetadataTable_.getViewP()->addRow();
242  // }
243 
244  if(doInitializeFromFhicl)
245  {
246  // create tables and fill based on fhicl
247  initializeFromFhicl(__ENV__("CONFIGURATION_INIT_FCL"));
248  return;
249  }
250  // else do normal init
251 
252  __GEN_COUTTV__(runTimeSeconds());
253  if(!initForWriteAccess) //ConfigurationManagerRW can do manual init later when it calls getAllTableInfo(true)
254  init(0 /*accumulatedErrors*/, initForWriteAccess);
255  __GEN_COUTTV__(runTimeSeconds());
256 
257 } // end constructor()
258 
259 //==============================================================================
260 ConfigurationManager::ConfigurationManager(const std::string& username)
261  : ConfigurationManager(true /*initForWriteAccess*/)
262 {
263  __GEN_COUT__ << "Private constructor for write access called." << __E__;
264  // overwrite read-only username initialization with write-access username:
265  mfSubject_ = username;
266  username_ = username;
267 } // end constructor(username)
268 
269 //==============================================================================
270 ConfigurationManager::~ConfigurationManager() { destroy(); }
271 
272 //==============================================================================
278 void ConfigurationManager::init(std::string* accumulatedErrors /*=0*/,
279  bool initForWriteAccess /*= false*/,
280  std::string* accumulatedWarnings /*=0*/)
281 {
282  // if(accumulatedErrors)
283  // *accumulatedErrors = "";
284 
285  // destroy();
286 
287  // once Interface is false (using artdaq db) ..
288  // then can test (configurationInterface_->getMode() == false)
289  {
290  try
291  {
292  __GEN_COUTTV__(username_);
293 
294  // if write access, then load all specified table groups (including configuration group),
295  // otherwise skip configuration group. Important to consider initForWriteAccess
296  // because this may be called before username_ is properly initialized
297  ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext =
298  ConfigurationManager::LoadGroupType::ALL_TYPES;
299  if(username_ == ConfigurationManager::READONLY_USER && !initForWriteAccess)
300  onlyLoadIfBackboneOrContext =
301  ConfigurationManager::LoadGroupType::ONLY_BACKBONE_OR_CONTEXT_TYPES;
302 
303  // clang-format off
304  restoreActiveTableGroups(accumulatedErrors ? true : false /*throwErrors*/,
305  "" /*pathToActiveGroupsFile*/,
306  onlyLoadIfBackboneOrContext,
307  accumulatedWarnings);
308  // clang-format on
309  }
310  catch(std::runtime_error& e)
311  {
312  __GEN_COUT_ERR__ << "Error caught in init(): " << e.what();
313  if(accumulatedErrors)
314  *accumulatedErrors += e.what();
315  else
316  {
317  __SS__ << e.what(); // add line number of rethrow
318  __SS_ONLY_THROW__;
319  }
320  }
321  }
322 } // end init()
323 
324 //==============================================================================
330  bool throwErrors /*=false*/,
331  const std::string& pathToActiveGroupsFile /*=""*/,
332  ConfigurationManager::LoadGroupType
333  onlyLoadIfBackboneOrContext /*= ConfigurationManager::LoadGroupType::ALL_TYPES */,
334  std::string* accumulatedWarnings /*=0*/)
335 {
336  destroyTableGroup("", true); // deactivate all
337 
338  std::string fn =
339  pathToActiveGroupsFile == "" ? ACTIVE_GROUPS_FILENAME : pathToActiveGroupsFile;
340  FILE* fp = fopen(fn.c_str(), "r");
341 
342  __GEN_COUTT__ << "ACTIVE_GROUPS_FILENAME = " << fn << __E__;
343  __GEN_COUTS__(10) << "ARTDAQ_DATABASE_URI = "
344  << std::string(__ENV__("ARTDAQ_DATABASE_URI")) << __E__;
345 
346  if(!fp)
347  {
348  __GEN_COUT_WARN__ << "No active groups file found at " << fn << __E__;
349  return;
350  }
351 
352  __GEN_COUTVS__(10, throwErrors);
353 
354  char tmp[500];
355  char strVal[500];
356 
357  std::string groupName;
358  std::string errorStr = "";
359  bool skip;
360 
361  __SS__;
362 
363  while(fgets(tmp, 500, fp))
364  {
365  // do check for out of sync.. i.e. name is a number
366  {
367  int numberCheck = 0;
368  sscanf(tmp, "%d", &numberCheck);
369  if(numberCheck)
370  {
371  __GEN_COUT__
372  << "Out of sync with active groups file lines, attempting to resync."
373  << __E__;
374  continue;
375  }
376  }
377 
378  skip = false;
379  sscanf(tmp, "%s", strVal); // sscanf to remove '\n'
380  for(unsigned int j = 0; j < strlen(strVal); ++j)
381  if(!((strVal[j] >= 'a' && strVal[j] <= 'z') ||
382  (strVal[j] >= 'A' && strVal[j] <= 'Z') ||
383  (strVal[j] >= '0' && strVal[j] <= '9')))
384  {
385  strVal[j] = '\0';
386  if(strlen(strVal) == 0)
387  __GEN_COUT__ << "Empty group name found, so skipping! Check active "
388  "groups file: "
389  << fn << __E__;
390  else
391  __GEN_COUT_WARN__
392  << "Illegal character found in group name '" << strVal
393  << "', so skipping! Check active groups file: " << fn << __E__;
394 
395  skip = true;
396  break;
397  }
398 
399  if(skip)
400  continue;
401 
402  groupName = strVal;
403  fgets(tmp, 500, fp);
404  sscanf(tmp, "%s", strVal); // sscanf to remove '\n'
405 
406  for(unsigned int j = 0; j < strlen(strVal); ++j)
407  if(!((strVal[j] >= '0' && strVal[j] <= '9')))
408  {
409  strVal[j] = '\0';
410 
411  if(groupName.size() > 3) // notify if seems like a real group name
412  __GEN_COUT_WARN__
413  << "Skipping active group with illegal character in group key '"
414  << strVal << ".' Check active groups file: " << fn << __E__;
415 
416  skip = true;
417  break;
418  }
419 
420  if(groupName.size() <= 3)
421  continue; //skip illegal group names
422 
423  if(skip)
424  continue;
425 
426  try
427  {
429  }
430  catch(...)
431  {
432  __GEN_COUT__
433  << "illegal group according to TableGroupKey::getFullGroupString... "
434  "Check active groups file: "
435  << fn << __E__;
436  skip = true;
437  }
438 
439  if(skip)
440  continue;
441 
442  try
443  {
444  // load and doActivate
445  std::string groupAccumulatedErrors = "";
446 
447  if(accumulatedWarnings)
448  __GEN_COUT__ << "Ignoring warnings while loading and activating group '"
449  << groupName << "(" << strVal << ")'" << __E__;
450 
452  groupName,
453  TableGroupKey(strVal),
454  true /*doActivate*/,
455  0 /*groupMembers*/,
456  0 /*progressBar*/,
457  (accumulatedWarnings ? &groupAccumulatedErrors
458  : 0) /*accumulateWarnings = 0*/,
459  0 /*groupComment = 0*/,
460  0 /*groupAuthor = 0*/,
461  0 /*groupCreateTime = 0*/,
462  0 /*doNotLoadMembers = false*/,
463  0 /*groupTypeString = 0*/,
464  0 /*groupAliases = 0*/,
465  onlyLoadIfBackboneOrContext /*onlyLoadIfBackboneOrContext = false*/
466  );
467 
468  if(accumulatedWarnings)
469  *accumulatedWarnings += groupAccumulatedErrors;
470  }
471  catch(std::runtime_error& e)
472  {
473  ss << "Failed to load group in ConfigurationManager::init() with name '"
474  << groupName << "(" << strVal
475  << ")' specified active by active groups file: " << fn << __E__;
476  ss << e.what() << __E__;
477 
478  errorStr += ss.str();
479  }
480  catch(...)
481  {
482  ss << "Failed to load group in ConfigurationManager::init() with name '"
483  << groupName << "(" << strVal
484  << ")' specified active by active groups file: " << fn << __E__;
485  try
486  {
487  throw;
488  } //one more try to printout extra info
489  catch(const std::exception& e)
490  {
491  ss << "Exception message: " << e.what();
492  }
493  catch(...)
494  {
495  }
496  errorStr += ss.str();
497  }
498  }
499 
500  fclose(fp);
501 
502  if(throwErrors && errorStr != "")
503  {
504  __SS__ << "\n" << errorStr;
505  __SS_ONLY_THROW__;
506  }
507  else if(errorStr != "")
508  __GEN_COUT_WARN__ << "\n" << errorStr;
509 
510 } // end restoreActiveTableGroups()
511 
512 //==============================================================================
517 void ConfigurationManager::destroyTableGroup(const std::string& theGroup,
518  bool onlyDeactivate)
519 {
520  // delete
521  bool isContext = theGroup == "" || theGroup == theContextTableGroup_;
522  bool isBackbone = theGroup == "" || theGroup == theBackboneTableGroup_;
523  bool isIterate = theGroup == "" || theGroup == theIterateTableGroup_;
524  bool isConfiguration = theGroup == "" || theGroup == theConfigurationTableGroup_;
525 
526  if(!isContext && !isBackbone && !isIterate && !isConfiguration)
527  {
528  __SS__ << "Invalid configuration group to destroy: " << theGroup << __E__;
529  __GEN_COUT_ERR__ << ss.str();
530  __SS_THROW__;
531  }
532 
533  std::string dbgHeader = onlyDeactivate ? "Deactivating" : "Destroying";
534  if(theGroup != "")
535  {
536  if(isContext)
537  __GEN_COUT__ << dbgHeader << " Context group: " << theGroup << __E__;
538  if(isBackbone)
539  __GEN_COUT__ << dbgHeader << " Backbone group: " << theGroup << __E__;
540  if(isIterate)
541  __GEN_COUT__ << dbgHeader << " Iterate group: " << theGroup << __E__;
542  if(isConfiguration)
543  __GEN_COUT__ << dbgHeader << " Configuration group: " << theGroup << __E__;
544  }
545 
546  getActiveContextMemberNames(); // make sure active contextMemberNames_ are up to date
547 
548  std::set<std::string>::const_iterator contextFindIt, backboneFindIt, iterateFindIt;
549  for(auto it = nameToTableMap_.begin(); it != nameToTableMap_.end();
550  /*no increment*/)
551  {
552  contextFindIt = contextMemberNames_.find(it->first);
553  backboneFindIt = backboneMemberNames_.find(it->first);
554  iterateFindIt = iterateMemberNames_.find(it->first);
555 
556  __GEN_COUTT__ << "Considering table: " << it->first << " contextFindIt:"
557  << (contextFindIt != contextMemberNames_.end() ? "Y" : "N")
558  << " backboneFindIt:"
559  << (backboneFindIt != backboneMemberNames_.end() ? "Y" : "N")
560  << " iterateFindIt:"
561  << (iterateFindIt != iterateMemberNames_.end() ? "Y" : "N")
562  << __E__;
563  if(theGroup == "" ||
564  ((isContext &&
565  contextFindIt !=
566  contextMemberNames_
567  .end()) || //for context group, deactivate context members AND optional member
568  (isContext &&
569  it->first ==
571  CONTEXT_SUBSYSTEM_OPTIONAL_TABLE) || //optional context member
572  (isBackbone && backboneFindIt != backboneMemberNames_.end()) ||
573  (isIterate && iterateFindIt != iterateMemberNames_.end()) ||
574  (isConfiguration && //for configuration group, deactivate all tables not specified in other group types
575  contextFindIt == contextMemberNames_.end() &&
576  it->first != ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE &&
577  backboneFindIt == backboneMemberNames_.end() &&
578  iterateFindIt == iterateMemberNames_.end())))
579  {
580  __GEN_COUTT__ << "\t" << dbgHeader << ".. " << it->first
581  << (it->second->isActive()
582  ? "_v" + it->second->getViewVersion().str()
583  : "")
584  << __E__;
585 
586  if(onlyDeactivate) // only deactivate
587  {
588  it->second->deactivate();
589  ++it;
590  }
591  else // else, delete/erase
592  {
593  delete it->second;
594  nameToTableMap_.erase(it++);
595  }
596  }
597  else
598  ++it;
599  }
600 
601  if(isConfiguration)
602  {
603  theConfigurationTableGroup_ = "";
604  if(theConfigurationTableGroupKey_ != 0)
605  {
606  __GEN_COUTT__ << "Destroying Configuration Key: "
607  << *theConfigurationTableGroupKey_ << __E__;
608  theConfigurationTableGroupKey_.reset();
609  }
610  }
611  if(isBackbone)
612  {
613  theBackboneTableGroup_ = "";
614  if(theBackboneTableGroupKey_ != 0)
615  {
616  __GEN_COUTT__ << "Destroying Backbone Key: " << *theBackboneTableGroupKey_
617  << __E__;
618  theBackboneTableGroupKey_.reset();
619  }
620  }
621  if(isIterate)
622  {
623  theIterateTableGroup_ = "";
624  if(theIterateTableGroupKey_ != 0)
625  {
626  __GEN_COUTT__ << "Destroying Iterate Key: " << *theIterateTableGroupKey_
627  << __E__;
628  theIterateTableGroupKey_.reset();
629  }
630  }
631  if(isContext)
632  {
633  theContextTableGroup_ = "";
634  if(theContextTableGroupKey_ != 0)
635  {
636  __GEN_COUTT__ << "Destroying Context Key: " << *theContextTableGroupKey_
637  << __E__;
638  theContextTableGroupKey_.reset();
639  }
640  }
641 } //end destroyTableGroup()
642 
643 //==============================================================================
644 void ConfigurationManager::destroy(void) { destroyTableGroup(); } //end destroy()
645 
646 //==============================================================================
653  const ConfigurationManager::GroupType& groupTypeId)
654 {
655  return groupTypeId == ConfigurationManager::GroupType::CONTEXT_TYPE
656  ? ConfigurationManager::GROUP_TYPE_NAME_CONTEXT
657  : (groupTypeId == ConfigurationManager::GroupType::BACKBONE_TYPE
658  ? ConfigurationManager::GROUP_TYPE_NAME_BACKBONE
659  : (groupTypeId == ConfigurationManager::GroupType::ITERATE_TYPE
660  ? ConfigurationManager::GROUP_TYPE_NAME_ITERATE
661  : (groupTypeId == ConfigurationManager::GroupType::
662  CONFIGURATION_TYPE
663  ? ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION
664  : ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN)));
665 } // end convertGroupTypeToName()
666 
667 //==============================================================================
674 ConfigurationManager::GroupType ConfigurationManager::getTypeOfGroup(
675  const std::map<std::string /*name*/, TableVersion /*version*/>& memberMap)
676 {
677  bool isContext = true;
678  bool isBackbone = true;
679  bool isIterate = true;
680  bool inGroup;
681  bool inContext = false;
682  bool inBackbone = false;
683  bool inIterate = false;
684  unsigned int matchCount = 0;
685 
686  for(auto& memberPair : memberMap)
687  {
688  //__COUT__ << "Member name: = "<< memberPair.first << __E__;
690  inGroup = false; // check context
691  if(memberPair.first == CONTEXT_SUBSYSTEM_OPTIONAL_TABLE)
692  {
693  inGroup = true;
694  inContext = true;
695  }
696  else
697  for(auto& contextMemberString : fixedContextMemberNames_)
698  if(memberPair.first == contextMemberString)
699  {
700  inGroup = true;
701  inContext = true;
702  ++matchCount;
703  break;
704  }
705  if(!inGroup)
706  {
707  isContext = false;
708  if(inContext) // there was a member in context!
709  {
710  __SS__ << "This group is an incomplete match to a Context group.\n";
711  ss << "\nTo be a Context group, the members must exactly match "
712  << "the following members (w/ or wo/ the optional table "
713  << CONTEXT_SUBSYSTEM_OPTIONAL_TABLE << "):\n";
714  int i = 0;
715  for(const auto& memberName : fixedContextMemberNames_)
716  ss << ++i << ". " << memberName << "\n";
717  ss << "\nThe members are as follows::\n";
718  i = 0;
719  for(const auto& memberPairTmp : memberMap)
720  ss << ++i << ". " << memberPairTmp.first << "\n";
721  __SS_ONLY_THROW__;
722  }
723  }
724 
726  inGroup = false; // check backbone
727  for(auto& backboneMemberString : backboneMemberNames_)
728  if(memberPair.first == backboneMemberString)
729  {
730  inGroup = true;
731  inBackbone = true;
732  ++matchCount;
733  break;
734  }
735  if(!inGroup)
736  {
737  isBackbone = false;
738  if(inBackbone) // there was a member in backbone!
739  {
740  __SS__ << "This group is an incomplete match to a Backbone group.\n";
741  ss << "\nTo be a Backbone group, the members must exactly match "
742  << "the following members:\n";
743  int i = 0;
744  for(auto& memberName : backboneMemberNames_)
745  ss << ++i << ". " << memberName << "\n";
746  ss << "\nThe members are as follows::\n";
747  i = 0;
748  for(const auto& memberPairTmp : memberMap)
749  ss << ++i << ". " << memberPairTmp.first << "\n";
750  //__COUT_ERR__ << "\n" << ss.str();
751  __SS_ONLY_THROW__;
752  }
753  }
754 
756  inGroup = false; // check iterate
757  for(auto& iterateMemberString : iterateMemberNames_)
758  if(memberPair.first == iterateMemberString)
759  {
760  inGroup = true;
761  inIterate = true;
762  ++matchCount;
763  break;
764  }
765  if(!inGroup)
766  {
767  isIterate = false;
768  if(inIterate) // there was a member in iterate!
769  {
770  __SS__ << "This group is an incomplete match to a Iterate group.\n";
771  ss << "\nTo be a Iterate group, the members must exactly match "
772  << "the following members:\n";
773  int i = 0;
774  for(auto& memberName : iterateMemberNames_)
775  ss << ++i << ". " << memberName << "\n";
776  ss << "\nThe members are as follows::\n";
777  i = 0;
778  for(const auto& memberPairTmp : memberMap)
779  ss << ++i << ". " << memberPairTmp.first << "\n";
780  //__COUT_ERR__ << "\n" << ss.str();
781  __SS_ONLY_THROW__;
782  }
783  }
784  }
785 
786  if((isContext || inContext) && matchCount != fixedContextMemberNames_.size())
787  {
788  __SS__ << "This group is an incomplete match to a Context group: "
789  << " Size=" << matchCount << " but should be "
790  << fixedContextMemberNames_.size() << __E__;
791  ss << "\nThe members currently are...\n";
792  int i = 0;
793  for(auto& memberPair : memberMap)
794  ss << ++i << ". " << memberPair.first << "\n";
795  ss << "\nThe expected Context members are...\n";
796  i = 0;
797  for(auto& memberName : fixedContextMemberNames_)
798  ss << ++i << ". " << memberName << "\n";
799  ss << "optional. (" << CONTEXT_SUBSYSTEM_OPTIONAL_TABLE << ")\n";
800  //__COUT_ERR__ << "\n" << ss.str();
801  __SS_ONLY_THROW__;
802  }
803 
804  if((isBackbone || inBackbone) && matchCount != backboneMemberNames_.size())
805  {
806  __SS__ << "This group is an incomplete match to a Backbone group: "
807  << " Size=" << matchCount << " but should be "
808  << backboneMemberNames_.size() << __E__;
809  ss << "\nThe members currently are...\n";
810  int i = 0;
811  for(auto& memberPair : memberMap)
812  ss << ++i << ". " << memberPair.first << "\n";
813  ss << "\nThe expected Backbone members are...\n";
814  i = 0;
815  for(auto& memberName : backboneMemberNames_)
816  ss << ++i << ". " << memberName << "\n";
817  //__COUT_ERR__ << "\n" << ss.str();
818  __SS_ONLY_THROW__;
819  }
820 
821  if((isIterate || inIterate) && matchCount != iterateMemberNames_.size())
822  {
823  __SS__ << "This group is an incomplete match to a Iterate group: "
824  << " Size=" << matchCount << " but should be "
825  << iterateMemberNames_.size() << __E__;
826  ss << "\nThe members currently are...\n";
827  int i = 0;
828  for(auto& memberPair : memberMap)
829  ss << ++i << ". " << memberPair.first << "\n";
830  ss << "\nThe expected Iterate members are...\n";
831  i = 0;
832  for(auto& memberName : iterateMemberNames_)
833  ss << ++i << ". " << memberName << "\n";
834  //__COUT_ERR__ << "\n" << ss.str();
835  __SS_ONLY_THROW__;
836  }
837 
838  return isContext
839  ? ConfigurationManager::GroupType::CONTEXT_TYPE
840  : (isBackbone
841  ? ConfigurationManager::GroupType::BACKBONE_TYPE
842  : (isIterate
843  ? ConfigurationManager::GroupType::ITERATE_TYPE
844  : ConfigurationManager::GroupType::CONFIGURATION_TYPE));
845 } // end getTypeOfGroup()
846 
847 //==============================================================================
851  const std::map<std::string /*name*/, TableVersion /*version*/>& memberMap)
852 {
853  return convertGroupTypeToName(getTypeOfGroup(memberMap));
854 } // end getTypeNameOfGroup()
855 
856 //==============================================================================
862 #define OUT out << tabStr << commentStr
863 #define PUSHTAB tabStr += "\t"
864 #define POPTAB tabStr.resize(tabStr.size() - 1)
865 #define PUSHCOMMENT commentStr += "# "
866 #define POPCOMMENT commentStr.resize(commentStr.size() - 2)
867 
868 void ConfigurationManager::dumpMacroMakerModeFhicl()
869 {
870  if(nameToTableMap_.find("FEInterfaceTable") == nameToTableMap_.end())
871  {
872  __COUT__ << "Skipping dumpMacroMakerModeFhicl() since FEInterface table is not "
873  "activated."
874  << __E__;
875  return;
876  }
877 
878  std::string filepath =
879  __ENV__("USER_DATA") + std::string("/") + "MacroMakerModeConfigurations";
880  mkdir(filepath.c_str(), 0755);
881  filepath += "/MacroMakerModeFhiclDump.fcl";
882  __GEN_COUT__ << "dumpMacroMakerModeFhicl: " << filepath << __E__;
883 
885  // generate MacroMaker mode fhicl file
886  std::fstream out;
887 
888  std::string tabStr = "";
889  std::string commentStr = "";
890 
891  out.open(filepath, std::fstream::out | std::fstream::trunc);
892  if(out.fail())
893  {
894  __SS__ << "Failed to open MacroMaker mode fcl file for configuration dump: "
895  << filepath << __E__;
896  __SS_THROW__;
897  }
898 
899  try
900  {
901  std::vector<std::pair<std::string, ConfigurationTree>> fes =
902  getNode("FEInterfaceTable").getChildren();
903 
904  for(auto& fe : fes)
905  {
906  // skip status false
907  if(!fe.second.status())
908  continue;
909 
910  //__GEN_COUTV__(fe.first);
911 
912  OUT << fe.first << ": {" << __E__;
913  PUSHTAB;
914 
915  // only do FEInterfacePluginName and LinkToFETypeTable at top level
916 
917  OUT << "FEInterfacePluginName"
918  << ": \t"
919  << "\"" << fe.second.getNode("FEInterfacePluginName").getValueAsString()
920  << "\"" << __E__;
921 
922  recursiveTreeToFhicl(
923  fe.second.getNode("LinkToFETypeTable"), out, tabStr, commentStr);
924 
925  POPTAB;
926  OUT << "} //end " << fe.first << __E__ << __E__;
927 
928  } // end fe handling
929  }
930  catch(...)
931  {
932  __SS__ << "Failed to complete MacroMaker mode fcl "
933  "file configuration dump due to error."
934  << __E__;
935  try
936  {
937  throw;
938  } //one more try to printout extra info
939  catch(const std::runtime_error& e)
940  {
941  ss << "Exception message: " << e.what();
942  }
943  catch(const std::exception& e)
944  {
945  ss << "Exception message: " << e.what();
946  }
947  __GEN_COUT_ERR__ << ss.str();
948  }
949 
950  out.close();
951  // end fhicl output
952 } // end dumpMacroMakerModeFhicl()
953 
954 //==============================================================================
963 void ConfigurationManager::recursiveTreeToFhicl(ConfigurationTree node,
964  std::ostream& out /* = std::cout */,
965  std::string& tabStr /* = "" */,
966  std::string& commentStr /* = "" */,
967  unsigned int depth /* = -1 */)
968 {
969  if(depth == 0)
970  {
971  __COUT__ << __COUT_HDR_P__ << "Depth limit reached. Ending recursion." << __E__;
972  return;
973  }
974 
975  //__COUT__ << __COUT_HDR_P__ << "Adding tree record '" << node.getValueAsString() << "' fields..." << __E__;
976 
977  if(depth == (unsigned int)-1)
978  depth = 10;
979 
980  // decorate link node with link_table {} wrapper
981  if(node.isLinkNode())
982  {
983  if(node.isDisconnected())
984  {
985  //__COUT__ << node.getFieldName() << " field is a disconnected link." << __E__;
986  return;
987  }
988 
989  OUT << node.getFieldName() << "_"
990  << node.getValueAsString(true /* returnLinkTableValue */) << ": \t{" << __E__;
991  PUSHTAB;
992  } // end link preamble decoration
993 
994  if(node.isGroupLinkNode())
995  {
996  // for group link, handle each as a UID record
997  std::vector<std::pair<std::string, ConfigurationTree>> children =
998  node.getChildren();
999  for(auto& child : children)
1000  recursiveTreeToFhicl(child.second, out, tabStr, commentStr, depth - 1);
1001 
1002  POPTAB;
1003  OUT << "} //end " << node.getValueAsString(true /* returnLinkTableValue */)
1004  << " group link record" << __E__;
1005  return;
1006  } // end group link handling
1007 
1008  // treat as UID record now
1009  // give UID decoration, then contents
1010 
1011  // open UID decoration
1012  OUT << node.getValueAsString() << ": \t{" << __E__;
1013  PUSHTAB;
1014  { // open UID content
1015 
1016  std::vector<std::pair<std::string, ConfigurationTree>> fields =
1017  node.getChildren();
1018 
1019  // skip last 3 fields that are always common
1020  for(unsigned int i = 0; i < fields.size() - 3; ++i)
1021  {
1022  //__COUT__ << fields[i].first << __E__;
1023 
1024  if(fields[i].second.isLinkNode())
1025  {
1026  recursiveTreeToFhicl(
1027  fields[i].second, out, tabStr, commentStr, depth - 1);
1028  continue;
1029  }
1030  // else a normal field
1031 
1032  OUT << fields[i].second.getFieldName() << ": \t";
1033  if(fields[i].second.isValueNumberDataType())
1034  OUT << fields[i].second.getValueAsString() << __E__;
1035  else
1036  OUT << "\"" << fields[i].second.getValueAsString() << "\"" << __E__;
1037 
1038  } // end fe fields
1039 
1040  } // close UID content
1041  POPTAB; // close UID decoration
1042  OUT << "} //end " << node.getValueAsString() << " record" << __E__;
1043 
1044  // handle link closing decoration
1045  if(node.isLinkNode())
1046  {
1047  POPTAB;
1048  OUT << "} //end " << node.getValueAsString(true /* returnLinkTableValue */)
1049  << " link record" << __E__;
1050  } // end link closing decoration
1051 
1052 } // end recursiveTreeToFhicl
1053 
1054 //==============================================================================
1058  const std::string& filePath,
1059  const std::string& dumpType,
1060  const std::string& configurationAlias,
1061  const std::string& subsystemCommonList,
1062  const std::string& subsystemCommonOverrideList,
1063  const std::string& logEntry,
1064  const std::string& activeUsers,
1065  const std::string& activeStateMachine,
1066  std::ostream& altOut /* = std::cout */)
1067 {
1068  time_t rawtime = time(0);
1069  __GEN_COUT__ << "filePath = " << filePath << __E__;
1070  __GEN_COUT__ << "dumpType = " << dumpType << __E__;
1071 
1072  std::ofstream fs;
1073  if(filePath != "")
1074  fs.open(filePath, std::fstream::out | std::fstream::trunc);
1075 
1076  std::ostream* out;
1077 
1078  // if file was valid use it, else default to cout
1079  if(fs.is_open())
1080  out = &fs;
1081  else
1082  {
1083  if(filePath != "")
1084  {
1085  __SS__ << "Invalid file path to dump active configuration. File " << filePath
1086  << " could not be opened!" << __E__;
1087  __GEN_COUT_ERR__ << ss.str();
1088  __SS_THROW__;
1089  }
1090  out = &(altOut);
1091  }
1092 
1093  if(dumpType == "JSON All")
1094  {
1095  (*out) << "{\n";
1096  (*out) << "\t\"ARTDAQ_DATABASE_URI\": \"" << __ENV__("ARTDAQ_DATABASE_URI")
1097  << "\"," << __E__;
1098  if(fs.is_open())
1099  {
1100  (*out) << "\t\"HOSTNAME\": \"" << __ENV__("HOSTNAME") << "\"," << __E__;
1101  (*out) << "\t\"HOSTNAME filepath\": \"" << filePath << "\"," << __E__;
1102  (*out) << "\t\"Active State Machine\": \"" << activeStateMachine << "\","
1103  << __E__;
1104  }
1105  (*out) << "\t\"active_users\": \t[";
1106  if(activeUsers.size())
1107  {
1108  std::istringstream iss(activeUsers);
1109  std::string user;
1110  bool first = true;
1111  while(std::getline(iss, user, ','))
1112  {
1113  if(!first)
1114  (*out) << ",";
1115  (*out) << "\n\t\t\"" << user << "\"";
1116  first = false;
1117  }
1118  }
1119  (*out) << "\n\t]," << __E__;
1120  (*out) << "\t\"dump_type\": \t\t\"" << dumpType << "\"," << __E__;
1121  (*out) << "\t\"dump_time\": \t\t\"" << rawtime << "\"," << __E__;
1122  (*out) << "\t\"dump_time_formatted\": \t\t\""
1123  << StringMacros::getTimestampString(rawtime) << "\"," << __E__;
1124  }
1125  else
1126  {
1127  (*out) << "#################################" << __E__;
1128  (*out) << "This is an ots system configuration dump.\n" << __E__;
1129  (*out) << "Source database is $ARTDAQ_DATABASE_URI: "
1130  << __ENV__("ARTDAQ_DATABASE_URI") << __E__;
1131  if(fs.is_open())
1132  (*out) << "Original location of dump: " << __ENV__("HOSTNAME")
1133  << ":" << filePath << __E__;
1134  (*out) << "\nActive ots users: \t"
1135  << (activeUsers.size() ? activeUsers : "no active users") << __E__;
1136  (*out) << "Type of dump: \t\t" << dumpType << __E__;
1137  (*out) << "Time of dump: \t\t" << rawtime;
1138  (*out) << " \t" << StringMacros::getTimestampString(rawtime) << __E__;
1139  }
1140 
1141  //determine configurationAlias tranlation
1142  std::pair<std::string, ots::TableGroupKey> configurationTableGroup =
1143  getTableGroupFromAlias(configurationAlias);
1144 
1145  if(dumpType != "JSON All")
1146  {
1147  (*out) << "Configuration Alias: \t\t\t" << configurationAlias << "\n";
1148  (*out) << "Configuration Alias translation: \t" << configurationTableGroup.first
1149  << "(" << configurationTableGroup.second << ")\n\n";
1150 
1151  if(logEntry.size())
1152  (*out) << "User Log Entry (" << logEntry.size() << " chars):\n"
1153  << logEntry << __E__;
1154  }
1155 
1156  // define local "lambda" functions
1157  // active groups
1158  // active tables
1159  // active group members
1160  // active table contents
1161 
1162  //============================
1163  auto localDumpActiveGroups = [](const ConfigurationManager* cfgMgr,
1164  std::ostream* out,
1165  std::string subsystemCommonList,
1166  std::string subsystemCommonOverrideList,
1167  bool jsonify = false,
1168  std::string configurationAlias = "") {
1169  std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroups =
1170  cfgMgr->getActiveTableGroups();
1171 
1172  if(jsonify)
1173  {
1174  if(!subsystemCommonList.empty())
1175  (*out) << "\n\t\"subsystem_common_table_list\": \"" << subsystemCommonList
1176  << "\"," << __E__;
1177  if(!subsystemCommonOverrideList.empty())
1178  (*out) << "\n\t\"subsystem_common_override_table_list\": \""
1179  << subsystemCommonOverrideList << "\",\n"
1180  << __E__;
1181  (*out) << "\n\t\"groups\": {\n";
1182  }
1183  else
1184  {
1185  (*out) << "Subsystem Common Table List: " << subsystemCommonList << __E__;
1186  (*out) << "Subsystem Common Override Table List: "
1187  << subsystemCommonOverrideList << __E__;
1188  (*out) << "\n\n************************" << __E__;
1189  (*out) << "Active Groups: " << __E__;
1190  }
1191 
1192  std::map<std::string, std::pair<std::string, TableGroupKey>>::iterator it;
1193 
1194  for(it = activeGroups.begin(); it != activeGroups.end(); ++it)
1195  {
1196  if(jsonify)
1197  {
1198  (*out) << "\t\t\"" << it->first << "_group_name\": \"" << it->second.first
1199  << "\",\n";
1200  (*out) << "\t\t\"" << it->first << "_group_key\": \"" << it->second.second
1201  << "\"";
1202  if(it->first == "Configuration")
1203  {
1204  (*out) << ",\n";
1205  (*out) << "\t\t\""
1206  << "Configuration_alias\": \"" << configurationAlias << "\"";
1207  }
1208  (*out) << (std::next(it) == activeGroups.end() ? "" : ",") << "\n";
1209  }
1210  else
1211  {
1212  (*out) << "\t" << it->first << " := " << it->second.first << " ("
1213  << it->second.second << ")" << __E__;
1214  }
1215  }
1216 
1217  if(jsonify)
1218  (*out) << "\t}";
1219  }; //end localDumpActiveGroups()
1220 
1221  //============================
1222  auto localDumpActiveTables = [](const ConfigurationManager* cfgMgr,
1223  std::ostream* out,
1224  bool jsonify = false) {
1225  std::map<std::string, TableVersion> activeTables = cfgMgr->getActiveVersions();
1226 
1227  if(jsonify)
1228  {
1229  (*out) << "\t\"tables\": { " << __E__;
1230  }
1231  else
1232  {
1233  (*out) << "\n\n************************" << __E__;
1234  (*out) << "Active Tables:" << __E__;
1235  (*out) << "Active Tables count = " << activeTables.size() << __E__;
1236  }
1237 
1238  unsigned int i = 0;
1239  std::map<std::string, TableVersion>::iterator it;
1240  for(it = activeTables.begin(); it != activeTables.end(); ++it)
1241  {
1242  if(jsonify)
1243  {
1244  (*out) << "\t\t\""
1245  << "active_table_name"
1246  << "\": \"" << it->first << "\",\n";
1247  (*out) << "\t\t\""
1248  << "active_table_version"
1249  << "\": \"" << it->second << "\"";
1250  (*out) << (std::next(it) == activeTables.end() ? "" : ",") << "\n";
1251  }
1252  else
1253  {
1254  (*out) << "\t" << ++i << ". " << it->first << "-v" << it->second << __E__;
1255  }
1256  }
1257 
1258  if(jsonify)
1259  (*out) << "\t}";
1260  }; //end localDumpActiveTables()
1261 
1262  //============================
1263  auto localDumpActiveGroupMembers = [](ConfigurationManager* cfgMgr,
1264  std::ostream* out,
1265  bool jsonify = false) {
1266  std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroups =
1267  cfgMgr->getActiveTableGroups();
1268 
1269  if(jsonify)
1270  {
1271  (*out) << "\t\"group_members\": { " << __E__;
1272  }
1273  else
1274  {
1275  (*out) << "\n\n************************" << __E__;
1276  (*out) << "Active Group Members:" << __E__;
1277  }
1278 
1279  int tableCount = 0;
1280  std::map<std::string, std::pair<std::string, TableGroupKey>>::iterator it;
1281  for(it = activeGroups.begin(); it != activeGroups.end(); ++it)
1282  {
1283  if(!jsonify)
1284  {
1285  (*out) << "\t" << it->first << " := " << it->second.first << " ("
1286  << it->second.second << ")" << __E__;
1287  }
1288 
1289  if(it->second.first == "")
1290  {
1291  if(!jsonify)
1292  {
1293  (*out) << "\t"
1294  << "Empty group name. Assuming no active group." << __E__;
1295  }
1296  continue;
1297  }
1298 
1299  if(jsonify)
1300  {
1301  (*out) << "\t\t\"" << it->first << "\" : {" << __E__;
1302  (*out) << "\t\t\t\"Name\": \t\"" << it->second.first << "\""
1303  << (std::next(it) == activeGroups.end() ? "" : ",") << __E__;
1304  }
1305 
1306  std::map<std::string /*name*/, TableVersion /*version*/> memberMap;
1307  std::map<std::string /*name*/, std::string /*alias*/> groupAliases;
1308  std::string groupComment;
1309  std::string groupAuthor;
1310  std::string groupCreateTime;
1311  time_t groupCreateTime_t;
1312 
1313  cfgMgr->loadTableGroup(it->second.first,
1314  it->second.second,
1315  false /*doActivate*/,
1316  &memberMap /*memberMap*/,
1317  0 /*progressBar*/,
1318  0 /*accumulateErrors*/,
1319  &groupComment,
1320  &groupAuthor,
1321  &groupCreateTime,
1322  true /*doNotLoadMembers*/,
1323  0 /*groupTypeString*/,
1324  &groupAliases);
1325 
1326  if(jsonify)
1327  {
1328  (*out) << "\t\t\t\"key\": \t\"" << it->second.second << "\"," << __E__;
1329  (*out) << "\t\t\t\"comment\": \t\"" << groupComment << "\"," << __E__;
1330  (*out) << "\t\t\t\"author\": \t\"" << groupAuthor << "\"," << __E__;
1331 
1332  sscanf(groupCreateTime.c_str(), "%ld", &groupCreateTime_t);
1333  std::string timeCreated = ctime(&groupCreateTime_t);
1334  (*out) << "\t\t\t\"create_time\": \t\""
1335  << timeCreated.erase(timeCreated.find('\n', 0), 1) << "\","
1336  << __E__;
1337  (*out) << "\t\t\t\"group_aliases\": \t\""
1338  << StringMacros::mapToString(groupAliases) << "\"," << __E__;
1339 
1340  (*out) << "\t\t\t\"table_count\": \t\"" << memberMap.size() << "\","
1341  << __E__;
1342  tableCount += memberMap.size();
1343 
1344  (*out) << "\t\t\t\"tables\": {" << __E__;
1345 
1346  std::map<std::string /*name*/, TableVersion /*version*/>::iterator
1347  iterMap;
1348  for(iterMap = memberMap.begin(); iterMap != memberMap.end(); ++iterMap)
1349  {
1350  (*out) << "\t\t\t\t\"" << iterMap->first << "\": \""
1351  << iterMap->second << "\""
1352  << (std::next(iterMap) == memberMap.end() ? "" : ",") << __E__;
1353  }
1354  (*out) << "\t\t\t}" << __E__;
1355  (*out) << "\t\t}," << __E__;
1356  }
1357  else
1358  {
1359  (*out) << "\t\tGroup Comment: \t" << groupComment << __E__;
1360  (*out) << "\t\tGroup Author: \t" << groupAuthor << __E__;
1361 
1362  sscanf(groupCreateTime.c_str(), "%ld", &groupCreateTime_t);
1363  (*out) << "\t\tGroup Create Time: \t" << ctime(&groupCreateTime_t)
1364  << __E__;
1365  (*out) << "\t\tGroup Aliases: \t"
1366  << StringMacros::mapToString(groupAliases) << __E__;
1367 
1368  (*out) << "\t\tMember table count = " << memberMap.size() << __E__;
1369  tableCount += memberMap.size();
1370 
1371  unsigned int i = 0;
1372  for(auto& member : memberMap)
1373  {
1374  (*out) << "\t\t\t" << ++i << ". " << member.first << "-v"
1375  << member.second << __E__;
1376  }
1377  }
1378  }
1379 
1380  if(jsonify)
1381  {
1382  (*out) << "\t\"total_table_count\": \"" << tableCount << "\"" << __E__;
1383  (*out) << "\t}";
1384  }
1385  else
1386  {
1387  (*out) << "\nActive Group Members total table count = " << tableCount
1388  << __E__;
1389  }
1390  }; //end localDumpActiveGroupMembers()
1391 
1392  //============================
1393  auto localDumpActiveTableContents = [](const ConfigurationManager* cfgMgr,
1394  std::ostream* out,
1395  bool jsonify = false) {
1396  std::map<std::string, TableVersion> activeTables = cfgMgr->getActiveVersions();
1397 
1398  if(jsonify)
1399  {
1400  (*out) << "\t\"tables\": {" << __E__;
1401  }
1402  else
1403  {
1404  (*out) << "\n\n************************" << __E__;
1405  (*out) << "Active Table Contents (table count = " << activeTables.size()
1406  << "):" << __E__;
1407  }
1408 
1409  unsigned int i = 0;
1410  std::map<std::string, TableVersion>::iterator it;
1411  for(it = activeTables.begin(); it != activeTables.end(); ++it)
1412  {
1413  if(jsonify)
1414  {
1415  __COUTT__ << "localDumpActiveTableContents table: " << it->first << __E__;
1416  auto table = cfgMgr->nameToTableMap_.find(it->first)->second->getViewP();
1417  (*out) << "\t\t\"" << it->first << "-v" << it->second << "\": ";
1418  table->printJSON(*out);
1419  (*out) << (std::next(it) == activeTables.end() ? "" : ",") << __E__;
1420  }
1421  else
1422  {
1423  (*out) << "\n\n=========================================================="
1424  "===="
1425  "================"
1426  << __E__;
1427  (*out) << "=============================================================="
1428  "===="
1429  "============"
1430  << __E__;
1431  (*out) << "\t" << ++i << ". " << it->first << "-v" << it->second << __E__;
1432 
1433  cfgMgr->nameToTableMap_.find(it->first)->second->print(*out);
1434  }
1435  }
1436 
1437  if(jsonify)
1438  {
1439  (*out) << "\t}" << __E__;
1440  }
1441  }; //end localDumpActiveTableContents()
1442 
1443  //============================
1444  auto localDumpActiveTableStructureStatus = [](ConfigurationManager* cfgMgr,
1445  std::ostream* out) {
1446  std::map<std::string, TableVersion> activeTables = cfgMgr->getActiveVersions();
1447 
1448  __COUT__ << "Active Table size: " << activeTables.size() << __E__;
1449  (*out) << "\t\"custom\": {" << __E__;
1450 
1451  std::string activeTableStructure = "";
1452  std::map<std::string, TableVersion>::iterator it;
1453  size_t tableStructureFoundCount = 0;
1454  for(it = activeTables.begin(); it != activeTables.end(); ++it)
1455  {
1456  try
1457  {
1458  __COUTT__ << "Trying to retrieve " << it->first << "-v" << it->second
1459  << " Structure" << __E__;
1460  activeTableStructure =
1461  cfgMgr->nameToTableMap_.find(it->first)->second->getStructureAsJSON(
1462  cfgMgr);
1463  if(activeTableStructure != "")
1464  {
1465  __COUTT__ << "Found Structure for Active Table: " << it->first << "-v"
1466  << it->second << __E__;
1467 
1468  (*out) << (tableStructureFoundCount++ ? "," : "") << __E__;
1469 
1470  (*out) << "\t\"" << it->first << "\": " << __E__;
1471  (*out) << activeTableStructure << __E__;
1472  }
1473  }
1474  catch(const std::exception& e)
1475  {
1476  __COUTT__ << "Error caught in localDumpActiveTableStructureStatus(): "
1477  << e.what();
1478  __COUTT__ << "Structure Status may not be implemented." << __E__;
1479  }
1480  } //end table structure loop
1481 
1482  __COUT__ << "Found " << tableStructureFoundCount << " Active Table Structures."
1483  << __E__;
1484 
1485  (*out) << "\t}" << __E__;
1486  }; //end localDumpActiveTableStructureStatus()
1487 
1488  //============================
1489  auto localDumpSoftwareVersions = [](std::ostream* out, bool jsonFormat = false) {
1490  __COUT__ << "localDumpSoftwareVersions()" << __E__;
1491  std::vector<std::string> entries;
1492 
1493  // collect spack output (split by newlines)
1494  std::map<std::string, std::string> spackPackages;
1495  std::map<std::string, std::string> checkedOutRepos;
1496  std::string environment;
1497 
1498  {
1499  std::string spackOut = StringMacros::exec("spack find");
1500  std::istringstream iss(spackOut);
1501  std::string line;
1502  while(std::getline(iss, line))
1503  {
1504  if(line.empty())
1505  continue;
1506 
1507  // Extract environment name
1508  if(line.find("==> In environment") != std::string::npos)
1509  {
1510  size_t start = line.find("environment ") + 12;
1511  environment = line.substr(start);
1512  }
1513  else if(line[0] != '[' && line[0] != '-' &&
1514  line.find("root specs") == std::string::npos)
1515  {
1516  // Parse spack packages
1517  size_t atPos = line.find('@');
1518  if(atPos != std::string::npos)
1519  {
1520  std::string pkgName = line.substr(0, atPos);
1521  // Remove leading [+] or [^] markers
1522  if(pkgName.find('[') != std::string::npos)
1523  pkgName = pkgName.substr(pkgName.find(']') + 2);
1524  std::string version = line.substr(atPos + 1);
1525  spackPackages[pkgName] = version;
1526  }
1527  else if(line.find('[') == std::string::npos && !line.empty() &&
1528  line[0] != 'c')
1529  {
1530  // Plain package name without version
1531  std::string pkgName = line;
1532  if(pkgName.find('[') != std::string::npos)
1533  pkgName = pkgName.substr(pkgName.find(']') + 2);
1534  spackPackages[pkgName] = "";
1535  }
1536  }
1537  }
1538  }
1539 
1540  // Collect checked out repositories
1541  {
1542  DIR* pDIR;
1543  struct dirent* entry;
1544  bool isDir;
1545  std::string name;
1546  int type;
1547  std::string src = __ENV__("OTS_SOURCE");
1548  if(!(pDIR = opendir((src).c_str())))
1549  {
1550  __SS__ << "Path '" << src << "' could not be opened!" << __E__;
1551  __SS_THROW__;
1552  }
1553  while((entry = readdir(pDIR)))
1554  {
1555  name = std::string(entry->d_name);
1556  type = int(entry->d_type);
1557 
1558  __COUTS__(2) << type << " " << name << "\n" << std::endl;
1559  if(name[0] != '.' &&
1560  (type == 0 || // 0 == UNKNOWN (which can happen - seen in SL7 VM)
1561  type == 4 || // directory type
1562  type == 8 || // file type
1563  type ==
1564  10 // 10 == link (could be directory or file, treat as unknown)
1565  ))
1566  {
1567  isDir = false;
1568 
1569  if(type == 0 || type == 10)
1570  {
1571  // unknown type .. determine if directory
1572  DIR* pTmpDIR = opendir((src + "/" + name).c_str());
1573  if(pTmpDIR)
1574  {
1575  isDir = true;
1576  closedir(pTmpDIR);
1577  }
1578  else //assume file
1579  __COUTS__(2) << "Unable to open path as directory: "
1580  << (src + "/" + name) << __E__;
1581  }
1582 
1583  if(type == 4)
1584  isDir = true; // flag directory types
1585 
1586  // handle directories
1587 
1588  if(isDir)
1589  {
1590  __COUTS__(2) << "Directory: " << type << " " << name << __E__;
1591  std::string describe = StringMacros::exec(
1592  ("cd " + src + "/" + name + "; git describe --tags").c_str());
1593  if(describe.size())
1594  {
1595  // strip trailing newline if any
1596  if(describe.back() == '\n')
1597  describe.pop_back();
1598  checkedOutRepos[name] = describe;
1599  }
1600  }
1601  }
1602  }
1603  closedir(pDIR);
1604  }
1605 
1606  if(jsonFormat)
1607  {
1608  (*out) << "\t\"software_versions\": {" << __E__;
1609 
1610  // Output spack packages
1611  (*out) << "\t\t\"spack\": {" << __E__;
1612  bool first = true;
1613  for(const auto& pkg : spackPackages)
1614  {
1615  if(!first)
1616  (*out) << "," << __E__;
1617  (*out) << "\t\t\t\"" << StringMacros::escapeJSONStringEntities(pkg.first)
1618  << "\": \"" << StringMacros::escapeJSONStringEntities(pkg.second)
1619  << "\"";
1620  first = false;
1621  }
1622  (*out) << __E__ << "\t\t}," << __E__;
1623 
1624  // Output checked out repositories
1625  (*out) << "\t\t\"checked_out\": {" << __E__;
1626  first = true;
1627  for(const auto& repo : checkedOutRepos)
1628  {
1629  if(!first)
1630  (*out) << "," << __E__;
1631  (*out) << "\t\t\t\"" << StringMacros::escapeJSONStringEntities(repo.first)
1632  << "\": \"" << StringMacros::escapeJSONStringEntities(repo.second)
1633  << "\"";
1634  first = false;
1635  }
1636  (*out) << __E__ << "\t\t}," << __E__;
1637 
1638  // Output environment
1639  (*out) << "\t\t\"environment\": \""
1640  << StringMacros::escapeJSONStringEntities(environment) << "\""
1641  << __E__;
1642 
1643  (*out) << "\t}" << __E__;
1644  }
1645  else
1646  {
1647  (*out) << "\n\n\"Software Versions\": {" << __E__;
1648  (*out) << " \"spack\": " << spackPackages.size() << " packages," << __E__;
1649  (*out) << " \"checked_out\": " << checkedOutRepos.size() << " repositories,"
1650  << __E__;
1651  (*out) << " \"environment\": \"" << environment << "\"" << __E__;
1652  (*out) << "}" << __E__;
1653  }
1654  }; //end localDumpSoftwareVersions
1655 
1656  if(dumpType == "Group Keys")
1657  {
1658  localDumpActiveGroups(
1659  this, out, subsystemCommonList, subsystemCommonOverrideList);
1660  }
1661  else if(dumpType == "Table Versions")
1662  {
1663  localDumpActiveTables(this, out);
1664  }
1665  else if(dumpType == "Group Keys and Table Versions")
1666  {
1667  localDumpActiveGroups(
1668  this, out, subsystemCommonList, subsystemCommonOverrideList);
1669  localDumpActiveTables(this, out);
1670  }
1671  else if(dumpType == "All")
1672  {
1673  localDumpActiveGroups(
1674  this, out, subsystemCommonList, subsystemCommonOverrideList);
1675  localDumpActiveGroupMembers(this, out);
1676  localDumpActiveTables(this, out);
1677  localDumpActiveTableContents(this, out);
1678  localDumpSoftwareVersions(out);
1679  }
1680  else if(dumpType == "JSON All")
1681  {
1682  localDumpActiveGroups(this,
1683  out,
1684  subsystemCommonList,
1685  subsystemCommonOverrideList,
1686  true,
1687  configurationAlias);
1688  (*out) << ",\n";
1689  localDumpActiveGroupMembers(this, out, true);
1690  (*out) << ",\n";
1691  //localDumpActiveTables(this, out, true);
1692  //(*out) << ",\n" << __E__;
1693  localDumpActiveTableContents(this, out, true);
1694  (*out) << ",\n" << __E__;
1695  localDumpActiveTableStructureStatus(this, out);
1696  (*out) << ",\n" << __E__;
1697  localDumpSoftwareVersions(out, true);
1698  (*out) << "}\n";
1699  }
1700  else
1701  {
1702  __SS__
1703  << "Invalid dump type '" << dumpType
1704  << "' given during dumpActiveConfiguration(). Valid types are as follows:\n"
1705  <<
1706 
1707  // List all choices (must match accepted dumpType strings)
1708  "Group Keys"
1709  << ", "
1710  << "Table Versions"
1711  << ", "
1712  << "Group Keys and Table Versions"
1713  << ", "
1714  << "All"
1715  << ", "
1716  << "JSON All"
1717  <<
1718 
1719  "\n\nPlease change the State Machine configuration to a valid dump type."
1720  << __E__;
1721  __SS_THROW__;
1722  }
1723 
1724  if(fs.is_open())
1725  fs.close();
1726 
1727 } //end dumpActiveConfiguration()
1728 
1729 //==============================================================================
1736  const std::map<std::string /*name*/, TableVersion /*version*/>& memberMap,
1737  std::string* accumulatedWarnings /* =0 */)
1738 {
1739  __GEN_COUTTV__(runTimeSeconds());
1740 
1741  TableBase* tmpTableBasePtr;
1742 
1743  //detect if using cache, and decide if multi-threading
1744  bool usingCache = false;
1745  if(memberMap.size() > 10 && nameToTableMap_.size() &&
1746  nameToTableMap_.find(memberMap.begin()->first) != nameToTableMap_.end() &&
1747  nameToTableMap_.at(memberMap.begin()->first)->isStored(memberMap.begin()->second))
1748  {
1749  usingCache = true;
1750  }
1751  if(usingCache)
1752  __GEN_COUTT__ << "Using cache!" << __E__;
1753 
1754  //Note: mongodb crashing from too many connections was resolved by increasing ulimit at mongodb launch
1755  // i.e. ulimit -n 64000 && ./start_mongod.sh
1756  const int numOfThreads =
1757  PROCESSOR_COUNT / 2 > memberMap.size() ? (PROCESSOR_COUNT / 2) : memberMap.size();
1758  if(memberMap.size() <= 2 /* i.e. is Context group */ || usingCache ||
1759  numOfThreads < 2) // no multi-threading
1760  {
1761  // for each member
1762  // get()
1763  for(auto& memberPair : memberMap)
1764  {
1765  // if(accumulatedWarnings)
1766  // __GEN_COUT__ << "\tFilling member table " << memberPair.first << ":" <<
1767  // memberPair.second << __E__;
1768 
1769  // get the proper temporary pointer
1770  // use 0 if doesn't exist yet.
1771  // Note: do not want to give nameToTableMap_[memberPair.first]
1772  // in case there is failure in get... (exceptions may be thrown)
1773  // Note: Default constructor is called by Map, i.e.
1774  // nameToTableMap_[memberPair.first] = 0; //create pointer and set to 0
1775  tmpTableBasePtr = nullptr;
1776  if(nameToTableMap_.find(memberPair.first) != nameToTableMap_.end())
1777  tmpTableBasePtr = nameToTableMap_.at(memberPair.first);
1778 
1779  std::string getError = "";
1780  try
1781  {
1782  theInterface_->get(tmpTableBasePtr, // tablePtr
1783  memberPair.first, // tableName
1784  0, // groupKey
1785  0, // groupName
1786  false, // dontFill=false to fill
1787  memberPair.second, // version
1788  false // resetTable
1789  );
1790  }
1791  catch(const std::runtime_error& e)
1792  {
1793  __SS__ << "Failed to load member table '" << memberPair.first << "-v"
1794  << memberPair.second << "' - here is the error: \n\n"
1795  << e.what() << __E__;
1796 
1797  ss << "\nIf the table '" << memberPair.first
1798  << "' should not exist, then please remove it from the group. If it "
1799  "should exist, then it "
1800  << "seems to have a problem; use the Table Editor to fix the table "
1801  "definition, or "
1802  "edit the table content to match the table definition."
1803  << __E__;
1804 
1805  // if accumulating warnings and table view was created, then continue
1806  if(accumulatedWarnings)
1807  getError = ss.str();
1808  else
1809  __SS_ONLY_THROW__;
1810  }
1811  catch(...)
1812  {
1813  __SS__ << "Failed to load member table '" << memberPair.first << " -v"
1814  << memberPair.second << "' due to unknown error!" << __E__;
1815  try
1816  {
1817  throw;
1818  } //one more try to printout extra info
1819  catch(const std::exception& e)
1820  {
1821  ss << "Exception message: " << e.what();
1822  }
1823  catch(...)
1824  {
1825  }
1826 
1827  ss << "\nIf the table '" << memberPair.first
1828  << "' should not exist, then please remove it from the group. If it "
1829  "should exist, then it "
1830  << "seems to have a problem; use the Table Editor to fix the table "
1831  "definition, or "
1832  "edit the table content to match the table definition."
1833  << __E__;
1834 
1835  // if accumulating warnings and table view was created, then continue
1836  if(accumulatedWarnings)
1837  getError = ss.str();
1838  else
1839  __SS_THROW__;
1840  }
1841 
1842  //__GEN_COUT__ << "Checking ptr.. " << (tmpTableBasePtr?"GOOD":"BAD") << __E__;
1843  if(!tmpTableBasePtr)
1844  {
1845  __SS__ << "Null pointer returned for table '" << memberPair.first << " -v"
1846  << memberPair.second << ".' Was the table info deleted?" << __E__;
1847  __GEN_COUT_ERR__ << ss.str();
1848 
1849  nameToTableMap_.erase(memberPair.first);
1850  if(accumulatedWarnings)
1851  {
1852  *accumulatedWarnings += ss.str();
1853  continue;
1854  }
1855  else
1856  __SS_ONLY_THROW__;
1857  }
1858 
1859  nameToTableMap_[memberPair.first] = tmpTableBasePtr;
1860  if(nameToTableMap_[memberPair.first]->getViewP())
1861  {
1862  //__GEN_COUT__ << "Activated version: " <<
1863  // nameToTableMap_[memberPair.first]->getViewVersion() << __E__;
1864 
1865  if(accumulatedWarnings && getError != "")
1866  {
1867  __SS__ << "Error caught during '" << memberPair.first << " -v"
1868  << memberPair.second << "' table retrieval: \n"
1869  << getError << __E__;
1870  __GEN_COUT_ERR__ << ss.str();
1871  *accumulatedWarnings += ss.str();
1872  }
1873  }
1874  else
1875  {
1876  __SS__ << nameToTableMap_[memberPair.first]->getTableName() << " -v"
1877  << memberPair.second << ": View version not activated properly!";
1878  __SS_THROW__;
1879  }
1880  } // end member map loop
1881  }
1882  else //multi-threading
1883  {
1884  __GEN_COUTT__ << " PROCESSOR_COUNT " << PROCESSOR_COUNT << " ==> " << numOfThreads
1885  << " threads for loading member map of size " << memberMap.size()
1886  << __E__;
1887 
1888  int threadsLaunched = 0;
1889  int foundThreadIndex = 0;
1890  std::string threadErrors;
1891  std::mutex threadMutex; // to protect accumulatedWarnings
1892  std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
1893  for(int i = 0; i < numOfThreads; ++i)
1894  threadDone.push_back(std::make_shared<std::atomic<bool>>(true));
1895  std::vector<TableBase*> tmpTableBasePtrs;
1896  for(int i = 0; i < numOfThreads; ++i)
1897  tmpTableBasePtrs.push_back(nullptr);
1898 
1899  for(auto& memberPair : memberMap)
1900  {
1901  if(threadsLaunched >= numOfThreads)
1902  {
1903  //find availableThreadIndex
1904  foundThreadIndex = -1;
1905  while(foundThreadIndex == -1)
1906  {
1907  for(int i = 0; i < numOfThreads; ++i)
1908  if(*(threadDone[i]))
1909  {
1910  foundThreadIndex = i;
1911  break;
1912  }
1913  if(foundThreadIndex == -1)
1914  {
1915  __GEN_COUTT__ << "Waiting for available thread..." << __E__;
1916  usleep(10000);
1917  }
1918  } //end thread search loop
1919  threadsLaunched = numOfThreads - 1;
1920  }
1921  __GEN_COUTT__ << "Starting filling thread... " << foundThreadIndex << " for "
1922  << memberPair.first << " -v" << memberPair.second << __E__;
1923  *(threadDone[foundThreadIndex]) = false;
1924 
1925  // get the proper temporary pointer
1926  // use 0 if doesn't exist yet.
1927  // Note: do not want to give nameToTableMap_[memberPair.first]
1928  // in case there is failure in get... (exceptions may be thrown)
1929  // Note: Default constructor is called by Map, i.e.
1930  // nameToTableMap_[memberPair.first] = 0; //create pointer and set to 0
1931  tmpTableBasePtrs[foundThreadIndex] = nullptr;
1932  if(nameToTableMap_.find(memberPair.first) != nameToTableMap_.end())
1933  tmpTableBasePtrs[foundThreadIndex] = nameToTableMap_.at(memberPair.first);
1934 
1935  std::thread(
1936  [](ConfigurationInterface* theInterface,
1937  std::map<std::string, ots::TableBase*>* theNameToTableMap,
1938  ots::TableBase* theTable,
1939  std::string theTableName,
1940  ots::TableVersion version,
1941  std::string* theThreadErrors,
1942  std::mutex* theThreadMutex,
1943  std::shared_ptr<std::atomic<bool>> theThreadDone) {
1944  ConfigurationManager::fillTableThread(theInterface,
1945  theNameToTableMap,
1946  theTable,
1947  theTableName,
1948  version,
1949  theThreadErrors,
1950  theThreadMutex,
1951  theThreadDone);
1952  },
1953  theInterface_,
1954  &nameToTableMap_,
1955  tmpTableBasePtrs[foundThreadIndex],
1956  memberPair.first,
1957  memberPair.second,
1958  &threadErrors,
1959  &threadMutex,
1960  threadDone[foundThreadIndex])
1961  .detach();
1962 
1963  ++threadsLaunched;
1964  ++foundThreadIndex;
1965  } //end table init thread loop
1966 
1967  //check for all threads done
1968  do
1969  {
1970  foundThreadIndex = -1;
1971  for(int i = 0; i < numOfThreads; ++i)
1972  if(!*(threadDone[i]))
1973  {
1974  foundThreadIndex = i;
1975  break;
1976  }
1977  if(foundThreadIndex != -1)
1978  {
1979  __GEN_COUT_TYPE__(TLVL_DEBUG + 2)
1980  << __COUT_HDR__ << "Waiting for thread to finish... "
1981  << foundThreadIndex << __E__;
1982  usleep(10000);
1983  }
1984  } while(foundThreadIndex != -1); //end thread done search loop
1985  __GEN_COUTT__ << "All threads done." << __E__;
1986 
1987  if(threadErrors != "")
1988  {
1989  __SS__ << "Error identified in threads during loading of member map: \n"
1990  << threadErrors << __E__;
1991  __GEN_COUTT__ << "\n" << ss.str() << __E__;
1992  if(accumulatedWarnings)
1993  *accumulatedWarnings += ss.str();
1994  else
1995  __SS_THROW__;
1996  }
1997  } //end multi-thread handling
1998 
1999  __GEN_COUTT__ << "loadMemberMap end runTimeSeconds()=" << runTimeSeconds() << __E__;
2000 } // end loadMemberMap()
2001 
2002 //==============================================================================
2025  const std::string& groupName,
2026  const TableGroupKey& groupKey,
2027  bool doActivate /*=false*/,
2028  std::map<std::string /*table name*/, TableVersion>*
2029  groupMembers /*=0 , note: db time intensive! */,
2030  ProgressBar* progressBar /*=0*/,
2031  std::string* accumulatedWarnings /*=0*/,
2032  std::string* groupComment /*=0 , note: in metadata */,
2033  std::string* groupAuthor /*=0 , note: in metadata */,
2034  std::string* groupCreateTime /*=0 , note: in metadata */,
2035  bool doNotLoadMembers /*=false*/,
2036  std::string* groupTypeString /*=0 , note: db time intensive! */,
2037  std::map<std::string /*name*/, std::string /*alias*/>*
2038  groupAliases /*=0 , note: in metadata */,
2039  ConfigurationManager::LoadGroupType
2040  groupTypeToLoad /*=ConfigurationManager::LoadGroupType::ALL_TYPES*/,
2041  bool ignoreVersionTracking /*=false*/,
2042  std::map<std::string /* tableName */, TableVersion> mergInTables /*={}*/,
2043  std::map<std::string /* tableName */, TableVersion> overrideTables /*={}*/)
2044 {
2045  // clear to defaults
2046  if(groupComment)
2047  *groupComment = ConfigurationManager::UNKNOWN_INFO;
2048  if(groupAuthor)
2049  *groupAuthor = ConfigurationManager::UNKNOWN_INFO;
2050  if(groupCreateTime)
2051  *groupCreateTime = ConfigurationManager::UNKNOWN_TIME;
2052  if(groupTypeString)
2053  *groupTypeString = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
2054  else
2055  __GEN_COUTT__ << "No group type requested." << __E__;
2056 
2057  // if(groupName == "defaultConfig")
2058  // { //debug active versions
2059  // std::map<std::string, TableVersion> allActivePairs = getActiveVersions();
2060  // for(auto& activePair: allActivePairs)
2061  // {
2062  // __GEN_COUT__ << "Active table = " <<
2063  // activePair.first << "-v" <<
2064  // getTableByName(activePair.first)->getView().getVersion() <<
2065  // __E__;
2066  // }
2067  // }
2068 
2069  // load all members of configuration group
2070  // if doActivate
2071  // determine the type configuration
2072  // deactivate all of that type (invalidate active view)
2073  //
2074  // for each member
2075  // get()
2076  // if doActivate, configBase->init()
2077  //
2078  // if doActivate
2079  // set theConfigurationTableGroup_, theContextTableGroup_, or
2080  // theBackboneTableGroup_ on success
2081 
2082  __GEN_COUTT__ << "Loading Table Group: " << groupName << "(" << groupKey << ")"
2083  << " accumulatedWarnings=" << (accumulatedWarnings ? 1 : 0) << __E__;
2084 
2085  //failing member map load should be an exception!
2086 
2087  std::map<std::string /*name*/, TableVersion /*version*/> memberMap =
2088  theInterface_->getTableGroupMembers(
2089  TableGroupKey::getFullGroupString(groupName, groupKey),
2090  true /*include meta data table*/);
2091 
2092  try
2093  {
2094  if(progressBar)
2095  progressBar->step();
2096 
2097  // remove meta data table and extract info
2098  auto metaTablePair = memberMap.find(TableBase::GROUP_METADATA_TABLE_NAME);
2099  if(metaTablePair != memberMap.end())
2100  {
2101  //only lock metadata table if metadata is needed
2102  if(groupAliases || groupComment || groupAuthor || groupCreateTime)
2103  {
2104  std::lock_guard<std::mutex> lock(metaDataTableMutex_);
2105 
2106  // clear table
2107  while(groupMetadataTable_.getView().getNumberOfRows())
2108  groupMetadataTable_.getViewP()->deleteRow(0);
2109 
2110  // retrieve metadata from database
2111  try
2112  {
2113  theInterface_->fill(&groupMetadataTable_, metaTablePair->second);
2114  }
2115  catch(const std::runtime_error& e)
2116  {
2117  __GEN_COUT_WARN__
2118  << "Failed to load " << groupMetadataTable_.getTableName() << "-v"
2119  << metaTablePair->second << ". Metadata error: " << e.what()
2120  << __E__;
2121  }
2122  catch(...)
2123  {
2124  __GEN_COUT_WARN__
2125  << "Failed to load " << groupMetadataTable_.getTableName() << "-v"
2126  << metaTablePair->second << ". Ignoring unknown metadata error. "
2127  << __E__;
2128  }
2129 
2130  // check that there is only 1 row
2131  if(groupMetadataTable_.getView().getNumberOfRows() != 1)
2132  {
2133  groupMetadataTable_.print();
2134  __GEN_COUT_ERR__ << "Ignoring that groupMetadataTable_ has wrong "
2135  "number of rows for '"
2136  << groupName << "(" << groupKey
2137  << ")!' Must "
2138  "be 1. Going with anonymous defaults."
2139  << __E__;
2140 
2141  // fix metadata table
2142  while(groupMetadataTable_.getViewP()->getNumberOfRows() > 1)
2143  groupMetadataTable_.getViewP()->deleteRow(0);
2144  if(groupMetadataTable_.getViewP()->getNumberOfRows() == 0)
2145  groupMetadataTable_.getViewP()->addRow();
2146  }
2147  else
2148  {
2149  // extract metadata fields
2150 
2151  if(groupAliases)
2153  groupMetadataTable_.getView().getValueAsString(
2154  0, ConfigurationManager::METADATA_COL_ALIASES),
2155  *groupAliases);
2156  if(groupComment)
2157  *groupComment = groupMetadataTable_.getView().getValueAsString(
2158  0, ConfigurationManager::METADATA_COL_COMMENT);
2159  if(groupAuthor)
2160  *groupAuthor = groupMetadataTable_.getView().getValueAsString(
2161  0, ConfigurationManager::METADATA_COL_AUTHOR);
2162  if(groupCreateTime)
2163  *groupCreateTime = groupMetadataTable_.getView().getValueAsString(
2164  0, ConfigurationManager::METADATA_COL_TIMESTAMP);
2165  }
2166  }
2167 
2168  memberMap.erase(metaTablePair); // remove from member map that is returned
2169 
2170  } // end metadata handling
2171  else
2172  {
2173  __GEN_COUTT__ << "Ignoring that groupMetadataTable_ is missing for group '"
2174  << groupName << "(" << groupKey
2175  << "). Going with anonymous defaults." << __E__;
2176  }
2177 
2178  //NEVER modify members based on aliases
2179  // Regarding Member Table Aliases: alias names are tracked in the metadata table,
2180  // however! The group member versions are decided at group save time
2181  // (loadTableGroup should always return the same groupName -> memberMap translation).
2182  // The group member versions do not undergo alias translation at load time (i.e. loadTableGroup).
2183  // The alias map can be retrieved using the groupAliases parameter.
2184  if(0)
2185  {
2186  std::map<std::string, std::string>& aliasMap = *groupAliases;
2187  std::map<std::string /*table*/, std::map<std::string /*alias*/, TableVersion>>
2188  versionAliases;
2189  if(aliasMap.size()) // load version aliases
2190  {
2191  __GEN_COUTV__(StringMacros::mapToString(aliasMap));
2192  versionAliases = ConfigurationManager::getVersionAliases();
2193  __GEN_COUTV__(StringMacros::mapToString(versionAliases));
2194  }
2195 
2196  // convert alias to version
2197  for(auto& aliasPair : aliasMap)
2198  {
2199  // check for alias table in member names
2200  if(memberMap.find(aliasPair.first) != memberMap.end())
2201  {
2202  __GEN_COUT__ << "Group member '" << aliasPair.first
2203  << "' was found in group member map!" << __E__;
2204  __GEN_COUT__ << "Looking for alias '" << aliasPair.second
2205  << "' in active version aliases..." << __E__;
2206 
2207  if(versionAliases.find(aliasPair.first) == versionAliases.end() ||
2208  versionAliases[aliasPair.first].find(aliasPair.second) ==
2209  versionAliases[aliasPair.first].end())
2210  {
2211  __SS__ << "Group '" << groupName << "(" << groupKey
2212  << ")' requires table version alias '" << aliasPair.first
2213  << ":" << aliasPair.second
2214  << ",' which was not found in the active Backbone!"
2215  << __E__;
2216  __SS_ONLY_THROW__;
2217  }
2218 
2219  memberMap[aliasPair.first] =
2220  versionAliases[aliasPair.first][aliasPair.second];
2221  __GEN_COUT__ << "Version alias translated to " << aliasPair.first
2222  << __E__;
2223  }
2224  }
2225  } // end modify members based on aliases
2226 
2227  if(groupMembers)
2228  *groupMembers = memberMap; // copy map for return
2229 
2230  if(progressBar)
2231  progressBar->step();
2232 
2233  ConfigurationManager::GroupType groupType =
2234  ConfigurationManager::GroupType::CONFIGURATION_TYPE;
2235  try
2236  {
2237  if(groupTypeString) // do before exit case
2238  {
2239  groupType = getTypeOfGroup(memberMap);
2240  *groupTypeString = convertGroupTypeToName(groupType);
2241  }
2242  else
2243  __GEN_COUTT__ << "No group type requested." << __E__;
2244 
2245  if(doNotLoadMembers)
2246  return; //this is useful if just getting group metadata
2247 
2248  // if not already done, determine the type configuration group
2249  if(!groupTypeString)
2250  groupType = getTypeOfGroup(memberMap);
2251 
2252  if(groupTypeToLoad ==
2253  ConfigurationManager::LoadGroupType::ONLY_BACKBONE_OR_CONTEXT_TYPES &&
2254  groupType != ConfigurationManager::GroupType::CONTEXT_TYPE &&
2255  groupType != ConfigurationManager::GroupType::BACKBONE_TYPE)
2256  {
2257  __GEN_COUT__ << "Not loading group because it is not of type Context or "
2258  "Backbone (it is type '"
2259  << convertGroupTypeToName(groupType) << "')." << __E__;
2260  return;
2261  }
2262  else if(groupTypeToLoad ==
2263  ConfigurationManager::LoadGroupType::ONLY_BACKBONE_TYPE &&
2264  groupType != ConfigurationManager::GroupType::BACKBONE_TYPE)
2265  {
2266  __GEN_COUT__ << "Not loading group because it is not of type "
2267  "Backbone (it is type '"
2268  << convertGroupTypeToName(groupType) << "')." << __E__;
2269  return;
2270  }
2271 
2272  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
2273  if(doActivate)
2274  __GEN_COUT__
2275  << "------------------------------------- init start \t [for all "
2276  "plug-ins in "
2277  << convertGroupTypeToName(groupType) << " group '" << groupName << "("
2278  << groupKey << ")"
2279  << "']" << __E__;
2280 
2281  if(doActivate)
2282  {
2283  std::string groupToDeactivate =
2284  groupType == ConfigurationManager::GroupType::CONTEXT_TYPE
2285  ? theContextTableGroup_
2286  : (groupType == ConfigurationManager::GroupType::BACKBONE_TYPE
2287  ? theBackboneTableGroup_
2288  : (groupType ==
2289  ConfigurationManager::GroupType::ITERATE_TYPE
2290  ? theIterateTableGroup_
2291  : theConfigurationTableGroup_));
2292 
2293  // deactivate all of that type (invalidate active view)
2294  if(groupToDeactivate != "") // deactivate only if pre-existing group
2295  {
2296  __GEN_COUTT__ << "groupToDeactivate '" << groupToDeactivate
2297  << "' of type " << convertGroupTypeToName(groupType)
2298  << __E__;
2299  destroyTableGroup(groupToDeactivate, true);
2300  }
2301  else
2302  {
2303  //Getting here, is kind of strange:
2304  // - this group may have only been partially loaded before?
2305  __GEN_COUTT__ << "no group to deactivate of type "
2306  << convertGroupTypeToName(groupType) << __E__;
2307  }
2308  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
2309  }
2310 
2311  if(progressBar)
2312  progressBar->step();
2313 
2314  loadMemberMap(memberMap, accumulatedWarnings);
2315 
2316  if(progressBar)
2317  progressBar->step();
2318 
2319  __GEN_COUTT__ << "loadMemberMap() completed." << __E__;
2320 
2321  if(accumulatedWarnings)
2322  {
2323  __GEN_COUTT__ << "Checking chosen group for tree errors... here are the "
2324  "current warnings: "
2325  << *accumulatedWarnings << __E__;
2326 
2327  getChildren(&memberMap, accumulatedWarnings);
2328  if(*accumulatedWarnings != "")
2329  {
2330  __GEN_COUT_WARN__
2331  << "Errors detected while loading Table Group: " << groupName
2332  << "(" << groupKey << "). Ignoring the following errors: "
2333  << "\n"
2334  << *accumulatedWarnings << __E__;
2335  }
2336  __GEN_COUTT__ << "After checking children warnings: "
2337  << *accumulatedWarnings << __E__;
2338  }
2339 
2340  if(progressBar)
2341  progressBar->step();
2342 
2343  __GEN_COUTT__ << "Tree view check complete." << __E__;
2344 
2345  // for each member
2346  // if doActivate, configBase->init()
2347  if(doActivate)
2348  {
2349  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
2350 
2351  if(overrideTables.size())
2352  {
2353  __GEN_COUT__ << "Overriding tables: "
2354  << StringMacros::mapToString(overrideTables) << __E__;
2355 
2356  std::map<std::pair<std::string /*original table*/,
2357  std::string /*original uidB*/>,
2358  std::string /*converted uidB*/>
2359  uidConversionMap;
2360  std::map<std::pair<std::string /*original table*/,
2361  std::pair<std::string /*group linkid*/,
2362  std::string /*original gidB*/>>,
2363  std::string /*converted gidB*/>
2364  groupidConversionMap;
2365 
2366  for(const auto& mergeInPair : overrideTables)
2367  {
2368  if(memberMap.find(mergeInPair.first) == memberMap.end())
2369  {
2370  __GEN_COUT__ << "Skipping override of table '"
2371  << mergeInPair.first << "-v"
2372  << mergeInPair.second
2373  << "' which is not in group " << groupName << "("
2374  << groupKey << ")." << __E__;
2375  continue;
2376  }
2377  __GEN_COUT__ << "Overriding group member table '"
2378  << mergeInPair.first << "' v"
2379  << memberMap.at(mergeInPair.first)
2380  << " with version v" << mergeInPair.second << __E__;
2381 
2382  std::stringstream mergeReport;
2383  TableVersion newVersion =
2384  nameToTableMap_.at(mergeInPair.first)
2385  ->mergeViews(
2387  mergeInPair.first,
2388  memberMap.at(mergeInPair.first))
2389  ->getView() /* sourceViewA */,
2390  getVersionedTableByName(mergeInPair.first,
2391  mergeInPair.second)
2392  ->getView() /* sourceViewB*/,
2393  TableVersion() /* destinationVersion*/,
2394  "override-table",
2395  TableBase::MergeApproach::REPLACE, //mergeApproach
2396  uidConversionMap, //should not used for Replace mode
2397  groupidConversionMap, //should not used for Replace mode
2398  false /* fillRecordConversionMaps */,
2399  true /* applyRecordConversionMaps */,
2400  false /* generateUniqueDataColumns */,
2401  &mergeReport); // dont make destination version the first time
2402 
2403  __GEN_COUTV__(newVersion);
2404  nameToTableMap_.at(mergeInPair.first)->setActiveView(newVersion);
2405  nameToTableMap_.at(mergeInPair.first)
2406  ->getViewP()
2407  ->setComment(nameToTableMap_.at(mergeInPair.first)
2408  ->getView()
2409  .getComment() +
2410  "\n" + mergeReport.str());
2411  __GEN_COUT__ << "Overriding table '" << mergeInPair.first
2412  << "' resulting version v" << newVersion << __E__;
2413  __GEN_COUTV__(mergeReport.str());
2414  } //end merge-in table loop
2415 
2416  __GEN_COUTV__(StringMacros::mapToString(getActiveVersions()));
2417  }
2418 
2419  if(mergInTables.size())
2420  {
2421  __GEN_COUT__ << "Merging-in tables: "
2422  << StringMacros::mapToString(mergInTables) << __E__;
2423 
2424  std::map<std::pair<std::string /*original table*/,
2425  std::string /*original uidB*/>,
2426  std::string /*converted uidB*/>
2427  uidConversionMap;
2428  std::map<std::pair<std::string /*original table*/,
2429  std::pair<std::string /*group linkid*/,
2430  std::string /*original gidB*/>>,
2431  std::string /*converted gidB*/>
2432  groupidConversionMap;
2433 
2434  for(const auto& mergeInPair : mergInTables)
2435  {
2436  if(memberMap.find(mergeInPair.first) == memberMap.end())
2437  {
2438  __GEN_COUT__ << "Skipping merging-in of table '"
2439  << mergeInPair.first << "-v"
2440  << mergeInPair.second
2441  << "' which is not in group " << groupName << "("
2442  << groupKey << ")." << __E__;
2443  continue;
2444  }
2445 
2446  __GEN_COUT__ << "Merging-in group member table '"
2447  << mergeInPair.first << "' v"
2448  << memberMap.at(mergeInPair.first)
2449  << " with version v" << mergeInPair.second << __E__;
2450 
2451  std::stringstream mergeReport;
2452  TableVersion newVersion =
2453  nameToTableMap_.at(mergeInPair.first)
2454  ->mergeViews(
2456  mergeInPair.first,
2457  memberMap.at(mergeInPair.first))
2458  ->getView() /* sourceViewA */,
2459  getVersionedTableByName(mergeInPair.first,
2460  mergeInPair.second)
2461  ->getView() /* sourceViewB*/,
2462  TableVersion() /* destinationVersion*/,
2463  "merge-in-table",
2464  TableBase::MergeApproach::SKIP, //mergeApproach
2465  uidConversionMap, //should not used for Skip mode
2466  groupidConversionMap, //should not used for Skip mode
2467  false /* fillRecordConversionMaps */,
2468  true /* applyRecordConversionMaps */,
2469  false /* generateUniqueDataColumns */,
2470  &mergeReport); // dont make destination version the first time
2471 
2472  __GEN_COUTV__(newVersion);
2473  nameToTableMap_.at(mergeInPair.first)->setActiveView(newVersion);
2474  nameToTableMap_.at(mergeInPair.first)
2475  ->getViewP()
2476  ->setComment(nameToTableMap_.at(mergeInPair.first)
2477  ->getView()
2478  .getComment() +
2479  "\n" + mergeReport.str());
2480  __GEN_COUT__ << "Merging-in table '" << mergeInPair.first
2481  << "' resulting version v" << newVersion << __E__;
2482  __GEN_COUTV__(mergeReport.str());
2483  } //end merge-in table loop
2484 
2485  __GEN_COUTV__(StringMacros::mapToString(getActiveVersions()));
2486  } //end merge-in table handling
2487 
2488  if(progressBar)
2489  progressBar->step();
2490 
2491  const int numOfThreads = PROCESSOR_COUNT / 2;
2492  __GEN_COUTT__ << " PROCESSOR_COUNT " << PROCESSOR_COUNT << " ==> "
2493  << numOfThreads
2494  << " threads for initializing tables for Table Group '"
2495  << groupName << "(" << groupKey << ")'." << __E__;
2496  if(groupType != ConfigurationManager::GroupType::CONFIGURATION_TYPE ||
2497  numOfThreads < 2) // no multi-threading
2498  {
2499  for(auto& memberPair : memberMap)
2500  {
2501  // do NOT allow activating Scratch versions if tracking is ON!
2502  if(!ignoreVersionTracking &&
2503  ConfigurationInterface::isVersionTrackingEnabled() &&
2504  memberPair.second.isScratchVersion())
2505  {
2506  __SS__
2507  << "Error while activating member Table '"
2508  << nameToTableMap_[memberPair.first]->getTableName()
2509  << "-v" << memberPair.second << " for Table Group '"
2510  << groupName << "(" << groupKey
2511  << ")'. When version tracking is enabled, Scratch views"
2512  << " are not allowed! Please only use unique, persistent "
2513  "versions when version tracking is enabled."
2514  << __E__;
2515  __SS_ONLY_THROW__;
2516  }
2517 
2518  // attempt to init using the configuration's specific init
2519  // this could be risky user code, try and catch
2520  try
2521  {
2522  nameToTableMap_.at(memberPair.first)->init(this);
2523  }
2524  catch(std::runtime_error& e)
2525  {
2526  __SS__ << "Error detected calling " << memberPair.first
2527  << ".init()!\n\n " << e.what() << __E__;
2528 
2529  if(accumulatedWarnings)
2530  {
2531  *accumulatedWarnings += ss.str();
2532  }
2533  else
2534  {
2535  ss << StringMacros::stackTrace();
2536  __SS_ONLY_THROW__;
2537  }
2538  }
2539  catch(...)
2540  {
2541  __SS__ << "Unknown Error detected calling "
2542  << memberPair.first << ".init()!\n\n " << __E__;
2543  try
2544  {
2545  throw;
2546  } //one more try to printout extra info
2547  catch(const std::exception& e)
2548  {
2549  ss << "Exception message: " << e.what();
2550  }
2551  catch(...)
2552  {
2553  }
2554  //__SS_THROW__;
2555 
2556  if(accumulatedWarnings)
2557  {
2558  *accumulatedWarnings += ss.str();
2559  }
2560  else // ignore error
2561  __GEN_COUT_WARN__ << ss.str();
2562  }
2563  }
2564  }
2565  else //multi-threading
2566  {
2567  int threadsLaunched = 0;
2568  int foundThreadIndex = 0;
2569  std::string threadErrors;
2570  std::mutex threadMutex; // to protect accumulatedWarnings
2571  std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
2572  for(int i = 0; i < numOfThreads; ++i)
2573  threadDone.push_back(std::make_shared<std::atomic<bool>>(true));
2574 
2575  if(!ignoreVersionTracking &&
2576  ConfigurationInterface::isVersionTrackingEnabled())
2577  for(auto& memberPair : memberMap)
2578  {
2579  // do NOT allow activating Scratch versions if tracking is ON!
2580  if(memberPair.second.isScratchVersion())
2581  {
2582  __SS__
2583  << "Error while activating member Table '"
2584  << nameToTableMap_[memberPair.first]->getTableName()
2585  << "-v" << memberPair.second << " for Table Group '"
2586  << groupName << "(" << groupKey
2587  << ")'. When version tracking is enabled, Scratch "
2588  "views"
2589  << " are not allowed! Please only use unique, "
2590  "persistent "
2591  "versions when version tracking is enabled."
2592  << __E__;
2593  __SS_ONLY_THROW__;
2594  }
2595  }
2596 
2597  for(auto& memberPair : memberMap)
2598  {
2599  if(threadsLaunched >= numOfThreads)
2600  {
2601  //find availableThreadIndex
2602  foundThreadIndex = -1;
2603  while(foundThreadIndex == -1)
2604  {
2605  for(int i = 0; i < numOfThreads; ++i)
2606  if(*(threadDone[i]))
2607  {
2608  foundThreadIndex = i;
2609  break;
2610  }
2611  if(foundThreadIndex == -1)
2612  {
2613  __GEN_COUTT__ << "Waiting for available thread..."
2614  << __E__;
2615  usleep(10000);
2616  }
2617  } //end thread search loop
2618  threadsLaunched = numOfThreads - 1;
2619  }
2620  __GEN_COUTT__ << "Starting init table thread... "
2621  << foundThreadIndex << " for " << memberPair.first
2622  << __E__;
2623  *(threadDone[foundThreadIndex]) = false;
2624 
2625  std::thread(
2626  [](ConfigurationManager* cfgMgr,
2627  ots::TableBase* theTable,
2628  std::string* theThreadErrors,
2629  std::mutex* theThreadMutex,
2630  std::shared_ptr<std::atomic<bool>> theThreadDone) {
2631  ConfigurationManager::initTableThread(cfgMgr,
2632  theTable,
2633  theThreadErrors,
2634  theThreadMutex,
2635  theThreadDone);
2636  },
2637  this,
2638  nameToTableMap_.at(memberPair.first),
2639  &threadErrors,
2640  &threadMutex,
2641  threadDone[foundThreadIndex])
2642  .detach();
2643 
2644  ++threadsLaunched;
2645  ++foundThreadIndex;
2646  } //end table init thread loop
2647 
2648  //check for all threads done
2649  do
2650  {
2651  foundThreadIndex = -1;
2652  for(int i = 0; i < numOfThreads; ++i)
2653  if(!*(threadDone[i]))
2654  {
2655  foundThreadIndex = i;
2656  break;
2657  }
2658  if(foundThreadIndex != -1)
2659  {
2660  __GEN_COUTT__ << "Waiting for thread to finish... "
2661  << foundThreadIndex << __E__;
2662  usleep(10000);
2663  }
2664  } while(foundThreadIndex != -1); //end thread done search loop
2665  __GEN_COUTT__ << "All threads done." << __E__;
2666 
2667  if(threadErrors != "")
2668  {
2669  __SS__ << "Error identified in threads during init of table "
2670  "group: \n"
2671  << threadErrors << __E__;
2672  __GEN_COUTT__ << "\n" << ss.str() << __E__;
2673  if(accumulatedWarnings)
2674  *accumulatedWarnings += ss.str();
2675  else
2676  __SS_THROW__;
2677  }
2678  } //end multi-thread handling
2679 
2680  __GEN_COUTTV__(StringMacros::mapToString(getActiveVersions()));
2681  } //end activate/init of member tables
2682 
2683  if(progressBar)
2684  progressBar->step();
2685 
2686  // if doActivate
2687  // set theConfigurationTableGroup_, theContextTableGroup_, or
2688  // theBackboneTableGroup_ on
2689  // success
2690 
2691  if(doActivate)
2692  {
2693  if(groupType == ConfigurationManager::GroupType::CONTEXT_TYPE) //
2694  {
2695  // __GEN_COUT_INFO__ << "Type=Context, Group loaded: " <<
2696  // groupName
2697  //<<
2698  // "(" << groupKey << ")" << __E__;
2699  theContextTableGroup_ = groupName;
2700  theContextTableGroupKey_ =
2701  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2702  }
2703  else if(groupType == ConfigurationManager::GroupType::BACKBONE_TYPE)
2704  {
2705  // __GEN_COUT_INFO__ << "Type=Backbone, Group loaded: " <<
2706  // groupName <<
2707  // "(" << groupKey << ")" << __E__;
2708  theBackboneTableGroup_ = groupName;
2709  theBackboneTableGroupKey_ =
2710  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2711  }
2712  else if(groupType == ConfigurationManager::GroupType::ITERATE_TYPE)
2713  {
2714  // __GEN_COUT_INFO__ << "Type=Iterate, Group loaded: " <<
2715  // groupName
2716  //<<
2717  // "(" << groupKey << ")" << __E__;
2718  theIterateTableGroup_ = groupName;
2719  theIterateTableGroupKey_ =
2720  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2721  }
2722  else // is theConfigurationTableGroup_
2723  {
2724  // __GEN_COUT_INFO__ << "Type=Configuration, Group loaded: " <<
2725  // groupName <<
2726  // "(" << groupKey << ")" << __E__;
2727  theConfigurationTableGroup_ = groupName;
2728  theConfigurationTableGroupKey_ =
2729  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
2730  }
2731  }
2732 
2733  if(progressBar)
2734  progressBar->step();
2735 
2736  if(doActivate)
2737  __GEN_COUT__
2738  << "------------------------------------- init complete \t [for all "
2739  "plug-ins in "
2740  << convertGroupTypeToName(groupType) << " group '" << groupName << "("
2741  << groupKey << ")"
2742  << "']" << __E__;
2743  } // end failed group load try
2744  catch(...)
2745  {
2746  // save group name and key of failed load attempt
2747  lastFailedGroupLoad_[convertGroupTypeToName(groupType)] =
2748  std::pair<std::string, TableGroupKey>(groupName, TableGroupKey(groupKey));
2749 
2750  try
2751  {
2752  throw;
2753  }
2754  catch(const std::runtime_error& e)
2755  {
2756  __SS__ << "Error occurred while loading table group '" << groupName << "("
2757  << groupKey << ")': \n"
2758  << e.what() << __E__;
2759 
2760  if(accumulatedWarnings)
2761  *accumulatedWarnings += ss.str();
2762  else
2763  __SS_ONLY_THROW__;
2764  }
2765  catch(...)
2766  {
2767  __SS__ << "An unknown error occurred while loading table group '"
2768  << groupName << "(" << groupKey << ")." << __E__;
2769  try
2770  {
2771  throw;
2772  } //one more try to printout extra info
2773  catch(const std::exception& e)
2774  {
2775  ss << "Exception message: " << e.what();
2776  }
2777  catch(...)
2778  {
2779  }
2780  if(accumulatedWarnings)
2781  *accumulatedWarnings += ss.str();
2782  else
2783  __SS_ONLY_THROW__;
2784  }
2785  }
2786 
2787  __GEN_COUTT__ << "loadTableGroup() complete for Table Group '" << groupName << "("
2788  << groupKey << ")'." << __E__;
2789  lastGroupLoad_[convertGroupTypeToName(groupType)] =
2790  std::make_pair(std::make_pair(groupName, TableGroupKey(groupKey)), memberMap);
2791  return;
2792  }
2793  catch(...)
2794  {
2795  __GEN_COUTT__ << "loadTableGroup() failed." << __E__;
2796 
2797  // save group name and key of failed load attempt
2798  lastFailedGroupLoad_[ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN] =
2799  std::pair<std::string, TableGroupKey>(groupName, TableGroupKey(groupKey));
2800 
2801  try
2802  {
2803  throw;
2804  }
2805  catch(const std::runtime_error& e)
2806  {
2807  __SS__ << "Error occurred while loading table group '" << groupName << "("
2808  << groupKey << ")': \n"
2809  << e.what() << __E__;
2810 
2811  if(accumulatedWarnings)
2812  *accumulatedWarnings += ss.str();
2813  else
2814  __SS_ONLY_THROW__;
2815  }
2816  catch(...)
2817  {
2818  __SS__ << "An unknown error occurred while loading table group '" << groupName
2819  << "(" << groupKey << ")." << __E__;
2820  try
2821  {
2822  throw;
2823  } //one more try to printout extra info
2824  catch(const std::exception& e)
2825  {
2826  ss << "Exception message: " << e.what();
2827  }
2828  catch(...)
2829  {
2830  }
2831  __GEN_COUT__ << StringMacros::stackTrace();
2832 
2833  if(accumulatedWarnings)
2834  *accumulatedWarnings += ss.str();
2835  else
2836  __SS_ONLY_THROW__;
2837  }
2838  }
2839 } // end loadTableGroup()
2840 
2841 //==============================================================================
2845  const ConfigurationManager& cacheConfigMgr,
2846  const std::map<std::string, TableVersion>& memberMap,
2847  const std::string& groupName /* = "" */,
2848  const TableGroupKey& groupKey /* = TableGroupKey::Invalid */,
2849  bool doActivate /* = false */,
2850  bool ignoreVersionTracking /* = false */)
2851 {
2852  //Note: mostly copied from onfigurationManager::loadTableGroup()
2853 
2854  // determine the type table group type for activation and to save last loaded types
2855  ConfigurationManager::GroupType groupType = getTypeOfGroup(memberMap);
2856  try
2857  {
2858  if(doActivate)
2859  __GEN_COUT__ << "------------------------------------- cacheCopy init start "
2860  " \t [for all "
2861  "plug-ins in member map"
2862  << "']" << __E__;
2863 
2864  if(doActivate)
2865  {
2866  std::string groupToDeactivate =
2867  groupType == ConfigurationManager::GroupType::CONTEXT_TYPE
2868  ? theContextTableGroup_
2869  : (groupType == ConfigurationManager::GroupType::BACKBONE_TYPE
2870  ? theBackboneTableGroup_
2871  : (groupType == ConfigurationManager::GroupType::ITERATE_TYPE
2872  ? theIterateTableGroup_
2873  : theConfigurationTableGroup_));
2874 
2875  // deactivate all of that type (invalidate active view)
2876  if(groupToDeactivate != "") // deactivate only if pre-existing group
2877  {
2878  //__GEN_COUT__ << "groupToDeactivate '" << groupToDeactivate << "'" <<
2879  // __E__;
2880  destroyTableGroup(groupToDeactivate, true);
2881  }
2882  // else
2883  // {
2884  // //Getting here, is kind of strange:
2885  // // - this group may have only been partially loaded before?
2886  // }
2887  }
2888 
2889  //Now load member map, copied from ConfigurationManager::loadMemberMap
2890  // loadMemberMap(memberMap, accumulatedWarnings);
2891  // for each member
2892  // get()
2893  for(auto& memberPair : memberMap)
2894  {
2895  __GEN_COUTT__ << "Copying " << memberPair.first << "-v" << memberPair.second
2896  << __E__;
2897 
2898  //if table does not exist, create it
2899  if(nameToTableMap_.find(memberPair.first) == nameToTableMap_.end())
2900  {
2901  TableBase* table = 0;
2902  theInterface_->get(table, // configurationPtr
2903  memberPair.first, // tableName
2904  0, // groupKey
2905  0, // groupName
2906  true // dontFill=false to fill
2907  );
2908 
2909  nameToTableMap_[memberPair.first] = table;
2910  }
2911  nameToTableMap_.at(memberPair.first)
2912  ->copyView(cacheConfigMgr.getTableByName(memberPair.first)
2913  ->getView(memberPair.second),
2914  memberPair.second,
2915  cacheConfigMgr.getTableByName(memberPair.first)
2916  ->getView(memberPair.second)
2917  .getAuthor(),
2918  true /* looseColumnMatching */);
2919 
2920  //Note: copyView does not make the new view the active view,
2921  // to make the new view the active view do this:
2922  // nameToTableMap_.at(memberPair.first)->setActiveView(memberPair.second);
2923  } //end member map copy loop
2924  __GEN_COUTT__ << "Done with member copy loop." << __E__;
2925 
2926  // for each member
2927  // if doActivate, configBase->init()
2928  if(doActivate)
2929  {
2930  std::string accumulatedWarnings;
2931  const int numOfThreads = PROCESSOR_COUNT / 2;
2932  __GEN_COUT__ << " PROCESSOR_COUNT " << PROCESSOR_COUNT << " ==> "
2933  << numOfThreads << " threads for initializing tables." << __E__;
2934  if(groupType != ConfigurationManager::GroupType::CONFIGURATION_TYPE ||
2935  numOfThreads < 2) // no multi-threading
2936  {
2937  for(auto& memberPair : memberMap)
2938  {
2939  // do NOT allow activating Scratch versions if tracking is ON!
2940  if(!ignoreVersionTracking &&
2941  ConfigurationInterface::isVersionTrackingEnabled() &&
2942  memberPair.second.isScratchVersion())
2943  {
2944  __SS__ << "Error while activating member Table '"
2945  << nameToTableMap_[memberPair.first]->getTableName()
2946  << "-v" << memberPair.second
2947  << " for member map. When version tracking is enabled, "
2948  "Scratch views"
2949  << " are not allowed! Please only use unique, persistent "
2950  "versions when version tracking is enabled."
2951  << __E__;
2952  __SS_ONLY_THROW__;
2953  }
2954 
2955  // attempt to init using the configuration's specific init
2956  // this could be risky user code, try and catch
2957  try
2958  {
2959  nameToTableMap_.at(memberPair.first)->init(this);
2960  }
2961  catch(std::runtime_error& e)
2962  {
2963  __SS__ << "Error detected calling " << memberPair.first
2964  << ".init()!\n\n " << e.what() << __E__;
2965  accumulatedWarnings += ss.str();
2966  }
2967  catch(...)
2968  {
2969  __SS__ << "Unknown Error detected calling " << memberPair.first
2970  << ".init()!\n\n " << __E__;
2971  try
2972  {
2973  throw;
2974  } //one more try to printout extra info
2975  catch(const std::exception& e)
2976  {
2977  ss << "Exception message: " << e.what();
2978  }
2979  catch(...)
2980  {
2981  }
2982  accumulatedWarnings += ss.str();
2983  }
2984  }
2985  }
2986  else //multi-threading
2987  {
2988  int threadsLaunched = 0;
2989  int foundThreadIndex = 0;
2990  std::mutex threadMutex; // to protect accumulatedWarnings
2991  std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
2992  for(int i = 0; i < numOfThreads; ++i)
2993  threadDone.push_back(std::make_shared<std::atomic<bool>>(true));
2994 
2995  if(!ignoreVersionTracking &&
2996  ConfigurationInterface::isVersionTrackingEnabled())
2997  for(auto& memberPair : memberMap)
2998  {
2999  // do NOT allow activating Scratch versions if tracking is ON!
3000  if(memberPair.second.isScratchVersion())
3001  {
3002  __SS__
3003  << "Error while activating member Table '"
3004  << nameToTableMap_[memberPair.first]->getTableName()
3005  << "-v" << memberPair.second
3006  << " for member map. When version tracking is enabled, "
3007  "Scratch views"
3008  << " are not allowed! Please only use unique, persistent "
3009  "versions when version tracking is enabled."
3010  << __E__;
3011  __SS_ONLY_THROW__;
3012  }
3013  }
3014 
3015  for(auto& memberPair : memberMap)
3016  {
3017  if(threadsLaunched >= numOfThreads)
3018  {
3019  //find availableThreadIndex
3020  foundThreadIndex = -1;
3021  while(foundThreadIndex == -1)
3022  {
3023  for(int i = 0; i < numOfThreads; ++i)
3024  if(*(threadDone[i]))
3025  {
3026  foundThreadIndex = i;
3027  break;
3028  }
3029  if(foundThreadIndex == -1)
3030  {
3031  __GEN_COUTT__ << "Waiting for available thread..."
3032  << __E__;
3033  usleep(10000);
3034  }
3035  } //end thread search loop
3036  threadsLaunched = numOfThreads - 1;
3037  }
3038  __GEN_COUTT__ << "Starting init table thread... " << foundThreadIndex
3039  << " for " << memberPair.first << __E__;
3040  *(threadDone[foundThreadIndex]) = false;
3041 
3042  std::thread(
3043  [](ConfigurationManager* cfgMgr,
3044  ots::TableBase* theTable,
3045  std::string* theAccumulatedWarnings,
3046  std::mutex* theThreadMutex,
3047  std::shared_ptr<std::atomic<bool>> theThreadDone) {
3048  ConfigurationManager::initTableThread(cfgMgr,
3049  theTable,
3050  theAccumulatedWarnings,
3051  theThreadMutex,
3052  theThreadDone);
3053  },
3054  this,
3055  nameToTableMap_.at(memberPair.first),
3056  &accumulatedWarnings,
3057  &threadMutex,
3058  threadDone[foundThreadIndex])
3059  .detach();
3060 
3061  ++threadsLaunched;
3062  ++foundThreadIndex;
3063  } //end table init thread loop
3064 
3065  //check for all threads done
3066  do
3067  {
3068  foundThreadIndex = -1;
3069  for(int i = 0; i < numOfThreads; ++i)
3070  if(!*(threadDone[i]))
3071  {
3072  foundThreadIndex = i;
3073  break;
3074  }
3075  if(foundThreadIndex != -1)
3076  {
3077  __GEN_COUTT__ << "Waiting for thread to finish... "
3078  << foundThreadIndex << __E__;
3079  usleep(10000);
3080  }
3081  } while(foundThreadIndex != -1); //end thread done search loop
3082 
3083  } //end multi-thread handling
3084 
3085  if(accumulatedWarnings != "")
3086  {
3087  __GEN_COUT__ << "Activating the member map after copying cache had the "
3088  "following warnings: "
3089  << accumulatedWarnings << __E__;
3090  }
3091  } //end activate/init of member tables
3092 
3093  // if doActivate
3094  // set theConfigurationTableGroup_, theContextTableGroup_, or
3095  // theBackboneTableGroup_ on
3096  // success
3097 
3098  if(doActivate)
3099  {
3100  if(groupType == ConfigurationManager::GroupType::CONTEXT_TYPE) //
3101  {
3102  // __GEN_COUT_INFO__ << "Type=Context, Group loaded: " <<
3103  // groupName
3104  //<<
3105  // "(" << groupKey << ")" << __E__;
3106  theContextTableGroup_ = groupName;
3107  theContextTableGroupKey_ =
3108  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
3109  }
3110  else if(groupType == ConfigurationManager::GroupType::BACKBONE_TYPE)
3111  {
3112  // __GEN_COUT_INFO__ << "Type=Backbone, Group loaded: " <<
3113  // groupName <<
3114  // "(" << groupKey << ")" << __E__;
3115  theBackboneTableGroup_ = groupName;
3116  theBackboneTableGroupKey_ =
3117  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
3118  }
3119  else if(groupType == ConfigurationManager::GroupType::ITERATE_TYPE)
3120  {
3121  // __GEN_COUT_INFO__ << "Type=Iterate, Group loaded: " <<
3122  // groupName
3123  //<<
3124  // "(" << groupKey << ")" << __E__;
3125  theIterateTableGroup_ = groupName;
3126  theIterateTableGroupKey_ =
3127  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
3128  }
3129  else // is theConfigurationTableGroup_
3130  {
3131  // __GEN_COUT_INFO__ << "Type=Configuration, Group loaded: " <<
3132  // groupName <<
3133  // "(" << groupKey << ")" << __E__;
3134  theConfigurationTableGroup_ = groupName;
3135  theConfigurationTableGroupKey_ =
3136  std::shared_ptr<TableGroupKey>(new TableGroupKey(groupKey));
3137  }
3138  }
3139 
3140  if(doActivate)
3141  __GEN_COUT__ << "------------------------------------- cacheCopy init "
3142  "complete \t [for all "
3143  "plug-ins in member map"
3144  << "']" << __E__;
3145 
3146  __GEN_COUTT__ << "Completed cache copy." << __E__;
3147  if(groupName != "" && !TableGroupKey(groupKey).isInvalid())
3148  lastGroupLoad_[convertGroupTypeToName(groupType)] =
3149  make_pair(make_pair(groupName, TableGroupKey(groupKey)), memberMap);
3150  } // end failed group load try
3151  catch(...)
3152  {
3153  __GEN_COUT__ << "Unknown failure in cache copy." << __E__;
3154  // save group name and key of failed load attempt
3155  lastFailedGroupLoad_[convertGroupTypeToName(groupType)] =
3156  std::pair<std::string, TableGroupKey>(groupName, TableGroupKey(groupKey));
3157  throw;
3158  } //end unknown failure handling
3159 } // end copyTableGroupFromCache()
3160 
3161 //==============================================================================
3162 std::pair<std::string /* groupName */, TableGroupKey>
3163 ConfigurationManager::getGroupOfLoadedTable(const std::string& tableName) const
3164 {
3165  for(const auto& loadedGroup : lastGroupLoad_) //search the loaded group member map
3166  if(loadedGroup.second.second.find(tableName) != loadedGroup.second.second.end())
3167  return loadedGroup.second.first; //found! so return group name/key
3168  return std::make_pair("", TableGroupKey(TableGroupKey::INVALID));
3169 } // end getGroupOfLoadedTable()
3170 
3171 //==============================================================================
3173 void ConfigurationManager::initTableThread(ConfigurationManager* cfgMgr,
3174  ots::TableBase* table,
3175  std::string* threadErrors,
3176  std::mutex* threadMutex,
3177  std::shared_ptr<std::atomic<bool>> threadDone)
3178 try
3179 {
3180  __COUTT__ << "Thread init of " << table->getTableName() << "-v"
3181  << table->getViewVersion() << " threadErrors=" << (threadErrors ? 1 : 0)
3182  << __E__;
3183 
3184  // attempt to init using the configuration's specific init
3185  // this could be risky user code, try and catch
3186  try
3187  {
3188  __COUTTV__(StringMacros::mapToString(cfgMgr->getActiveVersions()));
3189  table->init(cfgMgr);
3190  }
3191  catch(std::runtime_error& e)
3192  {
3193  __SS__ << "Error detected calling " << table->getTableName() << ".init()!\n\n "
3194  << e.what() << __E__;
3195 
3196  if(threadErrors)
3197  {
3198  std::lock_guard<std::mutex> lock(*threadMutex);
3199  *threadErrors += ss.str();
3200  }
3201  else
3202  {
3203  ss << StringMacros::stackTrace();
3204  __SS_ONLY_THROW__;
3205  }
3206  }
3207  catch(...)
3208  {
3209  __SS__ << "Unknown Error detected calling " << table->getTableName()
3210  << ".init()!\n\n " << __E__;
3211  try
3212  {
3213  throw;
3214  } //one more try to printout extra info
3215  catch(const std::exception& e)
3216  {
3217  ss << "Exception message: " << e.what();
3218  }
3219  catch(...)
3220  {
3221  }
3222 
3223  ss << StringMacros::stackTrace();
3224 
3225  if(threadErrors)
3226  {
3227  std::lock_guard<std::mutex> lock(*threadMutex);
3228  *threadErrors += ss.str();
3229  }
3230  else
3231  __SS_ONLY_THROW__;
3232  }
3233 
3234  *(threadDone) = true;
3235 } // end initTableThread()
3236 catch(...)
3237 {
3238  __SS__ << "Error occurred initializing table '" << table->getTableName() << "-v"
3239  << table->getViewVersion() << "'..." << __E__;
3240  try
3241  {
3242  throw;
3243  }
3244  catch(const std::runtime_error& e)
3245  {
3246  ss << " Run-time Exception message: " << e.what();
3247  }
3248  catch(const std::exception& e)
3249  {
3250  ss << " Exception message: " << e.what();
3251  }
3252  __COUT_WARN__ << ss.str() << __E__;
3253 
3254  if(threadErrors)
3255  {
3256  std::lock_guard<std::mutex> lock(*threadMutex);
3257  *threadErrors += ss.str();
3258  }
3259 
3260  *(threadDone) = true;
3261 } // end initTableThread catch
3262 
3263 //==============================================================================
3265 void ConfigurationManager::fillTableThread(
3266  ConfigurationInterface* theInterface,
3267  std::map<std::string, ots::TableBase*>* nameToTableMap,
3268  ots::TableBase* table,
3269  std::string tableName,
3270  ots::TableVersion version,
3271  std::string* threadErrors,
3272  std::mutex* threadMutex,
3273  std::shared_ptr<std::atomic<bool>> threadDone)
3274 try
3275 {
3276  __COUTT__ << "Thread fill of " << tableName << "-v" << version << __E__;
3277 
3278  // std::map<std::string, ots::TableBase *> n;
3279  // std::map<std::string, ots::TableBase *>*nameToTableMap = &n;
3280  // ots::TableBase* table;
3281  // // ots::TableVersion v;
3282  // // ots::TableVersion* version = &v;
3283  // std::string a;
3284  // std::string* accumulatedWarnings = &a;
3285  // std::string tableName = "";
3286  std::string getError = "";
3287  // attempt to init using the configuration's specific init
3288  // this could be risky user code, try and catch
3289  try
3290  {
3291  theInterface->get(table, // tablePtr
3292  tableName, // tableName
3293  0, // groupKey
3294  0, // groupName
3295  false, // dontFill=false to fill
3296  version, // version
3297  false // resetTable
3298  );
3299  }
3300  catch(const std::runtime_error& e)
3301  {
3302  __SS__ << "Failed to load member table '" << tableName << "-v" << version
3303  << "' - here is the error: \n\n"
3304  << e.what() << __E__;
3305 
3306  ss << "\nIf the table '" << tableName
3307  << "' should not exist, then please remove it from the group. If it "
3308  "should exist, then it "
3309  << "seems to have a problem; use the Table Editor to fix the table "
3310  "definition, or "
3311  "edit the table content to match the table definition."
3312  << __E__;
3313 
3314  // if accumulating warnings and table view was created, then continue
3315  if(threadErrors)
3316  getError = ss.str();
3317  else
3318  __SS_ONLY_THROW__;
3319  }
3320  catch(...)
3321  {
3322  __SS__ << "Failed to load member table '" << tableName << "-v" << version
3323  << "' due to unknown error!" << __E__;
3324  try
3325  {
3326  throw;
3327  } //one more try to printout extra info
3328  catch(const std::exception& e)
3329  {
3330  ss << "Exception message: " << e.what();
3331  }
3332  catch(...)
3333  {
3334  }
3335  ss << "\nIf the table '" << tableName
3336  << "' should not exist, then please remove it from the group. If it "
3337  "should exist, then it "
3338  << "seems to have a problem; use the Table Editor to fix the table "
3339  "definition, or "
3340  "edit the table content to match the table definition."
3341  << __E__;
3342 
3343  // if accumulating warnings and table view was created, then continue
3344  if(threadErrors)
3345  getError = ss.str();
3346  else
3347  __SS_THROW__;
3348  }
3349 
3350  if(getError != "")
3351  __COUTV__(getError);
3352 
3353  __COUT_TYPE__(TLVL_TRACE + 1)
3354  << __COUT_HDR__ << "Checking ptr.. " << (table ? "GOOD" : "BAD") << __E__;
3355  if(!table)
3356  {
3357  __SS__ << "Null pointer returned for table '" << tableName
3358  << ".' Was the table info deleted?" << __E__;
3359  __COUT_ERR__ << ss.str();
3360 
3361  std::lock_guard<std::mutex> lock(*threadMutex);
3362  nameToTableMap->erase(tableName);
3363 
3364  if(threadErrors)
3365  {
3366  *threadErrors += ss.str();
3367  *(threadDone) = true;
3368  return;
3369  }
3370  else
3371  __SS_ONLY_THROW__;
3372  }
3373  else
3374  {
3375  std::lock_guard<std::mutex> lock(*threadMutex);
3376  (*nameToTableMap)[tableName] = table;
3377  }
3378 
3379  if(nameToTableMap->at(tableName)->getViewP())
3380  {
3381  __COUT_TYPE__(TLVL_TRACE + 1)
3382  << __COUT_HDR__
3383  << "Activated version: " << nameToTableMap->at(tableName)->getViewVersion()
3384  << __E__;
3385 
3386  if(threadErrors && getError != "")
3387  {
3388  __SS__ << "Error caught during '" << tableName << "' table retrieval: \n"
3389  << getError << __E__;
3390  __COUT_ERR__ << ss.str();
3391  std::lock_guard<std::mutex> lock(*threadMutex);
3392  *threadErrors += ss.str();
3393  }
3394  }
3395  else
3396  {
3397  __SS__ << tableName << ": View version not activated properly!";
3398  __SS_THROW__;
3399  }
3400 
3401  __COUTT__ << "end Thread fill of " << tableName << "-v" << version << __E__;
3402  *(threadDone) = true;
3403 } // end fillTableThread()
3404 catch(const std::runtime_error& e)
3405 {
3406  __SS__ << "Error occurred filling table '" << tableName << "-v" << version
3407  << "': " << e.what() << __E__;
3408  __COUT_ERR__ << ss.str();
3409 
3410  if(threadErrors)
3411  {
3412  std::lock_guard<std::mutex> lock(*threadMutex);
3413  *threadErrors += ss.str();
3414  }
3415 
3416  *(threadDone) = true;
3417 }
3418 catch(...)
3419 {
3420  __SS__ << "Unknwon error occurred filling table '" << tableName << "-v" << version
3421  << "'..." << __E__;
3422  try
3423  {
3424  throw;
3425  } //one more try to printout extra info
3426  catch(const std::exception& e)
3427  {
3428  ss << "Exception message: " << e.what();
3429  }
3430  catch(...)
3431  {
3432  }
3433  __COUT_ERR__ << ss.str();
3434 
3435  if(threadErrors)
3436  {
3437  std::lock_guard<std::mutex> lock(*threadMutex);
3438  *threadErrors += ss.str();
3439  }
3440 
3441  *(threadDone) = true;
3442 } // end fillTableThread catch
3443 
3444 //==============================================================================
3450  const std::string& tableName,
3451  TableVersion version,
3452  bool looseColumnMatching /* = false */,
3453  std::string* accumulatedErrors /* = 0 */,
3454  bool getRawData /* = false */,
3455  bool touchLastAccessTime /* = true */)
3456 {
3457  auto it = nameToTableMap_.find(tableName);
3458  if(it == nameToTableMap_.end())
3459  {
3460  __SS__ << "\nCan not find table named '" << tableName
3461  << "'\n\n\n\nYou need to load the table before it can be used."
3462  << "It probably is missing from the member list of the Table "
3463  "Group that was loaded?\n\n\n\n\n"
3464  << __E__;
3465  __SS_THROW__;
3466  }
3467  TableBase* table = it->second;
3468 
3469  if(version.isTemporaryVersion())
3470  {
3471  table->setActiveView(version);
3472 
3473  if(getRawData)
3474  {
3475  std::stringstream jsonSs;
3476  table->getViewP()->printJSON(jsonSs);
3477  table->getViewP()->doGetSourceRawData(true);
3478  table->getViewP()->fillFromJSON(jsonSs.str());
3479  }
3480  }
3481  else
3482  {
3483  theInterface_->get(table,
3484  tableName,
3485  0 /* groupKey */,
3486  0 /* groupName */,
3487  false /* dontFill */, // false to fill w/version
3488  version,
3489  false /* resetConfiguration*/, // false to not reset
3490  looseColumnMatching,
3491  getRawData,
3492  accumulatedErrors,
3493  touchLastAccessTime);
3494  }
3495  return table;
3496 } // end getVersionedTableByName()
3497 
3498 //==============================================================================
3504 std::map<std::string, std::pair<std::string, TableGroupKey>>
3506 {
3507  // map<type, pair <groupName , TableGroupKey> >
3508  std::map<std::string, std::pair<std::string, TableGroupKey>> retMap;
3509 
3510  retMap[ConfigurationManager::GROUP_TYPE_NAME_CONTEXT] =
3511  std::pair<std::string, TableGroupKey>(
3512  theContextTableGroup_,
3513  theContextTableGroupKey_ ? *theContextTableGroupKey_ : TableGroupKey());
3514  retMap[ConfigurationManager::GROUP_TYPE_NAME_BACKBONE] =
3515  std::pair<std::string, TableGroupKey>(
3516  theBackboneTableGroup_,
3517  theBackboneTableGroupKey_ ? *theBackboneTableGroupKey_ : TableGroupKey());
3518  retMap[ConfigurationManager::GROUP_TYPE_NAME_ITERATE] =
3519  std::pair<std::string, TableGroupKey>(
3520  theIterateTableGroup_,
3521  theIterateTableGroupKey_ ? *theIterateTableGroupKey_ : TableGroupKey());
3522  retMap[ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION] =
3523  std::pair<std::string, TableGroupKey>(theConfigurationTableGroup_,
3524  theConfigurationTableGroupKey_
3525  ? *theConfigurationTableGroupKey_
3526  : TableGroupKey());
3527  return retMap;
3528 } // end getActiveTableGroups()
3529 
3530 //==============================================================================
3531 const std::string& ConfigurationManager::getActiveGroupName(
3532  const ConfigurationManager::GroupType& type) const
3533 {
3534  if(type == ConfigurationManager::GroupType::CONFIGURATION_TYPE)
3535  return theConfigurationTableGroup_;
3536  else if(type == ConfigurationManager::GroupType::CONTEXT_TYPE)
3537  return theContextTableGroup_;
3538  else if(type == ConfigurationManager::GroupType::BACKBONE_TYPE)
3539  return theBackboneTableGroup_;
3540  else if(type == ConfigurationManager::GroupType::ITERATE_TYPE)
3541  return theIterateTableGroup_;
3542 
3543  __SS__ << "IMPOSSIBLE! Invalid type requested '" << (int)type << "'" << __E__;
3544  __SS_THROW__;
3545 } // end getActiveGroupName()
3546 
3547 //==============================================================================
3548 TableGroupKey ConfigurationManager::getActiveGroupKey(
3549  const ConfigurationManager::GroupType& type) const
3550 {
3551  if(type == ConfigurationManager::GroupType::CONFIGURATION_TYPE)
3552  return theConfigurationTableGroupKey_ ? *theConfigurationTableGroupKey_
3553  : TableGroupKey();
3554  else if(type == ConfigurationManager::GroupType::CONTEXT_TYPE)
3555  return theContextTableGroupKey_ ? *theContextTableGroupKey_ : TableGroupKey();
3556  else if(type == ConfigurationManager::GroupType::BACKBONE_TYPE)
3557  return theBackboneTableGroupKey_ ? *theBackboneTableGroupKey_ : TableGroupKey();
3558  else if(type == ConfigurationManager::GroupType::ITERATE_TYPE)
3559  return theIterateTableGroupKey_ ? *theIterateTableGroupKey_ : TableGroupKey();
3560 
3561  __SS__ << "IMPOSSIBLE! Invalid type requested '" << (int)type << "'" << __E__;
3562  __SS_THROW__;
3563 } // end getActiveGroupKey()
3564 
3565 //==============================================================================
3566 ConfigurationTree ConfigurationManager::getContextNode(
3567  const std::string& contextUID, const std::string& /*applicationUID*/) const
3568 {
3569  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
3570  contextUID);
3571 } // end getContextNode()
3572 
3573 //==============================================================================
3574 ConfigurationTree ConfigurationManager::getSupervisorNode(
3575  const std::string& contextUID, const std::string& applicationUID) const
3576 {
3577  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
3578  contextUID + "/LinkToApplicationTable/" + applicationUID);
3579 } // end getSupervisorNode()
3580 
3581 //==============================================================================
3582 ConfigurationTree ConfigurationManager::getSupervisorTableNode(
3583  const std::string& contextUID, const std::string& applicationUID) const
3584 {
3585  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
3586  contextUID + "/LinkToApplicationTable/" + applicationUID +
3587  "/LinkToSupervisorTable");
3588 } // end getSupervisorTableNode()
3589 
3590 //==============================================================================
3593 {
3594  auto contextChildren =
3595  getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName())
3596  .getChildren();
3597  for(const auto& contextChild : contextChildren)
3598  {
3599  auto appChildren = contextChild.second.getNode("LinkToApplicationTable")
3600  .getChildren(); //colContext_.colLinkToApplicationTable_
3601  for(const auto& appChild : appChildren)
3602  {
3603  if(appChild.second.getNode("Class").getValue() ==
3604  "ots::GatewaySupervisor") //colApplication_.colClass_ ... XDAQContextTable::GATEWAY_SUPERVISOR_CLASS)
3605  return appChild.second;
3606  }
3607  }
3608  __SS__ << "No Gateway Supervisor node found!" << __E__;
3609  __SS_THROW__;
3610 } // end getGatewaySupervisorNode()
3611 
3612 //==============================================================================
3613 ConfigurationTree ConfigurationManager::getNode(const std::string& nodeString,
3614  bool doNotThrowOnBrokenUIDLinks) const
3615 {
3616  // __GEN_COUT__ << "nodeString=" << nodeString << " len=" << nodeString.length() << __E__;
3617 
3618  // get nodeName (in case of / syntax)
3619  if(nodeString.length() < 1)
3620  {
3621  __SS__ << ("Invalid empty node name") << __E__;
3622  __GEN_SS_THROW__;
3623  }
3624 
3625  // ignore multiple starting slashes
3626  size_t startingIndex = 0;
3627  while(startingIndex < nodeString.length() && nodeString[startingIndex] == '/')
3628  ++startingIndex;
3629  size_t endingIndex = nodeString.find('/', startingIndex);
3630  if(endingIndex == std::string::npos)
3631  endingIndex = nodeString.length();
3632 
3633  std::string nodeName = nodeString.substr(startingIndex, endingIndex - startingIndex);
3634  // __GEN_COUT__ << "nodeName=" << nodeName << " len" << nodeName.length() << __E__;
3635  if(nodeName.length() < 1)
3636  {
3637  // return root node
3638  return ConfigurationTree(this, 0);
3639 
3640  // __SS__ << "Invalid node name: " << nodeName << __E__;
3641  // __GEN_COUT_ERR__ << ss.str();
3642  // __SS_THROW__;
3643  }
3644  ++endingIndex;
3645  std::string childPath =
3646  (endingIndex >= nodeString.length() ? "" : nodeString.substr(endingIndex));
3647 
3648  // __GEN_COUT__ << "childPath=" << childPath << " len=" << childPath.length() << " endingIndex=" << endingIndex << " nodeString.length()=" << nodeString.length() << __E__;
3649 
3650  ConfigurationTree configTree(this, getTableByName(nodeName));
3651 
3652  if(childPath.length() > 1)
3653  return configTree.getNode(childPath, doNotThrowOnBrokenUIDLinks);
3654  else
3655  return configTree;
3656 } // end getNode()
3657 
3658 //==============================================================================
3659 std::map<std::string, ConfigurationTree> ConfigurationManager::getNodes(
3660  const std::string& nodeString) const
3661 {
3662  return getNode(nodeString).getChildrenMap();
3663 }
3664 
3665 //==============================================================================
3668  const ConfigurationTree& /*node*/, const std::string& /*startPath*/) const
3671 {
3672  std::string path = "/";
3673  return path;
3674 } // end getFirstPathToNode()
3675 
3676 //==============================================================================
3682 std::vector<std::pair<std::string, ConfigurationTree>> ConfigurationManager::getChildren(
3683  std::map<std::string, TableVersion>* memberMap,
3684  std::string* accumulatedTreeErrors) const
3685 {
3686  std::vector<std::pair<std::string, ConfigurationTree>> retVector;
3687 
3688  // if(accumulatedTreeErrors)
3689  // *accumulatedTreeErrors = "";
3690 
3691  bool filtering = memberMap && memberMap->size();
3692 
3693  //from root node, want active tables:
3694  for(auto& tablePair : nameToTableMap_)
3695  {
3696  if(filtering)
3697  {
3698  //if not in member map, ignore
3699  if(memberMap->find(tablePair.first) == memberMap->end())
3700  continue;
3701 
3702  //if in member map, and not active - that is a problem!
3703  try
3704  {
3705  if(!tablePair.second->isActive())
3706  {
3707  __SS__ << "Get Children with member map requires a child '"
3708  << tablePair.first << "' that is not active!" << __E__;
3709  __SS_THROW__;
3710  }
3711  }
3712  catch(const std::runtime_error& e)
3713  {
3714  if(accumulatedTreeErrors)
3715  {
3716  *accumulatedTreeErrors += e.what();
3717  __GEN_COUT_ERR__ << "Skipping " << tablePair.first
3718  << " since the table "
3719  "is not active."
3720  << __E__;
3721  continue;
3722  }
3723  throw;
3724  }
3725  }
3726 
3727  if(!tablePair.second->isActive()) // only consider if active
3728  continue;
3729 
3730  ConfigurationTree newNode(this, tablePair.second);
3731  if(accumulatedTreeErrors) // check for disconnects
3732  {
3733  try
3734  {
3735  std::vector<std::pair<std::string, ConfigurationTree>> newNodeChildren =
3736  newNode.getChildren();
3737  for(auto& newNodeChild : newNodeChildren)
3738  {
3739  if(newNodeChild.second.getTableName() ==
3740  ConfigurationManager::DESKTOP_ICON_TABLE_NAME &&
3741  !newNodeChild.second.isEnabled())
3742  continue; //skip check for Desktop Icons that are disabled.
3743 
3744  std::vector<std::pair<std::string, ConfigurationTree>>
3745  twoDeepChildren = newNodeChild.second.getChildren();
3746 
3747  for(auto& twoDeepChild : twoDeepChildren)
3748  {
3749  //__GEN_COUT__ << tablePair.first << " " <<
3750  // newNodeChild.first << " " << twoDeepChild.first
3751  // << __E__;
3752  if(twoDeepChild.second.isLinkNode() &&
3753  twoDeepChild.second.isDisconnected() &&
3754  twoDeepChild.second.getDisconnectedTableName() !=
3755  TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3756  {
3757  __SS__ << "At node '" + tablePair.first +
3758  "' with entry UID '" + newNodeChild.first +
3759  "' there is a disconnected child node at link "
3760  "column '" +
3761  twoDeepChild.first + "'" +
3762  " that points to table named '" +
3763  twoDeepChild.second.getDisconnectedTableName() +
3764  "' ...";
3765  *accumulatedTreeErrors += ss.str();
3766  }
3767  }
3768  }
3769  }
3770  catch(std::runtime_error& e)
3771  {
3772  __SS__ << "At node '" + tablePair.first +
3773  "' error detected descending through children:\n" +
3774  e.what();
3775  *accumulatedTreeErrors += ss.str();
3776  }
3777  } // done checking for disconnects
3778 
3779  retVector.push_back(
3780  std::pair<std::string, ConfigurationTree>(tablePair.first, newNode));
3781  } //end active table loop
3782 
3783  return retVector;
3784 } // end getChildren()
3785 
3786 //==============================================================================
3792 std::map<std::string /* childName */, ConfigurationTree>
3793 ConfigurationManager::getChildrenMap(std::map<std::string, TableVersion>* memberMap,
3794  std::string* accumulatedTreeErrors) const
3795 {
3796  std::map<std::string /* childName */, ConfigurationTree> retMap;
3797 
3798  // if(accumulatedTreeErrors)
3799  // *accumulatedTreeErrors = "";
3800 
3801  bool filtering = memberMap && memberMap->size();
3802 
3803  //from root node, want active tables:
3804  for(auto& tablePair : nameToTableMap_)
3805  {
3806  if(filtering)
3807  {
3808  //if not in member map, ignore
3809  if(memberMap->find(tablePair.first) == memberMap->end())
3810  continue;
3811 
3812  //if in member map, and not active - that is a problem!
3813  try
3814  {
3815  if(!tablePair.second->isActive())
3816  {
3817  __SS__ << "Get Children with member map requires a child '"
3818  << tablePair.first << "' that is not active!" << __E__;
3819  __SS_THROW__;
3820  }
3821  }
3822  catch(const std::runtime_error& e)
3823  {
3824  if(accumulatedTreeErrors)
3825  {
3826  *accumulatedTreeErrors += e.what();
3827  __GEN_COUT_ERR__ << "Skipping " << tablePair.first
3828  << " since the table "
3829  "is not active."
3830  << __E__;
3831  continue;
3832  }
3833  throw;
3834  }
3835  }
3836 
3837  if(!tablePair.second->isActive()) // only consider if active
3838  continue;
3839 
3840  ConfigurationTree newNode(this, tablePair.second);
3841  if(accumulatedTreeErrors) // check for disconnects
3842  {
3843  try
3844  {
3845  std::vector<std::pair<std::string, ConfigurationTree>> newNodeChildren =
3846  newNode.getChildren();
3847  for(auto& newNodeChild : newNodeChildren)
3848  {
3849  if(newNodeChild.second.getTableName() ==
3850  ConfigurationManager::DESKTOP_ICON_TABLE_NAME &&
3851  !newNodeChild.second.isEnabled())
3852  continue; //skip check for Desktop Icons that are disabled.
3853 
3854  std::vector<std::pair<std::string, ConfigurationTree>>
3855  twoDeepChildren = newNodeChild.second.getChildren();
3856 
3857  for(auto& twoDeepChild : twoDeepChildren)
3858  {
3859  //__GEN_COUT__ << tablePair.first << " " <<
3860  // newNodeChild.first << " " << twoDeepChild.first
3861  // << __E__;
3862  if(twoDeepChild.second.isLinkNode() &&
3863  twoDeepChild.second.isDisconnected() &&
3864  twoDeepChild.second.getDisconnectedTableName() !=
3865  TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3866  {
3867  __SS__ << "At node '" + tablePair.first +
3868  "' with entry UID '" + newNodeChild.first +
3869  "' there is a disconnected child node at link "
3870  "column '" +
3871  twoDeepChild.first + "'" +
3872  " that points to table named '" +
3873  twoDeepChild.second.getDisconnectedTableName() +
3874  "' ...";
3875  *accumulatedTreeErrors += ss.str();
3876  }
3877  }
3878  }
3879  }
3880  catch(std::runtime_error& e)
3881  {
3882  __SS__ << "At node '" + tablePair.first +
3883  "' error detected descending through children:\n" +
3884  e.what();
3885  *accumulatedTreeErrors += ss.str();
3886  }
3887  } // done checking for disconnects
3888 
3889  retMap.emplace(
3890  std::pair<std::string, ConfigurationTree>(tablePair.first, newNode));
3891  } //end active table loop
3892 
3893  return retMap;
3894 } // end getChildrenMap()
3895 
3896 //==============================================================================
3901 const TableBase* ConfigurationManager::getTableByName(const std::string& tableName) const
3902 {
3903  std::map<std::string, TableBase*>::const_iterator it;
3904  if((it = nameToTableMap_.find(tableName)) == nameToTableMap_.end())
3905  {
3906  __SS__ << "Cannot find table named '" << tableName
3907  << "' - you need to load the table before it can be used.";
3908 
3909  if(nameToTableMap_.size() == 0)
3910  ss << "\n\nAll tables are missing. Your configuration database connection "
3911  "may have been interrupted. Did an ssh tunnel disconnect?"
3912  << __E__;
3913  else
3914  {
3915  if(tableName == XDAQ_CONTEXT_TABLE_NAME)
3916  ss << "\n\nThe XDAQ Context Table is essential to the operation of ots. "
3917  "Without it, ots can not determine which applications are running "
3918  "on which hosts. Make sure that you have loaded a valid "
3919  "Configuration Context group that contains the XDAQ Context "
3920  "Table."
3921  << __E__;
3922  else
3923  ss << " It is likely missing from the member list of the Table "
3924  "Group that was loaded."
3925  << __E__;
3926 
3927  ss << "\nYou may need to enter wiz mode to remedy the situation, use the "
3928  "following:\n"
3929  "\n\t ots --wiz"
3930  "\n\n\n"
3931  << __E__;
3932 
3933  ss << __E__ << StringMacros::stackTrace() << __E__;
3934  }
3935 
3936  __SS_ONLY_THROW__;
3937  }
3938  TLOG_DEBUG(55) << "Table " << tableName << " is at "
3939  << static_cast<void*>(it->second);
3940  return it->second;
3941 } // end getTableByName()
3942 
3943 //==============================================================================
3948 {
3949  if(!theBackboneTableGroupKey_) // no active backbone
3950  {
3951  __GEN_COUT_WARN__ << "getTableGroupKey() Failed! No active backbone currently."
3952  << __E__;
3953  return TableGroupKey();
3954  }
3955 
3956  // may already be loaded, but that's ok, load anyway to be sure
3957  loadTableGroup(theBackboneTableGroup_, *theBackboneTableGroupKey_);
3958 
3959  return *theBackboneTableGroupKey_;
3960 } // end loadConfigurationBackbone()
3961 
3963 //==============================================================================
3975 std::pair<std::string, TableGroupKey> ConfigurationManager::getTableGroupFromAlias(
3976  std::string systemAlias, ProgressBar* progressBar)
3977 {
3978  // steps
3979  // check if special alias
3980  // if so, parse and return name/key
3981  // else, load active backbone
3982  // find runType in Group Aliases table
3983  // return key
3984 
3985  if(progressBar)
3986  progressBar->step();
3987 
3988  if(systemAlias.find("GROUP:") == 0)
3989  {
3990  if(progressBar)
3991  progressBar->step();
3992 
3993  unsigned int i = strlen("GROUP:");
3994  unsigned int j = systemAlias.find(':', i);
3995 
3996  if(progressBar)
3997  progressBar->step();
3998  if(j > i) // success
3999  return std::pair<std::string, TableGroupKey>(
4000  systemAlias.substr(i, j - i), TableGroupKey(systemAlias.substr(j + 1)));
4001  else // failure
4002  return std::pair<std::string, TableGroupKey>("", TableGroupKey());
4003  }
4004 
4006 
4007  if(progressBar)
4008  progressBar->step();
4009 
4010  try
4011  {
4012  // find runType in Group Aliases table
4013  ConfigurationTree entry =
4014  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getNode(systemAlias);
4015 
4016  if(progressBar)
4017  progressBar->step();
4018 
4019  return std::pair<std::string, TableGroupKey>(
4020  entry.getNode("GroupName").getValueAsString(),
4021  TableGroupKey(entry.getNode("GroupKey").getValueAsString()));
4022  }
4023  catch(...)
4024  {
4025  }
4026 
4027  // on failure, here
4028 
4029  if(progressBar)
4030  progressBar->step();
4031 
4032  return std::pair<std::string, TableGroupKey>("", TableGroupKey());
4033 } // end getTableGroupFromAlias()
4034 
4035 //==============================================================================
4038 std::map<std::string /*groupAlias*/, std::pair<std::string /*groupName*/, TableGroupKey>>
4040 {
4042  false /* throwErrors */,
4043  "" /* pathToActiveGroupsFile */,
4044  ConfigurationManager::LoadGroupType::
4045  ONLY_BACKBONE_TYPE); // make sure the active configuration backbone is
4046  // loaded from disk (i.e. the latest activated at the ConfigurationGUISupervisor)!
4047 
4048  std::map<std::string /*groupAlias*/,
4049  std::pair<std::string /*groupName*/, TableGroupKey>>
4050  retMap;
4051 
4052  std::vector<std::pair<std::string, ConfigurationTree>> entries =
4053  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
4054  for(auto& entryPair : entries)
4055  {
4056  retMap[entryPair.first] = std::pair<std::string, TableGroupKey>(
4057  entryPair.second.getNode("GroupName").getValueAsString(),
4058  TableGroupKey(entryPair.second.getNode("GroupKey").getValueAsString()));
4059  }
4060  return retMap;
4061 } // end getActiveGroupAliases()
4062 
4063 //==============================================================================
4066 std::set<std::pair<std::string /*table name*/, TableVersion /*aliased version*/>>
4067 ConfigurationManager::getVersionAliases(const std::string& tableAliasNeedle) const
4068 {
4069  std::set<std::pair<std::string /*table name*/, TableVersion /*aliased version*/>>
4070  retSet;
4071 
4072  auto tableAliasMap = getVersionAliases();
4073 
4074  for(auto& tableAliasMap : tableAliasMap)
4075  for(auto& tableAliasPair : tableAliasMap.second)
4076  if(tableAliasPair.first == tableAliasNeedle) //then table alias match!
4077  retSet.insert(std::pair<std::string /*table name*/,
4078  TableVersion /*aliased version*/>(
4079  tableAliasMap.first, tableAliasPair.second));
4080 
4081  return retSet;
4082 } //end getVersionAliases()
4083 
4084 //==============================================================================
4087 std::map<std::string /*table name*/,
4088  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
4090 {
4091  //__GEN_COUT__ << "getVersionAliases()" << __E__;
4092 
4093  std::map<std::string /*table name*/,
4094  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
4095  retMap;
4096 
4097  std::map<std::string, TableVersion> activeVersions = getActiveVersions();
4098  std::string versionAliasesTableName =
4099  ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
4100  if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
4101  {
4102  __SS__ << "Active version of VersionAliases missing!"
4103  << " Make sure you have a valid active Backbone Group." << __E__;
4104  __GEN_COUT_WARN__ << "\n" << ss.str();
4105  return retMap;
4106  }
4107 
4108  //__GEN_COUT__ << "activeVersions[\"" << versionAliasesTableName << "\"]=" << activeVersions[versionAliasesTableName] << __E__;
4109 
4110  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
4111  getNode(versionAliasesTableName).getChildren();
4112 
4113  // create map
4114  // add the first of each tableName, versionAlias pair encountered
4115  // ignore any repeats (Note: this also prevents overwriting of Scratch alias)
4116  std::string tableName, versionAlias;
4117  for(auto& aliasNodePair : aliasNodePairs)
4118  {
4119  tableName = aliasNodePair.second.getNode("TableName").getValueAsString();
4120  versionAlias = aliasNodePair.second.getNode("VersionAlias").getValueAsString();
4121 
4122  if(retMap.find(tableName) != retMap.end() &&
4123  retMap[tableName].find(versionAlias) != retMap[tableName].end())
4124  continue; // skip repeats (Note: this also prevents overwriting of Scratch
4125  // alias)
4126 
4127  // else add version to map
4128  retMap[tableName][versionAlias] =
4129  TableVersion(aliasNodePair.second.getNode("Version").getValueAsString());
4130  }
4131 
4132  return retMap;
4133 } // end getVersionAliases()
4134 
4135 //==============================================================================
4137 std::map<std::string, TableVersion> ConfigurationManager::getActiveVersions(void) const
4138 {
4139  std::map<std::string, TableVersion> retMap;
4140  for(auto& table : nameToTableMap_)
4141  {
4142  __GEN_COUTS__(2) << table.first << __E__;
4143 
4144  // check configuration pointer is not null and that there is an active view
4145  if(table.second && table.second->isActive())
4146  {
4147  __GEN_COUTS__(2) << table.first << "_v" << table.second->getViewVersion()
4148  << __E__;
4149  retMap.insert(std::pair<std::string, TableVersion>(
4150  table.first, table.second->getViewVersion()));
4151  }
4152  }
4153 
4154  return retMap;
4155 } // end getActiveVersions()
4156 
4159 //{
4160 //
4161 // //fixme/todo this is called before setupAll so it breaks!
4162 // //====================================================
4163 // const DetectorConfiguration* detectorConfiguration =
4164 //__GET_CONFIG__(DetectorConfiguration); for(auto& type :
4165 // detectorConfiguration->getDetectorTypes()) theDACsConfigurations_[type] =
4166 //(DACsTableBase*)(getTableByName(type + "DACsConfiguration"));
4167 // //====================================================
4168 //
4169 // theDACStreams_[fecName].makeStream(fecName,
4170 // __GET_CONFIG__(DetectorConfiguration),
4171 // __GET_CONFIG__(DetectorToFEConfiguration),
4172 // theDACsConfigurations_,
4173 // __GET_CONFIG__(MaskConfiguration));//, theTrimConfiguration_);
4174 //
4175 // __GEN_COUT__ << "Done with DAC stream!" << __E__;
4176 // return theDACStreams_[fecName];
4177 //}
4178 
4179 //==============================================================================
4180 std::shared_ptr<TableGroupKey> ConfigurationManager::makeTheTableGroupKey(
4181  TableGroupKey key)
4182 {
4183  if(theConfigurationTableGroupKey_)
4184  {
4185  if(*theConfigurationTableGroupKey_ != key)
4187  else
4188  return theConfigurationTableGroupKey_;
4189  }
4190  return std::shared_ptr<TableGroupKey>(new TableGroupKey(key));
4191 } // end makeTheTableGroupKey()
4192 
4193 //==============================================================================
4194 const std::set<std::string>& ConfigurationManager::getActiveContextMemberNames()
4195 {
4196  //copy fixed context tables, then add optional tables if active
4197  contextMemberNames_ = ConfigurationManager::fixedContextMemberNames_;
4198 
4199  auto it =
4200  nameToTableMap_.find(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
4201  if(it == nameToTableMap_.end())
4202  return contextMemberNames_;
4203 
4204  if(!it->second->isActive()) //if optional table is active, add it
4205  {
4206  contextMemberNames_.emplace(
4207  ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
4208  }
4209  return contextMemberNames_;
4210 } // end getContextMemberNames()
4211 
4212 //==============================================================================
4213 const std::set<std::string>& ConfigurationManager::getFixedContextMemberNames()
4214 {
4215  return ConfigurationManager::fixedContextMemberNames_;
4216 } // end getContextMemberNames()
4217 
4218 //==============================================================================
4219 const std::set<std::string>& ConfigurationManager::getBackboneMemberNames()
4220 {
4221  return ConfigurationManager::backboneMemberNames_;
4222 } // end getBackboneMemberNames()
4223 
4224 //==============================================================================
4225 const std::set<std::string>& ConfigurationManager::getIterateMemberNames()
4226 {
4227  return ConfigurationManager::iterateMemberNames_;
4228 } // end getIterateMemberNames()
4229 
4230 //==============================================================================
4231 const std::set<std::string>& ConfigurationManager::getConfigurationMemberNames(void)
4232 {
4233  configurationMemberNames_.clear();
4234 
4235  std::map<std::string, TableVersion> activeTables = getActiveVersions();
4236 
4237  for(auto& tablePair : activeTables)
4238  if(
4239  //check if not context table
4240  ConfigurationManager::fixedContextMemberNames_.find(tablePair.first) ==
4241  ConfigurationManager::fixedContextMemberNames_.end() &&
4242  tablePair.first != ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE &&
4243 
4244  //check if not backbone table
4245  ConfigurationManager::backboneMemberNames_.find(tablePair.first) ==
4246  ConfigurationManager::backboneMemberNames_.end() &&
4247 
4248  //check if not iterate table
4249  ConfigurationManager::iterateMemberNames_.find(tablePair.first) ==
4250  ConfigurationManager::iterateMemberNames_.end())
4251  {
4252  // else, it is a configuration table
4253  configurationMemberNames_.emplace(tablePair.first);
4254  }
4255 
4256  return configurationMemberNames_;
4257 } // end getConfigurationMemberNames()
4258 
4259 //==============================================================================
4260 void ConfigurationManager::initializeFromFhicl(const std::string& fhiclPath)
4261 {
4262  __GEN_COUT__ << "Initializing from fhicl: " << fhiclPath << __E__;
4263 
4264  // https://cdcvs.fnal.gov/redmine/projects/fhicl-cpp/wiki
4265 
4266  // LoadParameterSet() ... from $ARTDAQ_INC/artdaq/Application/LoadParameterSet.hh
4267  fhicl::ParameterSet pset = LoadParameterSet(fhiclPath);
4268 
4269  if(pset.get_names().size() == 0)
4270  {
4271  __GEN_SS__ << "Empty fcl configuration parameter set found! File: " << fhiclPath
4272  << __E__;
4273  __SS_THROW__;
4274  }
4275 
4276  //===========================
4277  // fcl should be FE record(s):
4278  // interface0: {
4279  // FEInterfacePluginName: "FEOtsUDPTemplateInterface"
4280  // LinkToFETypeTable_FEOtsUDPTemplateInterfaceTable: {
4281  // OtsInterface0: {
4282  // InterfaceIPAddress: "127.0.0.1"
4283  // InterfacePort: 4000
4284  // HostIPAddress: "127.0.0.1"
4285  // HostPort: 4020
4286  // StreamToIPAddress: "127.0.0.1"
4287  // StreamToPort: 4021
4288  // }
4289  // } //end FEOtsUDPTemplateInterfaceTable link record
4290  // } //end interface0
4291  //===========================
4292 
4293  // Steps:
4294  // Create one context with one FE supervisor
4295  // and one/many FEs specified by fcl
4296  //
4297 
4298  TableBase* table;
4299 
4300  // create context and add context record
4301  {
4302  table = 0;
4303  theInterface_->get(table, // configurationPtr
4304  ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME, // tableName
4305  0, // groupKey
4306  0, // groupName
4307  true // dontFill=false to fill
4308  );
4309 
4310  nameToTableMap_[ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME] = table;
4311 
4312  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4313  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4314 
4315  TableView* view = table->getViewP();
4316  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4317 
4318  // add context record ---------------------
4319  view->addRow();
4320  auto colMap = view->getColumnNamesMap();
4321 
4322  view->setValue("MacroMakerFEContext", 0, colMap["ContextUID"]);
4323  view->setValue("XDAQApplicationTable", 0, colMap["LinkToApplicationTable"]);
4324  view->setValue("MacroMakerFEContextApps", 0, colMap["LinkToApplicationGroupID"]);
4325  view->setValue("1", 0, colMap[TableViewColumnInfo::COL_NAME_STATUS]);
4326 
4327  __GEN_COUT__ << "Done adding context record..." << __E__;
4328  if(TTEST(1))
4329  {
4330  std::stringstream ss;
4331  view->print(ss);
4332  __GEN_COUTT__ << "view->print()" << ss.str() << __E__;
4333  }
4334 
4335  } // done with context record
4336 
4337  // create app table and add application record
4338  {
4339  table = 0;
4340  theInterface_->get(
4341  table, // configurationPtr
4342  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME, // tableName
4343  0, // groupKey
4344  0, // groupName
4345  true // dontFill=false to fill
4346  );
4347 
4348  nameToTableMap_[ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME] = table;
4349 
4350  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4351  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4352 
4353  TableView* view = table->getViewP();
4354  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4355 
4356  // add application record ---------------------
4357  view->addRow();
4358  auto colMap = view->getColumnNamesMap();
4359 
4360  view->setValue("MacroMakerFEContextApps", 0, colMap["ApplicationGroupID"]);
4361  view->setValue("MacroMakerFESupervisor", 0, colMap["ApplicationUID"]);
4362  view->setValue("FESupervisorTable", 0, colMap["LinkToSupervisorTable"]);
4363  view->setValue("MacroMakerFESupervisor", 0, colMap["LinkToSupervisorUID"]);
4364  view->setValue("1", 0, colMap[TableViewColumnInfo::COL_NAME_STATUS]);
4365  view->setValue(__ENV__("FE_SUPERVISOR_ID"), 0, colMap["Id"]); // XDAQ LID
4366 
4367  __GEN_COUT__ << "Done adding application record..." << __E__;
4368  if(TTEST(1))
4369  {
4370  std::stringstream ss;
4371  view->print(ss);
4372  __GEN_COUTT__ << "view->print()" << ss.str() << __E__;
4373  }
4374  } // done with app record
4375 
4376  // create FE Supervisor table and Supervisor record
4377  {
4378  table = 0;
4379  theInterface_->get(table, // configurationPtr
4380  "FESupervisorTable", // tableName
4381  0, // groupKey
4382  0, // groupName
4383  true // dontFill=false to fill
4384  );
4385 
4386  nameToTableMap_["FESupervisorTable"] = table;
4387 
4388  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4389  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4390 
4391  TableView* view = table->getViewP();
4392  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4393 
4394  // add application record ---------------------
4395  view->addRow();
4396  auto colMap = view->getColumnNamesMap();
4397 
4398  view->setValue("MacroMakerFESupervisor", 0, colMap["SupervisorUID"]);
4399  view->setValue("FEInterfaceTable", 0, colMap["LinkToFEInterfaceTable"]);
4400  view->setValue(
4401  "MacroMakerFESupervisorInterfaces", 0, colMap["LinkToFEInterfaceGroupID"]);
4402 
4403  __GEN_COUT__ << "Done adding supervisor record..." << __E__;
4404  if(TTEST(1))
4405  {
4406  std::stringstream ss;
4407  view->print(ss);
4408  __GEN_COUTT__ << "view->print()" << ss.str() << __E__;
4409  }
4410  } // done with app record
4411 
4412  // create FE Interface table and interface record(s)
4413  recursiveInitFromFhiclPSet("FEInterfaceTable" /*tableName*/,
4414  pset /*fhicl parameter set*/,
4415  "" /*uid*/,
4416  "MacroMakerFESupervisorInterfaces" /*groupID*/,
4417  "FE" /*childLinkIndex*/);
4418 
4419  // init every table after modifications
4420  for(auto& table : nameToTableMap_)
4421  {
4422  table.second->getViewP()->init();
4423  }
4424 
4425  // verify extraction
4426  if(0)
4427  {
4428  __GEN_COUT__ << "================================================" << __E__;
4429  nameToTableMap_["FESupervisorTable"]->getViewP()->print();
4430  nameToTableMap_["FEInterfaceTable"]->getViewP()->print();
4431 
4432  auto sups = getNode("FESupervisorTable").getChildrenNames();
4433  __GEN_COUT__ << "Supervisors extracted from fhicl: " << sups.size() << __E__;
4434  auto fes = getNode("FEInterfaceTable").getChildrenNames();
4435  __GEN_COUT__ << "Front-ends extracted from fhicl: " << fes.size() << __E__;
4436  {
4437  auto a = getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME);
4438  __GEN_COUTV__(a.getValueAsString());
4439 
4440  auto b = a.getNode("MacroMakerFEContext");
4441  __GEN_COUTV__(b.getValueAsString());
4442 
4443  auto c = b.getNode("LinkToApplicationTable");
4444  __GEN_COUTV__(c.getValueAsString());
4445 
4446  auto d = c.getNode("MacroMakerFESupervisor");
4447  __GEN_COUTV__(d.getValueAsString());
4448 
4449  auto e = d.getNode("LinkToSupervisorTable");
4450  __GEN_COUTV__(e.getValueAsString());
4451 
4452  auto f = e.getNode("LinkToFEInterfaceTable");
4453  __GEN_COUTV__(f.getValueAsString());
4454 
4455  auto z = f.getChildrenNames();
4456  __GEN_COUTV__(StringMacros::vectorToString(z));
4457  __GEN_COUTV__(z.size());
4458  auto y = f.getChildrenNames(false /*byPriority*/, true /*onlyStatusTrue*/);
4459  __GEN_COUTV__(StringMacros::vectorToString(y));
4460  __GEN_COUTV__(y.size());
4461  auto x = f.getChildrenNames(true /*byPriority*/, true /*onlyStatusTrue*/);
4462  __GEN_COUTV__(StringMacros::vectorToString(x));
4463  __GEN_COUTV__(x.size());
4464 
4465  auto g = f.getNode("dtc0");
4466  __GEN_COUTV__(g.getValueAsString());
4467  auto h = f.getNode("interface0");
4468  __GEN_COUTV__(h.getValueAsString());
4469 
4470  auto fes =
4471  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
4472  .getNode(
4473  "MacroMakerFEContext/LinkToApplicationTable/"
4474  "MacroMakerFESupervisor/LinkToSupervisorTable")
4475  .getNode("LinkToFEInterfaceTable")
4476  .getChildrenNames(true /*byPriority*/, true /*onlyStatusTrue*/);
4477  __GEN_COUTV__(fes.size());
4478  __GEN_COUTV__(StringMacros::vectorToString(fes));
4479  }
4480  }
4481 
4482 } // end initializeFromFhicl()
4483 
4484 //==============================================================================
4489 void ConfigurationManager::recursiveInitFromFhiclPSet(const std::string& tableName,
4490  const fhicl::ParameterSet& pset,
4491  const std::string& recordName,
4492  const std::string& groupName,
4493  const std::string& groupLinkIndex)
4494 {
4495  __GEN_COUTT__ << "recursiveInitFromFhiclPSet() "
4496  << "Adding table '" << tableName << "' record(s)..." << __E__;
4497 
4498  TableBase* table;
4499  // create context and add context record
4500  {
4501  table = 0;
4502  if(nameToTableMap_.find(tableName) == nameToTableMap_.end())
4503  {
4504  __GEN_COUTT__ << "Table not found, so making '" << tableName
4505  << "' instance..." << __E__;
4506  theInterface_->get(table, // configurationPtr
4507  tableName, // tableName
4508  0, // groupKey
4509  0, // groupName
4510  true // dontFill=false to fill
4511  );
4512 
4513  nameToTableMap_[tableName] = table;
4514  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4515  }
4516  else
4517  {
4518  __GEN_COUTT__ << "Existing table found, so using '" << tableName
4519  << "'instance..." << __E__;
4520  table = nameToTableMap_[tableName];
4521  }
4522 
4523  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4524 
4525  TableView* view = table->getViewP();
4526  __GEN_COUTT__ << "Activated version: " << view->getVersion() << __E__;
4527  // view->print();
4528 
4529  if(recordName != "") // then add this record
4530  {
4531  // Steps:
4532  // - add row
4533  // - set UID and enable (if possible)
4534  // - set values for parameter columns
4535  // - define links
4536 
4537  __GEN_COUTTV__(recordName);
4538 
4539  // add row and get column map
4540  unsigned int r = view->addRow();
4541  auto colMap = view->getColumnNamesMap();
4542 
4543  // set UID and enable (if possible)
4544  view->setValue(recordName, r, view->getColUID());
4545  try
4546  {
4547  view->setValue("1", r, view->getColStatus());
4548  }
4549  catch(...)
4550  {
4551  __GEN_COUTT__ << "No status column to set for '" << recordName << "'"
4552  << __E__;
4553  }
4554 
4555  if(groupName != "") // then set groupID for this record
4556  {
4557  __GEN_COUTT__ << "Setting group ID for group link index '"
4558  << groupLinkIndex << "'" << __E__;
4559 
4560  int groupIDCol = view->getLinkGroupIDColumn(groupLinkIndex);
4561  __GEN_COUTT__ << "Setting group ID for group link index '"
4562  << groupLinkIndex << "' at column " << groupIDCol << " to '"
4563  << groupName << ".'" << __E__;
4564 
4565  view->setValue(groupName, r, groupIDCol);
4566  }
4567 
4568  // then set parameters
4569  auto names = pset.get_names();
4570  for(const auto& colName : names)
4571  {
4572  if(!pset.is_key_to_atom(colName))
4573  continue;
4574 
4575  auto colIt = colMap.find(colName);
4576  if(colIt == colMap.end())
4577  {
4578  __SS__ << "Field '" << colName << "' of record '" << recordName
4579  << "' in table '" << tableName << "' was not found in columns."
4580  << "\n\nHere are the existing column names:\n";
4581  unsigned int i = 0;
4582  for(const auto& col : colMap)
4583  ss << "\n" << ++i << ".\t" << col.first;
4584  ss << __E__;
4585  __SS_THROW__;
4586  }
4587  // skip overwriting group ID - already setup by parent group link
4588  if(view->getColumnInfo(colIt->second).isGroupID())
4589  continue;
4590 
4591  const std::string value = pset.get<std::string>(colName);
4592  __GEN_COUTT__ << "Setting '" << recordName << "' parameter at column "
4593  << colIt->second << ", '" << colName << "'\t = " << value
4594  << __E__;
4595  view->setValueAsString(value, r, colIt->second);
4596  } // end set parameters
4597 
4598  // then define links
4599  for(const auto& linkName : names)
4600  {
4601  if(pset.is_key_to_atom(linkName))
4602  continue;
4603 
4604  __GEN_COUTTV__(linkName);
4605 
4606  // split into column name and table
4607  unsigned int c = linkName.size() - 1;
4608  for(; c >= 1; --c)
4609  if(linkName[c] == '_') // find first underscore to split linkName
4610  break;
4611 
4612  if(c == 0)
4613  {
4614  __SS__ << "Illegal link name '" << linkName
4615  << "' found. The format must be <Column name>_<Target table "
4616  "name>,.. for example '"
4617  << "LinkToFETypeTable_FEOtsUDPTemplateInterfaceTable'"
4618  << __E__;
4619  __SS_THROW__;
4620  }
4621  std::string colName = linkName.substr(0, c);
4622  __GEN_COUTTV__(colName);
4623 
4624  auto colIt = colMap.find(colName);
4625  if(colIt == colMap.end())
4626  {
4627  __SS__ << "Link '" << colName << "' of record '" << recordName
4628  << "' in table '" << tableName << "' was not found in columns."
4629  << "\n\nHere are the existing column names:\n";
4630  unsigned int i = 0;
4631  for(const auto& col : colMap)
4632  ss << "\n" << i << ".\t" << col.first << __E__;
4633  __SS_THROW__;
4634  }
4635  //__GEN_COUT__ << "Setting link at column " << colIt->second << __E__;
4636 
4637  std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>
4638  linkPair;
4639  bool isGroupLink;
4640  view->getChildLink(colIt->second, isGroupLink, linkPair);
4641 
4642  //__GEN_COUTV__(isGroupLink);
4643  //__GEN_COUTV__(linkPair.first);
4644  //__GEN_COUTV__(linkPair.second);
4645 
4646  std::string linkTableName = linkName.substr(c + 1);
4647  __GEN_COUTTV__(linkTableName);
4648 
4649  auto linkPset = pset.get<fhicl::ParameterSet>(linkName);
4650  auto linkRecords = linkPset.get_pset_names();
4651  if(!isGroupLink && linkRecords.size() > 1)
4652  {
4653  __SS__ << "A Unique Link can only point to one record. "
4654  << "The specified link '" << colName << "' of record '"
4655  << recordName << "' in table '" << tableName << "' has "
4656  << linkRecords.size() << " children records specified. "
4657  << __E__;
4658  __SS_THROW__;
4659  }
4660 
4661  if(linkRecords.size() == 0)
4662  {
4663  __GEN_COUTT__ << "No child records, so leaving link disconnected."
4664  << __E__;
4665  continue;
4666  }
4667 
4668  __GEN_COUTT__ << "Setting Link at columns [" << linkPair.first << ","
4669  << linkPair.second << "]" << __E__;
4670  view->setValue(linkTableName, r, linkPair.first);
4671 
4672  if(!isGroupLink)
4673  {
4674  __GEN_COUTT__ << "Setting up Unique link to " << linkRecords[0]
4675  << __E__;
4676 
4677  view->setValue(linkRecords[0], r, linkPair.second);
4678 
4679  recursiveInitFromFhiclPSet(
4680  linkTableName /*tableName*/,
4681  linkPset.get<fhicl::ParameterSet>(
4682  linkRecords[0]) /*fhicl parameter set*/,
4683  linkRecords[0] /*uid*/,
4684  "" /*groupID*/);
4685  }
4686  else
4687  {
4688  std::string childLinkIndex =
4689  view->getColumnInfo(linkPair.first).getChildLinkIndex();
4690  std::string groupName = recordName + "Group";
4691 
4692  view->setValue(groupName, r, linkPair.second);
4693 
4694  for(const auto& groupRecord : linkRecords)
4695  {
4696  __GEN_COUTT__ << "Setting '" << childLinkIndex
4697  << "' Group link to '" << groupName << "' record '"
4698  << groupRecord << "'" << __E__;
4699 
4700  recursiveInitFromFhiclPSet(
4701  linkTableName /*tableName*/,
4702  linkPset.get<fhicl::ParameterSet>(
4703  groupRecord) /*fhicl parameter set*/,
4704  groupRecord /*uid*/,
4705  groupName /*groupID*/,
4706  childLinkIndex /*groupLinkIndex*/);
4707  }
4708  }
4709 
4710  } // end link handling
4711  }
4712  else if(groupName != "") // then add group of records
4713  {
4714  // get_pset_names();
4715  // get_names
4716  __GEN_COUTTV__(groupName);
4717  auto psets = pset.get_pset_names();
4718  for(const auto& ps : psets)
4719  {
4720  __GEN_COUTTV__(ps);
4721  recursiveInitFromFhiclPSet(
4722  tableName /*tableName*/,
4723  pset.get<fhicl::ParameterSet>(ps) /*fhicl parameter set*/,
4724  ps /*uid*/,
4725  groupName /*groupID*/,
4726  groupLinkIndex /*groupLinkIndex*/);
4727  }
4728  }
4729  else
4730  {
4731  __SS__ << "Illegal recursive parameters!" << __E__;
4732  __SS_THROW__;
4733  }
4734  __GEN_COUT__ << "recursiveInitFromFhiclPSet() "
4735  << "Done adding table '" << tableName << "' record(s)..." << __E__;
4736  if(TTEST(1))
4737  {
4738  std::stringstream ss;
4739  view->print(ss);
4740  __GEN_COUTT__ << "view->print()" << ss.str() << __E__;
4741  }
4742  }
4743 
4744 } // end recursiveInitFromFhiclPSet()
4745 
4746 //==============================================================================
4751 {
4752  __GEN_COUTS__(11) << "Checking if owner '" << ownerContextUID_ << "/" << ownerAppUID_
4753  << "' is first App in Context:\n"
4754  << StringMacros::stackTrace() << __E__;
4755 
4756  if(ownerContextUID_ == "" || ownerAppUID_ == "")
4757  {
4758  __GEN_COUTTV__(!forceNotFirstInContext_);
4759  return !forceNotFirstInContext_; // default to 'yes' unless forced
4760  }
4761 
4762  __GEN_COUTVS__(10, ownerContextUID_);
4763  __GEN_COUTVS__(10, ownerAppUID_);
4764 
4765  try
4766  {
4767  auto contextChildren =
4768  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME + "/" +
4769  ownerContextUID_ + "/LinkToApplicationTable")
4770  .getChildrenNames(false /* byPriority */, true /* onlyStatusTrue */);
4771 
4772  if(contextChildren.size() == 0) // no enabled apps, check if owner is app[0]
4773  {
4774  contextChildren =
4775  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME + "/" +
4776  ownerContextUID_ + "/LinkToApplicationTable")
4777  .getChildrenNames(false /* byPriority */, false /* onlyStatusTrue */);
4778  __GEN_COUTVS__(10, StringMacros::vectorToString(contextChildren));
4779  }
4780  else
4781  __GEN_COUTVS__(10, StringMacros::vectorToString(contextChildren));
4782 
4783  bool isFirstAppInContext =
4784  contextChildren.size() == 0 || contextChildren[0] == ownerAppUID_;
4785 
4786  __GEN_COUTVS__(10, isFirstAppInContext);
4787 
4788  return isFirstAppInContext;
4789  }
4790  catch(...)
4791  {
4792  __GEN_COUTS__(10) << "Exception caught looking for XDAQ Context '"
4793  << ownerContextUID_ << "' in tree, so defaulting to 'yes'."
4794  << __E__;
4795  return true; // default to 'yes' if XDAQ Context doesn't exist
4796  }
4797 } // end isOwnerFirstAppInContext()
4798 
4799 //==============================================================================
4803  const std::string& otherSubsystemUID,
4804  std::string* userDataPathPtr /* = nullptr */,
4805  std::string* hostnamePtr /* = nullptr */,
4806  std::string* usernamePtr /* = nullptr */,
4807  std::string* fullNamePtr /* = nullptr */)
4808 {
4809  __GEN_COUTTV__(otherSubsystemUID);
4810 
4811  ConfigurationTree node =
4812  getNode(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE)
4813  .getNode(otherSubsystemUID);
4814  std::string userPath = node.getNode("SubsystemUserDataPath").getValue();
4815  if(fullNamePtr)
4816  *fullNamePtr = node.getNode("SubsystemFullName").getValue();
4817 
4818  auto splitPath = StringMacros::getVectorFromString(userPath, {':'});
4819  __GEN_COUTTV__(StringMacros::vectorToString(splitPath));
4820 
4821  if(!splitPath.size() || splitPath.size() > 2)
4822  {
4823  __GEN_SS__ << "Illegal user data path specified for subsystem '"
4824  << otherSubsystemUID << "': " << userPath << __E__;
4825  __SS_ONLY_THROW__;
4826  }
4827  std::string userDataPath = splitPath[splitPath.size() - 1];
4828 
4829  //since we are running exec, cleanse the filename path for alphanumeric,_,-,/ only
4830  for(unsigned int i = 0; i < userDataPath.length(); ++i)
4831  if(!((userDataPath[i] >= 'a' && userDataPath[i] <= 'z') ||
4832  (userDataPath[i] >= 'A' && userDataPath[i] <= 'Z') ||
4833  (userDataPath[i] >= '0' && userDataPath[i] <= '9') ||
4834  userDataPath[i] == '-' || userDataPath[i] == '_' || userDataPath[i] == '/'))
4835  {
4836  __GEN_SS__ << "Illegal user data path specified (no special characters "
4837  "allowed) for subsystem '"
4838  << otherSubsystemUID << "': " << userPath << __E__;
4839  __SS_ONLY_THROW__;
4840  } // end filename cleanse
4841 
4842  if(userDataPathPtr)
4843  *userDataPathPtr = userDataPath;
4844 
4845  std::string username, hostname;
4846  if(splitPath.size() == 2) //then need to scp the file
4847  {
4848  //since we are running exec, cleanse the username@host path for alphanumeric,_,-,/ only
4849  std::vector<std::string> userHostSplit =
4850  StringMacros::getVectorFromString(splitPath[0], {'@'});
4851  __GEN_COUTTV__(userHostSplit.size());
4852  if(userHostSplit.size() == 1)
4853  hostname = userHostSplit[0];
4854  else if(userHostSplit.size() == 2)
4855  {
4856  username = userHostSplit[0];
4857  hostname = userHostSplit[1];
4858  }
4859  else
4860  {
4861  __GEN_SS__ << "Illegal remote username/host specified for subsystem '"
4862  << otherSubsystemUID << "': " << userPath << __E__;
4863  __SS_ONLY_THROW__;
4864  }
4865 
4866  for(unsigned int i = 0; userHostSplit.size() == 2 && i < username.length(); ++i)
4867  if(!((username[i] >= 'a' && username[i] <= 'z') ||
4868  (username[i] >= 'A' && username[i] <= 'Z') ||
4869  (username[i] >= '0' && username[i] <= '9') || username[i] == '-' ||
4870  username[i] == '_'))
4871  {
4872  __GEN_SS__ << "Illegal remote username specified for subsystem '"
4873  << otherSubsystemUID << "': " << userPath << __E__;
4874  __SS_ONLY_THROW__;
4875  }
4876  unsigned int ii = 0; //track last . to prevent weird . usage
4877  for(unsigned int i = 0; i < hostname.length(); ++i)
4878  if(!((hostname[i] >= 'a' && hostname[i] <= 'z') ||
4879  (hostname[i] >= 'A' && hostname[i] <= 'Z') ||
4880  (hostname[i] >= '0' && hostname[i] <= '9') || hostname[i] == '-' ||
4881  hostname[i] == '_'))
4882  {
4883  if(hostname[i] == '.' && i > ii + 1)
4884  {
4885  //its ok to have this . so track position
4886  ii = i;
4887  }
4888  else //else not ok to have .. or other characters
4889  {
4890  __GEN_SS__ << "Illegal remote hostname '" << hostname
4891  << "' specified for subsystem '" << otherSubsystemUID
4892  << "': " << userPath << __E__;
4893  __SS_ONLY_THROW__;
4894  }
4895  }
4896  }
4897  else if(splitPath.size() == 1) //then can just directly access the file
4898  {
4899  __GEN_COUT__ << "Local user date path identified." << __E__;
4900  }
4901  else
4902  {
4903  __GEN_SS__ << "Illegal user data path specified for subsystem '"
4904  << otherSubsystemUID << "': " << userPath << __E__;
4905  __SS_ONLY_THROW__;
4906  }
4907 
4908  if(hostnamePtr)
4909  *hostnamePtr = hostname;
4910  if(usernamePtr)
4911  *usernamePtr = username;
4912 
4913 } // end getOtherSubsystemInstanceInfo()
4914 
4915 //==============================================================================
4916 std::map<std::string /*groupType*/, std::pair<std::string /*groupName*/, TableGroupKey>>
4917 ConfigurationManager::getOtherSubsystemActiveTableGroups(
4918  const std::string& otherSubsystemUID,
4919  std::string* userDataPathPtr /* = nullptr */,
4920  std::string* hostnamePtr /* = nullptr */,
4921  std::string* usernamePtr /* = nullptr */)
4922 {
4923  std::map<std::string /*groupType*/,
4924  std::pair<std::string /*groupName*/, TableGroupKey>>
4925  retMap;
4926 
4927  __GEN_COUTTV__(otherSubsystemUID);
4928 
4929  std::string userDataPath;
4930  std::string username, hostname;
4931 
4932  getOtherSubsystemInstanceInfo(otherSubsystemUID, &userDataPath, &hostname, &username);
4933 
4934  __GEN_COUTTV__(userDataPath);
4935  __GEN_COUTTV__(username);
4936  __GEN_COUTTV__(hostname);
4937 
4938  if(userDataPathPtr)
4939  *userDataPathPtr = userDataPath;
4940  if(hostnamePtr)
4941  *hostnamePtr = hostname;
4942  if(usernamePtr)
4943  *usernamePtr = username;
4944 
4945  //enforce filename ends correctly
4946  std::string filename = userDataPath + "/ServiceData/ActiveTableGroups.cfg";
4947 
4948  std::string cmdResult;
4949 
4950  if(hostname != "")
4951  {
4952  std::string tmpSubsystemFilename =
4953  ConfigurationManager::ACTIVE_GROUPS_FILENAME + "." + otherSubsystemUID;
4954  __GEN_COUTTV__(tmpSubsystemFilename);
4955  if(username != "") //has username
4956  {
4957  cmdResult = StringMacros::exec(
4958  ("rm " + tmpSubsystemFilename + " 2>/dev/null; scp " + username + "@" +
4959  hostname + ":" + filename + " " + tmpSubsystemFilename + " 2>&1; cat " +
4960  tmpSubsystemFilename + " 2>&1")
4961  .c_str());
4962  }
4963  else
4964  cmdResult = StringMacros::exec(
4965  ("rm " + tmpSubsystemFilename + " 2>/dev/null; scp " + hostname + ":" +
4966  filename + " " + tmpSubsystemFilename + " 2>&1; cat " +
4967  tmpSubsystemFilename + " 2>&1")
4968  .c_str());
4969  }
4970  else //then can just directly access the file
4971  {
4972  __GEN_COUT__ << "Local user date path identified." << __E__;
4973  cmdResult = StringMacros::exec(("cat " + filename + " 2>&1").c_str());
4974  }
4975 
4976  __GEN_COUTTV__(cmdResult);
4977  if(cmdResult.find("Permission denied") != std::string::npos)
4978  {
4979  __GEN_SS__
4980  << "\n\nPermission denied accessing user data path specified for subsystem '"
4981  << otherSubsystemUID << "': ";
4982  if(username != "")
4983  ss << username << "@";
4984  if(hostname != "")
4985  ss << hostname << ":";
4986  ss << userDataPath << __E__;
4987  __SS_ONLY_THROW__;
4988  }
4989  else if(cmdResult.find("No such file or directory") != std::string::npos)
4990  {
4991  __GEN_SS__ << "\n\nActive tables groups file not found at user data path "
4992  "specified for subsystem '"
4993  << otherSubsystemUID << "': ";
4994  if(username != "")
4995  ss << username << "@";
4996  if(hostname != "")
4997  ss << hostname << ":";
4998  ss << userDataPath << __E__;
4999  __SS_ONLY_THROW__;
5000  }
5001 
5002  auto subsystemActiveGroupMap = StringMacros::getVectorFromString(
5003  cmdResult, {'\n'} /* delimieter*/, {' ', '\t'} /* whitespace*/);
5004  __GEN_COUTTV__(StringMacros::vectorToString(subsystemActiveGroupMap));
5005  __GEN_COUTTV__(subsystemActiveGroupMap.size());
5006 
5007  std::string //groupComment, groupAuthor, groupCreationTime,
5008  groupType;
5009  for(unsigned int i = 0; i + 1 < subsystemActiveGroupMap.size(); i += 2)
5010  {
5011  if(subsystemActiveGroupMap[i] == "" || subsystemActiveGroupMap[i + 1] == "-1")
5012  continue;
5013 
5014  __GEN_COUTT__ << "Loading type of subsystem '" << otherSubsystemUID << "' group "
5015  << subsystemActiveGroupMap[i] << "("
5016  << subsystemActiveGroupMap[i + 1] << ")" << __E__;
5017 
5018  try
5019  {
5020  loadTableGroup(subsystemActiveGroupMap[i] /*groupName*/,
5021  TableGroupKey(subsystemActiveGroupMap[i + 1]),
5022  false /*doActivate*/,
5023  0 /*groupMembers*/,
5024  0 /*progressBar*/,
5025  0 /*accumulateErrors*/,
5026  0, // &groupComment,
5027  0, //&groupAuthor,
5028  0, //&groupCreationTime,
5029  true /*doNotLoadMember*/,
5030  &groupType);
5031  }
5032  catch(const std::runtime_error& e)
5033  {
5034  __GEN_COUTT__ << "Ignoring error loading subsystem '" << otherSubsystemUID
5035  << "' group " << subsystemActiveGroupMap[i] << "("
5036  << subsystemActiveGroupMap[i + 1] << "): " << __E__ << e.what()
5037  << __E__;
5038  groupType = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
5039  }
5040  retMap[groupType] = std::make_pair(subsystemActiveGroupMap[i],
5041  TableGroupKey(subsystemActiveGroupMap[i + 1]));
5042  } //end load table group loop
5043 
5044  __GEN_COUTTV__(StringMacros::mapToString(retMap));
5045  return retMap;
5046 } //end getOtherSubsystemActiveTableGroups()
5047 
5048 //==============================================================================
5050 std::set<std::string /* configAlias */>
5051 ConfigurationManager::getOtherSubsystemConfigAliases(const std::string& otherSubsystemUID)
5052 {
5053  std::set<std::string> retSet;
5054 
5055  __GEN_COUTTV__(otherSubsystemUID);
5056 
5057  std::map<std::string /*groupType*/,
5058  std::pair<std::string /*groupName*/, TableGroupKey>>
5059  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
5060 
5061  __GEN_COUTTV__(StringMacros::mapToString(retMap));
5062 
5063  //load backbone
5064  auto it = retMap.find(
5065  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
5066  if(it == retMap.end())
5067  {
5068  __GEN_SS__
5069  << "No active Backbone group found in the active groups of remote subsystem '"
5070  << otherSubsystemUID << "!'" << __E__;
5071  __GEN_SS_THROW__;
5072  }
5073  auto it2 = retMap.find(
5074  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
5075  if(it2 == retMap.end())
5076  {
5077  __GEN_SS__
5078  << "No active Context group found in the active groups of remote subsystem '"
5079  << otherSubsystemUID << "!'" << __E__;
5080  __GEN_SS_THROW__;
5081  }
5082 
5083  std::string accumulatedWarnings;
5084 
5085  // be careful to not activate! which calls init() and then generates output files to disk
5086  // and changes the system active group; instead only setActiveView
5087  loadTableGroup(it->second.first,
5088  it->second.second,
5089  false /*doActivate*/,
5090  0 /*groupMembers*/,
5091  0 /*progressBar*/,
5092  &accumulatedWarnings /*accumulateWarnings = 0*/
5093  );
5094  __GEN_COUTTV__(accumulatedWarnings);
5095 
5096  //get aliases (a la ConfigurationManager::getActiveGroupAliases:2888)
5097  std::vector<std::pair<std::string, ConfigurationTree>> entries =
5098  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
5099 
5100  for(auto& entry : entries)
5101  {
5102  if(entry.first.find("Context") == std::string::npos &&
5103  entry.first.find("Iterat") == std::string::npos)
5104  retSet.emplace(entry.first);
5105  }
5106  __GEN_COUTTV__(StringMacros::setToString(retSet));
5107  return retSet;
5108 } //end getOtherSubsystemConfigAliases()
5109 
5110 //==============================================================================
5112 std::set<std::string /* configAlias */>
5114  const std::string& otherSubsystemUID, const std::string& otherSubsystemFsmName)
5115 {
5116  std::set<std::string> retSet;
5117 
5118  std::map<std::string /*groupType*/,
5119  std::pair<std::string /*groupName*/, TableGroupKey>>
5120  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
5121 
5122  //load backbone
5123  auto it = retMap.find(
5124  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
5125  if(it == retMap.end())
5126  {
5127  __GEN_SS__
5128  << "No active Backbone group found in the active groups of remote subsystem '"
5129  << otherSubsystemUID << "!'" << __E__;
5130  __GEN_SS_THROW__;
5131  }
5132  auto it2 = retMap.find(
5133  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
5134  if(it2 == retMap.end())
5135  {
5136  __GEN_SS__
5137  << "No active Context group found in the active groups of remote subsystem '"
5138  << otherSubsystemUID << "!'" << __E__;
5139  __GEN_SS_THROW__;
5140  }
5141 
5142  std::string accumulatedWarnings;
5143 
5144  // be careful to not activate! which calls init() and then generates output files to disk
5145  // and changes the system active group; instead only setActiveView
5146  loadTableGroup(it->second.first,
5147  it->second.second,
5148  false /*doActivate*/,
5149  0 /*groupMembers*/,
5150  0 /*progressBar*/,
5151  &accumulatedWarnings /*accumulateWarnings = 0*/
5152  );
5153  loadTableGroup(it2->second.first,
5154  it2->second.second,
5155  false /*doActivate*/,
5156  0 /*groupMembers*/,
5157  0 /*progressBar*/,
5158  &accumulatedWarnings /*accumulateWarnings = 0*/
5159  );
5160  __GEN_COUTTV__(accumulatedWarnings);
5161 
5162  //get aliases (a la ConfigurationManager::getActiveGroupAliases:2888)
5163  std::vector<std::pair<std::string, ConfigurationTree>> entries =
5164  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
5165 
5166  //apply filter (a la GatewaySupervisor::addFilteredConfigAliasesToXML:5357)
5167 
5168  std::string stateMachineAliasFilter = "*"; // default to all
5169  try // if cant find alias, default to all
5170  {
5171  ConfigurationTree otherGatewayNode = getGatewaySupervisorNode();
5172  ConfigurationTree fsmFilterNode =
5173  otherGatewayNode.getNode("LinkToStateMachineTable")
5174  .getNode(otherSubsystemFsmName + "/SystemAliasFilter");
5175  if(!fsmFilterNode.isDefaultValue())
5176  stateMachineAliasFilter = fsmFilterNode.getValue<std::string>();
5177  else
5178  __GEN_COUT_INFO__ << "FSM has no SystemAliasFilter value." << __E__;
5179  }
5180  catch(std::runtime_error& e)
5181  {
5182  __COUT__ << "Ignoring unsetup SystemAliasFilter value: " << e.what() << __E__;
5183  }
5184  catch(...)
5185  {
5186  __COUT__ << "Ignoring unsetup SystemAliasFilter value." << __E__;
5187  }
5188 
5189  __COUT__ << "Applying alias filter for other user_data path FSM '"
5190  << otherSubsystemFsmName
5191  << "' and stateMachineAliasFilter = " << stateMachineAliasFilter << __E__;
5192 
5193  // filter list of aliases based on stateMachineAliasFilter
5194  // ! as first character means choose those that do NOT match filter
5195  // * can be used as wild card.
5196  {
5197  bool invertFilter =
5198  stateMachineAliasFilter.size() && stateMachineAliasFilter[0] == '!';
5199  std::vector<std::string> filterArr;
5200 
5201  size_t i = 0;
5202  if(invertFilter)
5203  ++i;
5204  size_t f;
5205  std::string tmp;
5206  while((f = stateMachineAliasFilter.find('*', i)) != std::string::npos)
5207  {
5208  tmp = stateMachineAliasFilter.substr(i, f - i);
5209  i = f + 1;
5210  filterArr.push_back(tmp);
5211  __COUTS__(20) << filterArr[filterArr.size() - 1] << " " << i << " of "
5212  << stateMachineAliasFilter.size() << __E__;
5213  }
5214  if(i <= stateMachineAliasFilter.size())
5215  {
5216  tmp = stateMachineAliasFilter.substr(i);
5217  filterArr.push_back(tmp);
5218  __COUTS__(20) << filterArr[filterArr.size() - 1] << " last." << __E__;
5219  }
5220 
5221  bool filterMatch;
5222 
5223  for(auto& aliasMapPair : entries)
5224  {
5225  __COUTS__(20) << "aliasMapPair.first: " << aliasMapPair.first << __E__;
5226 
5227  filterMatch = true;
5228 
5229  if(filterArr.size() == 1)
5230  {
5231  if(filterArr[0] != "" && filterArr[0] != "*" &&
5232  aliasMapPair.first != filterArr[0])
5233  filterMatch = false;
5234  }
5235  else
5236  {
5237  i = -1;
5238  for(f = 0; f < filterArr.size(); ++f)
5239  {
5240  if(!filterArr[f].size())
5241  continue; // skip empty filters
5242 
5243  if(f == 0) // must start with this filter
5244  {
5245  if((i = aliasMapPair.first.find(filterArr[f])) != 0)
5246  {
5247  filterMatch = false;
5248  break;
5249  }
5250  }
5251  else if(f == filterArr.size() - 1) // must end with this filter
5252  {
5253  if(aliasMapPair.first.rfind(filterArr[f]) !=
5254  aliasMapPair.first.size() - filterArr[f].size())
5255  {
5256  filterMatch = false;
5257  break;
5258  }
5259  }
5260  else if((i = aliasMapPair.first.find(filterArr[f])) ==
5261  std::string::npos)
5262  {
5263  filterMatch = false;
5264  break;
5265  }
5266  }
5267  }
5268 
5269  if(invertFilter)
5270  filterMatch = !filterMatch;
5271 
5272  __COUTS__(20) << "filterMatch=" << filterMatch << __E__;
5273 
5274  if(!filterMatch)
5275  continue;
5276 
5277  retSet.emplace(aliasMapPair.first);
5278 
5279  //If need more alias details, see ConfigurationGUISupervisor::handleGroupAliasesXML
5280  }
5281  }
5282 
5283  return retSet;
5284 } //end getOtherSubsystemFilteredConfigAliases()
5285 
5286 //==============================================================================
5289  const std::string& otherSubsystemUID,
5290  const std::string& configAlias,
5291  std::pair<std::string, TableGroupKey>& groupTranslation,
5292  std::string& groupComment,
5293  std::string& groupAuthor,
5294  std::string& groupCreationTime)
5295 {
5296  __GEN_COUTV__(otherSubsystemUID);
5297 
5298  std::map<std::string /*groupType*/,
5299  std::pair<std::string /*groupName*/, TableGroupKey>>
5300  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
5301 
5302  //load backbone
5303  auto it = retMap.find(
5304  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
5305  if(it == retMap.end())
5306  {
5307  __GEN_SS__
5308  << "No active Backbone group found in the active groups of remote subsystem '"
5309  << otherSubsystemUID << "!'" << __E__;
5310  __GEN_SS_THROW__;
5311  }
5312  auto it2 = retMap.find(
5313  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
5314  if(it2 == retMap.end())
5315  {
5316  __GEN_SS__
5317  << "No active Context group found in the active groups of remote subsystem '"
5318  << otherSubsystemUID << "!'" << __E__;
5319  __GEN_SS_THROW__;
5320  }
5321 
5322  std::string accumulatedWarnings;
5323 
5324  // be careful to not activate! which calls init() and then generates output files to disk
5325  // and changes the system active group; instead only setActiveView
5326  loadTableGroup(it->second.first,
5327  it->second.second,
5328  false /*doActivate*/,
5329  0 /*groupMembers*/,
5330  0 /*progressBar*/,
5331  &accumulatedWarnings /*accumulateWarnings = 0*/
5332  );
5333  __GEN_COUTTV__(accumulatedWarnings);
5334 
5335  // (a la ConfigurationManager::getTableGroupFromAlias)
5336  try
5337  {
5338  // find runType in Group Aliases table
5339  ConfigurationTree entry =
5340  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getNode(configAlias);
5341 
5342  groupTranslation = std::pair<std::string, TableGroupKey>(
5343  entry.getNode("GroupName").getValueAsString(),
5344  TableGroupKey(entry.getNode("GroupKey").getValueAsString()));
5345  __COUT__ << "Found " << configAlias << " translates to " << groupTranslation.first
5346  << "(" << groupTranslation.second << ")" << __E__;
5347 
5348  //get comment, author, creationTime
5349  try
5350  {
5351  loadTableGroup(groupTranslation.first,
5352  groupTranslation.second,
5353  false /*doActivate*/,
5354  0 /*groupMembers*/,
5355  0 /*progressBar*/,
5356  &accumulatedWarnings,
5357  &groupComment,
5358  &groupAuthor,
5359  &groupCreationTime,
5360  true /*doNotLoadMembers*/);
5361  }
5362  catch(...)
5363  {
5364  __COUT_WARN__ << "Failed to load group metadata." << __E__;
5365  }
5366  __COUT__ << "Found " << configAlias << " author: " << groupAuthor
5367  << ", createTime: " << groupCreationTime << ", comment: " << groupComment
5368  << __E__;
5369  }
5370  catch(...)
5371  {
5372  __GEN_SS__ << "Did not find the Configuration Alias '" << configAlias
5373  << "' in the active Backbone group of remote subsystem '"
5374  << otherSubsystemUID << "!'" << __E__;
5375  __GEN_SS_THROW__;
5376  }
5377 
5378 } //end getOtherSubsystemConfigAliasInfo()
5379 
5380 //==============================================================================
5382 TableBase* ConfigurationManager::getDesktopIconTable(void)
5383 {
5384  if(nameToTableMap_.find(DESKTOP_ICON_TABLE_NAME) == nameToTableMap_.end())
5385  {
5386  __SS__ << "Desktop icon table not found!" << __E__;
5387  ss << StringMacros::stackTrace() << __E__;
5388  __SS_THROW__;
5389  }
5390 
5391  return nameToTableMap_.at(DESKTOP_ICON_TABLE_NAME);
5392 } // end dynamicDesktopIconChange()
5393 
5394 //==============================================================================
5395 void ConfigurationManager::saveGroupNameAndKey(
5396  const std::pair<std::string /*group name*/, TableGroupKey>& theGroup,
5397  const std::string& fileName,
5398  bool appendMode /* = false */,
5399  const std::string& associatedUser /* = "" */)
5400 {
5401  std::string fullPath =
5402  ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/" + fileName;
5403  __COUTT__ << "Saving group " << theGroup.first << "(" << theGroup.second << ") to "
5404  << (appendMode ? "history " : "") << "file: " << fullPath << __E__;
5405 
5406  std::ofstream groupFile;
5407  if(appendMode)
5408  {
5409  //force size to MAX record count
5410  const size_t MAX_RECORDS = 200;
5411  auto records = loadGroupHistory(fullPath);
5412  while(records.size() >= MAX_RECORDS)
5413  records.erase(records.begin()); //remove oldest record
5414  //rewrite file
5415  groupFile.open(fullPath.c_str());
5416  for(const auto& record : records)
5417  {
5418  groupFile << record.at("groupName") << "\n"
5419  << record.at("groupKey") << "\n"
5420  << record.at("time") << " , " << record.at("user") << "\n";
5421  } //end rewrite records loop
5422  }
5423  else //if not append mode, just overwrite
5424  groupFile.open(fullPath.c_str());
5425  if(!groupFile.is_open())
5426  {
5427  __SS__ << "Error. Can't open file to save group activity: " << fullPath << __E__;
5428  __SS_THROW__;
5429  }
5430  std::stringstream outss;
5431  outss << theGroup.first << "\n" << theGroup.second << "\n";
5432  outss << time(0);
5433  if(associatedUser != "") //add user on same line as time if available
5434  outss << " , " << associatedUser;
5435  outss << "\n";
5436  groupFile << outss.str().c_str();
5437  groupFile.close();
5438 } // end saveGroupNameAndKey()
5439 
5440 //==============================================================================
5446 std::pair<std::string /*group name*/, TableGroupKey>
5447 ConfigurationManager::loadGroupNameAndKey(const std::string& fileName,
5448  std::string& returnedTimeString)
5449 {
5450  std::string fullPath =
5451  ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/" + fileName;
5452 
5453  FILE* groupFile = fopen(fullPath.c_str(), "r");
5454  if(!groupFile)
5455  {
5456  __COUT__ << "Can't open file: " << fullPath
5457  << ". Returning empty groupName and key -1" << __E__;
5458 
5459  return std::pair<std::string /*group name*/, TableGroupKey>("", TableGroupKey());
5460  }
5461 
5462  char line[500]; // assuming no group names longer than 500 chars
5463  // name and then key
5464  std::pair<std::string /*group name*/, TableGroupKey> theGroup;
5465 
5466  fgets(line, 500, groupFile); // name
5467  if(strlen(line) && line[strlen(line) - 1] == '\n')
5468  line[strlen(line) - 1] = '\0'; // remove trailing newline
5469  theGroup.first = line;
5470 
5471  fgets(line, 500, groupFile); // key
5472  int key;
5473  sscanf(line, "%d", &key);
5474  theGroup.second = key;
5475 
5476  fgets(line, 500, groupFile); // time
5477  time_t timestamp;
5478  sscanf(line, "%ld", &timestamp); // type long int
5479  // struct tm tmstruct;
5480  // ::localtime_r(&timestamp, &tmstruct);
5481  // ::strftime(line, 30, "%c %Z", &tmstruct);
5482  returnedTimeString = StringMacros::getTimestampString(timestamp); // line;
5483  fclose(groupFile);
5484 
5485  __COUTS__(2) << "theGroup.first=" << theGroup.first
5486  << " theGroup.second=" << theGroup.second << __E__;
5487 
5488  return theGroup;
5489 } // end loadGroupNameAndKey()
5490 
5491 //==============================================================================
5493 std::vector<
5494  std::map<std::string /* group field key */, std::string /* group field value */>>
5495 ConfigurationManager::loadGroupHistory(const std::string& groupAction,
5496  const std::string& groupType,
5497  bool formatTime /* = false */)
5498 {
5499  __COUTTV__(groupAction);
5500  __COUTTV__(groupType);
5501 
5502  std::string fullPath = ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/";
5503 
5504  if(groupAction == "Activated")
5505  {
5506  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5507  fullPath += ConfigurationManager::ACTIVATED_BACKBONES_FILE;
5508  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5509  fullPath += ConfigurationManager::ACTIVATED_CONTEXTS_FILE;
5510  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5511  fullPath += ConfigurationManager::ACTIVATED_CONFIGS_FILE;
5512  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5513  fullPath += ConfigurationManager::ACTIVATED_ITERATES_FILE;
5514  }
5515  else if(groupAction == "Attempted Configure")
5516  {
5517  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5518  fullPath += ConfigurationManager::ATTEMPTED_CONFIGURE_CONFIGS_FILE;
5519  else if(groupType == "Config Alias")
5520  fullPath += ConfigurationManager::ATTEMPTED_CONFIGURE_CONFIG_ALIASES_FILE;
5521  }
5522  else if(groupAction == "Configured")
5523  {
5524  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5525  fullPath += ConfigurationManager::CONFIGURED_BACKBONES_FILE;
5526  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5527  fullPath += ConfigurationManager::CONFIGURED_CONTEXTS_FILE;
5528  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5529  fullPath += ConfigurationManager::CONFIGURED_CONFIGS_FILE;
5530  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5531  fullPath += ConfigurationManager::CONFIGURED_ITERATES_FILE;
5532  else if(groupType == "Config Alias")
5533  fullPath += ConfigurationManager::CONFIGURED_CONFIG_ALIASES_FILE;
5534  }
5535  else if(groupAction == "Started")
5536  {
5537  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5538  fullPath += ConfigurationManager::STARTED_BACKBONES_FILE;
5539  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5540  fullPath += ConfigurationManager::STARTED_CONTEXTS_FILE;
5541  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5542  fullPath += ConfigurationManager::STARTED_CONFIGS_FILE;
5543  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5544  fullPath += ConfigurationManager::STARTED_ITERATES_FILE;
5545  else if(groupType == "Config Alias")
5546  fullPath += ConfigurationManager::STARTED_CONFIG_ALIASES_FILE;
5547  }
5548  else if(groupAction == "Configured or Started")
5549  {
5550  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5551  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_BACKBONES_FILE;
5552  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5553  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_CONTEXTS_FILE;
5554  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5555  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_CONFIGS_FILE;
5556  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5557  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_ITERATES_FILE;
5558  else if(groupType == "Config Alias")
5559  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_CONFIG_ALIASES_FILE;
5560  }
5561 
5562  if(fullPath == ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/")
5563  {
5564  __SS__ << "Illegal attempted group history request combination of groupAction: "
5565  << groupAction << ", and groupType: " << groupType << __E__;
5566  __SS_THROW__;
5567  }
5568  return loadGroupHistory(fullPath, formatTime);
5569 } // end loadGroupHistory()
5570 
5571 //==============================================================================
5573 std::vector<
5574  std::map<std::string /* group field key */, std::string /* group field value */>>
5575 ConfigurationManager::loadGroupHistory(const std::string& fullPath,
5576  bool formatTime /* = false */)
5577 {
5578  std::vector<
5579  std::map<std::string /* group field key */, std::string /* group field value */>>
5580  retVec;
5581 
5582  __COUTTV__(fullPath);
5583  FILE* groupFile = fopen(fullPath.c_str(), "r");
5584  if(!groupFile)
5585  {
5586  __COUT_WARN__ << "Can't open group history file (assuming no history yet): "
5587  << fullPath << __E__;
5588 
5589  __COUTTV__(retVec.size());
5590  return retVec;
5591  }
5592 
5593  char line[500]; // assuming no group names longer than 500 chars
5594  // name and then key
5595  std::pair<std::string /*group name*/, TableGroupKey> theGroup;
5596  std::string returnedTimeString, associatedUser;
5597  char user[500];
5598 
5599  while(fgets(line, 500, groupFile)) // name
5600  {
5601  if(strlen(line) && line[strlen(line) - 1] == '\n')
5602  line[strlen(line) - 1] = '\0'; // remove trailing newline
5603  theGroup.first = line;
5604 
5605  fgets(line, 500, groupFile); // key
5606  int key;
5607  sscanf(line, "%d", &key);
5608  theGroup.second = key;
5609 
5610  fgets(line, 500, groupFile); // time
5611  time_t timestamp;
5612  user[0] = '\0'; //clear in case not present in line
5613  sscanf(line, "%ld , %s", &timestamp, user); // type long int
5614  // struct tm tmstruct;
5615  // ::localtime_r(&timestamp, &tmstruct);
5616  // ::strftime(line, 30, "%c %Z", &tmstruct);
5617 
5618  __COUTS__(20) << "Read group from history file: " << theGroup.first << "("
5619  << theGroup.second << "), timestamp=" << timestamp
5620  << ", user=" << user << __E__;
5621 
5622  retVec.push_back({{"groupName", theGroup.first},
5623  {"groupKey", theGroup.second.toString()},
5624  {"time",
5625  formatTime ? StringMacros::getTimestampString(timestamp)
5626  : std::to_string(timestamp)},
5627  {"user", user}});
5628  } //end traversing group history file
5629 
5630  fclose(groupFile);
5631 
5632  __COUTTV__(retVec.size());
5633 
5634  return retVec;
5635 } // end loadGroupHistory()
5636 
5637 //==============================================================================
5640 try
5641 {
5642  __COUTT__ << "Initializing prerequisites for artdaq!" << __E__;
5643 
5644  auto activeTables = getActiveVersions();
5645  for(auto& tablePair : activeTables)
5646  {
5647  __COUTVS__(2, tablePair.first);
5648  try
5649  {
5650  nameToTableMap_.at(tablePair.first)->initPrereqsForARTDAQ(this);
5651  }
5652  catch(const std::runtime_error& e)
5653  {
5654  __COUTVS__(2, e.what());
5655  if(std::string(e.what()).find(
5656  "initPrereqsForARTDAQ() is not implemented for this table") ==
5657  std::string::npos)
5658  throw;
5659  //else ignore undefined virtual function error
5660  }
5661  } //end table loop
5662 
5663  __COUTT__ << "Done initializing prerequisites for artdaq!" << __E__;
5664 } // end initPrereqsForARTDAQ()
5665 catch(...)
5666 {
5667  __SS__ << "Error caught while initializing prerequisites for artdaq!";
5668  try
5669  {
5670  throw;
5671  }
5672  catch(const std::runtime_error& e)
5673  {
5674  ss << " Here was the error: " << e.what() << __E__;
5675  }
5676  __SS_THROW__;
5677 } // end initPrereqsForARTDAQ()
virtual std::map< std::string, TableVersion > getTableGroupMembers(std::string const &, bool=false) const
returns the set of table groups that contain the specified table name and version
std::map< std::string, std::map< std::string, TableVersion > > getVersionAliases(void) const
static const unsigned int PROCESSOR_COUNT
Static members.
static const std::string & convertGroupTypeToName(const ConfigurationManager::GroupType &groupTypeId)
void restoreActiveTableGroups(bool throwErrors=false, const std::string &pathToActiveGroupsFile="", ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, std::string *accumulatedWarnings=0)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveTableGroups(void) const
std::set< std::string > getOtherSubsystemConfigAliases(const std::string &otherSubsystemUID)
Ignore any System Aliases with "Context" or "Iterat" in the name.
void dumpActiveConfiguration(const std::string &filePath, const std::string &dumpType, const std::string &configurationAlias, const std::string &subsystemCommonList, const std::string &subsystemCommonOverrideList, const std::string &logEntry, const std::string &activeUsers, const std::string &activeStateMachine, std::ostream &altOut=std::cout)
void loadMemberMap(const std::map< std::string, TableVersion > &memberMap, std::string *accumulateWarnings=0)
std::map< std::string, TableVersion > getActiveVersions(void) const
getActiveVersions
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)
void getOtherSubsystemInstanceInfo(const std::string &otherSubsystemUID, std::string *userDataPathPtr=nullptr, std::string *hostnamePtr=nullptr, std::string *usernamePtr=nullptr, std::string *fullNamePtr=nullptr)
ConfigurationManager(bool initForWriteAccess=false, bool initializeFromFhicl=false, bool forceNotFirstInContext=false)
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType groupTypeToLoad=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false, std::map< std::string, TableVersion > mergeInTables={}, std::map< std::string, TableVersion > overrideTables={})
TableBase * getVersionedTableByName(const std::string &tableName, TableVersion version, bool looseColumnMatching=false, std::string *accumulatedErrors=0, bool getRawData=false, bool touchLastAccessTime=true)
void init(std::string *accumulatedErrors=0, bool initForWriteAccess=false, std::string *accumulatedWarnings=0)
std::string getFirstPathToNode(const ConfigurationTree &node, const std::string &startPath="/") const
getFirstPathToNode
static ConfigurationManager::GroupType getTypeOfGroup(const std::map< std::string, TableVersion > &memberMap)
static const std::string & getTypeNameOfGroup(const std::map< std::string, TableVersion > &memberMap)
void destroyTableGroup(const std::string &theGroup="", bool onlyDeactivate=false)
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
std::pair< std::string, TableGroupKey > getTableGroupFromAlias(std::string systemAlias, ProgressBar *progressBar=0)
Getters.
static std::vector< std::map< std::string, std::string > > loadGroupHistory(const std::string &groupAction, const std::string &groupType, bool formatTime=false)
loadGroupHistory static
void getOtherSubsystemConfigAliasInfo(const std::string &otherSubsystemUID, const std::string &configAlias, std::pair< std::string, TableGroupKey > &groupTranslation, std::string &groupComment, std::string &groupAuthor, std::string &groupCreationTime)
returns configAlias translation group info by reference
ConfigurationTree getGatewaySupervisorNode(void) const
There can only be one active Gateway Superivsor app, so find it.
static const std::string ACTIVE_GROUPS_FILENAME
added env check for otsdaq_flatten_active_to_version to function
std::set< std::string > getOtherSubsystemFilteredConfigAliases(const std::string &otherSubsystemUID, const std::string &otherSubsystemFsmName)
Ignore any System Aliases with "Context" or "Iterat" in the name.
TableGroupKey loadConfigurationBackbone(void)
const TableBase * getTableByName(const std::string &configurationName) const
static std::pair< std::string, TableGroupKey > loadGroupNameAndKey(const std::string &fileName, std::string &returnedTimeString)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveGroupAliases(void)
void initPrereqsForARTDAQ(void)
loadGroupHistory
bool isDisconnected(void) const
std::vector< std::string > getChildrenNames(bool byPriority=false, bool onlyStatusTrue=false) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool onlyStatusTrue=false) const
const std::string & getValueAsString(bool returnLinkTableValue=false) const
void getValue(T &value) const
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
const std::string & getFieldName(void) const
alias for getValueName
bool isGroupLinkNode(void) const
bool isDefaultValue(void) const
boolean info
void step()
thread safe
Definition: ProgressBar.cc:74
const std::string & getTableName(void) const
Getters.
Definition: TableBase.cc:814
void setupMockupView(TableVersion version)
Definition: TableBase.cc:292
bool isActive(void)
isActive
Definition: TableBase.cc:950
const TableVersion & getViewVersion(void) const
always the active one
Definition: TableBase.cc:823
void print(std::ostream &out=std::cout) const
always prints active view
Definition: TableBase.cc:277
static std::string getFullGroupString(const std::string &groupName, const TableGroupKey &key, const std::string &preKey="_v", const std::string &postKey="")
bool isTemporaryVersion(void) const
std::string getChildLinkIndex(void) const
getChildLinkIndex
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
Definition: TableView.cc:1087
void deleteRow(int r)
Definition: TableView.cc:3572
unsigned int getColStatus(void) const
Definition: TableView.cc:1404
unsigned int getLinkGroupIDColumn(const std::string &childLinkIndex) const
Definition: TableView.cc:1855
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
Definition: TableView.cc:3602
void init(void)
Definition: TableView.cc:195
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
Definition: TableView.cc:972
int fillFromJSON(const std::string &json)
Definition: TableView.cc:2371
unsigned int getColUID(void) const
Definition: TableView.cc:1319
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:3487
defines used also by OtsConfigurationWizardSupervisor
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 setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
setToString ~
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
vectorToString ~
static std::string escapeJSONStringEntities(const std::string &str)
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)