tdaq-develop-2025-02-12
otsdaq_flatten_system_aliases.cc
1 #include "otsdaq/MessageFacility/MessageFacility.h"
2 
3 #include <dirent.h>
4 #include <cassert>
5 #include <iostream>
6 #include <memory>
7 #include <string>
8 
9 #include "otsdaq/ConfigurationInterface/ConfigurationInterface.h"
10 #include "otsdaq/ConfigurationInterface/ConfigurationManagerRW.h"
11 // #include "artdaq-database/StorageProviders/FileSystemDB/provider_filedb_index.h"
12 // #include "artdaq-database/JsonDocument/JSONDocument.h"
13 
20 using namespace ots;
21 
22 void FlattenActiveSystemAliasTableGroups(int argc, char* argv[])
23 {
24  // The configuration uses __ENV__("SERVICE_DATA_PATH") in init() so define it if it is not defined
25  if(getenv("SERVICE_DATA_PATH") == NULL)
26  setenv("SERVICE_DATA_PATH",
27  (std::string(__ENV__("USER_DATA")) + "/ServiceData").c_str(),
28  1);
29 
30  std::cout << "=================================================\n";
31  std::cout << "=================================================\n";
32  std::cout << "=================================================\n";
33  __COUT__ << "\nFlattening Active System Aliases!" << std::endl;
34 
35  std::cout << "\n\nusage: Two arguments:\n\t <baseFlatVersion> <pathToSwapIn "
36  "(optional)> \n\n"
37  << "\t Default values: baseFlatVersion = 0, pathToSwapIn = \"\" \n\n"
38  << std::endl;
39 
40  std::cout << "\n\nNote: you can optionally just swap databases (and not modify their "
41  "contents at all)"
42  << " by providing an invalid baseFlatVersion of -1.\n\n"
43  << std::endl;
44 
45  std::cout << "\n\nNote: This assumes artdaq db file type interface. "
46  << "The current database/ will be moved to database_<linuxtime>/ "
47  << "and if a pathToSwapIn is specified it will be copied to database/ "
48  << "before saving the currently active groups.\n\n"
49  << std::endl;
50 
51  std::cout << "argc = " << argc << std::endl;
52  for(int i = 0; i < argc; i++)
53  std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
54 
55  if(argc < 2)
56  {
57  std::cout << "Error! Must provide at least one parameter.\n\n" << std::endl;
58  return;
59  }
60 
61  // determine if "h"elp was first parameter
62  std::string flatVersionStr = argv[1];
63  if(flatVersionStr.find('h') != std::string::npos)
64  {
65  std::cout
66  << "Recognized parameter 1. as a 'help' option. Usage was printed. Exiting."
67  << std::endl;
68  return;
69  }
70 
71  int flatVersion = 0;
72  std::string pathToSwapIn = "";
73  if(argc >= 2)
74  sscanf(argv[1], "%d", &flatVersion);
75  if(argc >= 3)
76  pathToSwapIn = argv[2];
77 
78  __COUT__ << "flatVersion = " << flatVersion << std::endl;
79  __COUT__ << "pathToSwapIn = " << pathToSwapIn << std::endl;
80 
81  // return;
82 
83  //==============================================================================
84  // Define environment variables
85  // Note: normally these environment variables are set by StartOTS.sh
86 
87  // These are needed by
88  // otsdaq/otsdaq/ConfigurationDataFormats/ConfigurationInfoReader.cc [207]
89  setenv("CONFIGURATION_TYPE", "File", 1); // Can be File, Database, DatabaseTest
90  setenv("CONFIGURATION_DATA_PATH",
91  (std::string(getenv("USER_DATA")) + "/ConfigurationDataExamples").c_str(),
92  1);
93  setenv(
94  "TABLE_INFO_PATH", (std::string(getenv("USER_DATA")) + "/TableInfo").c_str(), 1);
96 
97  // Some configuration plug-ins use __ENV__("OTSDAQ_LIB") and
98  // __ENV__("OTSDAQ_UTILITIES_LIB") in init() so define it to a non-sense place is ok
99  setenv("OTSDAQ_LIB", (std::string(getenv("USER_DATA")) + "/").c_str(), 1);
100  setenv("OTSDAQ_UTILITIES_LIB", (std::string(getenv("USER_DATA")) + "/").c_str(), 1);
101 
102  // Some configuration plug-ins use __ENV__("OTS_MAIN_PORT") in init() so define it
103  setenv("OTS_MAIN_PORT", "2015", 1);
104 
105  // also xdaq envs for XDAQContextTable
106  setenv("XDAQ_CONFIGURATION_DATA_PATH",
107  (std::string(getenv("USER_DATA")) + "/XDAQConfigurations").c_str(),
108  1);
109  setenv("XDAQ_CONFIGURATION_XML", "otsConfigurationNoRU_CMake", 1);
111 
112  //==============================================================================
113  // get prepared with initial source db
114 
115  // ConfigurationManager instance immediately loads active groups
116  __COUT__ << "Loading active Aliases..." << std::endl;
117  ConfigurationManagerRW cfgMgrInst("flatten_admin");
118  ConfigurationManagerRW* cfgMgr = &cfgMgrInst;
119 
120  {
121  std::string accumulatedWarnings;
122  cfgMgr->restoreActiveTableGroups(false /*throwErrors*/,
123  "" /*pathToActiveGroupsFile*/,
124  ConfigurationManager::LoadGroupType::ALL_TYPES,
125  &accumulatedWarnings);
126 
127  __COUT__ << "Done Loading active groups: \n" << accumulatedWarnings << std::endl;
128  }
129  // return;
130 
131  // create set of groups to persist
132  // include active context
133  // include active backbone
134  // include active iterate group
135  // include active config group
136  // (keep key translation separate activeGroupKeys)
137  // include all groups with system aliases
138 
139  // for group in set
140  // load/activate group and flatten tables to flatVersion to new DB
141  // save new version to modifiedTables
142  // save group with flatVersion key to new DB
143  // save new key to groupSet
144  // ++flatVersion
145 
146  // reload the active backbone (using activeGroupKeys)
147  // modify group aliases and table aliases properly based on groupSet and
148  // modifiedTables save new backbone with flatVersion to new DB
149 
150  // backup the file ConfigurationManager::ACTIVE_GROUPS_FILENAME with time
151  // and change the ConfigurationManager::ACTIVE_GROUPS_FILENAME
152  // to reflect new group names/keys
153 
154  /* map<<groupName, origKey>, newKey> */
155  std::map<std::pair<std::string, TableGroupKey>, TableGroupKey> groupSet;
156  /* <tableName, <origVersion, newVersion> >*/
157  std::map<std::pair<std::string, TableVersion>, TableVersion> modifiedTables;
158  std::map<std::string, std::pair<TableGroupKey, TableGroupKey>> activeGroupKeys;
159  std::map<std::pair<std::string, TableGroupKey>, std::string> groupErrors;
160 
161  std::string activeBackboneGroupName = "";
162  std::string activeContextGroupName = "";
163  std::string activeIterateGroupName = "";
164  std::string activeConfigGroupName = "";
165 
166  std::string nowTime = std::to_string(time(0));
167 
168  std::string thenTime = "";
169  if(pathToSwapIn != "") // get target then time
170  {
171  thenTime = pathToSwapIn.substr(pathToSwapIn.rfind('_') + 1);
172  __COUT__ << "thenTime = " << thenTime << std::endl;
173  // return;
174  }
175 
176  // add active groups to set
177  std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroupsMap =
178  cfgMgr->getActiveTableGroups();
179 
180  bool foundAnyActiveGroups = false;
181 
182  for(const auto& activeGroup : activeGroupsMap)
183  {
184  if(activeGroup.second.second.TableGroupKey::isInvalid())
185  continue;
186 
187  groupSet.insert(std::pair<std::pair<std::string, TableGroupKey>, TableGroupKey>(
188  std::pair<std::string, TableGroupKey>(activeGroup.second.first,
189  activeGroup.second.second),
190  TableGroupKey()));
191  activeGroupKeys.insert(
192  std::pair<std::string, std::pair<TableGroupKey, TableGroupKey>>(
193  activeGroup.second.first,
194  std::pair<TableGroupKey, TableGroupKey>(activeGroup.second.second,
195  TableGroupKey())));
196 
197  if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
198  {
199  activeBackboneGroupName = activeGroup.second.first;
200  __COUT__ << "found activeBackboneGroupName = " << activeBackboneGroupName
201  << std::endl;
202  foundAnyActiveGroups = true;
203  }
204  else if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
205  {
206  activeContextGroupName = activeGroup.second.first;
207  __COUT__ << "found activeContextGroupName = " << activeContextGroupName
208  << std::endl;
209  foundAnyActiveGroups = true;
210  }
211  else if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
212  {
213  activeIterateGroupName = activeGroup.second.first;
214  __COUT__ << "found activeIterateGroupName = " << activeIterateGroupName
215  << std::endl;
216  foundAnyActiveGroups = true;
217  }
218  else if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
219  {
220  activeConfigGroupName = activeGroup.second.first;
221  __COUT__ << "found activeConfigGroupName = " << activeConfigGroupName
222  << std::endl;
223  foundAnyActiveGroups = true;
224  }
225  }
226 
227  if(!foundAnyActiveGroups)
228  {
229  __SS__ << "Did not find any active groups to convert! Should not be possible, "
230  "must have a backbone at least?"
231  << std::endl;
232  __SS_THROW__;
233  }
234 
235  __COUT__ << "Identified active groups:" << std::endl;
236  for(auto& group : groupSet)
237  __COUT__ << " ==> Group to convert: " << group.first.first << " ("
238  << group.first.second << ")" << std::endl;
239  // return;
240 
241  // add system alias groups to set
242  const std::string groupAliasesTableName =
243  ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
244  std::map<std::string, TableVersion> activeVersions = cfgMgr->getActiveVersions();
245  if(activeVersions.find(groupAliasesTableName) == activeVersions.end())
246  {
247  __SS__ << "\nActive version of " << groupAliasesTableName << " missing! "
248  << groupAliasesTableName
249  << " is a required member of the Backbone configuration group."
250  << "\n\nLikely you need to activate a valid Backbone group." << std::endl;
251  __SS_THROW__;
252  }
253 
254  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
255  cfgMgr->getNode(groupAliasesTableName).getChildren();
256  for(auto& groupPair : aliasNodePairs)
257  groupSet.insert(std::pair<std::pair<std::string, TableGroupKey>, TableGroupKey>(
258  std::pair<std::string, TableGroupKey>(
259  groupPair.second.getNode("GroupName").getValueAsString(),
260  TableGroupKey(groupPair.second.getNode("GroupKey").getValueAsString())),
261  TableGroupKey()));
262 
263  __COUT__ << "All identified groups:" << std::endl;
264  for(auto& group : groupSet)
265  __COUT__ << " ==> Group to convert: " << group.first.first << " ("
266  << group.first.second << ")" << std::endl;
267  __COUT__ << std::endl;
268  __COUT__ << std::endl;
269 
270  if(!groupSet.size())
271  {
272  __SS__ << "No groups identified to convert!" << __E__;
273  __SS_THROW__;
274  }
275 
276  // return;
277  //==============================================================================
278  // prepare to manipulate directories
279  std::string currentDir = __ENV__("ARTDAQ_DATABASE_URI");
280 
281  if(currentDir.find("filesystemdb://") != 0)
282  {
283  __SS__ << "filesystemdb:// was not found in $ARTDAQ_DATABASE_URI!" << std::endl;
284  __COUT_ERR__ << "\n" << ss.str();
285  __SS_THROW__;
286  }
287 
288  currentDir = currentDir.substr(std::string("filesystemdb://").length());
289  while(currentDir.length() &&
290  currentDir[currentDir.length() - 1] == '/') // remove trailing '/'s
291  currentDir = currentDir.substr(0, currentDir.length() - 1);
292  std::string moveToDir = currentDir + "_" + nowTime;
293  if(argc < 2)
294  {
295  __SS__ << ("Aborting move! Must at least give version argument to flatten to!")
296  << std::endl;
297  __COUT_ERR__ << "\n" << ss.str();
298  __SS_THROW__;
299  }
300 
301  if(pathToSwapIn != "")
302  {
303  DIR* dp;
304  if((dp = opendir(pathToSwapIn.c_str())) == 0)
305  {
306  __COUT__ << "ERROR:(" << errno << "). Can't open directory: " << pathToSwapIn
307  << std::endl;
308  exit(0);
309  }
310  closedir(dp);
311  }
312 
313  // handle directory swap
314  __COUT__ << "Moving current directory: \t" << currentDir << std::endl;
315  __COUT__ << "\t... to: \t\t" << moveToDir << std::endl;
316  // return;
317  rename(currentDir.c_str(), moveToDir.c_str());
318 
319  if(pathToSwapIn != "")
320  {
321  __COUT__ << "Swapping in directory: \t" << pathToSwapIn << std::endl;
322  __COUT__ << "\t.. to: \t\t" << currentDir << std::endl;
323  rename(pathToSwapIn.c_str(), currentDir.c_str());
324 
325  // also swap in active groups file
326  // check if original active file exists
327  std::string activeGroupsFile =
329  FILE* fp = fopen(activeGroupsFile.c_str(), "r");
330  if(fp)
331  {
332  __COUT__ << "Swapping active groups file: \t" << activeGroupsFile
333  << std::endl;
334  __COUT__ << "\t.. to: \t\t" << ConfigurationManager::ACTIVE_GROUPS_FILENAME
335  << std::endl;
336  rename(activeGroupsFile.c_str(),
338  }
339  }
340 
341  ConfigurationInterface* theInterface_ = ConfigurationInterface::getInstance(
342  ConfigurationInterface::CONFIGURATION_MODE::ARTDAQ_DATABASE);
343  TableView* cfgView;
344  TableBase* config;
345 
346  bool errDetected;
347  std::string accumulateErrors = "";
348  int count = 0;
349 
350  std::map<std::string /*name*/, TableVersion> memberMap;
351  std::map<std::string /*name*/, std::string /*alias*/> groupAliases;
352  std::string groupComment;
353  std::string groupAuthor;
354  std::string groupCreateTime;
355  time_t groupCreateTime_t;
356  TableBase* groupMetadataTable = cfgMgr->getMetadataTable();
357 
358  // don't do anything more if flatVersion is not persistent
359  if(TableVersion(flatVersion).isInvalid() ||
360  TableVersion(flatVersion).isTemporaryVersion())
361  {
362  __COUT__ << "\n\nflatVersion " << TableVersion(flatVersion)
363  << " is an invalid or temporary version. Skipping to end!" << std::endl;
364  goto CLEAN_UP;
365  }
366 
367  for(auto& groupPair : groupSet)
368  {
369  errDetected = false;
370 
371  __COUT__ << "****************************" << std::endl;
372  __COUT__ << "Loading members for " << groupPair.first.first << "("
373  << groupPair.first.second << ")" << std::endl;
374  __COUT__ << "flatVersion = " << flatVersion << std::endl;
375 
376  // handle directory swap BACK
377  if(pathToSwapIn != "")
378  {
379  __COUT__ << "REVERT by Swapping back directory: \t" << currentDir
380  << std::endl;
381  __COUT__ << "\t.. to: \t\t" << pathToSwapIn << std::endl;
382  if(rename(currentDir.c_str(), pathToSwapIn.c_str()) < 0)
383  {
384  __SS__ << "Problem!" << std::endl;
385  __SS_THROW__;
386  }
387  }
388  else if(count) // if not first time, move currentDir to temporarily holding area
389  {
390  __COUT__ << "REVERT by Moving directory: \t" << currentDir << std::endl;
391  __COUT__ << "\t.. to temporary directory: \t\t" << (moveToDir + "_tmp")
392  << std::endl;
393  if(rename(currentDir.c_str(), (moveToDir + "_tmp").c_str()) < 0)
394  {
395  __SS__ << "Problem!" << std::endl;
396  __SS_THROW__;
397  }
398  }
399 
400  __COUT__ << "REVERT by Moving directory: \t" << moveToDir << std::endl;
401  __COUT__ << "\t... to: \t\t" << currentDir << std::endl;
402  if(rename(moveToDir.c_str(), currentDir.c_str()) < 0)
403  {
404  __SS__ << "Problem!" << std::endl;
405  __SS_THROW__;
406  }
407 
408  //=========================
409  // load group, group metadata, and tables from original DB
410  try
411  {
412  accumulateErrors = "";
413  cfgMgr->loadTableGroup(groupPair.first.first,
414  groupPair.first.second,
415  true /*doActivate*/,
416  &memberMap /*memberMap*/,
417  0 /*progressBar*/,
418  &accumulateErrors,
419  &groupComment,
420  &groupAuthor,
421  &groupCreateTime,
422  false /*doNotLoadMember*/,
423  0 /*groupTypeString*/,
424  &groupAliases);
425  }
426  catch(std::runtime_error& e)
427  {
428  __COUT__ << "Error was caught loading members for " << groupPair.first.first
429  << "(" << groupPair.first.second << ")" << std::endl;
430  __COUT__ << e.what() << std::endl;
431  errDetected = true;
432  }
433  catch(...)
434  {
435  __COUT__ << "Error was caught loading members for " << groupPair.first.first
436  << "(" << groupPair.first.second << ")" << std::endl;
437  errDetected = true;
438  }
439 
440  //=========================
441 
442  // if(count == 2) break;
443 
444  // handle directory swap
445  __COUT__ << "Moving current directory: \t" << currentDir << std::endl;
446  __COUT__ << "\t... to: \t\t" << moveToDir << std::endl;
447  if(rename(currentDir.c_str(), moveToDir.c_str()) < 0)
448  {
449  __SS__ << "Problem!" << std::endl;
450  __SS_THROW__;
451  }
452 
453  if(pathToSwapIn != "")
454  {
455  __COUT__ << "Swapping in directory: \t" << pathToSwapIn << std::endl;
456  __COUT__ << "\t.. to: \t\t" << currentDir << std::endl;
457  if(rename(pathToSwapIn.c_str(), currentDir.c_str()) < 0)
458  {
459  __SS__ << "Problem!" << std::endl;
460  __SS_THROW__;
461  }
462  }
463  else if(count) // if not first time, replace from temporarily holding area
464  {
465  __COUT__ << "Moving temporary directory: \t" << (moveToDir + "_tmp")
466  << std::endl;
467  __COUT__ << "\t.. to current directory: \t\t" << currentDir << std::endl;
468  if(rename((moveToDir + "_tmp").c_str(), currentDir.c_str()) < 0)
469  {
470  __SS__ << "Problem!" << std::endl;
471  __SS_THROW__;
472  }
473  }
474 
475  // exit loop if any (loading) failure
476  if(errDetected)
477  {
478  // goto CLEAN_UP;
479 
480  // power on if group failed
481  // and record error
482 
483  groupErrors.insert(
484  std::pair<std::pair<std::string, TableGroupKey>, std::string>(
485  std::pair<std::string, TableGroupKey>(groupPair.first.first,
486  groupPair.first.second),
487  "Error caught loading the group."));
488  continue;
489  }
490 
491  //=========================
492  // save group and its tables with new key and versions!
493  try
494  {
495  // saving tables
496  for(auto& memberPair : memberMap)
497  {
498  __COUT__ << memberPair.first << ":v" << memberPair.second << std::endl;
499 
500  // check if table has already been modified by a previous group
501  // (i.e. two groups using the same version of a table)
502  if(modifiedTables.find(std::pair<std::string, TableVersion>(
503  memberPair.first, memberPair.second)) != modifiedTables.end())
504  {
505  __COUT__ << "Table was already modified!" << std::endl;
506  memberPair.second =
507  modifiedTables[std::pair<std::string, TableVersion>(
508  memberPair.first, memberPair.second)];
509  __COUT__ << "\t to...\t" << memberPair.first << ":v"
510  << memberPair.second << std::endl;
511  continue;
512  }
513 
514  // change the version of the active view to flatVersion and save it
515  config = cfgMgr->getTableByName(memberPair.first);
516  cfgView = config->getViewP();
517  cfgView->setVersion(TableVersion(flatVersion));
518  theInterface_->saveActiveVersion(config);
519 
520  // set it back for the table so that future groups can re-use cached
521  // version
522  cfgView->setVersion(memberPair.second); // IMPORTANT
523 
524  // save new version to modifiedTables
525  modifiedTables.insert(
526  std::pair<std::pair<std::string, TableVersion>, TableVersion>(
527  std::pair<std::string, TableVersion>(memberPair.first,
528  memberPair.second),
529  TableVersion(flatVersion)));
530 
531  memberPair.second = flatVersion; // change version in the member map
532 
533  __COUT__ << "\t to...\t" << memberPair.first << ":v" << memberPair.second
534  << std::endl;
535  }
536 
537  // Note: this code copies actions in ConfigurationManagerRW::saveNewTableGroup
538 
539  // add meta data
540  __COUTV__(StringMacros::mapToString(groupAliases));
541  __COUTV__(groupComment);
542  __COUTV__(groupAuthor);
543  __COUTV__(groupCreateTime);
544  sscanf(groupCreateTime.c_str(), "%ld", &groupCreateTime_t);
545  __COUTV__(groupCreateTime_t);
546 
547  // to compensate for unusual errors upstream, make sure the metadata table has
548  // one row
549  while(groupMetadataTable->getViewP()->getNumberOfRows() > 1)
550  groupMetadataTable->getViewP()->deleteRow(0);
551  if(groupMetadataTable->getViewP()->getNumberOfRows() == 0)
552  groupMetadataTable->getViewP()->addRow();
553 
554  // columns are uid,comment,author,time
555  // ConfigurationManager::METADATA_COL_ALIASES TODO
556  groupMetadataTable->getViewP()->setValue(
558  groupAliases, "," /*primary delimiter*/, ":" /*secondary delimeter*/),
559  0,
560  ConfigurationManager::METADATA_COL_ALIASES);
561  groupMetadataTable->getViewP()->setValue(
562  groupComment, 0, ConfigurationManager::METADATA_COL_COMMENT);
563  groupMetadataTable->getViewP()->setValue(
564  groupAuthor, 0, ConfigurationManager::METADATA_COL_AUTHOR);
565  groupMetadataTable->getViewP()->setValue(
566  groupCreateTime_t, 0, ConfigurationManager::METADATA_COL_TIMESTAMP);
567 
568  // set version of metadata table
569  groupMetadataTable->getViewP()->setVersion(TableVersion(flatVersion));
570  theInterface_->saveActiveVersion(groupMetadataTable);
571 
572  // force groupMetadataTable_ to be a member for the group
573  memberMap[groupMetadataTable->getTableName()] =
574  groupMetadataTable->getViewVersion();
575 
576  // memberMap should now consist of members with new flat version, so save
577  // group
578  theInterface_->saveTableGroup(
579  memberMap,
580  TableGroupKey::getFullGroupString(groupPair.first.first,
581  TableGroupKey(flatVersion)));
582 
583  // and modify groupSet and activeGroupKeys keys
584  groupPair.second = TableGroupKey(flatVersion);
585 
586  // if this is an active group, save key change
587  if(activeGroupKeys.find(groupPair.first.first) != activeGroupKeys.end() &&
588  activeGroupKeys[groupPair.first.first].first == groupPair.first.second)
589  activeGroupKeys[groupPair.first.first].second =
590  TableGroupKey(flatVersion);
591  }
592  catch(std::runtime_error& e)
593  {
594  __COUT__ << "Error was caught saving group " << groupPair.first.first << " ("
595  << groupPair.first.second << ") " << std::endl;
596  __COUT__ << e.what() << std::endl;
597 
598  groupErrors.insert(
599  std::pair<std::pair<std::string, TableGroupKey>, std::string>(
600  std::pair<std::string, TableGroupKey>(groupPair.first.first,
601  groupPair.first.second),
602  "Error caught saving the group."));
603  }
604  catch(...)
605  {
606  __COUT__ << "Error was caught saving group " << groupPair.first.first << " ("
607  << groupPair.first.second << ") " << std::endl;
608 
609  groupErrors.insert(
610  std::pair<std::pair<std::string, TableGroupKey>, std::string>(
611  std::pair<std::string, TableGroupKey>(groupPair.first.first,
612  groupPair.first.second),
613  "Error caught saving the group."));
614  }
615  //=========================
616 
617  // increment flat version
618  ++flatVersion;
619  ++count;
620  }
621 
622  // record in readme for moveto
623  {
624  FILE* fp = fopen((moveToDir + "/README_otsdaq_flatten.txt").c_str(), "a");
625  if(!fp)
626  __COUT__ << "\tError opening README file!" << std::endl;
627  else
628  {
629  time_t rawtime;
630  struct tm* timeinfo;
631  char buffer[200];
632 
633  time(&rawtime);
634  timeinfo = localtime(&rawtime);
635  strftime(buffer, 200, "%b %d, %Y %I:%M%p %Z", timeinfo);
636 
637  fprintf(fp,
638  "This database was moved from...\n\t %s \nto...\n\t %s \nat this "
639  "time \n\t %lu \t %s\n\n\n",
640  currentDir.c_str(),
641  moveToDir.c_str(),
642  time(0),
643  buffer);
644 
645  fclose(fp);
646  }
647  }
648 
649  // record in readme for swapin
650  {
651  FILE* fp = fopen((currentDir + "/README_otsdaq_flatten.txt").c_str(), "a");
652 
653  if(!fp)
654  __COUT__ << "\tError opening README file!" << std::endl;
655  else
656  {
657  time_t rawtime;
658  struct tm* timeinfo;
659  char buffer[200];
660 
661  time(&rawtime);
662  timeinfo = localtime(&rawtime);
663  strftime(buffer, 200, "%b %d, %Y %I:%M:%S%p %Z", timeinfo);
664 
665  fprintf(fp,
666  "This database was moved from...\t %s \t to...\t %s at this time \t "
667  "%lu \t %s\n\n",
668  pathToSwapIn.c_str(),
669  currentDir.c_str(),
670  time(0),
671  buffer);
672  fclose(fp);
673  }
674  }
675 
676  // //print resulting all groups
677  //
678  // std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Groups:" << std::endl;
679  // for(const auto &group: groupSet)
680  // __COUT__<< group.first.first << ": " <<
681  // group.first.second << " => " << group.second << std::endl;
682  // std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Groups end." << std::endl;
683  //
684  //
685  // //print resulting active groups
686  //
687  // std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Active Groups:" << std::endl;
688  // for(const auto &activeGroup: activeGroupKeys)
689  // __COUT__<< activeGroup.first << ": " <<
690  // activeGroup.second.first << " => " << activeGroup.second.second <<
691  // std::endl;
692  //
693  // __COUT__<< activeBackboneGroupName << " is the " <<
694  // ConfigurationManager::GROUP_TYPE_NAME_BACKBONE << "." << std::endl;
695  // std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Active Groups end." <<
696  // std::endl;
697 
698  // reload the active backbone (using activeGroupKeys)
699  // modify group aliases and table aliases properly based on groupSet and
700  // modifiedTables save new backbone with flatVersion to new DB
701 
702  if(activeBackboneGroupName == "")
703  {
704  __COUT__ << "No active Backbone table identified." << std::endl;
705  goto CLEAN_UP;
706  }
707 
708  std::cout << "\n\n"
709  << __COUT_HDR_FL__
710  << "Modifying the active Backbone table to reflect new table versions and "
711  "group keys."
712  << std::endl;
713 
714  {
715  cfgMgr->loadTableGroup(activeBackboneGroupName,
716  activeGroupKeys[activeBackboneGroupName].second,
717  true,
718  &memberMap,
719  0,
720  &accumulateErrors);
721 
722  // modify Group Aliases Table and Version Aliases Table to point
723  // at DEFAULT and flatVersion respectively
724 
725  const std::string groupAliasesName =
726  ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
727  const std::string versionAliasesName =
728  ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
729 
730  std::map<std::string, TableVersion> activeMap = cfgMgr->getActiveVersions();
731 
732  // modify Group Aliases Table
733  if(activeMap.find(groupAliasesName) != activeMap.end())
734  {
735  __COUT__ << "\n\nModifying " << groupAliasesName << std::endl;
736  config = cfgMgr->getTableByName(groupAliasesName);
737  cfgView = config->getViewP();
738 
739  unsigned int col1 = cfgView->findCol("GroupName");
740  unsigned int col2 = cfgView->findCol("GroupKey");
741 
742  // cfgView->print();
743 
744  // change all key entries found to the new key and delete rows for groups not
745  // found
746  bool found;
747  for(unsigned int row = 0; row < cfgView->getNumberOfRows(); ++row)
748  {
749  found = false;
750  for(const auto& group : groupSet)
751  if(group.second.isInvalid())
752  continue;
753  else if(cfgView->getDataView()[row][col1] == group.first.first &&
754  cfgView->getDataView()[row][col2] ==
755  group.first.second.toString())
756  {
757  // found a matching group/key pair
758  __COUT__ << "Changing row " << row << " for "
759  << cfgView->getDataView()[row][col1]
760  << " key=" << cfgView->getDataView()[row][col2]
761  << " to NEW key=" << group.second << std::endl;
762  cfgView->setValue(group.second.toString(), row, col2);
763  found = true;
764  break;
765  }
766 
767  if(!found) // delete row
768  cfgView->deleteRow(row--);
769  }
770  // cfgView->print();
771  }
772 
773  // modify Version Aliases Table
774  if(activeMap.find(versionAliasesName) != activeMap.end())
775  {
776  __COUT__ << "\n\nModifying " << versionAliasesName << std::endl;
777  config = cfgMgr->getTableByName(versionAliasesName);
778  cfgView = config->getViewP();
779  unsigned int col1 = cfgView->findCol("TableName");
780  unsigned int col2 = cfgView->findCol("Version");
781 
782  // change all version entries to the new version and delete rows with no match
783  bool found;
784  for(unsigned int row = 0; row < cfgView->getNumberOfRows(); ++row)
785  {
786  found = false;
787  for(const auto& table : modifiedTables)
788  if(cfgView->getDataView()[row][col1] == table.first.first &&
789  cfgView->getDataView()[row][col2] == table.first.second.toString())
790  {
791  // found a matching group/key pair
792  __COUT__ << "Changing row " << row << " for "
793  << cfgView->getDataView()[row][col1]
794  << " version=" << cfgView->getDataView()[row][col2]
795  << " to NEW version=" << table.second << std::endl;
796  cfgView->setValue(table.second.toString(), row, col2);
797  found = true;
798  break;
799  }
800 
801  if(!found) // delete row
802  cfgView->deleteRow(row--);
803  }
804  }
805 
806  // save new Group Aliases Table and Version Aliases Table
807 
808  __COUT__ << groupAliasesName << ":v" << memberMap[groupAliasesName] << std::endl;
809  // change the version of the active view to flatVersion and save it
810  config = cfgMgr->getTableByName(groupAliasesName);
811  cfgView = config->getViewP();
812  cfgView->setVersion(TableVersion(flatVersion));
813  theInterface_->saveActiveVersion(config);
814 
815  memberMap[groupAliasesName] = flatVersion; // change version in the member map
816 
817  __COUT__ << "\t to...\t" << groupAliasesName << ":v"
818  << memberMap[groupAliasesName] << std::endl;
819 
820  __COUT__ << versionAliasesName << ":v" << memberMap[versionAliasesName]
821  << std::endl;
822  // change the version of the active view to flatVersion and save it
823  config = cfgMgr->getTableByName(versionAliasesName);
824  cfgView = config->getViewP();
825  cfgView->setVersion(TableVersion(flatVersion));
826  theInterface_->saveActiveVersion(config);
827 
828  memberMap[versionAliasesName] = flatVersion; // change version in the member map
829 
830  __COUT__ << "\t to...\t" << versionAliasesName << ":v"
831  << memberMap[versionAliasesName] << std::endl;
832 
833  // memberMap should now consist of members with new flat version, so save
834  theInterface_->saveTableGroup(
835  memberMap,
836  TableGroupKey::getFullGroupString(activeBackboneGroupName,
837  TableGroupKey(flatVersion)));
838 
839  activeGroupKeys[activeBackboneGroupName].second = TableGroupKey(flatVersion);
840 
841  __COUT__ << "New to-be-active backbone group " << activeBackboneGroupName << ":v"
842  << activeGroupKeys[activeBackboneGroupName].second << std::endl;
843  }
844 
845  // backup the file ConfigurationManager::ACTIVE_GROUPS_FILENAME with time
846  // and change the ConfigurationManager::ACTIVE_GROUPS_FILENAME
847  // to reflect new group names/keys
848 
849  {
850  std::cout << "\n\n"
851  << __COUT_HDR_FL__ << "Manipulating the Active Groups file..."
852  << std::endl;
853 
854  // check if original active file exists
855  FILE* fp = fopen(ConfigurationManager::ACTIVE_GROUPS_FILENAME.c_str(), "r");
856  if(!fp)
857  {
858  __SS__ << "Original active groups file '"
860  << std::endl;
861  goto CLEAN_UP;
862  }
863 
864  __COUT__ << "Backing up file: " << ConfigurationManager::ACTIVE_GROUPS_FILENAME
865  << std::endl;
866 
867  fclose(fp);
868 
869  std::string renameFile =
871  rename(ConfigurationManager::ACTIVE_GROUPS_FILENAME.c_str(), renameFile.c_str());
872 
873  __COUT__ << "Backup file name: " << renameFile << std::endl;
874 
875  TableGroupKey *theConfigurationTableGroupKey_, *theContextTableGroupKey_,
876  *theBackboneTableGroupKey_, *theIterateTableGroupKey_;
877  std::string theConfigurationTableGroup_, theContextTableGroup_,
878  theBackboneTableGroup_, theIterateTableGroup_;
879 
880  theConfigurationTableGroup_ = activeConfigGroupName;
881  theConfigurationTableGroupKey_ = &(activeGroupKeys[activeConfigGroupName].second);
882 
883  theContextTableGroup_ = activeContextGroupName;
884  theContextTableGroupKey_ = &(activeGroupKeys[activeContextGroupName].second);
885 
886  theBackboneTableGroup_ = activeBackboneGroupName;
887  theBackboneTableGroupKey_ = &(activeGroupKeys[activeBackboneGroupName].second);
888 
889  theIterateTableGroup_ = activeIterateGroupName;
890  theIterateTableGroupKey_ = &(activeGroupKeys[activeIterateGroupName].second);
891 
892  // the following is copied from ConfigurationManagerRW::activateTableGroup
893  {
894  __COUT__ << "Updating persistent active groups to "
896  << std::endl;
897 
899  FILE* fp = fopen(fn.c_str(), "w");
900  if(!fp)
901  return;
902 
903  fprintf(fp, "%s\n", theContextTableGroup_.c_str());
904  fprintf(fp,
905  "%s\n",
906  theContextTableGroupKey_
907  ? theContextTableGroupKey_->toString().c_str()
908  : "-1");
909  fprintf(fp, "%s\n", theBackboneTableGroup_.c_str());
910  fprintf(fp,
911  "%s\n",
912  theBackboneTableGroupKey_
913  ? theBackboneTableGroupKey_->toString().c_str()
914  : "-1");
915  fprintf(fp, "%s\n", theConfigurationTableGroup_.c_str());
916  fprintf(fp,
917  "%s\n",
918  theConfigurationTableGroupKey_
919  ? theConfigurationTableGroupKey_->toString().c_str()
920  : "-1");
921  fprintf(fp, "%s\n", theIterateTableGroup_.c_str());
922  fprintf(fp,
923  "%s\n",
924  theIterateTableGroupKey_
925  ? theIterateTableGroupKey_->toString().c_str()
926  : "-1");
927  fclose(fp);
928  }
929  }
930 
931  // print resulting all groups
932 
933  std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Groups:" << std::endl;
934  for(const auto& group : groupSet)
935  __COUT__ << "------------ " << group.first.first << ": " << group.first.second
936  << " => " << group.second << std::endl;
937  std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Groups end." << std::endl;
938 
939  // print resulting active groups
940 
941  std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Active Groups:" << std::endl;
942  for(const auto& activeGroup : activeGroupKeys)
943  __COUT__ << "------------ " << activeGroup.first << ": "
944  << activeGroup.second.first << " => " << activeGroup.second.second
945  << std::endl;
946 
947  __COUT__ << activeBackboneGroupName << " is the "
948  << ConfigurationManager::GROUP_TYPE_NAME_BACKBONE << "." << std::endl;
949  std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Active Groups end." << std::endl;
950 
951 CLEAN_UP:
952  //==============================================================================
953  std::cout << "\n\n"
954  << __COUT_HDR_FL__ << "End of Flattening Active Table Groups!\n\n\n"
955  << std::endl;
956 
957  __COUT__ << "****************************" << std::endl;
958  __COUT__ << "There were " << groupSet.size() << " groups considered, and there were "
959  << groupErrors.size() << " errors found handling those groups." << std::endl;
960  if(groupErrors.size())
961  {
962  __COUT_ERR__ << "There were " << groupErrors.size()
963  << " errors found while loading and converting groups. The "
964  "following errors were found handling the groups:"
965  << std::endl;
966  for(auto& groupErr : groupErrors)
967  __COUT_ERR__ << "\t" << groupErr.first.first << " " << groupErr.first.second
968  << ": \t" << groupErr.second << std::endl;
969  __COUT_ERR__ << "End of errors.\n\n" << std::endl;
970  }
971  else
972  __COUT_INFO__ << "There were NO ERRORS found while loading and converting groups."
973  << __E__;
974 
975  __COUT__ << "Run the following to return to your previous database structure:"
976  << std::endl;
977  __COUT__ << "\t otsdaq_flatten_system_aliases -1 " << moveToDir << "\n\n"
978  << std::endl;
979 
980  // make updated rebuild files
981  {
982  FILE* fp =
983  fopen((currentDir + "/fromConfigurationToTableConversion").c_str(), "w");
984  if(fp)
985  {
986  fprintf(fp, "converted");
987  fclose(fp);
988  }
989  }
990  {
991  FILE* fp =
992  fopen((currentDir + "/fromConfigurationToTableConversion2").c_str(), "w");
993  if(fp)
994  {
995  fprintf(fp, "converted");
996  fclose(fp);
997  }
998  }
999  {
1000  FILE* fp = fopen((currentDir + "/artdaqDaqTableConversion").c_str(), "w");
1001  if(fp)
1002  {
1003  fprintf(fp, "converted");
1004  fclose(fp);
1005  }
1006  }
1007  {
1008  FILE* fp = fopen((currentDir + "/fromIndexRebuild").c_str(), "w");
1009  if(fp)
1010  {
1011  fprintf(fp, "rebuilt");
1012  fclose(fp);
1013  }
1014  }
1015 
1016  return;
1017 }
1018 
1019 int main(int argc, char* argv[])
1020 {
1021  if(getenv("OTSDAQ_LOG_FHICL") == NULL)
1022  setenv("OTSDAQ_LOG_FHICL",
1023  (std::string(__ENV__("USER_DATA")) +
1024  "/MessageFacilityConfigurations/MessageFacilityWithCout.fcl")
1025  .c_str(),
1026  1);
1027 
1028  if(getenv("OTSDAQ_LOG_ROOT") == NULL)
1029  setenv(
1030  "OTSDAQ_LOG_ROOT", (std::string(__ENV__("USER_DATA")) + "/Logs").c_str(), 1);
1031 
1032  INIT_MF("FlattenSystemAliases");
1033  FlattenActiveSystemAliasTableGroups(argc, argv);
1034  return 0;
1035 }
1036 // BOOST_AUTO_TEST_SUITE_END()
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false)
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::map< std::string, TableVersion > getActiveVersions(void) const
getActiveVersions
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
static const std::string ACTIVE_GROUPS_FILENAME
added env check for otsdaq_flatten_active_to_version to function
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 & getTableName(void) const
Getters.
Definition: TableBase.cc:681
const TableVersion & getViewVersion(void) const
always the active one
Definition: TableBase.cc:690
std::string toString(void) const
toString
static std::string getFullGroupString(const std::string &groupName, const TableGroupKey &key, const std::string &preKey="_v", const std::string &postKey="")
void deleteRow(int r)
Definition: TableView.cc:3424
void setVersion(const T &version)
< in included .icc source
unsigned int findCol(const std::string &name) const
Definition: TableView.cc:1935
void setValue(const T &value, unsigned int row, unsigned int col)
< in included .icc source
unsigned int addRow(const std::string &author="", unsigned char incrementUniqueData=false, const std::string &baseNameAutoUID="", unsigned int rowToAdd=(unsigned int) -1, std::string childLinkIndex="", std::string groupId="")
Definition: TableView.cc:3339
void INIT_MF(const char *name)
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")