ATLAS Offline Software
TBranchAuxDynWriter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 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, int bufferSize, int splitLevel, int offsettab_len, bool branch_fill ) :
43  AthMessaging ("TBranchAuxDynWriter"),
44  m_ttree( tree ),
45  m_bufferSize( bufferSize ),
46  m_splitLevel( splitLevel ),
47  m_branchOffsetTabLen( offsettab_len ),
48  m_branchFillMode( branch_fill )
49  { }
50 
51 
52  /* Copied from RootTreeContainer::setBranchOffsetTabLen - probably should be kept in sych with it */
53  void TBranchAuxDynWriter::setBranchOffsetTabLen(TBranch* b, int offsettab_len) {
54  if( offsettab_len > 0 ) {
55  if( b->GetEntryOffsetLen() > 0 )
56  b->SetEntryOffsetLen( offsettab_len );
57  TIter biter( b->GetListOfBranches() );
58  TBranch* subbranch(nullptr);
59  while( (subbranch = (TBranch*)biter.Next()) ) {
60  setBranchOffsetTabLen( subbranch, offsettab_len );
61  }
62  }
63  }
64 
65 
66  // throws exceptions
68  std::string error_type("is unknown");
69  const std::type_info& ti = *info.typeinfo;
70  try {
71  auto createBasicAuxBranch = [&](const char* typeopt) {
72  info.is_basic_type = true;
73  info.branch = m_ttree->Branch(info.branch_name.c_str(), info.buffer, (info.name+typeopt).c_str(), 2048);
74  ATH_MSG_VERBOSE("MN: Created branch with name=" << info.branch_name << " type: " << info.name+typeopt);
75  };
76  if ( ti == typeid(UInt_t) ) createBasicAuxBranch("/i");
77  else if( ti == typeid(Int_t) ) createBasicAuxBranch("/I");
78  else if( ti == typeid(Double_t) ) createBasicAuxBranch("/D");
79  else if( ti == typeid(Float_t) ) createBasicAuxBranch("/F");
80  else if( ti == typeid(Long64_t) or ti == typeid(std::int64_t) ) createBasicAuxBranch("/L");
81  else if( ti == typeid(ULong64_t) or ti == typeid(std::uint64_t) ) createBasicAuxBranch("/l");
82  else if( ti == typeid(Short_t) ) createBasicAuxBranch("/S");
83  else if( ti == typeid(UShort_t) ) createBasicAuxBranch("/s");
84  else if( ti == typeid(Char_t) ) createBasicAuxBranch("/B");
85  else if( ti == typeid(UChar_t) ) createBasicAuxBranch("/b");
86  else if( ti == typeid(bool) ) createBasicAuxBranch("/O");
87  else if( ti == typeid(char*) || ti == typeid(unsigned char*) ) createBasicAuxBranch("/C");
88  else {
89  TClass* cl = TClass::GetClass(info.type_name.c_str());
90  if( !cl ) {
91  error_type =" has no TClass";
92  } else if( !cl->GetStreamerInfo() ) {
93  error_type =" has no streamer";
94  } else if( !cl->HasDictionary() ) {
95  error_type =" has no dictionary";
96  } else {
97  info.tclass = cl;
98  int split = cl->CanSplit() ? m_splitLevel : 0;
99  info.branch = m_ttree->Branch( info.branch_name.c_str(), // Branch name
100  cl->GetName(), // Object class
101  (void*)&info.buffer, // Object address
102  m_bufferSize, // Buffer size
103  split); // Split Mode (Levels)
104  ATH_MSG_VERBOSE("MN: Created branch with name=" << info.branch_name << " type: " << cl->GetName());
105  }
106  }
107  } catch( const std::exception& e ) {
108  error_type += std::string(" Exception msg: ") + e.what();
109  }
110  catch (...) {
111  error_type += " Unknown exception.";
112  }
113 
114  if( !info.branch ) {
115  throw std::runtime_error( std::string("Failed to create Auxiliary branch '") + info.branch_name
116  + "'. Class: " + info.type_name + error_type );
117  }
118  // Set AUTO-DELETE OFF. ROOT will not delete objects created by the framework
119  info.branch->SetAutoDelete(kFALSE);
120 
122  }
123 
124 
126  // throws exceptions
127  int TBranchAuxDynWriter::writeAuxAttributes( const std::string& base_branchname,
129  size_t backfill_nrows )
130  {
131  int bytes_written = 0;
132  const SG::auxid_set_t selection = store->getSelectedAuxIDs();
133  ATH_MSG_DEBUG("Writing " << base_branchname << " with " << selection.size() << " Dynamic attributes");
134 
135  // mark all attributes as not written yet
136  for( auto& aux_info_entry : m_auxInfoMap ) aux_info_entry.second.written = false;
137  m_needsFill = false;
138 
139  for(SG::auxid_t id : selection) {
140  AuxInfo& attrInfo = m_auxInfoMap[id];
141  if( !attrInfo.branch ) {
142  // new attribute info, fill it
143  attrInfo.typeinfo = store->getIOType(id);
144  attrInfo.type_name = SG::normalizedTypeinfoName( *attrInfo.typeinfo );
145  attrInfo.name = SG::AuxTypeRegistry::instance().getName(id);
146  attrInfo.branch_name = RootAuxDynIO::auxBranchName(attrInfo.name, base_branchname);
147  /*
148  // MN: this part can be used to reject late attribs and not do backfilling, to be compatible with current RNTuple behavior
149  static std::set<std::string> bad_branches;
150  std::string bnam = attrInfo.branch_name + ":" + attrInfo.name;
151  if( bad_branches.count(bnam) > 0 ) continue;
152  if( backfill_nrows ) {
153  bad_branches.insert(bnam);
154  if(mn) cout << "MN: ignoring late attribute: " << bnam << " type: " << attrInfo.type_name<< endl;
155  continue;
156  }
157  */
158  ATH_MSG_DEBUG("Creating branch for new dynamic attribute, Id=" << id << ": type=" << attrInfo.type_name << ", branch=" << attrInfo.branch_name );
159  createAuxBranch( attrInfo );
160  // backfill here
161  if( backfill_nrows ) {
162  // if this is not the first row, catch up with the rows written already to other branches
163  ATH_MSG_DEBUG(" Backfilling " << backfill_nrows << " entries for " << attrInfo.name);
164  // As of root 6.22, calling SetAddress with nullptr may not work as expected if the address had
165  // previously been set to something non-null.
166  // So we need to create the temp object ourselves.
167  attrInfo.setDummyAddr();
168  for( size_t r=0; r<backfill_nrows; ++r ) {
169  bytes_written += attrInfo.branch->BackFill();
170  ATH_MSG_VERBOSE("BACKFilled branch:" << m_ttree->GetName() << "::" << attrInfo.branch->GetName() <<
171  " Tree size=" << m_ttree->GetEntries()
172  << " branch size:" << attrInfo.branch->GetEntries() );
173  }
174  }
175  }
176  void *obj ATLAS_THREAD_SAFE = const_cast<void*>( store->getIOData(id) );
177  attrInfo.object = obj;
178  attrInfo.branch->SetAddress( attrInfo.objectAddr() );
179  attrInfo.written = true;
180  }
181 
182  for( auto& aux_info_entry : m_auxInfoMap ) {
183  AuxInfo& attrInfo = aux_info_entry.second;
184  // cout << "MN: AuxInfo loop: branch name=" << attrInfo.branch_name << " branch addr=" << attrInfo.branch<< endl;
185  // if an attribute was not written create a default object for it
186  if( !attrInfo.written ) {
187  attrInfo.setDummyAddr();
188  ATH_MSG_DEBUG("Default object added to branch: " << attrInfo.branch_name);
189  // cout << "Default object added to branch: " << attrInfo.branch_name << " Tree size=" << m_ttree->GetEntries() << " branch size:" << attrInfo.branch->GetEntries() << endl;
190  }
191  // if writing to branches independently, do it now
192  if( m_branchFillMode ) {
193  // cout << "MN: BranchFill for " << attrInfo.branch_name << endl;
194  bytes_written += attrInfo.branch->Fill();
195  } else {
196  m_needsFill = true;
197  }
198  }
199  return bytes_written;
200  }
201 
202 
204  ATH_MSG_WARNING("Commit for TBranchAuxDynWriter should be handled on the DB level");
205  return 0;
206  }
207 
208 } // namespace
grepfile.info
info
Definition: grepfile.py:38
RootAuxDynIO::AuxInfo
Definition: TBranchAuxDynWriter.h:21
beamspotman.r
def r
Definition: beamspotman.py:676
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:69
RootAuxDynIO::TBranchAuxDynWriter::createAuxBranch
void createAuxBranch(AuxInfo &info)
Definition: TBranchAuxDynWriter.cxx:67
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:49
RootAuxDynIO::AuxInfo::written
bool written
Definition: TBranchAuxDynWriter.h:31
RootAuxDynIO::AuxInfo::tclass
TClass * tclass
Definition: TBranchAuxDynWriter.h:27
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:77
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:277
tree
TChain * tree
Definition: tile_monitor.h:30
RootAuxDynIO::AuxInfo::name
std::string name
Definition: TBranchAuxDynWriter.h:22
RootAuxDynIO::AuxInfo::branch
TBranch * branch
Definition: TBranchAuxDynWriter.h:26
RootAuxDynIO::AuxInfo::type_name
std::string type_name
Definition: TBranchAuxDynWriter.h:23
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:46
RootAuxDynIO::TBranchAuxDynWriter::setBranchOffsetTabLen
void setBranchOffsetTabLen(TBranch *b, int offsettab_len)
Definition: TBranchAuxDynWriter.cxx:53
RootAuxDynIO::TBranchAuxDynWriter::writeAuxAttributes
virtual int writeAuxAttributes(const std::string &base_branchname, SG::IAuxStoreIO *store, size_t backfill_nrows) override final
handle writing of dynamic xAOD attributes of an object called from RootTreeContainer::writeObject()
Definition: TBranchAuxDynWriter.cxx:127
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::TBranchAuxDynWriter::m_branchFillMode
bool m_branchFillMode
Definition: TBranchAuxDynWriter.h:81
RootAuxDynIO::TBranchAuxDynWriter::commit
virtual int commit() override final
Call Fill() on the ROOT object used by this writer.
Definition: TBranchAuxDynWriter.cxx:203
RootAuxDynIO::AuxInfo::dummy
void * dummy
Definition: TBranchAuxDynWriter.h:39
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
calibdata.exception
exception
Definition: calibdata.py:496
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
RootAuxDynIO::TBranchAuxDynWriter::m_needsFill
bool m_needsFill
Definition: TBranchAuxDynWriter.h:82
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
RootAuxDynIO::AuxInfo::typeinfo
const std::type_info * typeinfo
Definition: TBranchAuxDynWriter.h:24
selection
std::string selection
Definition: fbtTestBasics.cxx:73
RootAuxDynIO::AuxInfo::dummyptr
dummy_ptr_t dummyptr
Definition: TBranchAuxDynWriter.h:38
RootAuxDynIO::AuxInfo::object
void * object
Definition: TBranchAuxDynWriter.h:29
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:194
RootAuxDynIO::TBranchAuxDynWriter::m_splitLevel
int m_splitLevel
Definition: TBranchAuxDynWriter.h:79
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
RootAuxDynIO::AuxInfo::dummy_ptr_t
std::unique_ptr< void, std::function< void(void *)> > dummy_ptr_t
Definition: TBranchAuxDynWriter.h:37
RootAuxDynIO
Specialization of RootAuxDynStore for reading Aux Dynamic attributes from RNTuple.
Definition: RNTupleContainer.h:25
RootAuxDynIO::AuxInfo::objectAddr
void * objectAddr()
Definition: TBranchAuxDynWriter.h:44
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
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
RootAuxDynIO::TBranchAuxDynWriter::TBranchAuxDynWriter
TBranchAuxDynWriter(TTree *tree, int bufferSize, int splitLevel, int offsettab_len, bool branch_fill)
Definition: TBranchAuxDynWriter.cxx:42
python.PyAthena.obj
obj
Definition: PyAthena.py:135
TBranchAuxDynWriter.h
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
RootAuxDynIO::TBranchAuxDynWriter::m_auxInfoMap
std::map< SG::auxid_t, AuxInfo > m_auxInfoMap
cached aux branches data by auxid
Definition: TBranchAuxDynWriter.h:85
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
RootAuxDynIO::AuxInfo::branch_name
std::string branch_name
Definition: TBranchAuxDynWriter.h:25
RootAuxDynIO::TBranchAuxDynWriter::m_bufferSize
int m_bufferSize
Definition: TBranchAuxDynWriter.h:78
RootAuxDynIO::AuxInfo::buffer
void * buffer
Definition: TBranchAuxDynWriter.h:30
RootAuxDynIO::TBranchAuxDynWriter::m_branchOffsetTabLen
int m_branchOffsetTabLen
Definition: TBranchAuxDynWriter.h:80