ATLAS Offline Software
TBranchAuxDynWriter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "TBranchAuxDynWriter.h"
6 
9 
10 #include "TFile.h"
11 #include "TTree.h"
12 #include "TBranch.h"
13 #include "TClass.h"
14 
15 
16 namespace RootAuxDynIO
17 {
18 
20  object = nullptr;
21  if( tclass ) {
22  if( !dummy ) {
23  using std::placeholders::_1;
24  void(TClass::*dxtor)(void*, Bool_t) = &TClass::Destructor;
25  std::function<void(void*)> del = std::bind(dxtor, tclass, _1, false);
26  dummyptr = dummy_ptr_t( tclass->New(), std::move(del) );
27  dummy = dummyptr.get();
28  }
29  branch->SetAddress( &dummy );
30  return &dummy;
31  }
32  return nullptr;
33  }
34 
36  if( buffer && tclass ) {
37  tclass->Destructor(buffer);
38  }
39  }
40 
41 
42  TBranchAuxDynWriter::TBranchAuxDynWriter( TTree& tree, TClass& cls, int bufferSize, int splitLevel,
43  int offsettab_len, bool branch_fill ) :
44  AthMessaging ("TBranchAuxDynWriter"), AuxDynAttrAccess(cls),
45  m_ttree( &tree ),
46  m_bufferSize( bufferSize ),
47  m_splitLevel( splitLevel ),
48  m_branchOffsetTabLen( offsettab_len ),
49  m_branchFillMode( branch_fill )
50  { }
51 
52 
53  /* Copied from RootTreeContainer::setBranchOffsetTabLen - probably should be kept in sych with it */
54  void TBranchAuxDynWriter::setBranchOffsetTabLen(TBranch* b, int offsettab_len) {
55  if( offsettab_len > 0 ) {
56  if( b->GetEntryOffsetLen() > 0 )
57  b->SetEntryOffsetLen( offsettab_len );
58  TIter biter( b->GetListOfBranches() );
59  TBranch* subbranch(nullptr);
60  while( (subbranch = (TBranch*)biter.Next()) ) {
61  setBranchOffsetTabLen( subbranch, offsettab_len );
62  }
63  }
64  }
65 
66 
67  // throws exceptions
69  std::string error_type("is unknown");
70  const std::type_info& ti = *info.typeinfo;
71  try {
72  auto createBasicAuxBranch = [&](const char* typeopt) {
73  info.is_basic_type = true;
74  info.branch = m_ttree->Branch(info.branch_name.c_str(), info.buffer, (info.name+typeopt).c_str(), 2048);
75  ATH_MSG_VERBOSE("Created branch with name=" << info.branch_name << " type: " << info.name+typeopt);
76  };
77  if ( ti == typeid(UInt_t) ) createBasicAuxBranch("/i");
78  else if( ti == typeid(Int_t) ) createBasicAuxBranch("/I");
79  else if( ti == typeid(Double_t) ) createBasicAuxBranch("/D");
80  else if( ti == typeid(Float_t) ) createBasicAuxBranch("/F");
81  else if( ti == typeid(Long64_t) or ti == typeid(std::int64_t) ) createBasicAuxBranch("/L");
82  else if( ti == typeid(ULong64_t) or ti == typeid(std::uint64_t) ) createBasicAuxBranch("/l");
83  else if( ti == typeid(Short_t) ) createBasicAuxBranch("/S");
84  else if( ti == typeid(UShort_t) ) createBasicAuxBranch("/s");
85  else if( ti == typeid(Char_t) ) createBasicAuxBranch("/B");
86  else if( ti == typeid(UChar_t) ) createBasicAuxBranch("/b");
87  else if( ti == typeid(bool) ) createBasicAuxBranch("/O");
88  else if( ti == typeid(char*) || ti == typeid(unsigned char*) ) createBasicAuxBranch("/C");
89  else {
90  TClass* cl = TClass::GetClass(info.type_name.c_str());
91  if( !cl ) {
92  error_type =" has no TClass";
93  } else if( !cl->GetStreamerInfo() ) {
94  error_type =" has no streamer";
95  } else if( !cl->HasDictionary() ) {
96  error_type =" has no dictionary";
97  } else {
98  info.tclass = cl;
99  int split = cl->CanSplit() ? m_splitLevel : 0;
100  info.branch = m_ttree->Branch( info.branch_name.c_str(), // Branch name
101  cl->GetName(), // Object class
102  (void*)&info.buffer, // Object address
103  m_bufferSize, // Buffer size
104  split); // Split Mode (Levels)
105  ATH_MSG_VERBOSE("Created branch with name=" << info.branch_name << " type: " << cl->GetName());
106  }
107  }
108  } catch( const std::exception& e ) {
109  error_type += std::string(" Exception msg: ") + e.what();
110  }
111  catch (...) {
112  error_type += " Unknown exception.";
113  }
114 
115  if( !info.branch ) {
116  throw std::runtime_error( std::string("Failed to create Auxiliary branch '") + info.branch_name
117  + "'. Class: " + info.type_name + error_type );
118  }
119  // Set AUTO-DELETE OFF. ROOT will not delete objects created by the framework
120  info.branch->SetAutoDelete(kFALSE);
121 
123  }
124 
125 
127  // throws exceptions
128  int TBranchAuxDynWriter::writeAuxAttributes( const std::string& base_branchname,
129  void* object,
130  size_t backfill_nrows )
131  {
132  SG::IAuxStoreIO *store = castIOStore(object);
133  int bytes_written = 0;
134  const SG::auxid_set_t selection = store->getSelectedAuxIDs();
135  ATH_MSG_DEBUG("Writing " << base_branchname << " with " << selection.size() << " Dynamic attributes");
136 
137  // mark all attributes as not written yet
138  for( auto& aux_info_entry : m_auxInfoMap ) aux_info_entry.second.written = false;
139  m_needsFill = false;
140 
141  for(SG::auxid_t id : selection) {
142  AuxInfo& attrInfo = m_auxInfoMap[id];
143  if( !attrInfo.branch ) {
144  // new attribute info, fill it
145  attrInfo.typeinfo = store->getIOType(id);
146  attrInfo.type_name = SG::normalizedTypeinfoName( *attrInfo.typeinfo );
147  attrInfo.name = SG::AuxTypeRegistry::instance().getName(id);
148  attrInfo.branch_name = RootAuxDynIO::auxBranchName(attrInfo.name, base_branchname);
149 
150  ATH_MSG_DEBUG("Creating branch for new dynamic attribute, Id=" << id << ": type=" << attrInfo.type_name
151  << ", branch=" << attrInfo.branch_name );
152  createAuxBranch( attrInfo );
153  // backfill here
154  if( backfill_nrows ) {
155  // if this is not the first row, catch up with the rows written already to other branches
156  ATH_MSG_DEBUG(" Backfilling " << backfill_nrows << " entries for " << attrInfo.name);
157  // As of root 6.22, calling SetAddress with nullptr may not work as expected if the address had
158  // previously been set to something non-null.
159  // So we need to create the temp object ourselves.
160  attrInfo.setDummyAddr();
161  for( size_t r=0; r<backfill_nrows; ++r ) {
162  bytes_written += attrInfo.branch->BackFill();
163  ATH_MSG_VERBOSE("BACKFilled branch:" << m_ttree->GetName() << "::" << attrInfo.branch->GetName() <<
164  " Tree size=" << m_ttree->GetEntries()
165  << " branch size:" << attrInfo.branch->GetEntries() );
166  }
167  }
168  }
169  void *obj ATLAS_THREAD_SAFE = const_cast<void*>( store->getIOData(id) );
170  attrInfo.object = obj;
171  attrInfo.branch->SetAddress( attrInfo.objectAddr() );
172  attrInfo.written = true;
173  }
174 
175  for( auto& aux_info_entry : m_auxInfoMap ) {
176  AuxInfo& attrInfo = aux_info_entry.second;
177  // if an attribute was not written create a default object for it
178  if( !attrInfo.written ) {
179  attrInfo.setDummyAddr();
180  ATH_MSG_DEBUG("Default object added to branch: " << attrInfo.branch_name);
181  }
182  // if writing to branches independently, do it now
183  if( m_branchFillMode ) {
184  bytes_written += attrInfo.branch->Fill();
185  } else {
186  m_needsFill = true;
187  }
188  }
189  return bytes_written;
190  }
191 
192 
194  ATH_MSG_WARNING("Commit for TBranchAuxDynWriter should be handled on the DB level");
195  return 0;
196  }
197 
198 } // namespace
RootAuxDynIO::AuxInfo
Definition: TBranchAuxDynWriter.h:22
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
SGTest::store
TestStore store
Definition: TestStore.cxx:23
beamspotman.r
def r
Definition: beamspotman.py:674
RootAuxDynIO::TBranchAuxDynWriter::createAuxBranch
void createAuxBranch(AuxInfo &info)
Definition: TBranchAuxDynWriter.cxx:68
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:639
RootAuxDynIO::AuxInfo::written
bool written
Definition: TBranchAuxDynWriter.h:32
RunTileMonitoring.bufferSize
bufferSize
Definition: RunTileMonitoring.py:298
RootAuxDynIO::AuxInfo::tclass
TClass * tclass
Definition: TBranchAuxDynWriter.h:28
SG::normalizedTypeinfoName
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
Definition: normalizedTypeinfoName.cxx:120
RootAuxDynIO::TBranchAuxDynWriter::m_ttree
TTree * m_ttree
Definition: TBranchAuxDynWriter.h:78
RootAuxDynIO::AuxInfo::setDummyAddr
void * setDummyAddr()
Definition: TBranchAuxDynWriter.cxx:19
SG::AuxTypeRegistry::getName
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
Definition: AuxTypeRegistry.cxx:881
tree
TChain * tree
Definition: tile_monitor.h:30
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
RootAuxDynIO::AuxInfo::name
std::string name
Definition: TBranchAuxDynWriter.h:23
RootAuxDynIO::AuxInfo::branch
TBranch * branch
Definition: TBranchAuxDynWriter.h:27
RootAuxDynIO::AuxInfo::type_name
std::string type_name
Definition: TBranchAuxDynWriter.h:24
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
RootAuxDynIO::auxBranchName
std::string auxBranchName(const std::string &attr_name, const std::string &baseBranchName)
Construct branch name for a given dynamic attribute.
Definition: RootAuxDynDefs.h:60
RootAuxDynIO::TBranchAuxDynWriter::setBranchOffsetTabLen
void setBranchOffsetTabLen(TBranch *b, int offsettab_len)
Definition: TBranchAuxDynWriter.cxx:54
SG::IAuxStoreIO
Interface providing I/O for a generic auxiliary store.
Definition: IAuxStoreIO.h:44
AthMessaging::ATLAS_THREAD_SAFE
std::atomic_flag m_initialized ATLAS_THREAD_SAFE
Messaging initialized (initMessaging)
Definition: AthMessaging.h:141
RootAuxDynIO::AuxInfo::~AuxInfo
~AuxInfo()
Definition: TBranchAuxDynWriter.cxx:35
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
RootAuxDynIO::AuxDynAttrAccess
Definition: RootAuxDynIO.h:20
RootAuxDynIO::TBranchAuxDynWriter::m_branchFillMode
bool m_branchFillMode
Definition: TBranchAuxDynWriter.h:82
RootAuxDynIO::TBranchAuxDynWriter::commit
virtual int commit() override final
Call Fill() on the ROOT object used by this writer.
Definition: TBranchAuxDynWriter.cxx:193
RootAuxDynIO::AuxInfo::dummy
void * dummy
Definition: TBranchAuxDynWriter.h:40
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
RootAuxDynIO::TBranchAuxDynWriter::writeAuxAttributes
virtual int writeAuxAttributes(const std::string &base_branchname, void *store, size_t backfill_nrows) override final
handle writing of dynamic xAOD attributes of an object called from RootTreeContainer::writeObject()
Definition: TBranchAuxDynWriter.cxx:128
calibdata.exception
exception
Definition: calibdata.py:495
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
RootAuxDynIO::TBranchAuxDynWriter::m_needsFill
bool m_needsFill
Definition: TBranchAuxDynWriter.h:83
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
RootAuxDynIO::AuxInfo::typeinfo
const std::type_info * typeinfo
Definition: TBranchAuxDynWriter.h:25
RootAuxDynIO::AuxInfo::dummyptr
dummy_ptr_t dummyptr
Definition: TBranchAuxDynWriter.h:39
RootAuxDynIO::AuxInfo::object
void * object
Definition: TBranchAuxDynWriter.h:30
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
RootAuxDynIO::AuxDynAttrAccess::castIOStore
SG::IAuxStoreIO * castIOStore(void *object)
Definition: RootAuxDynIO.cxx:45
selection
const std::string selection
Definition: fbtTestBasics.cxx:75
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
RootAuxDynIO::TBranchAuxDynWriter::m_splitLevel
int m_splitLevel
Definition: TBranchAuxDynWriter.h:80
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
RootAuxDynIO::TBranchAuxDynWriter::TBranchAuxDynWriter
TBranchAuxDynWriter(TTree &tree, TClass &cls, int bufferSize, int splitLevel, int offsettab_len, bool branch_fill)
Definition: TBranchAuxDynWriter.cxx:42
RootAuxDynIO::AuxInfo::dummy_ptr_t
std::unique_ptr< void, std::function< void(void *)> > dummy_ptr_t
Definition: TBranchAuxDynWriter.h:38
RootAuxDynIO
Specialization of RootAuxDynStore for reading Aux Dynamic attributes from RNTuple.
Definition: RNTupleContainer.h:28
RootAuxDynIO::AuxInfo::objectAddr
void * objectAddr()
Definition: TBranchAuxDynWriter.h:45
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
python.PyAthena.obj
obj
Definition: PyAthena.py:132
TBranchAuxDynWriter.h
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
RootAuxDynIO::TBranchAuxDynWriter::m_auxInfoMap
std::map< SG::auxid_t, AuxInfo > m_auxInfoMap
cached aux branches data by auxid
Definition: TBranchAuxDynWriter.h:86
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
RootAuxDynIO::AuxInfo::branch_name
std::string branch_name
Definition: TBranchAuxDynWriter.h:26
RootAuxDynIO::TBranchAuxDynWriter::m_bufferSize
int m_bufferSize
Definition: TBranchAuxDynWriter.h:79
RootAuxDynIO::AuxInfo::buffer
void * buffer
Definition: TBranchAuxDynWriter.h:31
RootAuxDynIO::TBranchAuxDynWriter::m_branchOffsetTabLen
int m_branchOffsetTabLen
Definition: TBranchAuxDynWriter.h:81