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