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 <boost/none.hpp>
14
15#include <TClass.h>
16
17namespace Belle2 {
24 {
25 reset();
26 }
27
29 {
30 static DBStore instance;
31 return instance;
32 }
33
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, query.globaltag, *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, query.globaltag, *m_storeEvent);
73 }
74 if (dbEntry.isIntraRunDependent()) m_intraRunDependencies.insert(&dbEntry);
75 }
76 return &dbEntry;
77 }
78
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 = std::nullopt;
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
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, query.globaltag, event);
138 if (dbEntry.isIntraRunDependent()) m_intraRunDependencies.insert(&dbEntry);
139 }
140 }
141
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
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");
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)
192 m_storeEvent = event;
193 m_manualEvent = std::nullopt;
194 }
195
196 std::set<std::string> DBStore::getAllEntryNames()
197 {
198 std::set<std::string> s{};
199 for (auto& [key, value] : m_dbEntries)
200 s.emplace(key);
201 return s;
202 };
203
204 void DBStore::addConstantOverride(const std::string& name, TObject* obj, bool oneRun)
205 {
207 if (oneRun) {
208 int exp, run;
209 if (m_manualEvent) {
210 exp = m_manualEvent->getExperiment();
211 run = m_manualEvent->getRun();
212 } else {
213 exp = m_storeEvent->getExperiment();
214 run = m_storeEvent->getRun();
215 }
216 iov = IntervalOfValidity(exp, run, exp, run);
217 }
218 // Add the DBStore entry
219 auto iter = m_dbEntries.find(name);
220 if (iter == end(m_dbEntries)) {
221 iter = m_dbEntries.emplace(name, DBStoreEntry::fromObject(name, obj, true)).first;
222 }
223 DBStoreEntry& dbEntry = iter->second;
224 dbEntry.overrideObject(obj, iov);
225 // we need to remove this entry from the intraRunDependencies list now.
226 // Otherwise it will reset the object on the next event call
227 m_intraRunDependencies.erase(&dbEntry);
228 B2WARNING("An override for DBEntry " << name << " was created.");
229 }
230
232} // 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:169
bool isRequired() const
check whether this payload is required for operation
Definition: DBStoreEntry.h:115
Singleton class to cache database objects.
Definition: DBStore.h:31
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
@ 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:96
void reset(bool keepEntries=false)
Invalidate all payloads.
Definition: DBStore.cc:177
void initialize(const EDatabaseState target=c_Ready)
Initialize the database connection settings on first use.
Definition: Database.cc:197
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:23
std::pair< TObject *, IntervalOfValidity > getData(const EventMetaData &event, const std::string &name)
Request an object from the database.
Definition: Database.cc:72
void performUpdateEvent(const EventMetaData &event)
The main code that does an updateEvent.
Definition: DBStore.cc:169
static Database & Instance()
Instance of a singleton Database.
Definition: Database.cc:42
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28
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:108
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:34
void updateEvent()
Updates all intra-run dependent objects.
Definition: DBStore.cc:142
void update()
Updates all objects that are outside their interval of validity.
Definition: DBStore.cc:79
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:37
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:204
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:196
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.
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