tdaq-develop-2025-02-12
Database_configInterface.cc
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"
5 
6 #include <algorithm>
7 #include <iostream>
8 #include <iterator>
9 #include <string>
10 
11 #include "artdaq-database/BasicTypes/basictypes.h"
12 #include "artdaq-database/ConfigurationDB/configurationdbifc.h"
13 #include "otsdaq/TableCore/TableBase.h"
14 
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"
19 
20 using namespace ots;
21 
22 using artdaq::database::basictypes::FhiclData;
23 using artdaq::database::basictypes::JsonData;
24 
26 using table_version_map_t = ots::DatabaseConfigurationInterface::table_version_map_t;
27 
28 namespace db = artdaq::database::configuration;
29 using VersionInfoList_t = db::ConfigurationInterface::VersionInfoList_t;
30 
31 constexpr auto default_dbprovider = "filesystem";
32 constexpr auto default_entity = "OTSROOT";
33 
34 //==============================================================================
35 DatabaseConfigurationInterface::DatabaseConfigurationInterface()
36 {
37 #ifdef ARTDAQ_DATABASE_DEBUG_ENABLE
38  // to enable debugging
39  {
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();
45 
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();
51 
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();
57 
58  artdaq::database::configuration::debug::MongoDB();
59  artdaq::database::configuration::debug::UconDB();
60  artdaq::database::configuration::debug::FileSystemDB();
61 
62  // artdaq::database::filesystem::index::debug::enable();
63 
64  // THIS TURNS OFF TRACE SLOW PATH!!! (bug? Gennadiy says was trying to avoid slowing down TRACE with too many messages on slow path)
65  artdaq::database::filesystem::debug::enable();
66 
67  // artdaq::database::mongo::debug::enable();
68 
69  // artdaq::database::docrecord::debug::JSONDocumentBuilder();
70  // artdaq::database::docrecord::debug::JSONDocument();
71 
72  // debug::registerUngracefullExitHandlers();
73  // artdaq::database::useFakeTime(true);
74  artdaq::database::configuration::Multitasker();
75  TRACE_CNTL("modeS", true); //TURN BACK ON TRACE SLOW PATH
76  }
77 #endif
78 
79  std::string envVar = __ENV__("ARTDAQ_DATABASE_URI");
80  if(envVar.length() &&
81  envVar[0] != 'f') //e.g., filesystemdb:///path/filesystemdb/test_db
82  IS_FILESYSTEM_DB = false;
83  else
84  IS_FILESYSTEM_DB = true;
85  __COUTV__(IS_FILESYSTEM_DB);
86 } //end constructor()
87 
88 //==============================================================================
92 
93 {
94  auto start = std::chrono::high_resolution_clock::now();
95 
96  auto ifc = db::ConfigurationInterface{default_dbprovider};
97 
98  auto versionstring = version.toString();
99 
100  auto result = ifc.template loadVersion<decltype(table), JsonData>(
101  table, versionstring, default_entity);
102 
103  auto end = std::chrono::high_resolution_clock::now();
104  auto duration =
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;
109 
110  if(result.first)
111  {
112  // make sure version is set.. not clear it was happening in loadVersion
113  table->getViewP()->setVersion(version);
114  return;
115  }
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__;
120  __SS_ONLY_THROW__;
121 } // end fill()
122 
123 //==============================================================================
126  bool overwrite) const
127 
128 {
129  auto start = std::chrono::high_resolution_clock::now();
130 
131  auto ifc = db::ConfigurationInterface{default_dbprovider};
132 
133  auto versionstring = table->getView().getVersion().toString();
134  //__COUT__ << "versionstring: " << versionstring << "\n";
135 
136  // auto result =
137  // ifc.template storeVersion<decltype(configuration), JsonData>(configuration,
138  // versionstring, default_entity);
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);
143 
144  auto end = std::chrono::high_resolution_clock::now();
145  auto duration =
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;
151 
152  if(result.first)
153  return;
154 
155  __SS__ << "DBI saveActiveVersion Error:" << result.second << __E__;
156  __SS_THROW__;
157 } //end saveActiveVersion()
158 
159 //==============================================================================
162  const TableBase* table) const noexcept
163 {
164  auto versions = getVersions(table);
165 
166  // __COUT__ << "Table Name: " << table->getTableName() << __E__;
167  // __SS__ << "All Versions: ";
168  // for(auto& v : versions)
169  // ss << v << " ";
170  // ss << __E__;
171  // __COUT__ << ss.str();
172 
173  if(!versions.size())
174  return TableVersion(); // return INVALID
175 
176  return *(versions.rbegin());
177 } //end findLatestVersion()
178 
179 //==============================================================================
182  const TableBase* table) const noexcept
183 try
184 {
185  auto start = std::chrono::high_resolution_clock::now();
186 
187  auto ifc = db::ConfigurationInterface{default_dbprovider};
188  auto result = ifc.template getVersions<decltype(table)>(table, default_entity);
189 
190  auto end = std::chrono::high_resolution_clock::now();
191  auto duration =
192  std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
193  __COUTT__
194  << "Time taken to call DatabaseConfigurationInterface::getVersions(tableName="
195  << table->getTableName() << ") " << duration << " milliseconds." << std::endl;
196 
197  auto resultSet = std::set<TableVersion>{};
198  for(std::string const& version : result)
199  resultSet.insert(TableVersion(std::stol(version, 0, 10)));
200 
201  // auto to_set = [](auto const& inputList)
202  // {
203  // auto resultSet = std::set<TableVersion>{};
204  // std::for_each(inputList.begin(), inputList.end(),
205  // [&resultSet](std::string const& version)
206  // { resultSet.insert(std::stol(version, 0, 10)); });
207  // return resultSet;
208  // };
209 
210  // auto vs = to_set(result);
211  // for(auto &v:vs)
212  // __COUT__ << "\tversion " << v << __E__;
213 
214  return resultSet; // to_set(result);
215 } //end getVersions()
216 catch(std::exception const& e)
217 {
218  __COUT_WARN__ << "DBI Exception:" << e.what() << "\n";
219  return {};
220 } //end getVersions() catch
221 
222 //==============================================================================
224 std::set<std::string /*name*/> DatabaseConfigurationInterface::getAllTableNames() const
225 try
226 {
227  auto start = std::chrono::high_resolution_clock::now();
228 
229  auto ifc = db::ConfigurationInterface{default_dbprovider};
230  auto collection_name_prefix = std::string{};
231 
232  auto result = ifc.listCollections(collection_name_prefix);
233 
234  auto end = std::chrono::high_resolution_clock::now();
235  auto duration =
236  std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
237  __COUTT__
238  << "Time taken to call "
239  "DatabaseConfigurationInterface::getAllTableNames(collection_name_prefix="
240  << collection_name_prefix << ") " << duration << " milliseconds." << std::endl;
241 
242  return result;
243 } //end getAllTableNames()
244 catch(std::exception const& e)
245 {
246  __SS__ << "DBI Exception:" << e.what() << "\n";
247  __SS_THROW__;
248 }
249 catch(...)
250 {
251  __SS__ << "DBI Unknown exception.\n";
252  __SS_THROW__;
253 } //end getAllTableNames() catch
254 
255 //==============================================================================
258  std::string const& filterString) const
259 try
260 {
261  auto start = std::chrono::high_resolution_clock::now();
262 
263  auto ifc = db::ConfigurationInterface{default_dbprovider};
264 
265  auto result = std::set<std::string>();
266 
267  if(filterString == "")
268  result = ifc.findGlobalConfigurations("*"); // GConfig will return all GConfig*
269  // with filesystem db.. for mongodb
270  // would require reg expr
271  else
272  result = ifc.findGlobalConfigurations(filterString + "*"); // GConfig will return
273  // all GConfig* with
274  // filesystem db.. for
275  // mongodb would require
276  // reg expr
277  auto end = std::chrono::high_resolution_clock::now();
278  auto duration =
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;
283 
284  return result;
285 } //end getAllTableGroupNames()
286 catch(std::exception const& e)
287 {
288  __SS__ << "Filter string '" << filterString << "' yielded DBI Exception:" << e.what()
289  << "\n";
290  __SS_THROW__;
291 }
292 catch(...)
293 {
294  __SS__ << "Filter string '" << filterString << "' yielded DBI Unknown exception.\n";
295  __SS_THROW__;
296 } //end getAllTableGroupNames() catch
297 
298 //==============================================================================
302  const std::string& groupName) const noexcept
303 {
304  std::set<TableGroupKey> keys = DatabaseConfigurationInterface::getKeys(groupName);
305  if(keys.size()) // if keys exist, bump the last
306  return *(keys.crbegin());
307 
308  // else, return invalid
309  return TableGroupKey();
310 }
311 
312 //==============================================================================
315  const std::string& groupName) const
316 {
317  std::set<TableGroupKey> retSet;
318  std::set<std::string /*name*/> names = getAllTableGroupNames();
319  for(auto& n : names)
320  if(n.find(groupName) == 0)
321  retSet.insert(TableGroupKey(n));
322  return retSet;
323 }
324 
325 //==============================================================================
328  std::string const& tableGroup, bool includeMetaDataTable /* = false */) const
329 try
330 {
331  auto start = std::chrono::high_resolution_clock::now();
332 
333  //Flow (motivation -- getTableGroupMembers() is super slow; can be 3 to 15 seconds):
334  // when saveTableGroup() is called
335  // saveDocument (collection: "GroupCache" + tableGroup, version: groupKey)
336  // containing --> table group members
337  // when getTableGroupMembers() is called
338  // loadDocument (collection: "GroupCache" + tableGroup, version: groupKey)
339  // if succeeds, use that
340  // else continue with db extended lookup
341  // AND create cache file (in this way slowly populating the cache even without saves)
342 
343  // format: groupName + "_v" + groupKey
344  try
345  {
346  table_version_map_t retMap = getCachedTableGroupMembers(tableGroup);
347  __COUTV__(tableGroup);
348  __COUT_TYPE__(TLVL_DEBUG + 20)
349  << __COUT_HDR__ << (StringMacros::mapToString(retMap));
350 
351  if(!includeMetaDataTable)
352  {
353  // remove special meta data table from member map
354  auto metaTable = retMap.find(GROUP_METADATA_TABLE_NAME);
355  if(metaTable != retMap.end())
356  retMap.erase(metaTable);
357  }
358 
359  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
360  std::chrono::high_resolution_clock::now() - start)
361  .count();
362  __COUTT__ << "Time taken to call "
363  "DatabaseConfigurationInterface::getTableGroupMembers(tableGroup="
364  << tableGroup << ") " << duration << " milliseconds." << std::endl;
365  return retMap;
366  }
367  catch(...) //ignore error and proceed with standard db access
368  {
369  __COUTT__ << "Ignoring error "
370  "DatabaseConfigurationInterface::getTableGroupMembers(tableGroup="
371  << tableGroup << ") " << __E__;
372  }
373 
374  auto ifc = db::ConfigurationInterface{default_dbprovider};
375  auto result = ifc.loadGlobalConfiguration(tableGroup);
376 
377  // for(auto &item:result)
378  // __COUTT__ << "====================> " << item.configuration << ": " << item.version << __E__;
379 
380  auto to_map = [](auto const& inputList, bool includeMetaDataTable) {
381  auto resultMap = table_version_map_t{};
382 
383  std::for_each(inputList.begin(), inputList.end(), [&resultMap](auto const& info) {
384  resultMap[info.configuration] = std::stol(info.version, 0, 10);
385  });
386 
387  if(!includeMetaDataTable)
388  {
389  // remove special meta data table from member map
390  auto metaTable = resultMap.find(GROUP_METADATA_TABLE_NAME);
391  if(metaTable != resultMap.end())
392  resultMap.erase(metaTable);
393  }
394  return resultMap;
395  };
396 
397  table_version_map_t retMap = to_map(result, includeMetaDataTable);
398 
399  //now create cache for next time!
400  saveTableGroupMemberCache(retMap, tableGroup);
401 
402  __COUTT__ << "Loaded db member map string " << StringMacros::mapToString(retMap)
403  << __E__;
404 
405  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
406  std::chrono::high_resolution_clock::now() - start)
407  .count();
408  __COUTT__ << "Time taken to call "
409  "DatabaseConfigurationInterface::getTableGroupMembers(tableGroup="
410  << tableGroup << ") " << duration << " milliseconds." << std::endl;
411 
412  return retMap;
413 } // end getTableGroupMembers()
414 catch(std::exception const& e)
415 {
416  __SS__ << "DBI Exception getting Group's member tables for '" << tableGroup
417  << "':\n\n"
418  << e.what() << "\n";
419  if(std::string(e.what()).find("connection refused") != std::string::npos)
420  {
421  ss << "\n\nConnection to database refused. Perhaps your ssh tunnel has "
422  "closed?\n\n";
423  }
424  __SS_THROW__;
425 }
426 catch(...)
427 {
428  __SS__ << "DBI Unknown exception getting Group's member tables for '" << tableGroup
429  << ".'\n";
430  __COUT_ERR__ << ss.str();
431  __SS_THROW__;
432 } // end getTableGroupMembers() catch
433 
434 //==============================================================================
437 table_version_map_t DatabaseConfigurationInterface::getCachedTableGroupMembers(
438  std::string const& tableGroup) const
439 try
440 {
441  table_version_map_t retMap;
442 
443  //Flow:
444  // when saveTableGroup() is called
445  // saveDocument (collection: "GroupCache_" + tableGroup, version: groupKey)
446  // containing --> table group members
447  // when getTableGroupMembers() is called
448  // loadDocument (collection: "GroupCache_" + tableGroup, version: groupKey)
449  // if succeeds, use that
450  // else continue with db extended lookup
451  // AND create cache file (in this way slowly populating the cache even without saves)
452 
453  // tableGroup format: groupName + "_v" + groupKey
454 
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__;
459 
460  TableBase localGroupMemberCacheSaver(TableBase::GROUP_CACHE_PREPEND + groupName);
461  TableVersion localVersion(atoi(groupKey.c_str()));
462 
463  //if filesystem db, as of April 2024, artdaq_database returned latest version when version is missing...
464  if(IS_FILESYSTEM_DB)
465  {
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())
470  {
471  __SS__ << "Cached member table versions not found for " << groupName << "("
472  << groupKey << ")" << __E__;
473  __SS_THROW__;
474  }
475  }
476 
477  localGroupMemberCacheSaver.changeVersionAndActivateView(
478  localGroupMemberCacheSaver.createTemporaryView(), localVersion);
479 
480  fill(&localGroupMemberCacheSaver, localVersion);
481 
482  __COUT_TYPE__(TLVL_DEBUG + 20)
483  << __COUT_HDR__ << "Loaded cache member map string "
484  << localGroupMemberCacheSaver.getViewP()->getCustomStorageData() << __E__;
485 
487  localGroupMemberCacheSaver.getViewP()->getCustomStorageData(), retMap);
488 
489  __COUT_TYPE__(TLVL_DEBUG + 20) << __COUT_HDR__ << "Loaded cache member map string "
490  << StringMacros::mapToString(retMap) << __E__;
491 
492  return retMap;
493 } //end getCachedTableGroupMembers()
494 catch(std::exception const& e)
495 {
496  __SS__ << "DBI Exception getCachedTableGroupMembers for '" << tableGroup << "':\n\n"
497  << e.what() << "\n";
498  __SS_THROW__;
499 }
500 catch(...)
501 {
502  __SS__ << "DBI Unknown exception getCachedTableGroupMembers for '" << tableGroup
503  << ".'\n";
504  __SS_THROW__;
505 } //end getCachedTableGroupMembers() catch
506 
507 //==============================================================================
509 void DatabaseConfigurationInterface::saveTableGroupMemberCache(
510  table_version_map_t const& memberMap, std::string const& tableGroup) const
511 try
512 {
513  //Flow:
514  // when saveTableGroup() is called
515  // saveDocument (collection: "GroupCache_" + tableGroup, version: groupKey)
516  // containing --> table group members
517  // when getTableGroupMembers() is called
518  // loadDocument (collection: "GroupCache_" + tableGroup, version: groupKey)
519  // if succeeds, use that
520  // else continue with db extended lookup
521  // AND create cache file (in this way slowly populating the cache even without saves)
522 
523  // tableGroup format: groupName + "_v" + groupKey
524 
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__;
529 
530  TableBase localGroupMemberCacheSaver(TableBase::GROUP_CACHE_PREPEND + groupName);
531  localGroupMemberCacheSaver.changeVersionAndActivateView(
532  localGroupMemberCacheSaver.createTemporaryView(),
533  TableVersion(atoi(groupKey.c_str())));
534 
535  { //set custom storage data
536  std::stringstream groupCacheData;
537  groupCacheData << "{ ";
538  for(const auto& member : memberMap)
539  groupCacheData << (member.first == memberMap.begin()->first ? "" : ", ")
540  << //skip comma on first
541  "\"" << member.first << "\" : \"" << member.second << "\"";
542  groupCacheData << "}";
543 
544  localGroupMemberCacheSaver.getViewP()->setCustomStorageData(groupCacheData.str());
545  } //end set custom storage data
546 
547  __COUTT__ << "Saving member map string "
548  << localGroupMemberCacheSaver.getViewP()->getCustomStorageData() << __E__;
549 
550  __COUTT__ << "Saving cache table "
551  << localGroupMemberCacheSaver.getView().getTableName() << "("
552  << localGroupMemberCacheSaver.getView().getVersion().toString() << ")"
553  << __E__;
554 
555  // save to db, and do not allow overwrite
556  saveActiveVersion(&localGroupMemberCacheSaver, false /* overwrite */);
557 
558 } //end saveTableGroupMemberCache()
559 catch(std::exception const& e)
560 {
561  __SS__ << "DBI Exception saveTableGroupMemberCache for '" << tableGroup << "':\n\n"
562  << e.what() << "\n";
563  __COUT_ERR__ << ss.str();
564  __SS_THROW__;
565 }
566 catch(...)
567 {
568  __SS__ << "DBI Unknown exception saveTableGroupMemberCache for '" << tableGroup
569  << ".'\n";
570  __COUT_ERR__ << ss.str();
571  __SS_THROW__;
572 } //end saveTableGroupMemberCache() catch
573 
574 //==============================================================================
576 void DatabaseConfigurationInterface::saveTableGroup(table_version_map_t const& memberMap,
577  std::string const& tableGroup) const
578 try
579 {
580  auto start = std::chrono::high_resolution_clock::now();
581 
582  auto ifc = db::ConfigurationInterface{default_dbprovider};
583 
584  auto to_list = [](auto const& inputMap) {
585  auto resultList = VersionInfoList_t{};
586  std::transform(
587  inputMap.begin(),
588  inputMap.end(),
589  std::back_inserter(resultList),
590  [](auto const& mapEntry) {
591  return VersionInfoList_t::value_type{
592  mapEntry.first, mapEntry.second.toString(), default_entity};
593  });
594 
595  return resultList;
596  };
597 
598  auto result = IS_FILESYSTEM_DB
599  ? ifc.storeGlobalConfiguration(to_list(memberMap), tableGroup)
600  : ifc.storeGlobalConfiguration_mt(to_list(memberMap), tableGroup);
601 
602  auto end = std::chrono::high_resolution_clock::now();
603  auto duration =
604  std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
605  __COUTT__
606  << "Time taken to call DatabaseConfigurationInterface::saveTableGroup(tableGroup="
607  << tableGroup << ") " << duration << " milliseconds." << std::endl;
608 
609  if(result.first)
610  {
611  //now save to db cache for reverse index lookup of group members
612  try
613  {
614  saveTableGroupMemberCache(memberMap, tableGroup);
615  }
616  catch(...)
617  {
618  __COUT_WARN__ << "Ignoring errors during saveTableGroupMemberCache()"
619  << __E__;
620  }
621 
622  return;
623  }
624 
625  __THROW__(result.second);
626 } // end saveTableGroup()
627 catch(std::exception const& e)
628 {
629  __SS__ << "DBI Exception saveTableGroup for '" << tableGroup << "':\n\n"
630  << e.what() << "\n";
631  __SS_THROW__;
632 }
633 catch(...)
634 {
635  __SS__ << "DBI Unknown exception saveTableGroup for '" << tableGroup << ".'\n";
636  __SS_THROW__;
637 } //end saveTableGroup() catch
638 
639 //==============================================================================
640 std::pair<std::string, TableVersion> DatabaseConfigurationInterface::saveCustomJSON(
641  const std::string& json, const std::string& documentNameToSave) const
642 try
643 {
644  __COUTT__ << "Saving doc '" << documentNameToSave << "'" << __E__;
645 
646  TableBase localDocSaver(TableBase::JSON_DOC_PREPEND + documentNameToSave);
647 
648  std::set<TableVersion> versions = getVersions(&localDocSaver);
649  TableVersion version;
650  if(versions.size())
651  version = TableVersion::getNextVersion(*versions.rbegin());
652  else
653  version = TableVersion::DEFAULT;
654  __COUTV__(version);
655 
656  localDocSaver.changeVersionAndActivateView(localDocSaver.createTemporaryView(),
657  version);
658 
659  localDocSaver.getViewP()->setCustomStorageData(json);
660 
661  __COUTT__ << "Saving JSON string: "
662  << localDocSaver.getViewP()->getCustomStorageData() << __E__;
663 
664  __COUTT__ << "Saving JSON doc as " << localDocSaver.getView().getTableName() << "("
665  << localDocSaver.getView().getVersion().toString() << ")" << __E__;
666 
667  // save to db, and do not allow overwrite
668  saveActiveVersion(&localDocSaver, false /* overwrite */);
669 
670  return std::make_pair(localDocSaver.getTableName(),
671  localDocSaver.getView().getVersion());
672 } //end saveCustomJSON()
673 catch(std::exception const& e)
674 {
675  __SS__ << "DBI Exception saveCustomJSON for '" << documentNameToSave << "':\n\n"
676  << e.what() << "\n";
677  __COUT_ERR__ << ss.str();
678  __SS_THROW__;
679 }
680 catch(...)
681 {
682  __SS__ << "DBI Unknown exception saveCustomJSON for '" << documentNameToSave
683  << ".'\n";
684  __COUT_ERR__ << ss.str();
685  __SS_THROW__;
686 } //end saveCustomJSON() catch
687 
688 //==============================================================================
689 std::string DatabaseConfigurationInterface::loadCustomJSON(
690  const std::string& documentNameToLoad, TableVersion documentVersionToLoad) const
691 try
692 {
693  __COUTT__ << "Loading doc '" << documentNameToLoad << "-v" << documentVersionToLoad
694  << "'" << __E__;
695 
696  TableBase localDocLoader(TableBase::JSON_DOC_PREPEND + documentNameToLoad);
697 
698  localDocLoader.changeVersionAndActivateView(localDocLoader.createTemporaryView(),
699  documentVersionToLoad);
700 
701  fill(&localDocLoader, documentVersionToLoad);
702 
703  __COUTT__ << "Loaded JSON doc string "
704  << localDocLoader.getViewP()->getCustomStorageData() << __E__;
705 
706  return localDocLoader.getViewP()->getCustomStorageData();
707 } //end loadCustomJSON()
708 catch(std::exception const& e)
709 {
710  __SS__ << "DBI Exception saveCustomJSON for '" << documentNameToLoad << "-v"
711  << documentVersionToLoad << "':\n\n"
712  << e.what() << "\n";
713  __COUT_ERR__ << ss.str();
714  __SS_THROW__;
715 }
716 catch(...)
717 {
718  __SS__ << "DBI Unknown exception saveCustomJSON for '" << documentNameToLoad << "-v"
719  << documentVersionToLoad << ".'\n";
720  __COUT_ERR__ << ss.str();
721  __SS_THROW__;
722 } //end loadCustomJSON() catch
723 
724 DEFINE_OTS_CONFIGURATION_INTERFACE(DatabaseConfigurationInterface)
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.
Definition: TableBase.cc:681
std::string toString(void) const
toString
Definition: TableVersion.cc:33
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 ~