 |
Belle II Software
release-05-02-19
|
11 #include <framework/datastore/DataStore.h>
13 #include <framework/logging/Logger.h>
14 #include <framework/datastore/RelationEntry.h>
15 #include <framework/datastore/DependencyMap.h>
16 #include <framework/dataobjects/RelationContainer.h>
17 #include <framework/datastore/RelationIndex.h>
18 #include <framework/datastore/RelationIndexManager.h>
19 #include <framework/datastore/RelationsObject.h>
20 #include <framework/datastore/StoreAccessorBase.h>
22 #include <TClonesArray.h>
25 #include <unordered_map>
40 DataStore::Instance().reset();
46 void fixAbsorbObjects(TClonesArray* from, TClonesArray* to)
48 to->AbsorbObjects(from, 0, from->GetEntriesFast() - 1);
52 bool DataStore::s_DoCleanup =
false;
61 DataStore::DataStore() : m_initializeActive(true), m_dependencyMap(new
DependencyMap)
76 B2DEBUG(31,
"DataStore::reset(): Removing all elements from DataStore");
98 static bool firstCall =
true;
100 atexit(cleanDataStore);
108 TClass* cl = TClass::GetClass((
"Belle2::" +
objectName).c_str());
130 const static string gfclass =
"genfit::Track";
131 const static string gfobjectname =
"GF2Track";
132 if (classname == gfclass)
135 size_t colon = classname.rfind(
':');
136 if (colon != std::string::npos) {
137 return classname.substr(colon + 1);
145 B2ASSERT(
"Cannot deduce default object name from null pointer TClass", t);
173 const char* entryType = (entry.
isArray) ?
"array" :
"object";
175 B2FATAL(
"Existing entry '" << entry.
name <<
"' is an " << entryType <<
" and the requested one an " << ((
176 accessor.
isArray()) ?
"array" :
"object"));
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 " <<
191 TClass* objClass,
bool array,
EStoreFlags storeFlags)
196 B2ERROR(
"Attempt to register " << accessor.
readableName() <<
197 " outside of the initialization phase. Please move calls to registerInDataStore() into your Module's initialize() function.");
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.");
218 if (!
checkType(entry, accessor))
return false;
222 B2WARNING(
"Existing " << accessor.
readableName() <<
" has different persistency type than requested. Changing to " <<
223 (dontwriteout ?
"c_DontWriteOut" :
"c_WriteOut") <<
".");
227 B2DEBUG(100,
"An " << accessor.
readableName() <<
" was registered once more.");
232 if (array and name ==
"ALL") {
233 B2ERROR(
"Creating an array with the reserved name 'ALL' is not allowed!");
240 B2DEBUG(100,
"Successfully registered " << accessor.
readableName());
245 EStoreFlags storeFlags,
const std::string& namedRelation)
248 B2FATAL(fromArray.
readableName() <<
" is not an array!");
254 B2FATAL(
"Named Relations can only contain alphabetic characters, given was: " << namedRelation);
265 B2FATAL(
"Tried to create a relation '" << relName <<
"' with a durability larger than the StoreArrays it relates");
272 const std::string& namedRelation)
276 B2FATAL(fromArray.
readableName() <<
" is not an array!");
282 B2FATAL(
"Named Relations can only contain alphabetic characters, given was: " << namedRelation);
299 return &(it->second);
312 return &(entry->
ptr);
321 " exists in the DataStore, did you forget to register it in your Module's initialize() function? Note: direct accesses to it will crash!");
325 if (entry->
ptr && !replace &&
object != entry->
object) {
326 B2ERROR(
"An " << accessor.
readableName() <<
" was already created in the DataStore.");
331 if (
object != entry->
object) {
348 B2FATAL(
"No " << from.
readableName() <<
" exists in the DataStore!");
350 B2FATAL(
"No " << to.
readableName() <<
" exists in the DataStore!");
354 if (!fromEntry->
ptr) {
356 toEntry->
ptr =
nullptr;
357 }
else if (fromEntry->
isArray) {
364 }
else if (fromEntry->
objClass == RelationContainer::Class()) {
372 fixAbsorbObjects(&fromRel->elements(), &toRel->elements());
375 fromRel->setModified(
true);
376 toRel->setModified(
true);
380 toEntry->
object = fromEntry->
ptr->Clone();
383 fromEntry->
ptr =
nullptr;
389 const TClonesArray* array =
static_cast<TClonesArray*
>(entry.
ptr);
390 const int nEntries = array->GetEntriesFast();
391 for (
int i = 0; i < nEntries; i++) {
394 relobj->m_cacheDataStoreEntry = &entry;
400 if (!entry or index < 0) {
405 entry = relObj->m_cacheDataStoreEntry;
406 index = relObj->m_cacheArrayIndex;
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");
426 const TClass* objectClass =
object->IsA();
428 if (mapEntry.second.ptr && mapEntry.second.isArray) {
429 const TClass* arrayClass = mapEntry.second.objClass;
430 if (arrayClass != objectClass)
433 const TClonesArray* array =
static_cast<TClonesArray*
>(mapEntry.second.ptr);
434 if (
object == array->Last()) {
436 index = array->GetLast();
438 if (arrayClass->InheritsFrom(RelationsObject::Class())) {
444 index =
static_cast<const RelationsObject*
>(object)->m_cacheArrayIndex;
445 if (index >= 0 and objEntry) {
452 index = array->IndexOf(
object);
457 entry = &mapEntry.second;
468 static vector<string> arrayNames;
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);
477 classToArrayName[arrayClass] = result;
478 arrayNames.emplace_back(result);
480 }
else if (name ==
"ALL") {
482 if (mapEntry.second.object and mapEntry.second.isArray and mapEntry.second.objClass->InheritsFrom(arrayClass)) {
483 arrayNames.emplace_back(mapEntry.second.name);
487 arrayNames.emplace_back(name);
493 StoreEntry*& toEntry,
int& toIndex,
float weight,
const std::string& namedRelation)
495 if (!fromObject or !toObject)
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.");
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.");
514 B2FATAL(
"No relation '" << relationsName <<
515 "' found. Please register it (using StoreArray::registerRelationTo()) before trying to add relations.");
523 if (relContainer->isDefaultConstructed()) {
525 relContainer->setFromDurability(
c_Event);
526 relContainer->setToName(toEntry->
name);
527 relContainer->setToDurability(
c_Event);
532 TClonesArray& relations = relContainer->elements();
533 new(relations.AddrAt(relations.GetLast() + 1))
RelationElement(fromIndex, toIndex, weight);
535 std::shared_ptr<RelationIndexContainer<TObject, TObject>> relIndex =
539 relIndex->index().emplace(fromIndex, toIndex, fromObject, toObject, weight);
542 relContainer->setModified(
true);
547 int& index,
const TClass* withClass,
const std::string& withName,
const std::string& namedRelation)
552 result.add(fromResult);
556 std::vector<RelationEntry> result;
562 const std::vector<string>& names =
getArrayNames(withName, withClass);
563 vector<string> relationNames;
566 for (
const std::string& name : names) {
569 entry->
name, namedRelation);
574 const size_t prevsize = result.size();
579 auto*
const toObject =
const_cast<TObject*
>(rel.to);
581 result.emplace_back(toObject, rel.weight);
585 auto*
const fromObject =
const_cast<TObject*
>(rel.from);
587 result.emplace_back(fromObject, rel.weight);
591 if (result.size() != prevsize)
592 relationNames.push_back(relationsName);
599 const TClass* withClass,
const std::string& withName,
const std::string& namedRelation)
603 if (!result.object) {
613 const std::vector<string>& names =
getArrayNames(withName, withClass);
616 for (
const std::string& name : names) {
619 entry->
name, namedRelation);
627 if (element && element->to) {
628 return RelationEntry(
const_cast<TObject*
>(element->to), element->weight);
632 if (element && element->from) {
633 return RelationEntry(
const_cast<TObject*
>(element->from), element->weight);
643 std::vector<std::string> arrays;
645 B2ERROR(
"getListOfRelatedArrays(): " << array.
readableName() <<
" is not an array!");
652 if (mapEntry.second.isArray) {
653 const std::string& name = mapEntry.second.name;
656 for (
int searchSide = 0; searchSide <
c_BothSides; searchSide++) {
660 arrays.emplace_back(name);
676 for (
const auto& entrypair : map) {
677 if (!entrypair.second.isArray) {
678 const TObject* obj = entrypair.second.object;
682 if (obj and obj->IsA()->InheritsFrom(objClass))
683 list.emplace_back(entrypair.first);
691 B2DEBUG(100,
"Invalidating objects for durability " << durability);
700 (accessor.
getClass() == RelationContainer::Class()));
702 B2FATAL(
"Attempt to require input " << accessor.
readableName() <<
703 " outside of the initialization phase. Please move isRequired() calls into your Module's initialize() function.");
707 B2ERROR(
"The required " << accessor.
readableName() <<
" does not exist. Maybe you forgot the module that registers it?");
717 (accessor.
getClass() == RelationContainer::Class()));
720 return (
getEntry(accessor) !=
nullptr);
724 std::string
const& namedRelation)
728 " outside of the initialization phase. Please move requireRelationTo() calls into your Module's initialize() function.");
732 B2FATAL(fromArray.
readableName() <<
" is not an array!");
741 std::string
const& namedRelation)
744 B2FATAL(fromArray.
readableName() <<
" is not an array!");
785 DataStore::SwitchableDataStoreContents::SwitchableDataStoreContents():
788 m_idToIndexMap[
""] = 0;
804 if (m_idToIndexMap.count(
id) == 0) {
806 if (!entrylist_event.empty())
807 B2FATAL(
"entrlylist_event given for new DS id. This shouldn't happen, report to framework author.");
808 targetidx = m_entries.size();
809 m_idToIndexMap[id] = targetidx;
812 m_entries.push_back(m_entries[m_currentIdx]);
813 }
else if (!entrylist_event.empty()) {
815 targetidx = m_idToIndexMap.at(
id);
816 for (
const auto& entryname : entrylist_event) {
817 if (m_entries[m_currentIdx][
c_Event].count(entryname) == 0)
819 if (m_entries[targetidx][
c_Event].count(entryname) != 0) {
820 B2WARNING(
"Independent path: entry '" << entryname <<
"' already exists in DataStore '" <<
id <<
821 "'! This will likely break something.");
823 m_entries[targetidx][
c_Event][entryname] = m_entries[m_currentIdx][
c_Event][entryname];
826 B2FATAL(
"no entrlylist_event given, not new DS id. This shouldn't happen, report to framework author.");
831 for (
auto& entrypair : m_entries[targetidx][iDurability]) {
832 if (not entrypair.second.object)
833 B2FATAL(
"createNewDataStoreID(): object '" << entrypair.first <<
" already null (this should never happen).");
834 if (!entrylist_event.empty()) {
839 if (std::find(entrylist_event.begin(), entrylist_event.end(), entrypair.first) == entrylist_event.end())
843 entrypair.second.object =
nullptr;
844 entrypair.second.ptr =
nullptr;
851 int targetidx = m_idToIndexMap.at(
id);
852 auto& targetMaps = m_entries[targetidx];
853 const auto& sourceMaps = m_entries[m_currentIdx];
856 for (
const auto& entrypair : sourceMaps[iDurability]) {
857 const StoreEntry& fromEntry = entrypair.second;
859 if (targetMaps[iDurability].count(fromEntry.
name) == 0) {
863 if (!entrylist_event.empty()) {
868 if (std::find(entrylist_event.begin(), entrylist_event.end(), fromEntry.
name) == entrylist_event.end())
875 if (not fromEntry.
ptr) {
877 target.recoverFromNullObject();
878 target.ptr =
nullptr;
881 delete target.object;
882 target.object = fromEntry.
object->Clone();
883 target.ptr = target.object;
894 m_currentIdx = m_idToIndexMap.at(
id);
896 if ((
unsigned int)m_currentIdx >= m_entries.size())
897 B2FATAL(
"out of bounds in SwitchableDataStoreContents::switchID(): " << m_currentIdx <<
" >= size " << m_entries.size());
907 m_idToIndexMap.clear();
908 m_idToIndexMap[
""] = 0;
915 for (
auto& map : m_entries) {
916 for (
auto& mapEntry : map[durability])
917 delete mapEntry.second.object;
918 map[durability].clear();
924 for (
auto& map : m_entries)
925 for (
auto& mapEntry : map[durability])
926 mapEntry.second.invalidate();
const std::string & currentID() const
returns ID of current DataStore.
@ c_BothSides
Combination of c_FromSide and c_ToSide.
TObject * object
The pointer to the actual object.
bool registerRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, EStoreFlags storeFlags, const std::string &namedRelation)
Register a relation in the DataStore map.
static void updateRelationsObjectCache(StoreEntry &entry)
For an array containing RelationsObjects, update index and entry cache for entire contents.
static RelationIndexManager & Instance()
Returns the singleton instance.
bool m_initializeActive
True if modules are currently being initialized.
StoreEntryMap::iterator StoreEntryIter
Iterator for a StoreEntry map.
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
std::map< std::string, int > m_idToIndexMap
Maps DataStore ID to index in m_entries.
const Element * getFirstElementTo(const TO &to) const
Return a pointer to the first relation Element of the given object.
void clear()
Reset all collected data.
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.
DataStore::EDurability getDurability() const
Return durability with which the object is saved in the DataStore.
std::string currentID() const
returns ID of current DataStore.
TClass * getClass() const
The underlying object's type.
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.
static DataStore & Instance()
Instance of singleton Store.
std::string readableName() const
Convert this acessor into a readable string (for messages).
static std::string arrayName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
std::map< std::string, StoreEntry > StoreEntryMap
Map for StoreEntries.
Collect information about the dependencies between modules.
ESearchSide
Which side of relations should be returned?
void setInitializeActive(bool active)
Setter for m_initializeActive.
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Class to store relations between StoreArrays in the DataStore.
EStoreFlags
Flags describing behaviours of objects etc.
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.
Provides access to fast ( O(log n) ) bi-directional lookups on a specified relation.
Wraps a stored array/object, stored under unique (name, durability) key.
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'.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
const Element * getFirstElementFrom(const FROM &from) const
Return a pointer to the first relation Element of the given object.
void replaceData(const StoreAccessorBase &from, const StoreAccessorBase &to)
For two StoreAccessors of same type, move all data in 'from' into 'to', discarding previous contents ...
void reset()
Reset the cache completely, that is clear all caches and don't even keep the Index objects around.
Base class for StoreObjPtr and StoreArray for easier common treatment.
range_to getElementsTo(const TO *to) const
Return a range of all elements pointing to the given object.
static std::string defaultObjectName()
Return the default storage name for an object of the given type.
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
@ c_Output
registered output.
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
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.
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.
base class for RelationVector<T>
bool optionalInput(const StoreAccessorBase &accessor)
Register the given object/array as an optional input.
bool isArray
Flag that indicates whether the object is a TClonesArray.
DependencyMap * m_dependencyMap
Collect information about the dependencies between modules.
StoreEntryMap & getStoreEntryMap(EDurability durability)
Get a reference to the object/array map.
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
std::string name
Name of the entry.
static bool s_DoCleanup
Global flag to to decide if we can do normal cleanup.
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 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.
const std::regex m_regexNamedRelationCheck
Regular expression to check that no special characters and no white spaces are in the string given fo...
Class to store a single element of a relation.
Element type for the index.
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 recreate()
Reset stored object to defaults, set ptr to new object.
range_from getElementsFrom(const FROM *from) const
Return a range of all elements pointing from the given object.
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 addEntry(const std::string &name, EEntryType type, bool isRelation)
Adds given entry/relation.
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 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...
SwitchableDataStoreContents m_storeEntryMap
Maps (name, durability) key to StoreEntry objects.
void setFromName(const std::string &name)
Set name of the StoreArray we relate from.
Abstract base class for different kinds of events.
void switchID(const std::string &id)
switch to DataStore with given ID.
TClonesArray & elements()
Get reference to the elements.
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.
const static int c_NDurabilityTypes
Number of Durability Types.
@ c_ToSide
Return relations/objects pointed to (from a given object).
bool isArray() const
Is this an accessor for an array?
static std::string defaultArrayName()
Return the default storage name for an array of the given type.
int m_cacheArrayIndex
Cache of the index in the TClonesArray to which this object belongs.
void clear()
same as calling reset() for all durabilities + all non-default datastore IDs are removed.
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.
bool registerEntry(const std::string &name, EDurability durability, TClass *objClass, bool array, EStoreFlags storeFlags)
Register an entry in the DataStore map.
void switchID(const std::string &id)
switch to DataStore with given ID.
void clear(DataStore::EDurability durability=DataStore::c_Event)
Clear the cache of RelationIndexContainers with the given durability.
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
bool findStoreEntry(const TObject *object, StoreEntry *&entry, int &index)
Find an object in an array in the data store.
TClonesArray * getPtrAsArray() const
Return ptr cast to TClonesArray.
Belle2::StoreEntry StoreEntry
Wraps a stored array/object, stored under unique (name, durability) key.
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
ModuleInfo & getCurrentModuleInfo()
Get info for current module.
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.
TObject * ptr
The pointer to the returned object, either equal to 'object' or null, depending on wether the object ...
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.
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.
bool createObject(TObject *object, bool replace, const StoreAccessorBase &accessor)
Create a new object/array in the DataStore or add an existing one.
bool optionalRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, std::string const &namedRelation)
Register the given relation as an optional input.
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.
TClass * objClass
class of object.
bool dontWriteOut
Flag that indicates whether the object should be written to the output by default.
StoreEntry * getEntry(const StoreAccessorBase &accessor)
Check whether an entry with the correct type is registered in the DataStore map and return it.
bool checkType(const StoreEntry &entry, const StoreAccessorBase &accessor) const
Check whether the given entry and the requested class match.
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
@ c_OptionalInput
optional input.
void reset()
Clears contents of the datastore (all durabilities)
In the store you can park objects that have to be accessed by various modules.
Defines interface for accessing relations of objects in StoreArray.
@ c_FromSide
Return relations/objects pointed from (to a given object).
bool requireInput(const StoreAccessorBase &accessor)
Produce ERROR message if no entry of the given type is registered in the DataStore.
EDurability
Durability types.