otsdaq  v2_03_00
ConfigurationInterface.h
1 #ifndef _ots_ConfigurationInterface_h_
2 #define _ots_ConfigurationInterface_h_
3 
4 #include <memory>
5 #include <set>
6 #include <sstream>
7 #include "otsdaq-core/Macros/CoutMacros.h"
8 
9 #include "otsdaq-core/PluginMakers/MakeTable.h"
10 #include "otsdaq-core/TableCore/TableBase.h"
11 #include "otsdaq-core/TableCore/TableGroupKey.h"
12 #include "otsdaq-core/TableCore/TableVersion.h"
13 
14 namespace ots
15 {
16 class ConfigurationHandlerBase;
17 
19 {
20  friend class ConfigurationManagerRW; // because need access to latestVersion() call
21  // for group metadata
22  friend class ConfigurationManager; // because need access to fill() call for group
23  // metadata
24 
25  public:
26  virtual ~ConfigurationInterface() { ; }
27 
28  static ConfigurationInterface* getInstance(bool mode);
29  static bool isVersionTrackingEnabled();
30  static void setVersionTrackingEnabled(bool setValue);
31 
32  static const std::string GROUP_METADATA_TABLE_NAME;
33  //==============================================================================
34  // get
35  // Note: If filling, assume, new view becomes active view.
36  //
37  // Loose column matching can be used to ignore column names when filling.
38  //
39  void get(TableBase*& table,
40  const std::string tableName,
41  std::shared_ptr<const TableGroupKey> groupKey = 0,
42  const std::string* groupName = 0,
43  bool dontFill = false,
44  TableVersion version = TableVersion(),
45  bool resetConfiguration = true,
46  bool looseColumnMatching = false)
47  {
48  if(table == 0)
49  {
50  // try making table table plugin, if fails use TableBase
51  try
52  {
53  table = makeTable(tableName);
54  }
55  catch(...)
56  {
57  }
58 
59  if(table == 0)
60  {
61  //__COUT__ << "Using TableBase object with table name " <<
62  // tableName << std::endl;
63 
64  // try making table base..
65  // if it fails, then probably something wrong with Info file
66  try
67  {
68  table = new TableBase(tableName);
69  }
70  catch(...) // failure so cleanup any halfway complete table work
71  {
72  __COUT_WARN__ << "Failed to even use TableBase!" << std::endl;
73  if(table)
74  delete table;
75  table = 0;
76  throw;
77  }
78  }
79  //__COUT__ << "Table constructed!" << std::endl;
80  }
81 
82  if(groupKey != 0 && groupName != 0)
83  { // FIXME -- new TableGroup and TableGroupKey should be used!
84  // version = configurations->getConditionVersion(*groupKey,
85  // table->getTableName());
86  __SS__ << "FATAL ERROR: new TableGroup and TableGroupKey should be used!"
87  << std::endl;
88  __SS_THROW__;
89  }
90  else if(!dontFill)
91  {
92  // check version choice
93  if(version == TableVersion::INVALID &&
94  (version = findLatestVersion(table)) == TableVersion::INVALID)
95  {
96  __COUT__ << "FATAL ERROR: Can't ask to fill a table object with "
97  "a negative version! "
98  << tableName << std::endl;
99  __SS__ << "FATAL ERROR: Invalid latest version." << std::endl
100  << std::endl
101  << std::endl
102  << "*******************" << std::endl
103  << "Suggestion: If you expect a version to exist for this "
104  "table, perhaps this is your first time running with "
105  "the artdaq database. (and your old configurations have not "
106  "been transferred?) "
107  << std::endl
108  << "Try running this once:\n\n\totsdaq_database_migrate"
109  << std::endl
110  << std::endl
111  << "This will migrate the old ots file system table to "
112  "the artdaq database approach."
113  << std::endl
114  << std::endl
115  << std::endl;
116  __SS_THROW__;
117  }
118  }
119 
120  if(resetConfiguration) // reset to empty table views and no active view
121  { // EXCEPT, keep temporary views! (call TableBase::reset to really reset all)
122  table->deactivate();
123  std::set<TableVersion> versions = table->getStoredVersions();
124  for(auto& version : versions)
125  if(!version.isTemporaryVersion()) // if not temporary
126  table->eraseView(version);
127  }
128 
129  if(dontFill)
130  return;
131 
132  // Note: assume new view becomes active view
133 
134  // take advantage of version possibly being cached
135  if(table->isStored(version))
136  {
137  //__COUT__ << "Using archived version: " << version << std::endl;
138 
139  // Make sure this version is not already active
140  if(!table->isActive() || version != table->getViewVersion())
141  table->setActiveView(version);
142 
143  table->getViewP()->setLastAccessTime();
144  return;
145  }
146 
147  try // to fill
148  {
149  if(version.isTemporaryVersion())
150  {
151  __SS__ << "FATAL ERROR: Can not use interface to fill a "
152  "table object with a temporary version!"
153  << std::endl;
154  ss << "FATAL ERROR: Invalid temporary version v" << version << std::endl;
155  __SS_THROW__;
156  }
157 
158  table->setupMockupView(version);
159  table->setActiveView(version);
160 
161  // loose column matching can be used to ignore column names
162  table->getViewP()->setLooseColumnMatching(looseColumnMatching);
163  fill(table, version);
164  if(looseColumnMatching)
165  table->getViewP()->setLooseColumnMatching(false);
166  table->getViewP()->setLastAccessTime();
167 
169  // verify the new view
170  if(table->getViewP()->getVersion() != version)
171  {
172  __COUT__ << "Version mismatch!! " << table->getViewP()->getVersion()
173  << " vs " << version << std::endl;
174  throw;
175  }
176 
177  // match key by ignoring '_'
178  bool nameIsMatch = true;
179  unsigned int nameIsMatchIndex, nameIsMatchStorageIndex;
180  for(nameIsMatchIndex = 0, nameIsMatchStorageIndex = 0;
181  nameIsMatchIndex < table->getViewP()->getTableName().size();
182  ++nameIsMatchIndex)
183  {
184  if(table->getMockupViewP()->getTableName()[nameIsMatchStorageIndex] ==
185  '_')
186  ++nameIsMatchStorageIndex; // skip to next storage character
187  if(table->getViewP()->getTableName()[nameIsMatchIndex] == '_')
188  continue; // skip to next character
189 
190  // match to storage name
191  if(nameIsMatchStorageIndex >=
192  table->getMockupViewP()->getTableName().size() ||
193  table->getViewP()->getTableName()[nameIsMatchIndex] !=
194  table->getMockupViewP()->getTableName()[nameIsMatchStorageIndex])
195  {
196  // size mismatch or character mismatch
197  nameIsMatch = false;
198  break;
199  }
200  ++nameIsMatchStorageIndex;
201  }
202 
203  if(nameIsMatch) // if name is considered match by above rule, then force
204  // matchup
205  table->getViewP()->setTableName(table->getMockupViewP()->getTableName());
206  else // table->getViewP()->getTableName() !=
207  // table->getMockupViewP()->getTableName())
208  {
209  __COUT__ << "View Table Name mismatch!! "
210  << table->getViewP()->getTableName() << " vs "
211  << table->getMockupViewP()->getTableName() << std::endl;
212  throw;
213  }
214  table->getViewP()
215  ->init(); // sanitize for column info (and possibly on dataType soon?)
216 
217  // at this point, view has been verified!
219  }
220  catch(...)
221  {
222  __COUT__ << "Error occurred while getting and filling Table \"" << tableName
223  << "\" version:" << version << std::endl;
224  __COUT__ << "\t-Configuration interface mode=" << theMode_ << std::endl;
225  throw;
226  }
227 
228  } // end get()
229 
230  // table handling
231  virtual std::set<std::string /*name*/> getAllTableNames() const
232  throw(std::runtime_error)
233  {
234  __SS__;
235  __THROW__(ss.str() +
236  "ConfigurationInterface::... Must only call "
237  "getAllTableNames in a mode with this functionality "
238  "implemented (e.g. DatabaseConfigurationInterface).");
239  }
240  virtual std::set<TableVersion> getVersions(const TableBase* configuration) const = 0;
241  const bool& getMode() const { return theMode_; }
242  TableVersion saveNewVersion(TableBase* configuration,
243  TableVersion temporaryVersion,
244  TableVersion newVersion = TableVersion());
245 
246  // group handling
247  virtual std::set<std::string /*name*/> getAllTableGroupNames(
248  const std::string& filterString = "") const throw(std::runtime_error)
249  {
250  __SS__;
251  __THROW__(ss.str() +
252  "ConfigurationInterface::... Must only call "
253  "getAllTableGroupNames in a mode with this functionality "
254  "implemented (e.g. DatabaseConfigurationInterface).");
255  }
256  virtual std::set<TableGroupKey> getKeys(const std::string& groupName) const
257  {
258  __SS__;
259  __THROW__(ss.str() +
260  "ConfigurationInterface::... Must only call "
261  "getKeys in a mode with this functionality "
262  "implemented (e.g. DatabaseConfigurationInterface).");
263  }
264 
265  // Caution: getTableGroupMembers must be carefully used.. the table versions
266  // are as initially defined for table versions aliases, i.e. not converted according
267  // to the metadata groupAliases!
268  virtual std::map<std::string /*name*/, TableVersion /*version*/> getTableGroupMembers(
269  std::string const& /*groupName*/, bool includeMetaDataTable = false) const
270  throw(std::runtime_error)
271  {
272  __SS__;
273  __THROW__(ss.str() +
274  "ConfigurationInterface::... Must only call "
275  "getTableGroupMembers in a mode with this functionality "
276  "implemented (e.g. DatabaseConfigurationInterface).");
277  }
278 
279  virtual void saveTableGroup(
280  std::map<std::string /*name*/,
281  TableVersion /*version*/> const& /*tableToVersionMap*/,
282  std::string const& /*groupName*/) const throw(std::runtime_error)
283  {
284  __SS__;
285  __THROW__(ss.str() +
286  "ConfigurationInterface::... Must only call "
287  "saveTableGroup in a mode with this functionality "
288  "implemented (e.g. DatabaseConfigurationInterface).");
289  };
290 
291  protected:
292  ConfigurationInterface(void); // Protected constructor
293 
294  virtual void fill(TableBase* configuration, TableVersion version) const = 0;
295 
296  public: // was protected,.. unfortunately, must be public to allow
297  // otsdaq_database_migrate and otsdaq_import_system_aliases to compile
298  virtual TableGroupKey findLatestGroupKey(
299  const std::string& groupName) const /* return INVALID if no existing versions */
300  {
301  __SS__;
302  __THROW__(ss.str() +
303  "ConfigurationInterface::... Must only call findLatestGroupKey in a "
304  "mode with this functionality implemented (e.g. "
305  "DatabaseConfigurationInterface).");
306  }
307  virtual TableVersion findLatestVersion(const TableBase* configuration)
308  const = 0; // return INVALID if no existing versions
309  virtual void saveActiveVersion(const TableBase* configuration,
310  bool overwrite = false) const = 0;
311 
312  protected:
313  ConfigurationHandlerBase* theConfigurationHandler_;
314 
315  private:
316  static ConfigurationInterface* theInstance_;
317  static bool theMode_; // 1 is FILE, 0 is artdaq-DB
318  static bool
319  theVersionTrackingEnabled_; // tracking versions 1 is enabled, 0 is disabled
320 };
321 
322 } // namespace ots
323 #endif