ATLAS Offline Software
Control/xAODRootAccess/Root/TEvent.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 // System include(s):
4 #include <cassert>
5 #include <sstream>
6 #include <iomanip>
7 #include <cstring>
8 
9 // ROOT include(s):
10 #include <TFile.h>
11 #include <TTree.h>
12 #include <TKey.h>
13 #include <TChain.h>
14 #include <TFriendElement.h>
15 #include <TChainElement.h>
16 #include <TBranch.h>
17 #include <TError.h>
18 #include <TMethodCall.h>
19 #include <TSystem.h>
20 
21 // Gaudi/Athena include(s):
28 #ifndef XAOD_STANDALONE
30 # include "SGTools/DataProxy.h"
31 #endif // not XAOD_STANDALONE
32 #include "CxxUtils/ClassName.h"
34 
35 // Interface include(s):
37 
38 // xAOD include(s):
39 #include "xAODCore/tools/IOStats.h"
42 #include "xAODCore/AuxSelection.h"
43 
44 // Local include(s):
45 #include "xAODRootAccess/TEvent.h"
48 #include "xAODRootAccess/TStore.h"
63 
64 namespace {
65 
71  void removeVersionNames( std::string& name ) {
72 
73  size_t pos = 0;
74  while( ( pos = name.find( "_v1" ) ) != name.npos ) {
75  name.erase( pos, 3 );
76  }
77  while( ( pos = name.find( "_v2" ) ) != name.npos ) {
78  name.erase( pos, 3 );
79  }
80  while( ( pos = name.find( "_v3" ) ) != name.npos ) {
81  name.erase( pos, 3 );
82  }
83  while( ( pos = name.find( "_v4" ) ) != name.npos ) {
84  name.erase( pos, 3 );
85  }
86  while( ( pos = name.find( "_v5" ) ) != name.npos ) {
87  name.erase( pos, 3 );
88  }
89  while( ( pos = name.find( "_v6" ) ) != name.npos ) {
90  name.erase( pos, 3 );
91  }
92  while( ( pos = name.find( "_v7" ) ) != name.npos ) {
93  name.erase( pos, 3 );
94  }
95  while( ( pos = name.find( "_v8" ) ) != name.npos ) {
96  name.erase( pos, 3 );
97  }
98 
99  return;
100  }
101 
104  class ForceTrackIndices : public SG::AuxVectorBase {
105  public:
107  }; // class ForceTrackIndices
108 
110  void forceTrackIndices NO_SANITIZE_UNDEFINED ( SG::AuxVectorBase& vec ) {
111  // Treat the received object like it would be of type @c ForceTrackIndices
112  ForceTrackIndices& xvec = static_cast< ForceTrackIndices& >( vec );
113  xvec.initAuxVectorBase< DataVector< SG::IAuxElement > >( SG::OWN_ELEMENTS,
115  return;
116  }
117 
118 } // private namespace
119 
120 namespace xAOD {
121 
122  //
123  // Initialise the static data:
124  //
125  const ::Int_t TEvent::CACHE_SIZE = -1;
126  const char* const TEvent::EVENT_TREE_NAME = "CollectionTree";
127  const char* const TEvent::METADATA_TREE_NAME = "MetaData";
128 
130  static const TEvent::EAuxMode DEFAULT_ACCESS_MODE = TEvent::kClassAccess;
132  static const TEvent::EAuxMode UNIT_TEST_ACCESS_MODE = TEvent::kAthenaAccess;
133 
135  : m_auxMode( mode ),
136  m_inTree( nullptr ), m_inTreeMissing( kFALSE ),
137  m_inChain( nullptr ), m_inChainTracker( nullptr ),
138  m_inTreeNumber( -1 ), m_inMetaTree( nullptr ),
139  m_entry( -1 ), m_outTree( nullptr ),
140  m_inputObjects(), m_inputMissingObjects(), m_outputObjects(),
141  m_inputMetaObjects(), m_outputMetaObjects(),
142  m_inputEventFormat(), m_outputEventFormat( nullptr ),
143  m_auxItemList(), m_listeners(), m_nameRemapping() {
144 
145  // Make sure that the I/O monitoring is active:
147 
148  // Make this the active event:
149  setActive();
150 
151  // If the user didn't ask for one particular access type, chose one
152  // based on the running environment:
153  if( m_auxMode == kUndefinedAccess ) {
154  if( gSystem->Getenv( "ROOTCORE_AUTO_UT" ) ||
155  gSystem->Getenv( "ROOTCORE_FAST_UT" ) ||
156  gSystem->Getenv( "ROOTCORE_SLOW_UT" ) ) {
157  ::Info( "xAOD::TEvent::TEvent",
158  "Using access mode \"%i\" for the unit test",
159  static_cast< int >( UNIT_TEST_ACCESS_MODE ) );
160  m_auxMode = UNIT_TEST_ACCESS_MODE;
161  } else {
162  m_auxMode = DEFAULT_ACCESS_MODE;
163  }
164  }
165  }
166 
168  : m_auxMode( mode ),
169  m_inTree( nullptr ), m_inTreeMissing( kFALSE ),
170  m_inChain( nullptr ), m_inChainTracker( nullptr ),
171  m_inTreeNumber( -1 ), m_inMetaTree( nullptr ),
172  m_entry( -1 ), m_outTree( nullptr ),
173  m_inputObjects(), m_inputMissingObjects(), m_outputObjects(),
174  m_inputMetaObjects(), m_outputMetaObjects(),
175  m_inputEventFormat(), m_outputEventFormat( nullptr ),
176  m_auxItemList(), m_listeners(), m_nameRemapping() {
177 
178  // Make sure that the I/O monitoring is active:
180 
181  // Make this the active event:
182  setActive();
183 
184  // If the user didn't ask for one particular access type, chose one
185  // based on the running environment:
186  if( m_auxMode == kUndefinedAccess ) {
187  if( gSystem->Getenv( "ROOTCORE_AUTO_UT" ) ||
188  gSystem->Getenv( "ROOTCORE_FAST_UT" ) ||
189  gSystem->Getenv( "ROOTCORE_SLOW_UT" ) ) {
190  ::Info( "xAOD::TEvent::TEvent",
191  "Using access mode \"%i\" for the unit test",
192  static_cast< int >( UNIT_TEST_ACCESS_MODE ) );
193  m_auxMode = UNIT_TEST_ACCESS_MODE;
194  } else {
195  m_auxMode = DEFAULT_ACCESS_MODE;
196  }
197  }
198 
199  // Let the initialisation function deal with setting up the object:
200  readFrom( file ).ignore();
201  }
202 
204  : m_auxMode( mode ),
205  m_inTree( nullptr ), m_inTreeMissing( kFALSE ),
206  m_inChain( nullptr ), m_inChainTracker( nullptr ),
207  m_inTreeNumber( -1 ), m_inMetaTree( nullptr ),
208  m_entry( -1 ), m_outTree( nullptr ),
209  m_inputObjects(), m_inputMissingObjects(), m_outputObjects(),
210  m_inputMetaObjects(), m_outputMetaObjects(),
211  m_inputEventFormat(), m_outputEventFormat( nullptr ),
212  m_auxItemList(), m_listeners(), m_nameRemapping() {
213 
214  // Make sure that the I/O monitoring is active:
216 
217  // Make this the active event:
218  setActive();
219 
220  // If the user didn't ask for one particular access type, chose one
221  // based on the running environment:
222  if( m_auxMode == kUndefinedAccess ) {
223  if( gSystem->Getenv( "ROOTCORE_AUTO_UT" ) ||
224  gSystem->Getenv( "ROOTCORE_FAST_UT" ) ||
225  gSystem->Getenv( "ROOTCORE_SLOW_UT" ) ) {
226  ::Info( "xAOD::TEvent::TEvent",
227  "Using access mode \"%i\" for the unit test",
228  static_cast< int >( UNIT_TEST_ACCESS_MODE ) );
229  m_auxMode = UNIT_TEST_ACCESS_MODE;
230  } else {
231  m_auxMode = DEFAULT_ACCESS_MODE;
232  }
233  }
234 
235  // Let the initialisation function deal with setting up the object:
236  readFrom( tree ).ignore();
237  }
238 
240 
241  Object_t::iterator itr = m_inputObjects.begin();
243  for( ; itr != end; ++itr ) {
244  delete itr->second;
245  }
246  itr = m_outputObjects.begin();
247  end = m_outputObjects.end();
248  for( ; itr != end; ++itr ) {
249  delete itr->second;
250  }
251  itr = m_inputMetaObjects.begin();
252  end = m_inputMetaObjects.end();
253  for( ; itr != end; ++itr ) {
254  delete itr->second;
255  }
256  itr = m_outputMetaObjects.begin();
257  end = m_outputMetaObjects.end();
258  for( ; itr != end; ++itr ) {
259  delete itr->second;
260  }
261 
262  if( m_inChainTracker ) {
263  delete m_inChainTracker;
264  }
265 
266  // If this is set up as the active event at the moment, notify
267  // the active event object that this object will no longer be
268  // available.
269  if( TActiveEvent::event() == this ) {
270  TActiveEvent::setEvent( nullptr );
271  }
272 #ifndef XAOD_STANDALONE
273  if( SG::CurrentEventStore::store() == this ) {
275  }
276 #endif // not XAOD_STANDALONE
277  }
278 
282 
283  return m_auxMode;
284  }
285 
295  std::string TEvent::dump() {
296 
297  // The internal stream object:
298  std::ostringstream ost;
299  ost << "<<<<<<<<<<<<<<<<<<<< xAOD::TEvent Dump >>>>>>>>>>>>>>>>>>>>\n";
300 
301  // Loop over the EventFormat object:
304  for( ; ef_itr != ef_end; ++ef_itr ) {
305 
306  // Construct the type name:
307  std::string typeName = ef_itr->second.className();
308  removeVersionNames( typeName );
309 
310  // Get the type:
311  ::TClass* cl =
312  ::TClass::GetClass( ef_itr->second.className().c_str() );
313  const std::type_info* ti = ( cl ? cl->GetTypeInfo() : nullptr );
314  if( ( ! cl ) || ( ! cl->IsLoaded() ) || ( ! ti ) ) {
315  Warning( "xAOD::TEvent::dump",
316  "Unknown type (%s) found in the event format",
317  ef_itr->second.className().c_str() );
318  continue;
319  }
320 
321  // Skip containers that are not available anyway:
322  if( ! contains( ef_itr->second.branchName(), *ti ) ) {
323  continue;
324  }
325 
326  // Do the printout:
327  ost << " Hash: 0x" << std::setw( 8 ) << std::setfill( '0' )
328  << std::hex << ef_itr->second.hash()
329  << " Key: \"" << ef_itr->second.branchName() << "\"\n";
330 
331  ost << " type: " << typeName << "\n";
332  const bool isNonConst = transientContains( ef_itr->second.branchName(),
333  *ti );
334  ost << " isConst: " << ( isNonConst ? "No" : "Yes" ) << "\n";
335  ost << " Data: "
336  << ( isNonConst ? getOutputObject( ef_itr->second.branchName(),
337  *ti ) :
338  getInputObject( ef_itr->second.branchName(), *ti ) ) << "\n";
339  }
340 
341  // Finish with the construction:
342  ost << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
343  return ost.str();
344  }
345 
350  void TEvent::printIOStats() const {
351 
352  // Simply do this via the xAODCore code:
353  IOStats::instance().stats().Print( "Summary" );
354 
355  return;
356  }
357 
367  StatusCode TEvent::readFrom( ::TFile* file, Bool_t useTreeCache,
368  const char* treeName ) {
369 
370  // If no file was specified, return gracefully:
371  if( ! file ) return StatusCode::SUCCESS;
372 
373  // Clear the cached input objects:
374  Object_t::iterator itr = m_inputObjects.begin();
376  for( ; itr != end; ++itr ) {
377  delete itr->second;
378  }
379  m_inputObjects.clear();
380  m_inputMissingObjects.clear();
381  {
383  lock.upgrade();
384  m_branches.clear();
385  }
386 
387  // Clear the cached input meta-objects:
388  itr = m_inputMetaObjects.begin();
389  end = m_inputMetaObjects.end();
390  for( ; itr != end; ++itr ) {
391  delete itr->second;
392  }
393  m_inputMetaObjects.clear();
394 
395  // Reset the internal flags:
396  m_inTreeMissing = kFALSE;
397  m_entry = -1;
398 
399  // Make sure we return to the current directory:
401 
402  // Set up the file access tracer:
403  static TFileAccessTracer tracer ATLAS_THREAD_SAFE;
404  tracer.add( *file );
405 
406  // Look for the metadata tree:
407  m_inMetaTree =
408  dynamic_cast< ::TTree* >( file->Get( METADATA_TREE_NAME ) );
409  if( ! m_inMetaTree ) {
410  ::Error( "xAOD::TEvent::readFrom",
411  XAOD_MESSAGE( "Couldn't find metadata tree on input. Object "
412  "unusable!" ) );
413  return StatusCode::FAILURE;
414  }
415 
416  // Set metadata entry to be read
417  // NB: no reading is done calling LoadTree
418  if ( m_inMetaTree->LoadTree(0) < 0 ){
419  ::Error( "xAOD::TEvent::readFrom",
420  XAOD_MESSAGE( "Failed to load entry for metadata tree=%s" ),
421  m_inMetaTree->GetName() );
422  return StatusCode::FAILURE;
423  }
424 
425  // A sanity check:
426  if( m_inMetaTree->GetEntries() != 1 ) {
427  ::Info( "xAOD::TEvent::readFrom",
428  "Was expecting a metadata tree with size 1, instead of %i.",
429  static_cast< int >( m_inMetaTree->GetEntries() ) );
430  ::Info( "xAOD::TEvent::readFrom",
431  "File most probably produced by hadd..." );
432  }
433 
434  // Make sure that the xAOD::EventFormat dictonary is loaded.
435  // This may not be the case if streamer information reading is turned
436  // off.
437  static const std::string eventFormatTypeName =
438  Utils::getTypeName( typeid( EventFormat ) );
439  ::TClass* cl = ::TClass::GetClass( eventFormatTypeName.c_str() );
440  if( ! cl ) {
441  ::Warning( "xAOD::TEvent::readFrom",
442  "Couldn't load the EventFormat dictionary" );
443  }
444 
445  // Check if the EventFormat branch is available:
446  const std::string eventFormatBranchName =
447  Utils::getFirstBranchMatch( m_inMetaTree, "EventFormat");
448  if( ! m_inMetaTree->GetBranch( eventFormatBranchName.c_str() ) ) {
449  // This can happen when the file was produced by an Athena job that
450  // didn't have any input events itself. This means that the file
451  // doesn't actually have any useful metadata.
452  ::Info( "xAOD::TEvent::readFrom", "Input file provides no event or "
453  "metadata" );
454  m_inTree = 0;
455  m_inTreeMissing = kTRUE;
456  return StatusCode::SUCCESS;
457  }
458 
459  // Read in the event format object:
460  EventFormat* format = 0; ::TBranch* br = 0;
461  const Int_t status =
462  m_inMetaTree->SetBranchAddress( eventFormatBranchName.c_str(),
463  &format, &br );
464  if( status < 0 ) {
465  ::Error( "xAOD::TEvent::readFrom",
466  XAOD_MESSAGE( "Failed to connect to EventFormat object" ) );
467  return StatusCode::FAILURE;
468  }
469 
470  // Read in the object to our private member:
471  br->GetEntry( 0 );
473 
474  // This is a strange place. The object has to be deleted, as it is the
475  // responsibility of the user code to do so. But if I also explicitly
476  // tell the branch to forget about the address of the pointer, then
477  // all hell breaks loose...
478  delete format;
479 
480 
481  // List all the other Metadata trees in the input file
482  // Having several metatrees can happen for augmented files for instance
483  // as one metadata tree per stream is produced
484  std::set<std::string> lOtherMetaTreeNames = {};
485  TList *lKeys = file->GetListOfKeys();
486 
487  if (lKeys){
488  for (int iKey = 0; iKey < lKeys->GetEntries() ; iKey++){
489  // iterate over keys and add
490  std::string keyName = lKeys->At(iKey)->GetName();
491  // Make sure the key corresponds to a metadata tree but
492  // do not add the current metadata tree in the list of other trees
493  // and do not add the metadata tree handlers to the list
494  if ( (keyName != METADATA_TREE_NAME)
495  && (keyName.find("MetaData") != std::string::npos)
496  && !(keyName.find("MetaDataHdr") != std::string::npos)){
497  // Make sure key corresponds to a tree
498  const char *className = ((::TKey*)lKeys->At(iKey))->GetClassName();
499  static constexpr Bool_t LOAD = kFALSE;
500  static constexpr Bool_t SILENT = kTRUE;
501  ::TClass* cl = ::TClass::GetClass(className, LOAD, SILENT);
502  if ((cl != nullptr) && cl->InheritsFrom(::TTree::Class())){
503  // key is corresponding to a metadata tree
504  lOtherMetaTreeNames.insert(std::move(keyName));
505  }
506  }
507  }
508  }
509 
510  // Loop over the other metadata trees found (if any)
511  for (const std::string & metaTreeName : lOtherMetaTreeNames){
512  TTree *tmpMetaTree = dynamic_cast< ::TTree* >( file->Get( metaTreeName.c_str() ) );
513 
514  if (!tmpMetaTree){
515  // Skip tree if could not read it
516  ::Warning( "xAOD::TEvent::readFrom", "Could not read metadata tree=%s",metaTreeName.c_str());
517  continue;
518  }
519 
520  // Set metadata entry to be read
521  // NB: no reading is done calling LoadTree
522  if ( tmpMetaTree->LoadTree(0) < 0 ){
523  ::Error( "xAOD::TEvent::readFrom",
524  XAOD_MESSAGE( "Failed to load entry for metadata tree=%s" ),
525  tmpMetaTree->GetName() );
526  return StatusCode::FAILURE;
527  }
528 
529  // Check if the EventFormat branch is available:
530  const std::string tmpEventFormatBranchName =
531  Utils::getFirstBranchMatch( tmpMetaTree, "EventFormat");
532  if( ! tmpMetaTree->GetBranch( tmpEventFormatBranchName.c_str() ) ) {
533  // skip the additionnal metadata tree
534  ::Warning( "xAOD::TEvent::readFrom", "No EventFormat branch found in metadata tree=%s",tmpMetaTree->GetName() );
535  continue ;
536  }
537  // Read in the event format object:
538  EventFormat* tmpFormat = 0; ::TBranch* tmpBr = 0;
539  const Int_t status =
540  tmpMetaTree->SetBranchAddress( tmpEventFormatBranchName.c_str(),
541  &tmpFormat, &tmpBr );
542  if( status < 0 ) {
543  ::Error( "xAOD::TEvent::readFrom",
544  XAOD_MESSAGE( "Failed to connect to EventFormat object for metadata tree = %s"), tmpMetaTree->GetName() );
545  return StatusCode::FAILURE;
546  }
547  // Read in the object
548  tmpBr->GetEntry( 0 );
549  // read all objects contained in the event format
550  for (const std::pair<const std::string, xAOD::EventFormatElement> &evtElem : *tmpFormat){
551  // if element is not existing
552  // then add it to the private event format member
553  if (!m_inputEventFormat.exists(evtElem.first)){
554  m_inputEventFormat.add(evtElem.second);
555  }
556  }
557  delete tmpFormat;
558  }
559 
560  // Look for the event tree in the input file:
561  m_inTree = dynamic_cast< ::TTree* >( file->Get( treeName ) );
562  if( ! m_inTree ) {
563  // This is no longer an error condition. As it can happen for DxAODs
564  // that don't have any events in them. But they still have metadata
565  // that needs to be collected.
566  m_inTreeMissing = kTRUE;
567  }
568 
569  // Turn on the cache if requested:
570  if( m_inTree && useTreeCache && ( ! m_inTree->GetCacheSize() ) ) {
571  m_inTree->SetCacheSize( CACHE_SIZE );
572  m_inTree->SetCacheLearnEntries( 10 );
573  }
574 
575  // Init the statistics collection:
576  RETURN_CHECK( "xAOD::TEvent::readFrom", initStats() );
577  // Update the event counter in the statistics object:
579  if( m_inTree ) {
580  stats.setNEvents( stats.nEvents() + m_inTree->GetEntries() );
581  }
582 
583  // Notify the listeners that a new file was opened:
584  const TIncident beginIncident( IncidentType::BeginInputFile );
585  for( TVirtualIncidentListener* listener : m_listeners ) {
586  listener->handle( beginIncident );
587  }
588  // For now implement a very simple scheme in which we claim already
589  // at the start that the entire file was processed. Since we have no way
590  // of ensuring that the user indeed does this. And we can't delay calling
591  // this function, as the user may likely close his/her output file before
592  // closing the last opened input file.
593  const TIncident endIncident( IncidentType::EndInputFile );
594  for( TVirtualIncidentListener* listener : m_listeners ) {
595  listener->handle( endIncident );
596  }
597 
598  // The initialisation was successful:
599  return StatusCode::SUCCESS;
600  }
601 
610  StatusCode TEvent::readFrom( ::TTree* tree, Bool_t useTreeCache ) {
611 
612  // Remember the info:
613  m_inTree = 0;
614  m_inTreeMissing = kFALSE;
615  m_inChain = dynamic_cast< ::TChain* >( tree );
616  m_inMetaTree = 0;
617 
618  if( m_inChain ) {
619 
620  // Set up the caching on the chain level. The individual trees of the
621  // input files will get a cache set up automatically after this.
622  if( useTreeCache && ( ! m_inChain->GetCacheSize() ) ) {
623  m_inChain->SetCacheSize( CACHE_SIZE );
624  m_inChain->SetCacheLearnEntries( 10 );
625  }
626 
627  // Explicitly open the first file of the chain. To correctly auto-load
628  // the dictionaries necessary. This doesn't happen automatically with
629  // some ROOT versions...
630  const TObjArray* files = m_inChain->GetListOfFiles();
631  if( ! files ) {
632  ::Error( "xAOD::TEvent::readFrom",
633  XAOD_MESSAGE( "Couldn't get the list of files from the "
634  "input TChain" ) );
635  return StatusCode::FAILURE;
636  }
637  if( ! files->GetEntries() ) {
638  ::Error( "xAOD::TEvent::readFrom",
639  XAOD_MESSAGE( "No files are present in the received "
640  "TChain" ) );
641  return StatusCode::FAILURE;
642  }
643  const ::TChainElement* chEl =
644  dynamic_cast< const ::TChainElement* >( files->At( 0 ) );
645  if( ! chEl ) {
646  ::Error( "xAOD::TEvent::readFrom",
647  XAOD_MESSAGE( "Couldn't cast object to TChainElement" ) );
648  return StatusCode::FAILURE;
649  }
650  ::TFile* dummyFile = ::TFile::Open( chEl->GetTitle() );
651  if( ! dummyFile ) {
652  ::Error( "xAOD::TEvent::readFrom",
653  XAOD_MESSAGE( "Couldn't open file %s" ),
654  chEl->GetTitle() );
655  return StatusCode::FAILURE;
656  }
657  delete dummyFile;
658 
659  // Set up a tracker for the chain:
660  if( ! m_inChainTracker ) {
662  }
664  tree->SetNotify( m_inChainTracker );
665 
666  // Stop at this point. The first file will be opened when the user
667  // asks for the first event. Otherwise we open the first file of the
668  // chain multiple times.
669  m_inTreeNumber = -1;
670  return StatusCode::SUCCESS;
671 
672  } else {
673 
674  // If it's a simple TTree, then let's fully initialise the object
675  // using its file:
676  m_inTreeNumber = -1;
677  if( m_inChainTracker ) {
678  delete m_inChainTracker;
679  m_inChainTracker = 0;
680  }
681  ::TFile* file = tree->GetCurrentFile();
682  return readFrom( file, useTreeCache, tree->GetName() );
683 
684  }
685  }
686 
695  StatusCode TEvent::writeTo( ::TFile* file, Int_t autoFlush,
696  const char* treeName ) {
697 
698  // Just a simple security check:
699  if( ! file ) {
700  ::Error( "xAOD::TEvent::writeTo",
701  XAOD_MESSAGE( "Null pointer given to the function!" ) );
702  return StatusCode::FAILURE;
703  }
704 
705  // Check that the object is in the "right state":
706  if( m_outTree ) {
707  ::Error( "xAOD::TEvent::writeTo",
708  XAOD_MESSAGE( "Object already writing to a file. Close that "
709  "file first!" ) );
710  return StatusCode::FAILURE;
711  }
712 
713  // Make sure we return to the current directory:
715 
716  // Create the output TTree:
717  file->cd();
718  m_outTree = new ::TTree( treeName, "xAOD event tree" );
719  m_outTree->SetDirectory( file );
720  m_outTree->SetAutoSave( 1000000 );
721  m_outTree->SetAutoFlush( autoFlush );
722 
723  // Access the EventFormat object associated with this file:
726 
727  // Return gracefully:
728  return StatusCode::SUCCESS;
729  }
730 
738 
739  // A small sanity check:
740  if( ! m_outTree ) {
741  ::Error( "xAOD::TEvent::finishWritingTo",
742  XAOD_MESSAGE( "The object doesn't seem to be connected to an "
743  "output file!" ) );
744  return StatusCode::FAILURE;
745  }
746 
747  // Make sure we return to the current directory:
749 
750  // Notify the listeners that they should write out their metadata, if they
751  // have any.
752  const TIncident incident( IncidentType::MetaDataStop );
753  Listener_t::iterator l_itr = m_listeners.begin();
754  Listener_t::iterator l_end = m_listeners.end();
755  for( ; l_itr != l_end; ++l_itr ) {
756  ( *l_itr )->handle( incident );
757  }
758 
759  // Write out the event tree, and delete it:
760  m_outTree->AutoSave( "FlushBaskets" );
761  m_outTree->SetDirectory( 0 );
762  delete m_outTree;
763  m_outTree = 0;
764 
765  // Now go to the output file:
766  file->cd();
767 
768  // Check if there's already a metadata tree in the output:
769  if( file->Get( METADATA_TREE_NAME ) ) {
770  // Let's assume that the metadata is complete in the file already.
771  return StatusCode::SUCCESS;
772  }
773 
774  // Create the metadata tree:
775  ::TTree* metatree =
776  new ::TTree( METADATA_TREE_NAME, "xAOD metadata tree" );
777  metatree->SetAutoSave( 10000 );
778  metatree->SetAutoFlush( -30000000 );
779  metatree->SetDirectory( file );
780 
781  // Create the only branch in it:
782  try {
783  metatree->Branch( "EventFormat",
784  SG::normalizedTypeinfoName( typeid( xAOD::EventFormat ) ).c_str(),
786  }
787  catch (const CxxUtils::ClassName::ExcBadClassName& e) {
788  ::Error( "xAOD::TEvent::finishWritingTo",
789  XAOD_MESSAGE( "Class name parsing fails for %s ! " ),
790  e.what() );
791  return StatusCode::FAILURE;
792  }
793 
794  // Create a copy of the m_outputMetaObjects variable. This is necessary
795  // because the putAux(...) function will modify this variable while we
796  // loop over it.
797  Object_t outputMetaObjects = m_outputMetaObjects;
798 
799  // Now loop over all the metadata objects that need to be put into the
800  // output file:
801  for( auto& object : outputMetaObjects ) {
802  // All metadata objects should be held by TObjectManager objects.
803  // Anything else is an error.
804  TObjectManager* mgr = dynamic_cast< TObjectManager* >( object.second );
805  if( ! mgr ) {
806  ::Error( "xAOD::TEvent::finishWritingTo",
807  XAOD_MESSAGE( "Internal logic error detected" ) );
808  return StatusCode::FAILURE;
809  }
810  // Select a split level depending on whether this is an interface or an
811  // auxiliary object:
812  const ::Int_t splitLevel = ( object.first.find( "Aux." ) ==
813  ( object.first.size() - 4 ) ? 1 : 0 );
814  // Create the new branch:
815  *( mgr->branchPtr() ) =
816  metatree->Branch( object.first.c_str(),
817  mgr->holder()->getClass()->GetName(),
818  mgr->holder()->getPtr(), 32000, splitLevel );
819  if( ! mgr->branch() ) {
820  ::Error( "xAOD::TEvent::finishWritingTo",
821  XAOD_MESSAGE( "Failed to create metadata branch "
822  "\"%s/%s\"" ),
823  mgr->holder()->getClass()->GetName(),
824  object.first.c_str() );
825  return StatusCode::FAILURE;
826  }
827  // Set up the saving of all the dynamic auxiliary properties
828  // of the object if it has any:
829  RETURN_CHECK( "xAOD::TEvent::finishWritingTo",
830  putAux( *metatree, *( object.second ), 32000, 0,
831  kTRUE ) );
832  }
833 
834  // Write the metadata objects:
835  if( metatree->Fill() <= 0 ) {
836  ::Error( "xAOD::TEvent::finishWritingTo",
837  XAOD_MESSAGE( "Failed to write event format metadata into "
838  "the output" ) );
839  metatree->SetDirectory( 0 );
840  delete metatree;
841  return StatusCode::FAILURE;
842  }
843 
844  // Now clean up:
845  metatree->Write();
846  metatree->SetDirectory( 0 );
847  delete metatree;
849  Object_t::iterator obj_itr = m_outputObjects.begin();
850  Object_t::iterator obj_end = m_outputObjects.end();
851  for( ; obj_itr != obj_end; ++obj_itr ) {
852  delete obj_itr->second;
853  }
854  m_outputObjects.clear();
855  obj_itr = m_outputMetaObjects.begin();
856  obj_end = m_outputMetaObjects.end();
857  for( ; obj_itr != obj_end; ++obj_itr ) {
858  delete obj_itr->second;
859  }
860  m_outputMetaObjects.clear();
861 
862  // Return gracefully:
863  return StatusCode::SUCCESS;
864  }
865 
871  void TEvent::setActive() const {
872 
873  // The active event and current store are thread-local globals:
874  TEvent* nc_this ATLAS_THREAD_SAFE = const_cast<TEvent*>(this);
875 
876  TActiveEvent::setEvent( static_cast<TVirtualEvent*>( nc_this ) );
877 
878 #ifndef XAOD_STANDALONE
880 #endif // not XAOD_STANDALONE
881 
882  // Return gracefully:
883  return;
884  }
885 
893  void TEvent::setAuxItemList( const std::string& containerKey,
894  const std::string& itemList ) {
895 
896  // Decoded attributes:
897  std::set< std::string > attributes;
898 
899  // Split up the received string using "." as the separator:
900  if( itemList.size() ) {
901  std::stringstream ss( itemList );
902  std::string attr;
903  while( std::getline( ss, attr, '.' ) ) {
904  attributes.insert( attr );
905  }
906  }
907 
908  // Remember the setting:
909  m_auxItemList[ containerKey ] = std::move(attributes);
910 
911  return;
912  }
913 
922 
923  // Check that we received a valid pointer:
924  if( ! listener ) {
925  ::Error( "xAOD::TEvent::addListener",
926  XAOD_MESSAGE( "Received a null pointer for the listener" ) );
927  return StatusCode::FAILURE;
928  }
929 
930  // Check if this listener is already in our list:
931  bool listenerKnown = false;
933  if( l == listener ) {
934  ::Warning( "xAOD::TEvent::addListener",
935  "Listener %p was added previously already",
936  static_cast< void* >( listener ) );
937  listenerKnown = true;
938  break;
939  }
940  }
941 
942  // If we don't know it yet, let's add it now:
943  if( ! listenerKnown ) {
944  m_listeners.push_back( listener );
945  }
946 
947  // Return gracefully:
948  return StatusCode::SUCCESS;
949  }
950 
958 
959  // Find the pointer if we can...
961  m_listeners.end(), listener );
962 
963  // If we didn't find it:
964  if( itr == m_listeners.end() ) {
965  ::Error( "xAOD::TEvent::removeListener",
966  XAOD_MESSAGE( "Listener %p not known" ),
967  static_cast< void* >( listener ) );
968  return StatusCode::FAILURE;
969  }
970 
971  // Remove it:
972  m_listeners.erase( itr );
973 
974  // Return gracefully:
975  return StatusCode::SUCCESS;
976  }
977 
982 
983  m_listeners.clear();
984  return;
985  }
986 
1001  StatusCode TEvent::addNameRemap( const std::string& onfile,
1002  const std::string& newName ) {
1003 
1004  // Check if this name is known on the input or output already. As that's
1005  // not good.
1006  if( m_inputEventFormat.exists( newName ) ) {
1007  ::Error( "xAOD::TEvent::addNameRemap",
1008  XAOD_MESSAGE( "Can't use \"%s\" as the target name in the"
1009  "\"%s\" -> \"%s\" remapping" ),
1010  newName.c_str(), onfile.c_str(), newName.c_str() );
1011  return StatusCode::FAILURE;
1012  }
1013 
1014  // Check if this name was remapped to something already:
1015  auto itr = m_nameRemapping.find( newName );
1016  if( itr != m_nameRemapping.end() ) {
1017  ::Warning( "xAOD::TEvent::addNameRemap",
1018  "Overriding existing name remapping \"%s\" -> \"%s\"",
1019  itr->second.c_str(), itr->first.c_str() );
1020  ::Warning( "xAOD::TEvent::addNameRemap", " with: \"%s\" -> \"%s\"",
1021  onfile.c_str(), newName.c_str() );
1022  }
1023 
1025  m_nameRemapping[ newName ] = onfile;
1026 
1027  // Return gracefully:
1028  return StatusCode::SUCCESS;
1029  }
1030 
1036 
1037  m_nameRemapping.clear();
1038  return;
1039  }
1040 
1044  void TEvent::printNameRemap() const {
1045 
1046  // Print a header:
1047  ::Info( "xAOD::TEvent::printNameRemap", "Name remapping rules:" );
1048 
1049  // In case no remapping rules have been set:
1050  if( ! m_nameRemapping.size() ) {
1051  ::Info( "xAOD::TEvent::printNameRemap", " NONE" );
1052  return;
1053  }
1054 
1055  // Otherwise:
1056  for( auto itr = m_nameRemapping.begin(); itr != m_nameRemapping.end();
1057  ++itr ) {
1058  ::Info( "xAOD::TEvent::printNameRemap", " \"%s\" -> \"%s\"",
1059  itr->second.c_str(), itr->first.c_str() );
1060  }
1061 
1062  // Return gracefully:
1063  return;
1064  }
1065 
1077  SG::IAuxStore* TEvent::recordAux( const std::string& key,
1079  ::Int_t basketSize, ::Int_t splitLevel ) {
1080 
1081  // A sanity check:
1082  if( ! m_outTree ) {
1083  ::Error( "xAOD::TEvent::recordAux",
1084  XAOD_MESSAGE( "No output tree given to the object" ) );
1085  return 0;
1086  }
1087 
1088  // Check for an object with this name in the output list:
1089  Object_t::iterator itr = m_outputObjects.find( key );
1090  if( itr == m_outputObjects.end() ) {
1091  // Create one if if it doesn't exist yet...
1092  // Translate the store type:
1094  switch( type ) {
1097  break;
1100  break;
1101  default:
1102  ::Error( "xAOD::TEvent::recordAux",
1103  XAOD_MESSAGE( "Unknown store type (%i) requested" ),
1104  static_cast< int >( type ) );
1105  return 0;
1106  }
1107  // Create and record the object:
1108  TAuxStore* store = new TAuxStore( key, kTRUE, mode,
1109  basketSize, splitLevel );
1110  if( record( store, key, basketSize, splitLevel, kTRUE ).isFailure() ) {
1111  ::Error( "xAOD::TEvent::recordAux",
1112  XAOD_MESSAGE( "Couldn't connect TAuxStore object to the "
1113  "output" ) );
1114  delete store;
1115  return 0;
1116  }
1117  // Update the iterator:
1118  itr = m_outputObjects.find( key );
1119  }
1120 
1121  // A security check:
1122  if( itr == m_outputObjects.end() ) {
1123  ::Error( "xAOD::TEvent::recordAux",
1124  XAOD_MESSAGE( "Internal logic error detected" ) );
1125  return 0;
1126  }
1127 
1128  // Check that it is of the right type:
1129  TAuxManager* mgr = dynamic_cast< TAuxManager* >( itr->second );
1130  if( ! mgr ) {
1131  ::Error( "xAOD::TEvent::recordAux",
1132  XAOD_MESSAGE( "Object of non-TAuxStore type registered "
1133  "with key \"%s\"" ), key.c_str() );
1134  return 0;
1135  }
1136 
1137  // Extract the pointer out of it:
1138  TAuxStore* store = mgr->getStore();
1139 
1140  // Give it to the user:
1141  return store;
1142  }
1143 
1154  StatusCode TEvent::copy( const std::string& key,
1155  ::Int_t basketSize, ::Int_t splitLevel ) {
1156 
1157  // Check if a name re-mapping should be applied or not:
1158  std::string keyToUse = key;
1159  auto remap_itr = m_nameRemapping.find( key );
1160  if( ( remap_itr != m_nameRemapping.end() ) &&
1161  ( ! m_inputEventFormat.exists( key ) ) &&
1162  m_inputEventFormat.exists( remap_itr->second ) ) {
1163  keyToUse = remap_itr->second;
1164  }
1165 
1166  // Make sure that the branch got connected to:
1167  RETURN_CHECK( "xAOD::TEvent::copy", connectBranch( keyToUse ) );
1168 
1169  // Make sure that the input object is properly updated:
1170  Object_t::const_iterator vobjMgr = m_inputObjects.find( keyToUse );
1171  if( vobjMgr == m_inputObjects.end() ) {
1172  ::Error( "xAOD::TEvent::copy",
1173  XAOD_MESSAGE( "Internal logic error detected" ) );
1174  return StatusCode::FAILURE;
1175  }
1176  TObjectManager* objMgr =
1177  dynamic_cast< TObjectManager* >( vobjMgr->second );
1178  if( ! objMgr ) {
1179  ::Error( "xAOD::TEvent::copy",
1180  XAOD_MESSAGE( "Internal logic error detected" ) );
1181  return StatusCode::FAILURE;
1182  }
1183  if( ! getInputObject( key,
1184  *( objMgr->holder()->getClass()->GetTypeInfo() ) ) ) {
1185  ::Error( "xAOD::TEvent::copy",
1186  XAOD_MESSAGE( "Internal logic error detected" ) );
1187  return StatusCode::FAILURE;
1188  }
1189 
1190  // Put the interface object into the output:
1191  RETURN_CHECK( "xAOD::TEvent::copy",
1192  record( objMgr->object(),
1193  objMgr->holder()->getClass()->GetName(),
1194  key, basketSize, splitLevel, kTRUE ) );
1195 
1196  // Check if we have a filtering rule for the store:
1197  const std::set< std::string >* filter = 0;
1198  auto fitr = m_auxItemList.find( key + "Aux." );
1199  if( fitr != m_auxItemList.end() ) {
1200  filter = &( fitr->second );
1201  }
1202 
1203  // Put the auxiliary store object into the output:
1204  Object_t::const_iterator vauxMgr = m_inputObjects.find( keyToUse +
1205  "Aux." );
1206  if( vauxMgr == m_inputObjects.end() ) {
1207  // If there is no auxiliary store for this object/container, we're
1208  // done already:
1209  return StatusCode::SUCCESS;
1210  }
1211  // Check what type of auxiliary store this is:
1213  TObjectManager* auxMgr =
1214  dynamic_cast< TObjectManager* >( vauxMgr->second );
1215  if( ! auxMgr ) {
1216  ::Error( "xAOD::TEvent::copy",
1217  XAOD_MESSAGE( "Internal logic error detected" ) );
1218  return StatusCode::FAILURE;
1219  }
1220  RETURN_CHECK( "xAOD::TEvent::copy",
1221  record( auxMgr->object(),
1222  auxMgr->holder()->getClass()->GetName(),
1223  key + "Aux.", basketSize, splitLevel, kTRUE ) );
1224  } else if( m_auxMode == kBranchAccess ) {
1225  TAuxManager* auxMgr =
1226  dynamic_cast< TAuxManager* >( vauxMgr->second );
1227  if( ! auxMgr ) {
1228  ::Error( "xAOD::TEvent::copy",
1229  XAOD_MESSAGE( "Internal logic error detected" ) );
1230  return StatusCode::FAILURE;
1231  }
1232  // Set up the filtering:
1233  if( filter ) {
1234  auxMgr->getStore()->selectAux( *filter );
1235  }
1236  RETURN_CHECK( "xAOD::TEvent::copy",
1237  record( auxMgr->getStore(),
1238  key + "Aux.", basketSize, splitLevel ) );
1239  } else {
1240  ::Fatal( "xAOD::TEvent::copy",
1241  XAOD_MESSAGE( "Internal logic error detected" ) );
1242  }
1243 
1244  // Return gracefully:
1245  return StatusCode::SUCCESS;
1246  }
1247 
1257  StatusCode TEvent::copy( ::Int_t basketSize, ::Int_t splitLevel ) {
1258 
1259  // Make sure that an input TTree is available:
1260  if( ! m_inTree ) {
1261  ::Error( "xAOD::TEvent::copy",
1262  XAOD_MESSAGE( "No input TTree is open" ) );
1263  return StatusCode::FAILURE;
1264  }
1265 
1266  // Loop over the known input containers:
1269  for( ; itr != end; ++itr ) {
1270 
1271  // Convenience reference:
1272  const EventFormatElement& efe = itr->second;
1273 
1274  // Ignore objects that don't exist on the input:
1275  if( ! m_inTree->GetBranch( efe.branchName().c_str() ) ) {
1276  continue;
1277  }
1278  // Skip all branches ending in "Aux.":
1279  if( efe.branchName().find( "Aux." ) ==
1280  ( efe.branchName().size() - 4 ) ) {
1281  continue;
1282  }
1283  // Also skip dynamic branches:
1284  if( efe.parentName() != "" ) {
1285  continue;
1286  }
1287  // Check if the class in question is known:
1288  ::TClass* cl = ::TClass::GetClass( efe.className().c_str() );
1289  if( ( ! cl ) || ( ! cl->IsLoaded() ) ) {
1290  continue;
1291  }
1292 
1293  // Make the copy then...
1294  RETURN_CHECK( "xAOD::TEvent::copy",
1295  this->copy( efe.branchName(), basketSize, splitLevel ) );
1296  }
1297 
1298  // Return gracefully:
1299  return StatusCode::SUCCESS;
1300  }
1301 
1304  ::Long64_t TEvent::getEntries() const {
1305 
1306  if( m_inChain ) {
1307  return m_inChain->GetEntries();
1308  } else if( m_inTree ) {
1309  return m_inTree->GetEntries();
1310  } else if( m_inTreeMissing ) {
1311  // The input file is empty:
1312  return 0;
1313  } else {
1314  ::Error( "xAOD::TEvent::getEntries",
1315  XAOD_MESSAGE( "Function called on an uninitialised "
1316  "object" ) );
1317  return 0;
1318  }
1319  }
1320 
1335  ::Int_t TEvent::getEntry( ::Long64_t entry, ::Int_t getall ) {
1336 
1337  // A little sanity check:
1338  if( ( ! m_inTree ) && ( ! m_inChain ) ) {
1339  ::Error( "xAOD::TEvent::getEntry",
1340  XAOD_MESSAGE( "Function called on an uninitialised "
1341  "object" ) );
1342  return -1;
1343  }
1344 
1345  // If we have a chain as input:
1346  if( m_inChain ) {
1347  // Make sure that the correct tree is loaded:
1348  const ::Long64_t fileEntry = m_inChain->LoadTree( entry );
1349  if( fileEntry < 0 ) {
1350  ::Error( "xAOD::TEvent::getEntry",
1351  XAOD_MESSAGE( "Failure in loading entry %i from the "
1352  "input chain" ),
1353  static_cast< int >( entry ) );
1354  return -1;
1355  }
1356  // Check if a new file was loaded:
1357  if( ( m_inTreeNumber != m_inChain->GetTreeNumber() ) ||
1359  // Reset the tracker:
1361  // Connect to this new file:
1362  m_inTreeNumber = m_inChain->GetTreeNumber();
1363  ::TFile* file = m_inChain->GetFile();
1364  // The useTreeCache parameter is set to false, since the cache
1365  // is anyway set up through the TChain. It shouldn't be modified
1366  // on the file level.
1367  if( ! readFrom( file, kFALSE, m_inChain->GetName() ) ) {
1368  ::Error( "xAOD::TEvent::getEntry",
1369  XAOD_MESSAGE( "Couldn't connect to input file #%i "
1370  "of the input chain" ), m_inTreeNumber );
1371  return -1;
1372  }
1373  }
1374  // Restore the previously received entry number.
1375  m_entry = fileEntry;
1376  }
1377  // If we have a regular file/tree as input:
1378  else {
1379  m_entry = entry;
1380  }
1381 
1382  // In order to make the reading of branches+tree cache work
1383  // NB: TTree::LoadTree() only set the entry that should be read for each branch
1384  // but no reading of the branch content is performed when calling that function.
1385  // The entry set that can be retrieved with
1386  // branch->GetTree()->GetReadEntry()
1387  // For friend trees, if an index was built, then the entry which is set for the related branches
1388  // is found by the LoadTree function by matching
1389  // the the major and minor values of the main tree and friend tree
1390  if( m_inTree && m_inTree->LoadTree( m_entry ) < 0 ) {
1391  ::Error( "xAOD::TEvent::getEntry",
1392  XAOD_MESSAGE( "Failure in loading entry %i from the input "
1393  "file" ), static_cast< int >( m_entry ) );
1394  return -1;
1395  }
1396 
1397  // Stats counter needs to know it's the next event:
1399 
1400  // If force-reading is not requested, we're done:
1401  if( ! getall ) {
1402 
1403  // Notify the listeners that a new event was loaded:
1404  const TIncident incident( IncidentType::BeginEvent );
1405  Listener_t::iterator l_itr = m_listeners.begin();
1406  Listener_t::iterator l_end = m_listeners.end();
1407  for( ; l_itr != l_end; ++l_itr ) {
1408  ( *l_itr )->handle( incident );
1409  }
1410 
1411  // No real reading was done:
1412  return 0;
1413  }
1414 
1415  // Loop over all input object managers, and force them to load their
1416  // content:
1417  ::Int_t result = 0;
1418  if( m_auxMode == kAthenaAccess ) {
1419  // In kAthenaAccess mode we need to use getInputObject(...) to load
1420  // all the input objects correctly.
1421  for( auto& inObj : m_inputObjects ) {
1422  static const std::string dynStorePostfix = "Aux.Dynamic";
1423  if( inObj.first.find( dynStorePostfix ) ==
1424  ( inObj.first.size() - dynStorePostfix.size() ) ) {
1425  // Ignore the dynamic store objects. They get loaded through
1426  // their parents.
1427  } else {
1428  // Load the objects and their auxiliary stores through the
1429  // getInputObject(...) function, which takes care of correctly
1430  // setting them up. The type is irrelevant here. We don't
1431  // really care about the exact type of the objects.
1432  getInputObject( inObj.first, typeid( int ), kTRUE, kFALSE );
1433  }
1434  }
1435  } else {
1436  // In a "reasonable" access mode, we do something very simple:
1437  for( auto& inObj : m_inputObjects ) {
1438  result += inObj.second->getEntry( getall );
1439  }
1440  }
1441 
1442  // Notify the listeners that a new event was loaded:
1443  const TIncident incident( IncidentType::BeginEvent );
1444  Listener_t::iterator l_itr = m_listeners.begin();
1445  Listener_t::iterator l_end = m_listeners.end();
1446  for( ; l_itr != l_end; ++l_itr ) {
1447  ( *l_itr )->handle( incident );
1448  }
1449 
1450  // Return the number of bytes read:
1451  return result;
1452  }
1453 
1463  ::Long64_t TEvent::getFiles() const {
1464 
1465  if( m_inChain ) {
1466  return m_inChain->GetListOfFiles()->GetEntries();
1467  } else if( m_inTree || m_inTreeMissing ) {
1468  return 1;
1469  } else {
1470  return 0;
1471  }
1472  }
1473 
1483  ::Int_t TEvent::getFile( ::Long64_t file, ::Int_t getall ) {
1484 
1485  // Check if the file number is valid:
1486  if( ( file < 0 ) || ( file >= getFiles() ) ) {
1487  ::Error( "xAOD::TEvent::getFile",
1488  XAOD_MESSAGE( "Function called with invalid file number "
1489  "(%i)" ), static_cast< int >( file ) );
1490  return -1;
1491  }
1492 
1493  // If we are not reading a TChain, return at this point. As the one and
1494  // only file is open already...
1495  if( ! m_inChain ) {
1496  return 0;
1497  }
1498 
1499  // Trigger the "scanning" of the input files, so the TChain would know
1500  // how many entries are in the various files.
1501  getEntries();
1502 
1503  // Calculate which entry/event we need to load:
1504  ::Long64_t entry = 0;
1505  for( ::Long64_t i = 0; i < file; ++i ) {
1506  entry += m_inChain->GetTreeOffset()[ i ];
1507  }
1508 
1509  // Load this entry using the regular event opening function:
1510  return getEntry( entry, getall );
1511  }
1512 
1519  ::Int_t TEvent::fill() {
1520 
1521  // A little sanity check:
1522  if( ! m_outTree ) {
1523  ::Error( "xAOD::TEvent::fill",
1524  XAOD_MESSAGE( "Object not connected to an output file!" ) );
1525  return 0;
1526  }
1527 
1528  // Make sure that all objects have been read in. The 99 as the value
1529  // has a special meaning for TAuxStore. With this value it doesn't
1530  // delete its transient (decoration) variables. Otherwise it does.
1531  // (As it's supposed to, when moving to a new event.)
1532  if( m_inChain ) {
1533  if (getEntry( m_inChain->GetReadEntry(), 99 ) < 0) {
1534  ::Error( "xAOD::TEvent::fill",
1535  XAOD_MESSAGE( "getEntry failed!" ) );
1536  return 0;
1537  }
1538  } else if( m_inTree ) {
1539  if (getEntry( m_entry, 99 ) < 0) {
1540  ::Error( "xAOD::TEvent::fill",
1541  XAOD_MESSAGE( "getEntry failed!" ) );
1542  return 0;
1543  }
1544  }
1545 
1546  // Prepare the objects for writing. Note that we need to iterate over a
1547  // copy of the m_outputObjects container. Since the putAux(...) function
1548  // called inside the loop may itself add elements to the m_outputObject
1549  // container.
1550  std::string unsetObjects;
1551  Object_t outputObjectsCopy = m_outputObjects;
1552  for( auto& itr : outputObjectsCopy ) {
1553  // Check that a new object was provided in the event:
1554  if( ! itr.second->create() ) {
1555  // We are now going to fail. But let's collect the names of
1556  // all the unset objects:
1557  if( unsetObjects.size() ) {
1558  unsetObjects.append( ", \"" + itr.first + "\"" );
1559  } else {
1560  unsetObjects.append( "\"" + itr.first + "\"" );
1561  }
1562  continue;
1563  }
1564  // Make sure that any dynamic auxiliary variables that
1565  // were added to the object after it was put into the event,
1566  // get added to the output:
1567  if( ! putAux( *m_outTree, *( itr.second ) ) ) {
1568  ::Error( "xAOD::TEvent::fill",
1569  XAOD_MESSAGE( "Failed to put dynamic auxiliary variables "
1570  "in the output for object \"%s\"" ),
1571  itr.first.c_str() );
1572  return 0;
1573  }
1574  }
1575 
1576  // Check if there were any unset objects:
1577  if( unsetObjects.size() ) {
1578  ::Error( "xAOD::TEvent::fill",
1579  XAOD_MESSAGE( "The following objects were not set in the "
1580  "current event: %s" ), unsetObjects.c_str() );
1581  return 0;
1582  }
1583 
1584  // Write the entry, and check the return value:
1585  const ::Int_t ret = m_outTree->Fill();
1586  if( ret <= 0 ) {
1587  ::Error( "xAOD::TEvent::fill",
1588  XAOD_MESSAGE( "Output tree filling failed with return "
1589  "value: %i" ), ret );
1590  }
1591 
1592  // Reset the object managers:
1593  Object_t::iterator ncitr = m_outputObjects.begin();
1594  Object_t::iterator ncend = m_outputObjects.end();
1595  for( ; ncitr != ncend; ++ncitr ) {
1596  ncitr->second->reset();
1597  }
1598 
1599  // Return the value:
1600  return ret;
1601  }
1602 
1615 
1616  // If we *are* reading an input file:
1617  if( m_inTree || m_inTreeMissing ) {
1618  return &m_inputEventFormat;
1619  }
1620 
1621  // If not, let's complain:
1622  ::Warning( "xAOD::TEvent::inputEventFormat",
1623  "No input file is connected at the moment" );
1624  return 0;
1625  }
1626 
1638 
1639  // If we *are* reading an input file:
1640  if( m_outTree ) {
1641  return m_outputEventFormat;
1642  }
1643 
1644  // If not, let's complain:
1645  ::Warning( "xAOD::TEvent::outputEventFormat",
1646  "No output file is connected at the moment" );
1647  return 0;
1648  }
1649 
1660  SG::sgkey_t TEvent::getHash( const std::string& key ) const {
1661 
1662  // For empty keys let's finish quickly:
1663  if( key == "" ) return 0;
1664 
1665  // If the key is used in the input file, let's use the same hash for
1666  // the output file as well:
1667  if( m_inputEventFormat.exists( key ) ) {
1668  return m_inputEventFormat.get( key )->hash();
1669  }
1670 
1671  // If it's a new key, make a new hash for it from scratch:
1672  return Utils::hash( key );
1673  }
1674 
1682  SG::sgkey_t TEvent::getKey( const void* obj ) const {
1683 
1684  // Make use of the getName function:
1685  return getHash( getName( obj ) );
1686  }
1687 
1695  const std::string& TEvent::getName( const void* obj ) const {
1696 
1697  // First look among the output objects:
1698  Object_t::const_iterator obj_itr = m_outputObjects.begin();
1699  Object_t::const_iterator obj_end = m_outputObjects.end();
1700  for( ; obj_itr != obj_end; ++obj_itr ) {
1701 
1702  // Check if this is our object:
1703  if( obj_itr->second->object() != obj ) continue;
1704 
1705  // If it is, let's return right away:
1706  return obj_itr->first;
1707  }
1708 
1709  // Now look among the input objects:
1710  obj_itr = m_inputObjects.begin();
1711  obj_end = m_inputObjects.end();
1712  for( ; obj_itr != obj_end; ++obj_itr ) {
1713 
1714  // Check if this is our object:
1715  if( obj_itr->second->object() != obj ) continue;
1716 
1717  // If it is, let's return:
1718  return obj_itr->first;
1719  }
1720 
1721  // If it's not there either, check if it's in an active TStore object:
1722  const TStore* store = TActiveStore::store();
1723  if( store && store->contains( obj ) ) {
1724  // Get the name from the store then:
1725  return store->getName( obj );
1726  }
1727 
1728  // We didn't find the object in the event...
1729  ::Warning( "xAOD::TEvent::getName",
1730  "Didn't find object with pointer %p in the event",
1731  obj );
1732  static const std::string dummy;
1733  return dummy;
1734  }
1735 
1736  void TEvent::getNames(const std::string& targetClassName,
1737  std::vector<std::string>& vkeys,
1738  bool metadata) const {
1739  // The results go in here
1740  std::set<std::string> keys;
1741 
1742  // Get list of branches from
1743  // the input metadata tree or input tree
1744  std::vector<TObjArray*> fullListOfBranches = {};
1745  if (metadata){
1746  if (m_inMetaTree){
1747  // No friend tree expected for metadata tree
1748  // Only add the list of branches of the metadata tree
1749  ::Info("xAOD::TEvent::getNames", "scanning input objects");
1750  fullListOfBranches.push_back(m_inMetaTree->GetListOfBranches());
1751  }
1752  }
1753  else {
1754  if (m_inTree){
1755  ::Info("xAOD::TEvent::getNames", "scanning input objects");
1756  // Add the list of branches of the main tree
1757  fullListOfBranches.push_back(m_inTree->GetListOfBranches());
1758  // If input tree has friend trees
1759  // add as well the list of friend tree branches
1760  if (m_inTree->GetListOfFriends()){
1761  // Get the list of friends
1762  TList *fList = m_inTree->GetListOfFriends();
1763  // Loop over friend elements
1764  for (TObject * feObj : *fList){
1765  if (feObj){
1766  // Get corresponding friend tree
1767  auto * pElement = dynamic_cast<TFriendElement*>(feObj);
1768  if (not pElement) continue;
1769  TTree *friendTree = pElement->GetTree();
1770  // Add list of branches of the friend tree
1771  fullListOfBranches.push_back(friendTree->GetListOfBranches());
1772  }
1773  }
1774  }
1775  }
1776  }
1777 
1778  // Loop over all list of branches (if any)
1779  for (const TObjArray * in : fullListOfBranches){
1780  // Loop over all branches inside the current list of branches
1781  for ( Int_t index = 0; index < in->GetEntriesFast(); ++index ) {
1782  const TObject * obj = in->At(index);
1783  if ( ! obj ) continue;
1784  const TBranch * element = dynamic_cast<const TBranch*>(obj);
1785  if (!element) {
1786  ::Error("xAOD::TEvent::getNames", "Failure inspecting input objects");
1787  break;
1788  }
1789  std::string objClassName = element->GetClassName();
1790  std::string key = obj->GetName();
1791  ::Info("xAOD::TEvent::getNames",
1792  "Inspecting %s / %s",
1793  objClassName.c_str(), key.c_str());
1794  if (objClassName == targetClassName) {
1795  ::Info("xAOD::TEvent::getNames",
1796  "Matched %s to key %s",
1797  targetClassName.c_str(), key.c_str());
1798  keys.insert(key);
1799  }
1800  }
1801  }
1802 
1803  const Object_t& inAux = ( metadata ?
1805 
1806  ::Info("xAOD::TEvent::getNames",
1807  "scanning input Aux objects for %s", targetClassName.c_str());
1808  for( const auto& object : inAux ) {
1809  // All metadata objects should be held by TObjectManager objects.
1810  // Anything else is an error.
1811  TObjectManager* mgr = dynamic_cast< TObjectManager* >( object.second );
1812  if ( ! mgr ) continue;
1813  const std::string& objClassName = mgr->holder()->getClass()->GetName();
1814  const std::string& key = object.first;
1815  ::Info("xAOD::TEvent::getNames",
1816  "Inspecting %s / %s",
1817  objClassName.c_str(), key.c_str());
1818  if (objClassName == targetClassName) {
1819  ::Info("xAOD::TEvent::getNames",
1820  "Matched %s to key %s",
1821  targetClassName.c_str(), key.c_str());
1822  keys.insert(key);
1823  }
1824  }
1825 
1826 
1827  // check output objects
1828  TTree *tree = ( metadata ? nullptr : m_outTree );
1829  if (tree) {
1830  const TObjArray * out = tree->GetListOfBranches();
1831  ::Info("xAOD::TEvent::getNames", "scanning output objects");
1832 
1833  for ( Int_t index = 0; index < out->GetEntriesFast(); ++index ) {
1834  const TObject * obj = out->At(index);
1835  if ( ! obj ) continue;
1836  const TBranch * element = dynamic_cast<const TBranch*>(obj);
1837  if (!element) {
1838  ::Error("xAOD::TEvent::getNames", "Failure inspecting input objects");
1839  break;
1840  }
1841  std::string objClassName = element->GetClassName();
1842  std::string key = obj->GetName();
1843  ::Info("xAOD::TEvent::getNames",
1844  "Inspecting %s / %s",
1845  objClassName.c_str(), key.c_str());
1846  if (objClassName == targetClassName) {
1847  ::Info("xAOD::TEvent::getNames",
1848  "Matched %s to key %s",
1849  targetClassName.c_str(), key.c_str());
1850  keys.insert(std::move(key));
1851  }
1852  }
1853  } else {
1854  ::Info("xAOD::TEvent::getNames", "no output tree connected");
1855  }
1856 
1857 
1858  const Object_t& outAux = ( metadata ?
1860 
1861  // Search though EventFormat for entries where class matches the provided
1862  // typeName
1863  ::Info("xAOD::TEvent::getNames",
1864  "scanning output Aux objects for %s", targetClassName.c_str());
1865  for( const auto& object : outAux ) {
1866  // All metadata objects should be held by TObjectManager objects.
1867  // Anything else is an error.
1868  TObjectManager* mgr = dynamic_cast< TObjectManager* >( object.second );
1869  if ( ! mgr ) continue;
1870  const std::string& objClassName = mgr->holder()->getClass()->GetName();
1871  const std::string& key = object.first;
1872  ::Info("xAOD::TEvent::getNames",
1873  "Inspecting %s / %s",
1874  objClassName.c_str(), key.c_str());
1875  if (objClassName == targetClassName) {
1876  ::Info("xAOD::TEvent::getNames",
1877  "Matched %s to key %s",
1878  targetClassName.c_str(), key.c_str());
1879  keys.insert(key);
1880  }
1881  }
1882 
1883  vkeys.insert(vkeys.end(), keys.begin(), keys.end());
1884  }
1885 
1893  const std::string& TEvent::getName( SG::sgkey_t hash ) const {
1894 
1895  // If the branch is known from the input:
1896  if( m_inputEventFormat.exists( hash ) ) {
1897  return m_inputEventFormat.get( hash )->branchName();
1898  }
1899 
1900  // If the branch is known on the output:
1901  if( m_outputEventFormat &&
1903  return m_outputEventFormat->get( hash )->branchName();
1904  }
1905 
1906  // If this is an object in the active store:
1907  const TStore* store = TActiveStore::store();
1908  if( store && store->contains( hash ) ) {
1909  return store->getName( hash );
1910  }
1911 
1912  // If it is unknown:
1913  static const std::string dummy;
1914  return dummy;
1915  }
1916 
1928  const std::type_info& ti ) {
1929 
1930  // Get a string name for this key:
1931  const std::string& name = getName( key );
1932  if( ! name.length() ) {
1933  return 0;
1934  }
1935 
1936  // Forward the call to the function using an std::string key:
1937  return getOutputObject( name, ti );
1938  }
1939 
1952  const std::type_info& ti,
1953  bool silent ) {
1954 
1955  // Get a string name for this key:
1956  const std::string& name = getName( key );
1957  if( ( ! name.length() ) && ( ! silent ) ) {
1958  Warning( "xAOD::TEvent::getInputObject",
1959  "Key 0x%08x unknown", key );
1960  return 0;
1961  }
1962 
1963  // Forward the call to the function using an std::string key:
1964  return getInputObject( name, ti, silent );
1965  }
1966 
1975 
1976  // If we're dealing with an empty input file, stop here:
1977  if( m_inTreeMissing ) {
1978  return StatusCode::SUCCESS;
1979  }
1980 
1981  // A little sanity check:
1982  if( ! m_inTree ) {
1983  ::Error( "xAOD::TEvent::initStats",
1984  XAOD_MESSAGE( "Function called on an uninitialised "
1985  "object" ) );
1986  return StatusCode::FAILURE;
1987  }
1988 
1989  // Reset the number of input branches information:
1991 
1992  // Loop over the EventFormat information
1995  for( ; itr != end; ++itr ) {
1996 
1997  // Get the name of the branch in question:
1998  const std::string& branchName = itr->second.branchName();
1999 
2000  // If it's an auxiliary container, scan it using TAuxStore:
2001  if( branchName.find( "Aux." ) != std::string::npos ) {
2002 
2003  // But first decide whether it describes a container, or just
2004  // a single object. Since the file may have been written in
2005  // kBranchAccess mode, it's not necessarily a good idea to check
2006  // the type of the auxiliary class. So let's check the interface
2007  // class instead.
2008  //
2009  // Get the name of the interface object/container:
2010  const std::string intName =
2011  branchName.substr( 0, branchName.size() - 4 );
2012  if( ! m_inputEventFormat.exists( intName ) ) {
2013  // When this happens, it may still be that both the interface and
2014  // the auxiliary container is missing from the file. As we didn't
2015  // check yet whether the auxiliary container is in place or not.
2016  // So, before printing a warning, let's check for this.
2017  // Unfortunately the check is pretty expensive, but this should
2018  // not be performance critical code after all...
2019  ::Bool_t auxFound = kFALSE;
2020  const std::string dynName = Utils::dynBranchPrefix( branchName );
2021 
2022  std::vector<TObjArray*> fullListOfBranches = {};
2023  // Add the list of branches of the main tree
2024  fullListOfBranches.push_back(m_inTree->GetListOfBranches());
2025  // If input tree has friend trees
2026  // add as well the list of friend tree branches
2027  if (m_inTree->GetListOfFriends()){
2028  // Get the list of friends
2029  TList *fList = m_inTree->GetListOfFriends();
2030  // Loop over friend elements
2031  for (TObject * feObj : *fList){
2032  if (feObj){
2033  // Get corresponding friend tree
2034  auto * pElement = dynamic_cast<TFriendElement*>(feObj);
2035  if (not pElement) continue;
2036  TTree *friendTree = pElement->GetTree();
2037  // Add list of branches of the friend tree
2038  fullListOfBranches.push_back(friendTree->GetListOfBranches());
2039  }
2040  }
2041  }
2042 
2043  for (TObjArray* branches : fullListOfBranches){
2044  for( Int_t i = 0; i < branches->GetEntriesFast(); ++i ){
2045  if (!branches->At( i )) continue ;
2046 
2047  const TString name( branches->At( i )->GetName() );
2048  if( name.BeginsWith( branchName ) ||
2049  name.BeginsWith( dynName ) ) {
2050  auxFound = kTRUE;
2051  break;
2052  }
2053  }
2054  }
2055  if( auxFound ) {
2056  ::Warning( "xAOD::TEvent::initStats",
2057  "Couldn't find interface object/container "
2058  "\"%s\" belonging to branch \"%s\"",
2059  intName.c_str(), branchName.c_str() );
2060  }
2061  continue;
2062  }
2063 
2064  // Get the type of the interface:
2065  const EventFormatElement* el = m_inputEventFormat.get( intName );
2066  ::TClass* cl = ::TClass::GetClass( el->className().c_str() );
2067  if( ( ! cl ) || ( ! cl->IsLoaded() ) ) {
2068  ::Warning( "xAOD::TEvent::initStats",
2069  "Couldn't find dictionary for type \"%s\"",
2070  el->className().c_str() );
2071  continue;
2072  }
2073 
2074  // Get the dictionary for the DataVector base class:
2075  static const std::type_info& baseTi = typeid( SG::AuxVectorBase );
2076  static const std::string baseName =
2077  SG::normalizedTypeinfoName( baseTi );
2078  static ::TClass* const baseCl = ::TClass::GetClass( baseName.c_str() );
2079  if( ! baseCl ) {
2080  ::Error( "xAOD::TEvent::initStats",
2081  XAOD_MESSAGE( "Couldn't get dictionary for type "
2082  "\"%s\"" ), baseName.c_str() );
2083  return StatusCode::FAILURE;
2084  }
2085 
2086  // The type of the auxiliary store is finally deduced from the
2087  // inheritance of the interface container.
2089  ( cl->InheritsFrom( baseCl ) ? TAuxStore::EStructMode::kContainerStore :
2091 
2092  // Scan the branches using a temporary TAuxStore instance:
2093  static constexpr bool TOP_STORE = true;
2094  TAuxStore temp( branchName, TOP_STORE, mode );
2095  static constexpr bool PRINT_WARNINGS = false;
2096  RETURN_CHECK( "xAOD::TEvent::initStats",
2097  temp.readFrom( *m_inTree, PRINT_WARNINGS ) );
2098 
2099  // Conveninence variable:
2101 
2102  // Teach the cache about all the branches:
2103  for (SG::auxid_t id : temp.getAuxIDs()) {
2104  stats.branch(branchName, id);
2105  }
2106 
2107  // Increment the number of known branches:
2108  stats.setBranchNum(stats.branchNum() + temp.getAuxIDs().size());
2109  }
2110  // If it's an interface container:
2111  else {
2112  // Try to access the branch:
2113  const ::TBranch* container =
2114  m_inTree->GetBranch( branchName.c_str() );
2115  // If it exists, let's remember it:
2116  if( container ) {
2117  IOStats::instance().stats().container( branchName );
2118  }
2119  }
2120  }
2121 
2122  // Return gracefully:
2123  return StatusCode::SUCCESS;
2124  }
2125 
2138  void* TEvent::getOutputObject( const std::string& key,
2139  const std::type_info& ti,
2140  ::Bool_t metadata ) const {
2141 
2142  // Select which object container to use:
2143  const Object_t& objects = ( metadata ?
2145 
2146  // Check if the object can be found:
2147  Object_t::const_iterator itr = objects.find( key );
2148  if( itr == objects.end() ) {
2149  // Do the following only for event data:
2150  if( ! metadata ) {
2151  // It's not in the event. Let's check if we find it in an active
2152  // TStore object...
2154  if( ( ! store ) || ( ! store->contains( key, ti ) ) ||
2155  store->isConst( key, ti ) ) {
2156  // Nope, not there either...
2157  return 0;
2158  }
2159  // Let's return the object from the TStore:
2160  void* result = store->getObject( key, ti );
2161  return result;
2162  } else {
2163  // For metadata we don't use external resources.
2164  return 0;
2165  }
2166  }
2167 
2168  // If the object is not set in this event yet, we can't continue:
2169  if( ! itr->second->isSet() ) {
2170  return 0;
2171  }
2172 
2173  // If it does exist, check if it's the right kind of object:
2174  TObjectManager* mgr =
2175  dynamic_cast< TObjectManager* >( itr->second );
2176  if( ! mgr ) {
2177  ::Error( "xAOD::TEvent::getOutputObject",
2178  XAOD_MESSAGE( "Object of wrong type found for key \"%s\"" ),
2179  key.c_str() );
2180  return 0;
2181  }
2182 
2183  // Ask the holder object for the object of this type:
2184  void* result = mgr->holder()->getAs( ti );
2185  if( ! result ) {
2186  ::Warning( "xAOD::TEvent::getOutputObject",
2187  "Couldn't retrieve object as \"%s\"",
2188  Utils::getTypeName( ti ).c_str() );
2189  return 0;
2190  }
2191 
2192  // Return the object:
2193  return result;
2194  }
2195 
2208  const void* TEvent::getInputObject( const std::string& key,
2209  const std::type_info& ti,
2210  ::Bool_t silent,
2211  ::Bool_t metadata ) {
2212 
2213  // Check if a name remapping should be applied or not:
2214  std::string keyToUse = key;
2215  auto remap_itr = m_nameRemapping.find( key );
2216  if( ( remap_itr != m_nameRemapping.end() ) &&
2217  ( ! m_inputEventFormat.exists( key ) ) &&
2218  m_inputEventFormat.exists( remap_itr->second ) ) {
2219  keyToUse = remap_itr->second;
2220  }
2221 
2222  // The following catches the cases when we ask for a transient
2223  // ConstDataVector object to be returned as "const DataVector".
2225  if( store && store->contains( keyToUse, ti ) &&
2226  store->isConst( keyToUse, ti ) ) {
2227  const void* result = store->getConstObject( keyToUse, ti );
2228  return result;
2229  }
2230 
2231  // A sanity check before checking for an object from the input file:
2232  if( ( ( ! m_inTree ) || ( m_entry < 0 ) ) &&
2233  ( ! metadata ) ) {
2234  return 0;
2235  }
2236  if( ( ! m_inMetaTree ) && metadata ) {
2237  return 0;
2238  }
2239 
2240  // Make sure that the requested branch is connected to:
2241  if( metadata ) {
2242  if( ! connectMetaBranch( keyToUse, silent ).isSuccess() ) {
2243  return 0;
2244  }
2245  } else {
2246  if( ! connectBranch( keyToUse, silent ).isSuccess() ) {
2247  return 0;
2248  }
2249  }
2250 
2251  // Select which object container to use:
2252  Object_t& objects = ( metadata ?
2254 
2255  // Access the object's manager:
2256  Object_t::iterator itr = objects.find( keyToUse );
2257  if( itr == objects.end() ) {
2258  ::Fatal( "xAOD::TEvent::getInputObject",
2259  XAOD_MESSAGE( "There is an internal logic error in the "
2260  "code..." ) );
2261  return 0;
2262  }
2263 
2264  // This has to be an ObjectManager object:
2265  TObjectManager* mgr =
2266  dynamic_cast< TObjectManager* >( itr->second );
2267  if( ! mgr ) {
2268  if( key == keyToUse ) {
2269  ::Error( "xAOD::TEvent::getInputObject",
2270  XAOD_MESSAGE( "Object of wrong type found for key "
2271  "\"%s\"" ),
2272  key.c_str() );
2273  } else {
2274  ::Error( "xAOD::TEvent::getInputObject",
2275  XAOD_MESSAGE( "Object of wrong type found for key "
2276  "\"%s\"/\"%s\"" ), key.c_str(),
2277  keyToUse.c_str() );
2278  }
2279  return 0;
2280  }
2281 
2282  // Make sure that the current entry is loaded for event data objects:
2283  if( ! metadata ) {
2284  if( mgr->getEntry() ) {
2285  // Connect the auxiliary store to objects needing it. This call also
2286  // takes care of updating the dynamic store of auxiliary containers,
2287  // when they are getting accessed directly.
2288  if( ! setAuxStore( *mgr ).isSuccess() ) {
2289  ::Error( "xAOD::TEvent::getInputObject",
2290  XAOD_MESSAGE( "Failed to set the auxiliary store for "
2291  "%s/%s" ),
2292  mgr->holder()->getClass()->GetName(),
2293  keyToUse.c_str() );
2294  return 0;
2295  }
2296  }
2297  }
2298 
2299  // Ask the holder object for the object of this type:
2300  const void* result = mgr->holder()->getAsConst( ti, silent );
2301  if( ! result ) {
2302  if( ! silent ) {
2303  ::Warning( "xAOD::TEvent::getInputObject",
2304  "Could not retrieve object with key \"%s\" "
2305  "as \"%s\"", keyToUse.c_str(),
2306  Utils::getTypeName( ti ).c_str() );
2307  }
2308  return 0;
2309  }
2310 
2311  // We succeeded:
2312  return result;
2313  }
2314 
2333  StatusCode TEvent::record( void* obj, const std::string& typeName,
2334  const std::string& key,
2335  ::Int_t basketSize, ::Int_t splitLevel,
2336  ::Bool_t overwrite, ::Bool_t metadata,
2337  ::Bool_t isOwner ) {
2338 
2339  // Check if we have an output tree when writing an event:
2340  if( ! m_outTree && ! metadata ) {
2341  ::Error( "xAOD::TEvent::record",
2342  XAOD_MESSAGE( "No output tree defined. Did you forget to "
2343  "call writeTo(...)?" ) );
2344  return StatusCode::FAILURE;
2345  }
2346  assert( m_outputEventFormat != 0 );
2347 
2348  // If this is metadata, just take ownership of it. The object will only
2349  // be recorded into the output file when calling finishWritingTo(...).
2350  if( metadata ) {
2351  // Check whether we already have such an object:
2352  if( ( ! overwrite ) &&
2353  ( m_outputMetaObjects.find( key ) !=
2354  m_outputMetaObjects.end() ) ) {
2355  ::Error( "xAOD::TEvent::record",
2356  XAOD_MESSAGE( "Meta-object %s/%s already recorded" ),
2357  typeName.c_str(), key.c_str() );
2358  return StatusCode::FAILURE;
2359  }
2360  // Check if we have a dictionary for this object:
2361  TClass* cl = TClass::GetClass( typeName.c_str() );
2362  if( ! cl ) {
2363  ::Error( "xAOD::TEvent::record",
2364  XAOD_MESSAGE( "Didn't find dictionary for type: %s" ),
2365  typeName.c_str() );
2366  return StatusCode::FAILURE;
2367  }
2368  // Let's create a holder for the object:
2369  THolder* hldr = new THolder( obj, cl, isOwner );
2370  TObjectManager* mgr =
2371  new TObjectManager( 0, hldr, m_auxMode == kAthenaAccess );
2373  // We're done. The rest will be done later on.
2374  return StatusCode::SUCCESS;
2375  }
2376 
2377  // Check if we accessed this object on the input. If yes, then this
2378  // key may not be used for recording.
2379  if( ( ! overwrite ) &&
2380  ( m_inputObjects.find( key ) != m_inputObjects.end() ) ) {
2381  ::Error( "xAOD::TEvent::record",
2382  XAOD_MESSAGE( "Object %s/%s already accessed from the input, "
2383  "can't be overwritten in memory" ),
2384  typeName.c_str(), key.c_str() );
2385  return StatusCode::FAILURE;
2386  }
2387 
2388  // Override the default 0 split level with a split level of 1 for
2389  // auxiliary container objects.
2390  if( ( splitLevel == 0 ) &&
2391  ( key.find( "Aux." ) == ( key.size() - 4 ) ) ) {
2392  splitLevel = 1;
2393  }
2394 
2395  // Check if we need to add it to the event record:
2396  Object_t::iterator vitr = m_outputObjects.find( key );
2397  if( vitr == m_outputObjects.end() ) {
2398 
2399  // Check if we have a dictionary for this object:
2400  TClass* cl = TClass::GetClass( typeName.c_str() );
2401  if( ! cl ) {
2402  ::Error( "xAOD::TEvent::record",
2403  XAOD_MESSAGE( "Didn't find dictionary for type: %s" ),
2404  typeName.c_str() );
2405  return StatusCode::FAILURE;
2406  }
2407 
2408  // Check if this is a new object "type" or not:
2409  if( ! m_outputEventFormat->exists( key ) ) {
2411  "", getHash( key ) ) );
2412  }
2413 
2414  // Let's create a holder for the object:
2415  THolder* hldr = new THolder( obj, cl, isOwner );
2416  TObjectManager* mgr =
2417  new TObjectManager( 0, hldr, m_auxMode == kAthenaAccess );
2418  m_outputObjects[ key ] = mgr;
2419 
2420  // ... and let's add it to the output TTree:
2421  *( mgr->branchPtr() ) =
2422  m_outTree->Branch( key.c_str(), cl->GetName(),
2423  hldr->getPtr(), basketSize, splitLevel );
2424  if( ! mgr->branch() ) {
2425  ::Error( "xAOD::TEvent::record",
2426  XAOD_MESSAGE( "Failed to create branch \"%s\" out of "
2427  "type \"%s\"" ),
2428  key.c_str(), cl->GetName() );
2429  // Clean up:
2430  hldr->setOwner( kFALSE );
2431  delete mgr;
2432  return StatusCode::FAILURE;
2433  }
2434 
2435  // Set up the saving of all the dynamic auxiliary properties
2436  // of the object if it has any:
2437  RETURN_CHECK( "xAOD::TEvent::record",
2438  putAux( *m_outTree, *mgr, basketSize, splitLevel,
2439  kFALSE ) );
2440 
2441  // Return at this point, as we don't want to run the rest of
2442  // the function's code:
2443  return StatusCode::SUCCESS;
2444  }
2445 
2446  // Access the object manager:
2447  TObjectManager* omgr = dynamic_cast< TObjectManager* >( vitr->second );
2448  if( ! omgr ) {
2449  ::Error( "xAOD::TEvent::record",
2450  XAOD_MESSAGE( "Manager object of the wrong type "
2451  "encountered" ) );
2452  return StatusCode::FAILURE;
2453  }
2454 
2455  // Check that the type of the object matches that of the previous
2456  // object:
2457  if( typeName != omgr->holder()->getClass()->GetName() ) {
2458  // This may still be, when the ROOT dictionary name differs from the
2459  // "simple type name" known to C++. So let's get the ROOT name of the
2460  // new type:
2461  TClass* cl = TClass::GetClass( typeName.c_str() );
2462  if( ( ! cl ) || ::strcmp( cl->GetName(),
2463  omgr->holder()->getClass()->GetName() ) ) {
2464  ::Error( "xAOD::TEvent::record",
2465  XAOD_MESSAGE( "For output key \"%s\" the previous type "
2466  "was \"%s\", the newly requested type is "
2467  "\"%s\"" ),
2468  key.c_str(), omgr->holder()->getClass()->GetName(),
2469  typeName.c_str() );
2470  return StatusCode::FAILURE;
2471  }
2472  }
2473 
2474  // Replace the managed object:
2475  omgr->setObject( obj );
2476 
2477  // Replace the auxiliary objects:
2478  return putAux( *m_outTree, *omgr, basketSize, splitLevel, kFALSE );
2479  }
2480 
2497  ::Int_t /*basketSize*/, ::Int_t /*splitLevel*/,
2498  ::Bool_t ownsStore ) {
2499 
2500  // Check if we have an output tree:
2501  if( ! m_outTree ) {
2502  ::Error( "xAOD::TEvent::record",
2503  XAOD_MESSAGE( "No output tree defined. Did you forget to "
2504  "call writeTo(...)?" ) );
2505  return StatusCode::FAILURE;
2506  }
2507 
2508  // Check if we have a filtering rule for this key:
2509  const std::set< std::string >* filter = 0;
2510  auto filter_itr = m_auxItemList.find( key );
2511  if( filter_itr != m_auxItemList.end() ) {
2512  filter = &( filter_itr->second );
2513  }
2514 
2515  // Check if we need to add it to the event record:
2516  Object_t::iterator vitr = m_outputObjects.find( key );
2517  if( vitr == m_outputObjects.end() ) {
2518 
2519  // Configure the object for variable filtering:
2520  if( filter ) {
2521  store->selectAux( *filter );
2522  }
2523  // Tell the object where to write its contents:
2524  RETURN_CHECK( "xAOD::TEvent::record", store->writeTo( *m_outTree ) );
2525  // Record it to the output list:
2526  TAuxManager* mgr = new TAuxManager( store, ownsStore );
2527  m_outputObjects[ key ] = mgr;
2528 
2529  // We're done:
2530  return StatusCode::SUCCESS;
2531  }
2532 
2533  // Check if the output has the right store:
2534  if( vitr->second->object() == store ) {
2535  // We're done already:
2536  return StatusCode::SUCCESS;
2537  }
2538 
2539  // If not, update the output manager. This can happen when we copy
2540  // objects from the input to the output files, and we process
2541  // multiple input files.
2542 
2543  // Check if the output manager is of the right type:
2544  TAuxManager* mgr = dynamic_cast< TAuxManager* >( vitr->second );
2545  if( ! mgr ) {
2546  ::Error( "xAOD::TEvent::record",
2547  XAOD_MESSAGE( "Output object with key %s already exists, "
2548  "and is not of type TAuxStore" ),
2549  key.c_str() );
2550  return StatusCode::FAILURE;
2551  }
2552 
2553  // Configure the object for variable filtering:
2554  if( filter ) {
2555  store->selectAux( *filter );
2556  }
2557 
2558  // Connect the auxiliary store to the output tree:
2559  RETURN_CHECK( "xAOD::TEvent::record", store->writeTo( *m_outTree ) );
2560 
2561  // Update the manager:
2562  mgr->setObject( store );
2563 
2564  // Return gracefully:
2565  return StatusCode::SUCCESS;
2566  }
2567 
2586  StatusCode TEvent::connectBranch( const std::string& key,
2587  ::Bool_t silent ) {
2588 
2589  // A little sanity check:
2590  if( ! m_inTree ) {
2591  ::Error( "xAOD::TEvent::connectBranch",
2592  XAOD_MESSAGE( "Function called on un-initialised object" ) );
2593  return StatusCode::FAILURE;
2594  }
2595 
2596  // Increment the access counter on this container:
2598 
2599  // Check if the branch is already connected:
2600  if( m_inputObjects.find( key ) != m_inputObjects.end() ) {
2601  return StatusCode::SUCCESS;
2602  }
2603  // Check if it was already found to be missing.
2604  if( m_inputMissingObjects.find( key ) != m_inputMissingObjects.end() ) {
2605  if( ! silent ) {
2606  ::Warning( "xAOD::TEvent::connectBranch",
2607  "Branch \"%s\" not available on input",
2608  key.c_str() );
2609  }
2610  return StatusCode::RECOVERABLE;
2611  }
2612 
2613  // Check if we have metadata about this branch:
2614  const xAOD::EventFormatElement* ef = 0;
2615  if( ! m_inputEventFormat.exists( key ) ) {
2616  if( ! silent ) {
2617  ::Warning( "xAOD::TEvent::connectBranch",
2618  "No metadata available for branch: %s",
2619  key.c_str() );
2620  }
2621  } else {
2623  }
2624 
2625  // Check if the branch exists in our input tree:
2626  ::TBranch* br =
2627  m_inTree->GetBranch( key.c_str() );
2628  if( ! br ) {
2629  if( ! silent ) {
2630  ::Warning( "xAOD::TEvent::connectBranch",
2631  "Branch \"%s\" not available on input",
2632  key.c_str() );
2633  }
2634  m_inputMissingObjects.insert( key );
2635  return StatusCode::RECOVERABLE;
2636  }
2637 
2638  // Make sure that it's not in "MakeClass mode":
2639  br->SetMakeClass( 0 );
2640 
2641  // Decide about the type that we need to use for the reading of this
2642  // branch:
2643  std::string className = br->GetClassName();
2644  if( className == "" ) {
2645  if( ef ) {
2646  // This is a fairly weird situation, but let's fall back to taking
2647  // the class name from the metadata object in this case.
2648  className = ef->className();
2649  } else {
2650  ::Error( "xAOD::TEvent::connectBranch",
2651  XAOD_MESSAGE( "Couldn't find an appropriate type with a "
2652  "dictionary for branch \"%s\"" ),
2653  key.c_str() );
2654  return StatusCode::FAILURE;
2655  }
2656  }
2657  ::TClass* realClass = ::TClass::GetClass( className.c_str() );
2658  if( ( ( ! realClass ) || ( ! realClass->IsLoaded() ) ) && ef ) {
2659  // We may need to do an actual schema evolution here, in which
2660  // case let's fall back on the class name coming from the metadata
2661  // object.
2662  className = ef->className();
2663  realClass = ::TClass::GetClass( className.c_str() );
2664  }
2665  if( ( ! realClass ) || ( ! realClass->IsLoaded() ) ) {
2666  // Now we're in trouble...
2667  ::Error( "xAOD::TEvent::connectBranch",
2668  XAOD_MESSAGE( "Couldn't find an appropriate type with a "
2669  "dictionary for branch \"%s\"" ),
2670  key.c_str() );
2671  return StatusCode::FAILURE;
2672  }
2673 
2674  // Make sure that the current object is the "active event":
2675  setActive();
2676 
2677  // The data type is always "other" for us:
2678  static const ::EDataType dataType = kOther_t;
2679 
2680  // Check if the output already has this object. If it does, let's
2681  // assume that we have been copying the object to the output. Which
2682  // means that we need to resume filling the same memory address that
2683  // the output holder points to.
2684  void* ptr = 0;
2685  Object_t::const_iterator out_itr = m_outputObjects.find( key );
2686  if( out_itr != m_outputObjects.end() ) {
2687  // It needs to be an object manager...
2688  TObjectManager* mgr =
2689  dynamic_cast< TObjectManager* >( out_itr->second );
2690  if( ! mgr ) {
2691  ::Error( "xAOD::TEvent::connectBranch",
2692  XAOD_MESSAGE( "Couldn't access output manager for: %s" ),
2693  key.c_str() );
2694  return StatusCode::FAILURE;
2695  }
2696  // Get the pointer out of it:
2697  ptr = mgr->holder()->get();
2698  }
2699 
2700  // If there is no output object, then let's create one ourselves.
2701  // This is the only way in which we can have the memory management of
2702  // THolder do the right thing with this object.
2703  if( ! ptr ) {
2704  ptr = realClass->New();
2705  }
2706 
2707  // Create the new manager object that will hold this EDM object:
2708  THolder* hldr = new THolder( ptr, realClass );
2709  TObjectManager* mgr =
2710  new TObjectManager( 0, hldr, ( m_auxMode == kAthenaAccess ) );
2711  m_inputObjects[ key ] = mgr;
2712 
2713  // One final check. If it's not an auxiliary store, then it must have
2714  // a split level of 0. Otherwise read rules may not work on it. Causing
2715  // *very* serious silent corruption in the data read, if we don't use
2716  // the "Athena read mode".
2717  if( ( m_auxMode != kAthenaAccess ) && ( br->GetSplitLevel() != 0 ) &&
2718  ( ! isAuxStore( *mgr ) ) ) {
2719  ::Error( "xAOD::TEvent::connectBranch",
2720  XAOD_MESSAGE( "Split level for branch \"%s\" is %i. "
2721  "This can only be read in kAthenaAccess mode." ),
2722  key.c_str(), br->GetSplitLevel() );
2723  // Clean up:
2724  *( hldr->getPtr() ) = 0;
2725  delete mgr;
2726  m_inputObjects.erase( key );
2727  return StatusCode::FAILURE;
2728  }
2729 
2730  // Now try to connect to the branch:
2731  const ::Int_t status = m_inTree->SetBranchAddress( key.c_str(),
2732  hldr->getPtr(),
2733  mgr->branchPtr(),
2734  realClass, dataType,
2735  kTRUE );
2736  if( status < 0 ) {
2737  ::Error( "xAOD::TEvent::connectBranch",
2738  XAOD_MESSAGE( "Couldn't connect variable of type \"%s\" to "
2739  "input branch \"%s\". Return code: %i" ),
2740  className.c_str(), key.c_str(), status );
2741  // Clean up:
2742  *( hldr->getPtr() ) = 0;
2743  delete mgr;
2744  m_inputObjects.erase( key );
2745  return StatusCode::FAILURE;
2746  }
2747 
2748  // If it's an auxiliary store object, set it up correctly:
2749  if( isAuxStore( *mgr ) ) {
2750  RETURN_CHECK( "xAOD::TEvent::connectBranch",
2752  }
2753 
2754  // Return here if the object can't have an auxiliary store:
2755  if( ! hasAuxStore( *mgr ) ) return StatusCode::SUCCESS;
2756 
2757  // If there may be an auxiliary object connected to this one,
2758  // connect that as well:
2759  return connectAux( key + "Aux.", isStandalone( *mgr ) );
2760  }
2761 
2771  ::Bool_t silent ) {
2772 
2773  // A little sanity check:
2774  if( ! m_inMetaTree ) {
2775  ::Error( "xAOD::TEvent::connectMetaBranch",
2776  XAOD_MESSAGE( "Function called on un-initialised object" ) );
2777  return StatusCode::FAILURE;
2778  }
2779 
2780  // Check if the branch is already connected:
2781  if( m_inputMetaObjects.find( key ) != m_inputMetaObjects.end() ) {
2782  return StatusCode::SUCCESS;
2783  }
2784 
2785  // Check if the branch exists in our metadata tree:
2786  ::TBranch* br = m_inMetaTree->GetBranch( key.c_str() );
2787  if( ! br ) {
2788  if( ! silent ) {
2789  ::Warning( "xAOD::TEvent::connectMetaBranch",
2790  "Branch \"%s\" not available on input",
2791  key.c_str() );
2792  }
2793  return StatusCode::RECOVERABLE;
2794  }
2795 
2796  // Check that we have an entry in the branch:
2797  if( ! br->GetEntries() ) {
2798  if( ! silent ) {
2799  ::Warning( "xAOD::TEvent::connectMetaBranch",
2800  "Branch \"%s\" doesn't hold any data",
2801  key.c_str() );
2802  }
2803  return StatusCode::RECOVERABLE;
2804  }
2805 
2806  // Make sure that it's not in "MakeClass mode":
2807  br->SetMakeClass( 0 );
2808 
2809  // Extract the type of the branch:
2810  ::TClass* cl = 0;
2811  ::EDataType dt = kOther_t;
2812  if( br->GetExpectedType( cl, dt ) || ( ! cl ) ) {
2813  ::Error( "xAOD::TEvent::connectMetaBranch",
2814  XAOD_MESSAGE( "Couldn't get the type for metadata "
2815  "branch %s" ), key.c_str() );
2816  return StatusCode::FAILURE;
2817  }
2818 
2819  // Create the object, and all of the managers around it:
2820  void* ptr = cl->New();
2821  THolder* hldr = new THolder( ptr, cl );
2822  TObjectManager* mgr =
2823  new TObjectManager( 0, hldr, m_auxMode == kAthenaAccess );
2824  m_inputMetaObjects[ key ] = mgr;
2825 
2826  // Now try to connect to the branch:
2827  const ::Int_t status = m_inMetaTree->SetBranchAddress( key.c_str(),
2828  hldr->getPtr(),
2829  mgr->branchPtr(),
2830  cl, dt,
2831  kTRUE );
2832  if( status < 0 ) {
2833  ::Error( "xAOD::TEvent::connectMetaBranch",
2834  XAOD_MESSAGE( "Couldn't connect variable of type \"%s\" to "
2835  "input branch \"%s\". Return code: %i" ),
2836  cl->GetName(), key.c_str(), status );
2837  // Clean up:
2838  *( hldr->getPtr() ) = 0;
2839  delete mgr;
2840  m_inputMetaObjects.erase( key );
2841  return StatusCode::FAILURE;
2842  }
2843 
2844  // Read in the object:
2845  if( mgr->getEntry() < 0 ) {
2846  ::Error( "xAOD::TEvent::connectMetaBranch",
2847  XAOD_MESSAGE( "Couldn't read in metadata object with key "
2848  "\"%s\"" ), key.c_str() );
2849  return StatusCode::FAILURE;
2850  }
2851 
2852  // If it's an auxiliary store object, set it up correctly:
2853  if( isAuxStore( *mgr ) ) {
2854  RETURN_CHECK( "xAOD::TEvent::connectBranch",
2856  }
2857 
2858  // Return here if the object can't have an auxiliary store:
2859  if( ! hasAuxStore( *mgr ) ) return StatusCode::SUCCESS;
2860 
2861  // If there may be an auxiliary object connected to this one,
2862  // connect that as well:
2863  RETURN_CHECK( "xAOD::TEvent::connectMetaBranch",
2864  connectMetaAux( key + "Aux.", isStandalone( *mgr ) ) );
2865 
2866  // And now connect the first object to its auxiliary store:
2867  RETURN_CHECK( "xAOD::TEvent::connectMetaBranch",
2868  setAuxStore( *mgr, kTRUE ) );
2869 
2870  // We succeeded:
2871  return StatusCode::SUCCESS;
2872  }
2873 
2884  StatusCode TEvent::connectAux( const std::string& prefix,
2885  ::Bool_t standalone ) {
2886 
2887  // A simple test...
2888  if( ! m_inTree ) {
2889  ::Error( "xAOD::TEvent::connectAux",
2890  XAOD_MESSAGE( "No input tree is available" ) );
2891  return StatusCode::FAILURE;
2892  }
2893 
2894  // Check if we know anything about this auxiliary object:
2895  if( ( ! m_inTree->GetBranch( prefix.c_str() ) ) &&
2897  // If not, then let's just return right away. Not having
2898  // an auxiliary object with this name is not an error per se.
2899  return StatusCode::SUCCESS;
2900  }
2901 
2902  // Check if the branch is already connected:
2903  if( m_inputObjects.find( prefix ) != m_inputObjects.end() ) {
2904  return StatusCode::SUCCESS;
2905  }
2906 
2907  // Do different things based on the "auxiliary mode" we are in:
2909 
2910  // In "class access mode" let's first connect the concrete auxiliary
2911  // object to the input:
2912  RETURN_CHECK( "xAOD::TEvent::connectAux", connectBranch( prefix ) );
2913 
2914  // Access the object's manager:
2915  Object_t::const_iterator mgr_itr = m_inputObjects.find( prefix );
2916  if( mgr_itr == m_inputObjects.end() ) {
2917  ::Fatal( "xAOD::TEvent::connectAux",
2918  XAOD_MESSAGE( "There's a logic error in the code" ) );
2919  }
2920  const TObjectManager* omgr =
2921  dynamic_cast< const TObjectManager* >( mgr_itr->second );
2922  if( ! omgr ) {
2923  ::Fatal( "xAOD::TEvent::connectAux",
2924  XAOD_MESSAGE( "There's a logic error in the code" ) );
2925  return StatusCode::FAILURE;
2926  }
2927 
2928  // Check if we can switch out the internal store of this object:
2929  static const TClass* const holderClass =
2930  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
2931  if( ! omgr->holder()->getClass()->InheritsFrom( holderClass ) ) {
2932  // Nope... So let's just end the journey here.
2933  return StatusCode::SUCCESS;
2934  }
2935 
2936  // Try to get the object as an IAuxStoreHolder:
2937  SG::IAuxStoreHolder* storeHolder =
2938  reinterpret_cast< SG::IAuxStoreHolder* >(
2939  omgr->holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
2940  if( ! storeHolder ) {
2941  ::Fatal( "xAOD::TEvent::connectAux",
2942  XAOD_MESSAGE( "There's a logic error in the code" ) );
2943  }
2944 
2945  // A sanity check to see whether the store's type is in sync with the
2946  // object's type that it will be connected to:
2947  if( ( standalone && ( storeHolder->getStoreType() !=
2949  ( ( ! standalone ) &&
2950  ( storeHolder->getStoreType() !=
2952  ::Error( "xAOD::TEvent::connectAux",
2953  XAOD_MESSAGE( "Requested store types inconsistent "
2954  "for: %s" ), prefix.c_str() );
2955  ::Error( "xAOD::TEvent::connectAux",
2956  XAOD_MESSAGE( "standalone = %s, getStoreType() = %i" ),
2957  ( standalone ? "kTRUE" : "kFALSE" ),
2958  static_cast< int >( storeHolder->getStoreType() ) );
2959  return StatusCode::FAILURE;
2960  }
2961 
2962  // Return gracefully:
2963  return StatusCode::SUCCESS;
2964 
2965  } else if( m_auxMode == kBranchAccess ) {
2966 
2967  // In "branch access mode" let's create a TAuxStore object, and let
2968  // that take care of the auxiliary store access:
2969  TAuxStore* store =
2970  new TAuxStore( prefix, kTRUE,
2973  // We're using this object to read from the input, it needs to be
2974  // locked:
2975  store->lock();
2976  TAuxManager* mgr = new TAuxManager( store );
2977  m_inputObjects[ prefix ] = mgr;
2978 
2979  // Now connect the object to the input tree:
2980  RETURN_CHECK( "xAOD::TEvent::connectAux",
2981  store->readFrom( *m_inTree ) );
2982 
2983  // Return gracefully:
2984  return StatusCode::SUCCESS;
2985  }
2986 
2987  // There was some problem:
2988  ::Error( "xAOD::TEvent::connectAux",
2989  XAOD_MESSAGE( "Unknown auxiliary access mode set (%i)" ),
2990  static_cast< int >( m_auxMode ) );
2991  return StatusCode::FAILURE;
2992  }
2993 
3004  ::Bool_t standalone ) {
3005 
3006  // Check if the branch is already connected:
3007  if( m_inputMetaObjects.find( prefix ) != m_inputMetaObjects.end() ) {
3008  return StatusCode::SUCCESS;
3009  }
3010 
3011  // A sanity check:
3012  if( ! m_inMetaTree ) {
3013  ::Fatal( "xAOD::TEvent::connectMetaAux",
3014  XAOD_MESSAGE( "Internal logic error detected" ) );
3015  return StatusCode::FAILURE;
3016  }
3017 
3018  // Do different things based on the "auxiliary mode" we are in:
3020 
3021  // In "class access mode" let's first connect the concrete auxiliary
3022  // object to the input:
3023  RETURN_CHECK( "xAOD::TEvent::connectMetaAux",
3025 
3026  // Access the object's manager:
3027  Object_t::const_iterator mgr_itr = m_inputMetaObjects.find( prefix );
3028  if( mgr_itr == m_inputMetaObjects.end() ) {
3029  ::Fatal( "xAOD::TEvent::connectMetaAux",
3030  XAOD_MESSAGE( "There's a logic error in the code" ) );
3031  }
3032  const TObjectManager* omgr =
3033  dynamic_cast< const TObjectManager* >( mgr_itr->second );
3034  if( ! omgr ) {
3035  ::Fatal( "xAOD::TEvent::connectMetaAux",
3036  XAOD_MESSAGE( "There's a logic error in the code" ) );
3037  return StatusCode::FAILURE;
3038  }
3039 
3040  // Check if we can switch out the internal store of this object:
3041  static const TClass* const holderClass =
3042  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
3043  if( ! omgr->holder()->getClass()->InheritsFrom( holderClass ) ) {
3044  // Nope... So let's just end the journey here.
3045  return StatusCode::SUCCESS;
3046  }
3047 
3048  // Try to get the object as an IAuxStoreHolder:
3049  SG::IAuxStoreHolder* storeHolder =
3050  reinterpret_cast< SG::IAuxStoreHolder* >(
3051  omgr->holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
3052  if( ! storeHolder ) {
3053  ::Fatal( "xAOD::TEvent::connectMetaAux",
3054  XAOD_MESSAGE( "There's a logic error in the code" ) );
3055  }
3056 
3057  // A sanity check to see whether the store's type is in sync with the
3058  // object's type that it will be connected to:
3059  if( ( standalone && ( storeHolder->getStoreType() !=
3061  ( ( ! standalone ) &&
3062  ( storeHolder->getStoreType() !=
3064  ::Error( "xAOD::TEvent::connectMetaAux",
3065  XAOD_MESSAGE( "Requested store types inconsistent" ) );
3066  ::Error( "xAOD::TEvent::connectMetaAux",
3067  XAOD_MESSAGE( "standalone = %s, getStoreType() = %i" ),
3068  ( standalone ? "kTRUE" : "kFALSE" ),
3069  static_cast< int >( storeHolder->getStoreType() ) );
3070  return StatusCode::FAILURE;
3071  }
3072 
3073  // Return gracefully:
3074  return StatusCode::SUCCESS;
3075 
3076  } else if( m_auxMode == kBranchAccess ) {
3077 
3078  // In "branch access mode" let's create a TAuxStore object, and let
3079  // that take care of the auxiliary store access:
3080  TAuxStore* store =
3081  new TAuxStore( prefix, kTRUE,
3084  // We use this object to read data from the input, it needs to be
3085  // locked:
3086  store->lock();
3087  TAuxManager* mgr = new TAuxManager( store );
3089 
3090  // Now connect the object to the input tree:
3091  RETURN_CHECK( "xAOD::TEvent::connectMetaAux",
3092  store->readFrom( *m_inMetaTree ) );
3093 
3094  // Tell the auxiliary store which entry to use:
3095  store->getEntry( 0 );
3096 
3097  // Return gracefully:
3098  return StatusCode::SUCCESS;
3099  }
3100 
3101  // There was some problem:
3102  ::Error( "xAOD::TEvent::connectMetaAux",
3103  XAOD_MESSAGE( "Unknown auxiliary access mode set (%i)" ),
3104  static_cast< int >( m_auxMode ) );
3105  return StatusCode::FAILURE;
3106  }
3107 
3117 
3118  // Check if we can call setName(...) on the object:
3119  ::TMethodCall setNameCall;
3120  // Don't use this code in Athena access mode. And just accept that access
3121  // monitoring is disabled in this case...
3122  if( m_auxMode != kAthenaAccess ) {
3123  setNameCall.InitWithPrototype( mgr.holder()->getClass(),
3124  "setName", "const char*" );
3125  if( setNameCall.IsValid() ) {
3126  // Yes, there is such a function. Let's call it with the branch
3127  // name:
3128  const ::TString params =
3129  ::TString::Format( "\"%s\"", mgr.branch()->GetName() );
3130  const char* charParams = params.Data();
3131  setNameCall.Execute( mgr.holder()->get(), charParams );
3132  } else {
3133  // This is weird. What sort of auxiliary container is this? :-/
3134  ::Warning( "xAOD::TEvent::setUpDynamicStore",
3135  "Couldn't find setName(...) function for container %s "
3136  " (type: %s)",
3137  mgr.branch()->GetName(),
3138  mgr.holder()->getClass()->GetName() );
3139  }
3140  }
3141 
3142  // Check if we can switch out the internal store of this object:
3143  static const TClass* const holderClass =
3144  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
3145  if( ! mgr.holder()->getClass()->InheritsFrom( holderClass ) ) {
3146  // Nope... So let's just end the journey here.
3147  return StatusCode::SUCCESS;
3148  }
3149 
3150  // Try to get the object as an IAuxStoreHolder:
3151  SG::IAuxStoreHolder* storeHolder =
3152  reinterpret_cast< SG::IAuxStoreHolder* >(
3153  mgr.holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
3154  if( ! storeHolder ) {
3155  ::Fatal( "xAOD::TEvent::setUpDynamicStore",
3156  XAOD_MESSAGE( "There's a logic error in the code" ) );
3157  return StatusCode::FAILURE;
3158  }
3159 
3160  // Create a TAuxStore instance that will read the dynamic variables
3161  // of this container. Notice that the TAuxManager doesn't own the
3162  // TAuxStore object. It will be owned by the SG::IAuxStoreHolder
3163  // object.
3164  TAuxStore* store =
3165  new TAuxStore( mgr.branch()->GetName(), kFALSE,
3166  ( storeHolder->getStoreType() ==
3170  // This object is used to read data from the input, it needs to be
3171  // locked:
3172  store->lock();
3173  TAuxManager* amgr = new TAuxManager( store, kFALSE );
3174  m_inputObjects[ std::string( mgr.branch()->GetName() ) +
3175  "Dynamic" ] = amgr;
3176  RETURN_CHECK( "xAOD::TEvent::setUpDynamicStore",
3177  store->readFrom( *tree ) );
3178  // Tell the auxiliary store which entry to use. This is essential for
3179  // metadata objects, and non-important for event data objects, which will
3180  // get a possibly different entry loaded in setAuxStore(...).
3181  store->getEntry( 0 );
3182 
3183  // Give this object to the store holder:
3184  storeHolder->setStore( store );
3185 
3186  // Return gracefully:
3187  return StatusCode::SUCCESS;
3188  }
3189 
3201  ::Bool_t metadata ) {
3202 
3203  // Check if we need to do anything:
3204  if( ( ! hasAuxStore( mgr ) ) && ( ! isAuxStore( mgr ) ) ) {
3205  return StatusCode::SUCCESS;
3206  }
3207 
3208  // Get the branch name of the object in question:
3209  const std::string key = mgr.branch()->GetName();
3210 
3211  // Select which object container to use:
3212  Object_t& objects = ( metadata ?
3214 
3215 
3216  // Look up the auxiliary object's manager:
3217  TVirtualManager* auxMgr = nullptr;
3218  std::string auxKey;
3219  if( isAuxStore( mgr ) ) {
3220  auxMgr = &mgr;
3221  auxKey = std::move(key);
3222  } else {
3223  auto itr = objects.find( key + "Aux." );
3224  if( itr == objects.end() ) {
3225  // Apparently there's no auxiliary object for this DV, so let's
3226  // give up:
3227  return StatusCode::SUCCESS;
3228  }
3229  auxMgr = itr->second;
3230  auxKey = key + "Aux.";
3231  }
3232 
3233  if( ! metadata ) {
3234  // Make sure the auxiliary object is up to date:
3235  ::Int_t readBytes = auxMgr->getEntry();
3236 
3237  // Check if there is a separate auxiliary object for the dynamic
3238  // variables:
3239  const std::string dynAuxKey = auxKey + "Dynamic";
3240  auto dynAuxMgr = objects.find( dynAuxKey );
3241 
3242  if( ( dynAuxMgr != objects.end() ) &&
3243  ( readBytes || ( m_auxMode == kAthenaAccess ) ||
3244  ( auxMgr == &mgr ) ) ) {
3245  // Do different things based on the access mode:
3246  if( m_auxMode != kAthenaAccess ) {
3247  // In "normal" access modes just tell the dynamic store object
3248  // to switch to a new event.
3249  dynAuxMgr->second->getEntry();
3250  } else {
3251  // In "Athena mode" this object has already been deleted when
3252  // the main auxiliary store object was switched to the new
3253  // event. So let's re-create it:
3254  xAOD::TObjectManager& auxMgrRef =
3255  dynamic_cast< xAOD::TObjectManager& >( *auxMgr );
3256  RETURN_CHECK( "xAOD::TEvent::setAuxStore",
3257  setUpDynamicStore( auxMgrRef,
3258  ( metadata ?
3259  m_inMetaTree :
3260  m_inTree ) ) );
3261  // Now tell the newly created dynamic store object which event
3262  // it should be looking at:
3263  auto dynAuxMgr = objects.find( dynAuxKey );
3264  if( dynAuxMgr == objects.end() ) {
3265  ::Error( "xAOD::TEvent::setAuxStore",
3266  XAOD_MESSAGE( "Internal logic error detected" ) );
3267  return StatusCode::FAILURE;
3268  }
3269  dynAuxMgr->second->getEntry();
3270  }
3271  }
3272  }
3273 
3274  // Stop here if we've set up an auxiliary store.
3275  if( auxMgr == &mgr ) {
3276  return StatusCode::SUCCESS;
3277  }
3278 
3279  // Access the auxiliary base class of the object/vector:
3280  SG::AuxVectorBase* vec = 0;
3281  SG::AuxElement* aux = 0;
3282  switch( mgr.holder()->typeKind() ) {
3283  case THolder::DATAVECTOR:
3284  {
3285  void* vvec = mgr.holder()->getAs( typeid( SG::AuxVectorBase ) );
3286  vec = reinterpret_cast< SG::AuxVectorBase* >( vvec );
3287  }
3288  break;
3289  case THolder::AUXELEMENT:
3290  {
3291  void* vaux = mgr.holder()->getAs( typeid( SG::AuxElement ) );
3292  aux = reinterpret_cast< SG::AuxElement* >( vaux );
3293  }
3294  break;
3295  default:
3296  break;
3297  }
3298 
3299  // Check whether index tracking is enabled for the type. If not, then
3300  // we need to fix it...
3301  if( vec && ( ! vec->trackIndices() ) ) {
3302  forceTrackIndices( *vec );
3303  }
3304 
3305  // Check if we were successful:
3306  if( ( ! vec ) && ( ! aux ) ) {
3307  ::Fatal( "xAOD::TEvent::setAuxStore",
3308  XAOD_MESSAGE( "Couldn't access class \"%s\" as "
3309  "SG::AuxVectorBase or SG::AuxElement" ),
3310  mgr.holder()->getClass()->GetName() );
3311  }
3312 
3313  // Get the auxiliary store object:
3314  const SG::IConstAuxStore* store = 0;
3315  if( m_auxMode == kBranchAccess ) {
3316  // Get the concrete auxiliary manager:
3317  TAuxManager* amgr = dynamic_cast< TAuxManager* >( auxMgr );
3318  if( ! amgr ) {
3319  ::Fatal( "xAOD::TEvent::setAuxStore",
3320  XAOD_MESSAGE( "Auxiliary manager for \"%s\" is not of the "
3321  "right type" ), auxKey.c_str() );
3322  return StatusCode::FAILURE;
3323  }
3324  store = amgr->getConstStore();
3325  // If the store still doesn't know its type, help it now:
3327  const TAuxStore::EStructMode mode = ( vec ?
3330  amgr->getStore()->setStructMode( mode );
3331  }
3332  } else if( m_auxMode == kClassAccess || m_auxMode == kAthenaAccess ) {
3333  // Get the concrete auxiliary manager:
3334  TObjectManager* omgr =
3335  dynamic_cast< TObjectManager* >( auxMgr );
3336  if( ! omgr ) {
3337  ::Fatal( "xAOD::TEvent::setAuxStore",
3338  XAOD_MESSAGE( "Auxiliary manager for \"%s\" is not of the "
3339  "right type" ), auxKey.c_str() );
3340  return StatusCode::FAILURE;
3341  }
3342  void* p = omgr->holder()->getAs( typeid( SG::IConstAuxStore ) );
3343  store = reinterpret_cast< const SG::IConstAuxStore* >( p );
3344  }
3345  if( ! store ) {
3346  ::Fatal( "xAOD::TEvent::setAuxStore",
3347  XAOD_MESSAGE( "Logic error detected in the code" ) );
3348  }
3349 
3350  // Connect the two:
3351  if( vec ) {
3352  vec->setStore( store );
3353  } else if( aux ) {
3354  aux->setStore( store );
3355  } else {
3356  ::Fatal( "xAOD::TEvent::setAuxStore",
3357  XAOD_MESSAGE( "Logic error detected in the code" ) );
3358  }
3359 
3360  // We succeeded:
3361  return StatusCode::SUCCESS;
3362  }
3363 
3377  StatusCode TEvent::putAux( ::TTree& outTree, TVirtualManager& vmgr,
3378  ::Int_t basketSize, ::Int_t splitLevel,
3379  ::Bool_t metadata ) {
3380 
3381  // A little sanity check:
3382  assert( m_outputEventFormat != 0 );
3383 
3384  // Do the conversion:
3385  TObjectManager* mgr = dynamic_cast< TObjectManager* >( &vmgr );
3386  if( ! mgr ) {
3387  // It's not an error any more when we don't get a TObjectManager.
3388  return StatusCode::SUCCESS;
3389  }
3390 
3391  // Check if we need to do anything here:
3392  if( ! mgr->holder()->getClass()->InheritsFrom( "SG::IAuxStoreIO" ) ) {
3393  return StatusCode::SUCCESS;
3394  }
3395 
3396  // Get a pointer to the auxiliary store I/O interface:
3397  SG::IAuxStoreIO* aux =
3398  reinterpret_cast< SG::IAuxStoreIO* >(
3399  mgr->holder()->getAs( typeid( SG::IAuxStoreIO ) ) );
3400  if( ! aux ) {
3401  ::Fatal( "xAOD::TEvent::putAux",
3402  XAOD_MESSAGE( "There is a logic error in the code!" ) );
3403  }
3404 
3405  // Check if we have rules defined for which auxiliary properties
3406  // to write out:
3408  if( ! metadata ) {
3409  auto item_itr = m_auxItemList.find( mgr->branch()->GetName() );
3410  if( item_itr != m_auxItemList.end() ) {
3411  sel.selectAux( item_itr->second );
3412  }
3413  }
3414 
3415  // Get the dynamic auxiliary variables held by this object, which
3416  // were selected to be written:
3417  const SG::auxid_set_t auxids = sel.getSelectedAuxIDs (aux->getSelectedAuxIDs());
3418 
3419  // If there are no dynamic auxiliary variables in the object, return
3420  // right away:
3421  if( auxids.empty() ) {
3422  return StatusCode::SUCCESS;
3423  }
3424 
3425  // Decide what should be the prefix of all the dynamic branches:
3426  const std::string dynNamePrefix =
3427  Utils::dynBranchPrefix( mgr->branch()->GetName() );
3428 
3429  // Select which container to add the variables to:
3431 
3432  // This iteration will determine the ordering of branches within
3433  // the tree, so sort auxids by name.
3435  typedef std::pair< std::string, SG::auxid_t > AuxVarSort_t;
3436  std::vector< AuxVarSort_t > varsort;
3437  varsort.reserve( auxids.size() );
3438  for( SG::auxid_t id : auxids ) {
3439  varsort.emplace_back( r.getName( id ), id );
3440  }
3441  std::sort( varsort.begin(), varsort.end() );
3442 
3443  // Extract all the dynamic variables from the object:
3444  for( const auto& p : varsort ) {
3445 
3446  // The auxiliary ID:
3447  const SG::auxid_t id = p.second;
3448 
3449  // Construct a name for the branch that we will write:
3450  const std::string brName = dynNamePrefix + p.first;
3451 
3452  // Try to find the branch:
3453  Object_t::iterator bmgr = objects.find( brName );
3454 
3455  // Check if we already know about this variable:
3456  if( bmgr == objects.end() ) {
3457 
3458  // Construct the full type name of the variable:
3459  const std::type_info* brType = aux->getIOType( id );
3460  if( ! brType ) {
3461  ::Error( "xAOD::TEvent::putAux",
3462  XAOD_MESSAGE( "No I/O type found for variable %s" ),
3463  brName.c_str() );
3464  return StatusCode::FAILURE;
3465  }
3466  const std::string brTypeName =
3467  Utils::getTypeName( *brType );
3468  std::string brProperTypeName = "<unknown>";
3469 
3470  // The branch that will hopefully be created:
3471  ::TBranch* br = 0;
3472 
3473  // Check if it's a primitive type or not:
3474  if( strlen( brType->name() ) == 1 ) {
3475 
3476  // Making the "proper" type name is simple in this case:
3477  brProperTypeName = brTypeName;
3478 
3479  // Get the character describing this type for ROOT:
3480  const char rootType = Utils::rootType( brType->name()[ 0 ] );
3481  if( rootType == '\0' ) {
3482  ::Error( "xAOD::TEvent::putAux",
3483  XAOD_MESSAGE( "Type not known for variable \"%s\" "
3484  "of type \"%s\"" ),
3485  brName.c_str(), brTypeName.c_str() );
3486  return StatusCode::FAILURE;
3487  }
3488 
3489  // Create the full description of the variable for ROOT:
3490  std::ostringstream leaflist;
3491  leaflist << brName << "/" << rootType;
3492 
3493  // Let's create a holder for this property:
3494  THolder* hldr = new THolder( aux->getIOData( id ),
3495  0, kFALSE );
3496  TPrimitiveAuxBranchManager* auxmgr =
3497  new TPrimitiveAuxBranchManager( id, 0, hldr );
3498  objects[ brName ] = auxmgr;
3499 
3500  // ... and let's add it to the output TTree:
3501  *( auxmgr->branchPtr() ) =
3502  outTree.Branch( brName.c_str(), hldr->get(),
3503  leaflist.str().c_str(),
3504  basketSize );
3505  if( ! auxmgr->branch() ) {
3506  ::Error( "xAOD::TEvent::putAux",
3507  XAOD_MESSAGE( "Failed to create branch \"%s\" out "
3508  "of type \"%s\"" ),
3509  brName.c_str(), brProperTypeName.c_str() );
3510  // Clean up:
3511  *( auxmgr->holder()->getPtr() ) = 0;
3512  delete auxmgr;
3513  objects.erase( brName );
3514  return StatusCode::FAILURE;
3515  }
3516  br = auxmgr->branch();
3517 
3518  } else {
3519 
3520  // Check if we have a dictionary for this type:
3521  TClass* cl = TClass::GetClass( *brType, kTRUE, kTRUE );
3522  if( ! cl ) {
3523  // The dictionary needs to be loaded now. This could be an
3524  // issue. But let's hope for the best...
3525  cl = TClass::GetClass( brTypeName.c_str() );
3526  // If still not found...
3527  if( ! cl ) {
3528  ::Error( "xAOD::TEvent::putAux",
3529  XAOD_MESSAGE( "Dictionary not available for "
3530  "variable \"%s\" of type \"%s\"" ),
3531  brName.c_str(), brTypeName.c_str() );
3532  return StatusCode::FAILURE;
3533  }
3534  }
3535 
3536  // The proper type name comes from the dictionary in this case:
3537  brProperTypeName = cl->GetName();
3538 
3539  // Let's create a holder for this property:
3540  THolder* hldr = new THolder( aux->getIOData( id ),
3541  cl, kFALSE );
3542  TAuxBranchManager* auxmgr =
3543  new TAuxBranchManager( id, 0, hldr );
3544  objects[ brName ] = auxmgr;
3545 
3546  if (!cl->CanSplit() && strncmp (cl->GetName(), "SG::PackedContainer<", 20) == 0)
3547  splitLevel = 0;
3548 
3549  // ... and let's add it to the output TTree:
3550  *( auxmgr->branchPtr() ) =
3551  outTree.Branch( brName.c_str(),
3552  cl->GetName(),
3553  hldr->getPtr(), basketSize, splitLevel );
3554  if( ! auxmgr->branch() ) {
3555  ::Error( "xAOD::TEvent::putAux",
3556  XAOD_MESSAGE( "Failed to create branch \"%s\" out "
3557  "of type \"%s\"" ),
3558  brName.c_str(), brProperTypeName.c_str() );
3559  // Clean up:
3560  *( auxmgr->holder()->getPtr() ) = 0;
3561  delete auxmgr;
3562  objects.erase( brName );
3563  return StatusCode::FAILURE;
3564  }
3565  br = auxmgr->branch();
3566 
3567  }
3568 
3569  // If this is not the first event, fill up the already filled
3570  // events with (empty) content:
3571  if( outTree.GetEntries() ) {
3572  void* ptr = br->GetAddress();
3573  br->SetAddress( 0 );
3574  for( ::Long64_t i = 0; i < outTree.GetEntries(); ++i ) {
3575  br->Fill();
3576  }
3577  br->SetAddress( ptr );
3578  }
3579 
3580  // If all went fine, let's add this branch to the event format
3581  // metadata:
3582  if( ! m_outputEventFormat->exists( brName ) ) {
3585  brProperTypeName,
3586  mgr->branch()->GetName(),
3587  getHash( brName ) ) );
3588  }
3589 
3590  // We don't need to do the rest:
3591  continue;
3592  }
3593 
3594  // Access the object manager:
3595  bmgr = objects.find( brName );
3596  if( bmgr == objects.end() ) {
3597  ::Fatal( "xAOD::TEvent::putAux",
3598  XAOD_MESSAGE( "There is an internal logic error in the "
3599  "code..." ) );
3600  }
3601 
3602  // Replace the managed object:
3603  void* nc_data ATLAS_THREAD_SAFE = // we hold non-const pointers but check on retrieve
3604  const_cast< void* >( static_cast< const void* >( aux->getIOData( id ) ) );
3605  bmgr->second->setObject( nc_data );
3606  }
3607 
3608  // Return gracefully:
3609  return StatusCode::SUCCESS;
3610  }
3611 
3621 
3622  // The classes whose children can have an auxiliary store attached
3623  // to them:
3624  static const TClass* const dvClass =
3625  ::TClass::GetClass( typeid( SG::AuxVectorBase ) );
3626  static const TClass* const aeClass =
3627  ::TClass::GetClass( typeid( SG::AuxElement ) );
3628 
3629  // Do the check:
3630  return ( mgr.holder()->getClass()->InheritsFrom( dvClass ) ||
3631  mgr.holder()->getClass()->InheritsFrom( aeClass ) );
3632  }
3633 
3642 
3643  // The classes whose children are considered auxiliary stores:
3644  static const TClass* const storeClass =
3645  ::TClass::GetClass( typeid( SG::IConstAuxStore ) );
3646  static const TClass* const storeHolderClass =
3647  ::TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
3648 
3649  // Do the check:
3650  return ( mgr.holder()->getClass()->InheritsFrom( storeClass ) ||
3651  mgr.holder()->getClass()->InheritsFrom( storeHolderClass ) );
3652  }
3653 
3665 
3666  // The classes whose children can have an auxiliary store attached
3667  // to them:
3668  static const TClass* const dvClass =
3669  TClass::GetClass( typeid( SG::AuxVectorBase ) );
3670  static const TClass* const aeClass =
3671  TClass::GetClass( typeid( SG::AuxElement ) );
3672 
3673  // Do the check:
3674  if( mgr.holder()->getClass()->InheritsFrom( aeClass ) ) {
3675  return kTRUE;
3676  } else if( mgr.holder()->getClass()->InheritsFrom( dvClass ) ) {
3677  return kFALSE;
3678  }
3679 
3680  // Some logic error happened:
3681  ::Error( "xAOD::TEvent::isStandalone",
3682  XAOD_MESSAGE( "Received type (%s) that can't have an "
3683  "auxiliary store" ),
3684  mgr.holder()->getClass()->GetName() );
3685  return kFALSE;
3686  }
3687 
3698  ::Bool_t TEvent::contains( const std::string& key,
3699  const std::type_info& ti,
3700  ::Bool_t metadata ) {
3701 
3702  return ( getOutputObject( key, ti, metadata ) ||
3703  getInputObject( key, ti, kTRUE, metadata ) );
3704  }
3705 
3717  ::Bool_t TEvent::transientContains( const std::string& key,
3718  const std::type_info& ti,
3719  ::Bool_t metadata ) const {
3720 
3721  return getOutputObject( key, ti, metadata );
3722  }
3723 
3726  }
3727 
3728 } // namespace xAOD
xAOD::TEvent::m_inTreeNumber
::Int_t m_inTreeNumber
The number of the currently open tree in the input chain.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:432
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::TEvent::m_nameRemapping
std::unordered_map< std::string, std::string > m_nameRemapping
Container name re-mapping rules.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:466
xAOD::EventFormat_v1::end
const_iterator end() const
STL-like function for getting the end of the container.
Definition: EventFormat_v1.cxx:163
xAOD::TEvent::addListener
StatusCode addListener(TVirtualIncidentListener *listener)
Register an incident listener object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:921
xAOD::TVirtualEvent
Base interface for getting objects out of the input file.
Definition: TVirtualEvent.h:32
xAOD::TEvent::finishWritingTo
StatusCode finishWritingTo(::TFile *file)
Finish writing to an output file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:737
SGTest::store
TestStore store
Definition: TestStore.cxx:23
xAOD::TPrimitiveAuxBranchManager::branchPtr
::TBranch ** branchPtr()
Pointer to the branch's pointer.
Definition: TPrimitiveAuxBranchManager.cxx:89
beamspotman.r
def r
Definition: beamspotman.py:672
CurrentEventStore.h
Hold a pointer to the current event store.
xAOD::EventFormat_v1::get
const EventFormatElement * get(const std::string &key, bool quiet=false) const
Get the description of a given branch.
Definition: EventFormat_v1.cxx:91
xAOD::THolder::AUXELEMENT
@ AUXELEMENT
A type inheriting from SG::AuxElement.
Definition: THolder.h:106
ClassName.h
Recursively separate out template arguments in a C++ class name.
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::TEvent::name
const std::string & name() const override
Get the name of the instance.
Definition: TEventProxyDict.cxx:452
SG::AuxVectorBase::initAuxVectorBase
void initAuxVectorBase(SG::OwnershipPolicy ownPolicy, SG::IndexTrackingPolicy indexTrackingPolicy)
Initialize index tracking mode.
xAOD::TEvent::m_auxMode
EAuxMode m_auxMode
The auxiliary access mode.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:420
xAOD::TEvent::kUndefinedAccess
@ kUndefinedAccess
Undefined, to be selected by the object.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:103
TEventFormatRegistry.h
IAuxStoreHolder.h
checkxAOD.brName
brName
Definition: Tools/PyUtils/bin/checkxAOD.py:125
python.trigbs_prescaleL1.ost
ost
Definition: trigbs_prescaleL1.py:104
get_generator_info.result
result
Definition: get_generator_info.py:21
SG::IAuxStoreHolder::getStoreType
virtual AuxStoreType getStoreType() const =0
Return the type of the store object.
TPrimitiveAuxBranchManager.h
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
LArConditions2Ntuple.objects
objects
Definition: LArConditions2Ntuple.py:64
vtune_athena.format
format
Definition: vtune_athena.py:14
xAOD::TEvent::getInputObject
const void * getInputObject(SG::sgkey_t key, const std::type_info &ti, bool silent=false) override
Function for retrieving an input object in a non-template way.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1951
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
xAOD::IOStats::stats
ReadStats & stats()
Access the object belonging to the current thread.
Definition: IOStats.cxx:17
L1CaloPhase1Monitoring.standalone
standalone
Definition: L1CaloPhase1Monitoring.py:139
xAOD::TAuxManager::getStore
TAuxStore * getStore()
Get a type-specific pointer to the managed object.
Definition: TAuxManager.cxx:100
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:639
xAOD::TAuxBranchManager
Manager for auxiliary branches created dynamically.
Definition: TAuxBranchManager.h:34
xAOD::details::AuxStoreBase::getAuxIDs
virtual const SG::auxid_set_t & getAuxIDs() const override
Get the types(names) of variables handled by this container.
Definition: AuxStoreBase.cxx:101
TAuxBranchManager.h
xAOD::THolder::setOwner
void setOwner(::Bool_t state=kTRUE)
Set whether the holder should own its object.
Definition: THolder.cxx:257
xAOD::TActiveEvent::setEvent
static void setEvent(TVirtualEvent *ptr)
Set the active event pointer.
Definition: TActiveEvent.cxx:21
SG::normalizedTypeinfoName
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
Definition: normalizedTypeinfoName.cxx:120
index
Definition: index.py:1
SG::AuxElement
Base class for elements of a container that can have aux data.
Definition: AuxElement.h:483
xAOD::TEvent::getOutputObject
void * getOutputObject(SG::sgkey_t key, const std::type_info &ti) override
Function for retrieving an output object in a non-template way.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1927
xAOD::THolder::DATAVECTOR
@ DATAVECTOR
A DataVector container.
Definition: THolder.h:105
xAOD::THolder::getAs
virtual void * getAs(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Return the object as a specific pointer.
Definition: THolder.cxx:370
xAOD::THolder
This class takes care of holding EDM objects in memory.
Definition: THolder.h:35
xAOD::details::AuxStoreBase::selectAux
virtual void selectAux(const std::set< std::string > &attributes)
Select dynamic auxiliary attributes for writing.
Definition: AuxStoreBase.cxx:620
xAOD::TEvent::kAthenaAccess
@ kAthenaAccess
Access containers/objects like Athena does.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:102
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:149
xAOD::TEvent::m_outTree
::TTree * m_outTree
The tree that we are writing to.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:439
xAOD::TEvent::getFile
::Int_t getFile(::Long64_t file, ::Int_t getall=0)
Load the first event for a given file from the input TChain.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1483
xAOD::TEvent::m_inChain
::TChain * m_inChain
The (optional) chain provided as input.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:428
xAOD::TEvent::putAux
StatusCode putAux(::TTree &outTree, TVirtualManager &mgr, ::Int_t basketSize=32000, ::Int_t splitLevel=0, ::Bool_t metadata=kFALSE)
Function saving the dynamically created auxiliary properties.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3377
tree
TChain * tree
Definition: tile_monitor.h:30
xAOD::TVirtualManager::getEntry
virtual ::Int_t getEntry(::Int_t getall=0)=0
Function for updating the object in memory if needed.
xAOD::ReadStats::Print
void Print(::Option_t *option="") const
Print information about the collected statistics.
xAOD::details::AuxStoreBase::EStructMode
EStructMode
"Structural" modes of the object
Definition: AuxStoreBase.h:30
xAOD::THolder::getPtr
void ** getPtr()
Return a typeless pointer to the held object's pointer.
Definition: THolder.cxx:225
xAOD::THolder::get
const void * get() const
Return a typeless const pointer to the held object.
Definition: THolder.cxx:215
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
SG::ALWAYS_TRACK_INDICES
@ ALWAYS_TRACK_INDICES
Always track indices, regardless of the setting of the ownership policy.
Definition: IndexTrackingPolicy.h:43
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
xAOD::TEvent::m_inputObjects
Object_t m_inputObjects
Collection of all the managed input objects.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:442
SG::CurrentEventStore::setStore
static IProxyDict * setStore(IProxyDict *store)
Set the current store.
Definition: CurrentEventStore.cxx:36
xAOD::TDirectoryReset
Helper class for making sure the current directory is preserved.
Definition: TDirectoryReset.h:28
downloadSingle.dataType
string dataType
Definition: downloadSingle.py:18
TChainStateTracker.h
NO_SANITIZE_UNDEFINED
#define NO_SANITIZE_UNDEFINED
Definition: no_sanitize_undefined.h:28
xAOD::TAuxManager::getConstStore
const SG::IConstAuxStore * getConstStore() const
Get a convenience pointer to the managed object.
Definition: TAuxManager.cxx:105
xAOD::TEvent::printNameRemap
void printNameRemap() const
Print the current name re-mapping rules.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1044
xAOD::TAuxStore
"ROOT @c TTree implementation" of IAuxStore
Definition: TAuxStore.h:30
xAOD::TActiveStore::store
static TStore * store()
Access the currently active TStore object.
Definition: TActiveStore.cxx:16
xAOD::TEvent::recordAux
SG::IAuxStore * recordAux(const std::string &key, SG::IAuxStoreHolder::AuxStoreType type=SG::IAuxStoreHolder::AST_ContainerStore, Int_t basketSize=32000, Int_t splitLevel=0)
Add an auxiliary store object to the output.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1077
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
SG::CurrentEventStore::store
static IProxyDict * store()
Fetch the current store.
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:157
xAOD::ReadStats::container
BranchStats * container(const std::string &name)
Access the description of a container. Creating it if necessary.
xAOD::EventFormatElement::parentName
const std::string & parentName() const
Get the name of the parent auxiliary object.
Definition: EventFormatElement.cxx:42
xAOD::TVirtualIncidentListener
Class providing an interface for classes listening to xAOD incidents.
Definition: TVirtualIncidentListener.h:25
xAOD::EventFormatElement
Class describing one branch of the ROOT file.
Definition: EventFormatElement.h:39
xAOD::TEvent::copy
StatusCode copy(const std::string &key, ::Int_t basketSize=32000, ::Int_t splitLevel=0)
Copy an object directly from the input to the output.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1154
XAOD_MESSAGE
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Definition: Control/xAODRootAccess/xAODRootAccess/tools/Message.h:19
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:9
xAOD::TEvent::~TEvent
virtual ~TEvent()
Destructor.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:239
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:111
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
Utils.h
xAOD::TVirtualManager
Interface class for the "manager classes".
Definition: TVirtualManager.h:24
xAOD::TEvent::getKey
SG::sgkey_t getKey(const void *obj) const override
Function returning the hash describing a known object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1682
xAOD::EventFormatElement::branchName
const std::string & branchName() const
Get the branch/key name.
Definition: EventFormatElement.cxx:30
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
IOStats.h
xAOD::TEvent::kClassAccess
@ kClassAccess
Access auxiliary data using the aux containers.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:101
TVirtualIncidentListener.h
xAOD::TEvent::dump
std::string dump()
Function creating a user-readable dump of the current input.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:295
xAOD::TPrimitiveAuxBranchManager
Manager for primitive auxiliary branches created dynamically.
Definition: TPrimitiveAuxBranchManager.h:35
TDirectoryReset.h
SG::IAuxStoreIO::getIOType
virtual const std::type_info * getIOType(SG::auxid_t auxid) const =0
Return the type of the data to be stored for one aux data item.
xAOD::TEvent::outputEventFormat
const EventFormat * outputEventFormat() const
Get information about the output objects.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1637
trigbs_dumpHLTContentInBS.stats
stats
Definition: trigbs_dumpHLTContentInBS.py:91
xAOD::details::AuxStoreBase::EStructMode::kObjectStore
@ kObjectStore
The object describes a single object.
xAOD::details::AuxStoreBase::structMode
EStructMode structMode() const
Get what structure mode the object was constructed with.
Definition: AuxStoreBase.cxx:29
PerfStats.h
ReturnCheck.h
AuxVectorBase.h
Manage index tracking and synchronization of auxiliary data.
xAOD::details::AuxStoreBase::EStructMode::kContainerStore
@ kContainerStore
The object describes an entire container.
SG::AuxVectorBase
Manage index tracking and synchronization of auxiliary data.
Definition: AuxVectorBase.h:98
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
xAOD::TEvent::m_inMetaTree
::TTree * m_inMetaTree
Pointer to the metadata tree in the input file.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:434
xAOD::EventFormatElement::hash
sgkey_t hash() const
Get the hash belonging to this branch/key.
Definition: EventFormatElement.cxx:48
SG::IAuxStoreIO
Interface providing I/O for a generic auxiliary store.
Definition: IAuxStoreIO.h:44
xAOD::Utils::dynBranchPrefix
std::string dynBranchPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary branches coming from a container c...
Definition: Control/xAODRootAccess/Root/Utils.cxx:144
xAOD::TEvent::clearNameRemap
void clearNameRemap()
Clear the current name re-mapping.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1035
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
xAOD::ReadStats::nextEvent
void nextEvent()
Function incrementing the processed event counter.
xAOD::THolder::getClass
const ::TClass * getClass() const
Definition: THolder.cxx:401
covarianceTool.filter
filter
Definition: covarianceTool.py:514
SG::AuxTypeRegistry
Handle mappings between names and auxid_t.
Definition: AuxTypeRegistry.h:61
xAOD::TEvent::auxMode
EAuxMode auxMode() const
Get what auxiliary access mode the object was constructed with.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:281
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
BchCleanup.mgr
mgr
Definition: BchCleanup.py:294
xAOD::TActiveEvent::event
static TVirtualEvent * event()
Access the currently active TVirtualEvent object.
Definition: TActiveEvent.cxx:16
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
runLayerRecalibration.branches
list branches
Definition: runLayerRecalibration.py:98
SG::IAuxStoreHolder::AuxStoreType
AuxStoreType
Type of the auxiliary store.
Definition: IAuxStoreHolder.h:66
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
xAOD::TEvent::m_printEventProxyWarnings
Bool_t m_printEventProxyWarnings
Option to silence common warnings that seem to be harmless.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:469
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
CxxUtils::ConcurrentBitset::size
bit_t size() const
Count the number of 1 bits in the set.
TFileAccessTracer.h
xAOD::details::AuxStoreBase::setStructMode
void setStructMode(EStructMode mode)
Set the structure mode of the object to a new value.
Definition: AuxStoreBase.cxx:34
xAOD::EventFormat_v1::begin
const_iterator begin() const
STL-like function for getting the beginning of the container.
Definition: EventFormat_v1.cxx:158
ReadStats.h
TAuxStore.h
xAOD::TEvent::m_inTree
::TTree * m_inTree
The main tree that we are reading from.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:423
xAOD::TAuxBranchManager::branch
::TBranch * branch()
Accessor to the branch.
Definition: TAuxBranchManager.cxx:82
xAOD::TEvent::getNames
void getNames(const std::string &targetClassName, std::vector< std::string > &vkeys, bool metadata=false) const override
Function determining the list keys associated with a type name.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1736
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:353
lumiFormat.i
int i
Definition: lumiFormat.py:85
SG::OWN_ELEMENTS
@ OWN_ELEMENTS
this data object owns its elements
Definition: OwnershipPolicy.h:17
SG::AuxElement::setStore
void setStore(const SG::IConstAuxStore *store)
Set the store associated with this object.
Definition: AuxElement.cxx:241
xAOD::TAuxStore::readFrom
StatusCode readFrom(::TTree &tree, bool printWarnings=true)
Connect the object to an input TTree.
Definition: TAuxStore.cxx:864
xAOD::TEvent::getEntries
::Long64_t getEntries() const
Get how many entries are available from the current input file(s)
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1304
IAuxStoreIO.h
Interface providing I/O for a generic auxiliary store.
xAOD::e
setPy e
Definition: CompositeParticle_v1.cxx:166
xAOD::TEvent::m_auxItemList
std::unordered_map< std::string, std::set< std::string > > m_auxItemList
Rules for selecting which auxiliary branches to write.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:460
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::TEvent::getEntry
::Int_t getEntry(::Long64_t entry, ::Int_t getall=0)
Function loading a given entry of the input TTree.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1335
Message.h
CaloNoise_fillDB.dt
dt
Definition: CaloNoise_fillDB.py:56
xAOD::TIncident
Class describing a certain "incident" that is communicated to user code.
Definition: TIncident.h:58
xAOD::TChainStateTracker
Class helping with tracking the state of TChain objects.
Definition: TChainStateTracker.h:32
xAOD::TEvent::isStandalone
::Bool_t isStandalone(const TObjectManager &mgr)
Function checking if an object is standalone (not a container)
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3664
sel
sel
Definition: SUSYToolsTester.cxx:92
SG::IAuxStoreIO::getSelectedAuxIDs
virtual SG::auxid_set_t getSelectedAuxIDs() const
Get a list of dynamic variables that need to be written out.
Definition: IAuxStoreIO.h:86
xAOD::TChainStateTracker::reset
void reset()
Reset the object.
Definition: TChainStateTracker.cxx:31
vertexingJO_ITK_init.itemList
list itemList
Definition: vertexingJO_ITK_init.py:95
generateReferenceFile.files
files
Definition: generateReferenceFile.py:12
TEvent.h
CalibDbCompareRT.dummy
dummy
Definition: CalibDbCompareRT.py:59
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
file
TFile * file
Definition: tile_monitor.h:29
dumpFileToPlots.treeName
string treeName
Definition: dumpFileToPlots.py:19
xAOD::EventFormatElement::className
const std::string & className() const
Get the class name of this branch/key.
Definition: EventFormatElement.cxx:36
xAOD::ReadStats::setBranchNum
void setBranchNum(::Int_t num)
Set the total number of branches on the input.
Preparation.mode
mode
Definition: Preparation.py:107
xAOD::TEvent::m_inputEventFormat
EventFormat m_inputEventFormat
Format of the current input file.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:455
python.getProblemFolderFromLogs.el
dictionary el
Definition: getProblemFolderFromLogs.py:48
CxxUtils::ConcurrentBitset::empty
bool empty() const
Return true if there are no 1 bits in the set.
xAOD::TEventFormatRegistry::instance
static const TEventFormatRegistry & instance()
Access the only instance of the object in memory.
Definition: TEventFormatRegistry.cxx:14
xAOD::TEvent::contains
::Bool_t contains(const std::string &key)
Function checking if an object is available from the store.
plotmaker.keyName
keyName
Definition: plotmaker.py:145
xAOD::IOStats::instance
static IOStats & instance()
Singleton object accessor.
Definition: IOStats.cxx:11
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
xAOD::TEvent::setPrintEventProxyWarnings
void setPrintEventProxyWarnings(bool)
Function to silence warnings associated with broken element links.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3724
xAOD::TEvent::m_listeners
Listener_t m_listeners
Listeners who should be notified when certain incidents happen.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:463
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
xAOD::TEvent::CACHE_SIZE
static const ::Int_t CACHE_SIZE
Size of a possible TTreeCache (30 MB)
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:413
xAOD::TEvent::m_outputMetaObjects
Object_t m_outputMetaObjects
Collection of all the managed output meta-objects.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:452
xAOD::TEvent::EVENT_TREE_NAME
static const char *const EVENT_TREE_NAME
Name of the event tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:415
xAOD::TEvent::m_outputObjects
Object_t m_outputObjects
Collection of all the managed output object.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:447
TObjectManager.h
xAOD::TEvent::m_inputMetaObjects
Object_t m_inputMetaObjects
Collection of all the managed input meta-objects.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:450
SG::IAuxStoreHolder::setStore
virtual void setStore(IAuxStore *store)=0
Give an auxiliary store object to the holder object.
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:26
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
xAOD::TVirtualEvent::keys
void keys(std::vector< std::string > &vkeys, bool metadata=false) const
provide list of all keys associated with provided type.
xAOD::TEvent::m_branchesMutex
upgrade_mutex_t m_branchesMutex
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:485
xAOD::AuxSelection
Class helping in dealing with dynamic branch selection.
Definition: AuxSelection.h:31
TAuxManager.h
xAOD::TEvent::METADATA_TREE_NAME
static const char *const METADATA_TREE_NAME
Name of the metadata tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:417
xAOD::TChainStateTracker::internalStateChanged
::Bool_t internalStateChanged() const
Check whether there was an internal state change without us knowing.
Definition: TChainStateTracker.cxx:26
TActiveEvent.h
xAOD::EventFormat_v1
Event format metadata for xAOD files.
Definition: EventFormat_v1.h:38
xAOD::TEvent::record
StatusCode record(T *obj, const std::string &key, ::Int_t basketSize=32000, ::Int_t splitLevel=0)
Add an output object to the event.
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAOD::TEvent::TEvent
TEvent(EAuxMode mode=kUndefinedAccess)
Default constructor.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:134
xAOD::TEvent::m_inTreeMissing
::Bool_t m_inTreeMissing
Internal status flag showing that an input file is open, but it doesn't contain an event tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:426
xAOD::ReadStats::readContainer
void readContainer(const std::string &name)
Function incrementing the read counter on a specific container.
MakeNewFileFromOldAndSubstitution.newName
dictionary newName
Definition: ICHEP2016/MakeNewFileFromOldAndSubstitution.py:95
xAOD::TFileAccessTracer
Helper class keeping track of the files that got accessed.
Definition: TFileAccessTracer.h:46
xAOD::TEvent::initStats
StatusCode initStats()
Function to initialise the statistics for all Tree content.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1974
xAOD::TObjectManager
Manager for EDM objects created by ROOT.
Definition: TObjectManager.h:29
SG::sgkey_t
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition: CxxUtils/CxxUtils/sgkey_t.h:32
SG::IAuxStoreIO::getIOData
virtual const void * getIOData(SG::auxid_t auxid) const =0
Return a pointer to the data to be stored for one aux data item.
xAOD::TAuxManager
Manager for TAuxStore objects.
Definition: TAuxManager.h:33
xAOD::TEvent::fill
::Int_t fill()
Function filling one event into the output tree.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1519
xAOD::PerfStats::instance
static PerfStats & instance()
Function accessing the singleton instance.
xAOD::TEventFormatRegistry::getEventFormat
EventFormat & getEventFormat(const TFile *file) const
Access the managed EventFormat object.
Definition: TEventFormatRegistry.cxx:20
xAOD::TEvent::transientContains
::Bool_t transientContains(const std::string &key) const
Function checking if an object is already in memory.
xAOD::TEvent::removeListener
StatusCode removeListener(TVirtualIncidentListener *listener)
Remove an incident listener object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:957
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
xAOD::TEvent::isAuxStore
::Bool_t isAuxStore(const TObjectManager &mgr)
Function checking if a given object may be an auxiliary store.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3641
xAOD::TEvent::connectAux
StatusCode connectAux(const std::string &prefix, ::Bool_t standalone)
Function setting up access to a set of auxiliary branches.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:2884
SG::IAuxStore
Interface for non-const operations on an auxiliary store.
Definition: IAuxStore.h:48
xAOD::TEvent::m_outputEventFormat
EventFormat * m_outputEventFormat
Format of the current output file.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:457
AuxSelection.h
xAOD::TEvent::setUpDynamicStore
StatusCode setUpDynamicStore(TObjectManager &mgr, ::TTree *tree)
Function adding dynamic variable reading capabilities to an auxiliary store object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3116
DeMoScan.index
string index
Definition: DeMoScan.py:362
xAOD::TEvent::EAuxMode
EAuxMode
Auxiliary store "mode".
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:99
xAOD::TEvent::getFiles
::Long64_t getFiles() const
Get how many files are available on the currently defined input.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1463
xAOD::TStore
A relatively simple transient store for objects created in analysis.
Definition: TStore.h:47
xAOD::TEvent::addNameRemap
StatusCode addNameRemap(const std::string &onfile, const std::string &newName)
Add a name re-mapping rule.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1001
CxxUtils::ClassName::ExcBadClassName
Exception to signal a malformed class name.
Definition: CxxUtils/CxxUtils/ClassName.h:109
python.trfDecorators.silent
def silent(func)
Redirect stdout/err to /dev/null Useful wrapper to get rid of ROOT verbosity...
Definition: trfDecorators.py:24
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
xAOD::TEvent::ATLAS_THREAD_SAFE
SG::SGKeyMap< BranchInfo > m_branches ATLAS_THREAD_SAFE
Map from hashed sgkey to BranchInfo.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:488
xAOD::TEvent::hasAuxStore
::Bool_t hasAuxStore(const TObjectManager &mgr)
Function checking if a given object may have an auxiliary store.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3620
xAOD::Utils::getFirstBranchMatch
std::string getFirstBranchMatch(TTree *tree, const std::string &pre)
This function is used to search for a branch in a TTree that contains a given substring.
Definition: Control/xAODRootAccess/Root/Utils.cxx:393
xAOD::TEvent::connectBranch
StatusCode connectBranch(const std::string &key, ::Bool_t silent=kFALSE)
Function setting up access to a particular branch.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:2586
xAOD::TEvent::getHash
SG::sgkey_t getHash(const std::string &key) const override
Function returning the hash describing an object name.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1660
xAOD::TObjectManager::holder
const THolder * holder() const
Accessor to the Holder object.
Definition: TObjectManager.cxx:82
xAOD::TEvent::m_entry
::Long64_t m_entry
The entry to look at from the input tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:436
THolder.h
xAOD::TEvent::inputEventFormat
const EventFormat * inputEventFormat() const
Get information about the input objects.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1614
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
xAOD::TPrimitiveAuxBranchManager::branch
::TBranch * branch()
Accessor to the branch.
Definition: TPrimitiveAuxBranchManager.cxx:84
xAOD::TAuxBranchManager::branchPtr
::TBranch ** branchPtr()
Pointer to the branch's pointer.
Definition: TAuxBranchManager.cxx:87
xAOD::TEvent::m_inChainTracker
TChainStateTracker * m_inChainTracker
Optional object for tracking the state changes of an input TChain.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:430
xAOD::TEvent::writeTo
StatusCode writeTo(::TFile *file, Int_t autoFlush=200, const char *treeName=EVENT_TREE_NAME)
Connect the object to an output file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:695
xAOD::details::AuxStoreBase::EStructMode::kUndefinedStore
@ kUndefinedStore
The structure mode is not defined.
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
xAOD::TEvent::readFrom
StatusCode readFrom(::TFile *file, Bool_t useTreeCache=kTRUE, const char *treeName=EVENT_TREE_NAME)
Connect the object to a new input file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:367
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
AthContainers_detail::upgrading_lock
Lock object for taking out upgradable locks.
Definition: threading.h:177
xAOD::TEvent::Object_t
std::unordered_map< std::string, TVirtualManager * > Object_t
Definition of the internal data structure type.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:408
merge.status
status
Definition: merge.py:16
xAOD::EventFormat_v1::const_iterator
KeyedData_t::const_iterator const_iterator
Iterator for looping over the elements of the object.
Definition: EventFormat_v1.h:67
xAOD::TEvent::kBranchAccess
@ kBranchAccess
Access auxiliary data branch-by-branch.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:100
no_sanitize_undefined.h
Helper to disable undefined behavior sanitizer for a function.
xAOD::TEvent::setAuxItemList
void setAuxItemList(const std::string &containerKey, const std::string &itemList)
Configure which dynamic variables to write out for a given store.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:893
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
xAOD::EventFormat_v1::add
void add(const EventFormatElement &element, bool updatePersistent=true)
Add the description of a new branch.
Definition: EventFormat_v1.cxx:43
xAOD::TEvent::getName
const std::string & getName(const void *obj) const override
Function returning the key describing a known object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1695
xAOD::ReadStats
Class describing the access statistics of a collection of branches.
Definition: ReadStats.h:123
SG::IConstAuxStore
Interface for const operations on an auxiliary store.
Definition: IConstAuxStore.h:64
python.PyAthena.obj
obj
Definition: PyAthena.py:132
xAOD::TEvent::setActive
void setActive() const
Set this event object as the currently active one.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:871
SG::IAuxStoreHolder::AST_ObjectStore
@ AST_ObjectStore
The store describes a single object.
Definition: IAuxStoreHolder.h:67
SG::IAuxStoreHolder
Interface for objects taking part in direct ROOT I/O.
Definition: IAuxStoreHolder.h:36
xAOD::Utils::hash
SG::sgkey_t hash(const std::string &name)
This function provides a hashed version of the key (branch) names used in the xAOD file,...
Definition: Control/xAODRootAccess/Root/Utils.cxx:125
xAOD::TObjectManager::setObject
virtual void setObject(void *obj) override
Function replacing the object being handled.
Definition: TObjectManager.cxx:189
xAOD::TEvent::connectMetaBranch
StatusCode connectMetaBranch(const std::string &key, ::Bool_t silent=kFALSE)
Function setting up access to a branch in the metadata tree.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:2770
xAOD::TEvent::printIOStats
void printIOStats() const
Function printing the I/O statistics of the current process.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:350
TIncident.h
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
LArL1Calo_ComputeHVCorr.className
className
Definition: LArL1Calo_ComputeHVCorr.py:135
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:294
xAOD::TAuxBranchManager::holder
const THolder * holder() const
Accessor to the Holder object (constant version)
Definition: TAuxBranchManager.cxx:92
python.TransformConfig.attributes
def attributes(self)
Definition: TransformConfig.py:383
TActiveStore.h
LheEventFiller_Common.ef
ef
Definition: SFGen_i/share/common/LheEventFiller_Common.py:7
TStore.h
xAOD::TEvent
Tool for accessing xAOD files outside of Athena.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:85
xAOD::TPrimitiveAuxBranchManager::holder
const THolder * holder() const
Accessor to the Holder object (constant version)
Definition: TPrimitiveAuxBranchManager.cxx:94
xAOD::TObjectManager::object
virtual const void * object() const override
Function getting a const pointer to the object being handled.
Definition: TObjectManager.cxx:175
xAOD::EventFormat_v1::exists
bool exists(const std::string &key) const
Check if a description exists about a given branch.
Definition: EventFormat_v1.cxx:65
AuxElement.h
Base class for elements of a container that can have aux data.
xAOD::TEvent::m_inputMissingObjects
std::set< std::string > m_inputMissingObjects
Objects that have been asked for, but were found to be missing in the current input.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:445
PlotCalibFromCool.br
br
Definition: PlotCalibFromCool.py:355
SG::IAuxStoreHolder::AST_ContainerStore
@ AST_ContainerStore
The store describes a container.
Definition: IAuxStoreHolder.h:68
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
xAOD::TEvent::connectMetaAux
StatusCode connectMetaAux(const std::string &prefix, ::Bool_t standalone)
Function setting up access to a set of auxiliary branches for a metadata object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3003
xAOD::TEvent::setAuxStore
StatusCode setAuxStore(TObjectManager &mgr, ::Bool_t metadata=kFALSE)
Function connecting a DV object to its auxiliary store.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:3200
DataProxy.h
xAOD::TEvent::clearListeners
void clearListeners()
Remove all listeners from the object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:981