Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
TAuxStore.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 // Local include(s).
5 
6 #include "isRegisteredType.h"
7 #include "lookupVectorType.h"
12 
13 // Athena include(s).
18 #include "CxxUtils/as_const_ptr.h"
20 #include "xAODCore/tools/IOStats.h"
22 
23 // ROOT include(s).
24 #include <TBranch.h>
25 #include <TBranchElement.h>
26 #include <TClass.h>
27 #include <TError.h>
28 #include <TROOT.h>
29 #include <TStreamerElement.h>
30 #include <TStreamerInfo.h>
31 #include <TString.h>
32 #include <TTree.h>
33 #include <TVirtualCollectionProxy.h>
34 
35 // System include(s):
36 #include <cassert>
37 #include <format>
38 #include <sstream>
39 #include <stdexcept>
40 
41 namespace {
42 
44 bool isPrimitiveBranch(TBranch& br) {
45 
46  // The variables needed for the check:
47  ::TClass* cl = nullptr;
48  ::EDataType dType = kOther_t;
49 
50  // Get the variable type from the branch:
51  if (br.GetExpectedType(cl, dType)) {
52  ::Error("::isPrimitiveBranch",
53  XAOD_MESSAGE("Couldn't determine the type of branch "
54  "\"%s\""),
55  br.GetName());
56  return false;
57  }
58 
59  // The check is made using the data type variable:
60  return ((dType != kOther_t) && (dType != kNoType_t) && (dType != kVoid_t));
61 }
62 
80 bool isContainerBranch(TBranch& br, SG::auxid_t auxid) {
81 
82  // For unknown types it doesn't matter if the branch describes a
83  // container or a single element.
84  if (!xAOD::details::isRegisteredType(auxid)) {
85  return true;
86  }
87 
88  // The variables needed for the check:
89  ::TClass* cl = nullptr;
90  ::EDataType dType = kOther_t;
91 
92  // Get the variable type from the branch:
93  if (br.GetExpectedType(cl, dType)) {
94  ::Error("::isContainerBranch",
95  XAOD_MESSAGE("Couldn't determine the type of branch \"%s\""),
96  br.GetName());
97  return false;
98  }
99 
100  // If there is no class associated with the branch then it should be
101  // a branch describing a standalone object. (As it should be a
102  // "primitive" branch in this case.)
103  if (!cl) {
104  return false;
105  }
106 
107  // If there is a class, ask for the type_info of its type:
108  const std::type_info* root_ti = cl->GetTypeInfo();
109  if (!root_ti) {
110  // This may be an emulated class. One known case is when the type name
111  // is saved as "basic_string<char>" rather than "string" by Athena I/O.
112  // (It's not fully understood why this happens for dynamic branches...)
113  // So, let's see if we can get a functional TClass by massaging the
114  // type name a bit.
115  ::TString typeName(cl->GetName());
116  typeName.ReplaceAll("basic_string<char>", "string");
117  ::TClass* newCl = ::TClass::GetClass(typeName);
118  if (newCl) {
119  root_ti = newCl->GetTypeInfo();
120  }
121  }
122  if (!root_ti) {
123  ::Error("::isContainerBranch",
124  XAOD_MESSAGE("Couldn't get an std::type_info object out of "
125  "branch \"%s\" of type \"%s\""),
126  br.GetName(), cl->GetName());
127  return false;
128  }
129 
130  // Ask for the auxiliary type infos:
131  const std::type_info* aux_obj_ti =
133  if (!aux_obj_ti) {
134  ::Error("::isContainerBranch",
135  XAOD_MESSAGE("Couldn't get std::type_info object for "
136  "auxiliary id: %i"),
137  static_cast<int>(auxid));
138  return false;
139  }
140  const std::type_info* aux_vec_ti =
142  if (!aux_vec_ti) {
143  ::Error("::isContainerBranch",
144  XAOD_MESSAGE("Couldn't get std::type_info object for "
145  "auxiliary id: %i"),
146  static_cast<int>(auxid));
147  return false;
148  }
149 
150  // Check which one the ROOT type info agrees with:
151  if (*root_ti == *aux_obj_ti) {
152  // This branch describes a single object:
153  return false;
154  } else if (*root_ti == *aux_vec_ti) {
155  // This branch describes a container of objects:
156  return true;
157  }
158 
159  // For enum and vector<enum> types (PFO...) the type given by
160  // the aux type registry is vector<int>. We have to take it into account
161  // here...
162  if (cl->GetCollectionProxy() && (*aux_vec_ti == typeid(std::vector<int>))) {
163  return true;
164  }
165 
166  TClass* cl2 = xAOD::details::lookupVectorType(*cl);
167  if (cl2) {
168  if (*cl2->GetTypeInfo() == *aux_vec_ti) {
169  return true;
170  }
171  }
172 
173  // If we got this far, the branch may have undergone schema evolution. If
174  // it's one that ROOT can deal with itself, then we should still be able
175  // to read the branch with this code.
176  //
177  // Note that even after looking at the ROOT source code, I'm still not
178  // 100% sure whether we would need to delete the objects returned by
179  // TClass::GetConversionStreamerInfo(...) in this code. :-( But based on
180  // general experience with the ROOT code, I'm going to say no...
181  TClass* aux_vec_cl =
182  TClass::GetClass(xAOD::Utils::getTypeName(*aux_vec_ti).c_str());
183  if (aux_vec_cl &&
184  aux_vec_cl->GetConversionStreamerInfo(cl, cl->GetClassVersion())) {
185  return true;
186  }
187  TClass* aux_obj_cl =
188  TClass::GetClass(xAOD::Utils::getTypeName(*aux_obj_ti).c_str());
189  if (aux_obj_cl &&
190  aux_obj_cl->GetConversionStreamerInfo(cl, cl->GetClassVersion())) {
191  return false;
192  }
193 
194  // If neither, then something went wrong...
195  ::Error("::isContainerBranch",
196  XAOD_MESSAGE("Couldn't determine if branch describes a single "
197  "object or a container"));
198  ::Error("::isContainerBranch", XAOD_MESSAGE("ROOT type : %s"),
199  xAOD::Utils::getTypeName(*root_ti).c_str());
200  ::Error(":isContainerBranch", XAOD_MESSAGE("Object type: %s"),
201  xAOD::Utils::getTypeName(*aux_obj_ti).c_str());
202  ::Error("::isContainerBranch", XAOD_MESSAGE("Vector type: %s"),
203  xAOD::Utils::getTypeName(*aux_vec_ti).c_str());
204  return false;
205 }
206 
212 class TBranchHandle {
213 
214  public:
216  TBranchHandle(bool staticBranch, bool primitiveBranch,
217  const std::type_info* ti, void* obj, SG::auxid_t auxid,
218  std::string_view prefix)
219  : m_branch(0),
220  m_entry(0),
221  m_object(obj),
222  m_static(staticBranch),
223  m_primitive(primitiveBranch),
224  m_typeInfo(ti),
225  m_needsRead(true),
226  m_auxid(auxid),
227  m_prefix(prefix) {}
228 
236  ::Int_t getEntry() {
237 
238  // A little sanity check:
239  if (!m_branch) {
240  // This is no longer an error. We can have such objects for
241  // decorations, which don't exist on the input.
242  return 0;
243  }
244 
245  // Update the I/O monitoring:
246  xAOD::IOStats::instance().stats().readBranch(std::string{m_prefix},
247  m_auxid);
248 
249  // Make sure that the branch is associated to a tree
250  // as the entry to be read is retrieved from the tree
251  if (!m_branch->GetTree()) {
252  Error(
253  "xAOD::TAuxStore::TBranchHandle::getEntry",
254  XAOD_MESSAGE("Branch=%s is not associated to any tree while reading "
255  "of branches within this class relies on that"),
256  m_branch->GetName());
257  return -1;
258  }
259 
260  // Get the entry that should be read
261  // The entry to be read is set with TTree::LoadTree()
262  // NB: for a branch from a friend tree and if the friend tree has an index
263  // built, then the entry to read is found when calling the TTree::LoadTree()
264  // function that matches the major and minor values between the main tree
265  // and the friend tree
266  ::Long64_t entry = m_branch->GetTree()->GetReadEntry();
267 
268  if (entry < 0) {
269  // Raise error as it implies
270  // either that the TTree::LoadTree() function has not been called
271  // or
272  // the entry requested to be read by the user
273  // is not corresponding to any entry for the friend tree
274  Error("xAOD::TAuxStore::TBranchHandle::getEntry",
275  XAOD_MESSAGE(
276  "Entry to read is not set for branch=%s from tree=%s. "
277  "It is either because TTree::LoadTree(entry) was not called "
278  "beforehand in the TEvent class OR "
279  "the entry requested to be read for the main tree is not "
280  "corresponding to an event for the friend tree"),
281  m_branch->GetName(), m_branch->GetTree()->GetName());
282  return -1;
283  }
284 
285  // Check if anything needs to be done:
286  if ((entry == m_entry) && (!m_needsRead)) {
287  return 0;
288  }
289 
290  // Switch the branch in the right mode:
291  if (!m_primitive) {
292  if ((m_branch->GetMakeClass() != m_static) &&
293  (!m_branch->SetMakeClass(m_static))) {
294  ::Error("xAOD::TAuxStore::TBranchHandle::getEntry",
295  XAOD_MESSAGE("Failed to call SetMakeClass(%i) on "
296  "branch \"%s\""),
297  static_cast<int>(m_static), m_branch->GetName());
298  return -1;
299  }
300  }
301 
302  // Load the entry.
303  const ::Int_t nbytes = m_branch->GetEntry(entry);
304 
305  // If the load was successful, remember that we loaded this entry.
306  if (nbytes >= 0) {
307  m_entry = entry;
308  // The reading will now be done:
309  m_needsRead = false;
310  }
311 
312  // Return the number of bytes read.
313  return nbytes;
314  }
315 
324  ::TBranch** branchPtr() { return &m_branch; }
325 
334  void* objectPtr() { return m_object; }
335 
353  void* inputObjectPtr() {
354  // Return the correct pointer:
355  if (m_static || m_primitive) {
356  return m_object;
357  } else {
358  return &m_object;
359  }
360  }
372  void* outputObjectPtr() {
373  // Return the correct pointer:
374  if (m_primitive) {
375  return m_object;
376  } else {
377  return &m_object;
378  }
379  }
381  const std::type_info* typeInfo() const { return m_typeInfo; }
395  void reset() { m_needsRead = true; }
396 
397  private:
399  ::TBranch* m_branch;
401  ::Long64_t m_entry;
403  void* m_object;
405  bool m_static;
407  bool m_primitive;
409  const std::type_info* m_typeInfo;
411  bool m_needsRead;
413  SG::auxid_t m_auxid;
415  std::string_view m_prefix;
416 
417 }; // class TBranchHandle
418 
419 } // namespace
420 
421 namespace xAOD {
422 
424 
443 
444  // Check if an input tree is even available:
445  if (!m_inTree) {
446  // It's not an error if it isn't.
447  return StatusCode::SUCCESS;
448  }
449 
450  // Check if the input was already scanned:
451  if (m_inputScanned) {
452  return StatusCode::SUCCESS;
453  }
454 
455  // Get a list of all branches in the tree:
456  TObjArray* branches = m_inTree->GetListOfBranches();
457 
458  // Check each of them:
459  for (Int_t i = 0; i < branches->GetEntriesFast(); ++i) {
460 
461  // The name of this top-level branch:
462  const TString brName = branches->At(i)->GetName();
463 
464  // Access the branch pointer:
465  TBranch* br = dynamic_cast<TBranch*>(branches->At(i));
466  if (!br) {
467  ::Fatal("xAOD::TAuxStore::impl::scanInputTree",
468  XAOD_MESSAGE("Logic error detected"));
469  }
470 
471  // For top-level stores let's scan the static branches as well:
472  if (m_data.m_topStore && (brName == m_data.m_prefix)) {
473 
474  // Make sure the object has been instantiated so that aux data
475  // registrations will have been done.
476  br->SetAddress(0);
477 
478  // Get a list of its sub-branches:
479  TObjArray* sbranches = br->GetListOfBranches();
480 
481  // ...and then loop over them:
482  for (Int_t j = 0; j < sbranches->GetEntriesFast(); ++j) {
483 
484  // The name of the sub-branch:
485  const TString brName = sbranches->At(j)->GetName();
486 
487  // Try to make a variable name out of the branch name:
488  const TString auxName =
489  brName(brName.Index(".") + 1, brName.Length());
490 
491  // Skip this entry if it refers to a base class:
492  if (auxName.BeginsWith("xAOD::") || auxName.BeginsWith("SG::") ||
493  (auxName == "ILockable")) {
494  continue;
495  }
496 
497  // The sub-branch:
498  ::TBranch* sbr = dynamic_cast< ::TBranch*>(sbranches->At(j));
499  if (!sbr) {
500  ::Fatal("xAOD::TAuxStore::impl::scanInputTree",
501  XAOD_MESSAGE("Logic error detected"));
502  }
503 
504  // Leave the rest up to the function that is shared with the
505  // dynamic branches:
506  RETURN_CHECK("xAOD::TAuxStore::impl::scanInputTree",
507  setupAuxBranch(*sbr, auxName, true));
508  }
509 
510  // Don't check the rest of the loop's body:
511  continue;
512  }
513 
514  // Check if it has the right prefix to be a dynamic variable:
515  if (!brName.BeginsWith(m_data.m_dynPrefix.data())) {
516  continue;
517  }
518  // It's possible to create dynamic variables with an empty name
519  // as well. Which is a bug. Such variables are just ignored
520  // for now.
521  if (brName == m_data.m_dynPrefix) {
522  ::Warning("xAOD::TAuxStore::impl::scanInputTree",
523  "Dynamic branch with empty name found on container: %s",
524  m_data.m_prefix.data());
525  continue;
526  }
527 
528  // The auxiliary property name:
529  const TString auxName = brName(brName.Index(".") + 1, brName.Length());
530 
531  // Leave the rest up to the function that is shared with the
532  // dynamic branches:
533  RETURN_CHECK("xAOD::TAuxStore::impl::scanInputTree",
534  setupAuxBranch(*br, auxName, false));
535  }
536 
537  // Okay, the input was successfully scanned:
538  m_inputScanned = true;
539 
540  // Return gracefully:
541  return StatusCode::SUCCESS;
542  }
543 
545  const std::type_info* auxBranchType(
546  ::TBranch& br, std::string_view auxName, bool staticBranch,
547  std::string* expectedClassName = nullptr) {
548 
549  // Get the branch's type:
550  ::TClass* expectedClass = nullptr;
551  ::EDataType expectedType = kOther_t;
552  if (br.GetExpectedType(expectedClass, expectedType) &&
553  ((!staticBranch) || (!auxName.starts_with("m_")))) {
554  ::Warning("xAOD::TAuxStore::impl::auxBranchType",
555  "Couldn't get the type of branch \"%s\"", br.GetName());
556  }
557 
558  // Check for schema evolution:
559  // If a branch has automatic schema evolution from one class to another,
560  // then what we get from GetExpectedType will be the on-disk class.
561  // What we have in memory is given by GetCurrentClass.
562  if (expectedClass) {
563  if (TBranchElement* bre = dynamic_cast<TBranchElement*>(&br)) {
564  TClass* newClass = bre->GetCurrentClass();
565  if (newClass && newClass != expectedClass) {
566  expectedClass = newClass;
567  }
568  }
569  if (expectedClassName) {
570  *expectedClassName = expectedClass->GetName();
571  }
572  }
573 
574  // If this is a primitive variable, and we're still not sure whether this
575  // is a store for an object or a container, the answer is given...
576  if ((!expectedClass) &&
579  }
580 
581  // Get the type_info of the branch.
582  const std::type_info* ti = nullptr;
584  if (expectedClass) {
585  ti = expectedClass->GetTypeInfo();
586  } else {
587  ti = &(Utils::getTypeInfo(expectedType));
588  }
589  } else {
590  if (!expectedClass) {
591  if ((!staticBranch) || (!auxName.starts_with("m_"))) {
592  ::Warning("xAOD::TAuxStore::impl::auxBranchType",
593  "Couldn't get the type of branch \"%s\"", br.GetName());
594  }
595  } else {
596  ::TVirtualCollectionProxy* prox = expectedClass->GetCollectionProxy();
597 
598  if (!prox) {
599  TClass* cl2 = details::lookupVectorType(*expectedClass);
600  if (cl2) {
601  prox = cl2->GetCollectionProxy();
602  }
603  }
604 
605  if (!prox) {
606  if ((!staticBranch) || (!auxName.starts_with("m_"))) {
607  ::Warning("xAOD::TAuxStore::impl::auxBranchType",
608  "Couldn't get the type of branch \"%s\"", br.GetName());
609  }
610  } else {
611  if (prox->GetValueClass()) {
612  ti = prox->GetValueClass()->GetTypeInfo();
613  } else {
614  ti = &(Utils::getTypeInfo(prox->GetType()));
615  }
616  }
617  }
618  }
619 
620  return ti;
621  }
622 
641  StatusCode setupAuxBranch(::TBranch& br, std::string_view auxName,
642  bool staticBranch) {
643 
644  // Get the (on disk) type of the branch.
645  std::string expectedClassName;
646  const std::type_info* ti =
647  auxBranchType(br, auxName, staticBranch, &expectedClassName);
648  if (ti == nullptr) {
649  // If we didn't find a type_info for the branch, give up now...
650  return StatusCode::SUCCESS;
651  }
652 
653  // Get the registry:
655 
656  // Check if the registry already knows this variable name. If yes, let's
657  // use the type known by the registry. To be able to deal with simple
658  // schema evolution in dynamic branches.
659  if (const SG::auxid_t regAuxid = registry.findAuxID(std::string{auxName});
660  regAuxid != SG::null_auxid) {
661  m_data.m_auxIDs.insert(regAuxid);
662  return StatusCode::SUCCESS;
663  }
664 
666  SG::auxid_t linked_auxid = SG::null_auxid;
667 
668  if (SG::AuxTypeRegistry::isLinkedName(std::string{auxName})) {
670  } else if (SG::AuxTypeRegistry::classNameHasLink(expectedClassName)) {
671  std::string linkedAttr =
672  SG::AuxTypeRegistry::linkedName(std::string{auxName});
673  std::string linkedBranch = SG::AuxTypeRegistry::linkedName(br.GetName());
674  ::TBranch* lbr = m_inTree->GetBranch(linkedBranch.c_str());
675  const std::type_info* lti = nullptr;
676  if (lbr) {
677  lti = auxBranchType(*lbr, linkedAttr, staticBranch);
678  }
679  if (lti) {
680  linked_auxid = registry.getAuxID(
681  *lti, linkedAttr, "",
683  }
684  if (linked_auxid == SG::null_auxid) {
685  ::Error("xAOD::TAuxStore::impl::setupAuxBranch",
686  "Could not find linked variable for %s type %s", auxName.data(),
687  expectedClassName.c_str());
688  }
689  }
690 
691  // Check for an auxiliary ID for this branch:
692  SG::auxid_t auxid =
693  registry.getAuxID(*ti, std::string{auxName}, "", flags, linked_auxid);
694 
695  // First try to find a compiled factory for the vector type:
696  if (auxid == SG::null_auxid) {
697 
698  // Construct the name of the factory's class:
699  // But be careful --- if we don't exactly match the name
700  // in TClassTable, then we may trigger autoparsing. Besides the
701  // resource usage that implies, that can lead to crashes in dbg
702  // builds due to cling bugs.
703  std::string tn = Utils::getTypeName(*ti);
704  if (tn.starts_with("std::vector<")) {
705  tn.erase(0, 5);
706  }
707  std::string fac_class_name =
708  "SG::AuxTypeVectorFactory<" + tn + ",allocator<" + tn;
709  if (fac_class_name[fac_class_name.size() - 1] == '>') {
710  fac_class_name += ' ';
711  }
712  fac_class_name += "> >";
713 
714  // Look for the dictionary of this type:
715  ::TClass* fac_class = TClass::GetClass(fac_class_name.c_str());
716  if (fac_class && fac_class->IsLoaded()) {
717  ::TClass* base_class = ::TClass::GetClass("SG::IAuxTypeVectorFactory");
718  if (base_class && base_class->IsLoaded()) {
719  const Int_t offs = fac_class->GetBaseClassOffset(base_class);
720  if (offs >= 0) {
721  void* fac_vp = fac_class->New();
722  if (fac_vp) {
723  unsigned long tmp =
724  reinterpret_cast<unsigned long>(fac_vp) + offs;
726  reinterpret_cast<SG::IAuxTypeVectorFactory*>(tmp);
727  registry.addFactory(
728  *ti, *fac->tiAlloc(),
729  std::unique_ptr<SG::IAuxTypeVectorFactory>(fac));
730  auxid = registry.getAuxID(*ti, std::string{auxName}, "", flags,
731  linked_auxid);
732  }
733  }
734  }
735  }
736  }
737 
738  // If that didn't succeed, let's assign a generic factory to this type:
739  if (auxid == SG::null_auxid && linked_auxid == SG::null_auxid) {
740 
741  // Construct the name of the vector type:
742  std::string vec_class_name = "std::vector<" + Utils::getTypeName(*ti);
743  if (vec_class_name[vec_class_name.size() - 1] == '>') {
744  vec_class_name += ' ';
745  }
746  vec_class_name += '>';
747 
748  // Get the dictionary for the type:
749  ::TClass* vec_class = ::TClass::GetClass(vec_class_name.c_str());
750  if (vec_class && vec_class->IsLoaded()) {
751  auto fac = std::make_unique<TAuxVectorFactory>(vec_class);
752  if (fac->tiAlloc()) {
753  const std::type_info* tiAlloc = fac->tiAlloc();
754  registry.addFactory(*ti, *tiAlloc, std::move(fac));
755  } else {
756  std::string tiAllocName = fac->tiAllocName();
757  registry.addFactory(*ti, tiAllocName, std::move(fac));
758  }
759  auxid = registry.getAuxID(*ti, std::string{auxName}, "",
761  } else {
762  ::Warning("xAOD::TAuxStore::impl::setupAuxBranch",
763  "Couldn't find dictionary for type: %s",
764  vec_class_name.c_str());
765  }
766  }
767 
768  // Check if we succeeded:
769  if (auxid == SG::null_auxid) {
770  if (linked_auxid != SG::null_auxid) {
771  ::Error("xAOD::TAuxStore::impl::setupAuxBranch",
772  XAOD_MESSAGE("Dynamic ROOT vector factory not implemented for "
773  "linked types; branch "
774  "\"%s\""),
775  br.GetName());
776  } else {
777  ::Error("xAOD::TAuxStore::impl::setupAuxBranch",
778  XAOD_MESSAGE("Couldn't assign auxiliary ID to branch "
779  "\"%s\""),
780  br.GetName());
781  }
782  return StatusCode::FAILURE;
783  }
784 
785  // Remember the auxiliary ID:
786  m_data.m_auxIDs.insert(auxid);
787  return StatusCode::SUCCESS;
788  }
789 
792 
794  int m_basketSize = 2048;
796  int m_splitLevel = 0;
797 
799  ::TTree* m_inTree = nullptr;
801  ::TTree* m_outTree = nullptr;
802 
804  bool m_inputScanned = false;
805 
807  std::vector<std::unique_ptr<TBranchHandle> > m_branches;
809  std::vector<bool> m_branchesWritten;
812  std::vector<bool> m_missingBranches;
813 
815  mutable mutex_t m_mutex;
816 };
817 
818 TAuxStore::TAuxStore(std::string_view prefix, bool topStore, EStructMode mode,
819  int basketSize, int splitLevel)
820  : details::AuxStoreBase(topStore, mode),
821  m_impl{std::make_unique<impl>(m_data, basketSize, splitLevel)} {
822 
823  setPrefix(prefix);
824 }
825 
826 TAuxStore::~TAuxStore() = default;
827 
828 void TAuxStore::setPrefix(std::string_view prefix) {
829 
832  reset();
833 }
834 
836 
837  assert(m_impl);
838  return m_impl->m_basketSize;
839 }
840 
842 
843  assert(m_impl);
844  m_impl->m_basketSize = value;
845 }
846 
848 
849  assert(m_impl);
850  return m_impl->m_splitLevel;
851 }
852 
854 
855  assert(m_impl);
856  m_impl->m_splitLevel = value;
857 }
858 
864 StatusCode TAuxStore::readFrom(::TTree& tree, bool printWarnings) {
865 
866  assert(m_impl);
867 
868  // Make sure that everything will be re-read after this:
869  reset();
870 
871  // We will need to check again which branches are available:
872  m_impl->m_missingBranches.clear();
873 
874  // Remember the tree:
875  m_impl->m_inTree = &tree;
876 
877  // Catalogue all the branches:
878  RETURN_CHECK("xAOD::TAuxStore::readFrom", m_impl->scanInputTree());
879 
880  // Check if we'll be likely to be able to read the "static"
881  // variables:
882  assert(m_impl->m_inTree != nullptr);
883  TBranch* br = m_impl->m_inTree->GetBranch(m_data.m_prefix.data());
884  if (br == nullptr) {
885  // We might not even have static branches, so this is not an error
886  // by itself...
887  return StatusCode::SUCCESS;
888  }
889  // In order to read complex objects, like smart pointers from an
890  // auxiliary container variable-by-variable, the split level of the
891  // branch must be exactly 1.
892  if ((br->GetSplitLevel() != 1) && m_data.m_topStore && printWarnings) {
893  ::Warning("xAOD::TAuxStore::readFrom",
894  "Static branch (%s) with split level %i discovered",
895  m_data.m_prefix.data(), br->GetSplitLevel());
896  ::Warning("xAOD::TAuxStore::readFrom",
897  "The reading of complex variables from it may/will fail!");
898  }
899 
900  // Return gracefully.
901  return StatusCode::SUCCESS;
902 }
903 
910 
911  assert(m_impl);
912 
913  // Look for any auxiliary branches that have not been connected to yet:
914  RETURN_CHECK("xAOD::TAuxStore::writeTo", m_impl->scanInputTree());
915 
916  // Store the TTree pointer:
917  m_impl->m_outTree = &tree;
918 
919  // Create all the variables that we already know about. Notice that the
920  // code makes a copy of the auxid set on purpose. Because the underlying
921  // AuxSelection object gets modified while doing the for loop.
922  const SG::auxid_set_t selAuxIDs = getSelectedAuxIDs();
923  for (SG::auxid_t id : selAuxIDs) {
924  RETURN_CHECK("xAOD::TAuxStore::writeTo", setupOutputData(id));
925  }
926 
927  // Return gracefully.
928  return StatusCode::SUCCESS;
929 }
930 
931 int TAuxStore::getEntry(int getall) {
932 
933  assert(m_impl);
934 
935  // Guard against multi-threaded execution:
936  guard_t guard(m_impl->m_mutex);
937 
938  // Reset the transient store. TEvent::fill() calls this function with
939  // getall==99. When that is happening, we need to keep the transient
940  // store still around. Since the user may want to interact with the
941  // object after it was written out. (And since TEvent::fill() asks for
942  // the transient decorations after calling getEntry(...).)
943  if (m_data.m_transientStore && (getall != 99)) {
944  // Remove the transient auxiliary IDs from the internal list:
945  m_data.m_auxIDs -= m_data.m_transientStore->getAuxIDs();
946  m_data.m_decorIDs -= m_data.m_transientStore->getDecorIDs();
947  // Delete the object:
948  m_data.m_transientStore.reset();
949  }
950 
951  // Now remove the IDs of the decorations that are getting persistified:
952  if (getall != 99) {
953  for (SG::auxid_t auxid = 0; auxid < m_data.m_isDecoration.size(); ++auxid) {
954  if (!m_data.m_isDecoration[auxid]) {
955  continue;
956  }
957  m_data.m_auxIDs.erase(auxid);
958  m_data.m_decorIDs.erase(auxid);
959  }
960  }
961 
962  // If we don't need everything loaded, return now:
963  if (!getall) {
964  return 0;
965  }
966 
967  // Get all the variables at once:
968  int bytesRead = 0;
969  for (auto& branchHandle : m_impl->m_branches) {
970  if (branchHandle) {
971  bytesRead += branchHandle->getEntry();
972  }
973  }
974  return bytesRead;
975 }
976 
978 
979  assert(m_impl);
980 
981  for (auto& branchHandle : m_impl->m_branches) {
982  if (branchHandle) {
983  branchHandle->reset();
984  }
985  }
986  m_impl->m_inputScanned = false;
987 }
988 
990 
991  assert(m_impl);
992  return ((m_impl->m_branches.size() > auxid) && m_impl->m_branches[auxid]);
993 }
994 
996 
997  assert(m_impl);
998  assert(m_impl->m_branches.size() > auxid);
999  assert(m_impl->m_branches[auxid]);
1000  const ::Int_t readBytes = m_impl->m_branches[auxid]->getEntry();
1001  if (readBytes < 0) {
1002  ::Error("xAOD::TAuxStore::getEntryFor",
1003  XAOD_MESSAGE("Couldn't read in variable %s"),
1004  SG::AuxTypeRegistry::instance().getName(auxid).c_str());
1005  return StatusCode::FAILURE;
1006  }
1007  return StatusCode::SUCCESS;
1008 }
1009 
1010 bool TAuxStore::hasOutput() const {
1011 
1012  assert(m_impl);
1013  return (m_impl->m_outTree != nullptr);
1014 }
1015 
1027 
1028  assert(m_impl);
1029 
1030  // Return right away if we already know that the branch is missing.
1031  if ((auxid < m_impl->m_missingBranches.size()) &&
1032  m_impl->m_missingBranches[auxid]) {
1033  return StatusCode::RECOVERABLE;
1034  }
1035 
1036  // Make sure the internal storage is large enough:
1037  if (m_data.m_vecs.size() <= auxid) {
1038  m_data.m_vecs.resize(auxid + 1);
1039  }
1040  if (m_impl->m_branches.size() <= auxid) {
1041  m_impl->m_branches.resize(auxid + 1);
1042  }
1043 
1044  // Check if we need to do anything:
1045  if (m_data.m_vecs[auxid] && m_impl->m_branches[auxid]) {
1046  return StatusCode::SUCCESS;
1047  }
1048 
1049  // A little sanity check.
1050  if (m_impl->m_inTree == nullptr) {
1051  ::Error("xAOD::TAuxStore::setupInputData",
1052  XAOD_MESSAGE("No input TTree set up!"));
1053  return StatusCode::FAILURE;
1054  }
1055 
1056  // Another sanity check.
1057  if (m_data.m_vecs[auxid] || m_impl->m_branches[auxid]) {
1058  ::Error("xAOD::TAuxStore::setupInputData",
1059  XAOD_MESSAGE("Internal logic error!"));
1060  return StatusCode::FAILURE;
1061  }
1062 
1063  // Convenience access to the registry.
1065 
1066  // Get the property name:
1067  const TString statBrName =
1068  std::format("{}{}", m_data.m_prefix, r.getName(auxid));
1069  const TString dynBrName =
1070  std::format("{}{}", m_data.m_dynPrefix, r.getName(auxid));
1071 
1072  // Check if the branch exists:
1073  Bool_t staticBranch = true;
1074  TString brName = statBrName;
1075 
1076  TBranch* br = m_impl->m_inTree->GetBranch(statBrName);
1077  if (!br) {
1078  br = m_impl->m_inTree->GetBranch(dynBrName);
1079  if (!br) {
1080  // Since TTree::GetBranch / TTObjArray::FindObject is expensive,
1081  // remember that we didn't find this branch in this file.
1082  if (m_impl->m_missingBranches.size() <= auxid) {
1083  m_impl->m_missingBranches.resize(auxid + 1);
1084  }
1085  m_impl->m_missingBranches[auxid] = true;
1086  // The branch doesn't exist, but this is not an error per se.
1087  // The user may just be calling isAvailable(...) on the variable.
1088  return StatusCode::RECOVERABLE;
1089  }
1090  // We have a dynamic branch:
1091  staticBranch = false;
1092  brName = dynBrName;
1093  }
1094 
1095  // Check if it's a "primitive branch":
1096  const Bool_t primitiveBranch = isPrimitiveBranch(*br);
1097  // Check if it's a "container branch":
1098  const Bool_t containerBranch =
1099  (primitiveBranch ? false : isContainerBranch(*br, auxid));
1100 
1101  // Set the structure mode if it has not been defined externally:
1103  m_data.m_structMode = (containerBranch ? EStructMode::kContainerStore
1105  }
1106 
1107  // Check that the branch type makes sense:
1108  if ((containerBranch &&
1110  !r.isLinked(auxid)) ||
1111  ((!containerBranch) &&
1113  ::Error("xAOD::TAuxStore::setupInputData",
1114  XAOD_MESSAGE("Branch type and requested structure mode "
1115  "differ for branch: %s"),
1116  brName.Data());
1117  return StatusCode::FAILURE;
1118  }
1119 
1120  // Check what variable it is:
1121  ::TClass* clDummy = 0;
1122  ::EDataType dType = kOther_t;
1123  if (br->GetExpectedType(clDummy, dType)) {
1124  ::Error("xAOD::TAuxStore::setupInputData",
1125  XAOD_MESSAGE("Couldn't determine the type of branch \"%s\""),
1126  brName.Data());
1127  return StatusCode::FAILURE;
1128  }
1129 
1130  // Get the property type:
1131  const std::type_info* brType = 0;
1132  if (details::isRegisteredType(auxid)) {
1133  // Get the type from the auxiliary type registry:
1134  brType = (containerBranch ? r.getVecType(auxid) : r.getType(auxid));
1135  } else {
1136  // Get the type from the input branch itself:
1137  brType = (clDummy ? clDummy->GetTypeInfo() : &(Utils::getTypeInfo(dType)));
1138  }
1139  if (!brType) {
1140  ::Error("xAOD::TAuxStore::setupInputData",
1141  XAOD_MESSAGE("Can't read/copy variable %s (%s)"), brName.Data(),
1142  clDummy->GetName());
1143  return StatusCode::RECOVERABLE;
1144  }
1145  const TString brTypeName = Utils::getTypeName(*brType).c_str();
1146 
1147  // Check if we have the needed dictionary for an object branch:
1148  ::TClass* brClass = 0;
1149  if (!primitiveBranch) {
1150  // Get the property's class:
1151  brClass = ::TClass::GetClass(*brType, true, true);
1152  if (!brClass) {
1153  brClass = ::TClass::GetClass(brTypeName);
1154  }
1155  if (!brClass) {
1156  ::Error("xAOD::TAuxStore::setupInputData",
1157  XAOD_MESSAGE("No dictionary available for class \"%s\""),
1158  brTypeName.Data());
1159  return StatusCode::FAILURE;
1160  }
1161  }
1162 
1163  // Create the smart object holding this vector:
1164  if (details::isRegisteredType(auxid)) {
1165  m_data.m_vecs[auxid] = r.makeVector(auxid, (size_t)0, (size_t)0);
1166  if (!containerBranch) {
1167  m_data.m_vecs[auxid]->resize(1);
1168  }
1169  if (clDummy &&
1170  strncmp(clDummy->GetName(), "SG::PackedContainer<", 20) == 0) {
1171  std::unique_ptr<SG::IAuxTypeVector> packed =
1172  m_data.m_vecs[auxid]->toPacked();
1173  std::swap(m_data.m_vecs[auxid], packed);
1174  }
1175  } else {
1176  ::Error("xAOD::TAuxStore::setupInputData",
1177  XAOD_MESSAGE("Couldn't create in-memory vector for "
1178  "variable %s (%i)"),
1179  brName.Data(), static_cast<int>(auxid));
1180  return StatusCode::FAILURE;
1181  }
1182 
1183  // Create a new branch handle:
1184  const std::type_info* objType = brType;
1185  if (containerBranch) {
1186  objType = m_data.m_vecs[auxid]->objType();
1187  if (!objType)
1188  objType = r.getType(auxid);
1189  }
1190  m_impl->m_branches[auxid] = std::make_unique<TBranchHandle>(
1191  staticBranch, primitiveBranch, objType,
1192  (containerBranch ? m_data.m_vecs[auxid]->toVector()
1193  : m_data.m_vecs[auxid]->toPtr()),
1194  auxid, m_data.m_prefix);
1195 
1196  // Set the tree/branch in the "right mode":
1197  if (staticBranch) {
1198  br->SetMakeClass();
1199  }
1200 
1201  // Connect to the branch:
1202  ::Int_t status = 0;
1203  if (clDummy && ::TString(clDummy->GetName()).Contains("basic_string<char>")) {
1204  // This is pretty much just a hack. As it happens, Athena I/O can
1205  // create dynamic branches that consider themselves to be of type
1206  // "vector<basic_string<char> >" and similar. (Instead of the
1207  // canonical "vector<string>" name.) When we encounter such a branch,
1208  // we just connect to it without performing any compatibility checks.
1209  // Since we don't need to apply any read rules in this case anyway.
1210  status = m_impl->m_inTree->SetBranchAddress(
1211  brName, m_impl->m_branches[auxid]->inputObjectPtr(),
1212  m_impl->m_branches[auxid]->branchPtr());
1213  } else {
1214  status = m_impl->m_inTree->SetBranchAddress(
1215  brName, m_impl->m_branches[auxid]->inputObjectPtr(),
1216  m_impl->m_branches[auxid]->branchPtr(), brClass, dType,
1217  ((!staticBranch) && (!primitiveBranch)));
1218  }
1219  if (status < 0) {
1220  ::Error("xAOD::TAuxStore::setupInputData",
1221  XAOD_MESSAGE("Coulnd't connect to branch \"%s\""), brName.Data());
1222  ::Error("xAOD::TAuxStore::setupInputData", XAOD_MESSAGE("Return code: %i"),
1223  status);
1224  m_data.m_vecs[auxid].reset();
1225  m_impl->m_branches[auxid].reset();
1226  return StatusCode::FAILURE;
1227  }
1228 
1229  // Get the current entry:
1230  m_impl->m_branches[auxid]->getEntry();
1231 
1232  // Remember which variable got created:
1233  m_data.m_auxIDs.insert(auxid);
1234 
1235  // Check if we just replaced a generic object:
1236  if (details::isRegisteredType(auxid)) {
1237  // The name of the variable we just created:
1238  const std::string auxname = r.getName(auxid);
1239  // Check if there's another variable with this name already:
1240  for (SG::auxid_t i = 0; i < m_data.m_vecs.size(); ++i) {
1241  // Check if we have this aux ID:
1242  if (!m_data.m_vecs[i]) {
1243  continue;
1244  }
1245  // Ingore the object that we *just* created:
1246  if (i == auxid) {
1247  continue;
1248  }
1249  // The name of the variable:
1250  const std::string testname = r.getName(i);
1251  // Check if it has the same name:
1252  if (testname != auxname) {
1253  continue;
1254  }
1255  // Check that the other one is a non-registered type:
1257  ::Error("xAOD::TAuxStore::setupInputData",
1258  XAOD_MESSAGE("Internal logic error!"));
1259  continue;
1260  }
1261  // Okay, we do need to remove this object:
1262  m_data.m_vecs[i].reset();
1263  m_impl->m_branches[i].reset();
1265  }
1266  }
1267 
1268  SG::auxid_t linked_auxid = r.linkedVariable(auxid);
1269  if (linked_auxid != SG::null_auxid) {
1270  return setupInputData(linked_auxid);
1271  }
1272 
1273  // Return gracefully.
1274  return StatusCode::SUCCESS;
1275 }
1276 
1287 
1288  assert(m_impl);
1289 
1290  // Check whether we need to do anything:
1291  if (!m_impl->m_outTree) {
1292  return StatusCode::SUCCESS;
1293  }
1294 
1295  // Check if the variable needs to be written out:
1296  if (!isAuxIDSelected(auxid)) {
1297  return StatusCode::SUCCESS;
1298  }
1299 
1300  // Make sure that containers are large enough:
1301  if (m_data.m_vecs.size() <= auxid) {
1302  m_data.m_vecs.resize(auxid + 1);
1303  }
1304  if (m_impl->m_branches.size() <= auxid) {
1305  m_impl->m_branches.resize(auxid + 1);
1306  }
1307  if (m_impl->m_branchesWritten.size() <= auxid) {
1308  m_impl->m_branchesWritten.resize(auxid + 1);
1309  }
1310 
1311  // Check if this auxiliary variable is already in the output:
1312  if (m_impl->m_branchesWritten[auxid]) {
1313  return StatusCode::SUCCESS;
1314  }
1315 
1316  // The registry:
1318 
1319  // Check if the variable was put into the transient store as a
1320  // decoration, and now needs to be put into the output file:
1321  if ((!m_data.m_vecs[auxid]) && m_data.m_transientStore &&
1322  (m_data.m_transientStore->getAuxIDs().test(auxid))) {
1323 
1324  // Get the variable from the transient store:
1325  const void* pptr = m_data.m_transientStore->getData(auxid);
1326  if (!pptr) {
1327  ::Fatal("xAOD::TAuxStore::setupOutputData",
1328  XAOD_MESSAGE("Internal logic error detected"));
1329  return StatusCode::FAILURE;
1330  }
1331 
1332  // Create the new object:
1333  m_data.m_vecs[auxid] = reg.makeVector(auxid, m_data.m_size, m_data.m_size);
1334  void* ptr = m_data.m_vecs[auxid]->toPtr();
1335  if (!ptr) {
1336  ::Error("xAOD::TAuxStore::setupOutputData",
1337  XAOD_MESSAGE("Couldn't create decoration in memory "
1338  "for writing"));
1339  return StatusCode::FAILURE;
1340  }
1341 
1342  // Get the type of this variable:
1343  const std::type_info* type = reg.getType(auxid);
1344  if (!type) {
1345  ::Error("xAOD::TAuxStore::setupOutputData",
1346  XAOD_MESSAGE("Couldn't get the type of transient "
1347  "variable %i"),
1348  static_cast<int>(auxid));
1349  return StatusCode::FAILURE;
1350  }
1351  // Now get the factory for this variable:
1352  const SG::IAuxTypeVectorFactory* factory = reg.getFactory(auxid);
1353  if (!factory) {
1354  ::Error("xAOD::TAuxStore::setupOutputData",
1355  XAOD_MESSAGE("No factory found for transient variable "
1356  "%i"),
1357  static_cast<int>(auxid));
1358  return StatusCode::FAILURE;
1359  }
1360 
1361  // Mark it as a decoration already, otherwise the copy may fail.
1362  if (m_data.m_isDecoration.size() <= auxid) {
1363  m_data.m_isDecoration.resize(auxid + 1);
1364  }
1365  m_data.m_isDecoration[auxid] = true;
1366 
1367  // Finally, do the copy:
1368  factory->copy(auxid, SG::AuxVectorInterface(*this), 0,
1370  m_data.m_size);
1371  }
1372 
1373  // Check if we know about this variable to be on the input,
1374  // but haven't connected to it yet:
1375  if ((m_data.m_auxIDs.test(auxid)) && (!m_data.m_vecs[auxid]) &&
1376  (!m_impl->m_branches[auxid])) {
1377  RETURN_CHECK("xAOD::TAuxStore::setupOutputData", setupInputData(auxid));
1378  }
1379 
1380  // Check that we know the store's type:
1383  ::Error("xAOD::TAuxStore::setupOutputData",
1384  XAOD_MESSAGE("Structure mode unknown for variable %s"),
1385  SG::AuxTypeRegistry::instance().getName(auxid).c_str());
1386  return StatusCode::FAILURE;
1387  }
1388 
1389  // Check if the variable exists already in memory:
1390  if (!m_data.m_vecs[auxid]) {
1391  m_data.m_vecs[auxid] =
1392  SG::AuxTypeRegistry::instance().makeVector(auxid, (size_t)0, (size_t)0);
1394  m_data.m_vecs[auxid]->resize(1);
1395  }
1396  }
1397 
1398  // Check if the branch handle exists already:
1399  if (!m_impl->m_branches[auxid]) {
1400  // Get the property type:
1401  const std::type_info* brType =
1405  // Create the handle object:
1406  bool primitiveBranch = (strlen(brType->name()) == 1);
1407  m_impl->m_branches[auxid] = std::make_unique<TBranchHandle>(
1408  false, (strlen(brType->name()) == 1),
1409  (primitiveBranch ? brType : m_data.m_vecs[auxid]->objType()),
1411  ? m_data.m_vecs[auxid]->toPtr()
1412  : m_data.m_vecs[auxid]->toVector()),
1413  auxid, m_data.m_prefix);
1414  }
1415 
1416  // Construct a name for the branch:
1417  const TString brName =
1418  std::format("{}{}", m_data.m_dynPrefix,
1420 
1421  // If the output branch exists already, assume that it was us making
1422  // it:
1423  ::TBranch* br = m_impl->m_outTree->GetBranch(brName);
1424  if (br) {
1425  // Apparently a branch that was already set up for copying as a basic
1426  // variable, now got accessed explicitly. So let's update the output
1427  // branch to point to this new location now.
1428  br->SetAddress(m_impl->m_branches[auxid]->outputObjectPtr());
1429  // Update the cache. Notice that the "write status" of the typeless
1430  // auxiliary ID is not turned off. But it shouldn't matter, as the
1431  // variable will not be accessed in a typeless way anymore.
1432  m_impl->m_branchesWritten[auxid] = true;
1433  // Return gracefully:
1434  return StatusCode::SUCCESS;
1435  }
1436 
1437  // Check that we know the type of the branch:
1438  const std::type_info* brType = m_impl->m_branches[auxid]->typeInfo();
1439  if (!brType) {
1440  ::Error("xAOD::TAuxStore::setupOutputData",
1441  XAOD_MESSAGE("There's an internal logic error in the "
1442  "code"));
1443  return StatusCode::FAILURE;
1444  }
1445  const std::string brTypeName = Utils::getTypeName(*brType);
1446 
1447  // Decide if this is a primitive branch:
1448  const Bool_t primitiveBranch = (strlen(brType->name()) == 1);
1449 
1450  // Let's create the branch now:
1451  if (primitiveBranch) {
1452 
1453  // Get the "ROOT type" belonging to this primitive:
1454  const char rootType = Utils::rootType(brType->name()[0]);
1455  if (rootType == '\0') {
1456  ::Error("xAOD::TAuxStore::setupOutputData",
1457  XAOD_MESSAGE("Type not known for variable \"%s\" "
1458  "of type \"%s\""),
1459  brName.Data(), brTypeName.c_str());
1460  return StatusCode::FAILURE;
1461  }
1462 
1463  // Construct the type description:
1464  std::ostringstream typeDesc;
1465  typeDesc << brName << "/" << rootType;
1466 
1467  // Create the branch:
1468  br = m_impl->m_outTree->Branch(
1469  brName, m_impl->m_branches[auxid]->outputObjectPtr(),
1470  typeDesc.str().c_str(), m_impl->m_basketSize);
1471 
1472  } else {
1473 
1474  // Access the dictionary for the type:
1475  TClass* cl = TClass::GetClass(*brType);
1476  if (!cl) {
1477  cl = TClass::GetClass(brTypeName.c_str());
1478  }
1479  if (!cl) {
1480  ::Error("xAOD::TAuxStore::setupOutputData",
1481  XAOD_MESSAGE("Couldn't find dictionary for type: %s"),
1482  brTypeName.c_str());
1483  return StatusCode::FAILURE;
1484  }
1485  if (!cl->GetStreamerInfo()) {
1486  ::Error("xAOD::TAuxStore::setupOutputData",
1487  XAOD_MESSAGE("No streamer info available for type %s"),
1488  cl->GetName());
1489  return StatusCode::FAILURE;
1490  }
1491 
1492  // Create the branch:
1493  br = m_impl->m_outTree->Branch(brName, cl->GetName(),
1494  m_impl->m_branches[auxid]->outputObjectPtr(),
1495  m_impl->m_basketSize, m_impl->m_splitLevel);
1496  }
1497 
1498  // Check if we succeeded:
1499  if (!br) {
1500  ::Error("xAOD::TAuxStore::setupOutputData",
1501  XAOD_MESSAGE("Failed creating branch \"%s\" of type "
1502  "\"%s\""),
1503  brName.Data(), brTypeName.c_str());
1504  return StatusCode::FAILURE;
1505  }
1506 
1507  // If this is not the first event, fill up the branch with dummy
1508  // info:
1509  for (Long64_t i = 0; i < m_impl->m_outTree->GetEntries(); ++i) {
1510  br->Fill();
1511  }
1512 
1513  // Update the cache:
1514  m_impl->m_branchesWritten[auxid] = true;
1515 
1516  // Also, remember that we now handle this variable:
1517  m_data.m_auxIDs.insert(auxid);
1518 
1519  // We were successful:
1520  return StatusCode::SUCCESS;
1521 }
1522 
1523 const void* TAuxStore::getInputObject(SG::auxid_t auxid) const {
1524 
1525  assert(m_impl);
1526  assert(m_impl->m_branches.size() > auxid);
1527  assert(m_impl->m_branches[auxid]);
1528  return m_impl->m_branches[auxid]->objectPtr();
1529 }
1530 
1531 const std::type_info* TAuxStore::getInputType(SG::auxid_t auxid) const {
1532 
1533  assert(m_impl);
1534  assert(m_impl->m_branches.size() > auxid);
1535  assert(m_impl->m_branches[auxid]);
1536  return m_impl->m_branches[auxid]->typeInfo();
1537 }
1538 
1539 } // namespace xAOD
SG::AuxTypeRegistry::getFactory
const IAuxTypeVectorFactory * getFactory(const std::type_info &ti, const std::type_info &ti_alloc)
Return the vector factory for a given vector element type.
Definition: AuxTypeRegistry.cxx:1110
python.Dso.registry
registry
Definition: Control/AthenaServices/python/Dso.py:159
xAOD::details::AuxStoreBase::prefix
const std::string & prefix() const
Get the currently configured object name prefix.
Definition: AuxStoreBase.cxx:38
beamspotman.r
def r
Definition: beamspotman.py:676
xAOD::TAuxStore::impl::m_branches
std::vector< std::unique_ptr< TBranchHandle > > m_branches
Branches reading the various auxiliary variables.
Definition: TAuxStore.cxx:807
xAOD::TAuxStore::setupOutputData
virtual StatusCode setupOutputData(SG::auxid_t auxid) override
Connect a variable to the output.
Definition: TAuxStore.cxx:1286
RETURN_CHECK
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Definition: ReturnCheck.h:26
xAOD::TAuxStore::impl::m_branchesWritten
std::vector< bool > m_branchesWritten
"Write status" of the different variables
Definition: TAuxStore.cxx:809
checkxAOD.brName
brName
Definition: Tools/PyUtils/bin/checkxAOD.py:125
xAOD::TAuxStore::setupInputData
virtual StatusCode setupInputData(SG::auxid_t auxid) override
Connect a variable to the input.
Definition: TAuxStore.cxx:1026
xAOD::details::lookupVectorType
TClass * lookupVectorType(TClass &cl)
Internal function used by xAOD::TAuxStore and xAOD::RAuxStore.
Definition: lookupVectorType.cxx:12
SG::SkipNameCheck
@ SkipNameCheck
Definition: AuxTypes.h:81
lookupVectorType.h
vtune_athena.format
format
Definition: vtune_athena.py:14
xAOD::details::AuxStoreBase::Members::m_vecs
std::vector< std::unique_ptr< SG::IAuxTypeVector > > m_vecs
Variables handled currently by the object (indexed by auxiliary ID)
Definition: AuxStoreBase.h:191
xAOD::IOStats::stats
ReadStats & stats()
Access the object belonging to the current thread.
Definition: IOStats.cxx:17
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:639
AuxVectorInterface.h
Make an AuxVectorData object from either a raw vector or an aux store.
AthenaPoolTestRead.flags
flags
Definition: AthenaPoolTestRead.py:8
xAOD::TAuxStore::getEntry
int getEntry(int getall=0)
Read the values from the TTree entry that was loaded with TTree::LoadTree()
Definition: TAuxStore.cxx:931
SG::AuxTypeRegistry::getName
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
Definition: AuxTypeRegistry.cxx:881
xAOD::TAuxStore::impl::m_basketSize
int m_basketSize
The basket size for the output branches.
Definition: TAuxStore.cxx:794
tree
TChain * tree
Definition: tile_monitor.h:30
xAOD::details::AuxStoreBase::Members::m_auxIDs
SG::auxid_set_t m_auxIDs
Internal list of auxiliary variable IDs handled currently by the object.
Definition: AuxStoreBase.h:186
exceptions.h
Exceptions that can be thrown from AthContainers.
xAOD::details::AuxStoreBase::EStructMode
EStructMode
"Structural" modes of the object
Definition: AuxStoreBase.h:30
as_const_ptr.h
Helper for getting a const version of a pointer.
isRegisteredType.h
xAOD::details::AuxStoreBase::guard_t
AthContainers_detail::lock_guard< mutex_t > guard_t
Guard type for multithreaded synchronisation.
Definition: AuxStoreBase.h:206
xAOD::details::AuxStoreBase::Members::m_transientStore
std::unique_ptr< SG::AuxStoreInternal > m_transientStore
Store for the in-memory-only variables.
Definition: AuxStoreBase.h:183
xAOD::TAuxStore::impl::scanInputTree
StatusCode scanInputTree()
Scan the input TTree for auxiliary branches.
Definition: TAuxStore.cxx:442
athena.value
value
Definition: athena.py:124
xAOD::details::AuxStoreBase::Members::m_size
std::size_t m_size
The current size of the container being described.
Definition: AuxStoreBase.h:193
xAOD::TAuxStore::impl::auxBranchType
const std::type_info * auxBranchType(::TBranch &br, std::string_view auxName, bool staticBranch, std::string *expectedClassName=nullptr)
Find the type_info to use as the aux type for a given branch.
Definition: TAuxStore.cxx:545
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
xAOD::details::isRegisteredType
bool isRegisteredType(SG::auxid_t auxid)
Check if the auxiliary variable has a registered type.
Definition: isRegisteredType.cxx:11
SG::AuxTypeRegistry::linkedName
static std::string linkedName(const std::string &name)
Given a variable name, return the name of the corresponding linked variable.
Definition: AuxTypeRegistry.cxx:1302
XAOD_MESSAGE
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Definition: Control/xAODRootAccess/xAODRootAccess/tools/Message.h:19
xAOD::TAuxStore::hasOutput
virtual bool hasOutput() const override
Check if an output is being written by the object.
Definition: TAuxStore.cxx:1010
Utils.h
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
IOStats.h
SG::AuxTypeRegistry::classNameHasLink
static bool classNameHasLink(const std::string &className)
Test to see if a class name corresponds to a class with a linked variable.
Definition: AuxTypeRegistry.cxx:1312
xAOD::details::AuxStoreBase::EStructMode::kObjectStore
@ kObjectStore
The object describes a single object.
xAOD::TAuxStore::reset
virtual void reset() override
Tell the object that all branches will need to be re-read.
Definition: TAuxStore.cxx:977
ReturnCheck.h
xAOD::details::AuxStoreBase::EStructMode::kContainerStore
@ kContainerStore
The object describes an entire container.
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
dumpTruth.getName
getName
Definition: dumpTruth.py:34
xAOD::Utils::dynBranchPrefix
std::string dynBranchPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary branches coming from a container c...
Definition: Control/xAODRootAccess/Root/Utils.cxx:144
xAOD::details::AuxStoreBase::Members::m_decorIDs
SG::auxid_set_t m_decorIDs
Internal list of auxiliary decoration IDs handled currently by the object.
Definition: AuxStoreBase.h:189
xAOD::TAuxStore::impl::m_mutex
mutex_t m_mutex
Mutex object used for multithreaded synchronisation.
Definition: TAuxStore.cxx:815
SG::AuxTypeRegistry
Handle mappings between names and auxid_t.
Definition: AuxTypeRegistry.h:61
xAOD::TAuxStore::impl::m_inTree
::TTree * m_inTree
The TTree being read from.
Definition: TAuxStore.cxx:799
runLayerRecalibration.branches
list branches
Definition: runLayerRecalibration.py:98
SG::Linked
@ Linked
Mark that this variable is linked to another one.
Definition: AuxTypes.h:77
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
SG::AuxTypeRegistry::getType
const std::type_info * getType(SG::auxid_t auxid) const
Return the type of an aux data item.
Definition: AuxTypeRegistry.cxx:908
H5Utils::internal::packed
H5::CompType packed(H5::CompType in)
Definition: common.cxx:16
xAOD::details::AuxStoreBase::m_data
Members m_data
Member variables of the base class.
Definition: AuxStoreBase.h:201
ReadStats.h
TAuxStore.h
xAOD::TAuxStore::impl::setupAuxBranch
StatusCode setupAuxBranch(::TBranch &br, std::string_view auxName, bool staticBranch)
Register one input branch as an available auxiliary variable.
Definition: TAuxStore.cxx:641
details
Definition: IParticleWriter.h:21
xAOD::details::AuxStoreBase::mutex_t
AthContainers_detail::mutex mutex_t
Mutex type for multithread synchronization.
Definition: AuxStoreBase.h:204
xAOD::TAuxStore::writeTo
StatusCode writeTo(::TTree &tree)
Connect the object to an output TTree.
Definition: TAuxStore.cxx:909
xAOD::Utils::getTypeName
std::string getTypeName(const std::type_info &ti)
This function is necessary in order to create type names that ROOT can understand.
Definition: Control/xAODRootAccess/Root/Utils.cxx:352
lumiFormat.i
int i
Definition: lumiFormat.py:85
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(bit_t bit, bit_t new_nbits=0)
Set a bit to 1.
xAOD::TAuxStore::readFrom
StatusCode readFrom(::TTree &tree, bool printWarnings=true)
Connect the object to an input TTree.
Definition: TAuxStore.cxx:864
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::TAuxStore::setPrefix
virtual void setPrefix(std::string_view prefix) override
Set the object name prefix.
Definition: TAuxStore.cxx:828
Message.h
SG::IAuxTypeVectorFactory
Interface for factory objects that create vectors.
Definition: IAuxTypeVectorFactory.h:50
SG::IAuxTypeVectorFactory::tiAlloc
virtual const std::type_info * tiAlloc() const =0
Return the type_info of the vector allocator.
xAOD::TAuxStore::TAuxStore
TAuxStore(std::string_view prefix="", bool topStore=true, EStructMode mode=EStructMode::kUndefinedStore, int basketSize=2048, int splitLevel=0)
Constructor.
Definition: TAuxStore.cxx:818
xAOD::details::AuxStoreBase::Members::m_prefix
std::string m_prefix
Static prefix for the branch names.
Definition: AuxStoreBase.h:178
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
Preparation.mode
mode
Definition: Preparation.py:107
SG::AuxTypeRegistry::isLinkedName
static bool isLinkedName(const std::string &name)
Test if a variable name corresponds to a linked variable.
Definition: AuxTypeRegistry.cxx:1292
SG::IAuxTypeVectorFactory::copy
virtual void copy(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const =0
Copy elements between vectors.
SG::AuxTypeRegistry::getVecType
const std::type_info * getVecType(SG::auxid_t auxid) const
Return the type of the STL vector used to hold an aux data item.
Definition: AuxTypeRegistry.cxx:936
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
xAOD::IOStats::instance
static IOStats & instance()
Singleton object accessor.
Definition: IOStats.cxx:11
SG::AuxVarFlags
AuxVarFlags
Additional flags to qualify an auxiliary variable.
Definition: AuxTypes.h:58
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
xAOD::details::AuxStoreBase::getSelectedAuxIDs
virtual SG::auxid_set_t getSelectedAuxIDs() const override
Get the IDs of the selected aux variables.
Definition: AuxStoreBase.cxx:623
xAOD::details::AuxStoreBase::isAuxIDSelected
bool isAuxIDSelected(SG::auxid_t auxid) const
Check if an auxiliary variable is selected for ouput writing.
Definition: AuxStoreBase.cxx:639
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
xAOD::TAuxStore::getEntryFor
virtual StatusCode getEntryFor(SG::auxid_t auxid) override
Load a single variable from the input.
Definition: TAuxStore.cxx:995
xAOD::TAuxStore::getInputType
virtual const std::type_info * getInputType(SG::auxid_t auxid) const override
Get the type of an input object, for getIOType()
Definition: TAuxStore.cxx:1531
SG::AuxTypeRegistry::makeVector
std::unique_ptr< IAuxTypeVector > makeVector(SG::auxid_t auxid, size_t size, size_t capacity) const
Construct a new vector to hold an aux item.
Definition: AuxTypeRegistry.cxx:817
xAOD::details::AuxStoreBase::Members::m_structMode
EStructMode m_structMode
The "structural" mode of the object.
Definition: AuxStoreBase.h:174
xAOD::TAuxStore::setBasketSize
void setBasketSize(int value)
Set the size of the baskets created for the output branches.
Definition: TAuxStore.cxx:841
xAOD::ReadStats::readBranch
void readBranch(const std::string &prefix, SG::auxid_t auxid)
Function incrementing the read counter on a specific branch.
xAOD::Utils::getTypeInfo
const std::type_info & getTypeInfo(EDataType type)
This function is used when reading a primitive branch from an input file without the user explicitly ...
Definition: Control/xAODRootAccess/Root/Utils.cxx:194
SG::AuxVectorInterface
Make an AuxVectorData object from either a raw array or an aux store.
Definition: AuxVectorInterface.h:33
xAOD::TAuxStore::getInputObject
virtual const void * getInputObject(SG::auxid_t auxid) const override
Get a pointer to an input object, as it is in memory, for getIOData()
Definition: TAuxStore.cxx:1523
xAOD::TAuxStore::m_impl
std::unique_ptr< impl > m_impl
Pointer to the internal object.
Definition: TAuxStore.h:89
CxxUtils::reset
constexpr std::enable_if_t< is_bitmask_v< E >, E & > reset(E &lhs, E rhs)
Convenience function to clear bits in a class enum bitmask.
Definition: bitmask.h:251
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
xAOD::TAuxStore::setSplitLevel
void setSplitLevel(int value)
Set the split level of the output branches.
Definition: TAuxStore.cxx:853
xAOD::TAuxStore::impl
Definition: TAuxStore.cxx:423
xAOD::details::AuxStoreBase::EStructMode::kUndefinedStore
@ kUndefinedStore
The structure mode is not defined.
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
xAOD::TAuxStore::~TAuxStore
virtual ~TAuxStore()
Destructor.
merge.status
status
Definition: merge.py:17
xAOD::TAuxStore::splitLevel
int splitLevel() const
Get the split level of the output branches.
Definition: TAuxStore.cxx:847
CxxUtils::ConcurrentBitset::erase
ConcurrentBitset & erase(bit_t bit)
Turn off one bit.
xAOD::details::AuxStoreBase::Members::m_isDecoration
std::vector< bool > m_isDecoration
Per variable lock status (indexed by auxiliary ID)
Definition: AuxStoreBase.h:196
xAOD::TAuxStore::impl::m_data
Members & m_data
Variables coming from AuxStoreBase.
Definition: TAuxStore.cxx:791
xAOD::TAuxStore::impl::m_inputScanned
bool m_inputScanned
"Scan status" of the input TTree
Definition: TAuxStore.cxx:804
checker_macros.h
Define macros for attributes used to control the static checker.
python.PyAthena.obj
obj
Definition: PyAthena.py:132
AuxStoreInternal.h
An auxiliary data store that holds data internally.
xAOD::details::AuxStoreBase::Members::m_dynPrefix
std::string m_dynPrefix
Dynamic prefix for the branch names.
Definition: AuxStoreBase.h:180
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
xAOD::details::AuxStoreBase::Members::m_topStore
bool m_topStore
Flag stating whether this is a "top store".
Definition: AuxStoreBase.h:176
TAuxVectorFactory.h
xAOD::Utils::rootType
char rootType(char typeidType)
This function is used internally in the code when creating primitive dynamic auxiliary branches.
Definition: Control/xAODRootAccess/Root/Utils.cxx:293
xAOD::TAuxStore::impl::m_missingBranches
std::vector< bool > m_missingBranches
Mark branches we've found to be missing.
Definition: TAuxStore.cxx:812
xAOD::TAuxStore::hasEntryFor
virtual bool hasEntryFor(SG::auxid_t auxid) const override
Check if a given variable is available from the input.
Definition: TAuxStore.cxx:989
xAOD::TAuxStore::basketSize
int basketSize() const
Get the size of the baskets created for the output branches.
Definition: TAuxStore.cxx:835
xAOD::TAuxStore::impl::m_splitLevel
int m_splitLevel
The split level for the output branches.
Definition: TAuxStore.cxx:796
xAOD::details::AuxStoreBase::Members
Struct collecting all member variables of this base class.
Definition: AuxStoreBase.h:171
PlotCalibFromCool.br
br
Definition: PlotCalibFromCool.py:355
CxxUtils::ConcurrentBitset::test
bool test(bit_t bit) const
Test to see if a bit is set.
xAOD::TAuxStore::impl::m_outTree
::TTree * m_outTree
The TTree being written to.
Definition: TAuxStore.cxx:801