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 820 of file DataStore.cc.

820 :
821 m_entries(1)
822{
823 m_idToIndexMap[""] = 0;
824}
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 1153 of file DataStore.cc.

1154{
1155 for (int i = 0; i < c_NDurabilityTypes; i++)
1156 reset((EDurability)i);
1157
1158 m_entries.clear();
1159 m_entries.resize(1);
1160 m_idToIndexMap.clear();
1161 m_idToIndexMap[""] = 0;
1162 m_currentID = "";
1163 m_currentIdx = 0;
1164}
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:73

◆ 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 945 of file DataStore.cc.

946{
947 int targetidx = m_idToIndexMap.at(id);
948 auto& targetMaps = m_entries[targetidx];
949 const auto& sourceMaps = m_entries[m_currentIdx];
950
951 for (int iDurability = 0; iDurability < c_NDurabilityTypes; iDurability++) {
952 for (const auto& entrypair : sourceMaps[iDurability]) {
953 const StoreEntry& fromEntry = entrypair.second;
954 //does this exist in target?
955 if (targetMaps[iDurability].count(fromEntry.name) == 0) {
956 continue;
957 }
958
959 if (!entrylist_event.empty()) {
960 //skip all entries of other durabilities
961 if (iDurability != c_Event)
962 continue;
963 //skip all entries not found in entrylist_event
964 if (std::find(entrylist_event.begin(), entrylist_event.end(), fromEntry.name) == entrylist_event.end())
965 continue;
966 }
967
968 StoreEntry& target = targetMaps[iDurability][fromEntry.name];
969
970 //copy contents into target object
971 if (not fromEntry.ptr) {
972 if (!target.object)
973 target.recoverFromNullObject();
974 target.ptr = nullptr;
975 } else {
976 //TODO there is some optimisation opportunity here, e.g. by only cloning the entries of a TClonesArray instead of the array itself
977 delete target.object;
978 target.object = fromEntry.object->Clone();
979 target.ptr = target.object;
980 }
981 }
982 }
983
984}
@ 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 whether 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 849 of file DataStore.cc.

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

◆ createEmptyDataStoreID()

void createEmptyDataStoreID ( const std::string &  id)

creates empty datastore with given id.

Definition at line 837 of file DataStore.cc.

838{
839 //does this id already exist?
840 if (m_idToIndexMap.count(id) > 0)
841 return;
842
843 int targetidx = m_entries.size();
844 m_idToIndexMap[id] = targetidx;
845
846 m_entries.push_back(DataStoreContents());
847}
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 826 of file DataStore.cc.

827{
828 //does this id already exist?
829 if (m_idToIndexMap.count(id) > 0)
830 return;
831
832 copyEntriesTo(id);
833 //copy actual contents, fixing pointers
834 copyContentsTo(id);
835}
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:849
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:945

◆ 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 1176 of file DataStore.cc.

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

◆ 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 986 of file DataStore.cc.

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

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

◆ switchID()

void switchID ( const std::string &  id)

switch to DataStore with given ID.

Definition at line 1143 of file DataStore.cc.

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

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: