Implement the auto-generated functions of the class.
In order to merge various kinds of metadata from the input files correctly into the output file, it is possible to specify the type names of dual-use metadata handling tools. The object then creates an instance of the specified tool, which should take care of merging its metadata type in the background.
This function does most of the heavy-lifting in the code. It recursively merges all the objects from an input directory into the output file's corresponding directory.
This function finds branches that appear in the first tree, but don't appear in the second one.
This function is used during fast merging to create branches that have been encountered first in file N (N >= 2).
37 {
38
39 TFileMerger::TFileMerger()
40 : TObject(), m_input(), m_copiedInput(), m_output( 0 ),
41 m_treesToSkip( { "##Shapes", "##Links", "##Params",
42 "##Sections",
43 "CollectionTreeInDet::Track_tlp2",
44 "POOLContainerForm", "POOLContainer",
45 "POOLCollectionTree", "MetaData",
46 "MetaDataHdrForm", "MetaDataHdr" } ),
47 m_events(), m_helperFiles(),
48 m_metaDataToolNames(), m_metaDataTools(),
49 m_mode( TEvent::kClassAccess ), m_entriesToMerge( kBigNumber ),
50 m_verbosity( 0 ) {
51
52 }
53
54
55 TFileMerger::~TFileMerger() {
56
57
58 closeFiles().ignore();
59 }
60
61 StatusCode TFileMerger::setOutputFileName( const std::string& name,
62 const std::string& mode ) {
63
64
65 m_output = ::TFile::Open(
name.c_str(),
mode.c_str() );
66 if( ! m_output ) {
67 Error(
"setOutputFileName",
68 XAOD_MESSAGE(
"Couldn't open output file \"%s\" in mode "
69 "\"%s\"" ),
71 return StatusCode::FAILURE;
72 }
73
74
75 Info(
"setOutputFileName",
"Opened \"%s\" for writing",
77
78
79 gROOT->cd();
80
81
82 return StatusCode::SUCCESS;
83 }
84
85 StatusCode TFileMerger::addFile( const std::string& name,
86 bool copyLocally ) {
87
88
89
90 std::string localName =
name;
91 if( copyLocally ) {
92
93 TUUID uuid;
94
95 localName =
96 TString::Format( "%s/XAODMERGE-%s.root",
97 gSystem->TempDirectory(), uuid.AsString() ).Data();
98
99 if( ! TFile::Cp(
name.c_str(), localName.c_str(), kTRUE ) ) {
101 XAOD_MESSAGE(
"Couldn't create local copy of \"%s\" under "
102 "\"%s\"" ),
103 name.c_str(), localName.c_str() );
104 return StatusCode::FAILURE;
105 }
106
107 Info(
"addFile",
"Made a local copy of: %s",
name.c_str() );
108 }
109
110
111 ::TFile*
ifile = ::TFile::Open( localName.c_str(),
"READ" );
112 if( ! ifile ) {
114 localName.c_str() );
115 return StatusCode::FAILURE;
116 }
117
118
119 m_input.push_back( ifile );
120 m_copiedInput.push_back( copyLocally );
121 Info(
"addFile",
"Opened \"%s\" for reading", localName.c_str() );
122
123
124 gROOT->cd();
125
126
127 return StatusCode::SUCCESS;
128 }
129
142 StatusCode TFileMerger::addMetaDataTool( const std::string& typeName ) {
143
144
145 if( m_metaDataToolNames.find( typeName ) != m_metaDataToolNames.end() ) {
146 Warning( "addMetaDataTool",
147 "Tool of type \"%s\" is already specified",
149 return StatusCode::RECOVERABLE;
150 }
151
152
153 ::TClass*
cl = ::TClass::GetClass(
typeName.c_str() );
154 if( ! cl ) {
155 Error(
"addMetaDataTool",
158 return StatusCode::FAILURE;
159 }
160
161
162 m_metaDataToolNames.insert( typeName );
163
164
165 if( m_verbosity > 1 ) {
166 Info(
"addMetaDataTool",
"Added tool of type \"%s\"",
168 }
169
170
171 return StatusCode::SUCCESS;
172 }
173
183 StatusCode TFileMerger::merge( EMergeMode mode, ::Long64_t
entries ) {
184
185
186 if( ! m_output ) {
188 return StatusCode::FAILURE;
189 }
190
191
192 if( ! m_input.size() ) {
193 Warning( "merge", "No input files were specified" );
194 return StatusCode::RECOVERABLE;
195 }
196
197
198 if( ( mode == kFastMerge ) && (
entries != kBigNumber ) ) {
199 Warning( "merge", "Number of entries can't be specified in fast "
200 "merging mode" );
201 m_entriesToMerge = kBigNumber;
202 } else {
204 }
205
206
207
208 for( ::TFile*
file : m_input ) {
210 mergeDirectory( *
file, *m_output, mode,
true ) );
211 }
212
213
214 m_output->SaveSelf();
215
216
217 RETURN_CHECK(
"xAOD::TFileMerger::merge", closeFiles() );
218
219
220 return StatusCode::SUCCESS;
221 }
222
223 TEvent::EAuxMode TFileMerger::accessMode() const {
224
225 return m_mode;
226 }
227
228 void TFileMerger::setAccessMode( TEvent::EAuxMode mode ) {
229
231 return;
232 }
233
234 int TFileMerger::verbosity() const {
235
236 return m_verbosity;
237 }
238
239 void TFileMerger::setVerbosity( int value ) {
240
242 return;
243 }
244
245 const std::set< std::string >& TFileMerger::treesSkipped() const {
246
247 return m_treesToSkip;
248 }
249
250 void TFileMerger::addTreeToSkip( const std::string& name ) {
251
252 m_treesToSkip.insert( name );
253 return;
254 }
255
256 StatusCode TFileMerger::closeFiles() {
257
258 if( m_verbosity >= 1 ) {
259 Info(
"closeFiles",
"Closing all open files" );
260 }
261
262
263 if( m_input.size() != m_copiedInput.size() ) {
266 }
267
268
269 auto ev_itr = m_events.begin();
270 auto ev_end = m_events.end();
271 for( ; ev_itr != ev_end; ++ev_itr ) {
272 if( ev_itr->second->m_outTree && m_output ) {
274 ev_itr->second->finishWritingTo( m_output ) );
275 }
276 }
277
278
279 for(
size_t i = 0;
i < m_input.size(); ++
i ) {
280 m_input[
i ]->Close();
281 if( m_verbosity >= 2 ) {
282 Info(
"closeFiles",
"Closed: %s", m_input[ i ]->GetName() );
283 }
284 if( m_copiedInput[ i ] ) {
285 TString
p( m_input[ i ]->GetPath() );
286 p =
p( 0,
p.Index(
':', 0 ) );
287 if( gSystem->Unlink( p ) ) {
291 return StatusCode::FAILURE;
292 }
293 if( m_verbosity >= 2 ) {
294 Info(
"closeFiles",
"Deleted: %s", m_input[ i ]->GetName() );
295 }
296 }
298 }
299 m_input.clear();
300 m_copiedInput.clear();
301
302
303 if( m_output ) {
304 m_output->Close();
305 if( m_verbosity >= 2 ) {
306 Info(
"closeFiles",
"Closed: %s", m_output->GetName() );
307 }
308 delete m_output;
309 m_output = 0;
310 }
311
312
313 m_events.clear();
314
315
316 for( ::TFile*
file : m_helperFiles ) {
318 }
319 m_helperFiles.clear();
320
321
322 return StatusCode::SUCCESS;
323 }
324
336 StatusCode TFileMerger::mergeDirectory( ::TDirectory& input,
337 ::TDirectory& output,
338 EMergeMode mode,
339 bool topLevelDir ) {
340
341 if( m_verbosity >= 1 ) {
342 Info(
"mergeDirectory",
"Merging directories:" );
343 Info(
"mergeDirectory",
" input : %s",
input.GetName() );
344 Info(
"mergeDirectory",
" output: %s",
output.GetName() );
345 }
346
347
348 TList* keyList =
input.GetListOfKeys();
349 if( ! keyList ) {
350 Error(
"mergeDirectory",
351 XAOD_MESSAGE(
"Couldn't get list of keys from input directory "
352 "\"%s\"" ),
input.GetName() );
353 return StatusCode::FAILURE;
354 }
355
356
357
358
359
360
361
362 std::set< std::string > processedTrees;
363 for( Int_t i = 0;
i < keyList->GetSize(); ++
i ) {
364
365
366 TKey*
key =
dynamic_cast< TKey*
>( keyList->At( i ) );
367 if( ! key ) {
368 Error(
"mergeDirectory",
370 "why..." ) );
371 return StatusCode::FAILURE;
372 }
373 if( m_verbosity >= 3 ) {
374 Info(
"mergeDirectory",
"Evaluating key \"%s;%hi\" with type "
375 "\"%s\"",
376 key->GetName(),
key->GetCycle(),
key->GetClassName() );
377 }
378
379
380 TObject*
obj =
input.Get( TString::Format(
"%s;%hi",
key->GetName(),
382 if( ! obj ) {
383 Error(
"mergeDirectory",
385 "\"%s;%hi\"" ),
386 key->GetName(),
key->GetCycle() );
387 return StatusCode::FAILURE;
388 }
389
390
391
392
393 if(
obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
394
395 if( m_verbosity >= 3 ) {
396 Info(
"mergeDirectory",
"Appears to be a TDirectory" );
397 }
398
399
400 TDirectory*
indir =
dynamic_cast< TDirectory*
>(
obj );
401 if( ! indir ) {
402 Error(
"mergeDirectory",
403 XAOD_MESSAGE(
"Couldn't cast to object to TDirectory" ) );
404 return StatusCode::FAILURE;
405 }
406
407
409 dynamic_cast< TDirectory*
>(
output.Get(
key->GetName() ) );
410
411 if( ! outdir ) {
412 if( ! ( outdir =
output.mkdir(
key->GetName(),
413 "dummy title" ) ) ) {
414 Error(
"mergeDirectory",
416 "name: %s" ),
418 return StatusCode::FAILURE;
419 }
420 }
421
422
423
424
426 mergeDirectory( *indir, *outdir, kFastMerge,
427 false ) );
428
429 }
else if(
obj->IsA()->InheritsFrom(
"TTree" ) ) {
430
431 if( m_verbosity >= 3 ) {
432 Info(
"mergeDirectory",
"Appears to be a TTree" );
433 }
434
435
436
437
438 if( m_treesToSkip.find(
key->GetName() ) !=
439 m_treesToSkip.end() ) {
440 if( m_verbosity >= 4 ) {
441 Info(
"mergeDirectory",
442 "Skipping it because of m_treesToSkip" );
443 }
444 continue;
445 }
446
447
448 if( processedTrees.find(
key->GetName() ) !=
449 processedTrees.end() ) {
450 if( m_verbosity >= 4 ) {
451 Info(
"mergeDirectory",
452 "Skipping it, because it was processed already" );
453 }
454 continue;
455 }
456
457 if( m_verbosity >= 3 ) {
458 Info(
"mergeDirectory",
459 "Tree not processed yet. Doing so now." );
460 }
461
462
463 ::TObject* treeObj =
input.Get(
key->GetName() );
464 if( ! treeObj ) {
465 Fatal(
"mergeDirectory",
467 return StatusCode::FAILURE;
468 }
469 ::TTree* itree = dynamic_cast< TTree* >( treeObj );
470 if( ! itree ) {
471 Error(
"mergeDirectory",
473 "pointer" ),
474 treeObj->GetName() );
475 return StatusCode::FAILURE;
476 }
477
478
479
480 if( itree->GetListOfFriends() &&
481 itree->GetListOfFriends()->GetSize() ) {
482 if( m_verbosity >= 2 ) {
483 Info(
"mergeDirectory",
"TTree \"%s\" has friends; "
484 "skipping from merge", itree->GetName() );
485 }
486 continue;
487 }
488
489
490
491
492
493 if( topLevelDir ) {
494
495 std::unique_ptr< TEvent >&
event = m_events[
key->GetName() ];
496 if( ( !
event.get() ) || (
event->auxMode() != m_mode ) ) {
497 event.reset( new TEvent( m_mode ) );
498 event->setActive();
499 }
500
502 createMetaDataTools() );
503
505 event->readFrom( itree ) );
506
507 Info(
"mergeDirectory",
"Copying xAOD tree \"%s\"",
509 } else {
510
511 Info(
"mergeDirectory",
"Copying non-xAOD tree \"%s\"",
513 }
514
515
516 if( mode == kFastMerge ) {
517
518
519
520 if( topLevelDir ) {
521 std::unique_ptr< TEvent >&
event = m_events[
key->GetName() ];
522 if( !
event.get() ) {
523 event.reset( new TEvent() );
524 }
525 if( !
event->m_outTree ) {
526
527
528
529
531 new ::TMemFile( TString::Format( "%sHelper.root",
533 "CREATE" );
534 m_helperFiles.push_back( ofile );
536 event->writeTo( ofile, 200,
538 }
539
540
541 const EventFormat* ief =
event->inputEventFormat();
543 if( ( ! ief ) || ( ! oef ) ) {
544 Error(
"mergeDirectory",
546 Error(
"mergeDirectory",
548 static_cast< const void* >( ief ),
549 static_cast< void* >( oef ) );
550 return StatusCode::FAILURE;
551 }
552 auto itr = ief->
begin();
553 auto end = ief->end();
554 for( ; itr !=
end; ++itr ) {
555 if( ! oef->exists( itr->first ) ) {
556 oef->add( itr->second );
557 }
558 }
559 }
560
561
562
563
564 ::TTree* otree =
565 dynamic_cast< ::TTree*
>(
output.Get(
key->GetName() ) );
566 if( otree ) {
567
568 if( m_verbosity >= 3 ) {
569 Info(
"mergeDirectory",
570 "Merging the tree into an existing one" );
571 }
572
573
574
575 const std::vector< ::TBranch* > missingMerged =
576 getMissingBranches( otree, itree );
577 const std::vector< ::TBranch* > missingIncoming =
578 getMissingBranches( itree, otree );
579 if( m_verbosity >= 4 ) {
580 Info(
"mergeDirectory",
"missingMerged.size() = %i",
581 static_cast< int >( missingMerged.size() ) );
582 Info(
"mergeDirectory",
"missingIncoming.size() = %i",
583 static_cast< int >( missingIncoming.size() ) );
584 }
585
586
587
588
589 for( ::TBranch* br : missingIncoming ) {
590 if( m_verbosity >= 4 ) {
591 Info(
"mergeDirectory",
"Adding auxiliary branch: %s",
593 }
595 addAuxBranch( otree, br ) );
596 }
597
598
599
600 const std::vector< ::TBranch* > skippedBranches =
601 getSkippedBranches( itree );
602 for( ::TBranch* br : skippedBranches ) {
603 itree->SetBranchStatus(
br->GetName(), 0 );
604 if( m_verbosity >= 4 ) {
605 Info(
"mergeDirectory",
606 "Deactivated branch \"%s\" from merging",
608 }
609 }
610
611
612
613 TObjArray* obranches = otree->GetListOfBranches();
614 std::map< ::Int_t, ::TBranch* > auxIndices;
615 for( ::TBranch* br : missingMerged ) {
616 const Int_t
index = obranches->IndexOf( br );
618 Error(
"mergeDirectory",
620 "detected" ) );
621 return StatusCode::FAILURE;
622 }
624 obranches->RemoveAt(
index );
625 if( m_verbosity >= 4 ) {
626 Info(
"mergeDirectory",
"Removed branch \"%s\" from "
627 "fast merge list",
br->GetName() );
628 }
629 }
630 if( auxIndices.size() ) {
631 obranches->Compress();
632 }
633
634
635
636 ::TTreeCloner
637 cloner( itree, otree, "fast SortBasketsByBranch",
638 ( ::TTreeCloner::kNoWarnings |
639 ::TTreeCloner::kIgnoreMissingTopLevel ) );
640
641 if( ! cloner.IsValid()) {
642
643 static const char* const okerror = "One of the export branch";
644 if( ::strncmp( cloner.GetWarning(), okerror,
645 ::strlen( okerror ) ) == 0 ) {
646
647 } else {
648 Error(
"mergeDirectory",
650 cloner.GetWarning() );
651 return StatusCode::FAILURE;
652 }
653 }
654
655
656 otree->SetEntries( otree->GetEntries() +
657 itree->GetEntries() );
658 if( ! cloner.Exec() ) {
659 Error(
"mergeDirectory",
661 return StatusCode::FAILURE;
662 }
663
664
665
666 for( auto it : auxIndices ) {
667 const Int_t last = obranches->GetLast();
668 if( last >= 0 ) {
669 obranches->AddAtAndExpand( obranches->At( last ),
670 last + 1 );
671 for( Int_t ind = last - 1; ind >=
it.first; --ind ) {
672 obranches->AddAt( obranches->At( ind ), ind + 1 );
673 }
674 obranches->AddAt(
it.second,
it.first );
675 } else {
676 obranches->Add(
it.second );
677 }
678 }
679
680 const ::Long64_t ientries = itree->GetEntries();
681 for( ::TBranch* br : missingMerged ) {
683 for( ::Long64_t i = 0;
i < ientries; ++
i ) {
684 if(
br->Fill() < 0 ) {
685 Error(
"mergeDirectory",
687 "with default content" ),
689 return StatusCode::FAILURE;
690 }
691 }
692 }
693
694
695 otree->AutoSave( "FlushBaskets" );
696
697 } else {
698
699 if( m_verbosity >= 3 ) {
700 Info(
"mergeDirectory",
"Cloning the tree as is" );
701 }
702
703
704
705
706
707
708
709
710
711
712 const std::vector< ::TBranch* > skippedBranches =
713 getSkippedBranches( itree );
714 for( ::TBranch* br : skippedBranches ) {
715 itree->SetBranchStatus(
br->GetName(), 0 );
716 if( m_verbosity >= 4 ) {
717 Info(
"mergeDirectory",
718 "Deactivated branch \"%s\" from cloning",
720 }
721 }
722
723
725 if( ! ( otree =
726 itree->CloneTree( -1,
727 "fast SortBasketsByBranch" ) ) ) {
728 Error(
"mergeDirectory",
730 "into the output" ),
731 itree->GetName() );
732 return StatusCode::FAILURE;
733 }
734 otree->SetDirectory( &output );
735 otree->AutoSave();
736 }
737
738
739
740 } else if( mode == kSlowMerge ) {
741
742
743
744
745 std::unique_ptr< TEvent >&
event = m_events[
key->GetName() ];
746 if( !
event.get() ) {
747 event.reset( new TEvent() );
748 }
749
750
751 if( !
event->m_outTree ) {
752
753 ::TFile*
ofile =
dynamic_cast< ::TFile*
>( &
output );
754 if( ! ofile ) {
755 Error(
"mergeDirectory",
757 return StatusCode::FAILURE;
758 }
760 event->writeTo( ofile, 200,
key->GetName() ) );
761 }
762
763
764 if( m_verbosity >= 3 ) {
765 Info(
"mergeDirectory",
"Slow copying xAOD tree \"%s\"",
767 }
768
769
770 const ::Long64_t
entries =
event->getEntries();
772
773
774 if(
event->m_outTree->GetEntries() >= m_entriesToMerge ) {
775 break;
776 }
777
778
779 if(
event->getEntry( entry ) < 0 ) {
780 Error(
"mergeDirectory",
782 "%s" ),
783 static_cast< int >( entry ),
key->GetName() );
784 return StatusCode::FAILURE;
785 }
786
787
788 if( ! ( entry % 500 ) ) {
789 Info(
"mergeDirectory",
"Copied %i / %i entries",
790 static_cast< int >( entry ),
791 ( m_entriesToMerge == kBigNumber ?
792 static_cast< int >(
entries ) :
793 static_cast< int >( m_entriesToMerge ) ) );
794 }
795
796
799
800
801 const ::Int_t bytes = event->fill();
802 if( bytes < 0 ) {
803 Error(
"mergeDirectory",
805 "%i from tree %s" ),
806 static_cast< int >( entry ),
key->GetName() );
807 return StatusCode::FAILURE;
808 } else if( bytes == 0 ) {
809 Warning( "mergeDirectory",
810 "No payload was written for entry %i",
811 static_cast< int >( entry ) );
812 }
813 }
814
815 } else {
816 Fatal(
"mergeDirectory",
818 static_cast< int >( mode ) );
819 }
820
821
822 processedTrees.insert(
key->GetName() );
823
824 }
else if(
obj->IsA()->InheritsFrom(
"TObject" ) ) {
825
826 if( m_verbosity >= 3 ) {
827 Info(
"mergeDirectory",
"Appears to be a TObject of type %s",
828 obj->IsA()->GetName() );
829 }
830
831
832 ::TClass*
cl = ::TClass::GetClass(
key->GetClassName() );
833 if( ( ! cl ) || ( !
cl->IsLoaded() ) ) {
834 continue;
835 }
836
837 if( m_verbosity >= 3 ) {
838 Info(
"mergeDirectory",
"We seem to have a dictionary for it" );
839 }
840
841
842 TObject* oobj =
output.Get(
key->GetName() );
843
844
845
846 if( oobj ) {
847 const StatusCode ret = mergeObject( *obj, *oobj );
848 if( ret.isSuccess() ) {
849
850
851 oobj->Write( 0, TObject::kOverwrite );
852 continue;
853 } else if( ret.isFailure() ) {
854
855 Error(
"mergeDirectory",
857 "\"%s\"" ),
obj->GetName() );
858 return StatusCode::FAILURE;
859 }
860 }
861
862 if( m_verbosity >= 3 ) {
863 Info(
"mergeDirectory",
"Simply writing it to the output" );
864 }
865
866
867
870 }
871 }
872
873
874 return StatusCode::SUCCESS;
875 }
876
893 StatusCode TFileMerger::mergeObject( ::TObject& input, ::TObject& output ) {
894
895 if( m_verbosity >= 3 ) {
896 Info(
"mergeObject",
"Called mergeObject( %s, %s )",
898 }
899
900
901 if( strcmp(
input.IsA()->GetName(),
output.IsA()->GetName() ) ) {
902 Error(
"mergeObject",
903 XAOD_MESSAGE(
"Received objects of different types" ) );
904 Error(
"mergeObject",
906 Error(
"mergeObject",
908 return StatusCode::FAILURE;
909 }
910
911
912 ::TMethodCall mergeMethod;
913 mergeMethod.InitWithPrototype(
output.IsA(),
"Merge",
"TCollection*" );
914 if( ! mergeMethod.IsValid() ) {
915
916 if( m_verbosity >= 3 ) {
917 Info(
"mergeObject",
"Type doesn't have a Merge function" );
918 }
919 return StatusCode::RECOVERABLE;
920 }
921
922
923
926
927
928 mergeMethod.SetParam( ( Long_t ) &list );
929 mergeMethod.Execute( &output );
930
931 if( m_verbosity >= 3 ) {
932 Info(
"mergeObject",
"Merging executed successfully" );
933 }
934
935
936 return StatusCode::SUCCESS;
937 }
938
939 StatusCode TFileMerger::createMetaDataTools() {
940
941
942 for( const std::string& typeName : m_metaDataToolNames ) {
943
944
945 if( m_metaDataTools.find( typeName ) != m_metaDataTools.end() ) {
946 continue;
947 }
948
949
950 ::TClass*
cl = ::TClass::GetClass(
typeName.c_str() );
951 if( ! cl ) {
952 Error(
"createMetaDataTools",
955 return StatusCode::FAILURE;
956 }
957 void*
ptr =
cl->New();
958 if( ! ptr ) {
959 Error(
"createMetaDataTools",
962 return StatusCode::FAILURE;
963 }
964
965
966 ::TMethodCall initMethod;
967 initMethod.InitWithPrototype( cl, "initialize", "" );
968 if( initMethod.IsValid() ) {
969
970
971 const std::string returnTypeName =
972 initMethod.GetMethod()->GetReturnTypeNormalizedName();
973 ::TClass* returnCl = ::TClass::GetClass( returnTypeName.c_str(),
974 kTRUE, kTRUE );
975 if( returnCl &&
976 returnCl->GetListOfMethods()->FindObject( "ignore" ) ) {
978 initMethod.Execute( ptr, "", &statusCode );
979 if( ! statusCode ) {
980 Warning( "createMetaDataTools", "No StatusCode was returned" );
981 }
982 ::TMethodCall ignoreMethod;
983 ignoreMethod.InitWithPrototype( returnCl, "ignore", "" );
984 if( ignoreMethod.IsValid() && statusCode ) {
985 ignoreMethod.Execute( static_cast< void* >( statusCode ) );
986 } else {
987 Error(
"createMetaDataTools",
989 "of the initialize() function's return "
990 "type" ) );
991 }
992 } else {
993
994
995
996 initMethod.Execute( ptr );
997 }
998 } else {
999 Warning( "createMetaDataTools",
1000 "No initialize() function found for tool \"%s\"",
1002 }
1003
1004
1005 m_metaDataTools[
typeName ] = THolder( ptr, cl );
1006 if( m_verbosity > 0 ) {
1007 Info(
"createMetaDataTools",
"Created tool of type \"%s\"",
1009 }
1010 }
1011
1012
1013 return StatusCode::SUCCESS;
1014 }
1015
1024 std::vector< ::TBranch* >
1025 TFileMerger::getMissingBranches( ::TTree* first,
1026 ::TTree* second ) const {
1027
1028
1029 std::vector< ::TBranch* >
result;
1030
1031
1032 ::TObjArray* brFirst =
first->GetListOfBranches();
1033 ::TObjArray* brSecond =
second->GetListOfBranches();
1034
1035
1036 for( ::Int_t i = 0;
i < brFirst->GetEntries(); ++
i ) {
1037
1038 if( brSecond->FindObject( brFirst->At( i )->GetName() ) ) {
1039 continue;
1040 }
1041
1042 ::TBranch*
br =
dynamic_cast< ::TBranch*
>( brFirst->At( i ) );
1043 if( ! br ) {
1044 Fatal(
"getMissingBranches",
1045 XAOD_MESSAGE(
"Couldn't cast branch to TBranch?!?" ) );
1047 }
1048
1050 ::EDataType
dt = kOther_t;
1051 if(
br->GetExpectedType( cl, dt ) ) {
1052 Error(
"getMissingBranches",
1053 XAOD_MESSAGE(
"Type could not be extracted for branch "
1054 "\"%s\"" ),
br->GetName() );
1055 continue;
1056 }
1057 if( cl && ( !
cl->IsLoaded() ) ) {
1058 continue;
1059 }
1060
1061
1063 }
1064
1065
1067 }
1068
1069 std::vector< ::TBranch* >
1070 TFileMerger::getSkippedBranches( ::TTree*
tree )
const {
1071
1072
1073 std::vector< ::TBranch* >
result;
1074
1075
1077
1078
1079
1080 for( ::Int_t i = 0;
i <
branches->GetEntries(); ++
i ) {
1081
1082 ::TBranch*
br =
dynamic_cast< ::TBranch*
>(
branches->At( i ) );
1083 if( ! br ) {
1084 Fatal(
"getSkippedBranches",
1085 XAOD_MESSAGE(
"Couldn't cast branch to TBranch?!?" ) );
1087 }
1088
1090 ::EDataType
dt = kOther_t;
1091 if(
br->GetExpectedType( cl, dt ) ) {
1092 Error(
"getSkippedBranches",
1093 XAOD_MESSAGE(
"Type could not be extracted for branch "
1094 "\"%s\"" ),
br->GetName() );
1095 continue;
1096 }
1097
1098
1099 if( cl && ( !
cl->IsLoaded() ) ) {
1101 }
1102 }
1103
1105 }
1106
1114 StatusCode TFileMerger::addAuxBranch( ::TTree* otree,
1115 ::TBranch* ibranch ) const {
1116
1117
1119 ::EDataType
dt = kOther_t;
1120 if( ibranch->GetExpectedType( cl, dt ) ) {
1121 Error(
"addAuxBranch",
1122 XAOD_MESSAGE(
"Type could not be extracted for branch \"%s\"" ),
1123 ibranch->GetName() );
1124 return StatusCode::FAILURE;
1125 }
1126
1127
1128 ::TBranch* obranch = 0;
1129
1130
1131 if( cl ) {
1132
1134 obranch = otree->Branch( ibranch->GetName(),
cl->GetName(),
1135 &ptr, ibranch->GetBasketSize(),
1136 ibranch->GetSplitLevel() );
1137 if( ! obranch ) {
1138 Error(
"addAuxBranch",
1139 XAOD_MESSAGE(
"Couldn't create auxiliary branch \"%s\" with "
1140 "type: %s" ),
1141 ibranch->GetName(),
cl->GetName() );
1142 return StatusCode::FAILURE;
1143 }
1144 } else if( dt != kOther_t ) {
1145
1147 Utils::rootType( Utils::getTypeInfo( dt ).
name()[ 0 ] );
1148 if( rootType == '\0' ) {
1149 Error(
"addAuxBranch",
1150 XAOD_MESSAGE(
"Type can't be extracted for EDataType = %i"),
1151 static_cast< int >( dt ) );
1152 return StatusCode::FAILURE;
1153 }
1154 std::ostringstream leaflist;
1155 leaflist << ibranch->GetName() <<
"/" <<
rootType;
1157 obranch = otree->Branch( ibranch->GetName(), ptr,
1158 leaflist.str().c_str(),
1159 ibranch->GetBasketSize() );
1160 if( ! obranch ) {
1161 Error(
"addAuxBranch",
1162 XAOD_MESSAGE(
"Couldn't create auxiliary branch \"%s\" with "
1163 "data type: %i" ),
1164 ibranch->GetName(), static_cast< int >( dt ) );
1165 return StatusCode::FAILURE;
1166 }
1167 } else {
1168 Error(
"addAuxBranch",
1169 XAOD_MESSAGE(
"Couldn't figure out the type of branch \"%s\"" ),
1170 ibranch->GetName() );
1171 return StatusCode::FAILURE;
1172 }
1173
1174
1175 obranch->SetAddress( 0 );
1176 for( ::Long64_t i = 0;
i < otree->GetEntries(); ++
i ) {
1177 if( obranch->Fill() < 0 ) {
1178 Error(
"addAuxBranch",
1179 XAOD_MESSAGE(
"Failed to fill branch \"%s\" with dummy "
1180 "data" ), obranch->GetName() );
1181 return StatusCode::FAILURE;
1182 }
1183 }
1184
1185
1186 return StatusCode::SUCCESS;
1187 }
1188
1189}
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Error
The different types of error that can be flagged in the L1TopoRDO.
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
char rootType(char typeidType)
This function is used internally in the code when creating primitive dynamic auxiliary branches.
EventFormat_v1 EventFormat
Definition of the current event format version.