Belle II Software light-2607-kasei
DataStore::SwitchableDataStoreContents Class Reference

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

Collaboration diagram for DataStore::SwitchableDataStoreContents:

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ switchID()

void switchID ( const std::string & id)

switch to DataStore with given ID.

Definition at line 1142 of file DataStore.cc.

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

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: