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