Belle II Software  release-06-02-00
DBStore.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/database/DBStore.h>
10 #include <framework/database/Database.h>
11 #include <framework/logging/Logger.h>
12 
13 #include <TClass.h>
14 
15 namespace Belle2 {
22  {
23  reset();
24  }
25 
27  {
28  static DBStore instance;
29  return instance;
30  }
31 
33  const TClass* objClass, bool array, bool required)
34  {
35  // Check whether the map entry already exists
36  const auto& entry = m_dbEntries.find(name);
37  if (entry != m_dbEntries.end()) {
38  DBStoreEntry& dbEntry = entry->second;
39 
40  // Check whether the types match
41  if (!dbEntry.checkType(type, objClass, array)) return nullptr;
42 
43  B2DEBUG(39, "DBEntry " << name << " was requested once more.");
44  if (required && !dbEntry.isRequired()) {
45  dbEntry.require();
46  B2DEBUG(34, "DBEntry " << name << " is now required");
47  }
48  return &dbEntry;
49  }
50 
51  // Add the DBStore entry
52  const auto iter = m_dbEntries.emplace(name, DBStoreEntry{type, name, objClass, array, required});
53  DBStoreEntry& dbEntry = iter.first->second;
54  B2DEBUG(34, "DBEntry " << name << " was created (" << (required ? "required" : "optional") << ")");
55 
56  // If no object was obtained from the database yet, but it should be available, get it
57 
58  // Check if we have a non-DataStore event to use
59  if (m_manualEvent) {
60  Database::DBQuery query(name, required);
61  if (Database::Instance().getData(*m_manualEvent, query)) {
62  dbEntry.updatePayload(query.revision, query.iov, query.filename, query.checksum, query.globaltag, *m_manualEvent);
63  }
64  if (dbEntry.isIntraRunDependent()) m_intraRunDependencies.insert(&dbEntry);
65  }
66  // Otherwise use the DataStore if it is valid
67  else if (m_storeEvent.isValid()) {
68  Database::DBQuery query(name, required);
69  if (Database::Instance().getData(*m_storeEvent, query)) {
70  dbEntry.updatePayload(query.revision, query.iov, query.filename, query.checksum, query.globaltag, *m_storeEvent);
71  }
72  if (dbEntry.isIntraRunDependent()) m_intraRunDependencies.insert(&dbEntry);
73  }
74  return &dbEntry;
75  }
76 
78  {
79  if (m_dbEntries.empty()) {
80  // make sure we at least fix the list of globaltags on the first time
82  return;
83  }
84 
85  // Make sure our EventMetaData pointer is reconnected as it could get
86  // disconnected if the DataStore is reset.
87  // TODO: This can be removed once BII-1262 is fixed.
89  m_storeEvent = event;
90  // Clear the m_manualEvent to indicate that we now want to use the DataStore event numbers
91  m_manualEvent = boost::none;
93  }
94 
95  void DBStore::update(const EventMetaData& event)
96  {
97  if (m_dbEntries.empty()) {
98  // make sure we at least fix the list of globaltags on the first time
100  return;
101  }
102  m_manualEvent = event;
104  }
105 
107  {
108  // For the time being we will request updates for all payloads just to make
109  // sure we never miss an update. This is done once per run so it should be
110  // fine from performance.
111  // TODO: once we are sure somehow to not have duplicate iovs we can relax
112  // this requirement.
113  std::vector<Database::DBQuery> entries;
114  entries.reserve(m_dbEntries.size());
115  for (auto& entry : m_dbEntries) {
116  bool expired = !entry.second.getIoV().contains(event);
117  if (expired) {
118  B2DEBUG(34, "DBEntry " << entry.first << " out of date, will need update");
119  }
120  if (!entry.second.keepUntilExpired() || expired)
121  entries.emplace_back(entry.first, entry.second.isRequired());
122  // remove from intra run handling, will be added again after update if needed.
123  m_intraRunDependencies.erase(&entry.second);
124  }
125 
126  // nothing to update
127  if (entries.empty()) return;
128 
129  // Request new objects and IoVs from database
130  Database::Instance().getData(event, entries);
131 
132  // Update DBStore entries
133  for (auto& query : entries) {
134  auto& dbEntry = m_dbEntries.find(query.name)->second;
135  dbEntry.updatePayload(query.revision, query.iov, query.filename, query.checksum, query.globaltag, event);
136  if (dbEntry.isIntraRunDependent()) m_intraRunDependencies.insert(&dbEntry);
137  }
138  }
139 
141  {
142  if (!m_manualEvent) {
144  } else {
145  B2WARNING("DBStore is currently using manual event information. But you are asking for the DataStore's EventMetaData "
146  "to be used to update the Intra-run dependencies. Update could not proceed. "
147  "Did you forget to call DBStore::Instance().update() before calling this function?");
148  }
149  }
150 
151  void DBStore::updateEvent(const unsigned int eventNumber)
152  {
153  // As m_manualEvent doesn't use the DataStore, it isn't automatically updated and we must manually update the event
154  // number prior to updating the intra-run objects.
155  // This also updates it ready for getData if a DBObject gets constructed later.
156  if (m_manualEvent) {
157  m_manualEvent->setEvent(eventNumber);
159  } else {
160  B2WARNING("DBStore is not currently using manual event information. But you are asking for the event number to be set "
161  " to a custom value. Update of the Intra-run dependencies could not proceed. "
162  "Did you forget to call DBStore::Instance().update(event), or accidentally call DBStore::Instance().update() "
163  "prior to to this?");
164  }
165  }
166 
168  {
169  // loop over intra-run dependent conditions and update the objects if needed
170  for (auto& dbEntry : m_intraRunDependencies) {
171  dbEntry->updateObject(event);
172  }
173  }
174 
175  void DBStore::reset(bool keepEntries)
176  {
177  if (!m_dbEntries.empty())
178  B2DEBUG(31, "DBStore::reset(): Cleaning all database information");
179  m_intraRunDependencies.clear();
180  if (!keepEntries) {
181  m_dbEntries.clear();
182  } else {
183  for (auto& entry : m_dbEntries) {
184  entry.second.resetPayload();
185  }
186  }
187  // Make sure our EventMetaData pointer is reconnected on next access ...
188  // because probably this is after resetting the DataStore (BII-1262)
190  m_storeEvent = event;
191  m_manualEvent = boost::none;
192  }
193 
194  void DBStore::addConstantOverride(const std::string& name, TObject* obj, bool oneRun)
195  {
197  if (oneRun) {
198  int exp, run;
199  if (m_manualEvent) {
200  exp = m_manualEvent->getExperiment();
201  run = m_manualEvent->getRun();
202  } else {
203  exp = m_storeEvent->getExperiment();
204  run = m_storeEvent->getRun();
205  }
206  iov = IntervalOfValidity(exp, run, exp, run);
207  }
208  // Add the DBStore entry
209  auto iter = m_dbEntries.find(name);
210  if (iter == end(m_dbEntries)) {
211  iter = m_dbEntries.emplace(name, DBStoreEntry::fromObject(name, obj, true)).first;
212  }
213  DBStoreEntry& dbEntry = iter->second;
214  dbEntry.overrideObject(obj, iov);
215  // we need to remove this entry from the intraRunDependencies list now.
216  // Otherwise it will reset the object on the next event call
217  m_intraRunDependencies.erase(&dbEntry);
218  B2WARNING("An override for DBEntry " << name << " was created.");
219  }
220 
222 } // namespace Belle2
Class to hold one entry from the ConditionsDB in the DBStore.
Definition: DBStoreEntry.h:47
EPayloadType
Possible Store entry types.
Definition: DBStoreEntry.h:50
bool isIntraRunDependent() const
return whether or not the payload might change even during the run
Definition: DBStoreEntry.h:119
void require()
Change status of this payload to required.
Definition: DBStoreEntry.h:167
bool isRequired() const
check whether this payload is required for operation
Definition: DBStoreEntry.h:115
Singleton class to cache database objects.
Definition: DBStore.h:32
StoreObjPtr< EventMetaData > m_storeEvent
StoreObjPtr for the EventMetaData to get the current experiment and run from the DataStore.
Definition: DBStore.h:168
boost::optional< EventMetaData > m_manualEvent
Optional EventMetaData variable.
Definition: DBStore.h:175
std::set< DBStoreEntry * > m_intraRunDependencies
List of intra-run dependent conditions.
Definition: DBStore.h:163
std::unordered_map< std::string, DBStoreEntry > m_dbEntries
Map names to DBEntry objects.
Definition: DBStore.h:160
@ c_InitGlobaltagList
Globaltag list has been finalized metadata providers not and globaltags are not checked for usability...
Definition: Database.h:49
Store event, run, and experiment numbers.
Definition: EventMetaData.h:33
A class that describes the interval of experiments/runs for which an object in the database is valid.
static IntervalOfValidity always()
Function that returns an interval of validity that is always valid, c.f.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
void reset(bool keepEntries=false)
Invalidate all payloads.
Definition: DBStore.cc:175
void initialize(const EDatabaseState target=c_Ready)
Initialize the database connection settings on first use.
Definition: Database.cc:196
bool checkType(const TObject *object) const
Check if a given TObject instance is compatible with the type of this entry.
~DBStore()
Destructor.
Definition: DBStore.cc:21
std::pair< TObject *, IntervalOfValidity > getData(const EventMetaData &event, const std::string &name)
Request an object from the database.
Definition: Database.cc:71
void performUpdateEvent(const EventMetaData &event)
The main code that does an updateEvent.
Definition: DBStore.cc:167
static Database & Instance()
Instance of a singleton Database.
Definition: Database.cc:41
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:26
void performUpdate(const EventMetaData &event)
The main code that does an update, factored out so it can be used by both update and update(event).
Definition: DBStore.cc:106
void overrideObject(TObject *obj, const IntervalOfValidity &iov)
Set an override object in case we want to use a different object then actually provided by the databa...
DBStoreEntry * getEntry(DBStoreEntry::EPayloadType payloadType, const std::string &name, const TClass *objClass, bool array, bool required=true)
Returns the entry with the requested name in the DBStore.
Definition: DBStore.cc:32
void updateEvent()
Updates all intra-run dependent objects.
Definition: DBStore.cc:140
void update()
Updates all objects that are outside their interval of validity.
Definition: DBStore.cc:77
static DBStoreEntry fromObject(const std::string &name, const TObject *obj, bool isRequired)
Construct a new DBStoreEntry with a requested name and an object directly.
Definition: DBStoreEntry.cc:38
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:194
void updatePayload(unsigned int revision, const IntervalOfValidity &iov, const std::string &filename, const std::string &checksum, const std::string &globaltag, const EventMetaData &event)
Update the payload information for this entry and if appropriate open the new file and extract the ob...
Definition: DBStoreEntry.cc:83
Abstract base class for different kinds of events.
Simple struct to group all information necessary for a single payload.