otsdaq  3.06.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 {
3456  auto it = nameToTableMap_.find(tableName);
3457  if(it == nameToTableMap_.end())
3458  {
3459  __SS__ << "\nCan not find table named '" << tableName
3460  << "'\n\n\n\nYou need to load the table before it can be used."
3461  << "It probably is missing from the member list of the Table "
3462  "Group that was loaded?\n\n\n\n\n"
3463  << __E__;
3464  __SS_THROW__;
3465  }
3466  TableBase* table = it->second;
3467 
3468  if(version.isTemporaryVersion())
3469  {
3470  table->setActiveView(version);
3471 
3472  if(getRawData)
3473  {
3474  std::stringstream jsonSs;
3475  table->getViewP()->printJSON(jsonSs);
3476  table->getViewP()->doGetSourceRawData(true);
3477  table->getViewP()->fillFromJSON(jsonSs.str());
3478  }
3479  }
3480  else
3481  {
3482  theInterface_->get(table,
3483  tableName,
3484  0 /* groupKey */,
3485  0 /* groupName */,
3486  false /* dontFill */, // false to fill w/version
3487  version,
3488  false /* resetConfiguration*/, // false to not reset
3489  looseColumnMatching,
3490  getRawData,
3491  accumulatedErrors);
3492  }
3493  return table;
3494 } // end getVersionedTableByName()
3495 
3496 //==============================================================================
3502 std::map<std::string, std::pair<std::string, TableGroupKey>>
3504 {
3505  // map<type, pair <groupName , TableGroupKey> >
3506  std::map<std::string, std::pair<std::string, TableGroupKey>> retMap;
3507 
3508  retMap[ConfigurationManager::GROUP_TYPE_NAME_CONTEXT] =
3509  std::pair<std::string, TableGroupKey>(
3510  theContextTableGroup_,
3511  theContextTableGroupKey_ ? *theContextTableGroupKey_ : TableGroupKey());
3512  retMap[ConfigurationManager::GROUP_TYPE_NAME_BACKBONE] =
3513  std::pair<std::string, TableGroupKey>(
3514  theBackboneTableGroup_,
3515  theBackboneTableGroupKey_ ? *theBackboneTableGroupKey_ : TableGroupKey());
3516  retMap[ConfigurationManager::GROUP_TYPE_NAME_ITERATE] =
3517  std::pair<std::string, TableGroupKey>(
3518  theIterateTableGroup_,
3519  theIterateTableGroupKey_ ? *theIterateTableGroupKey_ : TableGroupKey());
3520  retMap[ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION] =
3521  std::pair<std::string, TableGroupKey>(theConfigurationTableGroup_,
3522  theConfigurationTableGroupKey_
3523  ? *theConfigurationTableGroupKey_
3524  : TableGroupKey());
3525  return retMap;
3526 } // end getActiveTableGroups()
3527 
3528 //==============================================================================
3529 const std::string& ConfigurationManager::getActiveGroupName(
3530  const ConfigurationManager::GroupType& type) const
3531 {
3532  if(type == ConfigurationManager::GroupType::CONFIGURATION_TYPE)
3533  return theConfigurationTableGroup_;
3534  else if(type == ConfigurationManager::GroupType::CONTEXT_TYPE)
3535  return theContextTableGroup_;
3536  else if(type == ConfigurationManager::GroupType::BACKBONE_TYPE)
3537  return theBackboneTableGroup_;
3538  else if(type == ConfigurationManager::GroupType::ITERATE_TYPE)
3539  return theIterateTableGroup_;
3540 
3541  __SS__ << "IMPOSSIBLE! Invalid type requested '" << (int)type << "'" << __E__;
3542  __SS_THROW__;
3543 } // end getActiveGroupName()
3544 
3545 //==============================================================================
3546 TableGroupKey ConfigurationManager::getActiveGroupKey(
3547  const ConfigurationManager::GroupType& type) const
3548 {
3549  if(type == ConfigurationManager::GroupType::CONFIGURATION_TYPE)
3550  return theConfigurationTableGroupKey_ ? *theConfigurationTableGroupKey_
3551  : TableGroupKey();
3552  else if(type == ConfigurationManager::GroupType::CONTEXT_TYPE)
3553  return theContextTableGroupKey_ ? *theContextTableGroupKey_ : TableGroupKey();
3554  else if(type == ConfigurationManager::GroupType::BACKBONE_TYPE)
3555  return theBackboneTableGroupKey_ ? *theBackboneTableGroupKey_ : TableGroupKey();
3556  else if(type == ConfigurationManager::GroupType::ITERATE_TYPE)
3557  return theIterateTableGroupKey_ ? *theIterateTableGroupKey_ : TableGroupKey();
3558 
3559  __SS__ << "IMPOSSIBLE! Invalid type requested '" << (int)type << "'" << __E__;
3560  __SS_THROW__;
3561 } // end getActiveGroupKey()
3562 
3563 //==============================================================================
3564 ConfigurationTree ConfigurationManager::getContextNode(
3565  const std::string& contextUID, const std::string& /*applicationUID*/) const
3566 {
3567  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
3568  contextUID);
3569 } // end getContextNode()
3570 
3571 //==============================================================================
3572 ConfigurationTree ConfigurationManager::getSupervisorNode(
3573  const std::string& contextUID, const std::string& applicationUID) const
3574 {
3575  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
3576  contextUID + "/LinkToApplicationTable/" + applicationUID);
3577 } // end getSupervisorNode()
3578 
3579 //==============================================================================
3580 ConfigurationTree ConfigurationManager::getSupervisorTableNode(
3581  const std::string& contextUID, const std::string& applicationUID) const
3582 {
3583  return getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName() + "/" +
3584  contextUID + "/LinkToApplicationTable/" + applicationUID +
3585  "/LinkToSupervisorTable");
3586 } // end getSupervisorTableNode()
3587 
3588 //==============================================================================
3591 {
3592  auto contextChildren =
3593  getNode("/" + getTableByName(XDAQ_CONTEXT_TABLE_NAME)->getTableName())
3594  .getChildren();
3595  for(const auto& contextChild : contextChildren)
3596  {
3597  auto appChildren = contextChild.second.getNode("LinkToApplicationTable")
3598  .getChildren(); //colContext_.colLinkToApplicationTable_
3599  for(const auto& appChild : appChildren)
3600  {
3601  if(appChild.second.getNode("Class").getValue() ==
3602  "ots::GatewaySupervisor") //colApplication_.colClass_ ... XDAQContextTable::GATEWAY_SUPERVISOR_CLASS)
3603  return appChild.second;
3604  }
3605  }
3606  __SS__ << "No Gateway Supervisor node found!" << __E__;
3607  __SS_THROW__;
3608 } // end getGatewaySupervisorNode()
3609 
3610 //==============================================================================
3611 ConfigurationTree ConfigurationManager::getNode(const std::string& nodeString,
3612  bool doNotThrowOnBrokenUIDLinks) const
3613 {
3614  // __GEN_COUT__ << "nodeString=" << nodeString << " len=" << nodeString.length() << __E__;
3615 
3616  // get nodeName (in case of / syntax)
3617  if(nodeString.length() < 1)
3618  {
3619  __SS__ << ("Invalid empty node name") << __E__;
3620  __GEN_SS_THROW__;
3621  }
3622 
3623  // ignore multiple starting slashes
3624  size_t startingIndex = 0;
3625  while(startingIndex < nodeString.length() && nodeString[startingIndex] == '/')
3626  ++startingIndex;
3627  size_t endingIndex = nodeString.find('/', startingIndex);
3628  if(endingIndex == std::string::npos)
3629  endingIndex = nodeString.length();
3630 
3631  std::string nodeName = nodeString.substr(startingIndex, endingIndex - startingIndex);
3632  // __GEN_COUT__ << "nodeName=" << nodeName << " len" << nodeName.length() << __E__;
3633  if(nodeName.length() < 1)
3634  {
3635  // return root node
3636  return ConfigurationTree(this, 0);
3637 
3638  // __SS__ << "Invalid node name: " << nodeName << __E__;
3639  // __GEN_COUT_ERR__ << ss.str();
3640  // __SS_THROW__;
3641  }
3642  ++endingIndex;
3643  std::string childPath =
3644  (endingIndex >= nodeString.length() ? "" : nodeString.substr(endingIndex));
3645 
3646  // __GEN_COUT__ << "childPath=" << childPath << " len=" << childPath.length() << " endingIndex=" << endingIndex << " nodeString.length()=" << nodeString.length() << __E__;
3647 
3648  ConfigurationTree configTree(this, getTableByName(nodeName));
3649 
3650  if(childPath.length() > 1)
3651  return configTree.getNode(childPath, doNotThrowOnBrokenUIDLinks);
3652  else
3653  return configTree;
3654 } // end getNode()
3655 
3656 //==============================================================================
3657 std::map<std::string, ConfigurationTree> ConfigurationManager::getNodes(
3658  const std::string& nodeString) const
3659 {
3660  return getNode(nodeString).getChildrenMap();
3661 }
3662 
3663 //==============================================================================
3666  const ConfigurationTree& /*node*/, const std::string& /*startPath*/) const
3669 {
3670  std::string path = "/";
3671  return path;
3672 } // end getFirstPathToNode()
3673 
3674 //==============================================================================
3680 std::vector<std::pair<std::string, ConfigurationTree>> ConfigurationManager::getChildren(
3681  std::map<std::string, TableVersion>* memberMap,
3682  std::string* accumulatedTreeErrors) const
3683 {
3684  std::vector<std::pair<std::string, ConfigurationTree>> retVector;
3685 
3686  // if(accumulatedTreeErrors)
3687  // *accumulatedTreeErrors = "";
3688 
3689  bool filtering = memberMap && memberMap->size();
3690 
3691  //from root node, want active tables:
3692  for(auto& tablePair : nameToTableMap_)
3693  {
3694  if(filtering)
3695  {
3696  //if not in member map, ignore
3697  if(memberMap->find(tablePair.first) == memberMap->end())
3698  continue;
3699 
3700  //if in member map, and not active - that is a problem!
3701  try
3702  {
3703  if(!tablePair.second->isActive())
3704  {
3705  __SS__ << "Get Children with member map requires a child '"
3706  << tablePair.first << "' that is not active!" << __E__;
3707  __SS_THROW__;
3708  }
3709  }
3710  catch(const std::runtime_error& e)
3711  {
3712  if(accumulatedTreeErrors)
3713  {
3714  *accumulatedTreeErrors += e.what();
3715  __GEN_COUT_ERR__ << "Skipping " << tablePair.first
3716  << " since the table "
3717  "is not active."
3718  << __E__;
3719  continue;
3720  }
3721  throw;
3722  }
3723  }
3724 
3725  if(!tablePair.second->isActive()) // only consider if active
3726  continue;
3727 
3728  ConfigurationTree newNode(this, tablePair.second);
3729  if(accumulatedTreeErrors) // check for disconnects
3730  {
3731  try
3732  {
3733  std::vector<std::pair<std::string, ConfigurationTree>> newNodeChildren =
3734  newNode.getChildren();
3735  for(auto& newNodeChild : newNodeChildren)
3736  {
3737  if(newNodeChild.second.getTableName() ==
3738  ConfigurationManager::DESKTOP_ICON_TABLE_NAME &&
3739  !newNodeChild.second.isEnabled())
3740  continue; //skip check for Desktop Icons that are disabled.
3741 
3742  std::vector<std::pair<std::string, ConfigurationTree>>
3743  twoDeepChildren = newNodeChild.second.getChildren();
3744 
3745  for(auto& twoDeepChild : twoDeepChildren)
3746  {
3747  //__GEN_COUT__ << tablePair.first << " " <<
3748  // newNodeChild.first << " " << twoDeepChild.first
3749  // << __E__;
3750  if(twoDeepChild.second.isLinkNode() &&
3751  twoDeepChild.second.isDisconnected() &&
3752  twoDeepChild.second.getDisconnectedTableName() !=
3753  TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3754  {
3755  __SS__ << "At node '" + tablePair.first +
3756  "' with entry UID '" + newNodeChild.first +
3757  "' there is a disconnected child node at link "
3758  "column '" +
3759  twoDeepChild.first + "'" +
3760  " that points to table named '" +
3761  twoDeepChild.second.getDisconnectedTableName() +
3762  "' ...";
3763  *accumulatedTreeErrors += ss.str();
3764  }
3765  }
3766  }
3767  }
3768  catch(std::runtime_error& e)
3769  {
3770  __SS__ << "At node '" + tablePair.first +
3771  "' error detected descending through children:\n" +
3772  e.what();
3773  *accumulatedTreeErrors += ss.str();
3774  }
3775  } // done checking for disconnects
3776 
3777  retVector.push_back(
3778  std::pair<std::string, ConfigurationTree>(tablePair.first, newNode));
3779  } //end active table loop
3780 
3781  return retVector;
3782 } // end getChildren()
3783 
3784 //==============================================================================
3790 std::map<std::string /* childName */, ConfigurationTree>
3791 ConfigurationManager::getChildrenMap(std::map<std::string, TableVersion>* memberMap,
3792  std::string* accumulatedTreeErrors) const
3793 {
3794  std::map<std::string /* childName */, ConfigurationTree> retMap;
3795 
3796  // if(accumulatedTreeErrors)
3797  // *accumulatedTreeErrors = "";
3798 
3799  bool filtering = memberMap && memberMap->size();
3800 
3801  //from root node, want active tables:
3802  for(auto& tablePair : nameToTableMap_)
3803  {
3804  if(filtering)
3805  {
3806  //if not in member map, ignore
3807  if(memberMap->find(tablePair.first) == memberMap->end())
3808  continue;
3809 
3810  //if in member map, and not active - that is a problem!
3811  try
3812  {
3813  if(!tablePair.second->isActive())
3814  {
3815  __SS__ << "Get Children with member map requires a child '"
3816  << tablePair.first << "' that is not active!" << __E__;
3817  __SS_THROW__;
3818  }
3819  }
3820  catch(const std::runtime_error& e)
3821  {
3822  if(accumulatedTreeErrors)
3823  {
3824  *accumulatedTreeErrors += e.what();
3825  __GEN_COUT_ERR__ << "Skipping " << tablePair.first
3826  << " since the table "
3827  "is not active."
3828  << __E__;
3829  continue;
3830  }
3831  throw;
3832  }
3833  }
3834 
3835  if(!tablePair.second->isActive()) // only consider if active
3836  continue;
3837 
3838  ConfigurationTree newNode(this, tablePair.second);
3839  if(accumulatedTreeErrors) // check for disconnects
3840  {
3841  try
3842  {
3843  std::vector<std::pair<std::string, ConfigurationTree>> newNodeChildren =
3844  newNode.getChildren();
3845  for(auto& newNodeChild : newNodeChildren)
3846  {
3847  if(newNodeChild.second.getTableName() ==
3848  ConfigurationManager::DESKTOP_ICON_TABLE_NAME &&
3849  !newNodeChild.second.isEnabled())
3850  continue; //skip check for Desktop Icons that are disabled.
3851 
3852  std::vector<std::pair<std::string, ConfigurationTree>>
3853  twoDeepChildren = newNodeChild.second.getChildren();
3854 
3855  for(auto& twoDeepChild : twoDeepChildren)
3856  {
3857  //__GEN_COUT__ << tablePair.first << " " <<
3858  // newNodeChild.first << " " << twoDeepChild.first
3859  // << __E__;
3860  if(twoDeepChild.second.isLinkNode() &&
3861  twoDeepChild.second.isDisconnected() &&
3862  twoDeepChild.second.getDisconnectedTableName() !=
3863  TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
3864  {
3865  __SS__ << "At node '" + tablePair.first +
3866  "' with entry UID '" + newNodeChild.first +
3867  "' there is a disconnected child node at link "
3868  "column '" +
3869  twoDeepChild.first + "'" +
3870  " that points to table named '" +
3871  twoDeepChild.second.getDisconnectedTableName() +
3872  "' ...";
3873  *accumulatedTreeErrors += ss.str();
3874  }
3875  }
3876  }
3877  }
3878  catch(std::runtime_error& e)
3879  {
3880  __SS__ << "At node '" + tablePair.first +
3881  "' error detected descending through children:\n" +
3882  e.what();
3883  *accumulatedTreeErrors += ss.str();
3884  }
3885  } // done checking for disconnects
3886 
3887  retMap.emplace(
3888  std::pair<std::string, ConfigurationTree>(tablePair.first, newNode));
3889  } //end active table loop
3890 
3891  return retMap;
3892 } // end getChildrenMap()
3893 
3894 //==============================================================================
3899 const TableBase* ConfigurationManager::getTableByName(const std::string& tableName) const
3900 {
3901  std::map<std::string, TableBase*>::const_iterator it;
3902  if((it = nameToTableMap_.find(tableName)) == nameToTableMap_.end())
3903  {
3904  __SS__ << "Cannot find table named '" << tableName
3905  << "' - you need to load the table before it can be used.";
3906 
3907  if(nameToTableMap_.size() == 0)
3908  ss << "\n\nAll tables are missing. Your configuration database connection "
3909  "may have been interrupted. Did an ssh tunnel disconnect?"
3910  << __E__;
3911  else
3912  {
3913  if(tableName == XDAQ_CONTEXT_TABLE_NAME)
3914  ss << "\n\nThe XDAQ Context Table is essential to the operation of ots. "
3915  "Without it, ots can not determine which applications are running "
3916  "on which hosts. Make sure that you have loaded a valid "
3917  "Configuration Context group that contains the XDAQ Context "
3918  "Table."
3919  << __E__;
3920  else
3921  ss << " It is likely missing from the member list of the Table "
3922  "Group that was loaded."
3923  << __E__;
3924 
3925  ss << "\nYou may need to enter wiz mode to remedy the situation, use the "
3926  "following:\n"
3927  "\n\t ots --wiz"
3928  "\n\n\n"
3929  << __E__;
3930 
3931  ss << __E__ << StringMacros::stackTrace() << __E__;
3932  }
3933 
3934  __SS_ONLY_THROW__;
3935  }
3936  TLOG_DEBUG(55) << "Table " << tableName << " is at "
3937  << static_cast<void*>(it->second);
3938  return it->second;
3939 } // end getTableByName()
3940 
3941 //==============================================================================
3946 {
3947  if(!theBackboneTableGroupKey_) // no active backbone
3948  {
3949  __GEN_COUT_WARN__ << "getTableGroupKey() Failed! No active backbone currently."
3950  << __E__;
3951  return TableGroupKey();
3952  }
3953 
3954  // may already be loaded, but that's ok, load anyway to be sure
3955  loadTableGroup(theBackboneTableGroup_, *theBackboneTableGroupKey_);
3956 
3957  return *theBackboneTableGroupKey_;
3958 } // end loadConfigurationBackbone()
3959 
3961 //==============================================================================
3973 std::pair<std::string, TableGroupKey> ConfigurationManager::getTableGroupFromAlias(
3974  std::string systemAlias, ProgressBar* progressBar)
3975 {
3976  // steps
3977  // check if special alias
3978  // if so, parse and return name/key
3979  // else, load active backbone
3980  // find runType in Group Aliases table
3981  // return key
3982 
3983  if(progressBar)
3984  progressBar->step();
3985 
3986  if(systemAlias.find("GROUP:") == 0)
3987  {
3988  if(progressBar)
3989  progressBar->step();
3990 
3991  unsigned int i = strlen("GROUP:");
3992  unsigned int j = systemAlias.find(':', i);
3993 
3994  if(progressBar)
3995  progressBar->step();
3996  if(j > i) // success
3997  return std::pair<std::string, TableGroupKey>(
3998  systemAlias.substr(i, j - i), TableGroupKey(systemAlias.substr(j + 1)));
3999  else // failure
4000  return std::pair<std::string, TableGroupKey>("", TableGroupKey());
4001  }
4002 
4004 
4005  if(progressBar)
4006  progressBar->step();
4007 
4008  try
4009  {
4010  // find runType in Group Aliases table
4011  ConfigurationTree entry =
4012  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getNode(systemAlias);
4013 
4014  if(progressBar)
4015  progressBar->step();
4016 
4017  return std::pair<std::string, TableGroupKey>(
4018  entry.getNode("GroupName").getValueAsString(),
4019  TableGroupKey(entry.getNode("GroupKey").getValueAsString()));
4020  }
4021  catch(...)
4022  {
4023  }
4024 
4025  // on failure, here
4026 
4027  if(progressBar)
4028  progressBar->step();
4029 
4030  return std::pair<std::string, TableGroupKey>("", TableGroupKey());
4031 } // end getTableGroupFromAlias()
4032 
4033 //==============================================================================
4036 std::map<std::string /*groupAlias*/, std::pair<std::string /*groupName*/, TableGroupKey>>
4038 {
4040  false /* throwErrors */,
4041  "" /* pathToActiveGroupsFile */,
4042  ConfigurationManager::LoadGroupType::
4043  ONLY_BACKBONE_TYPE); // make sure the active configuration backbone is
4044  // loaded from disk (i.e. the latest activated at the ConfigurationGUISupervisor)!
4045 
4046  std::map<std::string /*groupAlias*/,
4047  std::pair<std::string /*groupName*/, TableGroupKey>>
4048  retMap;
4049 
4050  std::vector<std::pair<std::string, ConfigurationTree>> entries =
4051  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
4052  for(auto& entryPair : entries)
4053  {
4054  retMap[entryPair.first] = std::pair<std::string, TableGroupKey>(
4055  entryPair.second.getNode("GroupName").getValueAsString(),
4056  TableGroupKey(entryPair.second.getNode("GroupKey").getValueAsString()));
4057  }
4058  return retMap;
4059 } // end getActiveGroupAliases()
4060 
4061 //==============================================================================
4064 std::set<std::pair<std::string /*table name*/, TableVersion /*aliased version*/>>
4065 ConfigurationManager::getVersionAliases(const std::string& tableAliasNeedle) const
4066 {
4067  std::set<std::pair<std::string /*table name*/, TableVersion /*aliased version*/>>
4068  retSet;
4069 
4070  auto tableAliasMap = getVersionAliases();
4071 
4072  for(auto& tableAliasMap : tableAliasMap)
4073  for(auto& tableAliasPair : tableAliasMap.second)
4074  if(tableAliasPair.first == tableAliasNeedle) //then table alias match!
4075  retSet.insert(std::pair<std::string /*table name*/,
4076  TableVersion /*aliased version*/>(
4077  tableAliasMap.first, tableAliasPair.second));
4078 
4079  return retSet;
4080 } //end getVersionAliases()
4081 
4082 //==============================================================================
4085 std::map<std::string /*table name*/,
4086  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
4088 {
4089  //__GEN_COUT__ << "getVersionAliases()" << __E__;
4090 
4091  std::map<std::string /*table name*/,
4092  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
4093  retMap;
4094 
4095  std::map<std::string, TableVersion> activeVersions = getActiveVersions();
4096  std::string versionAliasesTableName =
4097  ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
4098  if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
4099  {
4100  __SS__ << "Active version of VersionAliases missing!"
4101  << " Make sure you have a valid active Backbone Group." << __E__;
4102  __GEN_COUT_WARN__ << "\n" << ss.str();
4103  return retMap;
4104  }
4105 
4106  //__GEN_COUT__ << "activeVersions[\"" << versionAliasesTableName << "\"]=" << activeVersions[versionAliasesTableName] << __E__;
4107 
4108  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
4109  getNode(versionAliasesTableName).getChildren();
4110 
4111  // create map
4112  // add the first of each tableName, versionAlias pair encountered
4113  // ignore any repeats (Note: this also prevents overwriting of Scratch alias)
4114  std::string tableName, versionAlias;
4115  for(auto& aliasNodePair : aliasNodePairs)
4116  {
4117  tableName = aliasNodePair.second.getNode("TableName").getValueAsString();
4118  versionAlias = aliasNodePair.second.getNode("VersionAlias").getValueAsString();
4119 
4120  if(retMap.find(tableName) != retMap.end() &&
4121  retMap[tableName].find(versionAlias) != retMap[tableName].end())
4122  continue; // skip repeats (Note: this also prevents overwriting of Scratch
4123  // alias)
4124 
4125  // else add version to map
4126  retMap[tableName][versionAlias] =
4127  TableVersion(aliasNodePair.second.getNode("Version").getValueAsString());
4128  }
4129 
4130  return retMap;
4131 } // end getVersionAliases()
4132 
4133 //==============================================================================
4135 std::map<std::string, TableVersion> ConfigurationManager::getActiveVersions(void) const
4136 {
4137  std::map<std::string, TableVersion> retMap;
4138  for(auto& table : nameToTableMap_)
4139  {
4140  __GEN_COUTS__(2) << table.first << __E__;
4141 
4142  // check configuration pointer is not null and that there is an active view
4143  if(table.second && table.second->isActive())
4144  {
4145  __GEN_COUTS__(2) << table.first << "_v" << table.second->getViewVersion()
4146  << __E__;
4147  retMap.insert(std::pair<std::string, TableVersion>(
4148  table.first, table.second->getViewVersion()));
4149  }
4150  }
4151 
4152  return retMap;
4153 } // end getActiveVersions()
4154 
4157 //{
4158 //
4159 // //fixme/todo this is called before setupAll so it breaks!
4160 // //====================================================
4161 // const DetectorConfiguration* detectorConfiguration =
4162 //__GET_CONFIG__(DetectorConfiguration); for(auto& type :
4163 // detectorConfiguration->getDetectorTypes()) theDACsConfigurations_[type] =
4164 //(DACsTableBase*)(getTableByName(type + "DACsConfiguration"));
4165 // //====================================================
4166 //
4167 // theDACStreams_[fecName].makeStream(fecName,
4168 // __GET_CONFIG__(DetectorConfiguration),
4169 // __GET_CONFIG__(DetectorToFEConfiguration),
4170 // theDACsConfigurations_,
4171 // __GET_CONFIG__(MaskConfiguration));//, theTrimConfiguration_);
4172 //
4173 // __GEN_COUT__ << "Done with DAC stream!" << __E__;
4174 // return theDACStreams_[fecName];
4175 //}
4176 
4177 //==============================================================================
4178 std::shared_ptr<TableGroupKey> ConfigurationManager::makeTheTableGroupKey(
4179  TableGroupKey key)
4180 {
4181  if(theConfigurationTableGroupKey_)
4182  {
4183  if(*theConfigurationTableGroupKey_ != key)
4185  else
4186  return theConfigurationTableGroupKey_;
4187  }
4188  return std::shared_ptr<TableGroupKey>(new TableGroupKey(key));
4189 } // end makeTheTableGroupKey()
4190 
4191 //==============================================================================
4192 const std::set<std::string>& ConfigurationManager::getActiveContextMemberNames()
4193 {
4194  //copy fixed context tables, then add optional tables if active
4195  contextMemberNames_ = ConfigurationManager::fixedContextMemberNames_;
4196 
4197  auto it =
4198  nameToTableMap_.find(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
4199  if(it == nameToTableMap_.end())
4200  return contextMemberNames_;
4201 
4202  if(!it->second->isActive()) //if optional table is active, add it
4203  {
4204  contextMemberNames_.emplace(
4205  ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
4206  }
4207  return contextMemberNames_;
4208 } // end getContextMemberNames()
4209 
4210 //==============================================================================
4211 const std::set<std::string>& ConfigurationManager::getFixedContextMemberNames()
4212 {
4213  return ConfigurationManager::fixedContextMemberNames_;
4214 } // end getContextMemberNames()
4215 
4216 //==============================================================================
4217 const std::set<std::string>& ConfigurationManager::getBackboneMemberNames()
4218 {
4219  return ConfigurationManager::backboneMemberNames_;
4220 } // end getBackboneMemberNames()
4221 
4222 //==============================================================================
4223 const std::set<std::string>& ConfigurationManager::getIterateMemberNames()
4224 {
4225  return ConfigurationManager::iterateMemberNames_;
4226 } // end getIterateMemberNames()
4227 
4228 //==============================================================================
4229 const std::set<std::string>& ConfigurationManager::getConfigurationMemberNames(void)
4230 {
4231  configurationMemberNames_.clear();
4232 
4233  std::map<std::string, TableVersion> activeTables = getActiveVersions();
4234 
4235  for(auto& tablePair : activeTables)
4236  if(
4237  //check if not context table
4238  ConfigurationManager::fixedContextMemberNames_.find(tablePair.first) ==
4239  ConfigurationManager::fixedContextMemberNames_.end() &&
4240  tablePair.first != ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE &&
4241 
4242  //check if not backbone table
4243  ConfigurationManager::backboneMemberNames_.find(tablePair.first) ==
4244  ConfigurationManager::backboneMemberNames_.end() &&
4245 
4246  //check if not iterate table
4247  ConfigurationManager::iterateMemberNames_.find(tablePair.first) ==
4248  ConfigurationManager::iterateMemberNames_.end())
4249  {
4250  // else, it is a configuration table
4251  configurationMemberNames_.emplace(tablePair.first);
4252  }
4253 
4254  return configurationMemberNames_;
4255 } // end getConfigurationMemberNames()
4256 
4257 //==============================================================================
4258 void ConfigurationManager::initializeFromFhicl(const std::string& fhiclPath)
4259 {
4260  __GEN_COUT__ << "Initializing from fhicl: " << fhiclPath << __E__;
4261 
4262  // https://cdcvs.fnal.gov/redmine/projects/fhicl-cpp/wiki
4263 
4264  // LoadParameterSet() ... from $ARTDAQ_INC/artdaq/Application/LoadParameterSet.hh
4265  fhicl::ParameterSet pset = LoadParameterSet(fhiclPath);
4266 
4267  if(pset.get_names().size() == 0)
4268  {
4269  __GEN_SS__ << "Empty fcl configuration parameter set found! File: " << fhiclPath
4270  << __E__;
4271  __SS_THROW__;
4272  }
4273 
4274  //===========================
4275  // fcl should be FE record(s):
4276  // interface0: {
4277  // FEInterfacePluginName: "FEOtsUDPTemplateInterface"
4278  // LinkToFETypeTable_FEOtsUDPTemplateInterfaceTable: {
4279  // OtsInterface0: {
4280  // InterfaceIPAddress: "127.0.0.1"
4281  // InterfacePort: 4000
4282  // HostIPAddress: "127.0.0.1"
4283  // HostPort: 4020
4284  // StreamToIPAddress: "127.0.0.1"
4285  // StreamToPort: 4021
4286  // }
4287  // } //end FEOtsUDPTemplateInterfaceTable link record
4288  // } //end interface0
4289  //===========================
4290 
4291  // Steps:
4292  // Create one context with one FE supervisor
4293  // and one/many FEs specified by fcl
4294  //
4295 
4296  TableBase* table;
4297 
4298  // create context and add context record
4299  {
4300  table = 0;
4301  theInterface_->get(table, // configurationPtr
4302  ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME, // tableName
4303  0, // groupKey
4304  0, // groupName
4305  true // dontFill=false to fill
4306  );
4307 
4308  nameToTableMap_[ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME] = table;
4309 
4310  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4311  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4312 
4313  TableView* view = table->getViewP();
4314  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4315  // view->print();
4316 
4317  // add context record ---------------------
4318  view->addRow();
4319  auto colMap = view->getColumnNamesMap();
4320 
4321  view->setValue("MacroMakerFEContext", 0, colMap["ContextUID"]);
4322  view->setValue("XDAQApplicationTable", 0, colMap["LinkToApplicationTable"]);
4323  view->setValue("MacroMakerFEContextApps", 0, colMap["LinkToApplicationGroupID"]);
4324  view->setValue("1", 0, colMap[TableViewColumnInfo::COL_NAME_STATUS]);
4325 
4326  __GEN_COUT__ << "Done adding context record..." << __E__;
4327  view->print();
4328 
4329  } // done with context record
4330 
4331  // create app table and add application record
4332  {
4333  table = 0;
4334  theInterface_->get(
4335  table, // configurationPtr
4336  ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME, // tableName
4337  0, // groupKey
4338  0, // groupName
4339  true // dontFill=false to fill
4340  );
4341 
4342  nameToTableMap_[ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME] = table;
4343 
4344  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4345  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4346 
4347  TableView* view = table->getViewP();
4348  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4349  // view->print();
4350 
4351  // add application record ---------------------
4352  view->addRow();
4353  auto colMap = view->getColumnNamesMap();
4354 
4355  view->setValue("MacroMakerFEContextApps", 0, colMap["ApplicationGroupID"]);
4356  view->setValue("MacroMakerFESupervisor", 0, colMap["ApplicationUID"]);
4357  view->setValue("FESupervisorTable", 0, colMap["LinkToSupervisorTable"]);
4358  view->setValue("MacroMakerFESupervisor", 0, colMap["LinkToSupervisorUID"]);
4359  view->setValue("1", 0, colMap[TableViewColumnInfo::COL_NAME_STATUS]);
4360  view->setValue(__ENV__("FE_SUPERVISOR_ID"), 0, colMap["Id"]); // XDAQ LID
4361 
4362  __GEN_COUT__ << "Done adding application record..." << __E__;
4363  view->print();
4364  } // done with app record
4365 
4366  // create FE Supervisor table and Supervisor record
4367  {
4368  table = 0;
4369  theInterface_->get(table, // configurationPtr
4370  "FESupervisorTable", // tableName
4371  0, // groupKey
4372  0, // groupName
4373  true // dontFill=false to fill
4374  );
4375 
4376  nameToTableMap_["FESupervisorTable"] = table;
4377 
4378  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4379  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4380 
4381  TableView* view = table->getViewP();
4382  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4383  // view->print();
4384 
4385  // add application record ---------------------
4386  view->addRow();
4387  auto colMap = view->getColumnNamesMap();
4388 
4389  view->setValue("MacroMakerFESupervisor", 0, colMap["SupervisorUID"]);
4390  view->setValue("FEInterfaceTable", 0, colMap["LinkToFEInterfaceTable"]);
4391  view->setValue(
4392  "MacroMakerFESupervisorInterfaces", 0, colMap["LinkToFEInterfaceGroupID"]);
4393 
4394  __GEN_COUT__ << "Done adding supervisor record..." << __E__;
4395  view->print();
4396  } // done with app record
4397 
4398  // create FE Interface table and interface record(s)
4399  recursiveInitFromFhiclPSet("FEInterfaceTable" /*tableName*/,
4400  pset /*fhicl parameter set*/,
4401  "" /*uid*/,
4402  "MacroMakerFESupervisorInterfaces" /*groupID*/,
4403  "FE" /*childLinkIndex*/);
4404 
4405  // init every table after modifications
4406  for(auto& table : nameToTableMap_)
4407  {
4408  table.second->getViewP()->init();
4409  }
4410 
4411  // verify extraction
4412  if(0)
4413  {
4414  __GEN_COUT__ << "================================================" << __E__;
4415  nameToTableMap_["FESupervisorTable"]->getViewP()->print();
4416  nameToTableMap_["FEInterfaceTable"]->getViewP()->print();
4417 
4418  auto sups = getNode("FESupervisorTable").getChildrenNames();
4419  __GEN_COUT__ << "Supervisors extracted from fhicl: " << sups.size() << __E__;
4420  auto fes = getNode("FEInterfaceTable").getChildrenNames();
4421  __GEN_COUT__ << "Front-ends extracted from fhicl: " << fes.size() << __E__;
4422  {
4423  auto a = getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME);
4424  __GEN_COUTV__(a.getValueAsString());
4425 
4426  auto b = a.getNode("MacroMakerFEContext");
4427  __GEN_COUTV__(b.getValueAsString());
4428 
4429  auto c = b.getNode("LinkToApplicationTable");
4430  __GEN_COUTV__(c.getValueAsString());
4431 
4432  auto d = c.getNode("MacroMakerFESupervisor");
4433  __GEN_COUTV__(d.getValueAsString());
4434 
4435  auto e = d.getNode("LinkToSupervisorTable");
4436  __GEN_COUTV__(e.getValueAsString());
4437 
4438  auto f = e.getNode("LinkToFEInterfaceTable");
4439  __GEN_COUTV__(f.getValueAsString());
4440 
4441  auto z = f.getChildrenNames();
4442  __GEN_COUTV__(StringMacros::vectorToString(z));
4443  __GEN_COUTV__(z.size());
4444  auto y = f.getChildrenNames(false /*byPriority*/, true /*onlyStatusTrue*/);
4445  __GEN_COUTV__(StringMacros::vectorToString(y));
4446  __GEN_COUTV__(y.size());
4447  auto x = f.getChildrenNames(true /*byPriority*/, true /*onlyStatusTrue*/);
4448  __GEN_COUTV__(StringMacros::vectorToString(x));
4449  __GEN_COUTV__(x.size());
4450 
4451  auto g = f.getNode("dtc0");
4452  __GEN_COUTV__(g.getValueAsString());
4453  auto h = f.getNode("interface0");
4454  __GEN_COUTV__(h.getValueAsString());
4455 
4456  auto fes =
4457  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME)
4458  .getNode(
4459  "MacroMakerFEContext/LinkToApplicationTable/"
4460  "MacroMakerFESupervisor/LinkToSupervisorTable")
4461  .getNode("LinkToFEInterfaceTable")
4462  .getChildrenNames(true /*byPriority*/, true /*onlyStatusTrue*/);
4463  __GEN_COUTV__(fes.size());
4464  __GEN_COUTV__(StringMacros::vectorToString(fes));
4465  }
4466  }
4467 
4468 } // end initializeFromFhicl()
4469 
4470 //==============================================================================
4475 void ConfigurationManager::recursiveInitFromFhiclPSet(const std::string& tableName,
4476  const fhicl::ParameterSet& pset,
4477  const std::string& recordName,
4478  const std::string& groupName,
4479  const std::string& groupLinkIndex)
4480 {
4481  __GEN_COUT__ << __COUT_HDR_P__ << "Adding table '" << tableName << "' record(s)..."
4482  << __E__;
4483 
4484  TableBase* table;
4485  // create context and add context record
4486  {
4487  table = 0;
4488  if(nameToTableMap_.find(tableName) == nameToTableMap_.end())
4489  {
4490  __GEN_COUT__ << "Table not found, so making '" << tableName << "' instance..."
4491  << __E__;
4492  theInterface_->get(table, // configurationPtr
4493  tableName, // tableName
4494  0, // groupKey
4495  0, // groupName
4496  true // dontFill=false to fill
4497  );
4498 
4499  nameToTableMap_[tableName] = table;
4500  table->setupMockupView(TableVersion(TableVersion::DEFAULT));
4501  }
4502  else
4503  {
4504  __GEN_COUT__ << "Existing table found, so using '" << tableName
4505  << "'instance..." << __E__;
4506  table = nameToTableMap_[tableName];
4507  }
4508 
4509  table->setActiveView(TableVersion(TableVersion::DEFAULT));
4510 
4511  TableView* view = table->getViewP();
4512  __GEN_COUT__ << "Activated version: " << view->getVersion() << __E__;
4513  // view->print();
4514 
4515  if(recordName != "") // then add this record
4516  {
4517  // Steps:
4518  // - add row
4519  // - set UID and enable (if possible)
4520  // - set values for parameter columns
4521  // - define links
4522 
4523  __GEN_COUTV__(recordName);
4524 
4525  // add row and get column map
4526  unsigned int r = view->addRow();
4527  auto colMap = view->getColumnNamesMap();
4528 
4529  // set UID and enable (if possible)
4530  view->setValue(recordName, r, view->getColUID());
4531  try
4532  {
4533  view->setValue("1", r, view->getColStatus());
4534  }
4535  catch(...)
4536  {
4537  __GEN_COUT__ << "No status column to set for '" << recordName << "'"
4538  << __E__;
4539  }
4540 
4541  if(groupName != "") // then set groupID for this record
4542  {
4543  __GEN_COUT__ << "Setting group ID for group link index '"
4544  << groupLinkIndex << "'" << __E__;
4545 
4546  int groupIDCol = view->getLinkGroupIDColumn(groupLinkIndex);
4547  __GEN_COUT__ << "Setting group ID for group link index '"
4548  << groupLinkIndex << "' at column " << groupIDCol << " to '"
4549  << groupName << ".'" << __E__;
4550 
4551  view->setValue(groupName, r, groupIDCol);
4552  }
4553 
4554  // then set parameters
4555  auto names = pset.get_names();
4556  for(const auto& colName : names)
4557  {
4558  if(!pset.is_key_to_atom(colName))
4559  continue;
4560 
4561  auto colIt = colMap.find(colName);
4562  if(colIt == colMap.end())
4563  {
4564  __SS__ << "Field '" << colName << "' of record '" << recordName
4565  << "' in table '" << tableName << "' was not found in columns."
4566  << "\n\nHere are the existing column names:\n";
4567  unsigned int i = 0;
4568  for(const auto& col : colMap)
4569  ss << "\n" << ++i << ".\t" << col.first;
4570  ss << __E__;
4571  __SS_THROW__;
4572  }
4573  // skip overwriting group ID - already setup by parent group link
4574  if(view->getColumnInfo(colIt->second).isGroupID())
4575  continue;
4576 
4577  const std::string value = pset.get<std::string>(colName);
4578  __GEN_COUT__ << "Setting '" << recordName << "' parameter at column "
4579  << colIt->second << ", '" << colName << "'\t = " << value
4580  << __E__;
4581  view->setValueAsString(value, r, colIt->second);
4582  } // end set parameters
4583 
4584  // then define links
4585  for(const auto& linkName : names)
4586  {
4587  if(pset.is_key_to_atom(linkName))
4588  continue;
4589 
4590  __GEN_COUTV__(linkName);
4591 
4592  // split into column name and table
4593  unsigned int c = linkName.size() - 1;
4594  for(; c >= 1; --c)
4595  if(linkName[c] == '_') // find first underscore to split linkName
4596  break;
4597 
4598  if(c == 0)
4599  {
4600  __SS__ << "Illegal link name '" << linkName
4601  << "' found. The format must be <Column name>_<Target table "
4602  "name>,.. for example '"
4603  << "LinkToFETypeTable_FEOtsUDPTemplateInterfaceTable'"
4604  << __E__;
4605  __SS_THROW__;
4606  }
4607  std::string colName = linkName.substr(0, c);
4608  __GEN_COUTV__(colName);
4609 
4610  auto colIt = colMap.find(colName);
4611  if(colIt == colMap.end())
4612  {
4613  __SS__ << "Link '" << colName << "' of record '" << recordName
4614  << "' in table '" << tableName << "' was not found in columns."
4615  << "\n\nHere are the existing column names:\n";
4616  unsigned int i = 0;
4617  for(const auto& col : colMap)
4618  ss << "\n" << i << ".\t" << col.first << __E__;
4619  __SS_THROW__;
4620  }
4621  //__GEN_COUT__ << "Setting link at column " << colIt->second << __E__;
4622 
4623  std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>
4624  linkPair;
4625  bool isGroupLink;
4626  view->getChildLink(colIt->second, isGroupLink, linkPair);
4627 
4628  //__GEN_COUTV__(isGroupLink);
4629  //__GEN_COUTV__(linkPair.first);
4630  //__GEN_COUTV__(linkPair.second);
4631 
4632  std::string linkTableName = linkName.substr(c + 1);
4633  __GEN_COUTV__(linkTableName);
4634 
4635  auto linkPset = pset.get<fhicl::ParameterSet>(linkName);
4636  auto linkRecords = linkPset.get_pset_names();
4637  if(!isGroupLink && linkRecords.size() > 1)
4638  {
4639  __SS__ << "A Unique Link can only point to one record. "
4640  << "The specified link '" << colName << "' of record '"
4641  << recordName << "' in table '" << tableName << "' has "
4642  << linkRecords.size() << " children records specified. "
4643  << __E__;
4644  __SS_THROW__;
4645  }
4646 
4647  if(linkRecords.size() == 0)
4648  {
4649  __GEN_COUT__ << "No child records, so leaving link disconnected."
4650  << __E__;
4651  continue;
4652  }
4653 
4654  __GEN_COUT__ << "Setting Link at columns [" << linkPair.first << ","
4655  << linkPair.second << "]" << __E__;
4656  view->setValue(linkTableName, r, linkPair.first);
4657 
4658  if(!isGroupLink)
4659  {
4660  __GEN_COUT__ << "Setting up Unique link to " << linkRecords[0]
4661  << __E__;
4662 
4663  view->setValue(linkRecords[0], r, linkPair.second);
4664 
4665  recursiveInitFromFhiclPSet(
4666  linkTableName /*tableName*/,
4667  linkPset.get<fhicl::ParameterSet>(
4668  linkRecords[0]) /*fhicl parameter set*/,
4669  linkRecords[0] /*uid*/,
4670  "" /*groupID*/);
4671  }
4672  else
4673  {
4674  std::string childLinkIndex =
4675  view->getColumnInfo(linkPair.first).getChildLinkIndex();
4676  std::string groupName = recordName + "Group";
4677 
4678  view->setValue(groupName, r, linkPair.second);
4679 
4680  for(const auto& groupRecord : linkRecords)
4681  {
4682  __GEN_COUT__ << "Setting '" << childLinkIndex
4683  << "' Group link to '" << groupName << "' record '"
4684  << groupRecord << "'" << __E__;
4685 
4686  recursiveInitFromFhiclPSet(
4687  linkTableName /*tableName*/,
4688  linkPset.get<fhicl::ParameterSet>(
4689  groupRecord) /*fhicl parameter set*/,
4690  groupRecord /*uid*/,
4691  groupName /*groupID*/,
4692  childLinkIndex /*groupLinkIndex*/);
4693  }
4694  }
4695 
4696  } // end link handling
4697  }
4698  else if(groupName != "") // then add group of records
4699  {
4700  // get_pset_names();
4701  // get_names
4702  __GEN_COUTV__(groupName);
4703  auto psets = pset.get_pset_names();
4704  for(const auto& ps : psets)
4705  {
4706  __GEN_COUTV__(ps);
4707  recursiveInitFromFhiclPSet(
4708  tableName /*tableName*/,
4709  pset.get<fhicl::ParameterSet>(ps) /*fhicl parameter set*/,
4710  ps /*uid*/,
4711  groupName /*groupID*/,
4712  groupLinkIndex /*groupLinkIndex*/);
4713  }
4714  }
4715  else
4716  {
4717  __SS__ << "Illegal recursive parameters!" << __E__;
4718  __SS_THROW__;
4719  }
4720  __GEN_COUT__ << __COUT_HDR_P__ << "Done adding table '" << tableName
4721  << "' record(s)..." << __E__;
4722  view->print();
4723  }
4724 
4725 } // end recursiveInitFromFhiclPSet()
4726 
4727 //==============================================================================
4732 {
4733  __GEN_COUTS__(11) << "Checking if owner '" << ownerContextUID_ << "/" << ownerAppUID_
4734  << "' is first App in Context:\n"
4735  << StringMacros::stackTrace() << __E__;
4736 
4737  if(ownerContextUID_ == "" || ownerAppUID_ == "")
4738  {
4739  __GEN_COUTTV__(!forceNotFirstInContext_);
4740  return !forceNotFirstInContext_; // default to 'yes' unless forced
4741  }
4742 
4743  __GEN_COUTVS__(10, ownerContextUID_);
4744  __GEN_COUTVS__(10, ownerAppUID_);
4745 
4746  try
4747  {
4748  auto contextChildren =
4749  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME + "/" +
4750  ownerContextUID_ + "/LinkToApplicationTable")
4751  .getChildrenNames(false /* byPriority */, true /* onlyStatusTrue */);
4752 
4753  if(contextChildren.size() == 0) // no enabled apps, check if owner is app[0]
4754  {
4755  contextChildren =
4756  getNode(ConfigurationManager::XDAQ_CONTEXT_TABLE_NAME + "/" +
4757  ownerContextUID_ + "/LinkToApplicationTable")
4758  .getChildrenNames(false /* byPriority */, false /* onlyStatusTrue */);
4759  __GEN_COUTVS__(10, StringMacros::vectorToString(contextChildren));
4760  }
4761  else
4762  __GEN_COUTVS__(10, StringMacros::vectorToString(contextChildren));
4763 
4764  bool isFirstAppInContext =
4765  contextChildren.size() == 0 || contextChildren[0] == ownerAppUID_;
4766 
4767  __GEN_COUTVS__(10, isFirstAppInContext);
4768 
4769  return isFirstAppInContext;
4770  }
4771  catch(...)
4772  {
4773  __GEN_COUTS__(10) << "Exception caught looking for XDAQ Context '"
4774  << ownerContextUID_ << "' in tree, so defaulting to 'yes'."
4775  << __E__;
4776  return true; // default to 'yes' if XDAQ Context doesn't exist
4777  }
4778 } // end isOwnerFirstAppInContext()
4779 
4780 //==============================================================================
4784  const std::string& otherSubsystemUID,
4785  std::string* userDataPathPtr /* = nullptr */,
4786  std::string* hostnamePtr /* = nullptr */,
4787  std::string* usernamePtr /* = nullptr */,
4788  std::string* fullNamePtr /* = nullptr */)
4789 {
4790  __GEN_COUTTV__(otherSubsystemUID);
4791 
4792  ConfigurationTree node =
4793  getNode(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE)
4794  .getNode(otherSubsystemUID);
4795  std::string userPath = node.getNode("SubsystemUserDataPath").getValue();
4796  if(fullNamePtr)
4797  *fullNamePtr = node.getNode("SubsystemFullName").getValue();
4798 
4799  auto splitPath = StringMacros::getVectorFromString(userPath, {':'});
4800  __GEN_COUTTV__(StringMacros::vectorToString(splitPath));
4801 
4802  if(!splitPath.size() || splitPath.size() > 2)
4803  {
4804  __GEN_SS__ << "Illegal user data path specified for subsystem '"
4805  << otherSubsystemUID << "': " << userPath << __E__;
4806  __SS_ONLY_THROW__;
4807  }
4808  std::string userDataPath = splitPath[splitPath.size() - 1];
4809 
4810  //since we are running exec, cleanse the filename path for alphanumeric,_,-,/ only
4811  for(unsigned int i = 0; i < userDataPath.length(); ++i)
4812  if(!((userDataPath[i] >= 'a' && userDataPath[i] <= 'z') ||
4813  (userDataPath[i] >= 'A' && userDataPath[i] <= 'Z') ||
4814  (userDataPath[i] >= '0' && userDataPath[i] <= '9') ||
4815  userDataPath[i] == '-' || userDataPath[i] == '_' || userDataPath[i] == '/'))
4816  {
4817  __GEN_SS__ << "Illegal user data path specified (no special characters "
4818  "allowed) for subsystem '"
4819  << otherSubsystemUID << "': " << userPath << __E__;
4820  __SS_ONLY_THROW__;
4821  } // end filename cleanse
4822 
4823  if(userDataPathPtr)
4824  *userDataPathPtr = userDataPath;
4825 
4826  std::string username, hostname;
4827  if(splitPath.size() == 2) //then need to scp the file
4828  {
4829  //since we are running exec, cleanse the username@host path for alphanumeric,_,-,/ only
4830  std::vector<std::string> userHostSplit =
4831  StringMacros::getVectorFromString(splitPath[0], {'@'});
4832  __GEN_COUTTV__(userHostSplit.size());
4833  if(userHostSplit.size() == 1)
4834  hostname = userHostSplit[0];
4835  else if(userHostSplit.size() == 2)
4836  {
4837  username = userHostSplit[0];
4838  hostname = userHostSplit[1];
4839  }
4840  else
4841  {
4842  __GEN_SS__ << "Illegal remote username/host specified for subsystem '"
4843  << otherSubsystemUID << "': " << userPath << __E__;
4844  __SS_ONLY_THROW__;
4845  }
4846 
4847  for(unsigned int i = 0; userHostSplit.size() == 2 && i < username.length(); ++i)
4848  if(!((username[i] >= 'a' && username[i] <= 'z') ||
4849  (username[i] >= 'A' && username[i] <= 'Z') ||
4850  (username[i] >= '0' && username[i] <= '9') || username[i] == '-' ||
4851  username[i] == '_'))
4852  {
4853  __GEN_SS__ << "Illegal remote username specified for subsystem '"
4854  << otherSubsystemUID << "': " << userPath << __E__;
4855  __SS_ONLY_THROW__;
4856  }
4857  unsigned int ii = 0; //track last . to prevent weird . usage
4858  for(unsigned int i = 0; i < hostname.length(); ++i)
4859  if(!((hostname[i] >= 'a' && hostname[i] <= 'z') ||
4860  (hostname[i] >= 'A' && hostname[i] <= 'Z') ||
4861  (hostname[i] >= '0' && hostname[i] <= '9') || hostname[i] == '-' ||
4862  hostname[i] == '_'))
4863  {
4864  if(hostname[i] == '.' && i > ii + 1)
4865  {
4866  //its ok to have this . so track position
4867  ii = i;
4868  }
4869  else //else not ok to have .. or other characters
4870  {
4871  __GEN_SS__ << "Illegal remote hostname '" << hostname
4872  << "' specified for subsystem '" << otherSubsystemUID
4873  << "': " << userPath << __E__;
4874  __SS_ONLY_THROW__;
4875  }
4876  }
4877  }
4878  else if(splitPath.size() == 1) //then can just directly access the file
4879  {
4880  __GEN_COUT__ << "Local user date path identified." << __E__;
4881  }
4882  else
4883  {
4884  __GEN_SS__ << "Illegal user data path specified for subsystem '"
4885  << otherSubsystemUID << "': " << userPath << __E__;
4886  __SS_ONLY_THROW__;
4887  }
4888 
4889  if(hostnamePtr)
4890  *hostnamePtr = hostname;
4891  if(usernamePtr)
4892  *usernamePtr = username;
4893 
4894 } // end getOtherSubsystemInstanceInfo()
4895 
4896 //==============================================================================
4897 std::map<std::string /*groupType*/, std::pair<std::string /*groupName*/, TableGroupKey>>
4898 ConfigurationManager::getOtherSubsystemActiveTableGroups(
4899  const std::string& otherSubsystemUID,
4900  std::string* userDataPathPtr /* = nullptr */,
4901  std::string* hostnamePtr /* = nullptr */,
4902  std::string* usernamePtr /* = nullptr */)
4903 {
4904  std::map<std::string /*groupType*/,
4905  std::pair<std::string /*groupName*/, TableGroupKey>>
4906  retMap;
4907 
4908  __GEN_COUTTV__(otherSubsystemUID);
4909 
4910  std::string userDataPath;
4911  std::string username, hostname;
4912 
4913  getOtherSubsystemInstanceInfo(otherSubsystemUID, &userDataPath, &hostname, &username);
4914 
4915  __GEN_COUTTV__(userDataPath);
4916  __GEN_COUTTV__(username);
4917  __GEN_COUTTV__(hostname);
4918 
4919  if(userDataPathPtr)
4920  *userDataPathPtr = userDataPath;
4921  if(hostnamePtr)
4922  *hostnamePtr = hostname;
4923  if(usernamePtr)
4924  *usernamePtr = username;
4925 
4926  //enforce filename ends correctly
4927  std::string filename = userDataPath + "/ServiceData/ActiveTableGroups.cfg";
4928 
4929  std::string cmdResult;
4930 
4931  if(hostname != "")
4932  {
4933  std::string tmpSubsystemFilename =
4934  ConfigurationManager::ACTIVE_GROUPS_FILENAME + "." + otherSubsystemUID;
4935  __GEN_COUTTV__(tmpSubsystemFilename);
4936  if(username != "") //has username
4937  {
4938  cmdResult = StringMacros::exec(
4939  ("rm " + tmpSubsystemFilename + " 2>/dev/null; scp " + username + "@" +
4940  hostname + ":" + filename + " " + tmpSubsystemFilename + " 2>&1; cat " +
4941  tmpSubsystemFilename + " 2>&1")
4942  .c_str());
4943  }
4944  else
4945  cmdResult = StringMacros::exec(
4946  ("rm " + tmpSubsystemFilename + " 2>/dev/null; scp " + hostname + ":" +
4947  filename + " " + tmpSubsystemFilename + " 2>&1; cat " +
4948  tmpSubsystemFilename + " 2>&1")
4949  .c_str());
4950  }
4951  else //then can just directly access the file
4952  {
4953  __GEN_COUT__ << "Local user date path identified." << __E__;
4954  cmdResult = StringMacros::exec(("cat " + filename + " 2>&1").c_str());
4955  }
4956 
4957  __GEN_COUTTV__(cmdResult);
4958  if(cmdResult.find("Permission denied") != std::string::npos)
4959  {
4960  __GEN_SS__
4961  << "\n\nPermission denied accessing user data path specified for subsystem '"
4962  << otherSubsystemUID << "': ";
4963  if(username != "")
4964  ss << username << "@";
4965  if(hostname != "")
4966  ss << hostname << ":";
4967  ss << userDataPath << __E__;
4968  __SS_ONLY_THROW__;
4969  }
4970 
4971  auto subsystemActiveGroupMap = StringMacros::getVectorFromString(
4972  cmdResult, {'\n'} /* delimieter*/, {' ', '\t'} /* whitespace*/);
4973  __GEN_COUTTV__(StringMacros::vectorToString(subsystemActiveGroupMap));
4974  __GEN_COUTTV__(subsystemActiveGroupMap.size());
4975 
4976  std::string //groupComment, groupAuthor, groupCreationTime,
4977  groupType;
4978  for(unsigned int i = 0; i + 1 < subsystemActiveGroupMap.size(); i += 2)
4979  {
4980  if(subsystemActiveGroupMap[i] == "" || subsystemActiveGroupMap[i + 1] == "-1")
4981  continue;
4982 
4983  __GEN_COUTT__ << "Loading type of subsystem '" << otherSubsystemUID << "' group "
4984  << subsystemActiveGroupMap[i] << "("
4985  << subsystemActiveGroupMap[i + 1] << ")" << __E__;
4986 
4987  try
4988  {
4989  loadTableGroup(subsystemActiveGroupMap[i] /*groupName*/,
4990  TableGroupKey(subsystemActiveGroupMap[i + 1]),
4991  false /*doActivate*/,
4992  0 /*groupMembers*/,
4993  0 /*progressBar*/,
4994  0 /*accumulateErrors*/,
4995  0, // &groupComment,
4996  0, //&groupAuthor,
4997  0, //&groupCreationTime,
4998  true /*doNotLoadMember*/,
4999  &groupType);
5000  }
5001  catch(const std::runtime_error& e)
5002  {
5003  __GEN_COUTT__ << "Ignoring error loading subsystem '" << otherSubsystemUID
5004  << "' group " << subsystemActiveGroupMap[i] << "("
5005  << subsystemActiveGroupMap[i + 1] << "): " << __E__ << e.what()
5006  << __E__;
5007  groupType = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
5008  }
5009  retMap[groupType] = std::make_pair(subsystemActiveGroupMap[i],
5010  TableGroupKey(subsystemActiveGroupMap[i + 1]));
5011  } //end load table group loop
5012 
5013  __GEN_COUTTV__(StringMacros::mapToString(retMap));
5014  return retMap;
5015 } //end getOtherSubsystemActiveTableGroups()
5016 
5017 //==============================================================================
5019 std::set<std::string /* configAlias */>
5020 ConfigurationManager::getOtherSubsystemConfigAliases(const std::string& otherSubsystemUID)
5021 {
5022  std::set<std::string> retSet;
5023 
5024  __GEN_COUTTV__(otherSubsystemUID);
5025 
5026  std::map<std::string /*groupType*/,
5027  std::pair<std::string /*groupName*/, TableGroupKey>>
5028  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
5029 
5030  __GEN_COUTTV__(StringMacros::mapToString(retMap));
5031 
5032  //load backbone
5033  auto it = retMap.find(
5034  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
5035  if(it == retMap.end())
5036  {
5037  __GEN_SS__
5038  << "No active Backbone group found in the active groups of remote subsystem '"
5039  << otherSubsystemUID << "!'" << __E__;
5040  __GEN_SS_THROW__;
5041  }
5042  auto it2 = retMap.find(
5043  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
5044  if(it2 == retMap.end())
5045  {
5046  __GEN_SS__
5047  << "No active Context group found in the active groups of remote subsystem '"
5048  << otherSubsystemUID << "!'" << __E__;
5049  __GEN_SS_THROW__;
5050  }
5051 
5052  std::string accumulatedWarnings;
5053 
5054  // be careful to not activate! which calls init() and then generates output files to disk
5055  // and changes the system active group; instead only setActiveView
5056  loadTableGroup(it->second.first,
5057  it->second.second,
5058  false /*doActivate*/,
5059  0 /*groupMembers*/,
5060  0 /*progressBar*/,
5061  &accumulatedWarnings /*accumulateWarnings = 0*/
5062  );
5063  __GEN_COUTTV__(accumulatedWarnings);
5064 
5065  //get aliases (a la ConfigurationManager::getActiveGroupAliases:2888)
5066  std::vector<std::pair<std::string, ConfigurationTree>> entries =
5067  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
5068 
5069  for(auto& entry : entries)
5070  {
5071  if(entry.first.find("Context") == std::string::npos &&
5072  entry.first.find("Iterat") == std::string::npos)
5073  retSet.emplace(entry.first);
5074  }
5075  __GEN_COUTTV__(StringMacros::setToString(retSet));
5076  return retSet;
5077 } //end getOtherSubsystemConfigAliases()
5078 
5079 //==============================================================================
5081 std::set<std::string /* configAlias */>
5083  const std::string& otherSubsystemUID, const std::string& otherSubsystemFsmName)
5084 {
5085  std::set<std::string> retSet;
5086 
5087  std::map<std::string /*groupType*/,
5088  std::pair<std::string /*groupName*/, TableGroupKey>>
5089  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
5090 
5091  //load backbone
5092  auto it = retMap.find(
5093  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
5094  if(it == retMap.end())
5095  {
5096  __GEN_SS__
5097  << "No active Backbone group found in the active groups of remote subsystem '"
5098  << otherSubsystemUID << "!'" << __E__;
5099  __GEN_SS_THROW__;
5100  }
5101  auto it2 = retMap.find(
5102  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
5103  if(it2 == retMap.end())
5104  {
5105  __GEN_SS__
5106  << "No active Context group found in the active groups of remote subsystem '"
5107  << otherSubsystemUID << "!'" << __E__;
5108  __GEN_SS_THROW__;
5109  }
5110 
5111  std::string accumulatedWarnings;
5112 
5113  // be careful to not activate! which calls init() and then generates output files to disk
5114  // and changes the system active group; instead only setActiveView
5115  loadTableGroup(it->second.first,
5116  it->second.second,
5117  false /*doActivate*/,
5118  0 /*groupMembers*/,
5119  0 /*progressBar*/,
5120  &accumulatedWarnings /*accumulateWarnings = 0*/
5121  );
5122  loadTableGroup(it2->second.first,
5123  it2->second.second,
5124  false /*doActivate*/,
5125  0 /*groupMembers*/,
5126  0 /*progressBar*/,
5127  &accumulatedWarnings /*accumulateWarnings = 0*/
5128  );
5129  __GEN_COUTTV__(accumulatedWarnings);
5130 
5131  //get aliases (a la ConfigurationManager::getActiveGroupAliases:2888)
5132  std::vector<std::pair<std::string, ConfigurationTree>> entries =
5133  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getChildren();
5134 
5135  //apply filter (a la GatewaySupervisor::addFilteredConfigAliasesToXML:5357)
5136 
5137  std::string stateMachineAliasFilter = "*"; // default to all
5138  try // if cant find alias, default to all
5139  {
5140  ConfigurationTree otherGatewayNode = getGatewaySupervisorNode();
5141  ConfigurationTree fsmFilterNode =
5142  otherGatewayNode.getNode("LinkToStateMachineTable")
5143  .getNode(otherSubsystemFsmName + "/SystemAliasFilter");
5144  if(!fsmFilterNode.isDefaultValue())
5145  stateMachineAliasFilter = fsmFilterNode.getValue<std::string>();
5146  else
5147  __GEN_COUT_INFO__ << "FSM has no SystemAliasFilter value." << __E__;
5148  }
5149  catch(std::runtime_error& e)
5150  {
5151  __COUT__ << "Ignoring unsetup SystemAliasFilter value: " << e.what() << __E__;
5152  }
5153  catch(...)
5154  {
5155  __COUT__ << "Ignoring unsetup SystemAliasFilter value." << __E__;
5156  }
5157 
5158  __COUT__ << "Applying alias filter for other user_data path FSM '"
5159  << otherSubsystemFsmName
5160  << "' and stateMachineAliasFilter = " << stateMachineAliasFilter << __E__;
5161 
5162  // filter list of aliases based on stateMachineAliasFilter
5163  // ! as first character means choose those that do NOT match filter
5164  // * can be used as wild card.
5165  {
5166  bool invertFilter =
5167  stateMachineAliasFilter.size() && stateMachineAliasFilter[0] == '!';
5168  std::vector<std::string> filterArr;
5169 
5170  size_t i = 0;
5171  if(invertFilter)
5172  ++i;
5173  size_t f;
5174  std::string tmp;
5175  while((f = stateMachineAliasFilter.find('*', i)) != std::string::npos)
5176  {
5177  tmp = stateMachineAliasFilter.substr(i, f - i);
5178  i = f + 1;
5179  filterArr.push_back(tmp);
5180  __COUTS__(20) << filterArr[filterArr.size() - 1] << " " << i << " of "
5181  << stateMachineAliasFilter.size() << __E__;
5182  }
5183  if(i <= stateMachineAliasFilter.size())
5184  {
5185  tmp = stateMachineAliasFilter.substr(i);
5186  filterArr.push_back(tmp);
5187  __COUTS__(20) << filterArr[filterArr.size() - 1] << " last." << __E__;
5188  }
5189 
5190  bool filterMatch;
5191 
5192  for(auto& aliasMapPair : entries)
5193  {
5194  __COUTS__(20) << "aliasMapPair.first: " << aliasMapPair.first << __E__;
5195 
5196  filterMatch = true;
5197 
5198  if(filterArr.size() == 1)
5199  {
5200  if(filterArr[0] != "" && filterArr[0] != "*" &&
5201  aliasMapPair.first != filterArr[0])
5202  filterMatch = false;
5203  }
5204  else
5205  {
5206  i = -1;
5207  for(f = 0; f < filterArr.size(); ++f)
5208  {
5209  if(!filterArr[f].size())
5210  continue; // skip empty filters
5211 
5212  if(f == 0) // must start with this filter
5213  {
5214  if((i = aliasMapPair.first.find(filterArr[f])) != 0)
5215  {
5216  filterMatch = false;
5217  break;
5218  }
5219  }
5220  else if(f == filterArr.size() - 1) // must end with this filter
5221  {
5222  if(aliasMapPair.first.rfind(filterArr[f]) !=
5223  aliasMapPair.first.size() - filterArr[f].size())
5224  {
5225  filterMatch = false;
5226  break;
5227  }
5228  }
5229  else if((i = aliasMapPair.first.find(filterArr[f])) ==
5230  std::string::npos)
5231  {
5232  filterMatch = false;
5233  break;
5234  }
5235  }
5236  }
5237 
5238  if(invertFilter)
5239  filterMatch = !filterMatch;
5240 
5241  __COUTS__(20) << "filterMatch=" << filterMatch << __E__;
5242 
5243  if(!filterMatch)
5244  continue;
5245 
5246  retSet.emplace(aliasMapPair.first);
5247 
5248  //If need more alias details, see ConfigurationGUISupervisor::handleGroupAliasesXML
5249  }
5250  }
5251 
5252  return retSet;
5253 } //end getOtherSubsystemFilteredConfigAliases()
5254 
5255 //==============================================================================
5258  const std::string& otherSubsystemUID,
5259  const std::string& configAlias,
5260  std::pair<std::string, TableGroupKey>& groupTranslation,
5261  std::string& groupComment,
5262  std::string& groupAuthor,
5263  std::string& groupCreationTime)
5264 {
5265  __GEN_COUTV__(otherSubsystemUID);
5266 
5267  std::map<std::string /*groupType*/,
5268  std::pair<std::string /*groupName*/, TableGroupKey>>
5269  retMap = getOtherSubsystemActiveTableGroups(otherSubsystemUID);
5270 
5271  //load backbone
5272  auto it = retMap.find(
5273  ConfigurationManager::convertGroupTypeToName(GroupType::BACKBONE_TYPE));
5274  if(it == retMap.end())
5275  {
5276  __GEN_SS__
5277  << "No active Backbone group found in the active groups of remote subsystem '"
5278  << otherSubsystemUID << "!'" << __E__;
5279  __GEN_SS_THROW__;
5280  }
5281  auto it2 = retMap.find(
5282  ConfigurationManager::convertGroupTypeToName(GroupType::CONTEXT_TYPE));
5283  if(it2 == retMap.end())
5284  {
5285  __GEN_SS__
5286  << "No active Context group found in the active groups of remote subsystem '"
5287  << otherSubsystemUID << "!'" << __E__;
5288  __GEN_SS_THROW__;
5289  }
5290 
5291  std::string accumulatedWarnings;
5292 
5293  // be careful to not activate! which calls init() and then generates output files to disk
5294  // and changes the system active group; instead only setActiveView
5295  loadTableGroup(it->second.first,
5296  it->second.second,
5297  false /*doActivate*/,
5298  0 /*groupMembers*/,
5299  0 /*progressBar*/,
5300  &accumulatedWarnings /*accumulateWarnings = 0*/
5301  );
5302  __GEN_COUTTV__(accumulatedWarnings);
5303 
5304  // (a la ConfigurationManager::getTableGroupFromAlias)
5305  try
5306  {
5307  // find runType in Group Aliases table
5308  ConfigurationTree entry =
5309  getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).getNode(configAlias);
5310 
5311  groupTranslation = std::pair<std::string, TableGroupKey>(
5312  entry.getNode("GroupName").getValueAsString(),
5313  TableGroupKey(entry.getNode("GroupKey").getValueAsString()));
5314  __COUT__ << "Found " << configAlias << " translates to " << groupTranslation.first
5315  << "(" << groupTranslation.second << ")" << __E__;
5316 
5317  //get comment, author, creationTime
5318  try
5319  {
5320  loadTableGroup(groupTranslation.first,
5321  groupTranslation.second,
5322  false /*doActivate*/,
5323  0 /*groupMembers*/,
5324  0 /*progressBar*/,
5325  &accumulatedWarnings,
5326  &groupComment,
5327  &groupAuthor,
5328  &groupCreationTime,
5329  true /*doNotLoadMembers*/);
5330  }
5331  catch(...)
5332  {
5333  __COUT_WARN__ << "Failed to load group metadata." << __E__;
5334  }
5335  __COUT__ << "Found " << configAlias << " author: " << groupAuthor
5336  << ", createTime: " << groupCreationTime << ", comment: " << groupComment
5337  << __E__;
5338  }
5339  catch(...)
5340  {
5341  __GEN_SS__ << "Did not find the Configuration Alias '" << configAlias
5342  << "' in the active Backbone group of remote subsystem '"
5343  << otherSubsystemUID << "!'" << __E__;
5344  __GEN_SS_THROW__;
5345  }
5346 
5347 } //end getOtherSubsystemConfigAliasInfo()
5348 
5349 //==============================================================================
5351 TableBase* ConfigurationManager::getDesktopIconTable(void)
5352 {
5353  if(nameToTableMap_.find(DESKTOP_ICON_TABLE_NAME) == nameToTableMap_.end())
5354  {
5355  __SS__ << "Desktop icon table not found!" << __E__;
5356  ss << StringMacros::stackTrace() << __E__;
5357  __SS_THROW__;
5358  }
5359 
5360  return nameToTableMap_.at(DESKTOP_ICON_TABLE_NAME);
5361 } // end dynamicDesktopIconChange()
5362 
5363 //==============================================================================
5364 void ConfigurationManager::saveGroupNameAndKey(
5365  const std::pair<std::string /*group name*/, TableGroupKey>& theGroup,
5366  const std::string& fileName,
5367  bool appendMode /* = false */,
5368  const std::string& associatedUser /* = "" */)
5369 {
5370  std::string fullPath =
5371  ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/" + fileName;
5372  __COUTT__ << "Saving group " << theGroup.first << "(" << theGroup.second << ") to "
5373  << (appendMode ? "history " : "") << "file: " << fullPath << __E__;
5374 
5375  std::ofstream groupFile;
5376  if(appendMode)
5377  {
5378  //force size to MAX record count
5379  const size_t MAX_RECORDS = 200;
5380  auto records = loadGroupHistory(fullPath);
5381  while(records.size() >= MAX_RECORDS)
5382  records.erase(records.begin()); //remove oldest record
5383  //rewrite file
5384  groupFile.open(fullPath.c_str());
5385  for(const auto& record : records)
5386  {
5387  groupFile << record.at("groupName") << "\n"
5388  << record.at("groupKey") << "\n"
5389  << record.at("time") << " , " << record.at("user") << "\n";
5390  } //end rewrite records loop
5391  }
5392  else //if not append mode, just overwrite
5393  groupFile.open(fullPath.c_str());
5394  if(!groupFile.is_open())
5395  {
5396  __SS__ << "Error. Can't open file to save group activity: " << fullPath << __E__;
5397  __SS_THROW__;
5398  }
5399  std::stringstream outss;
5400  outss << theGroup.first << "\n" << theGroup.second << "\n";
5401  outss << time(0);
5402  if(associatedUser != "") //add user on same line as time if available
5403  outss << " , " << associatedUser;
5404  outss << "\n";
5405  groupFile << outss.str().c_str();
5406  groupFile.close();
5407 } // end saveGroupNameAndKey()
5408 
5409 //==============================================================================
5415 std::pair<std::string /*group name*/, TableGroupKey>
5416 ConfigurationManager::loadGroupNameAndKey(const std::string& fileName,
5417  std::string& returnedTimeString)
5418 {
5419  std::string fullPath =
5420  ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/" + fileName;
5421 
5422  FILE* groupFile = fopen(fullPath.c_str(), "r");
5423  if(!groupFile)
5424  {
5425  __COUT__ << "Can't open file: " << fullPath
5426  << ". Returning empty groupName and key -1" << __E__;
5427 
5428  return std::pair<std::string /*group name*/, TableGroupKey>("", TableGroupKey());
5429  }
5430 
5431  char line[500]; // assuming no group names longer than 500 chars
5432  // name and then key
5433  std::pair<std::string /*group name*/, TableGroupKey> theGroup;
5434 
5435  fgets(line, 500, groupFile); // name
5436  if(strlen(line) && line[strlen(line) - 1] == '\n')
5437  line[strlen(line) - 1] = '\0'; // remove trailing newline
5438  theGroup.first = line;
5439 
5440  fgets(line, 500, groupFile); // key
5441  int key;
5442  sscanf(line, "%d", &key);
5443  theGroup.second = key;
5444 
5445  fgets(line, 500, groupFile); // time
5446  time_t timestamp;
5447  sscanf(line, "%ld", &timestamp); // type long int
5448  // struct tm tmstruct;
5449  // ::localtime_r(&timestamp, &tmstruct);
5450  // ::strftime(line, 30, "%c %Z", &tmstruct);
5451  returnedTimeString = StringMacros::getTimestampString(timestamp); // line;
5452  fclose(groupFile);
5453 
5454  __COUTS__(2) << "theGroup.first=" << theGroup.first
5455  << " theGroup.second=" << theGroup.second << __E__;
5456 
5457  return theGroup;
5458 } // end loadGroupNameAndKey()
5459 
5460 //==============================================================================
5462 std::vector<
5463  std::map<std::string /* group field key */, std::string /* group field value */>>
5464 ConfigurationManager::loadGroupHistory(const std::string& groupAction,
5465  const std::string& groupType,
5466  bool formatTime /* = false */)
5467 {
5468  __COUTTV__(groupAction);
5469  __COUTTV__(groupType);
5470 
5471  std::string fullPath = ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/";
5472 
5473  if(groupAction == "Activated")
5474  {
5475  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5476  fullPath += ConfigurationManager::ACTIVATED_BACKBONES_FILE;
5477  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5478  fullPath += ConfigurationManager::ACTIVATED_CONTEXTS_FILE;
5479  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5480  fullPath += ConfigurationManager::ACTIVATED_CONFIGS_FILE;
5481  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5482  fullPath += ConfigurationManager::ACTIVATED_ITERATES_FILE;
5483  }
5484  else if(groupAction == "Attempted Configure")
5485  {
5486  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5487  fullPath += ConfigurationManager::ATTEMPTED_CONFIGURE_CONFIGS_FILE;
5488  else if(groupType == "Config Alias")
5489  fullPath += ConfigurationManager::ATTEMPTED_CONFIGURE_CONFIG_ALIASES_FILE;
5490  }
5491  else if(groupAction == "Configured")
5492  {
5493  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5494  fullPath += ConfigurationManager::CONFIGURED_BACKBONES_FILE;
5495  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5496  fullPath += ConfigurationManager::CONFIGURED_CONTEXTS_FILE;
5497  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5498  fullPath += ConfigurationManager::CONFIGURED_CONFIGS_FILE;
5499  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5500  fullPath += ConfigurationManager::CONFIGURED_ITERATES_FILE;
5501  else if(groupType == "Config Alias")
5502  fullPath += ConfigurationManager::CONFIGURED_CONFIG_ALIASES_FILE;
5503  }
5504  else if(groupAction == "Started")
5505  {
5506  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5507  fullPath += ConfigurationManager::STARTED_BACKBONES_FILE;
5508  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5509  fullPath += ConfigurationManager::STARTED_CONTEXTS_FILE;
5510  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5511  fullPath += ConfigurationManager::STARTED_CONFIGS_FILE;
5512  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5513  fullPath += ConfigurationManager::STARTED_ITERATES_FILE;
5514  else if(groupType == "Config Alias")
5515  fullPath += ConfigurationManager::STARTED_CONFIG_ALIASES_FILE;
5516  }
5517  else if(groupAction == "Configured or Started")
5518  {
5519  if(groupType == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
5520  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_BACKBONES_FILE;
5521  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
5522  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_CONTEXTS_FILE;
5523  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
5524  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_CONFIGS_FILE;
5525  else if(groupType == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
5526  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_ITERATES_FILE;
5527  else if(groupType == "Config Alias")
5528  fullPath += ConfigurationManager::CONFIGURED_OR_STARTED_CONFIG_ALIASES_FILE;
5529  }
5530 
5531  if(fullPath == ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH + "/")
5532  {
5533  __SS__ << "Illegal attempted group history request combination of groupAction: "
5534  << groupAction << ", and groupType: " << groupType << __E__;
5535  __SS_THROW__;
5536  }
5537  return loadGroupHistory(fullPath, formatTime);
5538 } // end loadGroupHistory()
5539 
5540 //==============================================================================
5542 std::vector<
5543  std::map<std::string /* group field key */, std::string /* group field value */>>
5544 ConfigurationManager::loadGroupHistory(const std::string& fullPath,
5545  bool formatTime /* = false */)
5546 {
5547  std::vector<
5548  std::map<std::string /* group field key */, std::string /* group field value */>>
5549  retVec;
5550 
5551  __COUTTV__(fullPath);
5552  FILE* groupFile = fopen(fullPath.c_str(), "r");
5553  if(!groupFile)
5554  {
5555  __COUT_WARN__ << "Can't open group history file (assuming no history yet): "
5556  << fullPath << __E__;
5557 
5558  __COUTTV__(retVec.size());
5559  return retVec;
5560  }
5561 
5562  char line[500]; // assuming no group names longer than 500 chars
5563  // name and then key
5564  std::pair<std::string /*group name*/, TableGroupKey> theGroup;
5565  std::string returnedTimeString, associatedUser;
5566  char user[500];
5567 
5568  while(fgets(line, 500, groupFile)) // name
5569  {
5570  if(strlen(line) && line[strlen(line) - 1] == '\n')
5571  line[strlen(line) - 1] = '\0'; // remove trailing newline
5572  theGroup.first = line;
5573 
5574  fgets(line, 500, groupFile); // key
5575  int key;
5576  sscanf(line, "%d", &key);
5577  theGroup.second = key;
5578 
5579  fgets(line, 500, groupFile); // time
5580  time_t timestamp;
5581  user[0] = '\0'; //clear in case not present in line
5582  sscanf(line, "%ld , %s", &timestamp, user); // type long int
5583  // struct tm tmstruct;
5584  // ::localtime_r(&timestamp, &tmstruct);
5585  // ::strftime(line, 30, "%c %Z", &tmstruct);
5586 
5587  __COUTS__(20) << "Read group from history file: " << theGroup.first << "("
5588  << theGroup.second << "), timestamp=" << timestamp
5589  << ", user=" << user << __E__;
5590 
5591  retVec.push_back({{"groupName", theGroup.first},
5592  {"groupKey", theGroup.second.toString()},
5593  {"time",
5594  formatTime ? StringMacros::getTimestampString(timestamp)
5595  : std::to_string(timestamp)},
5596  {"user", user}});
5597  } //end traversing group history file
5598 
5599  fclose(groupFile);
5600 
5601  __COUTTV__(retVec.size());
5602 
5603  return retVec;
5604 } // end loadGroupHistory()
5605 
5606 //==============================================================================
5609 try
5610 {
5611  __COUTT__ << "Initializing prerequisites for artdaq!" << __E__;
5612 
5613  auto activeTables = getActiveVersions();
5614  for(auto& tablePair : activeTables)
5615  {
5616  __COUTVS__(2, tablePair.first);
5617  try
5618  {
5619  nameToTableMap_.at(tablePair.first)->initPrereqsForARTDAQ(this);
5620  }
5621  catch(const std::runtime_error& e)
5622  {
5623  __COUTVS__(2, e.what());
5624  if(std::string(e.what()).find(
5625  "initPrereqsForARTDAQ() is not implemented for this table") ==
5626  std::string::npos)
5627  throw;
5628  //else ignore undefined virtual function error
5629  }
5630  } //end table loop
5631 
5632  __COUTT__ << "Done initializing prerequisites for artdaq!" << __E__;
5633 } // end initPrereqsForARTDAQ()
5634 catch(...)
5635 {
5636  __SS__ << "Error caught while initializing prerequisites for artdaq!";
5637  try
5638  {
5639  throw;
5640  }
5641  catch(const std::runtime_error& e)
5642  {
5643  ss << " Here was the error: " << e.what() << __E__;
5644  }
5645  __SS_THROW__;
5646 } // 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
TableBase * getVersionedTableByName(const std::string &tableName, TableVersion version, bool looseColumnMatching=false, std::string *accumulatedErrors=0, bool getRawData=false)
static const unsigned int PROCESSOR_COUNT
Static members.
static const std::string & convertGroupTypeToName(const ConfigurationManager::GroupType &groupTypeId)
void restoreActiveTableGroups(bool throwErrors=false, const std::string &pathToActiveGroupsFile="", ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, std::string *accumulatedWarnings=0)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveTableGroups(void) const
std::set< std::string > getOtherSubsystemConfigAliases(const std::string &otherSubsystemUID)
Ignore any System Aliases with "Context" or "Iterat" in the name.
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={})
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:1081
void deleteRow(int r)
Definition: TableView.cc:3564
unsigned int getColStatus(void) const
Definition: TableView.cc:1398
unsigned int getLinkGroupIDColumn(const std::string &childLinkIndex) const
Definition: TableView.cc:1847
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
Definition: TableView.cc:3594
void init(void)
Definition: TableView.cc:195
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
Definition: TableView.cc:966
int fillFromJSON(const std::string &json)
Definition: TableView.cc:2363
unsigned int getColUID(void) const
Definition: TableView.cc:1313
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:3479
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)