Belle II Software development
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
15namespace Belle2 {
20
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 = std::nullopt;
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");
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 = std::nullopt;
192 }
193
194 std::set<std::string> DBStore::getAllEntryNames()
195 {
196 std::set<std::string> s{};
197 for (auto& [key, value] : m_dbEntries)
198 s.emplace(key);
199 return s;
200 };
201
202 void DBStore::addConstantOverride(const std::string& name, TObject* obj, bool oneRun)
203 {
205 if (oneRun) {
206 int exp, run;
207 if (m_manualEvent) {
208 exp = m_manualEvent->getExperiment();
209 run = m_manualEvent->getRun();
210 } else {
211 exp = m_storeEvent->getExperiment();
212 run = m_storeEvent->getRun();
213 }
214 iov = IntervalOfValidity(exp, run, exp, run);
215 }
216 // Add the DBStore entry
217 auto iter = m_dbEntries.find(name);
218 if (iter == end(m_dbEntries)) {
219 iter = m_dbEntries.emplace(name, DBStoreEntry::fromObject(name, obj, true)).first;
220 }
221 DBStoreEntry& dbEntry = iter->second;
222 dbEntry.overrideObject(obj, iov);
223 // we need to remove this entry from the intraRunDependencies list now.
224 // Otherwise it will reset the object on the next event call
225 m_intraRunDependencies.erase(&dbEntry);
226 B2WARNING("An override for DBEntry " << name << " was created.");
227 }
228
230} // namespace Belle2
Class to hold one entry from the ConditionsDB in the DBStore.
EPayloadType
Possible Store entry types.
bool isIntraRunDependent() const
return whether or not the payload might change even during the run
void require()
Change status of this payload to required.
bool isRequired() const
check whether this payload is required for operation
StoreObjPtr< EventMetaData > m_storeEvent
StoreObjPtr for the EventMetaData to get the current experiment and run from the DataStore.
Definition DBStore.h:174
std::set< DBStoreEntry * > m_intraRunDependencies
List of intra-run dependent conditions.
Definition DBStore.h:169
std::optional< EventMetaData > m_manualEvent
Optional EventMetaData variable.
Definition DBStore.h:181
std::unordered_map< std::string, DBStoreEntry > m_dbEntries
Map names to DBEntry objects.
Definition DBStore.h:166
DBStore()
Hidden constructor, as it is a singleton.
Definition DBStore.h:151
@ c_InitGlobaltagList
Globaltag list has been finalized metadata providers not and globaltags are not checked for usability...
Definition Database.h:49
Conditions::PayloadMetadata DBQuery
Struct for bulk read queries.
Definition Database.h:72
Store event, run, and experiment numbers.
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:96
STL class.
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.
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition DBStore.cc:202
std::set< std::string > getAllEntryNames()
Return the names of all the payloads stored in the database at the time of this function is called.
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...
Abstract base class for different kinds of events.
IntervalOfValidity iov
the interval of validity
std::string globaltag
Name of the globaltag this payload was taken from.
std::string checksum
digest (checksum) of the payload
std::string filename
full filename to the payload file
size_t revision
the revision of the payload