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