Belle II Software development
DataStore::SwitchableDataStoreContents Class Reference

Encapsulates DataStoreContents, but allows transparently switching between different versions ('DataStore IDs'). More...

Public Member Functions

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.
 
const StoreEntryMapoperator[] (int durability) const
 Get StoreEntry map for given durability (and current DataStore ID).
 
StoreEntryMapoperator[] (int durability)
 Get StoreEntry map for given durability (and current DataStore ID).
 
void switchID (const std::string &id)
 switch to DataStore with given ID.
 
const std::string & currentID () const
 returns ID of current DataStore.
 
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.
 
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 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.
 
void createNewDataStoreID (const std::string &id)
 creates new datastore with given id, copying the registered objects/arrays from the current one.
 
void createEmptyDataStoreID (const std::string &id)
 creates empty datastore with given id.
 

Private Attributes

std::vector< DataStoreContentsm_entries
 wrapped DataStoreContents.
 
std::map< std::string, int > m_idToIndexMap
 Maps DataStore ID to index in m_entries.
 
std::string m_currentID = ""
 currently active DataStore ID.
 
int m_currentIdx = 0
 index of currently active DataStore.
 

Detailed Description

Encapsulates DataStoreContents, but allows transparently switching between different versions ('DataStore IDs').

Accessed only through operator[].

Definition at line 581 of file DataStore.h.

Constructor & Destructor Documentation

◆ SwitchableDataStoreContents()

Definition at line 821 of file DataStore.cc.

821 :
822 m_entries(1)
823{
824 m_idToIndexMap[""] = 0;
825}
std::vector< DataStoreContents > m_entries
wrapped DataStoreContents.
Definition: DataStore.h:615
std::map< std::string, int > m_idToIndexMap
Maps DataStore ID to index in m_entries.
Definition: DataStore.h:616

Member Function Documentation

◆ clear()

void clear ( )

same as calling reset() for all durabilities + all non-default datastore IDs are removed.

Definition at line 1154 of file DataStore.cc.

1155{
1156 for (int i = 0; i < c_NDurabilityTypes; i++)
1157 reset((EDurability)i);
1158
1159 m_entries.clear();
1160 m_entries.resize(1);
1161 m_idToIndexMap.clear();
1162 m_idToIndexMap[""] = 0;
1163 m_currentID = "";
1164 m_currentIdx = 0;
1165}
std::string m_currentID
currently active DataStore ID.
Definition: DataStore.h:617
int m_currentIdx
index of currently active DataStore.
Definition: DataStore.h:618
static const int c_NDurabilityTypes
Number of Durability Types.
Definition: DataStore.h:63
EDurability
Durability types.
Definition: DataStore.h:58
void reset()
Clears contents of the datastore (all durabilities)
Definition: DataStore.cc:74

◆ copyContentsTo()

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 at line 946 of file DataStore.cc.

947{
948 int targetidx = m_idToIndexMap.at(id);
949 auto& targetMaps = m_entries[targetidx];
950 const auto& sourceMaps = m_entries[m_currentIdx];
951
952 for (int iDurability = 0; iDurability < c_NDurabilityTypes; iDurability++) {
953 for (const auto& entrypair : sourceMaps[iDurability]) {
954 const StoreEntry& fromEntry = entrypair.second;
955 //does this exist in target?
956 if (targetMaps[iDurability].count(fromEntry.name) == 0) {
957 continue;
958 }
959
960 if (!entrylist_event.empty()) {
961 //skip all entries of other durabilities
962 if (iDurability != c_Event)
963 continue;
964 //skip all entries not found in entrylist_event
965 if (std::find(entrylist_event.begin(), entrylist_event.end(), fromEntry.name) == entrylist_event.end())
966 continue;
967 }
968
969 StoreEntry& target = targetMaps[iDurability][fromEntry.name];
970
971 //copy contents into target object
972 if (not fromEntry.ptr) {
973 if (!target.object)
974 target.recoverFromNullObject();
975 target.ptr = nullptr;
976 } else {
977 //TODO there is some optimisation opportunity here, e.g. by only cloning the entries of a TClonesArray instead of the array itself
978 delete target.object;
979 target.object = fromEntry.object->Clone();
980 target.ptr = target.object;
981 }
982 }
983 }
984
985}
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
Wraps a stored array/object, stored under unique (name, durability) key.
Definition: StoreEntry.h:22
TObject * ptr
The pointer to the returned object, either equal to 'object' or null, depending on wether the object ...
Definition: StoreEntry.h:51
TObject * object
The pointer to the actual object.
Definition: StoreEntry.h:48
std::string name
Name of the entry.
Definition: StoreEntry.h:53

◆ copyEntriesTo()

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 at line 850 of file DataStore.cc.

852{
853 std::vector<std::string> entrylist;
854 if (entrylist_event.size() == 1 and entrylist_event.at(0) == "ALL") {
856 } else {
857 entrylist = entrylist_event;
858 }
859
860 if (mergeEntries) {
861 // Make sure that EventMetaData is always merged
862 if (std::find(entrylist.begin(), entrylist.end(), "EventMetaData") == entrylist.end()) {
863 entrylist.push_back("EventMetaData");
864 B2INFO("It is required to merge the 'EventMetaData' for consistency. Added.");
865 }
866 }
867
868 //collect the entries for which we do not have to fix duplicate pointers
869 std::vector<std::string> skipEntries;
870
871 int targetidx;
872 if (m_idToIndexMap.count(id) == 0) {
873 //new DataStore & full copy
874 if (!entrylist.empty())
875 B2FATAL("entrlylist_event given for new DS id. This shouldn't happen, report to framework author.");
876 targetidx = m_entries.size();
877 m_idToIndexMap[id] = targetidx;
878
879 //copy entries
880 m_entries.push_back(m_entries[m_currentIdx]);
881 } else if (!entrylist.empty()) {
882 targetidx = m_idToIndexMap.at(id);
883 // if we are merging DataStores, we need to register a new object that stores at which indices the arrays have been merged
884 if (mergeEntries) {
885 if (m_entries[targetidx][c_Event].count("MergedArrayIndices") != 0) {
886 B2FATAL("MergedArrayIndices already exists. This should not happen.");
887 }
888 m_entries[targetidx][c_Event]["MergedArrayIndices"] = StoreEntry(false, EventExtraInfo::Class(), "MergedArrayIndices", false);
889 }
890 for (std::string& entryname : entrylist) {
891 //copy only given entries (in c_Event)
892 if (m_entries[m_currentIdx][c_Event].count(entryname) == 0) {
893 continue;
894 }
895 if (m_entries[targetidx][c_Event].count(entryname) != 0) {
896 if (mergeEntries) {
897 // Skip Store-Arrays and Relations..
898 if (m_entries[targetidx][c_Event][entryname].isArray
899 or m_entries[targetidx][c_Event][entryname].objClass == RelationContainer::Class()) { //do nothing
900 // ..but not Store-Objects
901 } else {
902 // We have to create a new StoreEntry as the name of the key in the map changes
903 if (m_entries[targetidx][c_Event].count(entryname + "_indepPath") != 0) {
904 B2FATAL(entryname + "_indepPath already exists. This should not happen.");
905 }
906 m_entries[targetidx][c_Event][entryname + "_indepPath"] = StoreEntry(false, m_entries[targetidx][c_Event][entryname].objClass,
907 entryname + "_indepPath", m_entries[targetidx][c_Event][entryname].dontWriteOut);
908 }
909 skipEntries.push_back(entryname);
910 continue;
911 } else {
912 B2WARNING("Independent path: entry '" << entryname << "' already exists in DataStore '" << id <<
913 "'! This will likely break something.");
914 }
915 } else {
916 m_entries[targetidx][c_Event][entryname] = m_entries[m_currentIdx][c_Event][entryname];
917 }
918 }
919 } else {
920 B2FATAL("no entrlylist_event given, not new DS id. This shouldn't happen, report to framework author.");
921 }
922
923 //fix duplicate pointers
924 for (int iDurability = 0; iDurability < c_NDurabilityTypes; iDurability++) {
925 for (auto& entrypair : m_entries[targetidx][iDurability]) {
926 if (not entrypair.second.object)
927 B2FATAL("createNewDataStoreID(): object '" << entrypair.first << " already null (this should never happen).");
928 if (!entrylist.empty()) {
929 //skip all entries of other durabilities
930 if (iDurability != c_Event)
931 continue;
932 //skip all entries not found in entrylist
933 if (std::find(entrylist.begin(), entrylist.end(), entrypair.first) == entrylist.end())
934 continue;
935 //don't fix the ownership for these
936 if (std::find(skipEntries.begin(), skipEntries.end(), entrypair.first) != skipEntries.end())
937 continue;
938 }
939
940 entrypair.second.object = nullptr; //remove duplicate ownership
941 entrypair.second.ptr = nullptr;
942 }
943 }
944}
std::vector< std::string > getSortedListOfDataStore(EDurability durability) const
Returns a (sorted) list of all the content of the DataStore (Objs-Arrays-Relations).
Definition: DataStore.cc:703
Belle2::StoreEntry StoreEntry
Wraps a stored array/object, stored under unique (name, durability) key.
Definition: DataStore.h:84
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54

◆ createEmptyDataStoreID()

void createEmptyDataStoreID ( const std::string &  id)

creates empty datastore with given id.

Definition at line 838 of file DataStore.cc.

839{
840 //does this id already exist?
841 if (m_idToIndexMap.count(id) > 0)
842 return;
843
844 int targetidx = m_entries.size();
845 m_idToIndexMap[id] = targetidx;
846
847 m_entries.push_back(DataStoreContents());
848}
std::array< StoreEntryMap, c_NDurabilityTypes > DataStoreContents
StoreEntry maps for each durability.
Definition: DataStore.h:90

◆ createNewDataStoreID()

void createNewDataStoreID ( const std::string &  id)

creates new datastore with given id, copying the registered objects/arrays from the current one.

Definition at line 827 of file DataStore.cc.

828{
829 //does this id already exist?
830 if (m_idToIndexMap.count(id) > 0)
831 return;
832
833 copyEntriesTo(id);
834 //copy actual contents, fixing pointers
835 copyContentsTo(id);
836}
void copyEntriesTo(const std::string &id, const std::vector< std::string > &entrylist_event={}, bool mergeEntries=false)
copy entries (not contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:850
void copyContentsTo(const std::string &id, const std::vector< std::string > &entrylist_event={})
copy contents (actual array / object contents) of current DataStore to the DataStore with given ID.
Definition: DataStore.cc:946

◆ currentID()

const std::string & currentID ( ) const
inline

returns ID of current DataStore.

Definition at line 603 of file DataStore.h.

603{ return m_currentID; }

◆ invalidateData()

void invalidateData ( EDurability  durability)

Clears all registered StoreEntry objects of a specified durability, invalidating all objects.

Definition at line 1177 of file DataStore.cc.

1178{
1179 for (auto& map : m_entries)
1180 for (auto& mapEntry : map[durability])
1181 mapEntry.second.invalidate();
1182}

◆ mergeContentsTo()

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 at line 987 of file DataStore.cc.

988{
989 if (entrylist_event.empty()) {
990 B2WARNING("Nothing to merge. Returning.");
991 return;
992 }
993
994 std::vector<std::string> entrylist;
995 if (entrylist_event.size() == 1 and entrylist_event.at(0) == "ALL") {
997 } else {
998 entrylist = entrylist_event;
999 }
1000
1001 int targetidx = m_idToIndexMap.at(id);
1002 auto& targetMaps = m_entries[targetidx];
1003 const auto& sourceMaps = m_entries[m_currentIdx];
1004
1005 // we need to know the length of the original StoreArrays in order to fix the Relations
1006 if (targetMaps[c_Event].count("MergedArrayIndices") == 0) {
1007 B2FATAL("Did not find MergedArrayIndices in target. This should not happen.");
1008 }
1009 StoreEntry& target_arrayIndices = targetMaps[c_Event]["MergedArrayIndices"];
1010 target_arrayIndices.recreate();
1011 EventExtraInfo* arrayIndices = static_cast<EventExtraInfo*>(target_arrayIndices.ptr);
1012
1013 // we have to go through the list in this order to make sure StoreArrays are merged before their Relations
1014 for (std::string nextEntry : entrylist) {
1015 for (const auto& entrypair : sourceMaps[c_Event]) {
1016 const StoreEntry& fromEntry = entrypair.second;
1017 if (fromEntry.name != nextEntry) {
1018 continue;
1019 }
1020
1021 //does this exist in target?
1022 if (targetMaps[c_Event].count(fromEntry.name) == 0) {
1023 continue;
1024 }
1025
1026 StoreEntry& target = targetMaps[c_Event][fromEntry.name];
1027
1028 //copy contents into target object
1029 if (!fromEntry.ptr) {
1030 if (!target.object) {
1031 target.recoverFromNullObject();
1032 target.ptr = nullptr;
1033 } else {
1034 // keep the content as it is before merging and indicate this by the index
1035 if (target.isArray) {
1036 arrayIndices->addExtraInfo(target.name, target.getPtrAsArray()->GetEntriesFast());
1037 }
1038 }
1039 } else {
1040 // array-type object
1041 if (target.isArray) {
1042 if (!target.ptr) {
1043 target.object = fromEntry.object->Clone();
1044 target.ptr = target.object;
1045
1046 arrayIndices->addExtraInfo(target.name, 0);
1047 } else {
1048 if (target.objClass != fromEntry.objClass) {
1049 B2FATAL("Cannot merge StoreArrays " << target.name << "as they are of different classes.");
1050 }
1051
1052 arrayIndices->addExtraInfo(target.name, target.getPtrAsArray()->GetEntriesFast());
1053
1054 if (fromEntry.getPtrAsArray()->GetEntriesFast() == 0) {
1055 continue;
1056 }
1057
1058 // TClonesArray has no easy way to add objects to it
1059 // Instead work around this by cloning and absorbing the TClonesArray `fromEntry`
1060 // Also use `fixAbsorbObjects` define in this file to work around some potential memory leak
1061 // TODO: check if clone makes sense? or should we rather move the whole obj to avoid memleaks?
1062 TClonesArray* fromArr = static_cast<TClonesArray*>(fromEntry.getPtrAsArray()->Clone());
1063 fixAbsorbObjects(fromArr, target.getPtrAsArray());
1064
1065 // update the cache
1067 delete fromArr;
1068 }
1069 } else {
1070 if (!target.ptr) {
1071 target.object = fromEntry.object->Clone();
1072 target.ptr = target.object;
1073 } else {
1074 // relation-type object
1075 if (fromEntry.objClass == RelationContainer::Class()) {
1076 auto* fromRelContainer = static_cast<RelationContainer*>(fromEntry.ptr);
1077 if (fromRelContainer->isDefaultConstructed()) {
1078 continue;
1079 }
1080
1081 if (fromRelContainer->getEntries() == 0) {
1082 continue;
1083 }
1084
1085 const std::string& fromName = fromRelContainer->getFromName();
1086 const std::string& toName = fromRelContainer->getToName();
1087
1088 auto* targetRelContainer = static_cast<RelationContainer*>(target.ptr);
1089 if (not arrayIndices->hasExtraInfo(fromName) || not arrayIndices->hasExtraInfo(toName)) {
1090 B2WARNING("Skipping merging of relation " << fromEntry.name
1091 << ". The StoreArrays " << fromName << " and " << toName << " have to be merged before.");
1092 // clear relation just to make sure nobody actually uses it
1093 targetRelContainer->Clear();
1094 continue;
1095 }
1096
1097 // Make sure everything is properly initialized
1098 if (targetRelContainer->isDefaultConstructed()) {
1099 targetRelContainer->setFromName(fromName);
1100 targetRelContainer->setFromDurability(c_Event);
1101 targetRelContainer->setToName(toName);
1102 targetRelContainer->setToDurability(c_Event);
1103 }
1104
1105 // add relation
1106 TClonesArray& relations = targetRelContainer->elements();
1107 // The fast way would be to add the relation also to the RelationIndexManager (this is a cache for relations)
1108 // However, it seems to have some issues with the switching of the DataStore
1109 // (it simply uses the name of the relation for the mapping, but it exists twice..)
1110 // Instead, force rebuilding of the cache later
1111
1112 for (int i = 0; i < fromRelContainer->getEntries(); i++) {
1113 const RelationElement& rel = fromRelContainer->getElement(i);
1114 unsigned int fromIndex = arrayIndices->hasExtraInfo(fromName) ? rel.getFromIndex() + arrayIndices->getExtraInfo(fromName) : -1;
1115
1116 for (size_t rel_idx = 0; rel_idx < rel.getSize(); rel_idx++) {
1117 unsigned int toIndex = arrayIndices->hasExtraInfo(toName) ? rel.getToIndex(rel_idx) + arrayIndices->getExtraInfo(toName) : -1;
1118 float weight = rel.getWeight(rel_idx);
1119 new (relations.AddrAt(relations.GetLast() + 1)) RelationElement(fromIndex, toIndex, weight);
1120 }
1121 }
1122
1123 // as mentioned above, rebuild of cache
1124 targetRelContainer->setModified(true);
1125
1126 // simple object (cannot be merged, instead keep both)
1127 } else {
1128 std::string nameRenamed = fromEntry.name + "_indepPath";
1129 if (targetMaps[c_Event].count(nameRenamed) == 0) {
1130 B2FATAL("Did not find " << nameRenamed << " in target. This should not happen.");
1131 }
1132 StoreEntry& target_renamed = targetMaps[c_Event][nameRenamed];
1133 target_renamed.object = fromEntry.object->Clone();
1134 target_renamed.ptr = target_renamed.object;
1135 }
1136 }
1137 }
1138 }
1139 }
1140 }
1141
1142}
static void updateRelationsObjectCache(StoreEntry &entry)
For an array containing RelationsObjects, update index and entry cache for entire contents.
Definition: DataStore.cc:387
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.
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.
TClonesArray * getPtrAsArray() const
Return ptr cast to TClonesArray.
Definition: StoreEntry.cc:83
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

◆ operator[]() [1/2]

StoreEntryMap & operator[] ( int  durability)
inline

Get StoreEntry map for given durability (and current DataStore ID).

Definition at line 593 of file DataStore.h.

594 {
595 //reuse const implementation
596 const SwitchableDataStoreContents* this2 = this;
597 return const_cast<StoreEntryMap&>((*this2)[durability]);
598 }
std::map< std::string, StoreEntry > StoreEntryMap
Map for StoreEntries.
Definition: DataStore.h:87

◆ operator[]() [2/2]

const StoreEntryMap & operator[] ( int  durability) const
inline

Get StoreEntry map for given durability (and current DataStore ID).

Definition at line 591 of file DataStore.h.

591{ return m_entries[m_currentIdx][durability]; }

◆ reset()

void reset ( EDurability  durability)

Frees memory occupied by data store items and removes all objects from the map.

Definition at line 1167 of file DataStore.cc.

1168{
1169 for (auto& map : m_entries) {
1170 for (auto& mapEntry : map[durability]) {
1171 delete mapEntry.second.object;
1172 }
1173 map[durability].clear();
1174 }
1175}

◆ switchID()

void switchID ( const std::string &  id)

switch to DataStore with given ID.

Definition at line 1144 of file DataStore.cc.

1145{
1146 //switch
1147 m_currentID = id;
1149
1150 if ((unsigned int)m_currentIdx >= m_entries.size())
1151 B2FATAL("out of bounds in SwitchableDataStoreContents::switchID(): " << m_currentIdx << " >= size " << m_entries.size());
1152}

Member Data Documentation

◆ m_currentID

std::string m_currentID = ""
private

currently active DataStore ID.

Definition at line 617 of file DataStore.h.

◆ m_currentIdx

int m_currentIdx = 0
private

index of currently active DataStore.

Definition at line 618 of file DataStore.h.

◆ m_entries

std::vector<DataStoreContents> m_entries
private

wrapped DataStoreContents.

Definition at line 615 of file DataStore.h.

◆ m_idToIndexMap

std::map<std::string, int> m_idToIndexMap
private

Maps DataStore ID to index in m_entries.

Definition at line 616 of file DataStore.h.


The documentation for this class was generated from the following files: