9 #include <framework/datastore/DataStore.h>
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>
20 #include <TClonesArray.h>
23 #include <unordered_map>
38 DataStore::Instance().reset();
44 void fixAbsorbObjects(TClonesArray* from, TClonesArray* to)
46 to->AbsorbObjects(from, 0, from->GetEntriesFast() - 1);
50 bool DataStore::s_DoCleanup =
false;
59 DataStore::DataStore() : m_initializeActive(true), m_dependencyMap(new
DependencyMap)
74 B2DEBUG(31,
"DataStore::reset(): Removing all elements from DataStore");
96 static bool firstCall =
true;
98 atexit(cleanDataStore);
106 TClass* cl = TClass::GetClass((
"Belle2::" +
objectName).c_str());
128 const static string gfclass =
"genfit::Track";
129 const static string gfobjectname =
"GF2Track";
130 if (classname == gfclass)
133 size_t colon = classname.rfind(
':');
134 if (colon != std::string::npos) {
135 return classname.substr(colon + 1);
143 B2ASSERT(
"Cannot deduce default object name from null pointer TClass", t);
171 const char* entryType = (entry.
isArray) ?
"array" :
"object";
173 B2FATAL(
"Existing entry '" << entry.
name <<
"' is an " << entryType <<
" and the requested one an " << ((
174 accessor.
isArray()) ?
"array" :
"object"));
178 const TClass* entryClass = entry.
objClass;
179 if (!entryClass->InheritsFrom(accessor.
getClass())) {
180 B2FATAL(
"Existing " << accessor.
readableName() <<
" of type " << entryClass->GetName() <<
" doesn't match requested type " <<
189 TClass* objClass,
bool array,
EStoreFlags storeFlags)
194 B2ERROR(
"Attempt to register " << accessor.
readableName() <<
195 " outside of the initialization phase. Please move calls to registerInDataStore() into your Module's initialize() function.");
210 B2ERROR(
"An " << accessor.
readableName() <<
" of type " << entry.
object->ClassName() <<
211 " 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.");
216 if (!
checkType(entry, accessor))
return false;
220 B2WARNING(
"Existing " << accessor.
readableName() <<
" has different persistency type than requested. Changing to " <<
221 (dontwriteout ?
"c_DontWriteOut" :
"c_WriteOut") <<
".");
225 B2DEBUG(100,
"An " << accessor.
readableName() <<
" was registered once more.");
230 if (array and name ==
"ALL") {
231 B2ERROR(
"Creating an array with the reserved name 'ALL' is not allowed!");
238 B2DEBUG(100,
"Successfully registered " << accessor.
readableName());
243 EStoreFlags storeFlags,
const std::string& namedRelation)
246 B2FATAL(fromArray.
readableName() <<
" is not an array!");
252 B2FATAL(
"Named Relations can only contain alphabetic characters, given was: " << namedRelation);
263 B2FATAL(
"Tried to create a relation '" << relName <<
"' with a durability larger than the StoreArrays it relates");
270 const std::string& namedRelation)
274 B2FATAL(fromArray.
readableName() <<
" is not an array!");
280 B2FATAL(
"Named Relations can only contain alphabetic characters, given was: " << namedRelation);
297 return &(it->second);
310 return &(entry->
ptr);
319 " exists in the DataStore, did you forget to register it in your Module's initialize() function? Note: direct accesses to it will crash!");
323 if (entry->
ptr && !replace &&
object != entry->
object) {
324 B2ERROR(
"An " << accessor.
readableName() <<
" was already created in the DataStore.");
329 if (
object != entry->
object) {
346 B2FATAL(
"No " << from.
readableName() <<
" exists in the DataStore!");
348 B2FATAL(
"No " << to.
readableName() <<
" exists in the DataStore!");
352 if (!fromEntry->
ptr) {
354 toEntry->
ptr =
nullptr;
355 }
else if (fromEntry->
isArray) {
362 }
else if (fromEntry->
objClass == RelationContainer::Class()) {
370 fixAbsorbObjects(&fromRel->elements(), &toRel->elements());
373 fromRel->setModified(
true);
374 toRel->setModified(
true);
378 toEntry->
object = fromEntry->
ptr->Clone();
381 fromEntry->
ptr =
nullptr;
387 const TClonesArray* array =
static_cast<TClonesArray*
>(entry.
ptr);
388 const int nEntries = array->GetEntriesFast();
389 for (
int i = 0; i < nEntries; i++) {
392 relobj->m_cacheDataStoreEntry = &entry;
398 if (!entry or index < 0) {
403 entry = relObj->m_cacheDataStoreEntry;
404 index = relObj->m_cacheArrayIndex;
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");
424 const TClass* objectClass =
object->IsA();
426 if (mapEntry.second.ptr && mapEntry.second.isArray) {
427 const TClass* arrayClass = mapEntry.second.objClass;
428 if (arrayClass != objectClass)
431 const TClonesArray* array =
static_cast<TClonesArray*
>(mapEntry.second.ptr);
432 if (
object == array->Last()) {
434 index = array->GetLast();
436 if (arrayClass->InheritsFrom(RelationsObject::Class())) {
442 index =
static_cast<const RelationsObject*
>(object)->m_cacheArrayIndex;
443 if (index >= 0 and objEntry) {
450 index = array->IndexOf(
object);
455 entry = &mapEntry.second;
466 static vector<string> arrayNames;
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);
475 classToArrayName[arrayClass] = result;
476 arrayNames.emplace_back(result);
478 }
else if (name ==
"ALL") {
480 if (mapEntry.second.object and mapEntry.second.isArray and mapEntry.second.objClass->InheritsFrom(arrayClass)) {
481 arrayNames.emplace_back(mapEntry.second.name);
485 arrayNames.emplace_back(name);
491 StoreEntry*& toEntry,
int& toIndex,
float weight,
const std::string& namedRelation)
493 if (!fromObject or !toObject)
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.");
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.");
512 B2FATAL(
"No relation '" << relationsName <<
513 "' found. Please register it (using StoreArray::registerRelationTo()) before trying to add relations.");
521 if (relContainer->isDefaultConstructed()) {
523 relContainer->setFromDurability(
c_Event);
524 relContainer->setToName(toEntry->
name);
525 relContainer->setToDurability(
c_Event);
529 TClonesArray& relations = relContainer->elements();
530 new(relations.AddrAt(relations.GetLast() + 1))
RelationElement(fromIndex, toIndex, weight);
532 std::shared_ptr<RelationIndexContainer<TObject, TObject>> relIndex =
536 relIndex->index().emplace(fromIndex, toIndex, fromObject, toObject, weight);
539 relContainer->setModified(
true);
544 int& index,
const TClass* withClass,
const std::string& withName,
const std::string& namedRelation)
549 result.add(fromResult);
553 std::vector<RelationEntry> result;
559 const std::vector<string>& names =
getArrayNames(withName, withClass);
560 vector<string> relationNames;
563 for (
const std::string& name : names) {
566 entry->
name, namedRelation);
571 const size_t prevsize = result.size();
576 auto*
const toObject =
const_cast<TObject*
>(rel.to);
578 result.emplace_back(toObject, rel.weight);
582 auto*
const fromObject =
const_cast<TObject*
>(rel.from);
584 result.emplace_back(fromObject, rel.weight);
588 if (result.size() != prevsize)
589 relationNames.push_back(relationsName);
596 const TClass* withClass,
const std::string& withName,
const std::string& namedRelation)
600 if (!result.object) {
610 const std::vector<string>& names =
getArrayNames(withName, withClass);
613 for (
const std::string& name : names) {
616 entry->
name, namedRelation);
624 if (element && element->to) {
625 return RelationEntry(
const_cast<TObject*
>(element->to), element->weight);
629 if (element && element->from) {
630 return RelationEntry(
const_cast<TObject*
>(element->from), element->weight);
640 std::vector<std::string> arrays;
642 B2ERROR(
"getListOfRelatedArrays(): " << array.
readableName() <<
" is not an array!");
649 if (mapEntry.second.isArray) {
650 const std::string& name = mapEntry.second.name;
653 for (
int searchSide = 0; searchSide <
c_BothSides; searchSide++) {
657 arrays.emplace_back(name);
673 for (
const auto& entrypair : map) {
674 if (!entrypair.second.isArray) {
675 const TObject* obj = entrypair.second.object;
679 if (obj and obj->IsA()->InheritsFrom(objClass))
680 list.emplace_back(entrypair.first);
688 B2DEBUG(100,
"Invalidating objects for durability " << durability);
697 (accessor.
getClass() == RelationContainer::Class()));
699 B2FATAL(
"Attempt to require input " << accessor.
readableName() <<
700 " outside of the initialization phase. Please move isRequired() calls into your Module's initialize() function.");
704 B2ERROR(
"The required " << accessor.
readableName() <<
" does not exist. Maybe you forgot the module that registers it?");
714 (accessor.
getClass() == RelationContainer::Class()));
717 return (
getEntry(accessor) !=
nullptr);
721 std::string
const& namedRelation)
725 " outside of the initialization phase. Please move requireRelationTo() calls into your Module's initialize() function.");
729 B2FATAL(fromArray.
readableName() <<
" is not an array!");
738 std::string
const& namedRelation)
741 B2FATAL(fromArray.
readableName() <<
" is not an array!");
782 DataStore::SwitchableDataStoreContents::SwitchableDataStoreContents():
785 m_idToIndexMap[
""] = 0;
801 if (m_idToIndexMap.count(
id) == 0) {
803 if (!entrylist_event.empty())
804 B2FATAL(
"entrlylist_event given for new DS id. This shouldn't happen, report to framework author.");
805 targetidx = m_entries.size();
806 m_idToIndexMap[id] = targetidx;
809 m_entries.push_back(m_entries[m_currentIdx]);
810 }
else if (!entrylist_event.empty()) {
812 targetidx = m_idToIndexMap.at(
id);
813 for (
const auto& entryname : entrylist_event) {
814 if (m_entries[m_currentIdx][
c_Event].count(entryname) == 0)
816 if (m_entries[targetidx][
c_Event].count(entryname) != 0) {
817 B2WARNING(
"Independent path: entry '" << entryname <<
"' already exists in DataStore '" <<
id <<
818 "'! This will likely break something.");
820 m_entries[targetidx][
c_Event][entryname] = m_entries[m_currentIdx][
c_Event][entryname];
823 B2FATAL(
"no entrlylist_event given, not new DS id. This shouldn't happen, report to framework author.");
828 for (
auto& entrypair : m_entries[targetidx][iDurability]) {
829 if (not entrypair.second.object)
830 B2FATAL(
"createNewDataStoreID(): object '" << entrypair.first <<
" already null (this should never happen).");
831 if (!entrylist_event.empty()) {
836 if (std::find(entrylist_event.begin(), entrylist_event.end(), entrypair.first) == entrylist_event.end())
840 entrypair.second.object =
nullptr;
841 entrypair.second.ptr =
nullptr;
848 int targetidx = m_idToIndexMap.at(
id);
849 auto& targetMaps = m_entries[targetidx];
850 const auto& sourceMaps = m_entries[m_currentIdx];
853 for (
const auto& entrypair : sourceMaps[iDurability]) {
854 const StoreEntry& fromEntry = entrypair.second;
856 if (targetMaps[iDurability].count(fromEntry.
name) == 0) {
860 if (!entrylist_event.empty()) {
865 if (std::find(entrylist_event.begin(), entrylist_event.end(), fromEntry.
name) == entrylist_event.end())
872 if (not fromEntry.
ptr) {
874 target.recoverFromNullObject();
875 target.ptr =
nullptr;
878 delete target.object;
879 target.object = fromEntry.
object->Clone();
880 target.ptr = target.object;
891 m_currentIdx = m_idToIndexMap.at(
id);
893 if ((
unsigned int)m_currentIdx >= m_entries.size())
894 B2FATAL(
"out of bounds in SwitchableDataStoreContents::switchID(): " << m_currentIdx <<
" >= size " << m_entries.size());
904 m_idToIndexMap.clear();
905 m_idToIndexMap[
""] = 0;
912 for (
auto& map : m_entries) {
913 for (
auto& mapEntry : map[durability])
914 delete mapEntry.second.object;
915 map[durability].clear();
921 for (
auto& map : m_entries)
922 for (
auto& mapEntry : map[durability])
923 mapEntry.second.invalidate();
const std::string & currentID() const
returns ID of current DataStore.
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
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.
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.
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.
void copyEntriesTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
copy entries (not contents) of current DataStore to the DataStore with given ID.
In the store you can park objects that have to be accessed by various modules.
static std::string objectName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
StoreEntryMap::const_iterator StoreEntryConstIter
const_iterator for a StoreEntry map.
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'.
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
bool findStoreEntry(const TObject *object, StoreEntry *&entry, int &index)
Find an object in an array in the data store.
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.
static std::string defaultObjectName()
Return the default storage name for an object of the given type.
bool checkType(const StoreEntry &entry, const StoreAccessorBase &accessor) const
Check whether the given entry and the requested class match.
bool optionalRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, std::string const &namedRelation)
Register the given relation as an optional input.
EStoreFlags
Flags describing behaviours of objects etc.
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
void switchID(const std::string &id)
switch to DataStore with given ID.
StoreEntryMap::iterator StoreEntryIter
Iterator for a StoreEntry map.
const std::regex m_regexNamedRelationCheck
Regular expression to check that no special characters and no white spaces are in the string given fo...
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...
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.
bool registerRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, EStoreFlags storeFlags, const std::string &namedRelation)
Register a relation in the DataStore map.
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.
StoreEntryMap & getStoreEntryMap(EDurability durability)
Get a reference to the object/array map.
DependencyMap * m_dependencyMap
Collect information about the dependencies between modules.
static std::string defaultArrayName()
Return the default storage name for an array of the given type.
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.
ESearchSide
Which side of relations should be returned?
@ c_BothSides
Combination of c_FromSide and c_ToSide.
@ c_FromSide
Return relations/objects pointed from (to a given object).
@ c_ToSide
Return relations/objects pointed to (from a given object).
static void updateRelationsObjectCache(StoreEntry &entry)
For an array containing RelationsObjects, update index and entry cache for entire contents.
static const int c_NDurabilityTypes
Number of Durability Types.
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.
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.
bool requireInput(const StoreAccessorBase &accessor)
Produce ERROR message if no entry of the given type is registered in the DataStore.
EDurability
Durability types.
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Belle2::StoreEntry StoreEntry
Wraps a stored array/object, stored under unique (name, durability) key.
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...
std::string currentID() const
returns ID of current DataStore.
static DataStore & Instance()
Instance of singleton Store.
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.
void setInitializeActive(bool active)
Setter for m_initializeActive.
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.
static bool s_DoCleanup
Global flag to to decide if we can do normal cleanup.
void reset()
Clears contents of the datastore (all durabilities)
StoreEntry * getEntry(const StoreAccessorBase &accessor)
Check whether an entry with the correct type is registered in the DataStore map and return it.
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
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.
void copyEntriesTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
copy entries (not contents) of current DataStore to the DataStore with given ID.
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.
bool createObject(TObject *object, bool replace, const StoreAccessorBase &accessor)
Create a new object/array in the DataStore or add an existing one.
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
static std::string arrayName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
bool m_initializeActive
True if modules are currently being initialized.
bool registerEntry(const std::string &name, EDurability durability, TClass *objClass, bool array, EStoreFlags storeFlags)
Register an entry in the DataStore map.
bool optionalInput(const StoreAccessorBase &accessor)
Register the given object/array as an optional input.
SwitchableDataStoreContents m_storeEntryMap
Maps (name, durability) key to StoreEntry objects.
void replaceData(const StoreAccessorBase &from, const StoreAccessorBase &to)
For two StoreAccessors of same type, move all data in 'from' into 'to', discarding previous contents ...
std::map< std::string, StoreEntry > StoreEntryMap
Map for StoreEntries.
Collect information about the dependencies between modules.
@ c_Output
registered output.
@ c_OptionalInput
optional input.
ModuleInfo & getCurrentModuleInfo()
Get info for current module.
void clear()
Reset all collected data.
Class to store relations between StoreArrays in the DataStore.
TClonesArray & elements()
Get reference to the elements.
void setFromName(const std::string &name)
Set name of the StoreArray we relate from.
Class to store a single element of a relation.
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.
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.
void addEntry(const std::string &name, EEntryType type, bool isRelation)
Adds given entry/relation.
Element type for the index.
Wraps a stored array/object, stored under unique (name, durability) key.
TObject * ptr
The pointer to the returned object, either equal to 'object' or null, depending on wether the object ...
TClonesArray * getPtrAsArray() const
Return ptr cast to TClonesArray.
bool dontWriteOut
Flag that indicates whether the object should be written to the output by default.
TObject * object
The pointer to the actual object.
bool isArray
Flag that indicates whether the object is a TClonesArray.
std::string name
Name of the entry.
void recreate()
Reset stored object to defaults, set ptr to new object.
TClass * objClass
class of object.