Belle II Software  release-08-01-10
DataStore.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/datastore/DataStore.h>
10 
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>
19 #include <framework/dataobjects/EventExtraInfo.h>
20 
21 #include <TClonesArray.h>
22 #include <TClass.h>
23 
24 #include <unordered_map>
25 #include <algorithm>
26 #include <cstdlib>
27 #include <iostream>
28 
29 using namespace std;
30 using namespace Belle2;
31 
32 namespace {
38  void cleanDataStore()
39  {
40  DataStore::Instance().reset();
41  }
42 
46  void fixAbsorbObjects(TClonesArray* from, TClonesArray* to)
47  {
48  to->AbsorbObjects(from, 0, from->GetEntriesFast() - 1);
49  }
50 }
51 
52 bool DataStore::s_DoCleanup = false;
53 
54 DataStore& DataStore::Instance()
55 {
56  static DataStore instance;
57  return instance;
58 }
59 
60 
61 DataStore::DataStore() : m_initializeActive(true), m_dependencyMap(new DependencyMap)
62 {
63 }
64 
66 {
67  if (s_DoCleanup) {
68  //release all memory in data store
69  reset();
70  }
71  delete m_dependencyMap;
72 }
73 
75 {
76  B2DEBUG(31, "DataStore::reset(): Removing all elements from DataStore");
77  m_initializeActive = true;
79 
80  for (int i = 0; i < c_NDurabilityTypes; i++)
81  reset((EDurability)i);
82 
84 }
85 
86 void DataStore::reset(EDurability durability)
87 {
88  m_storeEntryMap.reset(durability);
89 
90  //invalidate any cached relations (expect RelationArrays to remain valid)
92 }
93 
95 {
96  m_initializeActive = active;
97 
98  static bool firstCall = true;
99  if (firstCall) {
100  atexit(cleanDataStore);
101  firstCall = false;
102  }
103 }
104 
105 TClass* DataStore::getTClassFromDefaultObjectName(const std::string& objectName)
106 {
107  // First look for an name without the namespace Belle2::
108  TClass* cl = TClass::GetClass(("Belle2::" + objectName).c_str());
109  if (not cl) {
110  // If this fails look for a name that already has the full namespace.
111  cl = TClass::GetClass(objectName.c_str());
112  }
113  return cl;
114 }
115 
116 TClass* DataStore::getTClassFromDefaultArrayName(const std::string& arrayName)
117 {
118  if (arrayName.empty()) {
119  return nullptr;
120  } else if ('s' == arrayName.back()) {
121  std::string objectName = arrayName.substr(0, arrayName.size() - 1);
123  } else {
124  return nullptr;
125  }
126 }
127 
128 std::string DataStore::defaultObjectName(const std::string& classname)
129 {
130  const static string gfclass = "genfit::Track";
131  const static string gfobjectname = "GF2Track";
132  if (classname == gfclass)
133  return gfobjectname;
134  //Strip qualifiers like namespaces
135  size_t colon = classname.rfind(':');
136  if (colon != std::string::npos) {
137  return classname.substr(colon + 1);
138  }
139  return classname;
140 }
141 
142 
143 std::string DataStore::defaultObjectName(const TClass* t)
144 {
145  B2ASSERT("Cannot deduce default object name from null pointer TClass", t);
146  const std::string s = defaultObjectName(t->GetName());
147  return s;
148 }
149 
150 
151 std::string DataStore::objectName(const TClass* t, const std::string& name)
152 {
153  return ((name.empty()) ? defaultObjectName(t) : name);
154 }
155 
156 
157 std::string DataStore::defaultArrayName(const TClass* t)
158 {
159  const std::string s = defaultArrayName(defaultObjectName(t));
160  return s;
161 }
162 
163 
164 std::string DataStore::arrayName(const TClass* t, const std::string& name)
165 {
166  return ((name.empty()) ? defaultArrayName(t) : name);
167 }
168 
169 
170 bool DataStore::checkType(const StoreEntry& entry, const StoreAccessorBase& accessor) const
171 {
172  // Check whether the existing entry and the requested object are both arrays or both single objects
173  const char* entryType = (entry.isArray) ? "array" : "object";
174  if (entry.isArray != accessor.isArray()) {
175  B2FATAL("Existing entry '" << entry.name << "' is an " << entryType << " and the requested one an " << ((
176  accessor.isArray()) ? "array" : "object"));
177  }
178 
179  // Check whether the existing entry has the same type
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 " <<
183  accessor.getClass()->GetName());
184  }
185 
186  return true;
187 }
188 
189 
190 bool DataStore::registerEntry(const std::string& name, EDurability durability,
191  TClass* objClass, bool array, EStoreFlags storeFlags)
192 {
193  const StoreAccessorBase accessor(name, durability, objClass, array);
194  // Check whether this method is called in the initialization phase
195  if (!m_initializeActive) {
196  B2ERROR("Attempt to register " << accessor.readableName() <<
197  " outside of the initialization phase. Please move calls to registerInDataStore() into your Module's initialize() function.");
198  return false;
199  }
200  const bool dontwriteout = storeFlags & c_DontWriteOut;
201 
202  //add to current module's outputs
203  m_dependencyMap->getCurrentModuleInfo().addEntry(name, DependencyMap::c_Output, (objClass == RelationContainer::Class()));
204 
205  // Check whether the map entry already exists
206  const auto& it = m_storeEntryMap[durability].find(name);
207  if (it != m_storeEntryMap[durability].end()) {
208  StoreEntry& entry = it->second;
209 
210  // Complain about existing entry
211  if (storeFlags & c_ErrorIfAlreadyRegistered) {
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.");
214  return false;
215  }
216 
217  // Check whether the types match
218  if (!checkType(entry, accessor)) return false;
219 
220  // Check whether the persistency type matches
221  if (entry.dontWriteOut != dontwriteout) {
222  B2WARNING("Existing " << accessor.readableName() << " has different persistency type than requested. Changing to " <<
223  (dontwriteout ? "c_DontWriteOut" : "c_WriteOut") << ".");
224  entry.dontWriteOut = dontwriteout;
225  }
226 
227  B2DEBUG(100, "An " << accessor.readableName() << " was registered once more.");
228  return true;
229  }
230 
231  // check reserved names
232  if (array and name == "ALL") {
233  B2ERROR("Creating an array with the reserved name 'ALL' is not allowed!");
234  return false;
235  }
236 
237  // Add the DataStore entry
238  m_storeEntryMap[durability][name] = StoreEntry(array, objClass, name, dontwriteout);
239 
240  B2DEBUG(100, "Successfully registered " << accessor.readableName());
241  return true;
242 }
243 
244 bool DataStore::registerRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
245  EStoreFlags storeFlags, const std::string& namedRelation)
246 {
247  if (!fromArray.isArray())
248  B2FATAL(fromArray.readableName() << " is not an array!");
249  if (!toArray.isArray())
250  B2FATAL(toArray.readableName() << " is not an array!");
251 
252  // check the the namedRelation only contains regular characters
253  if (!std::regex_match(namedRelation, m_regexNamedRelationCheck))
254  B2FATAL("Named Relations can only contain alphabetic characters, given was: " << namedRelation);
255 
256  const std::string& relName = relationName(fromArray.getName(), toArray.getName(), namedRelation);
257  /*
258  if ((fromArray.notWrittenOut() or toArray.notWrittenOut()) and !(storeFlags & c_DontWriteOut)) {
259  B2WARNING("You're trying to register a persistent relation " << relName << " from/to an array which is not written out (DataStore::c_DontWriteOut flag)! Relation will also not be saved!");
260  storeFlags |= c_DontWriteOut;
261  }
262  */
263 
264  if (fromArray.getDurability() > durability or toArray.getDurability() > durability) {
265  B2FATAL("Tried to create a relation '" << relName << "' with a durability larger than the StoreArrays it relates");
266  }
267 
268  return DataStore::Instance().registerEntry(relName, durability, RelationContainer::Class(), false, storeFlags);
269 }
270 
271 bool DataStore::hasRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
272  const std::string& namedRelation)
273 {
274  // check that the input makes sense
275  if (!fromArray.isArray())
276  B2FATAL(fromArray.readableName() << " is not an array!");
277  if (!toArray.isArray())
278  B2FATAL(toArray.readableName() << " is not an array!");
279 
280  // check the the namedRelation only contains regular characters
281  if (!std::regex_match(namedRelation, m_regexNamedRelationCheck))
282  B2FATAL("Named Relations can only contain alphabetic characters, given was: " << namedRelation);
283 
284  // get the internal relation name from the name provided
285  const std::string& realname = relationName(fromArray.getName(), toArray.getName(), namedRelation);
286 
287  // check whether the map entry exists
288  const auto& it = m_storeEntryMap[durability].find(realname);
289  if (it != m_storeEntryMap[durability].end()) return true;
290 
291  return false;
292 }
293 
295 {
296  const auto& it = m_storeEntryMap[accessor.getDurability()].find(accessor.getName());
297 
298  if (it != m_storeEntryMap[accessor.getDurability()].end() and checkType((it->second), accessor)) {
299  return &(it->second);
300  } else {
301  return nullptr;
302  }
303 }
304 
305 
306 TObject** DataStore::getObject(const StoreAccessorBase& accessor)
307 {
308  StoreEntry* entry = getEntry(accessor);
309  if (!entry) {
310  return nullptr;
311  }
312  return &(entry->ptr);
313 }
314 
315 
316 bool DataStore::createObject(TObject* object, bool replace, const StoreAccessorBase& accessor)
317 {
318  StoreEntry* entry = getEntry(accessor);
319  if (!entry) {
320  B2ERROR("No " << accessor.readableName() <<
321  " exists in the DataStore, did you forget to register it in your Module's initialize() function? Note: direct accesses to it will crash!");
322  return false;
323  }
324 
325  if (entry->ptr && !replace && object != entry->object) {
326  B2ERROR("An " << accessor.readableName() << " was already created in the DataStore.");
327  return false;
328  }
329 
330  if (object) {
331  if (object != entry->object) {
332  delete entry->object;
333  entry->object = object;
334  }
335  entry->ptr = entry->object;
336  } else {
337  entry->recreate();
338  }
339 
340  return true;
341 }
342 
344 {
345  StoreEntry* fromEntry = getEntry(from);
346  StoreEntry* toEntry = getEntry(to);
347  if (!fromEntry)
348  B2FATAL("No " << from.readableName() << " exists in the DataStore!");
349  if (!toEntry)
350  B2FATAL("No " << to.readableName() << " exists in the DataStore!");
351  if (from.isArray() != to.isArray() or from.getClass() != to.getClass())
352  B2FATAL("cannot replace " << to.readableName() << " with " << from.readableName() << " (incompatible types)!");
353 
354  if (!fromEntry->ptr) {
355  //since we don't need to move any data, just invalidate toEntry instead.
356  toEntry->ptr = nullptr;
357  } else if (fromEntry->isArray) {
358  if (!toEntry->ptr)
359  toEntry->ptr = toEntry->object;
360  toEntry->getPtrAsArray()->Delete();
361 
362  fixAbsorbObjects(fromEntry->getPtrAsArray(), toEntry->getPtrAsArray());
363  updateRelationsObjectCache(*toEntry);
364  } else if (fromEntry->objClass == RelationContainer::Class()) {
365  if (!toEntry->ptr)
366  toEntry->ptr = toEntry->object;
367  auto* fromRel = static_cast<RelationContainer*>(fromEntry->ptr);
368  auto* toRel = static_cast<RelationContainer*>(toEntry->ptr);
369 
370  toRel->elements().Delete();
371 
372  fixAbsorbObjects(&fromRel->elements(), &toRel->elements());
373 
374  //indices need a rebuild
375  fromRel->setModified(true);
376  toRel->setModified(true);
377  } else {
378  delete toEntry->object;
379 
380  toEntry->object = fromEntry->ptr->Clone();
381  toEntry->ptr = toEntry->object;
382 
383  fromEntry->ptr = nullptr;
384  }
385 }
386 
388 {
389  const TClonesArray* array = static_cast<TClonesArray*>(entry.ptr);
390  const int nEntries = array->GetEntriesFast();
391  for (int i = 0; i < nEntries; i++) {
392  auto* relobj = static_cast<RelationsObject*>(array->At(i));
393  relobj->m_cacheArrayIndex = i;
394  relobj->m_cacheDataStoreEntry = &entry;
395  }
396 }
397 
398 bool DataStore::findStoreEntry(const TObject* object, DataStore::StoreEntry*& entry, int& index)
399 {
400  if (!entry or index < 0) {
401  //usually entry/index should be passed for RelationsObject,
402  //but there are exceptions -> let's check again
403  const auto* relObj = dynamic_cast<const RelationsObject*>(object);
404  if (relObj) {
405  entry = relObj->m_cacheDataStoreEntry;
406  index = relObj->m_cacheArrayIndex;
407  }
408  }
409  // check whether the cached information is (still) valid
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");
417  }
418  entry = nullptr;
419  index = -1;
420 
421  //searching for nullptr should be safe
422  if (!object)
423  return false;
424 
425  // search for the object and set the entry and index
426  const TClass* objectClass = object->IsA();
427  for (auto& mapEntry : m_storeEntryMap[c_Event]) {
428  if (mapEntry.second.ptr && mapEntry.second.isArray) {
429  const TClass* arrayClass = mapEntry.second.objClass;
430  if (arrayClass != objectClass)
431  continue;
432 
433  const TClonesArray* array = static_cast<TClonesArray*>(mapEntry.second.ptr);
434  if (object == array->Last()) {
435  //quickly find entry if it's at the end of the array
436  index = array->GetLast();
437  } else {
438  if (arrayClass->InheritsFrom(RelationsObject::Class())) {
439  //update cache for entire array
440  updateRelationsObjectCache(mapEntry.second);
441 
442  //if found, m_cacheArrayIndex is now correct, otherwise still -1
443  StoreEntry* objEntry = static_cast<const RelationsObject*>(object)->m_cacheDataStoreEntry;
444  index = static_cast<const RelationsObject*>(object)->m_cacheArrayIndex;
445  if (index >= 0 and objEntry) {
446  //if the cache of 'object' is filled, make sure to also set entry!
447  entry = objEntry;
448  return true;
449  }
450  } else {
451  //not a RelationsObject, so no caching
452  index = array->IndexOf(object);
453  }
454  }
455 
456  if (index >= 0) {
457  entry = &mapEntry.second;
458  return true;
459  }
460  }
461  }
462  return false;
463 }
464 
465 const std::vector<std::string>& DataStore::getArrayNames(const std::string& name, const TClass* arrayClass,
466  EDurability durability) const
467 {
468  static vector<string> arrayNames;
469  arrayNames.clear();
470  if (name.empty()) {
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);
475  } else {
476  const std::string& result = defaultArrayName(arrayClass->GetName());
477  classToArrayName[arrayClass] = result;
478  arrayNames.emplace_back(result);
479  }
480  } else if (name == "ALL") {
481  for (auto& mapEntry : m_storeEntryMap[durability]) {
482  if (mapEntry.second.object and mapEntry.second.isArray and mapEntry.second.objClass->InheritsFrom(arrayClass)) {
483  arrayNames.emplace_back(mapEntry.second.name);
484  }
485  }
486  } else {
487  arrayNames.emplace_back(name);
488  }
489  return arrayNames;
490 }
491 
492 void DataStore::addRelation(const TObject* fromObject, StoreEntry*& fromEntry, int& fromIndex, const TObject* toObject,
493  StoreEntry*& toEntry, int& toIndex, float weight, const std::string& namedRelation)
494 {
495  if (!fromObject or !toObject)
496  return;
497 
498  // get entry from which the relation points
499  if (!findStoreEntry(fromObject, fromEntry, fromIndex)) {
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.");
502  }
503 
504  // get entry to which the relation points
505  if (!findStoreEntry(toObject, toEntry, toIndex)) {
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.");
508  }
509 
510  // get the relations from -> to
511  const string& relationsName = relationName(fromEntry->name, toEntry->name, namedRelation);
512  const StoreEntryIter& it = m_storeEntryMap[c_Event].find(relationsName);
513  if (it == m_storeEntryMap[c_Event].end()) {
514  B2FATAL("No relation '" << relationsName <<
515  "' found. Please register it (using StoreArray::registerRelationTo()) before trying to add relations.");
516  }
517  StoreEntry* entry = &(it->second);
518 
519  // auto create relations if needed (both if null pointer, or uninitialised object read from TTree)
520  if (!entry->ptr)
521  entry->recreate();
522  auto* relContainer = static_cast<RelationContainer*>(entry->ptr);
523  if (relContainer->isDefaultConstructed()) {
524  relContainer->setFromName(fromEntry->name);
525  relContainer->setFromDurability(c_Event);
526  relContainer->setToName(toEntry->name);
527  relContainer->setToDurability(c_Event);
528  }
529 
530  // add relation
531  TClonesArray& relations = relContainer->elements();
532  new (relations.AddrAt(relations.GetLast() + 1)) RelationElement(fromIndex, toIndex, weight);
533 
534  std::shared_ptr<RelationIndexContainer<TObject, TObject>> relIndex =
535  RelationIndexManager::Instance().getIndexIfExists<TObject, TObject>(relationsName, c_Event);
536  if (relIndex) {
537  // add it to index (so we avoid expensive rebuilding later)
538  relIndex->index().emplace(fromIndex, toIndex, fromObject, toObject, weight);
539  } else {
540  //mark for rebuilding later on
541  relContainer->setModified(true);
542  }
543 }
544 
546  int& index, const TClass* withClass, const std::string& withName, const std::string& namedRelation)
547 {
548  if (searchSide == c_BothSides) {
549  auto result = getRelationsWith(c_ToSide, object, entry, index, withClass, withName, namedRelation);
550  const auto& fromResult = getRelationsWith(c_FromSide, object, entry, index, withClass, withName, namedRelation);
551  result.add(fromResult);
552  return result;
553  }
554 
555  std::vector<RelationEntry> result;
556 
557  // get StoreEntry for 'object'
558  if (!findStoreEntry(object, entry, index)) return RelationVectorBase();
559 
560  // get names of store arrays to search
561  const std::vector<string>& names = getArrayNames(withName, withClass);
562  vector<string> relationNames;
563 
564  // loop over found store arrays
565  for (const std::string& name : names) {
566  // get the relations from -> to
567  const string& relationsName = (searchSide == c_ToSide) ? relationName(entry->name, name, namedRelation) : relationName(name,
568  entry->name, namedRelation);
569  RelationIndex<TObject, TObject> relIndex(relationsName, c_Event);
570  if (!relIndex)
571  continue;
572 
573  const size_t prevsize = result.size();
574 
575  //get relations with object
576  if (searchSide == c_ToSide) {
577  for (const auto& rel : relIndex.getElementsFrom(object)) {
578  auto* const toObject = const_cast<TObject*>(rel.to);
579  if (toObject)
580  result.emplace_back(toObject, rel.weight);
581  }
582  } else {
583  for (const auto& rel : relIndex.getElementsTo(object)) {
584  auto* const fromObject = const_cast<TObject*>(rel.from);
585  if (fromObject)
586  result.emplace_back(fromObject, rel.weight);
587  }
588  }
589 
590  if (result.size() != prevsize)
591  relationNames.push_back(relationsName);
592  }
593 
594  return RelationVectorBase(entry->name, index, result, relationNames);
595 }
596 
597 RelationEntry DataStore::getRelationWith(ESearchSide searchSide, const TObject* object, DataStore::StoreEntry*& entry, int& index,
598  const TClass* withClass, const std::string& withName, const std::string& namedRelation)
599 {
600  if (searchSide == c_BothSides) {
601  RelationEntry result = getRelationWith(c_ToSide, object, entry, index, withClass, withName, namedRelation);
602  if (!result.object) {
603  result = getRelationWith(c_FromSide, object, entry, index, withClass, withName, namedRelation);
604  }
605  return result;
606  }
607 
608  // get StoreEntry for 'object'
609  if (!findStoreEntry(object, entry, index)) return RelationEntry(nullptr);
610 
611  // get names of store arrays to search
612  const std::vector<string>& names = getArrayNames(withName, withClass);
613 
614  // loop over found store arrays
615  for (const std::string& name : names) {
616  // get the relations from -> to
617  const string& relationsName = (searchSide == c_ToSide) ? relationName(entry->name, name, namedRelation) : relationName(name,
618  entry->name, namedRelation);
619  RelationIndex<TObject, TObject> relIndex(relationsName, c_Event);
620  if (!relIndex)
621  continue;
622 
623  // get first element
624  if (searchSide == c_ToSide) {
625  const RelationIndex<TObject, TObject>::Element* element = relIndex.getFirstElementFrom(object);
626  if (element && element->to) {
627  return RelationEntry(const_cast<TObject*>(element->to), element->weight);
628  }
629  } else {
630  const RelationIndex<TObject, TObject>::Element* element = relIndex.getFirstElementTo(object);
631  if (element && element->from) {
632  return RelationEntry(const_cast<TObject*>(element->from), element->weight);
633  }
634  }
635  }
636 
637  return RelationEntry(nullptr);
638 }
639 
640 std::vector<std::string> DataStore::getListOfRelatedArrays(const StoreAccessorBase& array) const
641 {
642  std::vector<std::string> arrays;
643  if (!array.isArray()) {
644  B2ERROR("getListOfRelatedArrays(): " << array.readableName() << " is not an array!");
645  return arrays;
646  }
647 
648  //loop over all arrays
649  EDurability durability = array.getDurability();
650  for (auto& mapEntry : m_storeEntryMap[durability]) {
651  if (mapEntry.second.isArray) {
652  const std::string& name = mapEntry.second.name;
653 
654  //check both from & to 'array'
655  for (int searchSide = 0; searchSide < c_BothSides; searchSide++) {
656  const string& relationsName = (searchSide == c_ToSide) ? relationName(array.getName(), name) : relationName(name, array.getName());
657  const StoreEntryConstIter& it = m_storeEntryMap[durability].find(relationsName);
658  if (it != m_storeEntryMap[durability].end())
659  arrays.emplace_back(name);
660  }
661  }
662  }
663 
664  return arrays;
665 }
666 std::vector<std::string> DataStore::getListOfArrays(const TClass* arrayClass, EDurability durability) const
667 {
668  return getArrayNames("ALL", arrayClass, durability);
669 }
670 
671 std::vector<std::string> DataStore::getListOfObjects(const TClass* objClass, EDurability durability) const
672 {
673  vector<string> list;
675  for (const auto& entrypair : map) {
676  if (!entrypair.second.isArray) {
677  const TObject* obj = entrypair.second.object;
678  if (dynamic_cast<const RelationContainer*>(obj))
679  continue; //ignore relations in list
680 
681  if (obj and obj->IsA()->InheritsFrom(objClass))
682  list.emplace_back(entrypair.first);
683  }
684  }
685  return list;
686 }
687 
688 std::vector<std::string> DataStore::getListOfRelations(EDurability durability) const
689 {
690  vector<string> list;
692  for (const auto& entrypair : map) {
693  if (!entrypair.second.isArray) {
694  const TObject* obj = entrypair.second.object;
695  if (dynamic_cast<const RelationContainer*>(obj))
696  list.emplace_back(entrypair.first);
697 
698  }
699  }
700  return list;
701 }
702 
703 std::vector<std::string> DataStore::getSortedListOfDataStore(EDurability durability) const
704 {
705  std::vector<string> list;
706  std::vector<std::string> mergeContent = getListOfObjects(TObject::Class(), durability);
707  list.insert(std::end(list), std::begin(mergeContent), std::end(mergeContent));
708  mergeContent = getListOfArrays(TObject::Class(), durability);
709  list.insert(std::end(list), std::begin(mergeContent), std::end(mergeContent));
710  mergeContent = getListOfRelations(durability);
711  list.insert(std::end(list), std::begin(mergeContent), std::end(mergeContent));
712  return list;
713 }
714 
716 {
717  B2DEBUG(100, "Invalidating objects for durability " << durability);
718  m_storeEntryMap.invalidateData(durability);
720 }
721 
723 {
724  if (m_initializeActive) {
726  (accessor.getClass() == RelationContainer::Class()));
727  } else {
728  B2FATAL("Attempt to require input " << accessor.readableName() <<
729  " outside of the initialization phase. Please move isRequired() calls into your Module's initialize() function.");
730  }
731 
732  if (!getEntry(accessor)) {
733  B2ERROR("The required " << accessor.readableName() << " does not exist. Maybe you forgot the module that registers it?");
734  return false;
735  }
736  return true;
737 }
738 
740 {
741  if (m_initializeActive) {
743  (accessor.getClass() == RelationContainer::Class()));
744  }
745 
746  return (getEntry(accessor) != nullptr);
747 }
748 
749 bool DataStore::requireRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
750  std::string const& namedRelation)
751 {
752  if (!m_initializeActive) {
753  B2FATAL("Attempt to require relation " << fromArray.readableName() << " -> " << toArray.readableName() <<
754  " outside of the initialization phase. Please move requireRelationTo() calls into your Module's initialize() function.");
755  }
756 
757  if (!fromArray.isArray())
758  B2FATAL(fromArray.readableName() << " is not an array!");
759  if (!toArray.isArray())
760  B2FATAL(toArray.readableName() << " is not an array!");
761 
762  const std::string& relName = relationName(fromArray.getName(), toArray.getName(), namedRelation);
763  return DataStore::Instance().requireInput(StoreAccessorBase(relName, durability, RelationContainer::Class(), false));
764 }
765 
766 bool DataStore::optionalRelation(const StoreAccessorBase& fromArray, const StoreAccessorBase& toArray, EDurability durability,
767  std::string const& namedRelation)
768 {
769  if (!fromArray.isArray())
770  B2FATAL(fromArray.readableName() << " is not an array!");
771  if (!toArray.isArray())
772  B2FATAL(toArray.readableName() << " is not an array!");
773 
774  const std::string& relName = relationName(fromArray.getName(), toArray.getName(), namedRelation);
775  return DataStore::Instance().optionalInput(StoreAccessorBase(relName, durability, RelationContainer::Class(), false));
776 }
777 
778 
779 void DataStore::createNewDataStoreID(const std::string& id)
780 {
782 }
783 
784 void DataStore::createEmptyDataStoreID(const std::string& id)
785 {
787 }
788 
789 std::string DataStore::currentID() const
790 {
791  return m_storeEntryMap.currentID();
792 }
793 
794 void DataStore::switchID(const std::string& id)
795 {
796  if (id == m_storeEntryMap.currentID())
797  return;
798 
799  //remember to clear caches
801 
803 }
804 
805 void DataStore::copyEntriesTo(const std::string& id, const std::vector<std::string>& entrylist_event, bool mergeEntries)
806 {
807  m_storeEntryMap.copyEntriesTo(id, entrylist_event, mergeEntries);
808 }
809 
810 void DataStore::copyContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
811 {
812  m_storeEntryMap.copyContentsTo(id, entrylist_event);
813 }
814 
815 void DataStore::mergeContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
816 {
817  m_storeEntryMap.mergeContentsTo(id, entrylist_event);
818 }
819 
820 
821 DataStore::SwitchableDataStoreContents::SwitchableDataStoreContents():
822  m_entries(1)
823 {
824  m_idToIndexMap[""] = 0;
825 }
826 
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 }
837 
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 }
849 
850 void DataStore::SwitchableDataStoreContents::copyEntriesTo(const std::string& id, const std::vector<std::string>& entrylist_event,
851  bool mergeEntries)
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 }
945 
946 void DataStore::SwitchableDataStoreContents::copyContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
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 }
986 
987 void DataStore::SwitchableDataStoreContents::mergeContentsTo(const std::string& id, const std::vector<std::string>& entrylist_event)
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 }
1143 
1145 {
1146  //switch
1147  m_currentID = id;
1148  m_currentIdx = m_idToIndexMap.at(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 }
1153 
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 }
1166 
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 }
1176 
1178 {
1179  for (auto& map : m_entries)
1180  for (auto& mapEntry : map[durability])
1181  mapEntry.second.invalidate();
1182 }
const std::string & currentID() const
returns ID of current DataStore.
Definition: DataStore.h:603
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
Definition: DataStore.cc:827
void createEmptyDataStoreID(const std::string &id)
creates empty datastore with given id.
Definition: DataStore.cc:838
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 switchID(const std::string &id)
switch to DataStore with given ID.
Definition: DataStore.cc:1144
std::map< std::string, int > m_idToIndexMap
Maps DataStore ID to index in m_entries.
Definition: DataStore.h:616
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: DataStore.cc:987
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
void clear()
same as calling reset() for all durabilities + all non-default datastore IDs are removed.
Definition: DataStore.cc:1154
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition: DataStore.cc:1167
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
Definition: DataStore.cc:1177
In the store you can park objects that have to be accessed by various modules.
Definition: DataStore.h:51
static std::string objectName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition: DataStore.cc:151
StoreEntryMap::const_iterator StoreEntryConstIter
const_iterator for a StoreEntry map.
Definition: DataStore.h:89
std::array< StoreEntryMap, c_NDurabilityTypes > DataStoreContents
StoreEntry maps for each durability.
Definition: DataStore.h:90
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'.
Definition: DataStore.cc:640
std::vector< std::string > getListOfRelations(EDurability durability) const
Returns a list of names of StoreObjPtr-objects whose class is (or inherits from) RelationContainer.
Definition: DataStore.cc:688
void createNewDataStoreID(const std::string &id)
creates new datastore with given id, copying the registered objects/arrays from the current one.
Definition: DataStore.cc:779
void createEmptyDataStoreID(const std::string &id)
creates empty datastore with given id.
Definition: DataStore.cc:784
bool findStoreEntry(const TObject *object, StoreEntry *&entry, int &index)
Find an object in an array in the data store.
Definition: DataStore.cc:398
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.
Definition: DataStore.cc:465
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:805
static std::string defaultObjectName()
Return the default storage name for an object of the given type.
Definition: DataStore.h:127
bool checkType(const StoreEntry &entry, const StoreAccessorBase &accessor) const
Check whether the given entry and the requested class match.
Definition: DataStore.cc:170
bool optionalRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, std::string const &namedRelation)
Register the given relation as an optional input.
Definition: DataStore.cc:766
EStoreFlags
Flags describing behaviours of objects etc.
Definition: DataStore.h:69
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
void switchID(const std::string &id)
switch to DataStore with given ID.
Definition: DataStore.cc:794
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
StoreEntryMap::iterator StoreEntryIter
Iterator for a StoreEntry map.
Definition: DataStore.h:88
const std::regex m_regexNamedRelationCheck
Regular expression to check that no special characters and no white spaces are in the string given fo...
Definition: DataStore.h:634
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...
Definition: DataStore.cc:116
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: DataStore.cc:815
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.
Definition: DataStore.cc:492
bool registerRelation(const StoreAccessorBase &fromArray, const StoreAccessorBase &toArray, EDurability durability, EStoreFlags storeFlags, const std::string &namedRelation)
Register a relation in the DataStore map.
Definition: DataStore.cc:244
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.
Definition: DataStore.cc:105
StoreEntryMap & getStoreEntryMap(EDurability durability)
Get a reference to the object/array map.
Definition: DataStore.h:325
DependencyMap * m_dependencyMap
Collect information about the dependencies between modules.
Definition: DataStore.h:637
~DataStore()
Destructor.
Definition: DataStore.cc:65
static std::string defaultArrayName()
Return the default storage name for an array of the given type.
Definition: DataStore.h:157
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.
Definition: DataStore.cc:666
ESearchSide
Which side of relations should be returned?
Definition: DataStore.h:76
@ c_BothSides
Combination of c_FromSide and c_ToSide.
Definition: DataStore.h:79
@ c_FromSide
Return relations/objects pointed from (to a given object).
Definition: DataStore.h:77
@ c_ToSide
Return relations/objects pointed to (from a given object).
Definition: DataStore.h:78
static void updateRelationsObjectCache(StoreEntry &entry)
For an array containing RelationsObjects, update index and entry cache for entire contents.
Definition: DataStore.cc:387
static const int c_NDurabilityTypes
Number of Durability Types.
Definition: DataStore.h:63
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.
Definition: DataStore.cc:671
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:810
bool requireInput(const StoreAccessorBase &accessor)
Produce ERROR message if no entry of the given type is registered in the DataStore.
Definition: DataStore.cc:722
EDurability
Durability types.
Definition: DataStore.h:58
@ 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
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...
Definition: DataStore.cc:749
std::string currentID() const
returns ID of current DataStore.
Definition: DataStore.cc:789
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
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.
Definition: DataStore.cc:271
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:94
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.
Definition: DataStore.h:180
static bool s_DoCleanup
Global flag to to decide if we can do normal cleanup.
Definition: DataStore.h:100
void reset()
Clears contents of the datastore (all durabilities)
Definition: DataStore.cc:74
StoreEntry * getEntry(const StoreAccessorBase &accessor)
Check whether an entry with the correct type is registered in the DataStore map and return it.
Definition: DataStore.cc:294
void invalidateData(EDurability durability)
Clears all registered StoreEntry objects of a specified durability, invalidating all objects.
Definition: DataStore.cc:715
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.
Definition: DataStore.cc:545
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.
Definition: DataStore.cc:597
bool createObject(TObject *object, bool replace, const StoreAccessorBase &accessor)
Create a new object/array in the DataStore or add an existing one.
Definition: DataStore.cc:316
TObject ** getObject(const StoreAccessorBase &accessor)
Get a pointer to a pointer of an object in the DataStore.
Definition: DataStore.cc:306
static std::string arrayName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition: DataStore.cc:164
bool m_initializeActive
True if modules are currently being initialized.
Definition: DataStore.h:628
bool registerEntry(const std::string &name, EDurability durability, TClass *objClass, bool array, EStoreFlags storeFlags)
Register an entry in the DataStore map.
Definition: DataStore.cc:190
bool optionalInput(const StoreAccessorBase &accessor)
Register the given object/array as an optional input.
Definition: DataStore.cc:739
SwitchableDataStoreContents m_storeEntryMap
Maps (name, durability) key to StoreEntry objects.
Definition: DataStore.h:621
void replaceData(const StoreAccessorBase &from, const StoreAccessorBase &to)
For two StoreAccessors of same type, move all data in 'from' into 'to', discarding previous contents ...
Definition: DataStore.cc:343
std::map< std::string, StoreEntry > StoreEntryMap
Map for StoreEntries.
Definition: DataStore.h:87
Collect information about the dependencies between modules.
Definition: DependencyMap.h:29
@ c_Input
required input.
Definition: DependencyMap.h:33
@ c_Output
registered output.
Definition: DependencyMap.h:35
@ c_OptionalInput
optional input.
Definition: DependencyMap.h:34
ModuleInfo & getCurrentModuleInfo()
Get info for current module.
Definition: DependencyMap.h:63
void clear()
Reset all collected data.
Definition: DependencyMap.h:69
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.
TClonesArray & elements()
Get reference to the elements.
const std::string & getFromName() const
Get name of the StoreArray we relate from.
void setFromName(const std::string &name)
Set 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.
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.
Definition: RelationIndex.h:76
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.
Struct for relations.
Definition: RelationEntry.h:24
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
TClonesArray * getPtrAsArray() const
Return ptr cast to TClonesArray.
Definition: StoreEntry.cc:83
bool dontWriteOut
Flag that indicates whether the object should be written to the output by default.
Definition: StoreEntry.h:40
TObject * object
The pointer to the actual object.
Definition: StoreEntry.h:48
bool isArray
Flag that indicates whether the object is a TClonesArray.
Definition: StoreEntry.h:39
std::string name
Name of the entry.
Definition: StoreEntry.h:53
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