ATLAS Offline Software
Loading...
Searching...
No Matches
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
6
9
10#include "TFile.h"
11#include "TTree.h"
12#include "TBranch.h"
13#include "TClass.h"
14
15
16namespace 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 );
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
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle mappings between names and auxid_t.
std::atomic_flag m_initialized ATLAS_THREAD_SAFE
Messaging initialized (initMessaging)
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
SG::IAuxStoreIO * castIOStore(void *object)
void setBranchOffsetTabLen(TBranch *b, int offsettab_len)
virtual int commit() override final
Call Fill() on the ROOT object used by this writer.
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()
std::map< SG::auxid_t, AuxInfo > m_auxInfoMap
cached aux branches data by auxid
TBranchAuxDynWriter(TTree &tree, TClass &cls, int bufferSize, int splitLevel, int offsettab_len, bool branch_fill)
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Interface providing I/O for a generic auxiliary store.
Definition IAuxStoreIO.h:44
A set of aux data identifiers.
Definition AuxTypes.h:47
const std::string selection
int r
Definition globals.cxx:22
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
Specialization of RootAuxDynStore for reading Aux Dynamic attributes from RNTuple.
std::string auxBranchName(const std::string &attr_name, const std::string &baseBranchName)
Construct branch name for a given dynamic attribute.
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...
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
std::unique_ptr< void, std::function< void(void *)> > dummy_ptr_t
const std::type_info * typeinfo
TChain * tree