1 #include "otsdaq/ConfigurationInterface/Database_configInterface.h" 
    2 #include "otsdaq/Macros/ConfigurationInterfacePluginMacros.h" 
    3 #include "otsdaq/Macros/CoutMacros.h" 
    4 #include "otsdaq/MessageFacility/MessageFacility.h" 
   11 #include "artdaq-database/BasicTypes/basictypes.h" 
   12 #include "artdaq-database/ConfigurationDB/configurationdbifc.h" 
   13 #include "otsdaq/TableCore/TableBase.h" 
   15 #include "artdaq-database/ConfigurationDB/configuration_common.h" 
   16 #include "artdaq-database/ConfigurationDB/dispatch_common.h" 
   17 #include "artdaq-database/StorageProviders/FileSystemDB/provider_filedb.h" 
   18 #include "artdaq-database/StorageProviders/FileSystemDB/provider_filedb_index.h" 
   22 using artdaq::database::basictypes::FhiclData;
 
   23 using artdaq::database::basictypes::JsonData;
 
   26 using table_version_map_t = ots::DatabaseConfigurationInterface::table_version_map_t;
 
   28 namespace db            = artdaq::database::configuration;
 
   29 using VersionInfoList_t = db::ConfigurationInterface::VersionInfoList_t;
 
   31 constexpr 
auto default_dbprovider = 
"filesystem";
 
   32 constexpr 
auto default_entity     = 
"OTSROOT";
 
   35 DatabaseConfigurationInterface::DatabaseConfigurationInterface()
 
   37 #ifdef ARTDAQ_DATABASE_DEBUG_ENABLE 
   40         artdaq::database::configuration::debug::ExportImport();
 
   41         artdaq::database::configuration::debug::ManageAliases();
 
   42         artdaq::database::configuration::debug::ManageConfigs();
 
   43         artdaq::database::configuration::debug::ManageDocuments();
 
   44         artdaq::database::configuration::debug::Metadata();
 
   46         artdaq::database::configuration::debug::detail::ExportImport();
 
   47         artdaq::database::configuration::debug::detail::ManageAliases();
 
   48         artdaq::database::configuration::debug::detail::ManageConfigs();
 
   49         artdaq::database::configuration::debug::detail::ManageDocuments();
 
   50         artdaq::database::configuration::debug::detail::Metadata();
 
   52         artdaq::database::configuration::debug::options::OperationBase();
 
   53         artdaq::database::configuration::debug::options::BulkOperations();
 
   54         artdaq::database::configuration::debug::options::ManageDocuments();
 
   55         artdaq::database::configuration::debug::options::ManageConfigs();
 
   56         artdaq::database::configuration::debug::options::ManageAliases();
 
   58         artdaq::database::configuration::debug::MongoDB();
 
   59         artdaq::database::configuration::debug::UconDB();
 
   60         artdaq::database::configuration::debug::FileSystemDB();
 
   65         artdaq::database::filesystem::debug::enable();
 
   74         artdaq::database::configuration::Multitasker();
 
   75         TRACE_CNTL(
"modeS", 
true);  
 
   79     std::string envVar = __ENV__(
"ARTDAQ_DATABASE_URI");
 
   82         IS_FILESYSTEM_DB = 
false;
 
   84         IS_FILESYSTEM_DB = 
true;
 
   85     __COUTV__(IS_FILESYSTEM_DB);
 
   94     auto start = std::chrono::high_resolution_clock::now();
 
   96     auto ifc = db::ConfigurationInterface{default_dbprovider};
 
   98     auto versionstring = version.
toString();
 
  100     auto result = ifc.template loadVersion<decltype(table), JsonData>(
 
  101         table, versionstring, default_entity);
 
  103     auto end = std::chrono::high_resolution_clock::now();
 
  105         std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  106     __COUTT__ << 
"Time taken to call DatabaseConfigurationInterface::fill(tableName=" 
  107               << table->
getTableName() << 
", version=" << versionstring << 
") " 
  108               << duration << 
" milliseconds." << std::endl;
 
  116     __SS__ << 
"\n\nDBI Error while filling '" << table->
getTableName() << 
"' version '" 
  117            << versionstring << 
"' - are you sure this version exists?\n" 
  118            << 
"Here is the error:\n\n" 
  119            << result.second << __E__;
 
  126                                                        bool             overwrite)
 const 
  129     auto start = std::chrono::high_resolution_clock::now();
 
  131     auto ifc = db::ConfigurationInterface{default_dbprovider};
 
  133     auto versionstring = table->getView().getVersion().
toString();
 
  139     auto result = overwrite ? ifc.template overwriteVersion<decltype(table), JsonData>(
 
  140                                   table, versionstring, default_entity)
 
  141                             : ifc.template storeVersion<decltype(table), JsonData>(
 
  142                                   table, versionstring, default_entity);
 
  144     auto end = std::chrono::high_resolution_clock::now();
 
  146         std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  147     __COUTT__ << 
"Time taken to call " 
  148                  "DatabaseConfigurationInterface::saveActiveVersion(tableName=" 
  149               << table->
getTableName() << 
", versionstring=" << versionstring << 
") " 
  150               << duration << 
" milliseconds" << std::endl;
 
  155     __SS__ << 
"DBI saveActiveVersion Error:" << result.second << __E__;
 
  164     auto versions = getVersions(table);
 
  176     return *(versions.rbegin());
 
  185     auto start = std::chrono::high_resolution_clock::now();
 
  187     auto ifc    = db::ConfigurationInterface{default_dbprovider};
 
  188     auto result = ifc.template getVersions<decltype(table)>(table, default_entity);
 
  190     auto end = std::chrono::high_resolution_clock::now();
 
  192         std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  194         << 
"Time taken to call DatabaseConfigurationInterface::getVersions(tableName=" 
  195         << table->getTableName() << 
") " << duration << 
" milliseconds." << std::endl;
 
  197     auto resultSet = std::set<TableVersion>{};
 
  198     for(std::string 
const& version : result)
 
  199         resultSet.insert(
TableVersion(std::stol(version, 0, 10)));
 
  216 catch(std::exception 
const& e)
 
  218     __COUT_WARN__ << 
"DBI Exception:" << e.what() << 
"\n";
 
  227     auto start = std::chrono::high_resolution_clock::now();
 
  229     auto ifc                    = db::ConfigurationInterface{default_dbprovider};
 
  230     auto collection_name_prefix = std::string{};
 
  232     auto result = ifc.listCollections(collection_name_prefix);
 
  234     auto end = std::chrono::high_resolution_clock::now();
 
  236         std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  238         << 
"Time taken to call " 
  239            "DatabaseConfigurationInterface::getAllTableNames(collection_name_prefix=" 
  240         << collection_name_prefix << 
") " << duration << 
" milliseconds." << std::endl;
 
  244 catch(std::exception 
const& e)
 
  246     __SS__ << 
"DBI Exception:" << e.what() << 
"\n";
 
  251     __SS__ << 
"DBI Unknown exception.\n";
 
  258     std::string 
const& filterString) 
const 
  261     auto start = std::chrono::high_resolution_clock::now();
 
  263     auto ifc = db::ConfigurationInterface{default_dbprovider};
 
  265     auto result = std::set<std::string>();
 
  267     if(filterString == 
"")
 
  268         result = ifc.findGlobalConfigurations(
"*");  
 
  272         result = ifc.findGlobalConfigurations(filterString + 
"*");  
 
  277     auto end = std::chrono::high_resolution_clock::now();
 
  279         std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  280     __COUTT__ << 
"Time taken to call " 
  281                  "DatabaseConfigurationInterface::getAllTableGroupNames(filterString=" 
  282               << filterString << 
") " << duration << 
" milliseconds." << std::endl;
 
  286 catch(std::exception 
const& e)
 
  288     __SS__ << 
"Filter string '" << filterString << 
"' yielded DBI Exception:" << e.what()
 
  294     __SS__ << 
"Filter string '" << filterString << 
"' yielded DBI Unknown exception.\n";
 
  302     const std::string& groupName) 
const noexcept
 
  306         return *(keys.crbegin());
 
  315     const std::string& groupName)
 const 
  317     std::set<TableGroupKey>        retSet;
 
  320         if(n.find(groupName) == 0)
 
  328     std::string 
const& tableGroup, 
bool includeMetaDataTable ) 
const 
  331     auto start = std::chrono::high_resolution_clock::now();
 
  346         table_version_map_t retMap = getCachedTableGroupMembers(tableGroup);
 
  347         __COUTV__(tableGroup);
 
  348         __COUT_TYPE__(TLVL_DEBUG + 20)
 
  351         if(!includeMetaDataTable)
 
  354             auto metaTable = retMap.find(GROUP_METADATA_TABLE_NAME);
 
  355             if(metaTable != retMap.end())
 
  356                 retMap.erase(metaTable);
 
  359         auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
 
  360                             std::chrono::high_resolution_clock::now() - start)
 
  362         __COUTT__ << 
"Time taken to call " 
  363                      "DatabaseConfigurationInterface::getTableGroupMembers(tableGroup=" 
  364                   << tableGroup << 
") " << duration << 
" milliseconds." << std::endl;
 
  369         __COUTT__ << 
"Ignoring error " 
  370                      "DatabaseConfigurationInterface::getTableGroupMembers(tableGroup=" 
  371                   << tableGroup << 
") " << __E__;
 
  374     auto ifc    = db::ConfigurationInterface{default_dbprovider};
 
  375     auto result = ifc.loadGlobalConfiguration(tableGroup);
 
  380     auto to_map = [](
auto const& inputList, 
bool includeMetaDataTable) {
 
  381         auto resultMap = table_version_map_t{};
 
  383         std::for_each(inputList.begin(), inputList.end(), [&resultMap](
auto const& info) {
 
  384             resultMap[info.configuration] = std::stol(info.version, 0, 10);
 
  387         if(!includeMetaDataTable)
 
  390             auto metaTable = resultMap.find(GROUP_METADATA_TABLE_NAME);
 
  391             if(metaTable != resultMap.end())
 
  392                 resultMap.erase(metaTable);
 
  397     table_version_map_t retMap = to_map(result, includeMetaDataTable);
 
  400     saveTableGroupMemberCache(retMap, tableGroup);
 
  405     auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
 
  406                         std::chrono::high_resolution_clock::now() - start)
 
  408     __COUTT__ << 
"Time taken to call " 
  409                  "DatabaseConfigurationInterface::getTableGroupMembers(tableGroup=" 
  410               << tableGroup << 
") " << duration << 
" milliseconds." << std::endl;
 
  414 catch(std::exception 
const& e)
 
  416     __SS__ << 
"DBI Exception getting Group's member tables for '" << tableGroup
 
  419     if(std::string(e.what()).find(
"connection refused") != std::string::npos)
 
  421         ss << 
"\n\nConnection to database refused. Perhaps your ssh tunnel has " 
  428     __SS__ << 
"DBI Unknown exception getting Group's member tables for '" << tableGroup
 
  430     __COUT_ERR__ << ss.str();
 
  437 table_version_map_t DatabaseConfigurationInterface::getCachedTableGroupMembers(
 
  438     std::string 
const& tableGroup) 
const 
  441     table_version_map_t retMap;
 
  455     std::size_t vi        = tableGroup.rfind(
"_v");
 
  456     std::string groupName = tableGroup.substr(0, vi);
 
  457     std::string groupKey  = tableGroup.substr(vi + 2);
 
  458     __COUTT__ << 
"Getting cache for " << groupName << 
"(" << groupKey << 
")" << __E__;
 
  460     TableBase    localGroupMemberCacheSaver(TableBase::GROUP_CACHE_PREPEND + groupName);
 
  466         __COUTT__ << 
"IS_FILESYSTEM_DB=true, so checking cached keys for " << groupName
 
  467                   << 
"(" << groupKey << 
")" << __E__;
 
  468         std::set<TableVersion> versions = getVersions(&localGroupMemberCacheSaver);
 
  469         if(versions.find(localVersion) == versions.end())
 
  471             __SS__ << 
"Cached member table versions not found for " << groupName << 
"(" 
  472                    << groupKey << 
")" << __E__;
 
  477     localGroupMemberCacheSaver.changeVersionAndActivateView(
 
  478         localGroupMemberCacheSaver.createTemporaryView(), localVersion);
 
  480     fill(&localGroupMemberCacheSaver, localVersion);
 
  482     __COUT_TYPE__(TLVL_DEBUG + 20)
 
  483         << __COUT_HDR__ << 
"Loaded cache member map string " 
  484         << localGroupMemberCacheSaver.getViewP()->getCustomStorageData() << __E__;
 
  487         localGroupMemberCacheSaver.getViewP()->getCustomStorageData(), retMap);
 
  489     __COUT_TYPE__(TLVL_DEBUG + 20) << __COUT_HDR__ << 
"Loaded cache member map string " 
  494 catch(std::exception 
const& e)
 
  496     __SS__ << 
"DBI Exception getCachedTableGroupMembers for '" << tableGroup << 
"':\n\n" 
  502     __SS__ << 
"DBI Unknown exception getCachedTableGroupMembers for '" << tableGroup
 
  509 void DatabaseConfigurationInterface::saveTableGroupMemberCache(
 
  510     table_version_map_t 
const& memberMap, std::string 
const& tableGroup) 
const 
  525     std::size_t vi        = tableGroup.rfind(
"_v");
 
  526     std::string groupName = tableGroup.substr(0, vi);
 
  527     std::string groupKey  = tableGroup.substr(vi + 2);
 
  528     __COUTT__ << 
"Saving cache for " << groupName << 
"(" << groupKey << 
")" << __E__;
 
  530     TableBase localGroupMemberCacheSaver(TableBase::GROUP_CACHE_PREPEND + groupName);
 
  531     localGroupMemberCacheSaver.changeVersionAndActivateView(
 
  532         localGroupMemberCacheSaver.createTemporaryView(),
 
  536         std::stringstream groupCacheData;
 
  537         groupCacheData << 
"{ ";
 
  538         for(
const auto& member : memberMap)
 
  539             groupCacheData << (member.first == memberMap.begin()->first ? 
"" : 
", ")
 
  541                 "\"" << member.first << 
"\" : \"" << member.second << 
"\"";
 
  542         groupCacheData << 
"}";
 
  544         localGroupMemberCacheSaver.getViewP()->setCustomStorageData(groupCacheData.str());
 
  547     __COUTT__ << 
"Saving member map string " 
  548               << localGroupMemberCacheSaver.getViewP()->getCustomStorageData() << __E__;
 
  550     __COUTT__ << 
"Saving cache table " 
  551               << localGroupMemberCacheSaver.getView().getTableName() << 
"(" 
  552               << localGroupMemberCacheSaver.getView().getVersion().toString() << 
")" 
  556     saveActiveVersion(&localGroupMemberCacheSaver, 
false );
 
  559 catch(std::exception 
const& e)
 
  561     __SS__ << 
"DBI Exception saveTableGroupMemberCache for '" << tableGroup << 
"':\n\n" 
  563     __COUT_ERR__ << ss.str();
 
  568     __SS__ << 
"DBI Unknown exception saveTableGroupMemberCache for '" << tableGroup
 
  570     __COUT_ERR__ << ss.str();
 
  577                                                     std::string 
const& tableGroup) 
const 
  580     auto start = std::chrono::high_resolution_clock::now();
 
  582     auto ifc = db::ConfigurationInterface{default_dbprovider};
 
  584     auto to_list = [](
auto const& inputMap) {
 
  585         auto resultList = VersionInfoList_t{};
 
  589             std::back_inserter(resultList),
 
  590             [](
auto const& mapEntry) {
 
  591                 return VersionInfoList_t::value_type{
 
  592                     mapEntry.first, mapEntry.second.toString(), default_entity};
 
  598     auto result = IS_FILESYSTEM_DB
 
  599                       ? ifc.storeGlobalConfiguration(to_list(memberMap), tableGroup)
 
  600                       : ifc.storeGlobalConfiguration_mt(to_list(memberMap), tableGroup);
 
  602     auto end = std::chrono::high_resolution_clock::now();
 
  604         std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 
  606         << 
"Time taken to call DatabaseConfigurationInterface::saveTableGroup(tableGroup=" 
  607         << tableGroup << 
") " << duration << 
" milliseconds." << std::endl;
 
  614             saveTableGroupMemberCache(memberMap, tableGroup);
 
  618             __COUT_WARN__ << 
"Ignoring errors during saveTableGroupMemberCache()" 
  625     __THROW__(result.second);
 
  627 catch(std::exception 
const& e)
 
  629     __SS__ << 
"DBI Exception saveTableGroup for '" << tableGroup << 
"':\n\n" 
  635     __SS__ << 
"DBI Unknown exception saveTableGroup for '" << tableGroup << 
".'\n";
 
  640 std::pair<std::string, TableVersion> DatabaseConfigurationInterface::saveCustomJSON(
 
  641     const std::string& json, 
const std::string& documentNameToSave) 
const 
  644     __COUTT__ << 
"Saving doc '" << documentNameToSave << 
"'" << __E__;
 
  646     TableBase localDocSaver(TableBase::JSON_DOC_PREPEND + documentNameToSave);
 
  648     std::set<TableVersion> versions = getVersions(&localDocSaver);
 
  651         version = TableVersion::getNextVersion(*versions.rbegin());
 
  653         version = TableVersion::DEFAULT;
 
  656     localDocSaver.changeVersionAndActivateView(localDocSaver.createTemporaryView(),
 
  659     localDocSaver.getViewP()->setCustomStorageData(json);
 
  661     __COUTT__ << 
"Saving JSON string: " 
  662               << localDocSaver.getViewP()->getCustomStorageData() << __E__;
 
  664     __COUTT__ << 
"Saving JSON doc as " << localDocSaver.getView().getTableName() << 
"(" 
  665               << localDocSaver.getView().getVersion().toString() << 
")" << __E__;
 
  668     saveActiveVersion(&localDocSaver, 
false );
 
  670     return std::make_pair(localDocSaver.getTableName(),
 
  671                           localDocSaver.getView().getVersion());
 
  673 catch(std::exception 
const& e)
 
  675     __SS__ << 
"DBI Exception saveCustomJSON for '" << documentNameToSave << 
"':\n\n" 
  677     __COUT_ERR__ << ss.str();
 
  682     __SS__ << 
"DBI Unknown exception saveCustomJSON for '" << documentNameToSave
 
  684     __COUT_ERR__ << ss.str();
 
  689 std::string DatabaseConfigurationInterface::loadCustomJSON(
 
  690     const std::string& documentNameToLoad, 
TableVersion documentVersionToLoad) 
const 
  693     __COUTT__ << 
"Loading doc '" << documentNameToLoad << 
"-v" << documentVersionToLoad
 
  696     TableBase localDocLoader(TableBase::JSON_DOC_PREPEND + documentNameToLoad);
 
  698     localDocLoader.changeVersionAndActivateView(localDocLoader.createTemporaryView(),
 
  699                                                 documentVersionToLoad);
 
  701     fill(&localDocLoader, documentVersionToLoad);
 
  703     __COUTT__ << 
"Loaded JSON doc string " 
  704               << localDocLoader.getViewP()->getCustomStorageData() << __E__;
 
  706     return localDocLoader.getViewP()->getCustomStorageData();
 
  708 catch(std::exception 
const& e)
 
  710     __SS__ << 
"DBI Exception saveCustomJSON for '" << documentNameToLoad << 
"-v" 
  711            << documentVersionToLoad << 
"':\n\n" 
  713     __COUT_ERR__ << ss.str();
 
  718     __SS__ << 
"DBI Unknown exception saveCustomJSON for '" << documentNameToLoad << 
"-v" 
  719            << documentVersionToLoad << 
".'\n";
 
  720     __COUT_ERR__ << ss.str();
 
void saveTableGroup(table_version_map_t const &memberMap, std::string const &tableGroup) const override
create a new table group from the contents map
 
TableVersion findLatestVersion(const TableBase *table) const noexcept override
find the latest table version by table type
 
table_version_map_t getTableGroupMembers(std::string const &tableGroup, bool includeMetaDataTable=false) const override
return the contents of a table group
 
std::set< std::string > getAllTableGroupNames(std::string const &filterString="") const override
find all table groups in database
 
std::set< TableGroupKey > getKeys(const std::string &groupName) const override
find all configuration groups in database
 
std::set< TableVersion > getVersions(const TableBase *table) const noexcept override
find all table versions by table type
 
std::set< std::string > getAllTableNames(void) const override
returns a list of all table names
 
void fill(TableBase *table, TableVersion version) const override
read table from database
 
TableGroupKey findLatestGroupKey(const std::string &groupName) const noexcept override
 
void saveActiveVersion(const TableBase *table, bool overwrite=false) const override
write table to database
 
const std::string & getTableName(void) const
Getters.
 
std::string toString(void) const
toString
 
void setVersion(const T &version)
< in included .icc source
 
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
 
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
getMapFromString ~