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 {
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.
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: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:37
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...
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