otsdaq  3.03.00
ConfigurationInterface.cc
1 #include "otsdaq/ConfigurationInterface/ConfigurationInterface.h"
2 #include "otsdaq/ConfigurationInterface/MakeConfigurationInterface.h"
3 
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/MessageFacility/MessageFacility.h"
6 
7 #include <dirent.h>
8 #include <cassert>
9 #include <iostream>
10 #include <typeinfo>
11 
12 using namespace ots;
13 
14 #define DEBUG_CONFIGURATION true
15 
16 //==============================================================================
17 ConfigurationInterface* ConfigurationInterface::theInstance_ = nullptr;
18 ConfigurationInterface::CONFIGURATION_MODE ConfigurationInterface::theMode_ =
19  ConfigurationInterface::CONFIGURATION_MODE::DO_NOT_CREATE;
20 bool ConfigurationInterface::theVersionTrackingEnabled_ = true;
21 
22 //==============================================================================
24 
25 //==============================================================================
26 ConfigurationInterface* ConfigurationInterface::getInstance(
27  ConfigurationInterface::CONFIGURATION_MODE mode /* = DO_NOT_CREATE */)
28 {
29  if(mode == CONFIGURATION_MODE::DO_NOT_CREATE)
30  {
31  if(theInstance_ == nullptr)
32  std::cout
33  << __COUT_HDR_FL__
34  << "WARNING -- returning a nullptr ConfigurationInterface::theInstance_"
35  << __E__;
36  return theInstance_;
37  }
38 
39  auto instanceType = (mode == CONFIGURATION_MODE::XML_FILE) ? "File" : "Database";
40  if(theMode_ != mode)
41  {
42  delete theInstance_;
43  theInstance_ = nullptr;
44  }
45  if(theInstance_ == nullptr)
46  {
47  theInstance_ = makeConfigurationInterface(instanceType);
48  }
49 
50  theMode_ = mode;
51  return theInstance_;
52 } //end getInstance()
53 
54 //==============================================================================
55 bool ConfigurationInterface::isVersionTrackingEnabled()
56 {
57  return ConfigurationInterface::theVersionTrackingEnabled_;
58 }
59 
60 //==============================================================================
61 void ConfigurationInterface::setVersionTrackingEnabled(bool setValue)
62 {
63  ConfigurationInterface::theVersionTrackingEnabled_ = setValue;
64 }
65 
66 //==============================================================================
67 const ConfigurationInterface::CONFIGURATION_MODE& ConfigurationInterface::getMode()
68 {
69  return ConfigurationInterface::theMode_;
70 }
71 
72 //==============================================================================
80  TableVersion temporaryVersion,
81  TableVersion newVersion)
82 {
83  if(!temporaryVersion.isTemporaryVersion() || !table->isStored(temporaryVersion))
84  {
85  __COUT__ << "Invalid temporary version number: " << temporaryVersion << std::endl;
86  return TableVersion(); // return INVALID
87  }
88 
89  if(!ConfigurationInterface::isVersionTrackingEnabled()) // tracking is OFF, so always
90  // save to same version
91  newVersion = TableVersion::SCRATCH;
92 
93  bool rewriteableExists = false;
94 
95  std::set<TableVersion> versions = getVersions(table);
96  __COUTTV__(StringMacros::setToString(versions));
97  if(newVersion == TableVersion::INVALID)
98  {
99  if(versions.size())
100  __COUTTV__(*(versions.rbegin()));
101  if(versions.size() > 1)
102  __COUTTV__(*(++versions.rbegin()));
103 
104  if(versions
105  .size() && // 1 more than last version, if any non-scratch versions exist
106  *(versions.rbegin()) != TableVersion(TableVersion::SCRATCH))
107  newVersion = TableVersion::getNextVersion(*(versions.rbegin()));
108  else if(versions.size() >
109  1) // if scratch exists, take 1 more than second to last version
110  newVersion = TableVersion::getNextVersion(
111  *(++(versions.rbegin()))); //NOTE: ++ is reverse for a reverse_iterator!!
112  else
113  newVersion = TableVersion::DEFAULT;
114  __COUT__ << "Next available version number is " << newVersion << std::endl;
115  //
116  // //for sanity check, compare with config's idea of next version
117  // TableVersion baseNextVersion = table->getNextVersion();
118  // if(newVersion <= baseNextVersion)
119  // newVersion = TableVersion::getNextVersion(baseNextVersion);
120  //
121  // std::cout << __COUT_HDR_FL__ << "After considering baseNextVersion, " <<
122  // baseNextVersion <<
123  // ", next available version number is " << newVersion << std::endl;
124  }
125  else if(versions.find(newVersion) != versions.end())
126  {
127  __COUT__ << "newVersion(" << newVersion << ") already exists!" << std::endl;
128  rewriteableExists = newVersion == TableVersion::SCRATCH;
129 
130  // throw error if version already exists and this is not the rewriteable version
131  if(!rewriteableExists || ConfigurationInterface::isVersionTrackingEnabled())
132  {
133  __SS__ << ("New version already exists!") << std::endl;
134  __SS_THROW__;
135  }
136  }
137 
138  __COUT__ << "Version number to save is " << newVersion << std::endl;
139 
140  // copy to new version
141  table->changeVersionAndActivateView(temporaryVersion, newVersion);
142 
143  // save to disk
144  // only allow overwrite if version tracking is disabled AND the rewriteable version
145  // already exists.
146  bool overwrite =
147  !ConfigurationInterface::isVersionTrackingEnabled() && rewriteableExists;
148  uint16_t retries = overwrite ? 4 : 0; //only allow retries if not overwriting
149  auto tableView = table->getViewP();
150  while(1)
151  {
152  try
153  {
154  saveActiveVersion(table, overwrite);
155  }
156  catch(const std::runtime_error& e)
157  {
158  __COUT__ << "Caught runtime_error exception during table save." << __E__;
159  if(std::string(e.what()).find("there was a collision") != std::string::npos)
160  {
161  __COUT_WARN__ << "There was a collision saving the new table "
162  << *tableView << "(" << newVersion
163  << "), trying incremented table version... retries="
164  << retries << __E__;
165  if(++retries > 3) //give up
166  throw;
167  newVersion =
168  TableVersion::getNextVersion(newVersion); //increment table version
169  tableView->setVersion(newVersion);
170  __COUT__ << "New version for table: " << *tableView << " found as "
171  << newVersion << __E__;
172  continue;
173  }
174  else
175  throw;
176  }
177 
178  __COUT__ << "Created table: " << *tableView << "-v" << newVersion << __E__;
179  break;
180  } //end collission retry loop
181 
182  return newVersion;
183 } //end saveNewVersion()
ConfigurationInterface(void)
Protected constructor.
TableVersion saveNewVersion(TableBase *configuration, TableVersion temporaryVersion, TableVersion newVersion=TableVersion())
static TableVersion getNextVersion(const TableVersion &version=TableVersion())
bool isTemporaryVersion(void) const
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
setToString ~