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