Belle II Software development
DataStore.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/datastore/DataStore.h>
10
11#include <framework/logging/Logger.h>
12#include <framework/datastore/RelationEntry.h>
13#include <framework/datastore/DependencyMap.h>
14#include <framework/dataobjects/RelationContainer.h>
15#include <framework/datastore/RelationIndex.h>
16#include <framework/datastore/RelationIndexManager.h>
17#include <framework/datastore/RelationsObject.h>
18#include <framework/datastore/StoreAccessorBase.h>
19#include <framework/dataobjects/EventExtraInfo.h>
20
21#include <TClonesArray.h>
22#include <TClass.h>
23
24#include <unordered_map>
25#include <algorithm>
26#include <cstdlib>
27
28using namespace std;
29using namespace Belle2;
30
31namespace {
37 void cleanDataStore()
38 {
40 }
41
45 void fixAbsorbObjects(TClonesArray* from, TClonesArray* to)
46 {
47 to->AbsorbObjects(from, 0, from->GetEntriesFast() - 1);
48 }
49}
50
51bool DataStore::s_DoCleanup = false;
52
54{
55 static DataStore instance;
56 return instance;
57}
58
59
60DataStore::DataStore() : m_initializeActive(true), m_dependencyMap(new DependencyMap)
61{
62}
63
65{
66 if (s_DoCleanup) {
67 //release all memory in data store
68 reset();
69 }
70 delete m_dependencyMap;
71}
72
74{
75 B2DEBUG(31, "DataStore::reset(): Removing all elements from DataStore");
76 m_initializeActive = true;
78
79 for (int i = 0; i < c_NDurabilityTypes; i++)
81
83}
84
86{
87 m_storeEntryMap.reset(durability);
88
89 //invalidate any cached relations (expect RelationArrays to remain valid)
91}
92
94{
95 m_initializeActive = active;
96
97 static bool firstCall = true;
98 if (firstCall) {
99 atexit(cleanDataStore);
100 firstCall = false;
101 }
102}
103
104TClass* DataStore::getTClassFromDefaultObjectName(const std::string& objectName)
105{
106 // First look for an name without the namespace Belle2::
107 TClass* cl = TClass::GetClass(("Belle2::" + objectName).c_str());
108 if (not cl) {
109 // If this fails look for a name that already has the full namespace.
110 cl = TClass::GetClass(objectName.c_str());
111 }
112 return cl;
113}
114
115TClass* DataStore::getTClassFromDefaultArrayName(const std::string& arrayName)
116{
117 if (arrayName.empty()) {
118 return nullptr;
119 } else if ('s' == arrayName.back()) {
120 std::string objectName = arrayName.substr(0, arrayName.size() - 1);
122 } else {
123 return nullptr;
124 }
125}
126
127std::string DataStore::defaultObjectName(const std::string& classname)
128{
129 const static string gfclass = "genfit::Track";
130 const static string gfobjectname = "GF2Track";
131 if (classname == gfclass)
132 return gfobjectname;
133 //Strip qualifiers like namespaces
134 size_t colon = classname.rfind(':');
135 if (colon != std::string::npos) {
136 return classname.substr(colon + 1);
137 }
138 return classname;
139}
140
141
142std::string DataStore::defaultObjectName(const TClass* t)
143{
144 B2ASSERT("Cannot deduce default object name from null pointer TClass", t);
145 const std::string s = defaultObjectName(t->GetName());
146 return s;
147}
148
149
150std::string DataStore::objectName(const TClass* t, const std::string& name)
151{
152 return ((name.empty()) ? defaultObjectName(t) : name);
153}
154
155
156std::string DataStore::defaultArrayName(const TClass* t)
157{
158 const std::string s = defaultArrayName(defaultObjectName(t));
159 return s;
160}
161
162
163std::string DataStore::arrayName(const TClass* t, const std::string& name)
164{
165 return ((name.empty()) ? defaultArrayName(t) : name);
166}
167
168
169bool DataStore::checkType(const StoreEntry& entry, const StoreAccessorBase& accessor) const
170{
171 // Check whether the existing entry and the requested object are both arrays or both single objects
172 const char* entryType = (entry.isArray) ? "array" : "object";
173 if (entry.isArray != accessor.isArray()) {
174 B2FATAL("Existing entry '" << entry.name << "' is an " << entryType << " and the requested one an " << ((
175 accessor.isArray()) ? "array" : "object"));
176 }
177
178 // Check whether the existing entry has the same type
179 const TClass* entryClass = entry.objClass;
180 if (!entryClass->InheritsFrom(accessor.getClass())) {
181 B2FATAL("Existing " << accessor.readableName() << " of type " << entryClass->GetName() << " doesn't match requested type " <<
182 accessor.getClass()->GetName());
183 }
184
185 return true;
186}
187
188
189bool DataStore::registerEntry(const std::string& name, EDurability durability,
190 TClass* objClass, bool array, EStoreFlags storeFlags)
191{
192 const StoreAccessorBase accessor(name, durability, objClass, array);
193 // Check whether this method is called in the initialization phase
194 if (!m_initializeActive) {
195 B2ERROR("Attempt to register " << accessor.readableName() <<
196 " outside of the initialization phase. Please move calls to registerInDataStore() into your Module's initialize() function.");
197 return false;
198 }
199 const bool dontwriteout = storeFlags & c_DontWriteOut;
200
201 //add to current module's outputs
202 m_dependencyMap->getCurrentModuleInfo().addEntry(name, DependencyMap::c_Output, (objClass == RelationContainer::Class()));
203
204 // Check whether the map entry already exists
205 const auto& it = m_storeEntryMap[durability].find(name);
206 if (it != m_storeEntryMap[durability].end()) {
207 StoreEntry& entry = it->second;
208
209 // Complain about existing entry
210 if (storeFlags & c_ErrorIfAlreadyRegistered) {
211 B2ERROR("An " << accessor.readableName() << " of type " << entry.object->ClassName() <<
212 " was already registered before. (Multiple calls to registerInDataStore() are fine if the c_ErrorIfAlreadyRegistered flag is not set. For objects you will want to make sure that you don't discard existing data from other modules in that case.");
213 return false;
214 }
215
216 // Check whether the types match
217 if (!checkType(entry, accessor)) return false;
218
219 // Check whether the persistency type matches
220 if (entry.dontWriteOut != dontwriteout) {
221 B2WARNING("Existing " << accessor.readableName() << " has different persistency type than requested. Changing to " <<
222 (dontwriteout ? "c_DontWriteOut" : "c_WriteOut") << ".");
223 entry.dontWriteOut = dontwriteout;
224 }
225
226 B2DEBUG(100, "An " << accessor.readableName() << " was registered once more.");
227 return true;
228 }
229
230 // check reserved names
231 if (array and name == "ALL") {
232 B2ERROR("Creating an array with the reserved name 'ALL' is not allowed!");
233 return false;
234 }
235
236 // Add the DataStore entry
237 m_storeEntryMap[durability][name] = StoreEntry(array, objClass, name, dontwriteout);
238
239 B2DEBUG(100, "Successfully registered " << accessor.readableName());
240 return true;
241}
242
243bool DataStore::registerRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
244 EStoreFlags storeFlags, const std::string& namedRelation)
245{
246 if (!fromArray.isArray())
247 B2FATAL(fromArray.readableName() << " is not an array!");
248 if (!toArray.isArray())
249 B2FATAL(toArray.readableName() << " is not an array!");
250
251 // check the the namedRelation only contains regular characters
252 if (!std::regex_match(namedRelation, m_regexNamedRelationCheck))
253 B2FATAL("Named Relations can only contain alphabetic characters, given was: " << namedRelation);
254
255 const std::string& relName = relationName(fromArray.getName(), toArray.getName(), namedRelation);
256 /*
257 if ((fromArray.notWrittenOut() or toArray.notWrittenOut()) and !(storeFlags & c_DontWriteOut)) {
258 B2WARNING("You're trying to register a persistent relation " << relName << " from/to an array which is not written out (DataStore::c_DontWriteOut flag)! Relation will also not be saved!");
259 storeFlags |= c_DontWriteOut;
260 }
261 */
262
263 if (fromArray.getDurability() > durability or toArray.getDurability() > durability) {
264 B2FATAL("Tried to create a relation '" << relName << "' with a durability larger than the StoreArrays it relates");
265 }
266
267 return DataStore::Instance().registerEntry(relName, durability, RelationContainer::Class(), false, storeFlags);
268}
269
270bool DataStore::hasRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
271 const std::string& namedRelation)
272{
273 // check that the input makes sense
274 if (!fromArray.isArray())
275 B2FATAL(fromArray.readableName() << " is not an array!");
276 if (!toArray.isArray())
277 B2FATAL(toArray.readableName() << " is not an array!");
278
279 // check the the namedRelation only contains regular characters
280 if (!std::regex_match(namedRelation, m_regexNamedRelationCheck))
281 B2FATAL("Named Relations can only contain alphabetic characters, given was: " << namedRelation);
282
283 // get the internal relation name from the name provided
284 const std::string& realname = relationName(fromArray.getName(), toArray.getName(), namedRelation);
285
286 // check whether the map entry exists
287 const auto& it = m_storeEntryMap[durability].find(realname);
288 if (it != m_storeEntryMap[durability].end()) return true;
289
290 return false;
291}
292
294{
295 const auto& it = m_storeEntryMap[accessor.getDurability()].find(accessor.getName());
296
297 if (it != m_storeEntryMap[accessor.getDurability()].end() and checkType((it->second), accessor)) {
298 return &(it->second);
299 } else {
300 return nullptr;
301 }
302}
303
304
305TObject** DataStore::getObject(const StoreAccessorBase& accessor)
306{
307 StoreEntry* entry = getEntry(accessor);
308 if (!entry) {
309 return nullptr;
310 }
311 return &(entry->ptr);
312}
313
314
315bool DataStore::createObject(TObject* object, bool replace, const StoreAccessorBase& accessor)
316{
317 StoreEntry* entry = getEntry(accessor);
318 if (!entry) {
319 B2ERROR("No " << accessor.readableName() <<
320 " exists in the DataStore, did you forget to register it in your Module's initialize() function? Note: direct accesses to it will crash!");
321 return false;
322 }
323
324 if (entry->ptr && !replace && object != entry->object) {
325 B2ERROR("An " << accessor.readableName() << " was already created in the DataStore.");
326 return false;
327 }
328
329 if (object) {
330 if (object != entry->object) {
331 delete entry->object;
332 entry->object = object;
333 }
334 entry->ptr = entry->object;
335 } else {
336 entry->recreate();
337 }
338
339 return true;
340}
341
343{
344 StoreEntry* fromEntry = getEntry(from);
345 StoreEntry* toEntry = getEntry(to);
346 if (!fromEntry)
347 B2FATAL("No " << from.readableName() << " exists in the DataStore!");
348 if (!toEntry)
349 B2FATAL("No " << to.readableName() << " exists in the DataStore!");
350 if (from.isArray() != to.isArray() or from.getClass() != to.getClass())
351 B2FATAL("cannot replace " << to.readableName() << " with " << from.readableName() << " (incompatible types)!");
352
353 if (!fromEntry->ptr) {
354 //since we don't need to move any data, just invalidate toEntry instead.
355 toEntry->ptr = nullptr;
356 } else if (fromEntry->isArray) {
357 if (!toEntry->ptr)
358 toEntry->ptr = toEntry->object;
359 toEntry->getPtrAsArray()->Delete();
360
361 fixAbsorbObjects(fromEntry->getPtrAsArray(), toEntry->getPtrAsArray());
363 } else if (fromEntry->objClass == RelationContainer::Class()) {
364 if (!toEntry->ptr)
365 toEntry->ptr = toEntry->object;
366 auto* fromRel = static_cast<RelationContainer*>(fromEntry->ptr);
367 auto* toRel = static_cast<RelationContainer*>(toEntry->ptr);
368
369 toRel->elements().Delete();
370
371 fixAbsorbObjects(&fromRel->elements(), &toRel->elements());
372
373 //indices need a rebuild
374 fromRel->setModified(true);
375 toRel->setModified(true);
376 } else {
377 delete toEntry->object;
378
379 toEntry->object = fromEntry->ptr->Clone();
380 toEntry->ptr = toEntry->object;
381
382 fromEntry->ptr = nullptr;
383 }
384}
385
387{
388 const TClonesArray* array = static_cast<TClonesArray*>(entry.ptr);
389 const int nEntries = array->GetEntriesFast();
390 for (int i = 0; i < nEntries; i++) {
391 auto* relobj = static_cast<RelationsObject*>(array->At(i));
392 relobj->m_cacheArrayIndex = i;
393 relobj->m_cacheDataStoreEntry = &entry;
394 }
395}
396
397bool DataStore::findStoreEntry(const TObject* object, DataStore::StoreEntry*& entry, int& index)
398{
399 if (!entry or index < 0) {
400 //usually entry/index should be passed for RelationsObject,
401 //but there are exceptions -> let's check again
402 const auto* relObj = dynamic_cast<const RelationsObject*>(object);
403 if (relObj) {
404 entry = relObj->m_cacheDataStoreEntry;
405 index = relObj->m_cacheArrayIndex;
406 }
407 }
408 // check whether the cached information is (still) valid
409 if (entry && entry->ptr && (index >= 0)) {
410 const TClonesArray* array = static_cast<TClonesArray*>(entry->ptr);
411 if (array->At(index) == object) return true;
412 B2INFO("findStoreEntry: cached index invalid, probably harmless but odd : " << entry->name << " idx " << index);
413 index = array->IndexOf(object);
414 if (index >= 0) return true;
415 B2INFO("findStoreEntry: cached entry was also wrong");
416 }
417 entry = nullptr;
418 index = -1;
419
420 //searching for nullptr should be safe
421 if (!object)
422 return false;
423
424 // search for the object and set the entry and index
425 const TClass* objectClass = object->IsA();
426 for (auto& mapEntry : m_storeEntryMap[c_Event]) {
427 if (mapEntry.second.ptr && mapEntry.second.isArray) {
428 const TClass* arrayClass = mapEntry.second.objClass;
429 if (arrayClass != objectClass)
430 continue;
431
432 const TClonesArray* array = static_cast<TClonesArray*>(mapEntry.second.ptr);
433 if (object == array->Last()) {
434 //quickly find entry if it's at the end of the array
435 index = array->GetLast();
436 } else {
437 if (arrayClass->InheritsFrom(RelationsObject::Class())) {
438 //update cache for entire array
439 updateRelationsObjectCache(mapEntry.second);
440
441 //if found, m_cacheArrayIndex is now correct, otherwise still -1
442 StoreEntry* objEntry = static_cast<const RelationsObject*>(object)->m_cacheDataStoreEntry;
443 index = static_cast<const RelationsObject*>(object)->m_cacheArrayIndex;
444 if (index >= 0 and objEntry) {
445 //if the cache of 'object' is filled, make sure to also set entry!
446 entry = objEntry;
447 return true;
448 }
449 } else {
450 //not a RelationsObject, so no caching
451 index = array->IndexOf(object);
452 }
453 }
454
455 if (index >= 0) {
456 entry = &mapEntry.second;
457 return true;
458 }
459 }
460 }
461 return false;
462}
463
464const std::vector<std::string>& DataStore::getArrayNames(const std::string& name, const TClass* arrayClass,
465 EDurability durability) const
466{
467 static vector<string> arrayNames;
468 arrayNames.clear();
469 if (name.empty()) {
470 static std::unordered_map<const TClass*, string> classToArrayName;
471 const auto& it = classToArrayName.find(arrayClass);
472 if (it != classToArrayName.end()) {
473 arrayNames.emplace_back(it->second);
474 } else {
475 const std::string& result = defaultArrayName(arrayClass->GetName());
476 classToArrayName[arrayClass] = result;
477 arrayNames.emplace_back(result);
478 }
479 } else if (name == "ALL") {
480 for (auto& mapEntry : m_storeEntryMap[durability]) {
481 if (mapEntry.second.object and mapEntry.second.isArray and mapEntry.second.objClass->InheritsFrom(arrayClass)) {
482 arrayNames.emplace_back(mapEntry.second.name);
483 }
484 }
485 } else {
486 arrayNames.emplace_back(name);
487 }
488 return arrayNames;
489}
490
491void DataStore::addRelation(const TObject* fromObject, StoreEntry*& fromEntry, int& fromIndex, const TObject* toObject,
492 StoreEntry*& toEntry, int& toIndex, float weight, const std::string& namedRelation)
493{
494 if (!fromObject or !toObject)
495 return;
496
497 // get entry from which the relation points
498 if (!findStoreEntry(fromObject, fromEntry, fromIndex)) {
499 B2FATAL("Couldn't find from-side entry for relation between " << fromObject->ClassName() << " and " << toObject->ClassName() <<
500 ". Please make sure the object is part of a StoreArray before adding a relation.");
501 }
502
503 // get entry to which the relation points
504 if (!findStoreEntry(toObject, toEntry, toIndex)) {
505 B2FATAL("Couldn't find to-side entry for relation between " << fromObject->ClassName() << " and " << toObject->ClassName() <<
506 ". Please make sure the object is part of a StoreArray before adding a relation.");
507 }
508
509 // get the relations from -> to
510 const string& relationsName = relationName(fromEntry->name, toEntry->name, namedRelation);
511 const StoreEntryIter& it = m_storeEntryMap[c_Event].find(relationsName);
512 if (it == m_storeEntryMap[c_Event].end()) {
513 B2FATAL("No relation '" << relationsName <<
514 "' found. Please register it (using StoreArray::registerRelationTo()) before trying to add relations.");
515 }
516 StoreEntry* entry = &(it->second);
517
518 // auto create relations if needed (both if null pointer, or uninitialised object read from TTree)
519 if (!entry->ptr)
520 entry->recreate();
521 auto* relContainer = static_cast<RelationContainer*>(entry->ptr);
522 if (relContainer->isDefaultConstructed()) {
523 relContainer->setFromName(fromEntry->name);
524 relContainer->setFromDurability(c_Event);
525 relContainer->setToName(toEntry->name);
526 relContainer->setToDurability(c_Event);
527 }
528
529 // add relation
530 TClonesArray& relations = relContainer->elements();
531 new (relations.AddrAt(relations.GetLast() + 1)) RelationElement(fromIndex, toIndex, weight);
532
533 std::shared_ptr<RelationIndexContainer<TObject, TObject>> relIndex =
534 RelationIndexManager::Instance().getIndexIfExists<TObject, TObject>(relationsName, c_Event);
535 if (relIndex) {
536 // add it to index (so we avoid expensive rebuilding later)
537 relIndex->index().emplace(fromIndex, toIndex, fromObject, toObject, weight);
538 } else {
539 //mark for rebuilding later on
540 relContainer->setModified(true);
541 }
542}
543
545 int& index, const TClass* withClass, const std::string& withName, const std::string& namedRelation)
546{
547 if (searchSide == c_BothSides) {
548 auto result = getRelationsWith(c_ToSide, object, entry, index, withClass, withName, namedRelation);
549 const auto& fromResult = getRelationsWith(c_FromSide, object, entry, index, withClass, withName, namedRelation);
550 result.add(fromResult);
551 return result;
552 }
553
554 std::vector<RelationEntry> result;
555
556 // get StoreEntry for 'object'
557 if (!findStoreEntry(object, entry, index)) return RelationVectorBase();
558
559 // get names of store arrays to search
560 const std::vector<string>& names = getArrayNames(withName, withClass);
561 vector<string> relationNames;
562
563 // loop over found store arrays
564 for (const std::string& name : names) {
565 // get the relations from -> to
566 const string& relationsName = (searchSide == c_ToSide) ? relationName(entry->name, name, namedRelation) : relationName(name,
567 entry->name, namedRelation);
568 RelationIndex<TObject, TObject> relIndex(relationsName, c_Event);
569 if (!relIndex)
570 continue;
571
572 const size_t prevsize = result.size();
573
574 //get relations with object
575 if (searchSide == c_ToSide) {
576 for (const auto& rel : relIndex.getElementsFrom(object)) {
577 auto* const toObject = const_cast<TObject*>(rel.to);
578 if (toObject)
579 result.emplace_back(toObject, rel.weight);
580 }
581 } else {
582 for (const auto& rel : relIndex.getElementsTo(object)) {
583 auto* const fromObject = const_cast<TObject*>(rel.from);
584 if (fromObject)
585 result.emplace_back(fromObject, rel.weight);
586 }
587 }
588
589 if (result.size() != prevsize)
590 relationNames.push_back(relationsName);
591 }
592
593 return RelationVectorBase(entry->name, index, result, relationNames);
594}
595
596RelationEntry DataStore::getRelationWith(ESearchSide searchSide, const TObject* object, DataStore::StoreEntry*& entry, int& index,
597 const TClass* withClass, const std::string& withName, const std::string& namedRelation)
598{
599 if (searchSide == c_BothSides) {
600 RelationEntry result = getRelationWith(c_ToSide, object, entry, index, withClass, withName, namedRelation);
601 if (!result.object) {
602 result = getRelationWith(c_FromSide, object, entry, index, withClass, withName, namedRelation);
603 }
604 return result;
605 }
606
607 // get StoreEntry for 'object'
608 if (!findStoreEntry(object, entry, index)) return RelationEntry(nullptr);
609
610 // get names of store arrays to search
611 const std::vector<string>& names = getArrayNames(withName, withClass);
612
613 // loop over found store arrays
614 for (const std::string& name : names) {
615 // get the relations from -> to
616 const string& relationsName = (searchSide == c_ToSide) ? relationName(entry->name, name, namedRelation) : relationName(name,
617 entry->name, namedRelation);
618 RelationIndex<TObject, TObject> relIndex(relationsName, c_Event);
619 if (!relIndex)
620 continue;
621
622 // get first element
623 if (searchSide == c_ToSide) {
624 const RelationIndex<TObject, TObject>::Element* element = relIndex.getFirstElementFrom(object);
625 if (element && element->to) {
626 return RelationEntry(const_cast<TObject*>(element->to), element->weight);
627 }
628 } else {
629 const RelationIndex<TObject, TObject>::Element* element = relIndex.getFirstElementTo(object);
630 if (element && element->from) {
631 return RelationEntry(const_cast<TObject*>(element->from), element->weight);
632 }
633 }
634 }
635
636 return RelationEntry(nullptr);
637}
638
639std::vector<std::string> DataStore::getListOfRelatedArrays(const StoreAccessorBase& array) const
640{
641 std::vector<std::string> arrays;
642 if (!array.isArray()) {
643 B2ERROR("getListOfRelatedArrays(): " << array.readableName() << " is not an array!");
644 return arrays;
645 }
646
647 //loop over all arrays
648 EDurability durability = array.getDurability();
649 for (auto& mapEntry : m_storeEntryMap[durability]) {
650 if (mapEntry.second.isArray) {
651 const std::string& name = mapEntry.second.name;
652
653 //check both from & to 'array'
654 for (int searchSide = 0; searchSide < c_BothSides; searchSide++) {
655 const string& relationsName = (searchSide == c_ToSide) ? relationName(array.getName(), name) : relationName(name, array.getName());
656 const StoreEntryConstIter& it = m_storeEntryMap[durability].find(relationsName);
657 if (it != m_storeEntryMap[durability].end())
658 arrays.emplace_back(name);
659 }
660 }
661 }
662
663 return arrays;
664}
665std::vector<std::string> DataStore::getListOfArrays(const TClass* arrayClass, EDurability durability) const
666{
667 return getArrayNames("ALL", arrayClass, durability);
668}
669
670std::vector<std::string> DataStore::getListOfObjects(const TClass* objClass, EDurability durability) const
671{
672 vector<string> list;
674 for (const auto& entrypair : map) {
675 if (!entrypair.second.isArray) {
676 const TObject* obj = entrypair.second.object;
677 if (dynamic_cast<const RelationContainer*>(obj))
678 continue; //ignore relations in list
679
680 if (obj and obj->IsA()->InheritsFrom(objClass))
681 list.emplace_back(entrypair.first);
682 }
683 }
684 return list;
685}
686
687std::vector<std::string> DataStore::getListOfRelations(EDurability durability) const
688{
689 vector<string> list;
691 for (const auto& entrypair : map) {
692 if (!entrypair.second.isArray) {
693 const TObject* obj = entrypair.second.object;
694 if (dynamic_cast<const RelationContainer*>(obj))
695 list.emplace_back(entrypair.first);
696
697 }
698 }
699 return list;
700}
701
702std::vector<std::string> DataStore::getSortedListOfDataStore(EDurability durability) const
703{
704 std::vector<string> list;
705 std::vector<std::string> mergeContent = getListOfObjects(TObject::Class(), durability);
706 list.insert(std::end(list), std::begin(mergeContent), std::end(mergeContent));
707 mergeContent = getListOfArrays(TObject::Class(), durability);
708 list.insert(std::end(list), std::begin(mergeContent), std::end(mergeContent));
709 mergeContent = getListOfRelations(durability);
710 list.insert(std::end(list), std::begin(mergeContent), std::end(mergeContent));
711 return list;
712}
713
715{
716 B2DEBUG(100, "Invalidating objects for durability " << durability);
719}
720
722{
723 if (m_initializeActive) {
725 (accessor.getClass() == RelationContainer::Class()));
726 } else {
727 B2FATAL("Attempt to require input " << accessor.readableName() <<
728 " outside of the initialization phase. Please move isRequired() calls into your Module's initialize() function.");
729 }
730
731 if (!getEntry(accessor)) {
732 B2ERROR("The required " << accessor.readableName() << " does not exist. Maybe you forgot the module that registers it?");
733 return false;
734 }
735 return true;
736}
737
739{
740 if (m_initializeActive) {
742 (accessor.getClass() == RelationContainer::Class()));
743 }
744
745 return (getEntry(accessor) != nullptr);
746}
747
748bool DataStore::requireRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
749 std::string const& namedRelation)
750{
751 if (!m_initializeActive) {
752 B2FATAL("Attempt to require relation " << fromArray.readableName() << " -> " << toArray.readableName() <<
753 " outside of the initialization phase. Please move requireRelationTo() calls into your Module's initialize() function.");
754 }
755
756 if (!fromArray.isArray())
757 B2FATAL(fromArray.readableName() << " is not an array!");
758 if (!toArray.isArray())
759 B2FATAL(toArray.readableName() << " is not an array!");
760
761 const std::string& relName = relationName(fromArray.getName(), toArray.getName(), namedRelation);
762 return DataStore::Instance().requireInput(StoreAccessorBase(relName, durability, RelationContainer::Class(), false));
763}
764
765bool DataStore::optionalRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
766 std::string const& namedRelation)
767{
768 if (!fromArray.isArray())
769 B2FATAL(fromArray.readableName() << " is not an array!");
770 if (!toArray.isArray())
771 B2FATAL(toArray.readableName() << " is not an array!");
772
773 const std::string& relName = relationName(fromArray.getName(), toArray.getName(), namedRelation);
774 return DataStore::Instance().optionalInput(StoreAccessorBase(relName, durability, RelationContainer::Class(), false));
775}
776
777
778void DataStore::createNewDataStoreID(const std::string& id)
779{
781}
782
783void DataStore::createEmptyDataStoreID(const std::string& id)
784{
786}
787
788std::string DataStore::currentID() const
789{
790 return m_storeEntryMap.currentID();
791}
792
793void DataStore::switchID(const std::string& id)
794{
795 if (id == m_storeEntryMap.currentID())
796 return;
797
798 //remember to clear caches
800
802}
803
804void DataStore::copyEntriesTo(const std::string& id, const std::vector<std::string>& entrylist_event, bool mergeEntries)
805{
806 m_storeEntryMap.copyEntriesTo(id, entrylist_event, mergeEntries);
807}
808
809void DataStore::copyContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
810{
811 m_storeEntryMap.copyContentsTo(id, entrylist_event);
812}
813
814void DataStore::mergeContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
815{
816 m_storeEntryMap.mergeContentsTo(id, entrylist_event);
817}
818
819
820DataStore::SwitchableDataStoreContents::SwitchableDataStoreContents():
821 m_entries(1)
822{
823 m_idToIndexMap[""] = 0;
824}
825
827{
828 //does this id already exist?
829 if (m_idToIndexMap.count(id) > 0)
830 return;
831
832 copyEntriesTo(id);
833 //copy actual contents, fixing pointers
834 copyContentsTo(id);
835}
836
838{
839 //does this id already exist?
840 if (m_idToIndexMap.count(id) > 0)
841 return;
842
843 int targetidx = m_entries.size();
844 m_idToIndexMap[id] = targetidx;
845
846 m_entries.push_back(DataStoreContents());
847}
848
849void DataStore::SwitchableDataStoreContents::copyEntriesTo(const std::string& id, const std::vector<std::string>& entrylist_event,
850 bool mergeEntries)
851{
852 std::vector<std::string> entrylist;
853 if (entrylist_event.size() == 1 and entrylist_event.at(0) == "ALL") {
855 } else {
856 entrylist = entrylist_event;
857 }
858
859 if (mergeEntries) {
860 // Make sure that EventMetaData is always merged
861 if (std::find(entrylist.begin(), entrylist.end(), "EventMetaData") == entrylist.end()) {
862 entrylist.push_back("EventMetaData");
863 B2INFO("It is required to merge the 'EventMetaData' for consistency. Added.");
864 }
865 }
866
867 //collect the entries for which we do not have to fix duplicate pointers
868 std::vector<std::string> skipEntries;
869
870 int targetidx;
871 if (m_idToIndexMap.count(id) == 0) {
872 //new DataStore & full copy
873 if (!entrylist.empty())
874 B2FATAL("entrlylist_event given for new DS id. This shouldn't happen, report to framework author.");
875 targetidx = m_entries.size();
876 m_idToIndexMap[id] = targetidx;
877
878 //copy entries
879 m_entries.push_back(m_entries[m_currentIdx]);
880 } else if (!entrylist.empty()) {
881 targetidx = m_idToIndexMap.at(id);
882 // if we are merging DataStores, we need to register a new object that stores at which indices the arrays have been merged
883 if (mergeEntries) {
884 if (m_entries[targetidx][c_Event].count("MergedArrayIndices") != 0) {
885 B2FATAL("MergedArrayIndices already exists. This should not happen.");
886 }
887 m_entries[targetidx][c_Event]["MergedArrayIndices"] = StoreEntry(false, EventExtraInfo::Class(), "MergedArrayIndices", false);
888 }
889 for (std::string& entryname : entrylist) {
890 //copy only given entries (in c_Event)
891 if (m_entries[m_currentIdx][c_Event].count(entryname) == 0) {
892 continue;
893 }
894 if (m_entries[targetidx][c_Event].count(entryname) != 0) {
895 if (mergeEntries) {
896 // Skip Store-Arrays and Relations..
897 if (m_entries[targetidx][c_Event][entryname].isArray
898 or m_entries[targetidx][c_Event][entryname].objClass == RelationContainer::Class()) { //do nothing
899 // ..but not Store-Objects
900 } else {
901 // We have to create a new StoreEntry as the name of the key in the map changes
902 if (m_entries[targetidx][c_Event].count(entryname + "_indepPath") != 0) {
903 B2FATAL(entryname + "_indepPath already exists. This should not happen.");
904 }
905 m_entries[targetidx][c_Event][entryname + "_indepPath"] = StoreEntry(false, m_entries[targetidx][c_Event][entryname].objClass,
906 entryname + "_indepPath", m_entries[targetidx][c_Event][entryname].dontWriteOut);
907 }
908 skipEntries.push_back(entryname);
909 continue;
910 } else {
911 B2WARNING("Independent path: entry '" << entryname << "' already exists in DataStore '" << id <<
912 "'! This will likely break something.");
913 }
914 } else {
915 m_entries[targetidx][c_Event][entryname] = m_entries[m_currentIdx][c_Event][entryname];
916 }
917 }
918 } else {
919 B2FATAL("no entrlylist_event given, not new DS id. This shouldn't happen, report to framework author.");
920 }
921
922 //fix duplicate pointers
923 for (int iDurability = 0; iDurability < c_NDurabilityTypes; iDurability++) {
924 for (auto& entrypair : m_entries[targetidx][iDurability]) {
925 if (not entrypair.second.object)
926 B2FATAL("createNewDataStoreID(): object '" << entrypair.first << " already null (this should never happen).");
927 if (!entrylist.empty()) {
928 //skip all entries of other durabilities
929 if (iDurability != c_Event)
930 continue;
931 //skip all entries not found in entrylist
932 if (std::find(entrylist.begin(), entrylist.end(), entrypair.first) == entrylist.end())
933 continue;
934 //don't fix the ownership for these
935 if (std::find(skipEntries.begin(), skipEntries.end(), entrypair.first) != skipEntries.end())
936 continue;
937 }
938
939 entrypair.second.object = nullptr; //remove duplicate ownership
940 entrypair.second.ptr = nullptr;
941 }
942 }
943}
944
945void DataStore::SwitchableDataStoreContents::copyContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
946{
947 int targetidx = m_idToIndexMap.at(id);
948 auto& targetMaps = m_entries[targetidx];
949 const auto& sourceMaps = m_entries[m_currentIdx];
950
951 for (int iDurability = 0; iDurability < c_NDurabilityTypes; iDurability++) {
952 for (const auto& entrypair : sourceMaps[iDurability]) {
953 const StoreEntry& fromEntry = entrypair.second;
954 //does this exist in target?
955 if (targetMaps[iDurability].count(fromEntry.name) == 0) {
956 continue;
957 }
958
959 if (!entrylist_event.empty()) {
960 //skip all entries of other durabilities
961 if (iDurability != c_Event)
962 continue;
963 //skip all entries not found in entrylist_event
964 if (std::find(entrylist_event.begin(), entrylist_event.end(), fromEntry.name) == entrylist_event.end())
965 continue;
966 }
967
968 StoreEntry& target = targetMaps[iDurability][fromEntry.name];
969
970 //copy contents into target object
971 if (not fromEntry.ptr) {
972 if (!target.object)
973 target.recoverFromNullObject();
974 target.ptr = nullptr;
975 } else {
976 //TODO there is some optimisation opportunity here, e.g. by only cloning the entries of a TClonesArray instead of the array itself
977 delete target.object;
978 target.object = fromEntry.object->Clone();
979 target.ptr = target.object;
980 }
981 }
982 }
983
984}
985
986void DataStore::SwitchableDataStoreContents::mergeContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
987{
988 if (entrylist_event.empty()) {
989 B2WARNING("Nothing to merge. Returning.");
990 return;
991 }
992
993 std::vector<std::string> entrylist;
994 if (entrylist_event.size() == 1 and entrylist_event.at(0) == "ALL") {
996 } else {
997 entrylist = entrylist_event;
998 }
999
1000 int targetidx = m_idToIndexMap.at(id);
1001 auto& targetMaps = m_entries[targetidx];
1002 const auto& sourceMaps = m_entries[m_currentIdx];
1003
1004 // we need to know the length of the original StoreArrays in order to fix the Relations
1005 if (targetMaps[c_Event].count("MergedArrayIndices") == 0) {
1006 B2FATAL("Did not find MergedArrayIndices in target. This should not happen.");
1007 }
1008 StoreEntry& target_arrayIndices = targetMaps[c_Event]["MergedArrayIndices"];
1009 target_arrayIndices.recreate();
1010 EventExtraInfo* arrayIndices = static_cast<EventExtraInfo*>(target_arrayIndices.ptr);
1011
1012 // we have to go through the list in this order to make sure StoreArrays are merged before their Relations
1013 for (std::string nextEntry : entrylist) {
1014 for (const auto& entrypair : sourceMaps[c_Event]) {
1015 const StoreEntry& fromEntry = entrypair.second;
1016 if (fromEntry.name != nextEntry) {
1017 continue;
1018 }
1019
1020 //does this exist in target?
1021 if (targetMaps[c_Event].count(fromEntry.name) == 0) {
1022 continue;
1023 }
1024
1025 StoreEntry& target = targetMaps[c_Event][fromEntry.name];
1026
1027 //copy contents into target object
1028 if (!fromEntry.ptr) {
1029 if (!target.object) {
1030 target.recoverFromNullObject();
1031 target.ptr = nullptr;
1032 } else {
1033 // keep the content as it is before merging and indicate this by the index
1034 if (target.isArray) {
1035 arrayIndices->addExtraInfo(target.name, target.getPtrAsArray()->GetEntriesFast());
1036 }
1037 }
1038 } else {
1039 // array-type object
1040 if (target.isArray) {
1041 if (!target.ptr) {
1042 target.object = fromEntry.object->Clone();
1043 target.ptr = target.object;
1044
1045 arrayIndices->addExtraInfo(target.name, 0);
1046 } else {
1047 if (target.objClass != fromEntry.objClass) {
1048 B2FATAL("Cannot merge StoreArrays " << target.name << "as they are of different classes.");
1049 }
1050
1051 arrayIndices->addExtraInfo(target.name, target.getPtrAsArray()->GetEntriesFast());
1052
1053 if (fromEntry.getPtrAsArray()->GetEntriesFast() == 0) {
1054 continue;
1055 }
1056
1057 // TClonesArray has no easy way to add objects to it
1058 // Instead work around this by cloning and absorbing the TClonesArray `fromEntry`
1059 // Also use `fixAbsorbObjects` define in this file to work around some potential memory leak
1060 // TODO: check if clone makes sense? or should we rather move the whole obj to avoid memleaks?
1061 TClonesArray* fromArr = static_cast<TClonesArray*>(fromEntry.getPtrAsArray()->Clone());
1062 fixAbsorbObjects(fromArr, target.getPtrAsArray());
1063
1064 // update the cache
1066 delete fromArr;
1067 }
1068 } else {
1069 if (!target.ptr) {
1070 target.object = fromEntry.object->Clone();
1071 target.ptr = target.object;
1072 } else {
1073 // relation-type object
1074 if (fromEntry.objClass == RelationContainer::Class()) {
1075 auto* fromRelContainer = static_cast<RelationContainer*>(fromEntry.ptr);
1076 if (fromRelContainer->isDefaultConstructed()) {
1077 continue;
1078 }
1079
1080 if (fromRelContainer->getEntries() == 0) {
1081 continue;
1082 }
1083
1084 const std::string& fromName = fromRelContainer->getFromName();
1085 const std::string& toName = fromRelContainer->getToName();
1086
1087 auto* targetRelContainer = static_cast<RelationContainer*>(target.ptr);
1088 if (not arrayIndices->hasExtraInfo(fromName) || not arrayIndices->hasExtraInfo(toName)) {
1089 B2WARNING("Skipping merging of relation " << fromEntry.name
1090 << ". The StoreArrays " << fromName << " and " << toName << " have to be merged before.");
1091 // clear relation just to make sure nobody actually uses it
1092 targetRelContainer->Clear();
1093 continue;
1094 }
1095
1096 // Make sure everything is properly initialized
1097 if (targetRelContainer->isDefaultConstructed()) {
1098 targetRelContainer->setFromName(fromName);
1099 targetRelContainer->setFromDurability(c_Event);
1100 targetRelContainer->setToName(toName);
1101 targetRelContainer->setToDurability(c_Event);
1102 }
1103
1104 // add relation
1105 TClonesArray& relations = targetRelContainer->elements();
1106 // The fast way would be to add the relation also to the RelationIndexManager (this is a cache for relations)
1107 // However, it seems to have some issues with the switching of the DataStore
1108 // (it simply uses the name of the relation for the mapping, but it exists twice..)
1109 // Instead, force rebuilding of the cache later
1110
1111 for (int i = 0; i < fromRelContainer->getEntries(); i++) {
1112 const RelationElement& rel = fromRelContainer->getElement(i);
1113 unsigned int fromIndex = arrayIndices->hasExtraInfo(fromName) ? rel.getFromIndex() + arrayIndices->getExtraInfo(fromName) : -1;
1114
1115 for (size_t rel_idx = 0; rel_idx < rel.getSize(); rel_idx++) {
1116 unsigned int toIndex = arrayIndices->hasExtraInfo(toName) ? rel.getToIndex(rel_idx) + arrayIndices->getExtraInfo(toName) : -1;
1117 float weight = rel.getWeight(rel_idx);
1118 new (relations.AddrAt(relations.GetLast() + 1)) RelationElement(fromIndex, toIndex, weight);
1119 }
1120 }
1121
1122 // as mentioned above, rebuild of cache
1123 targetRelContainer->setModified(true);
1124
1125 // simple object (cannot be merged, instead keep both)
1126 } else {
1127 std::string nameRenamed = fromEntry.name + "_indepPath";
1128 if (targetMaps[c_Event].count(nameRenamed) == 0) {
1129 B2FATAL("Did not find " << nameRenamed << " in target. This should not happen.");
1130 }
1131 StoreEntry& target_renamed = targetMaps[c_Event][nameRenamed];
1132 target_renamed.object = fromEntry.object->Clone();
1133 target_renamed.ptr = target_renamed.object;
1134 }
1135 }
1136 }
1137 }
1138 }
1139 }
1140
1141}
1142
1144{
1145 //switch
1146 m_currentID = id;
1147 m_currentIdx = m_idToIndexMap.at(id);
1148
1149 if ((unsigned int)m_currentIdx >= m_entries.size())
1150 B2FATAL("out of bounds in SwitchableDataStoreContents::switchID(): " << m_currentIdx << " >= size " << m_entries.size());
1151}
1152
1154{
1155 for (int i = 0; i < c_NDurabilityTypes; i++)
1156 reset((EDurability)i);
1157
1158 m_entries.clear();
1159 m_entries.resize(1);
1160 m_idToIndexMap.clear();
1161 m_idToIndexMap[""] = 0;
1162 m_currentID = "";
1163 m_currentIdx = 0;
1164}
1165
1167{
1168 for (auto& map : m_entries) {
1169 for (auto& mapEntry : map[durability]) {
1170 delete mapEntry.second.object;
1171 }
1172 map[durability].clear();
1173 }
1174}
1175
1177{
1178 for (auto& map : m_entries)
1179 for (auto& mapEntry : map[durability])
1180 mapEntry.second.invalidate();
1181}
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
Definition: DataStore.cc:826
void createEmptyDataStoreID(const std::string &id)
creates empty datastore with given id.
Definition: DataStore.cc:837
void copyEntriesTo(const std::string &id, const std::vector< std::string > &entrylist_event={}, bool mergeEntries=false)
copy entries (not contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:849
void switchID(const std::string &id)
switch to DataStore with given ID.
Definition: DataStore.cc:1143
std::map< std::string, int > m_idToIndexMap
Maps DataStore ID to index in m_entries.
Definition: DataStore.h:616
void mergeContentsTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
merge contents (actual array / object contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:986
const std::string & currentID() const
returns ID of current DataStore.
Definition: DataStore.h:603
void copyContentsTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
copy contents (actual array / object contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:945
void clear()
same as calling reset() for all durabilities + all non-default datastore IDs are removed.
Definition: DataStore.cc:1153
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:1166
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
Definition: DataStore.cc:1176
In the store you can park objects that have to be accessed by various modules.
Definition: DataStore.h:51
static std::string objectName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition: DataStore.cc:150
StoreEntryMap::const_iterator StoreEntryConstIter
const_iterator for a StoreEntry map.
Definition: DataStore.h:89
std::array< StoreEntryMap, c_NDurabilityTypes > DataStoreContents
StoreEntry maps for each durability.
Definition: DataStore.h:90
std::vector< std::string > getListOfRelatedArrays(const StoreAccessorBase &array) const
Returns a list of names of arrays which have registered relations that point to or from 'array'.
Definition: DataStore.cc:639
std::vector< std::string > getListOfRelations(EDurability durability) const
Returns a list of names of StoreObjPtr-objects whose class is (or inherits from) RelationContainer.
Definition: DataStore.cc:687
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
Definition: DataStore.cc:778
void createEmptyDataStoreID(const std::string &id)
creates empty datastore with given id.
Definition: DataStore.cc:783
bool findStoreEntry(const TObject *object, StoreEntry *&entry, int &index)
Find an object in an array in the data store.
Definition: DataStore.cc:397
const std::vector< std::string > & getArrayNames(const std::string &arrayName, const TClass *arrayClass, EDurability durability=c_Event) const
Returns a vector with the names of store arrays matching the given name and class.
Definition: DataStore.cc:464
void copyEntriesTo(const std::string &id, const std::vector< std::string > &entrylist_event={}, bool mergeEntries=false)
copy entries (not contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:804
static std::string defaultObjectName()
Return the default storage name for an object of the given type.
Definition: DataStore.h:127
bool checkType(const StoreEntry &entry, const StoreAccessorBase &accessor) const
Check whether the given entry and the requested class match.
Definition: DataStore.cc:169
bool optionalRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, std::string const &namedRelation)
Register the given relation as an optional input.
Definition: DataStore.cc:765
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:69
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
void switchID(const std::string &id)
switch to DataStore with given ID.
Definition: DataStore.cc:793
std::vector< std::string > getSortedListOfDataStore(EDurability durability) const
Returns a (sorted) list of all the content of the DataStore (Objs-Arrays-Relations).
Definition: DataStore.cc:702
StoreEntryMap::iterator StoreEntryIter
Iterator for a StoreEntry map.
Definition: DataStore.h:88
const std::regex m_regexNamedRelationCheck
Regular expression to check that no special characters and no white spaces are in the string given fo...
Definition: DataStore.h:634
static TClass * getTClassFromDefaultArrayName(const std::string &arrayName)
Tries to deduce the TClass from a default array name, which is generally the name of the C++ class wi...
Definition: DataStore.cc:115
void mergeContentsTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
merge contents (actual array / object contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:814
void addRelation(const TObject *fromObject, StoreEntry *&fromEntry, int &fromIndex, const TObject *toObject, StoreEntry *&toEntry, int &toIndex, float weight, const std::string &namedRelation)
Add a relation from an object in a store array to another object in a store array.
Definition: DataStore.cc:491
bool registerRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, EStoreFlags storeFlags, const std::string &namedRelation)
Register a relation in the DataStore map.
Definition: DataStore.cc:243
static TClass * getTClassFromDefaultObjectName(const std::string &objectName)
Tries to deduce the TClass from a default object name, which is generally the name of the C++ class.
Definition: DataStore.cc:104
DataStore()
Hidden constructor, as it is a singleton.
Definition: DataStore.cc:60
DependencyMap * m_dependencyMap
Collect information about the dependencies between modules.
Definition: DataStore.h:637
~DataStore()
Destructor.
Definition: DataStore.cc:64
static std::string defaultArrayName()
Return the default storage name for an array of the given type.
Definition: DataStore.h:157
std::vector< std::string > getListOfArrays(const TClass *arrayClass, EDurability durability) const
Returns a list of names of arrays which are of type (or inherit from) arrayClass.
Definition: DataStore.cc:665
ESearchSide
Which side of relations should be returned?
Definition: DataStore.h:76
@ c_BothSides
Combination of c_FromSide and c_ToSide.
Definition: DataStore.h:79
@ c_FromSide
Return relations/objects pointed from (to a given object).
Definition: DataStore.h:77
@ c_ToSide
Return relations/objects pointed to (from a given object).
Definition: DataStore.h:78
StoreEntryMap & getStoreEntryMap(EDurability durability)
Get a reference to the object/array map.
Definition: DataStore.h:325
static void updateRelationsObjectCache(StoreEntry &entry)
For an array containing RelationsObjects, update index and entry cache for entire contents.
Definition: DataStore.cc:386
static const int c_NDurabilityTypes
Number of Durability Types.
Definition: DataStore.h:63
std::vector< std::string > getListOfObjects(const TClass *objClass, EDurability durability) const
Returns a list of names of StoreObjPtr-objects whose class is (or inherits from) objClass.
Definition: DataStore.cc:670
void copyContentsTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
copy contents (actual array / object contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:809
bool requireInput(const StoreAccessorBase &accessor)
Produce ERROR message if no entry of the given type is registered in the DataStore.
Definition: DataStore.cc:721
EDurability
Durability types.
Definition: DataStore.h:58
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
Belle2::StoreEntry StoreEntry
Wraps a stored array/object, stored under unique (name, durability) key.
Definition: DataStore.h:84
bool requireRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, std::string const &namedRelation)
Produce ERROR message if no relation of given durability exists between fromArray and toArray (in tha...
Definition: DataStore.cc:748
std::string currentID() const
returns ID of current DataStore.
Definition: DataStore.cc:788
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:53
bool hasRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, const std::string &namedRelation)
Check for the existence of a relation in the DataStore map.
Definition: DataStore.cc:270
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:93
static std::string relationName(const std::string &fromName, const std::string &toName, std::string const &namedRelation="")
Return storage name for a relation between two arrays of the given names.
Definition: DataStore.h:180
static bool s_DoCleanup
Global flag to to decide if we can do normal cleanup.
Definition: DataStore.h:100
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:85
void reset()
Clears contents of the datastore (all durabilities)
Definition: DataStore.cc:73
StoreEntry * getEntry(const StoreAccessorBase &accessor)
Check whether an entry with the correct type is registered in the DataStore map and return it.
Definition: DataStore.cc:293
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
Definition: DataStore.cc:714
RelationVectorBase getRelationsWith(ESearchSide searchSide, const TObject *object, StoreEntry *&entry, int &index, const TClass *withClass, const std::string &withName, const std::string &namedRelation)
Get the relations between an object and other objects in a store array.
Definition: DataStore.cc:544
Belle2::RelationEntry getRelationWith(ESearchSide searchSide, const TObject *object, StoreEntry *&entry, int &index, const TClass *withClass, const std::string &withName, const std::string &namedRelation)
Get the first relation between an object and another object in a store array.
Definition: DataStore.cc:596
bool createObject(TObject *object, bool replace, const StoreAccessorBase &accessor)
Create a new object/array in the DataStore or add an existing one.
Definition: DataStore.cc:315
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
Definition: DataStore.cc:305
static std::string arrayName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition: DataStore.cc:163
bool m_initializeActive
True if modules are currently being initialized.
Definition: DataStore.h:628
bool registerEntry(const std::string &name, EDurability durability, TClass *objClass, bool array, EStoreFlags storeFlags)
Register an entry in the DataStore map.
Definition: DataStore.cc:189
bool optionalInput(const StoreAccessorBase &accessor)
Register the given object/array as an optional input.
Definition: DataStore.cc:738
SwitchableDataStoreContents m_storeEntryMap
Maps (name, durability) key to StoreEntry objects.
Definition: DataStore.h:621
void replaceData(const StoreAccessorBase &from, const StoreAccessorBase &to)
For two StoreAccessors of same type, move all data in 'from' into 'to', discarding previous contents ...
Definition: DataStore.cc:342
std::map< std::string, StoreEntry > StoreEntryMap
Map for StoreEntries.
Definition: DataStore.h:87
Collect information about the dependencies between modules.
Definition: DependencyMap.h:29
@ c_Input
required input.
Definition: DependencyMap.h:33
@ c_Output
registered output.
Definition: DependencyMap.h:35
@ c_OptionalInput
optional input.
Definition: DependencyMap.h:34
ModuleInfo & getCurrentModuleInfo()
Get info for current module.
Definition: DependencyMap.h:63
void clear()
Reset all collected data.
Definition: DependencyMap.h:69
Class to stores ExtraInfo of the whole event.
float getExtraInfo(const std::string &name) const
Return given value if set.
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
Class to store relations between StoreArrays in the DataStore.
const std::string & getFromName() const
Get name of the StoreArray we relate from.
void setFromName(const std::string &name)
Set name of the StoreArray we relate from.
TClonesArray & elements()
Get reference to the elements.
Class to store a single element of a relation.
index_type getFromIndex() const
Get index we point from.
index_type getToIndex(size_t n=0) const
Get nth index we point to.
size_t getSize() const
Get number of indices we points to.
weight_type getWeight(size_t n=0) const
Get nth weight we point to.
std::shared_ptr< RelationIndexContainer< FROM, TO > > getIndexIfExists(const std::string &name, DataStore::EDurability durability) const
if the index exists in the cache, it is returned; otherwise NULL.
static RelationIndexManager & Instance()
Returns the singleton instance.
void clear(DataStore::EDurability durability=DataStore::c_Event)
Clear the cache of RelationIndexContainers with the given durability.
void reset()
Reset the cache completely, that is clear all caches and don't even keep the Index objects around.
Provides access to fast ( O(log n) ) bi-directional lookups on a specified relation.
Definition: RelationIndex.h:76
const Element * getFirstElementFrom(const FROM &from) const
Return a pointer to the first relation Element of the given object.
range_from getElementsFrom(const FROM *from) const
Return a range of all elements pointing from the given object.
const Element * getFirstElementTo(const TO &to) const
Return a pointer to the first relation Element of the given object.
range_to getElementsTo(const TO *to) const
Return a range of all elements pointing to the given object.
base class for RelationVector<T>
Defines interface for accessing relations of objects in StoreArray.
int m_cacheArrayIndex
Cache of the index in the TClonesArray to which this object belongs.
Base class for StoreObjPtr and StoreArray for easier common treatment.
DataStore::EDurability getDurability() const
Return durability with which the object is saved in the DataStore.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
std::string readableName() const
Convert this accessor into a readable string (for messages).
TClass * getClass() const
The underlying object's type.
bool isArray() const
Is this an accessor for an array?
Abstract base class for different kinds of events.
STL namespace.
void addEntry(const std::string &name, EEntryType type, bool isRelation)
Adds given entry/relation.
Struct for relations.
Definition: RelationEntry.h:24
Wraps a stored array/object, stored under unique (name, durability) key.
Definition: StoreEntry.h:22
TObject * ptr
The pointer to the returned object, either equal to 'object' or null, depending on whether the object...
Definition: StoreEntry.h:51
TClonesArray * getPtrAsArray() const
Return ptr cast to TClonesArray.
Definition: StoreEntry.cc:83
bool dontWriteOut
Flag that indicates whether the object should be written to the output by default.
Definition: StoreEntry.h:40
TObject * object
The pointer to the actual object.
Definition: StoreEntry.h:48
bool isArray
Flag that indicates whether the object is a TClonesArray.
Definition: StoreEntry.h:39
std::string name
Name of the entry.
Definition: StoreEntry.h:53
void recreate()
Reset stored object to defaults, set ptr to new object.
Definition: StoreEntry.cc:68
TClass * objClass
class of object.
Definition: StoreEntry.h:41