LCOV - code coverage report
Current view: top level - otsdaq/tools - otsdaq_import_groups_from_export_path.cc (source / functions) Coverage Total Hit
Test: mu2edaq.info.cleaned Lines: 0.0 % 853 0
Test Date: 2026-07-30 01:56:44 Functions: 0.0 % 177 0

            Line data    Source code
       1              : #include "otsdaq/MessageFacility/MessageFacility.h"
       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              : 
      12              : // Shared test utilities
      13              : #include "otsdaq/Macros/TestUtilities.h"
      14              : 
      15              : /// Imports all groups and group/table aliases (from backbone group) found at path
      16              : ///             to the current database and active backbone group. New table version and group keys will be assigned
      17              : ///             to the imported tables and groups.
      18              : /// usage:
      19              : /// otsdaq_import_groups_from_export_path <path to import from>
      20              : ///
      21              : ///
      22              : using namespace ots;
      23              : 
      24            0 : void ImportTableGroupsFromPath(int argc, char* argv[])
      25              : {
      26            0 :         std::cout << "=================================================\n";
      27            0 :         std::cout << "=================================================\n";
      28            0 :         std::cout << "=================================================\n";
      29            0 :         __COUT__ << "\nImporting Groups!" << std::endl;
      30              : 
      31            0 :         std::cout << "\n\nusage: One argument:\n\t <import path> \n\n" << std::endl;
      32              : 
      33            0 :         std::cout << "argc = " << argc << std::endl;
      34            0 :         for(int i = 0; i < argc; i++)
      35            0 :                 std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
      36              : 
      37            0 :         if(argc < 2)
      38              :         {
      39            0 :                 std::cout << "Error! Must provide at least one parameter.\n\n" << std::endl;
      40            0 :                 return;
      41              :         }
      42              : 
      43            0 :         std::string importPath = argv[1];
      44            0 :         std::string prepend    = argc > 2 ? argv[2] : "";  //get prepend arg or empty default
      45            0 :         bool        forceBackboneSave =
      46            0 :         argc > 3 ? true : false;  //get force backbone save arg or false
      47            0 :         int flatVersion = 0;
      48              : 
      49            0 :         __COUTV__(importPath);
      50            0 :         __COUTV__(flatVersion);
      51            0 :         __COUTV__(prepend);
      52            0 :         __COUTV__(forceBackboneSave);
      53              : 
      54              :         //==============================================================================
      55              :         // Steps:
      56              :         //
      57              :         //      -- create empty map of import alias to original groupName & groupKey
      58              :         //      -- create empty map of original groupName & groupKey to new groupKey
      59              :         //
      60              :         //      -- create empty map of import alias to original tableName & tableVersion
      61              :         //      -- create empty map of original tableName & tableVersion to new tableVersion
      62              :         //
      63              :         //      -- check import basename+alias for collision with existing group aliases and throw
      64              :         // error if collision
      65              :         //      -- check import basename+alias for collision with existing table aliases and throw
      66              :         // error if collision
      67              :         //
      68              :         //      -- track map of import alias --> import group name/key --> new group key
      69              :         //      -- track map of import table name --> import version --> new table version, to prevent looking multiple times for duplicate tables
      70              :         //      -- for each group to import
      71              :         //              - for each table in group to import
      72              :         //                      . load json into table view, check that table view is unique
      73              :         //                      . if not unique update member map version
      74              :         //              - save (modified) member map as new group
      75              :         //              - report to user import alias --> import group/table name/key --> new group/table key
      76              :         //
      77              :         //      -- reload active backbone group
      78              :         //      -- insert new aliases for imported groups in current active backbone
      79              :         //              - should be basename+alias connection to (hop through maps) new groupName & groupKey
      80              :         //      -- insert new aliases for imported tables
      81              :         //              - should be basename+alias connection to (hop through maps) new tableName & tableVersion
      82              :         //      -- save new backbone tables and save new backbone group
      83              :         //      -- backup the file ConfigurationManager::ACTIVE_GROUPS_FILENAME with time
      84              :         //      -- activate the new backbone group
      85              :         //
      86              :         //==============================================================================
      87              : 
      88              :         // clang-format off
      89              :         std::map<std::string /*importGroupAlias*/,
      90            0 :                 /*original*/ std::pair<std::string /*groupName*/, TableGroupKey /*origKey*/>>  importGroupAliasMap;
      91              :         std::map<std::pair<std::string /*groupName*/, TableGroupKey /*origKey*/>,
      92            0 :                 TableGroupKey /*newKey*/>                                                                                                            importGroupMap;
      93              :         std::map<std::string /*importTableAlias*/,
      94              :                  /*original*/ std::pair<std::string /*tableName*/,
      95            0 :                          TableVersion /*origVersion*/>>                                                                                           importTableAliasMap;
      96              :         std::map</*original*/ std::pair<std::string /*tableName*/, TableVersion /*origVersion*/>,
      97            0 :                  /*newVersion*/ TableVersion>                                                                                                importTableMap;
      98              :         // clang-format on
      99              : 
     100            0 :         std::string   importedBackboneGroupName = "";
     101            0 :         TableGroupKey importedBackboneGroupKey;
     102              : 
     103              :         // add groups to vector list from directory
     104              :         {
     105              :                 DIR*           dp;
     106              :                 struct dirent* dirp;
     107            0 :                 if((dp = opendir(importPath.c_str())) == 0)
     108              :                 {
     109            0 :                         __COUT_ERR__ << "ERROR:(" << errno
     110            0 :                                      << ").  Can't open directory: " << importPath << std::endl;
     111            0 :                         exit(0);
     112              :                 }
     113              : 
     114            0 :                 const unsigned char isDir = 0x4;
     115            0 :                 while((dirp = readdir(dp)) != 0)
     116            0 :                         if(dirp->d_type == isDir && dirp->d_name[0] != '.')  //if a directory type
     117              :                         {
     118            0 :                                 __COUT__ << "Directory: " << dirp->d_name << std::endl;
     119              : 
     120            0 :                                 auto split = StringMacros::getVectorFromString(dirp->d_name, {'_'});
     121              : 
     122            0 :                                 if(split.size() != 2)
     123            0 :                                         continue;
     124              : 
     125            0 :                                 importGroupMap.insert(
     126            0 :                                     std::pair<
     127              :                                         std::pair<std::string /*groupName*/, TableGroupKey /*origKey*/>,
     128              :                                         TableGroupKey /*newKey*/>(
     129            0 :                                         std::pair<std::string, TableGroupKey>(split[0], split[1]),
     130            0 :                                         TableGroupKey()));
     131              : 
     132              :                                 //check if group is the active backbone to import
     133              :                                 std::string groupIsBackbonePath =
     134            0 :                                     importPath + "/" + dirp->d_name + "/" + "groupIsBackbone.txt";
     135            0 :                                 __COUTV__(groupIsBackbonePath);
     136            0 :                                 FILE* fp = std::fopen(groupIsBackbonePath.c_str(), "r");
     137            0 :                                 if(fp)
     138              :                                 {
     139            0 :                                         fclose(fp);
     140            0 :                                         __COUT_INFO__ << "Found imported Backbone as " << split[0] << " ("
     141            0 :                                                       << split[1] << ")" << __E__;
     142            0 :                                         importedBackboneGroupName = split[0];
     143            0 :                                         importedBackboneGroupKey  = TableGroupKey(split[1]);
     144              :                                 }
     145            0 :                         }  //end found group directory handling
     146              : 
     147            0 :                 closedir(dp);
     148              :         }
     149              : 
     150            0 :         __COUT__ << "Identified groups to import:" << std::endl;
     151            0 :         for(auto& group : importGroupMap)
     152            0 :                 __COUT__ << " ==> Group to import: " << group.first.first << " ("
     153            0 :                          << group.first.second << ")" << std::endl;
     154            0 :         __COUTV__(importedBackboneGroupName);
     155              : 
     156            0 :         if(!importGroupMap.size())
     157              :         {
     158            0 :                 __SS__ << "No groups identified to import!" << __E__;
     159            0 :                 __SS_THROW__;
     160            0 :         }
     161              :         // return;
     162              : 
     163              :         //==============================================================================
     164              :         // Define environment variables
     165              :         //      Note: normally these environment variables are set by ots script
     166              : 
     167            0 :         test::util::check_and_make_envs();
     168              : 
     169              :         ////////////////////////////////////////////////////
     170              : 
     171              :         // get prepared with initial source db
     172              : 
     173              :         // ConfigurationManager instance immediately loads active groups
     174            0 :         __COUT__ << "Loading active Backbone..." << std::endl;
     175              : 
     176            0 :         std::string ARTDAQ_DATABASE_URI = __ENV__("ARTDAQ_DATABASE_URI");
     177            0 :         __COUTV__(ARTDAQ_DATABASE_URI);
     178              : 
     179              :         // return;
     180              : 
     181            0 :         ConfigurationManagerRW  cfgMgrInst("import_admin");
     182            0 :         ConfigurationManagerRW* cfgMgr = &cfgMgrInst;
     183              : 
     184              :         //get all table/group info
     185              :         {
     186            0 :                 std::string                             accumulatedWarnings;
     187              :                 const std::map<std::string, TableInfo>& allTableInfo =
     188            0 :                     cfgMgr->getAllTableInfo(true /* refresh */,
     189              :                                             &accumulatedWarnings,
     190              :                                             "" /* errorFilterName */,
     191              :                                             true /* getGroupKeys*/,
     192              :                                             false /* getGroupInfo */,
     193              :                                             true /* initializeActiveGroups */);
     194            0 :                 __COUTV__(allTableInfo.size());
     195            0 :                 auto groups = cfgMgr->getAllGroupInfo();
     196            0 :                 __COUTTV__(groups.size());
     197            0 :                 if(TTEST(1))
     198            0 :                         for(auto& group : groups)
     199              :                         {
     200            0 :                                 __COUTTV__(group.first);
     201              :                         }
     202            0 :         }
     203              : 
     204            0 :         ConfigurationInterface* theInterface_ = ConfigurationInterface::getInstance(
     205              :             ConfigurationInterface::CONFIGURATION_MODE::ARTDAQ_DATABASE);
     206              : 
     207              :         if(0)
     208              :         {
     209              :                 __COUT__ << "Test finding equivalent backbone table versions" << __E__;
     210              : 
     211              :                 auto table =
     212              :                     cfgMgr->getTableByName(ConfigurationManager::VERSION_ALIASES_TABLE_NAME);
     213              :                 __COUTV__(table->getTableName());
     214              :                 __COUTV__(table->getViewVersion());
     215              : 
     216              :                 auto         cfgView = table->getViewP();
     217              :                 unsigned int col0    = cfgView->findCol("VersionAlias");
     218              :                 unsigned int col1    = cfgView->findCol("TableName");
     219              :                 unsigned int col2    = cfgView->findCol("Version");
     220              : 
     221              :                 unsigned int row;
     222              : 
     223              :                 cfgView->print();
     224              : 
     225              :                 TableVersion duplicateVersion;
     226              : 
     227              :                 //      -- insert new aliases for imported tables
     228              :                 //              - should be basename+alias connection to (hop through maps) new
     229              :                 // tableName & tableVersion
     230              :                 for(auto& aliasPair : importTableAliasMap)
     231              :                 {
     232              :                         __COUT__ << "\t" << aliasPair.first << " ==> " << aliasPair.second.first
     233              :                                  << "-" << aliasPair.second.second << std::endl;
     234              : 
     235              :                         auto tableIt = importTableMap.find(std::pair<std::string, TableVersion>(
     236              :                             aliasPair.second.first, aliasPair.second.second));
     237              : 
     238              :                         if(tableIt == importTableMap.end())
     239              :                         {
     240              :                                 __COUT__ << "Error! Could not find the new entry for the original table "
     241              :                                          << aliasPair.second.first << "(" << aliasPair.second.second
     242              :                                          << ")" << __E__;
     243              :                                 continue;
     244              :                         }
     245              :                         row =
     246              :                             cfgView->addRow(prepend + "import_aliases", true /*incrementUniqueData*/);
     247              :                         cfgView->setValue(prepend + aliasPair.first, row, col0);
     248              :                         cfgView->setValue(aliasPair.second.first, row, col1);
     249              :                         cfgView->setValue(tableIt->second.toString(), row, col2);
     250              :                 }  // end group alias edit
     251              : 
     252              :                 if(!importTableAliasMap.size())
     253              :                         duplicateVersion =
     254              :                             table->getViewVersion();  //mark duplicate as self if nothing to add
     255              : 
     256              :                 cfgView->print();
     257              :                 TableVersion originalVersion =
     258              :                     table
     259              :                         ->getViewVersion();  //save version because cache fill will change active version
     260              : 
     261              :                 if(duplicateVersion.isInvalid())
     262              :                 {
     263              :                         auto tableName = ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
     264              :                         __COUT__ << "Checking for duplicate '" << tableName << "' tables..." << __E__;
     265              : 
     266              :                         {
     267              :                                 //"DEEP" checking
     268              :                                 //      load into cache 'recent' versions for this table
     269              :                                 //              'recent' := those already in cache, plus highest version numbers not in cache
     270              :                                 const std::map<std::string, TableInfo>& allTableInfo =
     271              :                                     cfgMgr->getAllTableInfo();  // do not refresh
     272              : 
     273              :                                 auto versionReverseIterator =
     274              :                                     allTableInfo.at(tableName)
     275              :                                         .versions_.rbegin();  // get reverse iterator
     276              :                                 __COUT__ << "Filling up '" << tableName << "' cache from "
     277              :                                          << table->getNumberOfStoredViews() << " to max count of "
     278              :                                          << table->MAX_VIEWS_IN_CACHE << __E__;
     279              :                                 for(;
     280              :                                     table->getNumberOfStoredViews() < table->MAX_VIEWS_IN_CACHE &&
     281              :                                     versionReverseIterator != allTableInfo.at(tableName).versions_.rend();
     282              :                                     ++versionReverseIterator)
     283              :                                 {
     284              :                                         __COUTT__ << "'" << tableName << "' versions in reverse order "
     285              :                                                   << *versionReverseIterator << __E__;
     286              :                                         try
     287              :                                         {
     288              :                                                 cfgMgr->getVersionedTableByName(
     289              :                                                     tableName,
     290              :                                                     *versionReverseIterator);  // load to cache
     291              :                                         }
     292              :                                         catch(const std::runtime_error& e)
     293              :                                         {
     294              :                                                 // ignore error
     295              :                                                 __COUTT__ << "'" << tableName << "' version failed to load: "
     296              :                                                           << *versionReverseIterator << __E__;
     297              :                                         }
     298              :                                 }
     299              :                         }
     300              : 
     301              :                         __COUT__ << "Checking '" << tableName << "' for duplicate..." << __E__;
     302              :                         duplicateVersion =
     303              :                             table->checkForDuplicate(originalVersion,
     304              :                                                      TableVersion());  // then all versions in search
     305              : 
     306              :                 }  //end check duplicate
     307              : 
     308              :                 //return the original version to active
     309              :                 table->setActiveView(originalVersion);
     310              : 
     311              :                 if(!duplicateVersion.isInvalid())
     312              :                 {
     313              :                         // found an equivalent!
     314              :                         __COUT__ << "Equivalent table found in version v" << duplicateVersion
     315              :                                  << __E__;
     316              :                 }
     317              :                 else
     318              :                 {
     319              :                         __COUTV__(table->getViewVersion());
     320              :                         auto newVersion =
     321              :                             TableVersion::getNextVersion(theInterface_->findLatestVersion(table));
     322              :                         __COUTV__(newVersion);
     323              :                         // cfgView->setVersion(newVersion);
     324              :                         // theInterface_->saveActiveVersion(table);
     325              :                 }
     326              : 
     327              :         }  //end test version alias new version
     328              : 
     329              :         // return;
     330              : 
     331              :         //if missing Active Groups File, create empty backbone group (e.g., to seed a new database)
     332            0 :         FILE* fp = nullptr;
     333            0 :         if(!(fp = fopen(ConfigurationManager::ACTIVE_GROUPS_FILENAME.c_str(), "r")))
     334              :         {
     335            0 :                 __COUT_INFO__ << "Identified missing Active Groups File: "
     336            0 :                               << ConfigurationManager::ACTIVE_GROUPS_FILENAME << __E__;
     337            0 :                 __COUT_INFO__ << "Creating an empty Backbone group... group name will match "
     338            0 :                                  "imported backbone name: "
     339            0 :                               << importedBackboneGroupName << __E__;
     340              : 
     341            0 :                 std::map<std::string, TableVersion> backboneMemberMap;
     342            0 :                 for(auto& memberName : ConfigurationManager::getBackboneMemberNames())
     343              :                 {
     344              :                         //create empty mockup version
     345              :                         // if mockup, then generate a new persistent version to use based on mockup
     346            0 :                         TableBase* table = cfgMgr->getTableByName(memberName);
     347              :                         // create a temporary version from the mockup as source version
     348            0 :                         TableVersion temporaryVersion = table->createTemporaryView();
     349            0 :                         __COUT__ << "\t\ttemporaryVersion: " << temporaryVersion << __E__;
     350              : 
     351              :                         // if other versions exist check for another mockup, and use that instead
     352            0 :                         __COUT__ << "Creating version from mock-up for name: " << memberName
     353            0 :                                  << " temporaryVersion: " << temporaryVersion << __E__;
     354              : 
     355              :                         // set table comment
     356              :                         table->getTemporaryView(temporaryVersion)
     357            0 :                             ->setComment("Auto-generated from mock-up.");
     358              : 
     359              :                         // finish off the version creation
     360              :                         bool foundEquivalent;
     361              :                         auto newAssignedVersion =
     362              :                             cfgMgr->saveModifiedVersion(memberName,
     363            0 :                                                         TableVersion() /*original source is mockup*/,
     364              :                                                         false /*makeTemporary*/,
     365              :                                                         table,
     366              :                                                         temporaryVersion,
     367              :                                                         false /*ignoreDuplicates*/,
     368              :                                                         true /*lookForEquivalent*/,
     369            0 :                                                         &foundEquivalent);
     370            0 :                         if(foundEquivalent)
     371            0 :                                 __COUT__ << "Found equivalent version: " << newAssignedVersion << __E__;
     372              :                         else
     373            0 :                                 __COUT__ << "Created new version: " << newAssignedVersion << __E__;
     374              : 
     375            0 :                         backboneMemberMap[memberName] = newAssignedVersion;
     376            0 :                 }
     377            0 :                 __COUTV__(StringMacros::mapToString(backboneMemberMap));
     378              : 
     379            0 :                 bool foundExistingEmptyBackbone = false;
     380              :                 {  //check if group is a duplicate
     381            0 :                         __COUT__ << "Checking for duplicate groups..." << __E__;
     382              :                         try
     383              :                         {
     384              :                                 TableGroupKey foundKey = cfgMgr->findTableGroup(
     385              :                                     importedBackboneGroupName,
     386            0 :                                     backboneMemberMap);  //, memberTableAliases); std::map<std::string /*name*/, std::string /*alias*/>    memberTableAliases
     387              : 
     388            0 :                                 if(!foundKey.isInvalid())
     389              :                                 {
     390            0 :                                         __COUT_WARN__ << "Found equivalent empty backbone group key ("
     391            0 :                                                       << foundKey << ") for " << importedBackboneGroupName
     392            0 :                                                       << ". Skipping creation and activating existing key!"
     393            0 :                                                       << __E__;
     394            0 :                                         foundExistingEmptyBackbone = true;
     395              : 
     396              :                                         //      -- activate the existing empty backbone group
     397            0 :                                         cfgMgr->activateTableGroup(
     398              :                                             importedBackboneGroupName,
     399              :                                             foundKey);  // and write to active group file
     400              :                                 }
     401              : 
     402            0 :                                 __COUT__ << "Check for empty backbone duplicate groups complete."
     403            0 :                                          << __E__;
     404            0 :                         }
     405            0 :                         catch(...)
     406              :                         {
     407            0 :                                 __COUT_WARN__ << "Ignoring errors looking for empty backbone duplicate "
     408              :                                                  "groups! Proceeding "
     409            0 :                                                  "with new group creation."
     410            0 :                                               << __E__;
     411            0 :                         }
     412              :                 }  //end check if group is a duplicate
     413            0 :                 __COUTV__(foundExistingEmptyBackbone);
     414              : 
     415            0 :                 if(!foundExistingEmptyBackbone)  //save new empty backbone
     416              :                 {
     417              :                         TableGroupKey newKey = TableGroupKey::getNextKey(
     418            0 :                             theInterface_->findLatestGroupKey(importedBackboneGroupName));
     419              : 
     420              :                         // save group, and retry on save collision
     421            0 :                         uint16_t retries = 0;
     422              :                         while(1)
     423              :                         {
     424            0 :                                 __COUT__ << "New Key for empty backbone group: "
     425            0 :                                          << importedBackboneGroupName << " found as " << newKey << __E__;
     426              : 
     427              :                                 try
     428              :                                 {
     429            0 :                                         theInterface_->saveTableGroup(backboneMemberMap,
     430            0 :                                                                       TableGroupKey::getFullGroupString(
     431              :                                                                           importedBackboneGroupName, newKey));
     432              :                                 }
     433            0 :                                 catch(const std::runtime_error& e)
     434              :                                 {
     435            0 :                                         __COUT__ << "Caught runtime_error exception during group save."
     436            0 :                                                  << __E__;
     437            0 :                                         if(std::string(e.what()).find("there was a collision") !=
     438              :                                            std::string::npos)
     439              :                                         {
     440            0 :                                                 __COUT_WARN__
     441            0 :                                                     << "There was a collision saving the new group "
     442            0 :                                                     << importedBackboneGroupName << "(" << newKey
     443            0 :                                                     << "), trying incremented group key... retries=" << retries
     444            0 :                                                     << __E__;
     445            0 :                                                 if(++retries > 3)  //give up
     446            0 :                                                         throw;
     447            0 :                                                 newKey = TableGroupKey::getNextKey(newKey);  //increment group key
     448            0 :                                                 __COUT__ << "New Key for group: " << importedBackboneGroupName
     449            0 :                                                          << " found as " << newKey << __E__;
     450            0 :                                                 continue;
     451            0 :                                         }
     452              :                                         else
     453            0 :                                                 throw;
     454            0 :                                 }
     455            0 :                                 __COUT__ << "Created new empty backbone table group: "
     456            0 :                                          << importedBackboneGroupName << "(" << newKey << ")" << __E__;
     457            0 :                                 break;
     458            0 :                         }  //end collission retry loop
     459              : 
     460              :                         //      -- activate the new empty backbone group
     461            0 :                         cfgMgr->activateTableGroup(importedBackboneGroupName,
     462              :                                                    newKey);  // and write to active group file
     463            0 :                 }
     464              : 
     465            0 :                 __COUT_INFO__ << "Empty backbone group now activated!" << __E__;
     466              :                 // return;
     467            0 :         }
     468            0 :         else if(fp)
     469            0 :                 fclose(fp);
     470              : 
     471              :         //load active backbone
     472              :         {
     473            0 :                 std::string accumulatedWarnings;
     474            0 :                 cfgMgr->restoreActiveTableGroups(
     475              :                     false /*throwErrors*/,
     476              :                     "" /*pathToActiveGroupsFile*/,
     477              :                     ConfigurationManager::LoadGroupType::ONLY_BACKBONE_TYPE,
     478              :                     &accumulatedWarnings);
     479              : 
     480            0 :                 __COUT__ << "Done Loading active backbone." << std::endl;
     481            0 :         }
     482              : 
     483              :         // return;
     484              : 
     485              :         /* <tableName, <origVersion, newVersion> >*/
     486            0 :         std::map<std::pair<std::string, TableVersion>, TableVersion>   modifiedTables;
     487            0 :         std::map<std::string, std::pair<TableGroupKey, TableGroupKey>> activeGroupKeys;
     488            0 :         std::map<std::pair<std::string, TableGroupKey>, std::string>   groupErrors;
     489              : 
     490            0 :         std::string activeBackboneGroupName = "";
     491            0 :         std::string activeContextGroupName  = "";
     492            0 :         std::string activeIterateGroupName  = "";
     493            0 :         std::string activeConfigGroupName   = "";
     494              : 
     495            0 :         std::string nowTime = std::to_string(time(0));
     496              : 
     497              :         // Find active backbone ---------------
     498              :         std::map<std::string, std::pair<std::string, TableGroupKey>> activeGroupsMap =
     499            0 :             cfgMgr->getActiveTableGroups();
     500              : 
     501            0 :         bool foundAnyActiveGroups = false;
     502              : 
     503            0 :         for(const auto& activeGroup : activeGroupsMap)
     504              :         {
     505            0 :                 if(activeGroup.second.second.TableGroupKey::isInvalid())
     506            0 :                         continue;
     507              : 
     508            0 :                 activeGroupKeys.insert(
     509            0 :                     std::pair<std::string, std::pair<TableGroupKey, TableGroupKey>>(
     510            0 :                         activeGroup.second.first,
     511            0 :                         std::pair<TableGroupKey, TableGroupKey>(activeGroup.second.second,
     512            0 :                                                                 TableGroupKey())));
     513              : 
     514            0 :                 if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_BACKBONE)
     515              :                 {
     516            0 :                         activeBackboneGroupName = activeGroup.second.first;
     517            0 :                         __COUT__ << "found activeBackboneGroupName = " << activeBackboneGroupName
     518            0 :                                  << std::endl;
     519            0 :                         foundAnyActiveGroups = true;
     520              :                 }
     521            0 :                 else if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
     522              :                 {
     523            0 :                         activeContextGroupName = activeGroup.second.first;
     524            0 :                         __COUT__ << "found activeContextGroupName = " << activeContextGroupName
     525            0 :                                  << std::endl;
     526            0 :                         foundAnyActiveGroups = true;
     527              :                 }
     528            0 :                 else if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_ITERATE)
     529              :                 {
     530            0 :                         activeIterateGroupName = activeGroup.second.first;
     531            0 :                         __COUT__ << "found activeIterateGroupName = " << activeIterateGroupName
     532            0 :                                  << std::endl;
     533            0 :                         foundAnyActiveGroups = true;
     534              :                 }
     535            0 :                 else if(activeGroup.first == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
     536              :                 {
     537            0 :                         activeConfigGroupName = activeGroup.second.first;
     538            0 :                         __COUT__ << "found activeConfigGroupName = " << activeConfigGroupName
     539            0 :                                  << std::endl;
     540            0 :                         foundAnyActiveGroups = true;
     541              :                 }
     542              :         }
     543            0 :         __COUT__ << "Identified active groups: " << activeGroupsMap.size() << std::endl;
     544            0 :         for(auto& group : activeGroupsMap)
     545            0 :                 __COUT__ << " ==> Active Group of type " << group.first << ": "
     546            0 :                          << group.second.first << " (" << group.second.second << ")" << std::endl;
     547              : 
     548            0 :         __COUT__ << "Identified groups to import: " << importGroupMap.size() << std::endl;
     549            0 :         for(auto& group : importGroupMap)
     550            0 :                 __COUT__ << " ==> Group to import: " << group.first.first << " ("
     551            0 :                          << group.first.second << ")" << std::endl;
     552            0 :         __COUTV__(importedBackboneGroupName);
     553            0 :         __COUTV__(prepend);
     554              : 
     555            0 :         if(activeBackboneGroupName == "" || !foundAnyActiveGroups)
     556              :         {
     557            0 :                 __SS__
     558              :                     << "Did not find valid active groups in current database as starting point "
     559              :                        "for import! "
     560              :                        "Must have a backbone at least. Is the current database URI correct? "
     561              :                        "ARTDAQ_DATABASE_URI = "
     562              :                     << ARTDAQ_DATABASE_URI
     563              :                     << "\n\n*** Note: The active groups are specified by the Active Groups file: "
     564              :                     << ConfigurationManager::ACTIVE_GROUPS_FILENAME
     565              :                     << "\n*** If you want an empty backbone to be generated for you as a "
     566            0 :                        "starting point, please delete the Active Groups file."
     567            0 :                     << std::endl;
     568            0 :                 __SS_THROW__;
     569            0 :         }
     570              :         //return; //comment for production functionality
     571              : 
     572              :         // ------------
     573              :         // At this point, all groups to import have been identified! and which import is Backbone has been identified ------------
     574              :         // now check for any alias conflicts between current Backbone and Backbone-to-Import
     575              : 
     576              :         {  //check import backbone group and table aliases for uniqueness
     577            0 :                 std::string importBackbonePath = importPath + "/" + importedBackboneGroupName +
     578            0 :                                                  "_" + importedBackboneGroupKey.str();
     579            0 :                 __COUTV__(importBackbonePath);
     580              : 
     581              :                 std::map<std::string /* tableName */, TableVersion /* tableVersion */>
     582            0 :                     memberTableSet;
     583              :                 {  //get member table file names
     584              :                         DIR*           dp;
     585              :                         struct dirent* dirp;
     586            0 :                         if((dp = opendir(importBackbonePath.c_str())) == 0)
     587              :                         {
     588            0 :                                 __COUT_ERR__ << "ERROR:(" << errno
     589            0 :                                              << ").  Can't open directory: " << importBackbonePath
     590            0 :                                              << std::endl;
     591            0 :                                 exit(0);
     592              :                         }
     593              : 
     594            0 :                         const unsigned char isDir = 0x4;
     595            0 :                         while((dirp = readdir(dp)) != 0)
     596            0 :                                 if(dirp->d_type != isDir && strlen(dirp->d_name) > 5 &&
     597            0 :                                    dirp->d_name[strlen(dirp->d_name) - 5] == '.' &&
     598            0 :                                    dirp->d_name[strlen(dirp->d_name) - 4] == 'j' &&
     599            0 :                                    dirp->d_name[strlen(dirp->d_name) - 3] == 's' &&
     600            0 :                                    dirp->d_name[strlen(dirp->d_name) - 2] == 'o' &&
     601            0 :                                    dirp->d_name[strlen(dirp->d_name) - 1] ==
     602              :                                        'n')  //if not directory w/extension .json
     603              :                                 {
     604            0 :                                         __COUT__ << dirp->d_name << std::endl;
     605              : 
     606            0 :                                         auto split = StringMacros::getVectorFromString(dirp->d_name, {'_'});
     607              : 
     608            0 :                                         if(split.size() != 2)
     609            0 :                                                 continue;
     610              : 
     611            0 :                                         memberTableSet.insert(std::pair<std::string, TableVersion>(
     612            0 :                                             split[0], split[1].substr(1, split[1].size() - 6)));
     613            0 :                                 }  //end found group directory handling
     614              : 
     615            0 :                         closedir(dp);
     616              :                 }  //end load of backbone alias table names/versions from directory
     617              : 
     618              :                 {  //verify group aliases are unique
     619              :                         std::vector<std::pair<std::string, ConfigurationTree>> currentAliasNodePairs =
     620            0 :                             cfgMgr->getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME)
     621            0 :                                 .getChildren();
     622            0 :                         std::set<std::string /* current aliases */> currentAliases;
     623              : 
     624            0 :                         __COUTV__(cfgMgr->getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME)
     625            0 :                                       .getTableName());
     626            0 :                         __COUTV__(cfgMgr->getNode(ConfigurationManager::GROUP_ALIASES_TABLE_NAME)
     627            0 :                                       .getTableVersion());
     628              : 
     629            0 :                         __COUT__ << "Existing group aliases:" << __E__;
     630            0 :                         for(auto& groupPair : currentAliasNodePairs)
     631              :                         {
     632            0 :                                 __COUT__ << " ==> Current group alias "
     633            0 :                                          << groupPair.second.getNode("GroupKeyAlias").getValueAsString()
     634            0 :                                          << ": "
     635            0 :                                          << groupPair.second.getNode("GroupName").getValueAsString()
     636            0 :                                          << " ("
     637            0 :                                          << TableGroupKey(
     638            0 :                                                 groupPair.second.getNode("GroupKey").getValueAsString())
     639            0 :                                          << ")" << __E__;
     640              : 
     641            0 :                                 currentAliases.emplace(
     642            0 :                                     groupPair.second.getNode("GroupKeyAlias").getValueAsString());
     643              :                         }
     644              : 
     645              :                         std::string fullpath =
     646            0 :                             importBackbonePath + "/" +
     647            0 :                             ConfigurationManager::GROUP_ALIASES_TABLE_NAME + "_v" +
     648            0 :                             memberTableSet.at(ConfigurationManager::GROUP_ALIASES_TABLE_NAME).str() +
     649            0 :                             ".json";
     650              : 
     651            0 :                         std::string json;
     652            0 :                         std::FILE*  fp = std::fopen(fullpath.c_str(), "rb");
     653            0 :                         if(!fp)
     654              :                         {
     655            0 :                                 __SS__ << "Could not open file at " << fullpath << ". Error: " << errno
     656            0 :                                        << " - " << strerror(errno) << __E__;
     657            0 :                                 __SS_THROW__;
     658            0 :                         }
     659            0 :                         std::fseek(fp, 0, SEEK_END);
     660            0 :                         json.resize(std::ftell(fp));
     661            0 :                         std::rewind(fp);
     662            0 :                         std::fread(&json[0], 1, json.size(), fp);
     663            0 :                         std::fclose(fp);
     664              : 
     665            0 :                         __COUTV__(json);
     666              : 
     667              :                         auto aliasTable =
     668            0 :                             cfgMgr->getTableByName(ConfigurationManager::GROUP_ALIASES_TABLE_NAME);
     669            0 :                         auto temporaryVersion = aliasTable->createTemporaryView();
     670            0 :                         auto aliasView        = aliasTable->getViewP(temporaryVersion);
     671              : 
     672            0 :                         aliasView->fillFromJSON(json);
     673            0 :                         aliasView->print();
     674              : 
     675            0 :                         auto aliasCol     = aliasView->findCol("GroupKeyAlias");
     676            0 :                         auto groupNameCol = aliasView->findCol("GroupName");
     677            0 :                         auto groupKeyCol  = aliasView->findCol("GroupKey");
     678              : 
     679            0 :                         __COUT__ << "Existing group aliases: " << currentAliases.size() << __E__;
     680            0 :                         for(auto& currentAlias : currentAliases)
     681            0 :                                 __COUTV__(currentAlias);
     682              : 
     683            0 :                         __COUT__ << "Checking that group aliases to import are unique:" << __E__;
     684            0 :                         for(size_t row = 0; row < aliasView->getNumberOfRows(); ++row)
     685              :                         {
     686            0 :                                 std::string aliasName = aliasView->getValueAsString(row, aliasCol);
     687            0 :                                 __COUT__ << " ==> Group alias to import at row " << row << ": "
     688            0 :                                          << aliasName << __E__;
     689            0 :                                 if(currentAliases.find(prepend + aliasName) != currentAliases.end())
     690              :                                 {
     691            0 :                                         __SS__ << "The imported prepend + group alias of '" << prepend
     692              :                                                << "' + '" << aliasName
     693              :                                                << "' already exists as a group alias in the current database."
     694              :                                                << " Please modify the prepend string to make the imported "
     695            0 :                                                   "alias names unique."
     696            0 :                                                << __E__;
     697            0 :                                         __SS_THROW__;
     698            0 :                                 }
     699            0 :                                 importGroupAliasMap[aliasName] =
     700            0 :                                     std::pair<std::string /*groupName*/, TableGroupKey /*origKey*/>(
     701            0 :                                         aliasView->getValueAsString(row, groupNameCol),
     702            0 :                                         aliasView->getValueAsString(row, groupKeyCol));
     703            0 :                         }
     704            0 :                         __COUT__ << "Verified group aliases to import are unique." << __E__;
     705            0 :                 }  //end verify group aliases are unique
     706              : 
     707              :                 {  //verify table aliases are unique
     708              :                         std::vector<std::pair<std::string, ConfigurationTree>> currentAliasNodePairs =
     709            0 :                             cfgMgr->getNode(ConfigurationManager::VERSION_ALIASES_TABLE_NAME)
     710            0 :                                 .getChildren();
     711            0 :                         std::set<std::string /* current aliases */> currentAliases;
     712              : 
     713            0 :                         __COUTV__(cfgMgr->getNode(ConfigurationManager::VERSION_ALIASES_TABLE_NAME)
     714            0 :                                       .getTableName());
     715            0 :                         __COUTV__(cfgMgr->getNode(ConfigurationManager::VERSION_ALIASES_TABLE_NAME)
     716            0 :                                       .getTableVersion());
     717              : 
     718            0 :                         __COUT__ << "Existing table aliases: " << currentAliasNodePairs.size()
     719            0 :                                  << __E__;
     720            0 :                         for(auto& groupPair : currentAliasNodePairs)
     721              :                         {
     722            0 :                                 __COUT__ << " ==> Current table alias "
     723            0 :                                          << groupPair.second.getNode("VersionAlias").getValueAsString()
     724            0 :                                          << ": "
     725            0 :                                          << groupPair.second.getNode("TableName").getValueAsString()
     726            0 :                                          << " ("
     727            0 :                                          << TableGroupKey(
     728            0 :                                                 groupPair.second.getNode("Version").getValueAsString())
     729            0 :                                          << ")" << __E__;
     730              : 
     731            0 :                                 currentAliases.emplace(
     732            0 :                                     groupPair.second.getNode("VersionAlias").getValueAsString());
     733              :                         }
     734              : 
     735              :                         std::string fullpath =
     736            0 :                             importBackbonePath + "/" +
     737            0 :                             ConfigurationManager::VERSION_ALIASES_TABLE_NAME + "_v" +
     738            0 :                             memberTableSet.at(ConfigurationManager::VERSION_ALIASES_TABLE_NAME)
     739            0 :                                 .str() +
     740            0 :                             ".json";
     741              : 
     742            0 :                         std::string json;
     743            0 :                         std::FILE*  fp = std::fopen(fullpath.c_str(), "rb");
     744            0 :                         if(!fp)
     745              :                         {
     746            0 :                                 __SS__ << "Could not open file at " << fullpath << ". Error: " << errno
     747            0 :                                        << " - " << strerror(errno) << __E__;
     748            0 :                                 __SS_THROW__;
     749            0 :                         }
     750            0 :                         std::fseek(fp, 0, SEEK_END);
     751            0 :                         json.resize(std::ftell(fp));
     752            0 :                         std::rewind(fp);
     753            0 :                         std::fread(&json[0], 1, json.size(), fp);
     754            0 :                         std::fclose(fp);
     755              : 
     756            0 :                         __COUTV__(json);
     757              : 
     758              :                         auto aliasTable =
     759            0 :                             cfgMgr->getTableByName(ConfigurationManager::VERSION_ALIASES_TABLE_NAME);
     760            0 :                         auto temporaryVersion = aliasTable->createTemporaryView();
     761            0 :                         auto aliasView        = aliasTable->getViewP(temporaryVersion);
     762              : 
     763            0 :                         aliasView->fillFromJSON(json);
     764            0 :                         aliasView->print();
     765              : 
     766            0 :                         auto aliasCol        = aliasView->findCol("VersionAlias");
     767            0 :                         auto tablepNameCol   = aliasView->findCol("TableName");
     768            0 :                         auto tableVersionCol = aliasView->findCol("Version");
     769              : 
     770            0 :                         __COUT__ << "Existing table aliases:" << __E__;
     771            0 :                         for(auto& currentAlias : currentAliases)
     772            0 :                                 __COUTV__(currentAlias);
     773              : 
     774            0 :                         __COUT__ << "Checking that table aliases to import are unique:" << __E__;
     775            0 :                         for(size_t row = 0; row < aliasView->getNumberOfRows(); ++row)
     776              :                         {
     777            0 :                                 std::string aliasName = aliasView->getValueAsString(row, aliasCol);
     778            0 :                                 __COUT__ << " ==> Table alias to import at row " << row << ": "
     779            0 :                                          << aliasName << __E__;
     780            0 :                                 if(currentAliases.find(prepend + aliasName) != currentAliases.end())
     781              :                                 {
     782            0 :                                         __SS__ << "The imported prepend + table alias of '" << prepend
     783              :                                                << "' + '" << aliasName
     784              :                                                << "' already exists as a table alias in the current database."
     785              :                                                << " Please modify the prepend string to make the imported "
     786            0 :                                                   "alias names unique."
     787            0 :                                                << __E__;
     788            0 :                                         __SS_THROW__;
     789            0 :                                 }
     790            0 :                                 importTableAliasMap[aliasName] =
     791            0 :                                     std::pair<std::string /*tableName*/, TableVersion /*origVersion*/>(
     792            0 :                                         aliasView->getValueAsString(row, tablepNameCol),
     793            0 :                                         aliasView->getValueAsString(row, tableVersionCol));
     794            0 :                         }
     795            0 :                         __COUT__ << "Verified table aliases to import are unique." << __E__;
     796            0 :                 }  //end verify table aliases are unique
     797              : 
     798            0 :         }  //end check import backbone group aliases for uniqueness
     799              : 
     800            0 :         __COUT__ << "Identified group aliases to import:" << std::endl;
     801            0 :         for(auto& groupAlias : importGroupAliasMap)
     802            0 :                 __COUT__ << "\t" << groupAlias.first << " ==> " << groupAlias.second.first << " ("
     803            0 :                          << groupAlias.second.second << ")" << std::endl;
     804            0 :         __COUT__ << "Identified table aliases to import:" << std::endl;
     805            0 :         for(auto& tableAlias : importTableAliasMap)
     806            0 :                 __COUT__ << "\t" << tableAlias.first << " ==> " << tableAlias.second.first << "-v"
     807            0 :                          << tableAlias.second.second << std::endl;
     808              :         // return;
     809              : 
     810              :         //Now...
     811              :         //      -- for each group to import
     812              :         //              - for each table in group to import
     813              :         //                      . load json into table view, check that table view is unique
     814              :         //                      . if not unique update member map version
     815              :         //              - save (modified) member map as new group
     816              :         //              - report to user import alias --> import group name/key --> new group key
     817              :         //
     818            0 :         bool anyNewGroupSaved = false;
     819            0 :         __COUT__ << "Importing member tables..." << __E__;
     820            0 :         for(auto& group : importGroupMap)
     821              :         {
     822            0 :                 __COUT__ << " ==> Group to import: " << group.first.first << " ("
     823            0 :                          << group.first.second << ")" << std::endl;
     824              : 
     825              :                 std::string importGroupPath =
     826            0 :                     importPath + "/" + group.first.first + "_" + group.first.second.str();
     827            0 :                 __COUTV__(importGroupPath);
     828              : 
     829              :                 std::map<std::string /* tableName */, TableVersion /* tableVersion */>
     830            0 :                     memberTableSet;
     831              :                 {  //get member table file names
     832              :                         DIR*           dp;
     833              :                         struct dirent* dirp;
     834            0 :                         if((dp = opendir(importGroupPath.c_str())) == 0)
     835              :                         {
     836            0 :                                 __COUT_ERR__ << "ERROR:(" << errno
     837            0 :                                              << ").  Can't open directory: " << importGroupPath
     838            0 :                                              << std::endl;
     839            0 :                                 exit(0);
     840              :                         }
     841              : 
     842            0 :                         const unsigned char isDir = 0x4;
     843            0 :                         while((dirp = readdir(dp)) != 0)
     844            0 :                                 if(dirp->d_type != isDir && strlen(dirp->d_name) > 5 &&
     845            0 :                                    dirp->d_name[strlen(dirp->d_name) - 5] == '.' &&
     846            0 :                                    dirp->d_name[strlen(dirp->d_name) - 4] == 'j' &&
     847            0 :                                    dirp->d_name[strlen(dirp->d_name) - 3] == 's' &&
     848            0 :                                    dirp->d_name[strlen(dirp->d_name) - 2] == 'o' &&
     849            0 :                                    dirp->d_name[strlen(dirp->d_name) - 1] ==
     850              :                                        'n')  //if not directory w/extension .json
     851              :                                 {
     852              :                                         // __COUT__ << dirp->d_name << std::endl;
     853              : 
     854            0 :                                         auto split = StringMacros::getVectorFromString(dirp->d_name, {'_'});
     855              : 
     856            0 :                                         if(split.size() != 2)
     857            0 :                                                 continue;
     858              : 
     859            0 :                                         memberTableSet.insert(std::pair<std::string, TableVersion>(
     860            0 :                                             split[0], split[1].substr(1, split[1].size() - 6)));
     861            0 :                                 }  //end found group directory handling
     862              : 
     863            0 :                         closedir(dp);
     864              :                 }  //end load of group member table names/versions from directory
     865              : 
     866            0 :                 std::map<std::string, TableVersion> groupMembers;
     867            0 :                 for(auto& member : memberTableSet)
     868              :                 {
     869            0 :                         __COUT__ << "     ==> Member table to import: " << member.first << " v"
     870            0 :                                  << member.second << std::endl;
     871              : 
     872            0 :                         std::string fullpath = importGroupPath + "/" + member.first + "_v" +
     873            0 :                                                member.second.str() + ".json";
     874              : 
     875            0 :                         std::string json;
     876            0 :                         std::FILE*  fp = std::fopen(fullpath.c_str(), "rb");
     877            0 :                         if(!fp)
     878              :                         {
     879            0 :                                 __SS__ << "Could not open file at " << fullpath << ". Error: " << errno
     880            0 :                                        << " - " << strerror(errno) << __E__;
     881            0 :                                 __SS_THROW__;
     882            0 :                         }
     883            0 :                         std::fseek(fp, 0, SEEK_END);
     884            0 :                         json.resize(std::ftell(fp));
     885            0 :                         std::rewind(fp);
     886            0 :                         std::fread(&json[0], 1, json.size(), fp);
     887            0 :                         std::fclose(fp);
     888              : 
     889            0 :                         __COUTV__(json);
     890              : 
     891            0 :                         auto memberTable = member.first == TableBase::GROUP_METADATA_TABLE_NAME
     892            0 :                                                ? cfgMgr->getMetadataTable()
     893            0 :                                                : cfgMgr->getTableByName(member.first);
     894              : 
     895            0 :                         TableVersion newAssignedVersion;
     896            0 :                         if(member.first == TableBase::GROUP_METADATA_TABLE_NAME)
     897              :                         {
     898              :                                 //only one view ever for meta data table
     899            0 :                                 auto tableView = memberTable->getViewP();
     900              : 
     901            0 :                                 tableView->print();
     902              :                                 //clear all data from table (fill does not clear)
     903            0 :                                 while(tableView->getNumberOfRows() > 0)
     904            0 :                                         tableView->deleteRow(0);
     905            0 :                                 tableView->print();
     906              : 
     907            0 :                                 tableView->fillFromJSON(json);
     908            0 :                                 tableView->print();
     909              : 
     910              :                                 // set metadata table version to first available persistent version
     911            0 :                                 newAssignedVersion = TableVersion::getNextVersion(
     912            0 :                                     theInterface_->findLatestVersion(memberTable));
     913            0 :                                 __COUTV__(newAssignedVersion);
     914            0 :                                 tableView->setVersion(newAssignedVersion);
     915            0 :                                 memberTable->getViewP()->print();
     916              : 
     917              :                                 // save table, and retry on save collision
     918            0 :                                 uint16_t retries = 0;
     919              :                                 while(1)
     920              :                                 {
     921              :                                         try
     922              :                                         {
     923            0 :                                                 theInterface_->saveActiveVersion(memberTable);
     924              :                                         }
     925            0 :                                         catch(const std::runtime_error& e)
     926              :                                         {
     927            0 :                                                 __COUT__ << "Caught runtime_error exception during table save: "
     928            0 :                                                          << e.what() << __E__;
     929            0 :                                                 if(std::string(e.what()).find("there was a collision") !=
     930              :                                                    std::string::npos)
     931              :                                                 {
     932            0 :                                                         __COUT_WARN__
     933            0 :                                                             << "There was a collision saving the new table "
     934            0 :                                                             << *tableView << "(" << newAssignedVersion
     935            0 :                                                             << "), trying incremented table version... retries="
     936            0 :                                                             << retries << __E__;
     937            0 :                                                         if(++retries > 3)  //give up
     938            0 :                                                                 throw;
     939            0 :                                                         newAssignedVersion = TableVersion::getNextVersion(
     940            0 :                                                             newAssignedVersion);  //increment table version
     941            0 :                                                         tableView->setVersion(newAssignedVersion);
     942            0 :                                                         __COUT__ << "New version for table: " << *tableView
     943            0 :                                                                  << " found as " << newAssignedVersion << __E__;
     944            0 :                                                         continue;
     945            0 :                                                 }
     946              :                                                 else
     947            0 :                                                         throw;
     948            0 :                                         }
     949              : 
     950            0 :                                         __COUT__ << "Created table: " << *tableView << "-v"
     951            0 :                                                  << newAssignedVersion << __E__;
     952            0 :                                         break;
     953            0 :                                 }  //end collission retry loop
     954              : 
     955            0 :                                 __COUTV__(memberTable->getViewVersion());
     956              :                         }
     957              :                         else  //else normal member table
     958              :                         {
     959            0 :                                 auto temporaryVersion = memberTable->createTemporaryView();
     960            0 :                                 auto tableView        = memberTable->getViewP(temporaryVersion);
     961              : 
     962            0 :                                 tableView->fillFromJSON(json);
     963            0 :                                 tableView->print();
     964              : 
     965              :                                 bool foundEquivalent;
     966              :                                 newAssignedVersion =
     967            0 :                                     cfgMgr->saveModifiedVersion(member.first,
     968              :                                                                 temporaryVersion,
     969              :                                                                 false /*makeTemporary*/,
     970              :                                                                 memberTable,
     971              :                                                                 temporaryVersion,
     972              :                                                                 false /*ignoreDuplicates*/,
     973              :                                                                 true /*lookForEquivalent*/,
     974            0 :                                                                 &foundEquivalent);
     975            0 :                                 if(foundEquivalent)
     976            0 :                                         __COUT__ << "Found equivalent version: " << newAssignedVersion
     977            0 :                                                  << __E__;
     978            0 :                         }
     979            0 :                         __COUTV__(newAssignedVersion);
     980              : 
     981              :                         //assembly importTableMap at this point
     982            0 :                         importTableMap[std::make_pair(member.first, member.second)] =
     983            0 :                             newAssignedVersion;
     984            0 :                         groupMembers[member.first] = newAssignedVersion;
     985              :                         // return;
     986            0 :                 }  //end member table import and find loop
     987              : 
     988            0 :                 __COUT__ << "Tables imported so far: " << importTableMap.size() << std::endl;
     989            0 :                 for(auto& table : importTableMap)
     990            0 :                         __COUT__ << " ==> Member table imported: " << table.first.first << " v"
     991            0 :                                  << table.first.second << " ==> v" << table.second << std::endl;
     992              : 
     993            0 :                 __COUT__ << "Saving group '" << group.first.first
     994            0 :                          << "' members: " << groupMembers.size() << std::endl;
     995              : 
     996            0 :                 std::map<std::string, TableVersion> groupMembersWithoutMeta;
     997            0 :                 for(auto& table : groupMembers)
     998              :                 {
     999            0 :                         __COUT__ << " ==> Saving group w/Member table: " << table.first << " v"
    1000            0 :                                  << table.second << std::endl;
    1001              : 
    1002            0 :                         if(table.first != TableBase::GROUP_METADATA_TABLE_NAME)
    1003            0 :                                 groupMembersWithoutMeta[table.first] = table.second;
    1004              :                 }
    1005              : 
    1006              :                 {  //check if group is a duplicate
    1007            0 :                         __COUT__ << "Checking for duplicate groups..." << __E__;
    1008              :                         try
    1009              :                         {
    1010              :                                 TableGroupKey foundKey = cfgMgr->findTableGroup(
    1011            0 :                                     group.first.first,
    1012            0 :                                     groupMembersWithoutMeta);  //, memberTableAliases); std::map<std::string /*name*/, std::string /*alias*/>    memberTableAliases
    1013              : 
    1014            0 :                                 if(!foundKey.isInvalid())
    1015              :                                 {
    1016            0 :                                         __COUT_WARN__ << "Found equivalent group key (" << foundKey
    1017            0 :                                                       << ") for " << group.first.first << ". Skipping import!"
    1018            0 :                                                       << __E__;
    1019              :                                         //update key import transformation map
    1020            0 :                                         importGroupMap.at(
    1021            0 :                                             std::make_pair(group.first.first, group.first.second)) = foundKey;
    1022            0 :                                         continue;
    1023            0 :                                 }
    1024              : 
    1025            0 :                                 __COUT__ << "Check for duplicate groups complete." << __E__;
    1026            0 :                         }
    1027            0 :                         catch(...)
    1028              :                         {
    1029            0 :                                 __COUT_WARN__
    1030              :                                     << "Ignoring errors looking for duplicate groups! Proceeding "
    1031            0 :                                        "with new group creation."
    1032            0 :                                     << __E__;
    1033            0 :                         }
    1034              :                 }  //end check if group is a duplicate
    1035              :                 // return;
    1036              : 
    1037              :                 TableGroupKey newKey = TableGroupKey::getNextKey(
    1038            0 :                     theInterface_->findLatestGroupKey(group.first.first));
    1039            0 :                 __COUT__ << "New Key for group: " << group.first.first << " found as " << newKey
    1040            0 :                          << __E__;
    1041              : 
    1042              :                 // save group, and retry on save collision
    1043            0 :                 uint16_t retries = 0;
    1044              :                 while(1)
    1045              :                 {
    1046              :                         try
    1047              :                         {
    1048            0 :                                 theInterface_->saveTableGroup(
    1049              :                                     groupMembers,
    1050            0 :                                     TableGroupKey::getFullGroupString(group.first.first, newKey));
    1051              :                         }
    1052            0 :                         catch(const std::runtime_error& e)
    1053              :                         {
    1054            0 :                                 __COUT__ << "Caught runtime_error exception during group save: "
    1055            0 :                                          << e.what() << __E__;
    1056            0 :                                 if(std::string(e.what()).find("there was a collision") !=
    1057              :                                    std::string::npos)
    1058              :                                 {
    1059            0 :                                         __COUT_WARN__
    1060            0 :                                             << "There was a collision saving the new group "
    1061            0 :                                             << group.first.first << "(" << newKey
    1062            0 :                                             << "), trying incremented group key... retries=" << retries
    1063            0 :                                             << __E__;
    1064            0 :                                         if(++retries > 3)  //give up
    1065            0 :                                                 throw;
    1066            0 :                                         newKey = TableGroupKey::getNextKey(newKey);  //increment group key
    1067            0 :                                         __COUT__ << "New Key for group: " << group.first.first << " found as "
    1068            0 :                                                  << newKey << __E__;
    1069            0 :                                         continue;
    1070            0 :                                 }
    1071              :                                 else
    1072            0 :                                         throw;
    1073            0 :                         }
    1074            0 :                         __COUT__ << "Created table group: " << group.first.first << "(" << newKey
    1075            0 :                                  << ")" << __E__;
    1076            0 :                         break;
    1077            0 :                 }  //end collission retry loop
    1078              : 
    1079            0 :                 anyNewGroupSaved = true;
    1080              : 
    1081              :                 //update key import transformation map
    1082            0 :                 importGroupMap.at(std::make_pair(group.first.first, group.first.second)) = newKey;
    1083              :                 // return;
    1084            0 :         }  //end group import loop
    1085              : 
    1086            0 :         if(!forceBackboneSave && !anyNewGroupSaved)
    1087              :         {
    1088            0 :                 __SS__ << "All groups to import already exist in current db! Was the wrong db "
    1089            0 :                           "selected from which to import?"
    1090            0 :                        << __E__;
    1091            0 :                 __SS_THROW__;
    1092            0 :         }
    1093              : 
    1094              :         //              - report to user import alias --> import group name/key --> new group key
    1095            0 :         __COUT__ << "Tables imported summary: " << importTableMap.size() << std::endl;
    1096            0 :         for(auto& table : importTableMap)
    1097            0 :                 __COUT__ << " ==> Table imported: " << table.first.first << " v"
    1098            0 :                          << table.first.second << " ==> v" << table.second << std::endl;
    1099              : 
    1100            0 :         __COUT__ << "Groups imported summary: " << importGroupMap.size() << std::endl;
    1101            0 :         for(auto& group : importGroupMap)
    1102            0 :                 __COUT__ << " ==> Group imported: " << group.first.first << " ("
    1103            0 :                          << group.first.second << ") ==> (" << group.second << ")" << std::endl;
    1104              : 
    1105              :         // return;
    1106              : 
    1107              :         // Done making groups, now...
    1108              :         //      -- insert new aliases for imported groups/tables in current active backbone
    1109              :         //              - should be basename+alias connection to (hop through maps) new groupName & groupKey
    1110              :         {  //insert new aliases for imported groups in current active backbone
    1111              :                 auto table =
    1112            0 :                     cfgMgr->getTableByName(ConfigurationManager::GROUP_ALIASES_TABLE_NAME);
    1113            0 :                 __COUTV__(table->getTableName());
    1114            0 :                 __COUTV__(table->getViewVersion());
    1115              : 
    1116              :         }  //end insert new aliases for imported groups in current active backbone
    1117              :         {  //insert new aliases for imported tables in current active backbone
    1118              :                 auto table =
    1119            0 :                     cfgMgr->getTableByName(ConfigurationManager::VERSION_ALIASES_TABLE_NAME);
    1120            0 :                 __COUTV__(table->getTableName());
    1121            0 :                 __COUTV__(table->getViewVersion());
    1122              : 
    1123              :         }  //end insert new aliases for imported tables in current active backbone
    1124              : 
    1125            0 :         std::map<std::string, TableVersion> backboneMemberMap;
    1126              :         {
    1127            0 :                 std::string accumulatedWarnings, accumulateErrors;
    1128            0 :                 cfgMgr->restoreActiveTableGroups(
    1129              :                     false /*throwErrors*/,
    1130              :                     "" /*pathToActiveGroupsFile*/,
    1131              :                     ConfigurationManager::LoadGroupType::
    1132              :                         ALL_TYPES,  //must do ALL_TYPES to not affect activeTablesGroup file
    1133              :                     &accumulatedWarnings);
    1134              : 
    1135              :                 activeBackboneGroupName =
    1136            0 :                     cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::BACKBONE_TYPE);
    1137            0 :                 cfgMgr->loadTableGroup(
    1138              :                     activeBackboneGroupName,
    1139            0 :                     cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::BACKBONE_TYPE),
    1140              :                     true,
    1141              :                     &backboneMemberMap,
    1142              :                     0,
    1143              :                     &accumulateErrors);
    1144            0 :                 __COUT__ << "Done re-loading active backbone: " << activeBackboneGroupName << " ("
    1145            0 :                          << cfgMgr->getActiveGroupKey(
    1146            0 :                                 ConfigurationManager::GroupType::BACKBONE_TYPE)
    1147            0 :                          << ")" << std::endl;
    1148            0 :         }
    1149              : 
    1150            0 :         __COUT__ << "Modifying the active Backbone table to reflect new table versions and "
    1151            0 :                     "group keys."
    1152            0 :                  << std::endl;
    1153              : 
    1154              :         // Done making groups, now...
    1155              :         //      -- insert new aliases for imported groups/tables in current active backbone
    1156              :         //              - should be basename+alias connection to (hop through maps) new groupName & groupKey
    1157              :         {  //insert new aliases for imported groups in current active backbone
    1158              :                 auto table =
    1159            0 :                     cfgMgr->getTableByName(ConfigurationManager::GROUP_ALIASES_TABLE_NAME);
    1160            0 :                 __COUTV__(table->getTableName());
    1161            0 :                 __COUTV__(table->getViewVersion());
    1162              : 
    1163            0 :                 auto cfgView = table->getViewP();
    1164              : 
    1165            0 :                 unsigned int col0 = cfgView->findCol("GroupKeyAlias");
    1166            0 :                 unsigned int col1 = cfgView->findCol("GroupName");
    1167            0 :                 unsigned int col2 = cfgView->findCol("GroupKey");
    1168              :                 unsigned int row;
    1169              : 
    1170            0 :                 cfgView->print();
    1171              : 
    1172            0 :                 TableVersion duplicateVersion;
    1173              : 
    1174              :                 //      -- insert new aliases for imported groups
    1175              :                 //              - should be basename+alias connection to (hop through maps) new
    1176              :                 // groupName & groupKey
    1177            0 :                 for(auto& aliasPair : importGroupAliasMap)
    1178              :                 {
    1179            0 :                         __COUT__ << "\t" << aliasPair.first << " ==> " << aliasPair.second.first
    1180            0 :                                  << "-v" << aliasPair.second.second << std::endl;
    1181              : 
    1182            0 :                         auto groupIt = importGroupMap.find(std::pair<std::string, TableGroupKey>(
    1183            0 :                             aliasPair.second.first, aliasPair.second.second));
    1184              : 
    1185            0 :                         if(groupIt == importGroupMap.end())
    1186              :                         {
    1187            0 :                                 __COUT__ << "Error! Could not find the new entry for the original group "
    1188            0 :                                          << aliasPair.second.first << "(" << aliasPair.second.second
    1189            0 :                                          << ")" << __E__;
    1190            0 :                                 continue;
    1191            0 :                         }
    1192              :                         row =
    1193            0 :                             cfgView->addRow(prepend + "import_aliases", true /*incrementUniqueData*/);
    1194            0 :                         cfgView->setValue(prepend + aliasPair.first, row, col0);
    1195            0 :                         cfgView->setValue(aliasPair.second.first, row, col1);
    1196            0 :                         cfgView->setValue(groupIt->second.toString(), row, col2);
    1197              :                 }  // end group alias edit
    1198              : 
    1199            0 :                 if(!importGroupAliasMap.size())
    1200              :                         duplicateVersion =
    1201            0 :                             table->getViewVersion();  //mark duplicate as self if nothing to add
    1202              : 
    1203            0 :                 cfgView->print();
    1204              : 
    1205              :                 TableVersion originalVersion =
    1206              :                     table
    1207            0 :                         ->getViewVersion();  //save version because cache fill will change active version
    1208            0 :                 if(duplicateVersion.isInvalid())
    1209              :                 {
    1210            0 :                         auto tableName = ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
    1211            0 :                         __COUT__ << "Checking for duplicate '" << tableName << "' tables..." << __E__;
    1212              : 
    1213              :                         {
    1214              :                                 //"DEEP" checking
    1215              :                                 //      load into cache 'recent' versions for this table
    1216              :                                 //              'recent' := those already in cache, plus highest version numbers not in cache
    1217              :                                 const std::map<std::string, TableInfo>& allTableInfo =
    1218            0 :                                     cfgMgr->getAllTableInfo();  // do not refresh
    1219              : 
    1220              :                                 auto versionReverseIterator =
    1221            0 :                                     allTableInfo.at(tableName)
    1222            0 :                                         .versions_.rbegin();  // get reverse iterator
    1223            0 :                                 __COUT__ << "Filling up '" << tableName << "' cache from "
    1224            0 :                                          << table->getNumberOfStoredViews() << " to max count of "
    1225            0 :                                          << table->MAX_VIEWS_IN_CACHE << __E__;
    1226            0 :                                 for(;
    1227            0 :                                     table->getNumberOfStoredViews() < table->MAX_VIEWS_IN_CACHE &&
    1228            0 :                                     versionReverseIterator != allTableInfo.at(tableName).versions_.rend();
    1229            0 :                                     ++versionReverseIterator)
    1230              :                                 {
    1231            0 :                                         __COUTT__ << "'" << tableName << "' versions in reverse order "
    1232            0 :                                                   << *versionReverseIterator << __E__;
    1233              :                                         try
    1234              :                                         {
    1235            0 :                                                 cfgMgr->getVersionedTableByName(
    1236              :                                                     tableName,
    1237            0 :                                                     *versionReverseIterator);  // load to cache
    1238              :                                         }
    1239            0 :                                         catch(const std::runtime_error& e)
    1240              :                                         {
    1241              :                                                 // ignore error
    1242            0 :                                                 __COUTT__ << "'" << tableName << "' version failed to load: "
    1243            0 :                                                           << *versionReverseIterator << __E__;
    1244            0 :                                         }
    1245              :                                 }
    1246              :                         }
    1247              : 
    1248            0 :                         __COUT__ << "Checking '" << tableName << "' for duplicate..." << __E__;
    1249              :                         duplicateVersion =
    1250            0 :                             table->checkForDuplicate(originalVersion,
    1251            0 :                                                      TableVersion());  // then all versions in search
    1252              : 
    1253            0 :                 }  //end check duplicate
    1254              : 
    1255              :                 //return the original version to active
    1256            0 :                 table->setActiveView(originalVersion);
    1257              : 
    1258            0 :                 if(!duplicateVersion.isInvalid())
    1259              :                 {
    1260              :                         // found an equivalent!
    1261            0 :                         __COUT__ << "Equivalent " << ConfigurationManager::GROUP_ALIASES_TABLE_NAME
    1262            0 :                                  << " table found in version v" << duplicateVersion << __E__;
    1263            0 :                         backboneMemberMap.at(ConfigurationManager::GROUP_ALIASES_TABLE_NAME) =
    1264            0 :                             duplicateVersion;
    1265              :                 }
    1266              :                 else
    1267              :                 {
    1268              :                         auto newVersion =
    1269            0 :                             TableVersion::getNextVersion(theInterface_->findLatestVersion(table));
    1270            0 :                         __COUTV__(newVersion);
    1271            0 :                         cfgView->setVersion(newVersion);
    1272              : 
    1273              :                         // save table, and retry on save collision
    1274            0 :                         uint16_t retries = 0;
    1275              :                         while(1)
    1276              :                         {
    1277              :                                 try
    1278              :                                 {
    1279            0 :                                         theInterface_->saveActiveVersion(table);
    1280              :                                 }
    1281            0 :                                 catch(const std::runtime_error& e)
    1282              :                                 {
    1283            0 :                                         __COUT__ << "Caught runtime_error exception during table save."
    1284            0 :                                                  << __E__;
    1285            0 :                                         if(std::string(e.what()).find("there was a collision") !=
    1286              :                                            std::string::npos)
    1287              :                                         {
    1288            0 :                                                 __COUT_WARN__ << "There was a collision saving the new table "
    1289            0 :                                                               << *cfgView << "(" << newVersion
    1290            0 :                                                               << "), trying incremented table version... retries="
    1291            0 :                                                               << retries << __E__;
    1292            0 :                                                 if(++retries > 3)  //give up
    1293            0 :                                                         throw;
    1294            0 :                                                 newVersion = TableVersion::getNextVersion(
    1295            0 :                                                     newVersion);  //increment table version
    1296            0 :                                                 cfgView->setVersion(newVersion);
    1297            0 :                                                 __COUT__ << "New version for table: " << *cfgView << " found as "
    1298            0 :                                                          << newVersion << __E__;
    1299            0 :                                                 continue;
    1300            0 :                                         }
    1301              :                                         else
    1302            0 :                                                 throw;
    1303            0 :                                 }
    1304              : 
    1305            0 :                                 __COUT__ << "Created table: " << *cfgView << "-v" << newVersion << __E__;
    1306            0 :                                 break;
    1307            0 :                         }  //end collission retry loop
    1308              : 
    1309            0 :                         __COUT__ << "Updated backbone table "
    1310            0 :                                  << ConfigurationManager::GROUP_ALIASES_TABLE_NAME << " from v"
    1311            0 :                                  << backboneMemberMap.at(
    1312            0 :                                         ConfigurationManager::GROUP_ALIASES_TABLE_NAME)
    1313            0 :                                  << " to v" << newVersion << std::endl;
    1314            0 :                         backboneMemberMap.at(ConfigurationManager::GROUP_ALIASES_TABLE_NAME) =
    1315            0 :                             newVersion;  // change version in the member map
    1316            0 :                 }
    1317              : 
    1318            0 :         }  //end insert new aliases for imported groups in current active backbone
    1319              :         {  //insert new aliases for imported tables in current active backbone
    1320              :                 auto table =
    1321            0 :                     cfgMgr->getTableByName(ConfigurationManager::VERSION_ALIASES_TABLE_NAME);
    1322            0 :                 __COUTV__(table->getTableName());
    1323            0 :                 __COUTV__(table->getViewVersion());
    1324              : 
    1325            0 :                 auto         cfgView = table->getViewP();
    1326            0 :                 unsigned int col0    = cfgView->findCol("VersionAlias");
    1327            0 :                 unsigned int col1    = cfgView->findCol("TableName");
    1328            0 :                 unsigned int col2    = cfgView->findCol("Version");
    1329            0 :                 __COUTV__(table->getViewVersion());
    1330              : 
    1331              :                 unsigned int row;
    1332              : 
    1333            0 :                 cfgView->print();
    1334              : 
    1335            0 :                 TableVersion duplicateVersion;
    1336              : 
    1337              :                 //      -- insert new aliases for imported tables
    1338              :                 //              - should be basename+alias connection to (hop through maps) new
    1339              :                 // tableName & tableVersion
    1340            0 :                 for(auto& aliasPair : importTableAliasMap)
    1341              :                 {
    1342            0 :                         __COUT__ << "\t" << aliasPair.first << " ==> " << aliasPair.second.first
    1343            0 :                                  << "-" << aliasPair.second.second << std::endl;
    1344              : 
    1345            0 :                         auto tableIt = importTableMap.find(std::pair<std::string, TableVersion>(
    1346            0 :                             aliasPair.second.first, aliasPair.second.second));
    1347              : 
    1348            0 :                         if(tableIt == importTableMap.end())
    1349              :                         {
    1350            0 :                                 __COUT__ << "Error! Could not find the new entry for the original table "
    1351            0 :                                          << aliasPair.second.first << "(" << aliasPair.second.second
    1352            0 :                                          << ")" << __E__;
    1353            0 :                                 continue;
    1354            0 :                         }
    1355              :                         row =
    1356            0 :                             cfgView->addRow(prepend + "import_aliases", true /*incrementUniqueData*/);
    1357            0 :                         cfgView->setValue(prepend + aliasPair.first, row, col0);
    1358            0 :                         cfgView->setValue(aliasPair.second.first, row, col1);
    1359            0 :                         cfgView->setValue(tableIt->second.toString(), row, col2);
    1360              :                 }  // end group alias edit
    1361            0 :                 __COUTV__(table->getViewVersion());
    1362              : 
    1363            0 :                 if(!importTableAliasMap.size())
    1364              :                         duplicateVersion =
    1365            0 :                             table->getViewVersion();  //mark duplicate as self if nothing to add
    1366              : 
    1367            0 :                 __COUTV__(table->getViewVersion());
    1368            0 :                 cfgView->print();
    1369            0 :                 __COUTV__(table->getViewVersion());
    1370              : 
    1371              :                 TableVersion originalVersion =
    1372              :                     table
    1373            0 :                         ->getViewVersion();  //save version because cache fill will change active version
    1374            0 :                 if(duplicateVersion.isInvalid())
    1375              :                 {
    1376            0 :                         auto tableName = ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
    1377            0 :                         __COUT__ << "Checking for duplicate '" << tableName << "' tables..." << __E__;
    1378              : 
    1379              :                         {
    1380              :                                 //"DEEP" checking
    1381              :                                 //      load into cache 'recent' versions for this table
    1382              :                                 //              'recent' := those already in cache, plus highest version numbers not in cache
    1383              :                                 const std::map<std::string, TableInfo>& allTableInfo =
    1384            0 :                                     cfgMgr->getAllTableInfo();  // do not refresh
    1385            0 :                                 __COUTV__(table->getViewVersion());
    1386              : 
    1387              :                                 auto versionReverseIterator =
    1388            0 :                                     allTableInfo.at(tableName)
    1389            0 :                                         .versions_.rbegin();  // get reverse iterator
    1390            0 :                                 __COUT__ << "Filling up '" << tableName << "' cache from "
    1391            0 :                                          << table->getNumberOfStoredViews() << " to max count of "
    1392            0 :                                          << table->MAX_VIEWS_IN_CACHE << __E__;
    1393            0 :                                 for(;
    1394            0 :                                     table->getNumberOfStoredViews() < table->MAX_VIEWS_IN_CACHE &&
    1395            0 :                                     versionReverseIterator != allTableInfo.at(tableName).versions_.rend();
    1396            0 :                                     ++versionReverseIterator)
    1397              :                                 {
    1398            0 :                                         __COUTT__ << "'" << tableName << "' versions in reverse order "
    1399            0 :                                                   << *versionReverseIterator << __E__;
    1400              :                                         try
    1401              :                                         {
    1402            0 :                                                 cfgMgr->getVersionedTableByName(
    1403              :                                                     tableName,
    1404            0 :                                                     *versionReverseIterator);  // load to cache
    1405              :                                         }
    1406            0 :                                         catch(const std::runtime_error& e)
    1407              :                                         {
    1408              :                                                 // ignore error
    1409            0 :                                                 __COUTT__ << "'" << tableName << "' version failed to load: "
    1410            0 :                                                           << *versionReverseIterator << __E__;
    1411            0 :                                         }
    1412            0 :                                         __COUTV__(table->getViewVersion());
    1413              :                                 }
    1414              :                         }
    1415              : 
    1416            0 :                         __COUT__ << "Checking '" << tableName << "' for duplicate..." << __E__;
    1417              :                         duplicateVersion =
    1418            0 :                             table->checkForDuplicate(originalVersion,
    1419            0 :                                                      TableVersion());  // then all versions in search
    1420              : 
    1421            0 :                         __COUTV__(table->getViewVersion());
    1422            0 :                 }  //end check duplicate
    1423              : 
    1424              :                 //return the original version to active
    1425            0 :                 table->setActiveView(originalVersion);
    1426              : 
    1427            0 :                 if(!duplicateVersion.isInvalid())
    1428              :                 {
    1429              :                         // found an equivalent!
    1430            0 :                         __COUT__ << "Equivalent " << ConfigurationManager::VERSION_ALIASES_TABLE_NAME
    1431            0 :                                  << " table found in version v" << duplicateVersion << __E__;
    1432            0 :                         backboneMemberMap.at(ConfigurationManager::VERSION_ALIASES_TABLE_NAME) =
    1433            0 :                             duplicateVersion;  // change version in the member map
    1434              :                 }
    1435              :                 else
    1436              :                 {
    1437              :                         auto newVersion =
    1438            0 :                             TableVersion::getNextVersion(theInterface_->findLatestVersion(table));
    1439            0 :                         cfgView->setVersion(newVersion);
    1440              :                         // table->setActiveView(newVersion);
    1441              : 
    1442              :                         // save table, and retry on save collision
    1443            0 :                         uint16_t retries = 0;
    1444              :                         while(1)
    1445              :                         {
    1446              :                                 try
    1447              :                                 {
    1448            0 :                                         theInterface_->saveActiveVersion(table);
    1449              :                                 }
    1450            0 :                                 catch(const std::runtime_error& e)
    1451              :                                 {
    1452            0 :                                         __COUT__ << "Caught runtime_error exception during table save."
    1453            0 :                                                  << __E__;
    1454            0 :                                         if(std::string(e.what()).find("there was a collision") !=
    1455              :                                            std::string::npos)
    1456              :                                         {
    1457            0 :                                                 __COUT_WARN__ << "There was a collision saving the new table "
    1458            0 :                                                               << *cfgView << "(" << newVersion
    1459            0 :                                                               << "), trying incremented table version... retries="
    1460            0 :                                                               << retries << __E__;
    1461            0 :                                                 if(++retries > 3)  //give up
    1462            0 :                                                         throw;
    1463            0 :                                                 newVersion = TableVersion::getNextVersion(
    1464            0 :                                                     newVersion);  //increment table version
    1465            0 :                                                 cfgView->setVersion(newVersion);
    1466            0 :                                                 __COUT__ << "New version for table: " << *cfgView << " found as "
    1467            0 :                                                          << newVersion << __E__;
    1468            0 :                                                 continue;
    1469            0 :                                         }
    1470              :                                         else
    1471            0 :                                                 throw;
    1472            0 :                                 }
    1473              : 
    1474            0 :                                 __COUT__ << "Created table: " << *cfgView << "-v" << newVersion << __E__;
    1475            0 :                                 break;
    1476            0 :                         }  //end collission retry loop
    1477              : 
    1478            0 :                         __COUT__ << "Updated backbone table "
    1479            0 :                                  << ConfigurationManager::VERSION_ALIASES_TABLE_NAME << " from v"
    1480            0 :                                  << backboneMemberMap.at(
    1481            0 :                                         ConfigurationManager::VERSION_ALIASES_TABLE_NAME)
    1482            0 :                                  << " to v" << newVersion << std::endl;
    1483            0 :                         backboneMemberMap.at(ConfigurationManager::VERSION_ALIASES_TABLE_NAME) =
    1484            0 :                             newVersion;  // change version in the member map
    1485            0 :                 }
    1486              : 
    1487            0 :         }  //end insert new aliases for imported tables in current active backbone
    1488              : 
    1489            0 :         __COUT_INFO__ << "Done inserting new aliases in active Backbone." << __E__;
    1490              : 
    1491              :         // return;
    1492              : 
    1493              :         //      -- save new backbone tables and save new backbone group, then activate
    1494              :         {
    1495            0 :                 __COUT__ << "Backbone member map to create:" << std::endl;
    1496            0 :                 for(auto& member : backboneMemberMap)
    1497            0 :                         __COUT__ << " ==> Member to create: " << member.first << "-v" << member.second
    1498            0 :                                  << std::endl;
    1499              : 
    1500            0 :                 bool foundExistingEmptyBackbone = false;
    1501              :                 {  //check if group is a duplicate
    1502            0 :                         __COUT__ << "Checking for duplicate backbone groups..." << __E__;
    1503              :                         try
    1504              :                         {
    1505              :                                 TableGroupKey foundKey = cfgMgr->findTableGroup(
    1506              :                                     activeBackboneGroupName,
    1507            0 :                                     backboneMemberMap);  //, memberTableAliases); std::map<std::string /*name*/, std::string /*alias*/>    memberTableAliases
    1508              : 
    1509            0 :                                 if(!foundKey.isInvalid())
    1510              :                                 {
    1511            0 :                                         __COUT_WARN__ << "Found equivalent empty backbone group key ("
    1512            0 :                                                       << foundKey << ") for " << activeBackboneGroupName
    1513            0 :                                                       << ". Skipping creation and activating existing key!"
    1514            0 :                                                       << __E__;
    1515            0 :                                         foundExistingEmptyBackbone = true;
    1516              : 
    1517              :                                         //      -- backup the file ConfigurationManager::ACTIVE_GROUPS_FILENAME with time
    1518              :                                         std::string renameFile =
    1519            0 :                                             ConfigurationManager::ACTIVE_GROUPS_FILENAME + "." + nowTime;
    1520            0 :                                         rename(ConfigurationManager::ACTIVE_GROUPS_FILENAME.c_str(),
    1521              :                                                renameFile.c_str());
    1522              : 
    1523            0 :                                         __COUT__ << "Backing up '"
    1524            0 :                                                  << ConfigurationManager::ACTIVE_GROUPS_FILENAME
    1525            0 :                                                  << "' to ... '" << renameFile << "'" << std::endl;
    1526              : 
    1527              :                                         //      -- activate the existing empty backbone group
    1528            0 :                                         cfgMgr->activateTableGroup(
    1529              :                                             activeBackboneGroupName,
    1530              :                                             foundKey);  // and write to active group file
    1531            0 :                                 }
    1532              : 
    1533            0 :                                 __COUT__ << "Check for existing backbone duplicate groups complete."
    1534            0 :                                          << __E__;
    1535            0 :                         }
    1536            0 :                         catch(...)
    1537              :                         {
    1538            0 :                                 __COUT_WARN__ << "Ignoring errors looking for existing backbone "
    1539              :                                                  "duplicate groups! Proceeding "
    1540            0 :                                                  "with new group creation."
    1541            0 :                                               << __E__;
    1542            0 :                         }
    1543              :                 }  //end check if group is a duplicate
    1544            0 :                 __COUTV__(foundExistingEmptyBackbone);
    1545              : 
    1546            0 :                 if(!foundExistingEmptyBackbone)
    1547              :                 {
    1548              :                         auto newKey = TableGroupKey::getNextKey(
    1549            0 :                             theInterface_->findLatestGroupKey(activeBackboneGroupName));
    1550              : 
    1551            0 :                         __COUT__ << "Updating backbone group from ("
    1552            0 :                                  << cfgMgr->getActiveGroupKey(
    1553            0 :                                         ConfigurationManager::GroupType::BACKBONE_TYPE)
    1554            0 :                                  << ") to (" << newKey << ")" << __E__;
    1555              : 
    1556              :                         // memberMap should now consist of members with new flat version, so save
    1557              : 
    1558              :                         // save group, and retry on save collision
    1559            0 :                         uint16_t retries = 0;
    1560              :                         while(1)
    1561              :                         {
    1562              :                                 try
    1563              :                                 {
    1564            0 :                                         theInterface_->saveTableGroup(backboneMemberMap,
    1565            0 :                                                                       TableGroupKey::getFullGroupString(
    1566              :                                                                           activeBackboneGroupName, newKey));
    1567              :                                 }
    1568            0 :                                 catch(const std::runtime_error& e)
    1569              :                                 {
    1570            0 :                                         __COUT__ << "Caught runtime_error exception during group save."
    1571            0 :                                                  << __E__;
    1572            0 :                                         if(std::string(e.what()).find("there was a collision") !=
    1573              :                                            std::string::npos)
    1574              :                                         {
    1575            0 :                                                 __COUT_WARN__
    1576            0 :                                                     << "There was a collision saving the new group "
    1577            0 :                                                     << activeBackboneGroupName << "(" << newKey
    1578            0 :                                                     << "), trying incremented group key... retries=" << retries
    1579            0 :                                                     << __E__;
    1580            0 :                                                 if(++retries > 3)  //give up
    1581            0 :                                                         throw;
    1582            0 :                                                 newKey = TableGroupKey::getNextKey(newKey);  //increment group key
    1583            0 :                                                 __COUT__ << "New Key for group: " << activeBackboneGroupName
    1584            0 :                                                          << " found as " << newKey << __E__;
    1585            0 :                                                 continue;
    1586            0 :                                         }
    1587              :                                         else
    1588            0 :                                                 throw;
    1589            0 :                                 }
    1590              : 
    1591            0 :                                 __COUT__ << "Created table group: " << activeBackboneGroupName << "("
    1592            0 :                                          << newKey << ")" << __E__;
    1593            0 :                                 break;
    1594            0 :                         }  //end collission retry loop
    1595              : 
    1596              :                         //      -- backup the file ConfigurationManager::ACTIVE_GROUPS_FILENAME with time
    1597              :                         std::string renameFile =
    1598            0 :                             ConfigurationManager::ACTIVE_GROUPS_FILENAME + "." + nowTime;
    1599            0 :                         rename(ConfigurationManager::ACTIVE_GROUPS_FILENAME.c_str(),
    1600              :                                renameFile.c_str());
    1601              : 
    1602            0 :                         __COUT__ << "Backing up '" << ConfigurationManager::ACTIVE_GROUPS_FILENAME
    1603            0 :                                  << "' to ... '" << renameFile << "'" << std::endl;
    1604              : 
    1605              :                         //      -- activate the new backbone group
    1606            0 :                         cfgMgr->activateTableGroup(activeBackboneGroupName,
    1607              :                                                    newKey);  // and write to active group file
    1608            0 :                 }
    1609              :         }
    1610              : 
    1611            0 :         __COUT__ << "End of Importing Table Groups from path!\n\n\n" << std::endl;
    1612              : 
    1613            0 : }  //end ImportTableGroupsFromPath()
    1614              : 
    1615            0 : int main(int argc, char* argv[])
    1616              : {
    1617              :         try
    1618              :         {
    1619            0 :                 ImportTableGroupsFromPath(argc, argv);
    1620              :         }
    1621            0 :         catch(...)
    1622              :         {
    1623            0 :                 __COUT_ERR__ << "Unhandled exception caught in main()!" << __E__
    1624            0 :                              << StringMacros::stackTrace() << std::endl;
    1625            0 :                 throw;
    1626            0 :         }
    1627              : 
    1628            0 :         return 0;
    1629              : }
    1630              : // BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1