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