ATLAS Offline Software
TAuxStore.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 // System include(s):
4 #include <cassert>
5 #include <string.h>
6 #include <sstream>
7 #include <stdexcept>
8 
9 // ROOT include(s):
10 #include <TError.h>
11 #include <TTree.h>
12 #include <TBranch.h>
13 #include <TString.h>
14 #include <TClass.h>
15 #include <TROOT.h>
16 #include <TVirtualCollectionProxy.h>
17 #include <TBranchElement.h>
18 #include <TStreamerInfo.h>
19 #include <TStreamerElement.h>
20 
21 // Athena include(s):
26 #include "CxxUtils/as_const_ptr.h"
28 #include "xAODCore/tools/IOStats.h"
30 
31 // Local include(s):
37 
38 namespace {
39 
40 
41 TClass* lookupVectorType (TClass *cl)
42 {
43  std::string tname = cl->GetName();
44  tname += "::vector_type";
45  TDataType* typ = gROOT->GetType (tname.c_str());
46  if (typ)
47  return TClass::GetClass (typ->GetFullTypeName());
48  return nullptr;
49 }
50 
51 
52 }
53 
54 
55 namespace xAOD {
56 
57  TAuxStore::TAuxStore( const char* prefix, Bool_t topStore,
58  EStructMode mode, Int_t basketSize,
59  Int_t splitLevel )
60  : SG::IAuxStore(), SG::IAuxStoreIO(),
61  m_prefix( prefix ), m_dynPrefix( Utils::dynBranchPrefix( prefix ) ),
62  m_topStore( topStore ), m_structMode( mode ), m_basketSize( basketSize ),
63  m_splitLevel( splitLevel ), m_inTree( 0 ), m_outTree( 0 ),
64  m_inputScanned( kFALSE ), m_selection(), m_transientStore( 0 ),
65  m_auxIDs(), m_decorIDs(), m_vecs(), m_size( 0 ), m_locked( kFALSE ), m_isDecoration(),
66  m_mutex1(), m_mutex2(),
67  m_branches(), m_branchesWritten(), m_missingBranches() {
68 
69  }
70 
72 
75  for( ; vitr != vend; ++vitr ) {
76  if( *vitr ) delete *vitr;
77  }
78 
81  for( ; bitr != bend; ++bitr ) {
82  if( *bitr ) delete *bitr;
83  }
84 
86  }
87 
89 
90  return m_structMode;
91  }
92 
101 
102  // Only allow this on an uninitialised object:
103  if( m_branches.size() || ( m_structMode != kUndefinedStore ) ) {
104  ::Error( "xAOD::TAuxStore::setStructMode",
105  XAOD_MESSAGE( "Trying to change the structure mode of an "
106  "initialised object" ) );
107  return StatusCode::FAILURE;
108  }
109 
110  // Make the change:
111  m_structMode = mode;
112  return StatusCode::SUCCESS;
113  }
114 
115  const char* TAuxStore::prefix() const {
116 
117  return m_prefix.c_str();
118  }
119 
120  void TAuxStore::setPrefix( const char* prefix ) {
121 
122  m_prefix = prefix;
124  reset();
125  return;
126  }
127 
128  ::Bool_t TAuxStore::isTopStore() const {
129 
130  return m_topStore;
131  }
132 
133  void TAuxStore::setTopStore( ::Bool_t value ) {
134 
135  m_topStore = value;
136  reset();
137  return;
138  }
139 
140  ::Int_t TAuxStore::basketSize() const {
141 
142  return m_basketSize;
143  }
144 
145  void TAuxStore::setBasketSize( ::Int_t value ) {
146 
148  return;
149  }
150 
151  ::Int_t TAuxStore::splitLevel() const {
152 
153  return m_splitLevel;
154  }
155 
156  void TAuxStore::setSplitLevel( ::Int_t value ) {
157 
159  return;
160  }
161 
167  StatusCode TAuxStore::readFrom( ::TTree* tree, ::Bool_t printWarnings ) {
168 
169  // Make sure that everything will be re-read after this:
170  reset();
171 
172  // We will need to check again which branches are available:
173  m_missingBranches.clear();
174 
175  // Remember the tree:
176  m_inTree = tree;
177 
178  // Catalogue all the branches:
179  RETURN_CHECK( "xAOD::TAuxStore::readFrom", scanInputTree() );
180 
181  // Check if we'll be likely to be able to read the "static"
182  // variables:
183  assert( m_inTree != nullptr );
184  TBranch* br = m_inTree->GetBranch( m_prefix.c_str() );
185  if( ! br ) {
186  // We might not even have static branches, so this is not an error
187  // by itself...
188  return StatusCode::SUCCESS;
189  }
190  // In order to read complex objects, like smart pointers from an
191  // auxiliary container variable-by-variable, the split level of the
192  // branch must be exactly 1.
193  if( ( br->GetSplitLevel() != 1 ) && m_topStore && printWarnings ) {
194  ::Warning( "xAOD::TAuxStore::readFrom",
195  "Static branch (%s) with split level %i discovered",
196  m_prefix.c_str(), br->GetSplitLevel() );
197  ::Warning( "xAOD::TAuxStore::readFrom",
198  "The reading of complex variables from it may/will fail!" );
199  }
200 
201  return StatusCode::SUCCESS;
202  }
203 
210 
211  // Look for any auxiliary branches that have not been connected to yet:
212  RETURN_CHECK( "xAOD::TAuxStore::writeTo", scanInputTree() );
213 
214  // Store the TTree pointer:
215  m_outTree = tree;
216 
217  // Create all the variables that we already know about. Notice that the
218  // code makes a copy of the auxid set on purpose. Because the underlying
219  // AuxSelection object gets modified while doing the for loop.
220  const auxid_set_t selAuxIDs = getSelectedAuxIDs();
221  for (SG::auxid_t id : selAuxIDs) {
222  RETURN_CHECK( "xAOD::TAuxStore::writeTo", setupOutputData( id ) );
223  }
224 
225  return StatusCode::SUCCESS;
226  }
227 
228  ::Int_t TAuxStore::getEntry( ::Int_t getall ) {
229 
230  // Guard against multi-threaded execution:
231  guard_t guard( m_mutex1 );
232 
233  // Reset the transient store. TEvent::fill() calls this function with
234  // getall==99. When that is happening, we need to keep the transient
235  // store still around. Since the user may want to interact with the
236  // object after it was written out. (And since TEvent::fill() asks for
237  // the transient decorations after calling getEntry(...).)
238  if( m_transientStore && ( getall != 99 ) ) {
239  // Remove the transient auxiliary IDs from the internal list:
242  // Delete the object:
243  delete m_transientStore;
244  m_transientStore = 0;
245  }
246 
247  // Now remove the IDs of the decorations that are getting persistified:
248  if( getall != 99 ) {
249  for( auxid_t auxid = 0; auxid < m_isDecoration.size(); ++auxid ) {
250  if( ! m_isDecoration[ auxid ] ) {
251  continue;
252  }
253  m_auxIDs.erase( auxid );
254  m_decorIDs.erase( auxid );
255  }
256  }
257 
258  // If we don't need everything loaded, return now:
259  if( ! getall ) return 0;
260 
261  // Get all the variables at once:
262  ::Int_t bytesRead = 0;
265  for( ; itr != end; ++itr ) {
266  if( *itr ) {
267  bytesRead += ( *itr )->getEntry();
268  }
269  }
270 
271  return bytesRead;
272  }
273 
275 
276  // Reset all the branches:
279  for( ; itr != end; ++itr ) {
280  if( *itr ) ( *itr )->reset();
281  }
282 
283  // Remember that the input TTree needs to be re-scanned:
284  m_inputScanned = kFALSE;
285 
286  return;
287  }
288 
289  const void* TAuxStore::getData( auxid_t auxid ) const {
290 
291  const SG::IAuxTypeVector* v = getVector( auxid );
292  if( v ) {
293  return v->toPtr();
294  }
295  return nullptr;
296  }
297 
299 
300  // Guard against multi-threaded execution:
301  guard_t guard( m_mutex1 );
302 
303  // Check if the transient store already handles this variable:
304  if( m_transientStore &&
305  ( m_transientStore->getAuxIDs().test( auxid ) ) ) {
306  return m_transientStore->getVector( auxid );
307  }
308 
309  // Connect this auxiliary variable both to the input and output
310  // if needed:
311  if( ( auxid >= m_vecs.size() ) || ( ! m_vecs[ auxid ] ) ||
312  ( auxid >= m_branches.size() ) || ( ! m_branches[ auxid ] ) ) {
313  auto this_nc ATLAS_THREAD_SAFE = const_cast<TAuxStore*>(this); // locked above
314  if( ( ! this_nc->setupInputData( auxid ).isSuccess() ) ||
315  ( ! this_nc->setupOutputData( auxid ).isSuccess() ) ) {
316  return nullptr;
317  }
318  }
319 
320  // Make sure the variable is up to date:
321  const ::Int_t readBytes = m_branches[ auxid ]->getEntry();
322  if( readBytes < 0 ) {
323  ::Error( "xAOD::TAuxStore::getData",
324  XAOD_MESSAGE( "Couldn't read in variable %s" ),
325  SG::AuxTypeRegistry::instance().getName( auxid ).c_str() );
326  return nullptr;
327  }
328 
329  // Return the pointer to the object:
330  return m_vecs[ auxid ];
331  }
332 
334 
335  return m_auxIDs;
336  }
337 
339 
340  return m_decorIDs;
341  }
342 
343  void* TAuxStore::getDecoration( auxid_t auxid, size_t size,
344  size_t capacity ) {
345 
346  // Guard against multi-threaded execution:
347  guard_t guard( m_mutex1 );
348 
349  // Remember the requested size:
350  m_size = size;
351 
352  // If this is a locked object, deal with it correctly:
353  if( m_locked ) {
354  // If the variable exists already and it's a decoration, then let's
355  // give it back.
356  if( ( auxid < m_vecs.size() ) && m_vecs[ auxid ] &&
357  ( auxid < m_isDecoration.size() && m_isDecoration[ auxid ] ) ) {
358  // Things look okay...
359  m_vecs[ auxid ]->reserve( capacity );
360  m_vecs[ auxid ]->resize( size );
361  return m_vecs[ auxid ]->toPtr();
362  }
363  // If it's in the transient store already, return it from there.
364  // Since in a locked store *everything* is a decoration in the
365  // transient store.
366  if( m_transientStore &&
367  m_transientStore->getAuxIDs().test( auxid ) ) {
368  return m_transientStore->getDecoration( auxid, size, capacity );
369  }
370  // If we know this auxiliary ID, but it was not found as a decoration
371  // by the previous checks, then we're in trouble.
372  if( m_auxIDs.test( auxid ) ) {
373  // It may still be a decoration in a transient store. If such
374  // a store exists, leave it up to that store to
375  throw SG::ExcStoreLocked( auxid );
376  }
377  }
378 
379  // Check if we want to write this variable to the output:
380  if( ( ! isAuxIDSelected( auxid ) ) || ( ! m_outTree ) ) {
381 
382  // Create the store only when necessary:
383  if( ! m_transientStore ) {
386  if( m_locked ) {
388  }
389  }
390  // Let the transient store create the decoration:
391  const size_t nids = m_transientStore->getAuxIDs().size();
392  void* result = m_transientStore->getDecoration( auxid, size,
393  capacity );
394  if( result && ( nids != m_transientStore->getAuxIDs().size() ) ) {
395  m_auxIDs.insert( auxid );
396  if( m_transientStore->isDecoration( auxid ) ) {
397  m_decorIDs.insert( auxid );
398  }
399  }
400  // Return the memory address from the transient store:
401  return result;
402  }
403 
404  // Doesn't exist yet. So let's make it:
405  void* result = getData( auxid, size, capacity );
406  if( m_locked ) {
407  // If the container is locked, remember that this is a decoration:
408  if( m_isDecoration.size() <= auxid ) {
409  m_isDecoration.resize( auxid + 1 );
410  }
411  m_isDecoration[ auxid ] = ::kTRUE;
412  m_decorIDs.insert( auxid );
413  }
414 
415  // Return the pointer made by getData(...):
416  return result;
417  }
418 
419 
421  {
422  if (m_locked) {
423  if (auxid < m_isDecoration.size() && m_isDecoration[auxid]) {
424  return true;
425  }
426  if (m_transientStore) {
427  return m_transientStore->isDecoration (auxid);
428  }
429  }
430  return false;
431  }
432 
433 
435 
436  // Guard against multi-threaded execution:
437  guard_t guard( m_mutex1 );
438 
439  m_locked = true;
440  if( m_transientStore ) {
442  }
443 
444  return;
445  }
446 
448 
449  // Guard against multi-threaded execution:
450  guard_t guard( m_mutex1 );
451 
452  // Clear the transient decorations:
453  bool anycleared = false;
454  if( m_transientStore ) {
456 
457  // Clear the decorations from the transient store:
458  anycleared = m_transientStore->clearDecorations();
459 
460  // Now remove ids that were cleared.
461  if (anycleared) {
462  old_id_set -= m_transientStore->getAuxIDs();
463  // old_id_set is now the set of ids that were cleared.
464  m_auxIDs -= old_id_set;
465  m_decorIDs.clear();
466  }
467  }
468 
469  // The decorations which are going into the output file, are here to stay.
470  // Removing their IDs from the internal set would just cause more problems
471  // in my mind than just leaving them be.
472 
473  return anycleared;
474  }
475 
478  {
479  if( m_transientStore ) {
481  }
482  m_decorIDs.erase( auxid );
483  }
484 
485 
486  size_t TAuxStore::size() const {
487 
488  // First, try to find a managed vector in the store:
489  for( SG::auxid_t id : m_auxIDs) {
490  // Make sure that we are still within the bounds of our vector:
491  if( id >= m_vecs.size() ) break;
492  // Skip non-existent or linked objects:
493  if( ! m_vecs[ id ] || m_vecs[ id ]->isLinked() ) continue;
494  // Ask the vector for its size:
495  const size_t size = m_vecs[ id ]->size();
496  // Only accept a non-zero size. Not sure why...
497  if( size > 0 ) {
498  return size;
499  }
500  }
501 
502  // Check if we have a transient store, and get the size from that:
503  if( m_transientStore ) {
504  return m_transientStore->size();
505  }
506 
507  // Apparently the store is empty:
508  return 0;
509  }
510 
513  auxid_t linked_id = r.linkedVariable( auxid );
514  guard_t guard( m_mutex1 );
515  if ( linked_id < m_vecs.size() ) {
516  return m_vecs[ linked_id ];
517  }
518  if ( m_transientStore ) {
519  return CxxUtils::as_const_ptr(m_transientStore)->linkedVector( auxid );
520  }
521  return nullptr;
522  }
523 
526  auxid_t linked_id = r.linkedVariable( auxid );
527  guard_t guard( m_mutex1 );
528  if ( linked_id < m_vecs.size() ) {
529  return m_vecs[ linked_id ];
530  }
531  if ( m_transientStore ) {
532  return m_transientStore->linkedVector( auxid );
533  }
534  return nullptr;
535  }
536 
537  void* TAuxStore::getData( auxid_t auxid, size_t size,
538  size_t capacity ) {
539 
540  // Guard against multi-threaded execution:
541  guard_t guard( m_mutex2 );
542 
543  // Remember the size:
544  m_size = size;
545 
546  // Check if we want to write this variable to the output:
547  if( ( ! m_outTree ) || ( ! isAuxIDSelected( auxid ) ) ) {
548  // Create the store only when necessary:
549  if( ! m_transientStore ) {
552  if( m_locked ) {
554  }
555  }
556  // Let the transient store create the variable:
557  size_t nids = m_transientStore->getAuxIDs().size();
558  void* result = m_transientStore->getData( auxid, size, capacity );
559  if( result && ( nids != m_transientStore->getAuxIDs().size() ) ) {
560  m_auxIDs.insert( auxid );
561  }
562  // Return the address in the transient memory:
563  return result;
564  }
565 
566  // If the variable exists already, and this is a locked store, then
567  // we are in trouble.
568  if( m_locked && ( auxid < m_vecs.size() ) && m_vecs[ auxid ] ) {
569  if( ! ( ( auxid < m_isDecoration.size() ) &&
570  m_isDecoration[ auxid ] ) ) {
571  throw SG::ExcStoreLocked( auxid );
572  }
573  }
574 
575  // Connect this auxiliary variable just to the output:
576  if( setupOutputData( auxid ).isFailure() ) {
577  ::Error( "xAOD::TAuxStore::getData",
578  XAOD_MESSAGE( "Failed to set up variable %s" ),
579  SG::AuxTypeRegistry::instance().getName( auxid ).c_str() );
580  return 0;
581  }
582 
583  // Check whether things make sense:
584  if( ( m_structMode == kObjectStore ) && ( size != 1 ) ) {
585  ::Error( "xAOD::TAuxStore::getData",
586  XAOD_MESSAGE( "Branch creation requested with:" ) );
587  ::Error( "xAOD::TAuxStore::getData",
588  XAOD_MESSAGE( " name = %s" ),
589  SG::AuxTypeRegistry::instance().getName( auxid ).c_str() );
590  ::Error( "xAOD::TAuxStore::getData",
591  XAOD_MESSAGE( " size = %i" ),
592  static_cast< int >( size ) );
593  ::Error( "xAOD::TAuxStore::getData",
594  XAOD_MESSAGE( " m_structMode = kObjectStore" ) );
595  return 0;
596  }
597 
598  // Make sure the variable is of the right size:
599  m_vecs[ auxid ]->reserve( capacity );
600  m_vecs[ auxid ]->resize( size );
601 
602  // Return the object:
603  return m_vecs[ auxid ]->toPtr();
604  }
605 
607 
608  return getAuxIDs();
609  }
610 
611  bool TAuxStore::resize( size_t size ) {
612 
613  // Guard against multi-threaded execution:
614  guard_t guard( m_mutex1 );
615 
616  // A sanity check:
617  if( ( m_structMode == kObjectStore ) && ( size != 1 ) ) {
618  ::Error( "xAOD::TAuxStore::resize",
619  XAOD_MESSAGE( "size = %i for single-object store" ),
620  static_cast< int >( size ) );
621  return false;
622  }
623 
624  // Remember the new size:
625  m_size = size;
626 
627  bool nomoves = true;
628  for (SG::IAuxTypeVector* v : m_vecs) {
629  if(v && !v->isLinked()) {
630  if (!v->resize( size ))
631  nomoves = false;
632  }
633  }
634  if( m_transientStore ) {
635  if (!m_transientStore->resize( size ))
636  nomoves = false;
637  }
638 
639  return nomoves;
640  }
641 
642  void TAuxStore::reserve( size_t size ) {
643 
644  // Guard against multi-threaded execution:
645  guard_t guard( m_mutex1 );
646 
647  // A sanity check:
648  if( ( m_structMode == kObjectStore ) && ( size != 1 ) ) {
649  ::Error( "xAOD::TAuxStore::reserve",
650  XAOD_MESSAGE( "size = %i for single-object store" ),
651  static_cast< int >( size ) );
652  return;
653  }
654 
655  for (SG::IAuxTypeVector* v : m_vecs) {
656  if(v && !v->isLinked()) {
657  v->reserve( size );
658  }
659  }
660 
661  if( m_transientStore ) {
663  }
664 
665  return;
666  }
667 
668  void TAuxStore::shift( size_t pos, ptrdiff_t offs ) {
669 
670  // Guard against multi-threaded execution:
671  guard_t guard( m_mutex1 );
672 
673  // A sanity check:
674  if( m_structMode == kObjectStore ) {
675  ::Error( "xAOD::TAuxStore::shift",
676  XAOD_MESSAGE( "Should not have been called for single-object "
677  "store" ) );
678  return;
679  }
680 
681  // Adjust the size of the container:
682  if( ( static_cast< std::size_t >( std::abs( offs ) ) > m_size ) &&
683  ( offs < 0 ) ) {
684  m_size = 0;
685  } else {
686  m_size += offs;
687  }
688 
689  for (SG::IAuxTypeVector* v : m_vecs) {
690  if(v && !v->isLinked()) {
691  v->shift( pos, offs );
692  }
693  }
694 
695  if( m_transientStore ) {
696  m_transientStore->shift( pos, offs );
697  }
698 
699  return;
700  }
701 
703  IAuxStore& other,
704  const SG::auxid_set_t& ignore_in)
705  {
706  // Guard against multi-threaded execution:
707  guard_t guard( m_mutex1 );
708 
709  // A sanity check:
710  if( m_structMode == kObjectStore ) {
711  ::Error( "xAOD::TAuxStore::insertMove",
712  XAOD_MESSAGE( "Should not have been called for single-object "
713  "store" ) );
714  return false;
715  }
716 
717  bool nomove = true;
718  size_t other_size = other.size();
719 
720  SG::auxid_set_t ignore = ignore_in;
721 
722  for (SG::auxid_t id : m_auxIDs) {
723  SG::IAuxTypeVector* v_dst = nullptr;
724  if (id < m_vecs.size())
725  v_dst = m_vecs[id];
726  if (v_dst && !v_dst->isLinked()) {
727  ignore.insert (id);
728  if (other.getData (id)) {
729  void* src_ptr = other.getData (id, other_size, other_size);
730  if (src_ptr) {
731  if (!v_dst->insertMove (pos, src_ptr, 0, other_size,
732  other))
733  nomove = false;
734  }
735  }
736  else {
737  const void* orig = v_dst->toPtr();
738  v_dst->shift (pos, other_size);
739  if (orig != v_dst->toPtr())
740  nomove = false;
741  }
742  }
743  }
744 
745  if( m_transientStore ) {
747  nomove = false;
748  }
749 
750  return nomove;
751  }
752 
753 
754  const void* TAuxStore::getIOData( auxid_t auxid ) const {
755 
756  // Guard against multi-threaded execution:
757  guard_t guard( m_mutex1 );
758 
759  // If the variable is connected to already:
760  if( ( auxid < m_branches.size() ) && m_branches[ auxid ] ) {
761  // Make sure that the right payload is in memory:
762  m_branches[ auxid ]->getEntry();
763  // Return the pointer:
764  return m_branches[ auxid ]->objectPtr();
765  }
766 
767  // Check if it's in the transient store:
768  if( m_transientStore && m_transientStore->getAuxIDs().test( auxid ) ) {
769  return m_transientStore->getIOData( auxid );
770  }
771 
772  // If not, try connecting to it now:
773  auto this_nc ATLAS_THREAD_SAFE = const_cast<TAuxStore*>(this); // locked above
774  if( ! this_nc->setupInputData( auxid ).isSuccess() ) {
775  // This is not actually an error condition anymore. We can end up here
776  // when we decorate constant objects coming from the input file, but
777  // on one event we can't set any decorations. For instance when the
778  // input container is empty. In that case the object will still list
779  // the auxiliary ID belonging to that decoration as being available,
780  // but it really isn't.
781  //
782  // Later on it might be needed to tweak the logic of all of this, but
783  // for now just silently returning 0 seems to do the right thing.
784  return 0;
785  }
786 
787  // Now we should know this variable:
788  if( ( auxid >= m_branches.size() ) || ( ! m_branches[ auxid ] ) ) {
789  ::Fatal( "xAOD::TAuxStore::getIOData",
790  XAOD_MESSAGE( "Internal logic error detected" ) );
791  return 0;
792  }
793 
794  // Make sure that the right payload is in memory:
795  m_branches[ auxid ]->getEntry();
796 
797  // Return the pointer:
798  return m_branches[ auxid ]->objectPtr();
799  }
800 
801  const std::type_info* TAuxStore::getIOType( auxid_t auxid ) const {
802 
803  // Guard against multi-threaded execution:
804  guard_t guard( m_mutex1 );
805 
806  // If the variable is connected to already:
807  if( ( auxid < m_branches.size() ) && m_branches[ auxid ] ) {
808  return m_branches[ auxid ]->typeInfo();
809  }
810 
811  // Check if it's in the transient store:
812  if( m_transientStore && m_transientStore->getAuxIDs().test( auxid ) ) {
813  return m_transientStore->getIOType( auxid );
814  }
815 
816  // If not, try connecting to it now:
817  auto this_nc ATLAS_THREAD_SAFE = const_cast<TAuxStore*>(this); // locked above
818  if( ! this_nc->setupInputData( auxid ).isSuccess() ) {
819  ::Error( "xAOD::TAuxStore::getIOType",
820  XAOD_MESSAGE( "Couldn't connect to auxiliary variable "
821  "%i %s" ),
822  static_cast< int >( auxid ),
823  SG::AuxTypeRegistry::instance().getName( auxid ).c_str() );
824  return 0;
825  }
826 
827  // Now we should know this variable:
828  if( ( auxid >= m_branches.size() ) || ( ! m_branches[ auxid ] ) ) {
829  ::Fatal( "xAOD::TAuxStore::getIOType",
830  XAOD_MESSAGE( "Internal logic error detected" ) );
831  return 0;
832  }
833 
834  // Return the type info:
835  return m_branches[ auxid ]->typeInfo();
836  }
837 
839 
840  // All the auxiliary decorations handled by this object are considered
841  // dynamic:
842  return getAuxIDs();
843  }
844 
845  void TAuxStore::selectAux( const std::set< std::string >& attributes ) {
846 
847  // Guard against multi-threaded execution:
848  guard_t guard( m_mutex1 );
849 
851  return;
852  }
853 
855 
856  // Guard against multi-threaded execution:
857  guard_t guard( m_mutex1 );
858 
859  // Leave the calculation up to the internal object:
861  }
862 
872 
873  // Connect the object to this input tree:
874  RETURN_CHECK( "initStats", readFrom( tree, kFALSE ) );
875 
876  // Conveninence variable:
878 
879  // Teach the cache about all the branches:
880  size_t nbranch = 0;
881  for (SG::auxid_t id : m_auxIDs) {
882  stats.branch( m_prefix, id );
883  ++nbranch;
884  }
885 
886  // Increment the number of known branches:
887  stats.setBranchNum( stats.branchNum() + nbranch );
888 
889  // Return gracefully:
890  return StatusCode::SUCCESS;
891  }
892 
902 
903  // Return right away if we already know that the branch is missing:
904  if( ( auxid < m_missingBranches.size() ) && m_missingBranches[ auxid ] ) {
905  return StatusCode::RECOVERABLE;
906  }
907 
908  // Make sure the internal storage is large enough:
909  if( m_vecs.size() <= auxid ) {
910  m_vecs.resize( auxid + 1 );
911  }
912  if( m_branches.size() <= auxid ) {
913  m_branches.resize( auxid + 1 );
914  }
915 
916  // Check if we need to do anything:
917  if( m_vecs[ auxid ] && m_branches[ auxid ] ) {
918  return StatusCode::SUCCESS;
919  }
920 
921  // A little sanity check:
922  if( ! m_inTree ) {
923  ::Error( "xAOD::TAuxStore::setupInputData",
924  XAOD_MESSAGE( "No input TTree set up!" ) );
925  return StatusCode::FAILURE;
926  }
927 
928  // Another sanity check:
929  if( m_vecs[ auxid ] || m_branches[ auxid ] ) {
930  ::Error( "xAOD::TAuxStore::setupInputData",
931  XAOD_MESSAGE( "The internal variables of the object got "
932  "messed up?!?" ) );
933  return StatusCode::FAILURE;
934  }
935 
937 
938  // Get the property name:
939  const TString statBrName = m_prefix + r.getName( auxid ).c_str();
940  const TString dynBrName = m_dynPrefix + r.getName( auxid ).c_str();
941 
942  // Check if the branch exists:
943  Bool_t staticBranch = kTRUE;
944  TString brName = statBrName;
945 
946  TBranch* br = m_inTree->GetBranch( statBrName );
947  if( ! br ) {
948  br = m_inTree->GetBranch( dynBrName );
949  if( ! br ) {
950  // Since TTree::GetBranch / TTObjArray::FindObject is expensive,
951  // remember that we didn't find this branch in this file.
952  if( m_missingBranches.size() <= auxid ) {
953  m_missingBranches.resize( auxid + 1 );
954  }
955  m_missingBranches[ auxid ] = true;
956  // The branch doesn't exist, but this is not an error per se.
957  // The user may just be calling isAvailable(...) on the variable.
958  return StatusCode::RECOVERABLE;
959  }
960  // We have a dynamic branch:
961  staticBranch = kFALSE;
962  brName = dynBrName;
963  }
964 
965  // Check if it's a "primitive branch":
966  const Bool_t primitiveBranch = isPrimitiveBranch( br );
967  // Check if it's a "container branch":
968  const Bool_t containerBranch =
969  ( primitiveBranch ? kFALSE : isContainerBranch( br, auxid ) );
970 
971  // Set the structure mode if it has not been defined externally:
972  if( m_structMode == kUndefinedStore ) {
973  m_structMode = ( containerBranch ? kContainerStore : kObjectStore );
974  }
975 
976  // Check that the branch type makes sense:
977  if( ( containerBranch && ( m_structMode != kContainerStore ) && !r.isLinked( auxid ) ) ||
978  ( ( ! containerBranch ) && ( m_structMode != kObjectStore ) ) ) {
979  ::Error( "xAOD::TAuxStore::setupInputData",
980  XAOD_MESSAGE( "Branch type and requested structure mode "
981  "differ for branch: %s" ),
982  brName.Data() );
983  return StatusCode::FAILURE;
984  }
985 
986  // Check what variable it is:
987  ::TClass* clDummy = 0;
988  ::EDataType dType = kOther_t;
989  if( br->GetExpectedType( clDummy, dType ) ) {
990  ::Error( "xAOD::TAuxStore::setupInputData",
991  XAOD_MESSAGE( "Couldn't determine the type of branch "
992  "\"%s\"" ), brName.Data() );
993  return StatusCode::FAILURE;
994  }
995 
996  // Get the property type:
997  const std::type_info* brType = 0;
998  if( isRegisteredType( auxid ) ) {
999  // Get the type from the auxiliary type registry:
1000  brType =
1001  ( containerBranch ?
1002  r.getVecType( auxid ) :
1003  r.getType( auxid ) );
1004  } else {
1005  // Get the type from the input branch itself:
1006  brType = ( clDummy ? clDummy->GetTypeInfo() :
1007  &( Utils::getTypeInfo( dType ) ) );
1008  }
1009  if( ! brType ) {
1010  ::Error( "xAOD::TAuxStore::setupInputData",
1011  XAOD_MESSAGE( "Can't read/copy variable %s (%s)" ),
1012  brName.Data(), clDummy->GetName() );
1013  return StatusCode::RECOVERABLE;
1014  }
1015  const TString brTypeName = Utils::getTypeName( *brType ).c_str();
1016 
1017  // Check if we have the needed dictionary for an object branch:
1018  ::TClass* brClass = 0;
1019  if( ! primitiveBranch ) {
1020  // Get the property's class:
1021  brClass = ::TClass::GetClass( *brType, kTRUE, kTRUE );
1022  if( ! brClass ) {
1023  brClass = ::TClass::GetClass( brTypeName );
1024  }
1025  if( ! brClass ) {
1026  ::Error( "xAOD::TAuxStore::setupInputData",
1027  XAOD_MESSAGE( "No dictionary available for class \"%s\"" ),
1028  brTypeName.Data() );
1029  return StatusCode::FAILURE;
1030  }
1031  }
1032 
1033  // Create the smart object holding this vector:
1034  if( isRegisteredType( auxid ) ) {
1035  m_vecs[ auxid ] =
1036  r.makeVector( auxid, (size_t)0, (size_t)0 ).release();
1037  if( ! containerBranch ) {
1038  m_vecs[ auxid ]->resize( 1 );
1039  }
1040  if (clDummy && strncmp (clDummy->GetName(), "SG::PackedContainer<", 20) == 0) {
1041  SG::IAuxTypeVector* packed = m_vecs[ auxid ]->toPacked().release();
1042  std::swap (m_vecs[ auxid ], packed);
1043  delete packed;
1044  }
1045  } else {
1046  ::Error( "xAOD::TAuxStore::setupInputData",
1047  XAOD_MESSAGE( "Couldn't create in-memory vector for "
1048  "variable %s (%i)" ),
1049  brName.Data(),
1050  static_cast< int >( auxid ) );
1051  return StatusCode::FAILURE;
1052  }
1053 
1054  // Create a new branch handle:
1055  const std::type_info* objType = brType;
1056  if (containerBranch) {
1057  objType = m_vecs[ auxid ]->objType();
1058  if (!objType)
1059  objType = r.getType( auxid );
1060  }
1061  m_branches[ auxid ] = new TBranchHandle( staticBranch, primitiveBranch,
1062  objType,
1063  ( containerBranch ?
1064  m_vecs[ auxid ]->toVector() :
1065  m_vecs[ auxid ]->toPtr() ),
1066  auxid, &m_prefix );
1067 
1068  // Set the tree/branch in the "right mode":
1069  if( staticBranch ) {
1070  br->SetMakeClass();
1071  }
1072 
1073  // Connect to the branch:
1074  ::Int_t status = 0;
1075  if( clDummy &&
1076  ::TString( clDummy->GetName() ).Contains( "basic_string<char>" ) ) {
1077  // This is pretty much just a hack. As it happens, Athena I/O can
1078  // create dynamic branches that consider themselves to be of type
1079  // "vector<basic_string<char> >" and similar. (Instead of the
1080  // canonical "vector<string>" name.) When we encounter such a branch,
1081  // we just connect to it without performing any compatibility checks.
1082  // Since we don't need to apply any read rules in this case anyway.
1083  status =
1084  m_inTree->SetBranchAddress( brName,
1085  m_branches[ auxid ]->inputObjectPtr(),
1086  m_branches[ auxid ]->branchPtr() );
1087  } else {
1088  status =
1089  m_inTree->SetBranchAddress( brName,
1090  m_branches[ auxid ]->inputObjectPtr(),
1091  m_branches[ auxid ]->branchPtr(),
1092  brClass, dType,
1093  ( ( ! staticBranch ) &&
1094  ( ! primitiveBranch ) ) );
1095  }
1096  if( status < 0 ) {
1097  ::Error( "xAOD::TAuxStore::setupInputData",
1098  XAOD_MESSAGE( "Coulnd't connect to branch \"%s\"" ),
1099  brName.Data() );
1100  ::Error( "xAOD::TAuxStore::setupInputData",
1101  XAOD_MESSAGE( "Return code: %i" ), status );
1102  delete m_vecs[ auxid ];
1103  m_vecs[ auxid ] = 0;
1104  delete m_branches[ auxid ];
1105  m_branches[ auxid ] = 0;
1106  return StatusCode::FAILURE;
1107  }
1108 
1109  // Get the current entry:
1110  m_branches[ auxid ]->getEntry();
1111 
1112  // Remember which variable got created:
1113  m_auxIDs.insert( auxid );
1114 
1115  // Check if we just replaced a generic object:
1116  if( isRegisteredType( auxid ) ) {
1117  // The name of the variable we just created:
1118  const std::string auxname = r.getName( auxid );
1119  // Check if there's another variable with this name already:
1120  for( auxid_t i = 0; i < m_vecs.size(); ++i ) {
1121  // Check if we have this aux ID:
1122  if( ! m_vecs[ i ] ) continue;
1123  // Ingore the object that we *just* created:
1124  if( i == auxid ) continue;
1125  // The name of the variable:
1126  const std::string testname = r.getName( i );
1127  // Check if it has the same name:
1128  if( testname != auxname ) continue;
1129  // Check that the other one is a non-registered type:
1130  if( isRegisteredType( i ) ) {
1131  ::Error( "xAOD::TAuxStore::setupInputData",
1132  XAOD_MESSAGE( "Internal logic error!" ) );
1133  continue;
1134  }
1135  // Okay, we do need to remove this object:
1136  delete m_vecs[ i ]; delete m_branches[ i ];
1137  m_vecs[ i ] = 0; m_branches[ i ] = 0;
1138  m_auxIDs.erase( i );
1139  }
1140  }
1141 
1142  SG::auxid_t linked_auxid = r.linkedVariable( auxid );
1143  if (linked_auxid != SG::null_auxid) {
1144  return setupInputData( linked_auxid );
1145  }
1146 
1147  // Return gracefully:
1148  return StatusCode::SUCCESS;
1149  }
1150 
1159 
1160  // Check whether we need to do anything:
1161  if( ! m_outTree ) return StatusCode::SUCCESS;
1162 
1163  // Check if the variable needs to be written out:
1164  if( ! isAuxIDSelected( auxid ) ) return StatusCode::SUCCESS;
1165 
1166  // Make sure that containers are large enough:
1167  if( m_vecs.size() <= auxid ) {
1168  m_vecs.resize( auxid + 1 );
1169  }
1170  if( m_branches.size() <= auxid ) {
1171  m_branches.resize( auxid + 1 );
1172  }
1173  if( m_branchesWritten.size() <= auxid ) {
1174  m_branchesWritten.resize( auxid + 1 );
1175  }
1176 
1177  // Check if this auxiliary variable is already in the output:
1178  if( m_branchesWritten[ auxid ] ) return StatusCode::SUCCESS;
1179 
1180  // Check if the variable was put into the transient store as a
1181  // decoration, and now needs to be put into the output file:
1182  if( ( ! m_vecs[ auxid ] ) && m_transientStore &&
1183  ( m_transientStore->getAuxIDs().test( auxid ) ) ) {
1184 
1185  // Get the variable from the transient store:
1186  const void* pptr = m_transientStore->getData( auxid );
1187  if( ! pptr ) {
1188  ::Fatal( "xAOD::TAuxStore::setupOutputData",
1189  XAOD_MESSAGE( "Internal logic error detected" ) );
1190  return StatusCode::FAILURE;
1191  }
1192 
1193  // The registry:
1195 
1196  // Create the new object:
1197  m_vecs[ auxid ] = reg.makeVector( auxid, m_size, m_size ).release();
1198  void* ptr = m_vecs[ auxid ]->toPtr();
1199  if( ! ptr ) {
1200  ::Error( "xAOD::TAuxStore::setupOutputData",
1201  XAOD_MESSAGE( "Couldn't create decoration in memory "
1202  "for writing" ) );
1203  return StatusCode::FAILURE;
1204  }
1205 
1206  // Get the type of this variable:
1207  const std::type_info* type = reg.getType( auxid );
1208  if( ! type ) {
1209  ::Error( "xAOD::TAuxStore::setupOutputData",
1210  XAOD_MESSAGE( "Couldn't get the type of transient "
1211  "variable %i" ),
1212  static_cast< int >( auxid ) );
1213  return StatusCode::FAILURE;
1214  }
1215  // Now get the factory for this variable:
1216  const SG::IAuxTypeVectorFactory* factory =
1217  reg.getFactory( auxid );
1218  if( ! factory ) {
1219  ::Error( "xAOD::TAuxStore::setupOutputData",
1220  XAOD_MESSAGE( "No factory found for transient variable "
1221  "%i" ), static_cast< int >( auxid ) );
1222  return StatusCode::FAILURE;
1223  }
1224 
1225  // Finally, do the copy:
1226  factory->copy( auxid,
1227  SG::AuxVectorInterface( *this ), 0,
1229  m_size );
1230 
1231  // And now remember that this is a decoration:
1232  if( m_isDecoration.size() <= auxid ) {
1233  m_isDecoration.resize( auxid + 1 );
1234  }
1235  m_isDecoration[ auxid ] = ::kTRUE;
1236  }
1237 
1238  // Check if we know about this variable to be on the input,
1239  // but haven't connected to it yet:
1240  if( ( m_auxIDs.test( auxid ) ) &&
1241  ( ! m_vecs[ auxid ] ) && ( ! m_branches[ auxid ] ) ) {
1242  RETURN_CHECK( "xAOD::TAuxStore::setupOutputData",
1243  setupInputData( auxid ) );
1244  }
1245 
1246  // Check that we know the store's type:
1247  if( ( m_structMode != kContainerStore ) &&
1248  ( m_structMode != kObjectStore ) ) {
1249  ::Error( "xAOD::TAuxStore::setupOutputData",
1250  XAOD_MESSAGE( "Structure mode unknown for variable %s" ),
1251  SG::AuxTypeRegistry::instance().getName( auxid ).c_str() );
1252  return StatusCode::FAILURE;
1253  }
1254 
1255  // Check if the variable exists already in memory:
1256  if( ! m_vecs[ auxid ] ) {
1257  m_vecs[ auxid ] =
1258  SG::AuxTypeRegistry::instance().makeVector( auxid, (size_t)0, (size_t)0 ).release();
1259  if( m_structMode == kObjectStore ) {
1260  m_vecs[ auxid ]->resize( 1 );
1261  }
1262  }
1263 
1264  // Check if the branch handle exists already:
1265  if( ! m_branches[ auxid ] ) {
1266  // Get the property type:
1267  const std::type_info* brType =
1271  // Create the handle object:
1272  bool primitiveBranch = (strlen( brType->name() ) == 1);
1273  m_branches[ auxid ] =
1274  new TBranchHandle( kFALSE, ( strlen( brType->name() ) == 1 ),
1275  (primitiveBranch ?
1276  brType :
1277  m_vecs[ auxid ]->objType() ),
1278  ( m_structMode == kObjectStore ?
1279  m_vecs[ auxid ]->toPtr() :
1280  m_vecs[ auxid ]->toVector() ),
1281  auxid, &m_prefix );
1282  }
1283 
1284  // Construct a name for the branch:
1285  const TString brName =
1287 
1288  // If the output branch exists already, assume that it was us making
1289  // it:
1290  ::TBranch* br = m_outTree->GetBranch( brName );
1291  if( br ) {
1292  // Apparently a branch that was already set up for copying as a basic
1293  // variable, now got accessed explicitly. So let's update the output
1294  // branch to point to this new location now.
1295  br->SetAddress( m_branches[ auxid ]->outputObjectPtr() );
1296  // Update the cache. Notice that the "write status" of the typeless
1297  // auxiliary ID is not turned off. But it shouldn't matter, as the
1298  // variable will not be accessed in a typeless way anymore.
1299  m_branchesWritten[ auxid ] = true;
1300  // Return gracefully:
1301  return StatusCode::SUCCESS;
1302  }
1303 
1304  // Check that we know the type of the branch:
1305  const std::type_info* brType = m_branches[ auxid ]->typeInfo();
1306  if( ! brType ) {
1307  ::Error( "xAOD::TAuxStore::setupOutputData",
1308  XAOD_MESSAGE( "There's an internal logic error in the "
1309  "code" ) );
1310  return StatusCode::FAILURE;
1311  }
1312  const std::string brTypeName = Utils::getTypeName( *brType );
1313 
1314  // Decide if this is a primitive branch:
1315  const Bool_t primitiveBranch = ( strlen( brType->name() ) == 1 );
1316 
1317  // Let's create the branch now:
1318  if( primitiveBranch ) {
1319 
1320  // Get the "ROOT type" belonging to this primitive:
1321  const char rootType = Utils::rootType( brType->name()[ 0 ] );
1322  if( rootType == '\0' ) {
1323  ::Error( "xAOD::TAuxStore::setupOutputData",
1324  XAOD_MESSAGE( "Type not known for variable \"%s\" "
1325  "of type \"%s\"" ),
1326  brName.Data(), brTypeName.c_str() );
1327  return StatusCode::FAILURE;
1328  }
1329 
1330  // Construct the type description:
1331  std::ostringstream typeDesc;
1332  typeDesc << brName << "/" << rootType;
1333 
1334  // Create the branch:
1335  br = m_outTree->Branch( brName,
1336  m_branches[ auxid ]->outputObjectPtr(),
1337  typeDesc.str().c_str(), m_basketSize );
1338 
1339  } else {
1340 
1341  // Access the dictionary for the type:
1342  TClass* cl = TClass::GetClass( *brType );
1343  if( ! cl ) {
1344  cl = TClass::GetClass( brTypeName.c_str() );
1345  }
1346  if( ! cl ) {
1347  ::Error( "xAOD::TAuxStore::setupOutputData",
1348  XAOD_MESSAGE( "Couldn't find dictionary for type: %s" ),
1349  brTypeName.c_str() );
1350  return StatusCode::FAILURE;
1351  }
1352  if( ! cl->GetStreamerInfo() ) {
1353  ::Error( "xAOD::TAuxStore::setupOutputData",
1354  XAOD_MESSAGE( "No streamer info available for type %s" ),
1355  cl->GetName() );
1356  return StatusCode::FAILURE;
1357  }
1358 
1359  // Create the branch:
1360  br = m_outTree->Branch( brName, cl->GetName(),
1361  m_branches[ auxid ]->outputObjectPtr(),
1363  }
1364 
1365  // Check if we succeeded:
1366  if( ! br ) {
1367  ::Error( "xAOD::TAuxStore::setupOutputData",
1368  XAOD_MESSAGE( "Failed creating branch \"%s\" of type "
1369  "\"%s\"" ),
1370  brName.Data(), brTypeName.c_str() );
1371  return StatusCode::FAILURE;
1372  }
1373 
1374  // If this is not the first event, fill up the branch with dummy
1375  // info:
1376  for( Long64_t i = 0; i < m_outTree->GetEntries(); ++i ) {
1377  br->Fill();
1378  }
1379 
1380  // Update the cache:
1381  m_branchesWritten[ auxid ] = true;
1382 
1383  // Also, remember that we now handle this variable:
1384  m_auxIDs.insert( auxid );
1385 
1386  // We were successful:
1387  return StatusCode::SUCCESS;
1388  }
1389 
1406 
1407  // Check if an input tree is even available:
1408  if( ! m_inTree ) {
1409  // It's not an error if it isn't.
1410  return StatusCode::SUCCESS;
1411  }
1412 
1413  // Check if the input was already scanned:
1414  if( m_inputScanned ) {
1415  return StatusCode::SUCCESS;
1416  }
1417 
1418  // Get a list of all branches in the tree:
1419  TObjArray* branches = m_inTree->GetListOfBranches();
1420 
1421  // Check each of them:
1422  for( Int_t i = 0; i < branches->GetEntriesFast(); ++i ) {
1423 
1424  // The name of this top-level branch:
1425  const TString brName = branches->At( i )->GetName();
1426 
1427  // Access the branch pointer:
1428  TBranch* br = dynamic_cast< TBranch* >( branches->At( i ) );
1429  if( ! br ) {
1430  ::Fatal( "xAOD::TAuxStore::scanInputTree",
1431  XAOD_MESSAGE( "Logic error detected" ) );
1432  }
1433 
1434  // For top-level stores let's scan the static branches as well:
1435  if( m_topStore && ( brName == m_prefix ) ) {
1436 
1437  // Make sure the object has been instantiated so that aux data
1438  // registrations will have been done.
1439  br->SetAddress(0);
1440 
1441  // Get a list of its sub-branches:
1442  TObjArray* sbranches = br->GetListOfBranches();
1443 
1444  // ...and then loop over them:
1445  for( Int_t j = 0; j < sbranches->GetEntriesFast(); ++j ) {
1446 
1447  // The name of the sub-branch:
1448  const TString brName = sbranches->At( j )->GetName();
1449 
1450  // Try to make a variable name out of the branch name:
1451  const TString auxName = brName( brName.Index( "." ) + 1,
1452  brName.Length() );
1453 
1454  // Skip this entry if it refers to a base class:
1455  if( auxName.BeginsWith( "xAOD::" ) ||
1456  auxName.BeginsWith( "SG::" ) ||
1457  ( auxName == "ILockable" ) ) {
1458  continue;
1459  }
1460 
1461  // The sub-branch:
1462  ::TBranch* sbr =
1463  dynamic_cast< ::TBranch* >( sbranches->At( j ) );
1464  if( ! sbr ) {
1465  ::Fatal( "xAOD::TAuxStore::scanInputTree",
1466  XAOD_MESSAGE( "Logic error detected" ) );
1467  }
1468 
1469  // Leave the rest up to the function that is shared with the
1470  // dynamic branches:
1471  RETURN_CHECK( "xAOD::TAuxStore::scanInputTree",
1472  setupAuxBranch( sbr, auxName, kTRUE ) );
1473  }
1474 
1475  // Don't check the rest of the loop's body:
1476  continue;
1477  }
1478 
1479  // Check if it has the right prefix to be a dynamic variable:
1480  if( ! brName.BeginsWith( m_dynPrefix ) ) {
1481  continue;
1482  }
1483  // It's possible to create dynamic variables with an empty name
1484  // as well. Which is a bug. Such variables are just ignored
1485  // for now.
1486  if( brName == m_dynPrefix ) {
1487  ::Warning( "xAOD::TAuxStore::scanInputTree",
1488  "Dynamic branch with empty name found on container: %s",
1489  m_prefix.c_str() );
1490  continue;
1491  }
1492 
1493  // The auxiliary property name:
1494  const TString auxName = brName( brName.Index( "." ) + 1,
1495  brName.Length() );
1496 
1497  // Leave the rest up to the function that is shared with the
1498  // dynamic branches:
1499  RETURN_CHECK( "xAOD::TAuxStore::scanInputTree",
1500  setupAuxBranch( br, auxName, kFALSE ) );
1501  }
1502 
1503  // Okay, the input was successfully scanned:
1504  m_inputScanned = kTRUE;
1505 
1506  // Return gracefully:
1507  return StatusCode::SUCCESS;
1508  }
1509 
1511  const std::type_info*
1512  TAuxStore::auxBranchType( ::TBranch* br, const char* auxName,
1513  ::Bool_t staticBranch,
1514  std::string* expectedClassName ) {
1515 
1516  // Get the branch's type:
1517  ::TClass* expectedClass = 0;
1518  ::EDataType expectedType = kOther_t;
1519  if( br->GetExpectedType( expectedClass, expectedType ) &&
1520  ( ( ! staticBranch ) || ( strncmp( auxName, "m_", 2 ) != 0 ) ) ) {
1521  ::Warning( "xAOD::TAuxStore::setupAuxBranch",
1522  "Couldn't get the type of branch \"%s\"",
1523  br->GetName() );
1524  }
1525 
1526  // Check for schema evolution:
1527  // If a branch has automatic schema evolution from one class to another,
1528  // then what we get from GetExpectedType will be the on-disk class.
1529  // What we have in memory is given by GetCurrentClass.
1530  if (expectedClass) {
1531  if (TBranchElement* bre = dynamic_cast<TBranchElement*> (br)) {
1532  TClass* newClass = bre->GetCurrentClass();
1533  if (newClass && newClass != expectedClass) {
1534  expectedClass = newClass;
1535  }
1536  }
1537  if (expectedClassName) {
1538  *expectedClassName = expectedClass->GetName();
1539  }
1540  }
1541 
1542  // If this is a primitive variable, and we're still not sure whether this
1543  // is a store for an object or a container, the answer is given...
1544  if( ( ! expectedClass ) &&
1545  ( m_structMode == kUndefinedStore ) ) {
1547  }
1548 
1549  // Get the type_info of the branch:
1550  const std::type_info* ti = 0;
1551  if( m_structMode == kObjectStore ) {
1552  if( expectedClass ) {
1553  ti = expectedClass->GetTypeInfo();
1554  } else {
1555  ti = &( Utils::getTypeInfo( expectedType ) );
1556  }
1557  } else {
1558  if( ! expectedClass ) {
1559  if( ( ! staticBranch ) || ( strncmp( auxName, "m_", 2 ) != 0 ) ) {
1560  ::Warning( "xAOD::TAuxStore::setupAuxBranch",
1561  "Couldn't get the type of branch \"%s\"",
1562  br->GetName() );
1563  }
1564  } else {
1565  ::TVirtualCollectionProxy* prox =
1566  expectedClass->GetCollectionProxy();
1567 
1568  if (!prox) {
1569  TClass* cl2 = lookupVectorType (expectedClass);
1570  if (cl2)
1571  prox = cl2->GetCollectionProxy();
1572  }
1573 
1574  if( ! prox ) {
1575  if( ( ! staticBranch ) ||
1576  ( strncmp( auxName, "m_", 2 ) != 0 ) ) {
1577  ::Warning( "xAOD::TAuxStore::setupAuxBranch",
1578  "Couldn't get the type of branch \"%s\"",
1579  br->GetName() );
1580  }
1581  } else {
1582  if( prox->GetValueClass() ) {
1583  ti = prox->GetValueClass()->GetTypeInfo();
1584  } else {
1585  ti = &( Utils::getTypeInfo( prox->GetType() ) );
1586  }
1587  }
1588  }
1589  }
1590 
1591  return ti;
1592  }
1593 
1609  StatusCode TAuxStore::setupAuxBranch( ::TBranch* br, const char* auxName,
1610  ::Bool_t staticBranch ) {
1611 
1612  std::string expectedClassName;
1613  const std::type_info* ti = auxBranchType( br, auxName, staticBranch,
1614  &expectedClassName );
1615 
1616  // Get the registry:
1618 
1619  // Check if the registry already knows this variable name. If yes, let's
1620  // use the type known by the registry. To be able to deal with simple
1621  // schema evolution in dynamic branches.
1622  const auxid_t regAuxid = registry.findAuxID( auxName );
1623  if( regAuxid != SG::null_auxid ) {
1624  m_auxIDs.insert( regAuxid );
1625  return StatusCode::SUCCESS;
1626  }
1627 
1628  // If we didn't find a type_info for the branch, give up now...
1629  if( ! ti ) {
1630  return StatusCode::SUCCESS;
1631  }
1632 
1634  SG::auxid_t linked_auxid = SG::null_auxid;
1635 
1636  if ( SG::AuxTypeRegistry::isLinkedName( auxName ) ) {
1638  }
1639  else if ( SG::AuxTypeRegistry::classNameHasLink( expectedClassName) ) {
1640  std::string linkedAttr = SG::AuxTypeRegistry::linkedName( auxName );
1641  std::string linkedBranch = SG::AuxTypeRegistry::linkedName( br->GetName() );
1642  ::TBranch* lbr = m_inTree->GetBranch( linkedBranch.c_str() );
1643  const std::type_info* lti = nullptr;
1644  if (lbr) {
1645  lti = auxBranchType( lbr, linkedAttr.c_str(), staticBranch );
1646  }
1647  if (lti) {
1648  linked_auxid = registry.getAuxID( *lti, linkedAttr, "",
1651  }
1652  if (linked_auxid == SG::null_auxid) {
1653  ::Error( "xAOD::TAuxStore::setupAuxBranch",
1654  "Could not find linked variable for %s type %s",
1655  auxName, expectedClassName.c_str() );
1656  }
1657  }
1658 
1659  // Check for an auxiliary ID for this branch:
1660  auxid_t auxid = registry.getAuxID( *ti, auxName, "",
1661  flags, linked_auxid );
1662 
1663  // First try to find a compiled factory for the vector type:
1664  if( auxid == SG::null_auxid ) {
1665 
1666  // Construct the name of the factory's class:
1667  // But be careful --- if we don't exactly match the name
1668  // in TClassTable, then we may trigger autoparsing. Besides the
1669  // resource usage that implies, that can lead to crashes in dbg
1670  // builds due to cling bugs.
1671  std::string tn = Utils::getTypeName( *ti );
1672  if (tn.starts_with("std::vector<"))
1673  tn.erase (0, 5);
1674  std::string fac_class_name = "SG::AuxTypeVectorFactory<" +
1675  tn + ",allocator<" + tn;
1676  if( fac_class_name[ fac_class_name.size() - 1 ] == '>' ) {
1677  fac_class_name += ' ';
1678  }
1679  fac_class_name += "> >";
1680 
1681  // Look for the dictionary of this type:
1682  ::TClass* fac_class = TClass::GetClass( fac_class_name.c_str() );
1683  if( fac_class && fac_class->IsLoaded() ) {
1684  ::TClass* base_class =
1685  ::TClass::GetClass( "SG::IAuxTypeVectorFactory" );
1686  if( base_class && base_class->IsLoaded() ) {
1687  const Int_t offs = fac_class->GetBaseClassOffset( base_class );
1688  if( offs >= 0 ) {
1689  void* fac_vp = fac_class->New();
1690  if( fac_vp ) {
1691  unsigned long tmp =
1692  reinterpret_cast< unsigned long >( fac_vp ) + offs;
1694  reinterpret_cast< SG::IAuxTypeVectorFactory* >( tmp );
1695  registry.addFactory( *ti, *fac->tiAlloc(), std::unique_ptr<SG::IAuxTypeVectorFactory>( fac ) );
1696  auxid = registry.getAuxID( *ti, auxName, "",
1697  flags, linked_auxid );
1698  }
1699  }
1700  }
1701  }
1702  }
1703 
1704  // If that didn't succeed, let's assign a generic factory to this type:
1705  if( auxid == SG::null_auxid && linked_auxid == SG::null_auxid ) {
1706 
1707  // Construct the name of the vector type:
1708  std::string vec_class_name = "std::vector<" +
1709  Utils::getTypeName( *ti );
1710  if( vec_class_name[ vec_class_name.size() - 1 ] == '>' ) {
1711  vec_class_name += ' ';
1712  }
1713  vec_class_name += '>';
1714 
1715  // Get the dictionary for the type:
1716  ::TClass* vec_class = ::TClass::GetClass( vec_class_name.c_str() );
1717  if( vec_class && vec_class->IsLoaded() ) {
1718  auto fac = std::make_unique<TAuxVectorFactory>( vec_class );
1719  if (fac->tiAlloc()) {
1720  const std::type_info* tiAlloc = fac->tiAlloc();
1721  registry.addFactory( *ti, *tiAlloc, std::move( fac ) );
1722  }
1723  else {
1724  std::string tiAllocName = fac->tiAllocName();
1725  registry.addFactory( *ti, tiAllocName, std::move( fac ) );
1726  }
1727  auxid = registry.getAuxID( *ti, auxName, "",
1729  } else {
1730  ::Warning( "xAOD::TAuxStore::setupAuxBranch",
1731  "Couldn't find dictionary for type: %s",
1732  vec_class_name.c_str() );
1733  }
1734  }
1735 
1736  // Check if we succeeded:
1737  if( auxid == SG::null_auxid ) {
1738  if ( linked_auxid != SG::null_auxid ) {
1739  ::Error( "xAOD::TAuxStore::setupAuxBranch",
1740  XAOD_MESSAGE( "Dynamic ROOT vector factory not implemented for linked types; branch "
1741  "\"%s\"" ),
1742  br->GetName() );
1743  }
1744  else {
1745  ::Error( "xAOD::TAuxStore::setupAuxBranch",
1746  XAOD_MESSAGE( "Couldn't assign auxiliary ID to branch "
1747  "\"%s\"" ),
1748  br->GetName() );
1749  }
1750  return StatusCode::FAILURE;
1751  }
1752 
1753  // Remember the auxiliary ID:
1754  m_auxIDs.insert( auxid );
1755  return StatusCode::SUCCESS;
1756  }
1757 
1766  ::Bool_t TAuxStore::isAuxIDSelected( auxid_t auxid ) const {
1767 
1768  // A temporary object:
1769  auxid_set_t auxids; auxids.insert( auxid );
1770 
1771  // Check if the auxid is returned as a selected ID:
1772  return m_selection.getSelectedAuxIDs( auxids ).size();
1773  }
1774 
1783  ::Bool_t TAuxStore::isPrimitiveBranch( ::TBranch* br ) {
1784 
1785  // The variables needed for the check:
1786  ::TClass* cl = 0;
1787  ::EDataType dType = kOther_t;
1788 
1789  // Get the variable type from the branch:
1790  if( br->GetExpectedType( cl, dType ) ) {
1791  ::Error( "xAOD::TAuxStore::isPrimitiveBranch",
1792  XAOD_MESSAGE( "Couldn't determine the type of branch "
1793  "\"%s\"" ), br->GetName() );
1794  return kFALSE;
1795  }
1796 
1797  // The check is made using the data type variable:
1798  return ( ( dType != kOther_t ) && ( dType != kNoType_t ) &&
1799  ( dType != kVoid_t ) );
1800  }
1801 
1817  ::Bool_t TAuxStore::isContainerBranch( ::TBranch* br, auxid_t auxid ) {
1818 
1819  // For unknown types it doesn't matter if the branch describes a
1820  // container or a single element.
1821  if( ! isRegisteredType( auxid ) ) return kTRUE;
1822 
1823  // The variables needed for the check:
1824  ::TClass* cl = 0;
1825  ::EDataType dType = kOther_t;
1826 
1827  // Get the variable type from the branch:
1828  if( br->GetExpectedType( cl, dType ) ) {
1829  ::Error( "xAOD::TAuxStore::isContainerBranch",
1830  XAOD_MESSAGE( "Couldn't determine the type of branch "
1831  "\"%s\"" ), br->GetName() );
1832  return kFALSE;
1833  }
1834 
1835  // If there is no class associated with the branch then it should be
1836  // a branch describing a standalone object. (As it should be a
1837  // "primitive" branch in this case.)
1838  if( ! cl ) {
1839  return kFALSE;
1840  }
1841 
1842  // If there is a class, ask for the type_info of its type:
1843  const std::type_info* root_ti = cl->GetTypeInfo();
1844  if( ! root_ti ) {
1845  // This may be an emulated class. One known case is when the type name
1846  // is saved as "basic_string<char>" rather than "string" by Athena I/O.
1847  // (It's not fully understood why this happens for dynamic branches...)
1848  // So, let's see if we can get a functional TClass by massaging the
1849  // type name a bit.
1850  ::TString typeName( cl->GetName() );
1851  typeName.ReplaceAll( "basic_string<char>", "string" );
1852  ::TClass* newCl = ::TClass::GetClass( typeName );
1853  if( newCl ) {
1854  root_ti = newCl->GetTypeInfo();
1855  }
1856  }
1857  if( ! root_ti ) {
1858  ::Error( "xAOD::TAuxStore::isContainerBranch",
1859  XAOD_MESSAGE( "Couldn't get an std::type_info object out of "
1860  "branch \"%s\" of type \"%s\"" ),
1861  br->GetName(), cl->GetName() );
1862  return kFALSE;
1863  }
1864 
1865  // Ask for the auxiliary type infos:
1866  const std::type_info* aux_obj_ti =
1868  if( ! aux_obj_ti ) {
1869  ::Error( "xAOD::TAuxStore::isContainerBranch",
1870  XAOD_MESSAGE( "Couldn't get std::type_info object for "
1871  "auxiliary id: %i" ),
1872  static_cast< int >( auxid ) );
1873  return kFALSE;
1874  }
1875  const std::type_info* aux_vec_ti =
1877  if( ! aux_vec_ti ) {
1878  ::Error( "xAOD::TAuxStore::isContainerBranch",
1879  XAOD_MESSAGE( "Couldn't get std::type_info object for "
1880  "auxiliary id: %i" ),
1881  static_cast< int >( auxid ) );
1882  return kFALSE;
1883  }
1884 
1885  // Check which one the ROOT type info agrees with:
1886  if( *root_ti == *aux_obj_ti ) {
1887  // This branch describes a single object:
1888  return kFALSE;
1889  } else if( *root_ti == *aux_vec_ti ) {
1890  // This branch describes a container of objects:
1891  return kTRUE;
1892  }
1893 
1894  // For enum and vector<enum> types (PFO...) the type given by
1895  // the aux type registry is vector<int>. We have to take it into account
1896  // here...
1897  if( cl->GetCollectionProxy() &&
1898  ( *aux_vec_ti == typeid( std::vector< int > ) ) ) {
1899  return kTRUE;
1900  }
1901 
1902  TClass* cl2 = lookupVectorType (cl);
1903  if (cl2) {
1904  if (*cl2->GetTypeInfo() == *aux_vec_ti)
1905  return kTRUE;
1906  }
1907 
1908  // If we got this far, the branch may have undergone schema evolution. If
1909  // it's one that ROOT can deal with itself, then we should still be able
1910  // to read the branch with this code.
1911  //
1912  // Note that even after looking at the ROOT source code, I'm still not
1913  // 100% sure whether we would need to delete the objects returned by
1914  // TClass::GetConversionStreamerInfo(...) in this code. :-( But based on
1915  // general experience with the ROOT code, I'm going to say no...
1916  TClass* aux_vec_cl =
1917  TClass::GetClass( Utils::getTypeName( *aux_vec_ti ).c_str() );
1918  if( aux_vec_cl && aux_vec_cl->GetConversionStreamerInfo( cl, cl->GetClassVersion() ) ) {
1919  return kTRUE;
1920  }
1921  TClass* aux_obj_cl =
1922  TClass::GetClass( Utils::getTypeName( *aux_obj_ti ).c_str() );
1923  if( aux_obj_cl && aux_obj_cl->GetConversionStreamerInfo( cl, cl->GetClassVersion() ) ) {
1924  return kFALSE;
1925  }
1926 
1927  // If neither, then something went wrong...
1928  ::Error( "xAOD::TAuxStore::isContainerBranch",
1929  XAOD_MESSAGE( "Couldn't determine if branch describes a single "
1930  "object or a container" ) );
1931  ::Error( "xAOD::TAuxStore::isContainerBranch",
1932  XAOD_MESSAGE( "ROOT type : %s" ),
1933  Utils::getTypeName( *root_ti ).c_str() );
1934  ::Error( "xAOD::TAuxStore::isContainerBranch",
1935  XAOD_MESSAGE( "Object type: %s" ),
1936  Utils::getTypeName( *aux_obj_ti ).c_str() );
1937  ::Error( "xAOD::TAuxStore::isContainerBranch",
1938  XAOD_MESSAGE( "Vector type: %s" ),
1939  Utils::getTypeName( *aux_vec_ti ).c_str() );
1940  return kFALSE;
1941  }
1942 
1950 
1951  // Cache some data:
1954  static const auxid_t sauxid =
1955  registry.getAuxID< SG::AuxTypePlaceholder >( "AuxTypePlaceholder" );
1956  static const std::type_info* const sti = registry.getVecType( sauxid );
1957 
1958  // Check if the types match:
1959  return ( *sti != *( registry.getVecType( auxid ) ) );
1960  }
1961 
1963  ::Bool_t primitiveBranch,
1964  const std::type_info* ti,
1965  void* obj, SG::auxid_t auxid,
1966  const std::string* prefix )
1967  : m_branch( 0 ), m_entry( 0 ) , m_object( obj ), m_static( staticBranch ),
1968  m_primitive( primitiveBranch ),
1969  m_typeInfo( ti ), m_needsRead( kTRUE ), m_auxid( auxid ),
1970  m_prefix( prefix ) {
1971  }
1972 
1977  //
1979 
1980  // A little sanity check:
1981  if( ! m_branch ) {
1982  // This is no longer an error. We can have such objects for
1983  // decorations, which don't exist on the input.
1984  return 0;
1985  }
1986 
1987  // Update the I/O monitoring:
1988  IOStats::instance().stats().readBranch( *m_prefix, m_auxid );
1989 
1990  // Make sure that the branch is associated to a tree
1991  // as the entry to be read is retrieved from the tree
1992  if (!m_branch->GetTree()){
1993  Error("xAOD::TAuxStore::TBranchHandle::getEntry",
1994  XAOD_MESSAGE("Branch=%s is not associated to any tree while reading of branches within this class relies on that"),
1995  m_branch->GetName());
1996  return -1;
1997  }
1998 
1999  // Get the entry that should be read
2000  // The entry to be read is set with TTree::LoadTree()
2001  // NB: for a branch from a friend tree and if the friend tree has an index built,
2002  // then the entry to read is found when calling the TTree::LoadTree() function
2003  // that matches the major and minor values between the main tree and the friend tree
2004  ::Long64_t entry = m_branch->GetTree()->GetReadEntry();
2005 
2006  if ( entry < 0 ){
2007  // Raise error as it implies
2008  // either that the TTree::LoadTree() function has not been called
2009  // or
2010  // the entry requested to be read by the user
2011  // is not corresponding to any entry for the friend tree
2012  Error("xAOD::TAuxStore::TBranchHandle::getEntry",
2013  XAOD_MESSAGE( "Entry to read is not set for branch=%s from tree=%s. "
2014  "It is either because TTree::LoadTree(entry) was not called "
2015  "beforehand in the TEvent class OR "
2016  "the entry requested to be read for the main tree is not corresponding to an event for the friend tree"),
2017  m_branch->GetName(),
2018  m_branch->GetTree()->GetName());
2019  return -1;
2020  }
2021 
2022  // Check if anything needs to be done:
2023  if( ( entry == m_entry ) && ( ! m_needsRead ) ) {
2024  return 0;
2025  }
2026 
2027  // Switch the branch in the right mode:
2028  if( ! m_primitive ) {
2029  if( ( m_branch->GetMakeClass() != m_static ) &&
2030  ( ! m_branch->SetMakeClass( m_static ) ) ) {
2031  ::Error( "xAOD::TAuxStore::TBranchHandle::getEntry",
2032  XAOD_MESSAGE( "Failed to call SetMakeClass(%i) on "
2033  "branch \"%s\"" ),
2034  static_cast< int >( m_static ), m_branch->GetName() );
2035  return -1;
2036  }
2037  }
2038 
2039  // Load the entry.
2040  const ::Int_t nbytes = m_branch->GetEntry( entry );
2041 
2042  // If the load was successful, remember that we loaded this entry.
2043  if( nbytes >= 0 ) {
2044  m_entry = entry;
2045  // The reading will now be done:
2046  m_needsRead = kFALSE;
2047  }
2048 
2049  // Return the number of bytes read.
2050  return nbytes;
2051  }
2052 
2060  return &m_branch;
2061  }
2062 
2070 
2071  return m_object;
2072  }
2073 
2090 
2091  // Return the correct pointer:
2092  if( m_static || m_primitive ) {
2093  return m_object;
2094  } else {
2095  return &m_object;
2096  }
2097  }
2098 
2109 
2110  // Return the correct pointer:
2111  if( m_primitive ) {
2112  return m_object;
2113  } else {
2114  return &m_object;
2115  }
2116  }
2117 
2118  const std::type_info* TAuxStore::TBranchHandle::typeInfo() const {
2119 
2120  return m_typeInfo;
2121  }
2122 
2135 
2136  m_needsRead = kTRUE;
2137  return;
2138  }
2139 
2140 } // 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:1111
SG::AuxStoreInternal::reserve
virtual void reserve(size_t sz) override
Change the capacity of all aux data vectors.
Definition: AuxStoreInternal.cxx:267
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
python.Dso.registry
registry
Definition: Control/AthenaServices/python/Dso.py:159
xAOD::TAuxStore::setTopStore
void setTopStore(Bool_t value=kTRUE)
Set whether the object should behave as a "top store" or not.
Definition: TAuxStore.cxx:133
SG::IAuxTypeVector::shift
virtual bool shift(size_t pos, ptrdiff_t offs)=0
Shift the elements of the vector.
SG::IAuxTypeVector::isLinked
bool isLinked() const
Return true if this variable is linked from another one.
Definition: IAuxTypeVector.h:226
beamspotman.r
def r
Definition: beamspotman.py:676
xAOD::TAuxStore::m_missingBranches
std::vector< bool > m_missingBranches
Mark branches we've found to be missing.
Definition: TAuxStore.h:318
xAOD::TAuxStore::getSelectedAuxIDs
virtual auxid_set_t getSelectedAuxIDs() const override
Get the IDs of the selected aux variables.
Definition: TAuxStore.cxx:854
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::TBranchHandle::typeInfo
const std::type_info * typeInfo() const
Get the type of the variable in memory.
Definition: TAuxStore.cxx:2118
xAOD::TAuxStore::getAuxIDs
virtual const auxid_set_t & getAuxIDs() const override
Get the types(names) of variables handled by this container.
Definition: TAuxStore.cxx:333
xAOD::TAuxStore::TBranchHandle::reset
void reset()
Tell the object that the branch contents need to be re-read.
Definition: TAuxStore.cxx:2134
xAOD::TAuxStore::isDecoration
virtual bool isDecoration(auxid_t auxid) const override
Test if a variable is a decoration.
Definition: TAuxStore.cxx:420
xAOD::TAuxStore::basketSize
Int_t basketSize() const
Get the size of the baskets created for the output branches.
Definition: TAuxStore.cxx:140
checkxAOD.brName
brName
Definition: Tools/PyUtils/bin/checkxAOD.py:114
get_generator_info.result
result
Definition: get_generator_info.py:21
xAOD::TAuxStore::readFrom
StatusCode readFrom(::TTree *tree, ::Bool_t printWarnings=kTRUE)
Connect the object to an input TTree.
Definition: TAuxStore.cxx:167
SG::AuxStoreInternal::getDecoration
virtual void * getDecoration(auxid_t auxid, size_t size, size_t capacity) override
Return the data vector for one aux data decoration item.
Definition: AuxStoreInternal.cxx:198
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
SG::SkipNameCheck
@ SkipNameCheck
Definition: AuxTypes.h:81
xAOD::IOStats::stats
ReadStats & stats()
Access the object belonging to the current thread.
Definition: IOStats.cxx:17
SG::AuxStoreInternal::getData
virtual const void * getData(SG::auxid_t auxid) const override
Return the data vector for one aux data item.
Definition: AuxStoreInternal.cxx:83
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:640
AuxVectorInterface.h
Make an AuxVectorData object from either a raw vector or an aux store.
AthenaPoolTestRead.flags
flags
Definition: AthenaPoolTestRead.py:8
xAOD::TAuxStore::m_isDecoration
std::vector< ::Bool_t > m_isDecoration
Flags items as decorations.
Definition: TAuxStore.h:253
xAOD::TAuxStore::m_prefix
std::string m_prefix
Static prefix for the branch names.
Definition: TAuxStore.h:215
SG::AuxTypeRegistry::getName
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
Definition: AuxTypeRegistry.cxx:882
SG::ExcStoreLocked
Exception — Attempted to modify auxiliary data in a locked store.
Definition: Control/AthContainers/AthContainers/exceptions.h:183
tree
TChain * tree
Definition: tile_monitor.h:30
xAOD::TAuxStore::isTopStore
Bool_t isTopStore() const
Check if the object is a "top store", or not.
Definition: TAuxStore.cxx:128
exceptions.h
Exceptions that can be thrown from AthContainers.
xAOD::TAuxStore::m_splitLevel
::Int_t m_splitLevel
The split level for the output branches.
Definition: TAuxStore.h:227
as_const_ptr.h
Helper for getting a const version of a pointer.
xAOD::TAuxStore::m_auxIDs
auxid_set_t m_auxIDs
Internal list of variable IDs handled currently by the object.
Definition: TAuxStore.h:243
xAOD::TAuxStore::setBasketSize
void setBasketSize(Int_t value)
Set the size of the baskets created for the output branches.
Definition: TAuxStore.cxx:145
xAOD::TAuxStore::resize
virtual bool resize(size_t size) override
Resize the arrays to a given size.
Definition: TAuxStore.cxx:611
xAOD::other
@ other
Definition: TrackingPrimitives.h:509
xAOD::TAuxStore::setStructMode
StatusCode setStructMode(EStructMode mode)
Set the structure mode of the object to a new value.
Definition: TAuxStore.cxx:100
xAOD::TAuxStore
"ROOT implementation" of IAuxStore
Definition: TAuxStore.h:46
athena.value
value
Definition: athena.py:124
SG::IAuxTypeVector::insertMove
virtual bool insertMove(size_t pos, void *src, size_t src_pos, size_t src_n, IAuxStore &srcStore)=0
Insert elements into the vector via move semantics.
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
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:1303
XAOD_MESSAGE
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Definition: Control/xAODRootAccess/xAODRootAccess/tools/Message.h:19
Utils.h
xAOD::TAuxStore::EStructMode
EStructMode
"Structural" modes of the object
Definition: TAuxStore.h:53
xAOD::TAuxStore::m_basketSize
::Int_t m_basketSize
The basket size for the output branches.
Definition: TAuxStore.h:225
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:1313
trigbs_dumpHLTContentInBS.stats
stats
Definition: trigbs_dumpHLTContentInBS.py:91
xAOD::TAuxStore::m_locked
::Bool_t m_locked
Is this container locked?
Definition: TAuxStore.h:251
ReturnCheck.h
CxxUtils::ConcurrentBitset::clear
ConcurrentBitset & clear()
Clear all bits in the set.
xAOD::TAuxStore::scanInputTree
StatusCode scanInputTree()
Scan the input TTree for auxiliary branches.
Definition: TAuxStore.cxx:1405
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
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
xAOD::TAuxStore::getVector
virtual const SG::IAuxTypeVector * getVector(SG::auxid_t auxid) const override
Return vector interface for one aux data item.
Definition: TAuxStore.cxx:298
SG::AuxStoreInternal::getAuxIDs
virtual const SG::auxid_set_t & getAuxIDs() const override
Return a set of identifiers for existing data items in this store.
Definition: AuxStoreInternal.cxx:400
SG::AuxTypeRegistry
Handle mappings between names and auxid_t.
Definition: AuxTypeRegistry.h:61
xAOD::TAuxStore::m_inTree
::TTree * m_inTree
The TTree being read from.
Definition: TAuxStore.h:230
xAOD::TAuxStore::m_dynPrefix
std::string m_dynPrefix
Dynamic prefix for the branch names.
Definition: TAuxStore.h:217
xAOD::TAuxStore::insertMove
virtual bool insertMove(size_t pos, IAuxStore &other, const SG::auxid_set_t &ignore) override
Insert contents of another store via move.
Definition: TAuxStore.cxx:702
xAOD::TAuxStore::guard_t
AthContainers_detail::lock_guard< mutex_t > guard_t
Guard type for multithreaded synchronisation.
Definition: TAuxStore.h:258
xAOD::TAuxStore::reset
void reset()
Tell the object that all branches will need to be re-read.
Definition: TAuxStore.cxx:274
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
runLayerRecalibration.branches
list branches
Definition: runLayerRecalibration.py:98
DiTauMassTools::ignore
void ignore(T &&)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:58
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:909
H5Utils::internal::packed
H5::CompType packed(H5::CompType in)
Definition: common.cxx:16
xAOD::TAuxStore::auxBranchType
const std::type_info * auxBranchType(::TBranch *br, const char *auxName, ::Bool_t staticBranch, std::string *expectedClassName=nullptr)
Find the type_info to use as the aux type for a given branch.
Definition: TAuxStore.cxx:1512
xAOD::TAuxStore::lock
virtual void lock() override
Lock the object, and don't let decorations be added.
Definition: TAuxStore.cxx:434
CxxUtils::ConcurrentBitset::size
bit_t size() const
Count the number of 1 bits in the set.
xAOD::TAuxStore::m_outTree
::TTree * m_outTree
The TTree being written to.
Definition: TAuxStore.h:232
ReadStats.h
TAuxStore.h
xAOD::TAuxStore::getWritableAuxIDs
virtual const auxid_set_t & getWritableAuxIDs() const override
Return a set of writable data identifiers.
Definition: TAuxStore.cxx:606
xAOD::TAuxStore::isRegisteredType
::Bool_t isRegisteredType(auxid_t auxid)
Check if the auxiliary variable has a registered type.
Definition: TAuxStore.cxx:1949
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:285
lumiFormat.i
int i
Definition: lumiFormat.py:85
xAOD::TAuxStore::getDecorIDs
virtual const auxid_set_t & getDecorIDs() const override
Get the types(names) of decorations handled by this container.
Definition: TAuxStore.cxx:338
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(bit_t bit, bit_t new_nbits=0)
Set a bit to 1.
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Message.h
SG::AuxStoreInternal::clearDecorations
virtual bool clearDecorations() override
Clear all decorations.
Definition: AuxStoreInternal.cxx:581
xAOD::TAuxStore::getIOType
virtual const std::type_info * getIOType(auxid_t auxid) const override
Return the type of the data to be stored for one aux data item.
Definition: TAuxStore.cxx:801
SG::IAuxTypeVectorFactory
Interface for factory objects that create vectors.
Definition: IAuxTypeVectorFactory.h:50
xAOD::TAuxStore::kObjectStore
@ kObjectStore
The object describes a single object.
Definition: TAuxStore.h:56
xAOD::TAuxStore::writeTo
StatusCode writeTo(::TTree *tree)
Connect the object to an output TTree.
Definition: TAuxStore.cxx:209
xAOD::TAuxStore::isAuxIDSelected
::Bool_t isAuxIDSelected(auxid_t auxid) const
Check if this auxiliary variable needs to go to the output.
Definition: TAuxStore.cxx:1766
SG::AuxStoreInternal::lock
virtual void lock() override
Lock the container.
Definition: AuxStoreInternal.cxx:564
SG::AuxStoreInternal::lockDecoration
virtual void lockDecoration(SG::auxid_t auxid) override
Lock a decoration.
Definition: AuxStoreInternal.cxx:753
SG::IAuxTypeVectorFactory::tiAlloc
virtual const std::type_info * tiAlloc() const =0
Return the type_info of the vector allocator.
xAOD::TAuxStore::reserve
virtual void reserve(size_t size) override
Reserve a given size for the arrays.
Definition: TAuxStore.cxx:642
xAOD::TAuxStore::isContainerBranch
::Bool_t isContainerBranch(TBranch *br, auxid_t auxid)
Check if a branch describes a container or a single object.
Definition: TAuxStore.cxx:1817
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
xAOD::TAuxStore::m_mutex1
mutex_t m_mutex1
Mutexes object used for multithreaded synchronisation.
Definition: TAuxStore.h:260
xAOD::TAuxStore::m_mutex2
mutex_t m_mutex2
Definition: TAuxStore.h:260
xAOD::TAuxStore::splitLevel
Int_t splitLevel() const
Get the split level of the output branches.
Definition: TAuxStore.cxx:151
SG::AuxStoreInternal::shift
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the elements of the container.
Definition: AuxStoreInternal.cxx:301
SG::AuxTypePlaceholder
Used as type_info when we read an aux data item but it doesn't exist in the registry.
Definition: AuxTypes.h:34
xAOD::TAuxStore::shift
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the contents of the stored arrays.
Definition: TAuxStore.cxx:668
Preparation.mode
mode
Definition: Preparation.py:94
SG::AuxStoreInternal::insertMove
virtual bool insertMove(size_t pos, IAuxStore &other, const SG::auxid_set_t &ignore=SG::auxid_set_t(0)) override
Move all elements from other to this store.
Definition: AuxStoreInternal.cxx:332
SG::AuxTypeRegistry::isLinkedName
static bool isLinkedName(const std::string &name)
Test if a variable name corresponds to a linked variable.
Definition: AuxTypeRegistry.cxx:1293
xAOD::TAuxStore::m_decorIDs
auxid_set_t m_decorIDs
Definition: TAuxStore.h:244
xAOD::TAuxStore::m_transientStore
SG::AuxStoreInternal * m_transientStore
Store for the in-memory-only variables.
Definition: TAuxStore.h:240
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:937
SG::AuxStoreInternal::getIOType
virtual const std::type_info * getIOType(SG::auxid_t auxid) const override
Return the type of the data to be stored for one aux data item.
Definition: AuxStoreInternal.cxx:532
SG::AuxStoreInternal::size
virtual size_t size() const override
Return the number of elements in the store.
Definition: AuxStoreInternal.cxx:602
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
xAOD::IOStats::instance
static IOStats & instance()
Singleton object accessor.
Definition: IOStats.cxx:11
xAOD::TAuxStore::getData
virtual const void * getData(auxid_t auxid) const override
Get a pointer to a given array.
Definition: TAuxStore.cxx:289
xAOD::TAuxStore::getEntry
Int_t getEntry(Int_t getall=0)
Read the values from the TTree entry that was loaded with TTree::LoadTree()
Definition: TAuxStore.cxx:228
SG::AuxVarFlags
AuxVarFlags
Additional flags to qualify an auxiliary variable.
Definition: AuxTypes.h:58
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
SG::AuxStoreInternal::linkedVector
virtual IAuxTypeVector * linkedVector(SG::auxid_t auxid) override
Return interface for a linked variable.
Definition: AuxStoreInternal.cxx:769
xAOD::TAuxStore::initStats
StatusCode initStats(::TTree *tree)
Function used for setting up the statistics info about the managed branches.
Definition: TAuxStore.cxx:871
SG::AuxStoreInternal::getIOData
virtual const void * getIOData(SG::auxid_t auxid) const override
Return a pointer to the data to be stored for one aux data item.
Definition: AuxStoreInternal.cxx:515
xAOD::TAuxStore::kContainerStore
@ kContainerStore
The object describes an entire container.
Definition: TAuxStore.h:55
xAOD::TAuxStore::m_structMode
EStructMode m_structMode
The "structural" mode of the object.
Definition: TAuxStore.h:223
xAOD::TAuxStore::getDecoration
virtual void * getDecoration(auxid_t auxid, size_t size, size_t capacity) override
Get a pointer to a given array, creating the array if necessary.
Definition: TAuxStore.cxx:343
xAOD::TAuxStore::m_vecs
std::vector< SG::IAuxTypeVector * > m_vecs
Variables handled currently by the object.
Definition: TAuxStore.h:246
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
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:818
xAOD::TAuxStore::getDynamicAuxIDs
virtual const auxid_set_t & getDynamicAuxIDs() const override
Get the types(names) of variables created dynamically.
Definition: TAuxStore.cxx:838
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:220
CxxUtils::as_const_ptr
const T * as_const_ptr(const T *p)
Helper for getting a const version of a pointer.
Definition: as_const_ptr.h:32
xAOD::TAuxStore::m_inputScanned
::Bool_t m_inputScanned
"Scan status" of the input TTree
Definition: TAuxStore.h:235
xAOD::TAuxStore::TBranchHandle::inputObjectPtr
void * inputObjectPtr()
Get a pointer to the object (or its pointer) in memory for reading.
Definition: TAuxStore.cxx:2089
xAOD::ReadStats::readBranch
void readBranch(const std::string &prefix, SG::auxid_t auxid)
Function incrementing the read counter on a specific branch.
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
xAOD::TAuxStore::setSplitLevel
void setSplitLevel(Int_t value)
Set the split level of the output branches.
Definition: TAuxStore.cxx:156
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:169
SG::AuxStoreInternal
An auxiliary data store that holds data internally.
Definition: AuxStoreInternal.h:43
xAOD::TAuxStore::lockDecoration
virtual void lockDecoration(SG::auxid_t auxid) override
Lock a decoration.
Definition: TAuxStore.cxx:477
python.PyAthena.v
v
Definition: PyAthena.py:154
SG::AuxVectorInterface
Make an AuxVectorData object from either a raw array or an aux store.
Definition: AuxVectorInterface.h:33
xAOD::TAuxStore::m_topStore
::Bool_t m_topStore
Flag stating whether this is a "top store".
Definition: TAuxStore.h:220
xAOD::TAuxStore::kUndefinedStore
@ kUndefinedStore
The structure mode is not defined.
Definition: TAuxStore.h:54
xAOD::TAuxStore::selectAux
virtual void selectAux(const std::set< std::string > &attributes)
Select dynamic auxiliary attributes for writing.
Definition: TAuxStore.cxx:845
xAOD::TAuxStore::auxid_t
SG::auxid_t auxid_t
Convenience type declaration.
Definition: TAuxStore.h:59
SG::AuxStoreInternal::getVector
virtual const IAuxTypeVector * getVector(SG::auxid_t auxid) const override
Return vector interface for one aux data item.
Definition: AuxStoreInternal.cxx:99
xAOD::TAuxStore::TBranchHandle::objectPtr
void * objectPtr()
Get a pointer to the object.
Definition: TAuxStore.cxx:2069
xAOD::TAuxStore::TBranchHandle::getEntry
::Int_t getEntry()
Get entry from the branch that was loaded with TTree::LoadTree()
Definition: TAuxStore.cxx:1978
SG::AuxStoreInternal::isDecoration
virtual bool isDecoration(auxid_t auxid) const override
Test if a particular variable is tagged as a decoration.
Definition: AuxStoreInternal.cxx:420
xAOD::TAuxStore::TBranchHandle::branchPtr
::TBranch ** branchPtr()
Get a pointer to the branch being held.
Definition: TAuxStore.cxx:2059
xAOD::TAuxStore::size
virtual size_t size() const override
Return the number of elements in the store.
Definition: TAuxStore.cxx:486
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
SG::IAuxTypeVector
Abstract interface for manipulating vectors of arbitrary types.
Definition: IAuxTypeVector.h:42
xAOD::TAuxStore::m_size
std::size_t m_size
The current size of the container being described.
Definition: TAuxStore.h:248
xAOD::TAuxStore::TAuxStore
TAuxStore(const char *prefix="", Bool_t topStore=kTRUE, EStructMode mode=kUndefinedStore, Int_t basketSize=2048, Int_t splitLevel=0)
Default constructor.
Definition: TAuxStore.cxx:57
xAOD::TAuxStore::getIOData
virtual const void * getIOData(auxid_t auxid) const override
Get a pointer to the data being stored for one aux data item.
Definition: TAuxStore.cxx:754
xAOD::TAuxStore::structMode
EStructMode structMode() const
Get what structure mode the object was constructed with.
Definition: TAuxStore.cxx:88
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
xAOD::TAuxStore::setupAuxBranch
StatusCode setupAuxBranch(::TBranch *br, const char *auxName, ::Bool_t staticBranch)
Register one input branch as an available auxiliary variable.
Definition: TAuxStore.cxx:1609
xAOD::TAuxStore::m_branches
std::vector< TBranchHandle * > m_branches
Branches reading the various auxiliary variables.
Definition: TAuxStore.h:313
SG::AuxStoreInternal::resize
virtual bool resize(size_t sz) override
Change the size of all aux data vectors.
Definition: AuxStoreInternal.cxx:243
SG::AuxStoreInternal::getDecorIDs
virtual const SG::auxid_set_t & getDecorIDs() const override
Return a set of identifiers for decorations in this store.
Definition: AuxStoreInternal.cxx:410
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
collListGuids.attributes
attributes
Definition: collListGuids.py:46
xAOD::TAuxStore::TBranchHandle::TBranchHandle
TBranchHandle(::Bool_t staticBranch, ::Bool_t primitiveBranch, const std::type_info *ti, void *obj, SG::auxid_t auxid, const std::string *prefix)
Constructor.
Definition: TAuxStore.cxx:1962
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
xAOD::TAuxStore::~TAuxStore
~TAuxStore()
Destructor.
Definition: TAuxStore.cxx:71
merge.status
status
Definition: merge.py:17
xAOD::TAuxStore::TBranchHandle::outputObjectPtr
void * outputObjectPtr()
Get a pointer to the object (or its pointer) in memory for writing.
Definition: TAuxStore.cxx:2108
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
xAOD::TAuxStore::setupOutputData
StatusCode setupOutputData(auxid_t auxid)
Connect a variable to the output tree.
Definition: TAuxStore.cxx:1158
xAOD::AuxSelection::selectAux
virtual void selectAux(const std::set< std::string > &attributes)
Select which variables should be written out.
Definition: AuxSelection.cxx:47
xAOD::TAuxStore::clearDecorations
virtual bool clearDecorations() override
Remove the decorations added so far.
Definition: TAuxStore.cxx:447
xAOD::ReadStats
Class describing the access statistics of a collection of branches.
Definition: ReadStats.h:123
CxxUtils::ConcurrentBitset::erase
ConcurrentBitset & erase(bit_t bit)
Turn off one bit.
xAOD::AuxSelection::getSelectedAuxIDs
virtual SG::auxid_set_t getSelectedAuxIDs(const SG::auxid_set_t &fullset) const
Return which variables were selected to be written out.
Definition: AuxSelection.cxx:62
xAOD::TAuxStore::isPrimitiveBranch
::Bool_t isPrimitiveBranch(TBranch *br)
Check if a branch holds a primitive variable or not.
Definition: TAuxStore.cxx:1783
Utils
Definition: CaloCellSelectorUtils.cxx:10
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::TAuxStore::setupInputData
StatusCode setupInputData(auxid_t auxid)
Connect a variable to the input tree.
Definition: TAuxStore.cxx:901
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
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:226
xAOD::TAuxStore::linkedVector
virtual const SG::IAuxTypeVector * linkedVector(SG::auxid_t auxid) const override
Return interface for a linked variable.
Definition: TAuxStore.cxx:511
SG::IAuxTypeVector::toPtr
virtual void * toPtr()=0
Return a pointer to the start of the vector's data.
xAOD::TAuxStore::TBranchHandle
Class used internally to implement just-in-time reading.
Definition: TAuxStore.h:267
xAOD::TAuxStore::setPrefix
void setPrefix(const char *prefix)
Set the branch name prefix.
Definition: TAuxStore.cxx:120
xAOD::TAuxStore::m_branchesWritten
std::vector< bool > m_branchesWritten
"Write status" of the different variables
Definition: TAuxStore.h:315
xAOD::TAuxStore::prefix
const char * prefix() const
Get the currently configured branch name prefix.
Definition: TAuxStore.cxx:115
xAOD::TAuxStore::m_selection
AuxSelection m_selection
Object helping to select which auxiliary variables to write.
Definition: TAuxStore.h:238
PlotCalibFromCool.br
br
Definition: PlotCalibFromCool.py:355
CxxUtils::ConcurrentBitset::test
bool test(bit_t bit) const
Test to see if a bit is set.