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