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