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