tdaq-develop-2025-02-12
otsdaq_import_system_aliases.cc
1 #include <dirent.h>
2 #include <cassert>
3 #include <iostream>
4 #include <memory>
5 #include <string>
6 #include "otsdaq/ConfigurationInterface/ConfigurationInterface.h"
7 #include "otsdaq/ConfigurationInterface/ConfigurationManagerRW.h"
8 
15 using namespace ots;
16 
17 void ImportSystemAliasTableGroups(int argc, char* argv[])
18 {
19  __COUT__ << "=================================================\n";
20  __COUT__ << "=================================================\n";
21  __COUT__ << "=================================================\n";
22  __COUT__ << "Importing External System Aliases!" << std::endl;
23 
24  std::string prependBaseName = "Imported";
25  const std::string groupAliasesTableName =
26  ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
27  const std::string versionAliasesTableName =
28  ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
29 
30  std::cout << "\n\nusage: Two arguments:\n\n\t otsdaq_import_system_aliases "
31  "<path_to_import_database_folder> <path_to_active_groups_file> "
32  "<import_prepend_base_name (optional)> \n\n"
33  << "\t\t Default values: \n\t\t\timport_prepend_base_name = \""
34  << prependBaseName << "\" "
35  << "\n\n"
36  << "\t\tfor example:\n\n"
37  << "\t\t\totsdaq_import_system_aliases "
38  "~/databaseToImport/filesystemdb/test_db "
39  "~/UserDataToImport/ServiceData/ActiveTableGroups.cfg"
40  << __E__;
41 
42  std::cout << "\n\n\tExample active groups file content:\n\n"
43  << "testContext\n2\nTableEditWizBackbone\n3\ndefaultConfig\n1\n\n"
44  << __E__;
45 
46  std::cout << "\n\nNote: This assumes artdaq db file type interface. "
47  << "The current database/ will be backed up to database_<linuxtime>/ "
48  << "before importing the active groups.\n\n"
49  << __E__;
50 
51  __COUTV__(argc);
52  for(int i = 0; i < argc; i++)
53  std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
54 
55  if(argc < 3)
56  {
57  __COUT__ << "Must provide at least two parameters (the database and active "
58  "groups files for the import).\n\n\n"
59  << __E__;
60  return;
61  }
62 
63  // remove trailing /'s
64  while(strlen(argv[1]) && argv[1][strlen(argv[1]) - 1] == '/')
65  argv[1][strlen(argv[1]) - 1] = '\0';
66 
67  // determine if "h"elp was first parameter
68  std::string pathToImportDatabase = argv[1];
69  if(pathToImportDatabase.size() &&
70  (pathToImportDatabase[0] == 'h' || pathToImportDatabase[0] == '-'))
71  {
72  __COUT__
73  << "Recognized parameter 1. as a 'help' option. Usage was printed. Exiting."
74  << std::endl;
75  return;
76  }
77 
78  std::string pathToImportActiveGroups = "";
79  if(argc >= 3)
80  pathToImportActiveGroups = argv[2];
81  if(argc >= 4)
82  prependBaseName = argv[3];
83 
84  __COUTV__(pathToImportDatabase);
85  __COUTV__(pathToImportActiveGroups);
86  __COUTV__(prependBaseName);
87 
88  //==============================================================================
89  // Define environment variables
90  // Note: normally these environment variables are set by StartOTS.sh
91 
92  // These are needed by
93  // otsdaq/otsdaq/ConfigurationDataFormats/ConfigurationInfoReader.cc [207]
94  setenv("CONFIGURATION_TYPE", "File", 1); // Can be File, Database, DatabaseTest
95  setenv("CONFIGURATION_DATA_PATH",
96  (std::string(__ENV__("USER_DATA")) + "/ConfigurationDataExamples").c_str(),
97  1);
98  setenv(
99  "TABLE_INFO_PATH", (std::string(__ENV__("USER_DATA")) + "/TableInfo").c_str(), 1);
101 
102  // Some configuration plug-ins use __ENV__("SERVICE_DATA_PATH") in init() so define it
103  setenv("SERVICE_DATA_PATH",
104  (std::string(__ENV__("USER_DATA")) + "/ServiceData").c_str(),
105  1);
106 
107  // Some configuration plug-ins use __ENV__("OTSDAQ_LIB") and
108  // __ENV__("OTSDAQ_UTILITIES_LIB") in init() so define it to a non-sense place is ok
109  setenv("OTSDAQ_LIB", (std::string(__ENV__("USER_DATA")) + "/").c_str(), 1);
110  setenv("OTSDAQ_UTILITIES_LIB", (std::string(__ENV__("USER_DATA")) + "/").c_str(), 1);
111 
112  // Some configuration plug-ins use __ENV__("OTS_MAIN_PORT") in init() so define it
113  setenv("OTS_MAIN_PORT", "2015", 1);
114 
115  // also xdaq envs for XDAQContextTable
116  setenv("XDAQ_CONFIGURATION_DATA_PATH",
117  (std::string(__ENV__("USER_DATA")) + "/XDAQConfigurations").c_str(),
118  1);
119  setenv("XDAQ_CONFIGURATION_XML", "otsConfigurationNoRU_CMake", 1);
121 
122  //==============================================================================
123 
124  // Steps:
125  //
126  // -- create empty map of import alias to original groupName & groupKey
127  // -- create empty map of original groupName & groupKey to new groupKey
128  //
129  // -- create empty map of import alias to original tableName & tableVersion
130  // -- create empty map of original tableName & tableVersion to new tableVersion
131  //
132  // -- in current-db extract info
133  // - get set of existing group aliases
134  // . load current aliases from current-db
135  // - get set of existing table aliases
136  // . load current aliases from current-db
137  //
138  // -- swap to import-db, clear cache, and create vector of groups to import
139  // - get active groups from user data file
140  // - get aliases from active backbone group
141  // . check basename+alias for collision with existing group aliases and throw
142  // error if collision
143  // . add map record of basename+alias to original groupName & groupKey
144  // . check basename+alias for collision with existing table aliases and throw
145  // error if collision
146  // . add map record of basename+alias to original tableName & tableVersion
147  //
148  // -- for each group in set
149  // - swap to import-db
150  // - load/activate group
151  // - swap to current-db
152  // - for each member table in group
153  // . check map of original tableName & tableVersion to new tableName &
154  // tableVersion, to prevent making a new table
155  // . if needed, save active tables as next table version (using interface)
156  // , add map record of original tableName & tableVersion to new tableName
157  //& tableVersion
158  // - save new group with associated table versions
159  // . add map record of original groupName & groupKey to new groupName &
160  // groupKey
161  //
162  //
163  // -- in current-db after loop...
164  // - destroy and reload active groups
165  // -- insert new aliases for imported groups
166  // - should be basename+alias connection to (hop through maps) new groupName &
167  // groupKey
168  // -- insert new aliases for imported tables
169  // - should be basename+alias connection to (hop through maps) new tableName &
170  // tableVersion
171  // -- save new backbone tables and save new backbone group
172  // -- backup the file ConfigurationManager::ACTIVE_GROUPS_FILENAME with time
173  // -- activate the new backbone group
174  //
175 
176  //==============================================================================
177 
178  // create objects
179 
180  // std::map<std::string /*tableName*/,
181  // TableVersion /*next persisten version*/>
182  // tableNextVersionMap;
183 
184  std::map<std::string /*importGroupAlias*/,
185  /*original*/ std::pair<std::string /*groupName*/, TableGroupKey>>
186  originalGroupAliasMap;
187 
188  std::map</*original*/ std::pair<std::string /*groupName*/, TableGroupKey>,
189  /*new*/ TableGroupKey>
190  groupSet;
191 
192  std::map<std::string /*importTableAlias*/,
193  /*original*/ std::pair<std::string /*tableName*/, TableVersion>>
194  originalTableAliasMap;
195 
196  std::map</*original*/ std::pair<std::string /*tableName*/, TableVersion>,
197  /*new*/ TableVersion>
198  newTableVersionMap;
199 
200  std::map</*original*/ std::pair<std::string, TableGroupKey>,
201  std::string /*error string*/>
202  groupErrors;
203 
204  // get prepared with initial source db
205 
206  // ConfigurationManager instance immediately loads active groups
207  __COUT__ << "Getting started..." << std::endl;
208  ConfigurationManagerRW cfgMgrInst("import_aliases");
209  ConfigurationManagerRW* cfgMgr = &cfgMgrInst;
210  bool importedDbInPlace = false;
211 
212  {
213  std::string accumulatedWarnings;
214  cfgMgr->restoreActiveTableGroups(false /*throwErrors*/,
215  "" /*pathToActiveGroupsFile*/,
216  ConfigurationManager::LoadGroupType::ALL_TYPES,
217  &accumulatedWarnings);
218 
219  __COUT__ << "Done Loading active groups: \n" << accumulatedWarnings << std::endl;
220  }
221 
222  __COUT__ << "Configuration manager initialized." << __E__;
223 
224  std::string nowTime = std::to_string(time(0));
225  std::string currentDir = __ENV__("ARTDAQ_DATABASE_URI");
226 
227  if(currentDir.find("filesystemdb://") != 0)
228  {
229  __SS__ << "filesystemdb:// was not found in $ARTDAQ_DATABASE_URI!" << std::endl;
230  __COUT_ERR__ << "\n" << ss.str();
231  __SS_THROW__;
232  }
233 
234  currentDir = currentDir.substr(std::string("filesystemdb://").length());
235  while(currentDir.length() &&
236  currentDir[currentDir.length() - 1] == '/') // remove trailing '/'s
237  currentDir = currentDir.substr(0, currentDir.length() - 1);
238 
239  __COUTV__(currentDir);
240 
241  std::string backupDir = currentDir + "_" + nowTime;
242  std::string importDir = pathToImportDatabase + "_" + nowTime;
243  std::string tmpCurrentDir = currentDir + "_tmp_" + nowTime;
244  // std::string tmpImportDir = pathToImportDatabase + "_tmp_" + nowTime;
245 
246  // -- get set of existing aliases
247  std::map<std::string /*table name*/,
248  std::map<std::string /*version alias*/, TableVersion /*aliased version*/>>
249  existingTableAliases = cfgMgr->ConfigurationManager::getVersionAliases();
250  std::map<std::string /*alias*/, std::pair<std::string /*group name*/, TableGroupKey>>
251  existingGroupAliases = cfgMgr->getActiveGroupAliases();
252 
253  // //NOT NEEDED -- just ask db on fly for next version // - fill map of table name
254  // to next persistent table version
255  // {
256  // const std::map<std::string, TableInfo>& allCfgInfo =
257  // cfgMgr->getAllConfigurationInfo(); for(auto& mapPair : allCfgInfo)
258  // {
259  // tableNextVersionMap[mapPair.first] =
260  // mapPair.second.versions_.size()?
261  // *(mapPair.second.versions_.rbegin()):
262  // TableVersion(TableVersion::DEFAULT);
263  // }
264  // }
265  //
266  // __COUTV__(StringMacros::mapToString(tableNextVersionMap));
267 
268  // -- swap to import-db and clear cache
269  {
270  // back up current directory now
271  __COUT__ << "Backing up current database at '" << currentDir << "' to '"
272  << backupDir << "'" << __E__;
273  std::system(("cp -r " + currentDir + " " + backupDir).c_str());
274 
275  __COUT__ << "Backing up current database at '" << pathToImportDatabase << "' to '"
276  << importDir << "'" << __E__;
277  std::system(("cp -r " + pathToImportDatabase + " " + importDir).c_str());
278 
279  cfgMgr->destroy();
280 
281  __COUT__ << "Swap to import-db" << std::endl;
282  if(rename(currentDir.c_str(), tmpCurrentDir.c_str()) < 0)
283  {
284  __SS__ << "Problem!" << std::endl;
285  __SS_THROW__;
286  }
287  if(rename(importDir.c_str(), currentDir.c_str()) < 0)
288  {
289  __SS__ << "Problem!" << std::endl;
290  __SS_THROW__;
291  }
292  importedDbInPlace = true;
293  }
294 
295  try
296  {
297  // - get active groups from user data file
298  cfgMgr->restoreActiveTableGroups(true /*throwErrors*/, pathToImportActiveGroups);
299 
300  // add active groups to set
301  std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroupsMap =
302  cfgMgr->getActiveTableGroups();
303 
304  for(const auto& activeGroup : activeGroupsMap)
305  {
306  if(activeGroup.second.second.isInvalid())
307  continue;
308  if(activeGroup.second.first == "")
309  continue;
310 
311  __COUTV__(activeGroup.second.first);
312  __COUTV__(activeGroup.second.second);
313 
314  groupSet.insert(
315  std::pair<std::pair<std::string, TableGroupKey>, TableGroupKey>(
316  std::pair<std::string, TableGroupKey>(activeGroup.second.first,
317  activeGroup.second.second),
318  TableGroupKey()));
319  }
320 
321  // add system alias groups to set
322  std::map<std::string, TableVersion> activeVersions = cfgMgr->getActiveVersions();
323  if(activeVersions.find(groupAliasesTableName) == activeVersions.end())
324  {
325  __SS__ << "\nActive version of " << groupAliasesTableName << " missing! "
326  << groupAliasesTableName
327  << " is a required member of the Backbone configuration group."
328  << "\n\nLikely you need to activate a valid Backbone group."
329  << std::endl;
330  __SS_THROW__;
331  }
332  if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
333  {
334  __SS__ << "\nActive version of " << versionAliasesTableName << " missing! "
335  << versionAliasesTableName
336  << " is a required member of the Backbone configuration group."
337  << "\n\nLikely you need to activate a valid Backbone group."
338  << std::endl;
339  __SS_THROW__;
340  }
341 
342  std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
343  cfgMgr->getNode(groupAliasesTableName).getChildren();
344  std::string aliasName;
345  for(auto& aliasPair : aliasNodePairs)
346  {
347  if(TableGroupKey(aliasPair.second.getNode("GroupKey").getValueAsString())
348  .isInvalid())
349  continue;
350  if(aliasPair.second.getNode("GroupName").getValueAsString() == "")
351  continue;
352 
353  aliasName = aliasPair.second.getNode("GroupKeyAlias").getValueAsString();
354  if(aliasName == "")
355  continue;
356 
357  if(aliasName[0] >= 'a' && aliasName[0] <= 'z') // capitalize the name
358  aliasName[0] -= 32;
359  aliasName = prependBaseName + aliasName;
360  __COUTV__(aliasName);
361  __COUTV__(aliasPair.second.getNode("GroupName").getValueAsString());
362  __COUTV__(aliasPair.second.getNode("GroupKey").getValueAsString());
363 
364  // . check basename+alias for collision with existing group aliases
365  // and throw error if collision
366  if(existingGroupAliases.find(aliasName) != existingGroupAliases.end())
367  {
368  __SS__ << "Conflicting group alias '" << aliasName << "' found!" << __E__;
369  __SS_THROW__;
370  }
371 
372  groupSet.insert(
373  std::pair<std::pair<std::string, TableGroupKey>, TableGroupKey>(
374  std::pair<std::string, TableGroupKey>(
375  aliasPair.second.getNode("GroupName").getValueAsString(),
377  aliasPair.second.getNode("GroupKey").getValueAsString())),
378  TableGroupKey()));
379 
380  originalGroupAliasMap[aliasName] = std::pair<std::string, TableGroupKey>(
381  aliasPair.second.getNode("GroupName").getValueAsString(),
382  TableGroupKey(aliasPair.second.getNode("GroupKey").getValueAsString()));
383  } // end group aliases loop
384 
385  aliasNodePairs = cfgMgr->getNode(versionAliasesTableName).getChildren();
386  for(auto& aliasPair : aliasNodePairs)
387  {
388  if(TableVersion(aliasPair.second.getNode("Version").getValueAsString())
389  .isInvalid())
390  continue;
391  if(aliasPair.second.getNode("TableName").getValueAsString() == "")
392  continue;
393  aliasName = aliasPair.second.getNode("VersionAlias").getValueAsString();
394  if(aliasName == "")
395  continue;
396 
397  if(aliasName[0] >= 'a' && aliasName[0] <= 'z') // capitalize the name
398  aliasName[0] -= 32;
399  aliasName = prependBaseName + aliasName;
400  __COUTV__(aliasPair.second.getNode("TableName").getValueAsString());
401  __COUTV__(aliasName);
402  __COUTV__(aliasPair.second.getNode("Version").getValueAsString());
403 
404  // . check basename+alias for collision with existing table aliases
405  // and throw error if collision
406  if(existingTableAliases.find(aliasName) != existingTableAliases.end())
407  {
408  __SS__ << "Conflicting table version alias '" << aliasName << "' found!"
409  << __E__;
410  __SS_THROW__;
411  }
412 
413  originalTableAliasMap[aliasName] = std::pair<std::string, TableVersion>(
414  aliasPair.second.getNode("TableName").getValueAsString(),
415  TableVersion(aliasPair.second.getNode("Version").getValueAsString()));
416  } // end table aliases loop
417  } // end extract group set
418  catch(const std::runtime_error& e)
419  {
420  __COUT_ERR__ << "There was a fatal error: " << e.what() << __E__;
421 
422  __COUT__ << std::endl;
423  __COUT__ << std::endl;
424  __COUT__ << "Run the following to return to your previous database structure:"
425  << std::endl;
426  __COUT__ << "\t otsdaq_flatten_system_aliases -1 " << backupDir << "\n\n"
427  << std::endl;
428  __COUT__ << std::endl;
429  __COUT__ << std::endl;
430  return;
431  }
432 
433  __COUTV__(StringMacros::mapToString(existingGroupAliases));
434  __COUTV__(StringMacros::mapToString(existingTableAliases));
435 
436  __COUT__ << std::endl;
437  __COUT__ << std::endl;
438  __COUT__ << "Identified groups:" << std::endl;
439  for(auto& group : groupSet)
440  __COUT__ << "\t" << group.first.first << " " << group.first.second << std::endl;
441  __COUT__ << std::endl;
442  __COUT__ << std::endl;
443 
444  __COUT__ << "Identified group aliases:" << std::endl;
445  for(auto& groupAlias : originalGroupAliasMap)
446  __COUT__ << "\t" << groupAlias.first << " ==> " << groupAlias.second.first << "-"
447  << groupAlias.second.second << std::endl;
448  __COUT__ << std::endl;
449  __COUT__ << std::endl;
450 
451  //==============================================================================
452  // -- for each group in set
453 
454  ConfigurationInterface* theInterface_ = ConfigurationInterface::getInstance(
455  ConfigurationInterface::CONFIGURATION_MODE::ARTDAQ_DATABASE);
456  TableView* cfgView;
457  TableBase* config;
458  TableVersion newVersion;
459  TableGroupKey newKey;
460 
461  bool errDetected;
462  std::string accumulateErrors = "";
463  int count = 0;
464 
465  std::map<std::string, TableVersion> memberMap;
466  std::map<std::string /*name*/, std::string /*alias*/> groupAliases;
467  std::string groupComment;
468  std::string groupAuthor;
469  std::string groupCreateTime;
470  time_t groupCreateTime_t;
471  TableBase* groupMetadataTable = cfgMgr->getMetadataTable();
472 
473  __COUT__ << "Proceeding with handling of identified groups..." << __E__;
474 
475  // -- for each group in set
476  for(auto& groupPair : groupSet)
477  {
478  cfgMgr->destroy();
479 
480  errDetected = false;
481 
482  //- swap to import-db (first time already in import-db
483  //- load/activate group
484 
485  __COUTV__(importedDbInPlace);
486  // -- swap to import-db
487  if(!importedDbInPlace)
488  {
489  __COUT__ << "Swap to import-db" << std::endl;
490  if(rename(currentDir.c_str(), tmpCurrentDir.c_str()) < 0)
491  {
492  __SS__ << "Problem!" << std::endl;
493  __SS_THROW__;
494  }
495  if(rename(importDir.c_str(), currentDir.c_str()) < 0)
496  {
497  __SS__ << "Problem!" << std::endl;
498  __SS_THROW__;
499  }
500  importedDbInPlace = true;
501  }
502 
503  // cfgMgr->restoreActiveTableGroups(true
504  // /*throwErrors*/,pathToImportActiveGroups);
505 
506  __COUT__ << "****************************" << std::endl;
507  __COUT__ << "Loading members for " << groupPair.first.first << "("
508  << groupPair.first.second << ")" << std::endl;
509  __COUTV__(count);
510 
511  //=========================
512  // load group, group metadata, and tables from original DB
513  try
514  {
515  cfgMgr->loadTableGroup(groupPair.first.first,
516  groupPair.first.second,
517  true /*doActivate*/,
518  &memberMap /*memberMap*/,
519  0 /*progressBar*/,
520  &accumulateErrors,
521  &groupComment,
522  &groupAuthor,
523  &groupCreateTime,
524  false /*doNotLoadMember*/,
525  0 /*groupTypeString*/,
526  &groupAliases);
527  }
528  catch(std::runtime_error& e)
529  {
530  __COUT__ << "Error was caught loading members for " << groupPair.first.first
531  << "(" << groupPair.first.second << ")" << std::endl;
532  __COUT__ << e.what() << std::endl;
533  errDetected = true;
534  }
535  catch(...)
536  {
537  __COUT__ << "Error was caught loading members for " << groupPair.first.first
538  << "(" << groupPair.first.second << ")" << std::endl;
539  errDetected = true;
540  }
541 
542  //=========================
543 
544  // if(count == 2) break;
545 
546  // exit loop if any (loading) failure
547  if(errDetected)
548  {
549  // goto CLEAN_UP;
550 
551  // power on if group failed
552  // and record error
553 
554  groupErrors.insert(
555  std::pair<std::pair<std::string, TableGroupKey>, std::string>(
556  std::pair<std::string, TableGroupKey>(groupPair.first.first,
557  groupPair.first.second),
558  "Error caught loading the group."));
559  continue;
560  }
561 
562  // -- swap to current-db
563  if(importedDbInPlace)
564  {
565  __COUT__ << "Swap to current-db" << std::endl;
566  if(rename(currentDir.c_str(), importDir.c_str()) < 0)
567  {
568  __SS__ << "Problem!" << std::endl;
569  __SS_THROW__;
570  }
571  if(rename(tmpCurrentDir.c_str(), currentDir.c_str()) < 0)
572  {
573  __SS__ << "Problem!" << std::endl;
574  __SS_THROW__;
575  }
576  importedDbInPlace = false;
577  }
578 
579  //=========================
580  // save group and its tables with new key and versions!
581  try
582  {
583  // saving tables
584  for(auto& memberPair : memberMap)
585  {
586  __COUT__ << memberPair.first << ":v" << memberPair.second << std::endl;
587 
588  // check if table has already been modified by a previous group
589  // (i.e. two groups using the same version of a table)
590  if(newTableVersionMap.find(std::pair<std::string, TableVersion>(
591  memberPair.first, memberPair.second)) != newTableVersionMap.end())
592  {
593  __COUT__ << "Table was already modified!" << std::endl;
594  memberPair.second =
595  newTableVersionMap[std::pair<std::string, TableVersion>(
596  memberPair.first, memberPair.second)];
597  __COUT__ << "\t to...\t" << memberPair.first << ":v"
598  << memberPair.second << std::endl;
599  continue;
600  }
601 
602  // change the version of the active view to next available version and
603  // save it
604  config = cfgMgr->getTableByName(memberPair.first);
605  cfgView = config->getViewP();
606  // newVersion = theInterface_->saveNewVersion(config, temporaryVersion);
607  newVersion = TableVersion::getNextVersion(
608  theInterface_->findLatestVersion(config));
609  __COUTV__(newVersion);
610  cfgView->setVersion(newVersion);
611  theInterface_->saveActiveVersion(config);
612 
613  // set it back for the table so that future groups can re-use cached
614  // version
615  // FIXME -- RAR note: I do not understand why this was important.. seems
616  // like it will not help since the cache is destroyed for each group
617  // cfgView->setVersion(memberPair.second); //IMPORTANT
618 
619  // save new version to modifiedTables
620  newTableVersionMap.insert(
621  std::pair<std::pair<std::string, TableVersion>, TableVersion>(
622  std::pair<std::string, TableVersion>(memberPair.first,
623  memberPair.second),
624  newVersion));
625 
626  memberPair.second = newVersion; // change version in the member map
627 
628  __COUT__ << "\t to...\t" << memberPair.first << ":v" << memberPair.second
629  << std::endl;
630  } // end member map loop
631 
632  __COUT__ << "Member map completed" << __E__;
633  __COUTV__(StringMacros::mapToString(memberMap));
634 
635  // Note: this code copies actions in ConfigurationManagerRW::saveNewTableGroup
636 
637  // add meta data
638  __COUTV__(StringMacros::mapToString(groupAliases));
639  __COUTV__(groupComment);
640  __COUTV__(groupAuthor);
641  __COUTV__(groupCreateTime);
642  sscanf(groupCreateTime.c_str(), "%ld", &groupCreateTime_t);
643  __COUTV__(groupCreateTime_t);
644 
645  // to compensate for unusual errors upstream, make sure the metadata table has
646  // one row
647  while(groupMetadataTable->getViewP()->getNumberOfRows() > 1)
648  groupMetadataTable->getViewP()->deleteRow(0);
649  if(groupMetadataTable->getViewP()->getNumberOfRows() == 0)
650  groupMetadataTable->getViewP()->addRow();
651 
652  // columns are uid,comment,author,time
653  // ConfigurationManager::METADATA_COL_ALIASES TODO
654  groupMetadataTable->getViewP()->setValue(
656  groupAliases, "," /*primary delimiter*/, ":" /*secondary delimeter*/),
657  0,
658  ConfigurationManager::METADATA_COL_ALIASES);
659  groupMetadataTable->getViewP()->setValue(
660  groupComment, 0, ConfigurationManager::METADATA_COL_COMMENT);
661  groupMetadataTable->getViewP()->setValue(
662  groupAuthor, 0, ConfigurationManager::METADATA_COL_AUTHOR);
663  groupMetadataTable->getViewP()->setValue(
664  groupCreateTime_t, 0, ConfigurationManager::METADATA_COL_TIMESTAMP);
665 
666  // set version of metadata table
667  newVersion = TableVersion::getNextVersion(
668  theInterface_->findLatestVersion(groupMetadataTable));
669  __COUTV__(newVersion);
670  groupMetadataTable->getViewP()->setVersion(newVersion);
671  theInterface_->saveActiveVersion(groupMetadataTable);
672 
673  // force groupMetadataTable_ to be a member for the group
674  memberMap[groupMetadataTable->getTableName()] =
675  groupMetadataTable->getViewVersion();
676 
677  // memberMap should now consist of members with new flat version, so save
678  // group
679  newKey = TableGroupKey::getNextKey(
680  theInterface_->findLatestGroupKey(groupPair.first.first));
681 
682  __COUTV__(newKey);
683 
684  // memberMap should now consist of members with new flat version, so save
685  theInterface_->saveTableGroup(
686  memberMap,
687  TableGroupKey::getFullGroupString(groupPair.first.first, newKey));
688 
689  // and modify groupSet and activeGroupKeys keys
690  groupPair.second = newKey;
691  }
692  catch(std::runtime_error& e)
693  {
694  __COUT__ << "Error was caught saving group " << groupPair.first.first << " ("
695  << groupPair.first.second << ") " << std::endl;
696  __COUT__ << e.what() << std::endl;
697 
698  groupErrors.insert(
699  std::pair<std::pair<std::string, TableGroupKey>, std::string>(
700  std::pair<std::string, TableGroupKey>(groupPair.first.first,
701  groupPair.first.second),
702  "Error caught saving the group."));
703  }
704  catch(...)
705  {
706  __COUT__ << "Error was caught saving group " << groupPair.first.first << " ("
707  << groupPair.first.second << ") " << std::endl;
708 
709  groupErrors.insert(
710  std::pair<std::pair<std::string, TableGroupKey>, std::string>(
711  std::pair<std::string, TableGroupKey>(groupPair.first.first,
712  groupPair.first.second),
713  "Error caught saving the group."));
714  }
715  //=========================
716 
717  // increment
718  ++count;
719  } // end group loop
720 
721  __COUT__ << "Completed group and table saving for " << count << " groups." << __E__;
722  __COUT__ << "Created tables:" << std::endl;
723  for(auto& tablePair : newTableVersionMap)
724  __COUT__ << "\t" << tablePair.first.first << "-v" << tablePair.first.second
725  << " ==> " << tablePair.second << std::endl;
726  __COUT__ << std::endl;
727  __COUT__ << std::endl;
728  __COUT__ << "Created groups:" << std::endl;
729  for(auto& group : groupSet)
730  __COUT__ << "\t" << group.first.first << "(" << group.first.second << ") ==> "
731  << group.second << std::endl;
732 
733  // -- in current-db after loop...
734  // -- swap to current-db
735  if(importedDbInPlace)
736  {
737  __COUT__ << "Swap to current-db" << std::endl;
738  if(rename(currentDir.c_str(), importDir.c_str()) < 0)
739  {
740  __SS__ << "Problem!" << std::endl;
741  __SS_THROW__;
742  }
743  if(rename(tmpCurrentDir.c_str(), currentDir.c_str()) < 0)
744  {
745  __SS__ << "Problem!" << std::endl;
746  __SS_THROW__;
747  }
748  importedDbInPlace = false;
749  }
750 
751  // record in readme for current-db
752  {
753  FILE* fp = fopen((currentDir + "/README_otsdaq_import.txt").c_str(), "a");
754 
755  if(!fp)
756  __COUT__ << "\tError opening README file!" << std::endl;
757  else
758  {
759  time_t rawtime;
760  struct tm* timeinfo;
761  char buffer[200];
762 
763  time(&rawtime);
764  timeinfo = localtime(&rawtime);
765  strftime(buffer, 200, "%b %d, %Y %I:%M:%S%p %Z", timeinfo);
766 
767  fprintf(fp,
768  "This database...\t %s \t received an import from...\t %s \t at this "
769  "time \t %lu \t %s\n\n",
770  currentDir.c_str(),
771  pathToImportDatabase.c_str(),
772  time(0),
773  buffer);
774  fclose(fp);
775  }
776  }
777 
778  // -- in current-db after loop...
779  // - destroy and reload active groups
780  cfgMgr->destroy();
781  cfgMgr->restoreActiveTableGroups(true /*throwErrors*/);
782 
783  // -- insert new aliases for imported groups
784  // - should be basename+alias connection to (hop through maps) new groupName &
785  // groupKey
786  // -- insert new aliases for imported tables
787  // - should be basename+alias connection to (hop through maps) new tableName &
788  // tableVersion
789  // -- save new backbone tables and save new backbone group
790 
791  __COUT__ << "Modifying the active Backbone table to reflect new table versions and "
792  "group keys."
793  << std::endl;
794 
795  try
796  {
797  // modify Group Aliases Table and Version Aliases Table to
798  // include new groups and tables
799 
800  std::string activeBackboneGroupName =
801  cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::BACKBONE_TYPE);
802  cfgMgr->loadTableGroup(
803  activeBackboneGroupName,
804  cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::BACKBONE_TYPE),
805  true,
806  &memberMap,
807  0,
808  &accumulateErrors);
809 
810  std::map<std::string, TableVersion> activeMap = cfgMgr->getActiveVersions();
811 
812  // modify Group Aliases Table
813  if(activeMap.find(groupAliasesTableName) != activeMap.end())
814  {
815  __COUT__ << "\n\nModifying " << groupAliasesTableName << std::endl;
816  config = cfgMgr->getTableByName(groupAliasesTableName);
817  cfgView = config->getViewP();
818 
819  unsigned int col0 = cfgView->findCol("GroupKeyAlias");
820  unsigned int col1 = cfgView->findCol("GroupName");
821  unsigned int col2 = cfgView->findCol("GroupKey");
822  unsigned int row;
823 
824  cfgView->print();
825 
826  // -- insert new aliases for imported groups
827  // - should be basename+alias connection to (hop through maps) new
828  // groupName & groupKey
829  for(auto& aliasPair : originalGroupAliasMap)
830  {
831  auto groupIt = groupSet.find(std::pair<std::string, TableGroupKey>(
832  aliasPair.second.first, aliasPair.second.second));
833 
834  if(groupIt == groupSet.end())
835  {
836  __COUT__
837  << "Error! Could not find the new entry for the original group "
838  << aliasPair.second.first << "(" << aliasPair.second.second << ")"
839  << __E__;
840  continue;
841  }
842  row = cfgView->addRow("import_aliases", true /*incrementUniqueData*/);
843  cfgView->setValue(aliasPair.first, row, col0);
844  cfgView->setValue(aliasPair.second.first, row, col1);
845  cfgView->setValue(groupIt->second.toString(), row, col2);
846  } // end group alias edit
847 
848  cfgView->print();
849  }
850 
851  // modify Version Aliases Table
852  if(activeMap.find(versionAliasesTableName) != activeMap.end())
853  {
854  __COUT__ << "\n\nModifying " << versionAliasesTableName << std::endl;
855  config = cfgMgr->getTableByName(versionAliasesTableName);
856  cfgView = config->getViewP();
857  unsigned int col0 = cfgView->findCol("VersionAlias");
858  unsigned int col1 = cfgView->findCol("TableName");
859  unsigned int col2 = cfgView->findCol("Version");
860 
861  unsigned int row;
862 
863  cfgView->print();
864 
865  // -- insert new aliases for imported tables
866  // - should be basename+alias connection to (hop through maps) new
867  // tableName & tableVersion
868  for(auto& aliasPair : originalTableAliasMap)
869  {
870  auto tableIt =
871  newTableVersionMap.find(std::pair<std::string, TableVersion>(
872  aliasPair.second.first, aliasPair.second.second));
873 
874  if(tableIt == newTableVersionMap.end())
875  {
876  __COUT__
877  << "Error! Could not find the new entry for the original table "
878  << aliasPair.second.first << "(" << aliasPair.second.second << ")"
879  << __E__;
880  continue;
881  }
882  row = cfgView->addRow("import_aliases", true /*incrementUniqueData*/);
883  cfgView->setValue(aliasPair.first, row, col0);
884  cfgView->setValue(aliasPair.second.first, row, col1);
885  cfgView->setValue(tableIt->second.toString(), row, col2);
886  } // end group alias edit
887 
888  cfgView->print();
889  }
890 
891  // save new Group Aliases Table and Version Aliases Table
892 
893  // change the version of the active view to flatVersion and save it
894  config = cfgMgr->getTableByName(groupAliasesTableName);
895  cfgView = config->getViewP();
896  newVersion =
897  TableVersion::getNextVersion(theInterface_->findLatestVersion(config));
898  __COUTV__(newVersion);
899  cfgView->setVersion(newVersion);
900  theInterface_->saveActiveVersion(config);
901 
902  memberMap[groupAliasesTableName] = newVersion; // change version in the member
903  // map
904 
905  __COUT__ << "\t to...\t" << groupAliasesTableName << ":v"
906  << memberMap[groupAliasesTableName] << std::endl;
907 
908  __COUT__ << versionAliasesTableName << ":v" << memberMap[versionAliasesTableName]
909  << std::endl;
910  // change the version of the active view to flatVersion and save it
911  config = cfgMgr->getTableByName(versionAliasesTableName);
912  cfgView = config->getViewP();
913  newVersion =
914  TableVersion::getNextVersion(theInterface_->findLatestVersion(config));
915  __COUTV__(newVersion);
916  cfgView->setVersion(newVersion);
917  theInterface_->saveActiveVersion(config);
918 
919  memberMap[versionAliasesTableName] =
920  newVersion; // change version in the member map
921 
922  __COUT__ << "\t to...\t" << versionAliasesTableName << ":v"
923  << memberMap[versionAliasesTableName] << std::endl;
924 
925  __COUT__ << "Backbone member map completed" << __E__;
926  __COUTV__(StringMacros::mapToString(memberMap));
927 
928  newKey = TableGroupKey::getNextKey(
929  theInterface_->findLatestGroupKey(activeBackboneGroupName));
930 
931  __COUTV__(newKey);
932 
933  // memberMap should now consist of members with new flat version, so save
934  theInterface_->saveTableGroup(
935  memberMap,
936  TableGroupKey::getFullGroupString(activeBackboneGroupName, newKey));
937 
938  std::string renameFile =
940  rename(ConfigurationManager::ACTIVE_GROUPS_FILENAME.c_str(), renameFile.c_str());
941 
942  __COUT__ << "Backing up '" << ConfigurationManager::ACTIVE_GROUPS_FILENAME
943  << "' to ... '" << renameFile << "'" << std::endl;
944 
945  cfgMgr->activateTableGroup(activeBackboneGroupName,
946  newKey); // and write to active group file
947 
948  } // end try
949  catch(const std::runtime_error& e)
950  {
951  __COUT_ERR__ << "There was a fatal error during backbone modification: "
952  << e.what() << __E__;
953 
954  goto CLEAN_UP;
955  }
956 
957  // print resulting all groups
958 
959  std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Groups:" << std::endl;
960  for(const auto& group : groupSet)
961  __COUT__ << "\t" << group.first.first << ": " << group.first.second << " => "
962  << group.second << std::endl;
963  std::cout << "\n\n" << __COUT_HDR_FL__ << "Resulting Groups end." << std::endl;
964 
965 CLEAN_UP:
966  //==============================================================================
967  __COUT__ << "End of Importing Active Table Groups!\n\n\n" << std::endl;
968 
969  __COUT__ << "****************************" << std::endl;
970  __COUT__ << "There were " << groupSet.size() << " groups considered, and there were "
971  << groupErrors.size() << " errors found handling those groups." << std::endl;
972  __COUT__ << "The following errors were found handling the groups:" << std::endl;
973  for(auto& groupErr : groupErrors)
974  __COUT__ << "\t" << groupErr.first.first << " " << groupErr.first.second << ": \t"
975  << groupErr.second << std::endl;
976  __COUT__ << "End of errors.\n\n" << std::endl;
977 
978  __COUT__ << "Run the following to return to your previous database structure:"
979  << std::endl;
980  __COUT__ << "\t otsdaq_flatten_system_aliases -1 " << backupDir << "\n\n"
981  << std::endl;
982 
983  return;
984 }
985 
986 int main(int argc, char* argv[])
987 {
988  ImportSystemAliasTableGroups(argc, argv);
989  return 0;
990 }
991 // BOOST_AUTO_TEST_SUITE_END()
virtual TableGroupKey findLatestGroupKey(const std::string &) const
otsdaq_database_migrate and otsdaq_import_system_aliases to compile
virtual TableVersion findLatestVersion(const TableBase *configuration) const =0
return INVALID if no existing versions
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::map< std::string, std::pair< std::string, TableGroupKey > > getActiveGroupAliases(void)
void activateTableGroup(const std::string &tableGroupName, TableGroupKey tableGroupKey, std::string *accumulatedTreeErrors=0, std::string *groupTypeString=0)
modifiers of table groups
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
static TableGroupKey getNextKey(const TableGroupKey &key=TableGroupKey())
bool isInvalid(void) const
isInvalid
static std::string getFullGroupString(const std::string &groupName, const TableGroupKey &key, const std::string &preKey="_v", const std::string &postKey="")
bool isInvalid(void) const
isInvalid
static TableVersion getNextVersion(const TableVersion &version=TableVersion())
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
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")