otsdaq  v2_04_01
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  {
233  __SS__;
234  __THROW__(ss.str() +
235  "ConfigurationInterface::... Must only call "
236  "getAllTableNames in a mode with this functionality "
237  "implemented (e.g. DatabaseConfigurationInterface).");
238  }
239  virtual std::set<TableVersion> getVersions(const TableBase* configuration) const = 0;
240  const bool& getMode() const { return theMode_; }
241  TableVersion saveNewVersion(TableBase* configuration,
242  TableVersion temporaryVersion,
243  TableVersion newVersion = TableVersion());
244 
245  // group handling
246  virtual std::set<std::string /*name*/> getAllTableGroupNames(
247  const std::string& filterString = "") const
248  {
249  __SS__;
250  __THROW__(ss.str() +
251  "ConfigurationInterface::... Must only call "
252  "getAllTableGroupNames in a mode with this functionality "
253  "implemented (e.g. DatabaseConfigurationInterface).");
254  }
255  virtual std::set<TableGroupKey> getKeys(const std::string& groupName) const
256  {
257  __SS__;
258  __THROW__(ss.str() +
259  "ConfigurationInterface::... Must only call "
260  "getKeys in a mode with this functionality "
261  "implemented (e.g. DatabaseConfigurationInterface).");
262  }
263 
264  // Caution: getTableGroupMembers must be carefully used.. the table versions
265  // are as initially defined for table versions aliases, i.e. not converted according
266  // to the metadata groupAliases!
267  virtual std::map<std::string /*name*/, TableVersion /*version*/> getTableGroupMembers(
268  std::string const& /*groupName*/, bool includeMetaDataTable = false) const
269  {
270  __SS__;
271  __THROW__(ss.str() +
272  "ConfigurationInterface::... Must only call "
273  "getTableGroupMembers in a mode with this functionality "
274  "implemented (e.g. DatabaseConfigurationInterface).");
275  }
276 
277  virtual void saveTableGroup(
278  std::map<std::string /*name*/,
279  TableVersion /*version*/> const& /*tableToVersionMap*/,
280  std::string const& /*groupName*/) const
281  {
282  __SS__;
283  __THROW__(ss.str() +
284  "ConfigurationInterface::... Must only call "
285  "saveTableGroup in a mode with this functionality "
286  "implemented (e.g. DatabaseConfigurationInterface).");
287  };
288 
289  protected:
290  ConfigurationInterface(void); // Protected constructor
291 
292  virtual void fill(TableBase* configuration, TableVersion version) const = 0;
293 
294  public: // was protected,.. unfortunately, must be public to allow
295  // otsdaq_database_migrate and otsdaq_import_system_aliases to compile
296  virtual TableGroupKey findLatestGroupKey(
297  const std::string& groupName) const /* return INVALID if no existing versions */
298  {
299  __SS__;
300  __THROW__(ss.str() +
301  "ConfigurationInterface::... Must only call findLatestGroupKey in a "
302  "mode with this functionality implemented (e.g. "
303  "DatabaseConfigurationInterface).");
304  }
305  virtual TableVersion findLatestVersion(const TableBase* configuration)
306  const = 0; // return INVALID if no existing versions
307  virtual void saveActiveVersion(const TableBase* configuration,
308  bool overwrite = false) const = 0;
309 
310  protected:
311  ConfigurationHandlerBase* theConfigurationHandler_;
312 
313  private:
314  static ConfigurationInterface* theInstance_;
315  static bool theMode_; // 1 is FILE, 0 is artdaq-DB
316  static bool
317  theVersionTrackingEnabled_; // tracking versions 1 is enabled, 0 is disabled
318 };
319 
320 } // namespace ots
321 #endif