ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMSelector.cxx
Revision: 1.22
Committed: Sat Apr 7 10:13:32 2012 UTC (13 years, 1 month ago) by bendavid
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_030, Mit_029c, Mit_029b, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_028, Mit_027a, Mit_027, Mit_026, HEAD
Changes since 1.21: +2 -9 lines
Log Message:
fix for auto branch loading to follow changes to TBranchRef behaviour in Root 532

File Contents

# Content
1 //
2 // $Id: TAMSelector.cxx,v 1.21 2012/03/28 12:15:37 paus Exp $
3 //
4
5 #include "MitAna/TAM/interface/TAMSelector.h"
6
7
8 #ifndef ROOT_RVersion
9 #include <RVersion.h>
10 #endif
11 #ifndef ROOT_TFile
12 #include "TFile.h"
13 #endif
14 #ifndef ROOT_TTree
15 #include "TTree.h"
16 #endif
17 #ifndef ROOT_TError
18 #include "TError.h"
19 #endif
20 #ifndef ROOT_TROOT
21 #include "TROOT.h"
22 #endif
23 #ifndef ROOT_TList
24 #include "TList.h"
25 #endif
26 #ifndef ROOT_TClass
27 #include "TClass.h"
28 #endif
29 #ifndef ROOT_TProcessID
30 #include "TProcessID.h"
31 #endif
32 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,0,0) && \
33 ROOT_VERSION_CODE < ROOT_VERSION(5,11,2)
34 #ifndef ROOT_TUrl
35 #include "TUrl.h"
36 #endif
37 #endif
38 #ifndef ROOT_TRefTable
39 #include <TRefTable.h>
40 #endif
41 #ifndef ROOT_TBranchRef
42 #include <TBranchRef.h>
43 #endif
44 #ifndef ROOT_TFriendElement
45 #include "TFriendElement.h"
46 #endif
47 #ifndef TAM_TAModule
48 #include "MitAna/TAM/interface/TAModule.h"
49 #endif
50 #ifndef TAM_TAMOutput
51 #include "MitAna/TAM/interface/TAMOutput.h"
52 #endif
53 #ifndef TAM_TAMVirtualLoader
54 #include "MitAna/TAM/interface/TAMVirtualLoader.h"
55 #endif
56 #ifndef TAM_TAMVirtualBranchLoader
57 #include "MitAna/TAM/interface/TAMVirtualBranchLoader.h"
58 #endif
59 #ifndef TAM_TAMTreeLoader
60 #include "MitAna/TAM/interface/TAMTreeLoader.h"
61 #endif
62 #include <map>
63
64 //////////////////////////////////////////////////////////////////////////
65 // //
66 // TAMSelector //
67 // //
68 // A selector class for modular processing of a tree (or chain). //
69 // Processing is done by TAModule(s). //
70 // //
71 // Each TAModule contains pointers to the objects that will be read //
72 // in from the tree. For each such pointer, it will call //
73 // ReqBranch(name, pointer) to request that the branch be available for //
74 // processing by the module. The module's pointer would then be //
75 // automatically set to point to the object for the current event by //
76 // the TAMSelector, whenever the module calls LoadBranch. //
77 // //
78 // TAMSelector provides (and hides) all interaction with the tree //
79 // for the TAModule(s). //
80 // //
81 // Author : Corey Reed 07/20/2004 //
82 // Maarten Ballintijn 12/06/2005 //
83 // Constantin Loizides 12/06/2005 //
84 // //
85 //////////////////////////////////////////////////////////////////////////
86
87 ClassImp(TAMSelector)
88
89
90 #if ROOT_VERSION_CODE < ROOT_VERSION(5,11,3)
91 #define R__ASSERT(e) \
92 if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
93 #endif
94
95 //______________________________________________________________________________
96 TAMSelector::BranchProxy::BranchProxy(TAMSelector *sel, Bool_t e) :
97 fSel(sel),
98 fOrig(0),
99 fFake(new TRefTable(this, 10)),
100 fCurEntry(-1)
101 {
102 // Default constructor.
103
104 memset(fBrRead, 0, 1024*sizeof(Bool_t));
105
106 if (e)
107 Enable();
108 }
109
110
111 //______________________________________________________________________________
112 TAMSelector::BranchProxy::~BranchProxy()
113 {
114 // Destructor.
115
116 Disable();
117 delete fFake;
118 fFake = 0;
119 }
120
121
122 //______________________________________________________________________________
123 void TAMSelector::BranchProxy::Disable()
124 {
125 // Disable the auto branch loading via TAM.
126
127 if (fOrig)
128 TRefTable::SetRefTable(fOrig);
129 }
130
131
132 //______________________________________________________________________________
133 void TAMSelector::BranchProxy::Enable()
134 {
135 // Enable the auto branch loading via TAM.
136
137 TBranchRef *bref = fSel->GetTree()->GetTree()->GetBranchRef();
138 if (bref) {
139 fOrig = bref->GetRefTable();
140 TRefTable::SetRefTable(fFake);
141 }
142 }
143
144
145 //______________________________________________________________________________
146 TObject *TAMSelector::BranchProxy::GetObjectWithID(UInt_t uid, TProcessID *pid)
147 {
148 // This function should be called by a reference class which is designed to
149 // use TAM. Branch loading via TAM is handled through the BranchProxy class.
150 // Optimized loading is used if the object table cleaning has been
151 // enabled in TAM.
152
153 // printf("enter TAMSelector::BranchProxy::GetObjectWithID: %d\n",uid);
154
155 if (fSel->GetObjTabClean()) {
156 // can trust that object table was cleaned
157 TObject *obj = pid->GetObjectWithID(uid);
158 if (obj)
159 return obj;
160 }
161
162 TBranchRef *br = fSel->GetTree()->GetTree()->GetBranchRef();
163 if (!br)
164 return pid->GetObjectWithID(uid);
165
166 //printf(" br table loaded %p\n",(void*)br);
167
168 TRefTable *table = br->GetRefTable();
169 if (!table)
170 return pid->GetObjectWithID(uid);
171
172 //printf(" ref table loaded %p\n",(void*)table);
173
174 table->SetUID(uid,pid);
175
176
177 //printf("loading\n");
178 Load(uid,pid,br,table);
179 //printf(" loaded %p\n",(void*)pid->GetObjectWithID(uid));
180
181 return pid->GetObjectWithID(uid);
182 }
183
184
185 //______________________________________________________________________________
186 Bool_t TAMSelector::BranchProxy::Load(UInt_t uid, TProcessID *pid,
187 TBranchRef *br, TRefTable *table)
188 {
189 // Find and load branch corresponding to given uid/pid.
190
191 // read entry for this event
192 Long64_t readentry = fSel->fCurEvt;
193 Long64_t chainentry = readentry + fSel->GetTree()->GetChainOffset();
194
195 // read branchref if needed
196 if (fCurEntry != chainentry) {
197 Int_t bytes = br->GetEntry(readentry);
198 if (bytes<0) {
199 Fatal("Load", "Could not get entry %lld from %s branch",
200 readentry, br->GetName());
201 }
202 }
203
204 // get branch from RefTable
205 TBranch *branch = dynamic_cast<TBranch*>(table->GetParent(uid, pid));
206
207 if (!branch) { //scan for possible friend Trees
208 TList *friends = fSel->GetTree()->GetListOfFriends();
209 if (friends) {
210
211 // reset branch read flags if new entry to be read
212 if (fCurEntry != chainentry)
213 memset(fBrRead, 0, 1024*sizeof(Bool_t));
214
215 TObjLink *lnk = friends->FirstLink();
216 Int_t nfriend = 0;
217 while (lnk) {
218 TFriendElement *elem =
219 static_cast<TFriendElement*>(lnk->GetObject());
220 TBranchRef *bref = elem->GetTree()->GetBranchRef();
221 if (bref) {
222 if (!fBrRead[nfriend]) {
223 bref->GetEntry(readentry);
224 fBrRead[nfriend] = kTRUE;
225 }
226 TBranch *branch = dynamic_cast<TBranch*>
227 (bref->GetRefTable()->GetParent(uid, pid));
228 if (branch)
229 break; // found branch
230 }
231 lnk = lnk->Next();
232 ++nfriend;
233 R__ASSERT(nfriend<1024);
234 }
235 }
236 }
237
238 // cache last branch read attempt
239 fCurEntry = chainentry;
240
241 if (!branch) {
242 return kFALSE;
243 }
244
245 // access the main branch
246 TBranch *readbranch = branch->GetMother();
247 if (!readbranch) {
248 return kFALSE;
249 }
250
251 // check if TAMBranchInfo already exists
252 // and if not add it
253 const char *brname = readbranch->GetName();
254 TObject *brInfo = fSel->fBranchTable.FindObject(brname);
255 TAMBranchInfo *branchInfo;
256 if (brInfo==0) {
257 branchInfo = new TAMBranchInfo(brname);
258 fSel->fBranchTable.Add(branchInfo);
259 }
260 else
261 branchInfo = dynamic_cast<TAMBranchInfo*>(brInfo);
262
263 // load the branch
264 fSel->LoadBranch(branchInfo);
265
266 return kTRUE;
267 }
268
269
270 //______________________________________________________________________________
271 Bool_t TAMSelector::BranchProxy::Notify()
272 {
273 // Notification received from TRefTable::Notify. Originally this would
274 // have been address to the TBranchRef owner of the TRefTable, but
275 // we intercept this call.
276
277 if (!fOrig)
278 return kFALSE;
279
280 TBranchRef *br = dynamic_cast<TBranchRef*>(fOrig->GetOwner());
281 if (!br)
282 return kFALSE;
283
284 // get the desired uid/pid pair
285 UInt_t uid = fFake->GetUID();
286 TProcessID *pid = fFake->GetUIDContext();
287 fOrig->SetUID(uid,pid);
288 if (0) // this is what ROOT would have done
289 return br->Notify();
290
291 return Load(uid, pid, br, fOrig);
292 }
293
294 //______________________________________________________________________________
295 TAMSelector::TAMSelector() :
296 fTree(0),
297 fTreeCache(0),
298 fCacheSize(0),
299 fBranchTable(TCollection::kInitHashTableCapacity, 1),
300 fEventObjs(TCollection::kInitHashTableCapacity, 1),
301 fAModules(new TAModule("TAMTopModule",
302 "Top-most module containing all other modules.")),
303 fCurEvt(-1),
304 fOwnInput(0),
305 fAnalysisAborted(kFALSE),
306 fModAborted(kFALSE),
307 fEventAborted(kFALSE),
308 fActNotify(kFALSE),
309 fObjCounter(0),
310 fVerbosity(0),
311 fProxy(this),
312 fDoProxy(kFALSE),
313 fDoObjTabClean(kFALSE),
314 fObjTabClean(kFALSE),
315 fLoaders()
316 {
317 // Default constructor.
318
319 fBranchTable.SetOwner(kTRUE);
320 fEventObjs.SetOwner(kTRUE);
321 gROOT->GetListOfBrowsables()->Add(fAModules,"Analysis Modules");
322 fLoaders.SetName("TAM_LOADERS");
323 }
324
325
326 //______________________________________________________________________________
327 TAMSelector::~TAMSelector()
328 {
329 // Destructor.
330
331 gROOT->GetListOfBrowsables()->Remove(fAModules);
332 TList *submods = fAModules->GetListOfTasks();
333 if (submods!=0) submods->Clear("nodelete");
334 delete fAModules;
335 delete fOwnInput;
336 }
337
338
339 //______________________________________________________________________________
340 void TAMSelector::AbortAnalysis()
341 {
342 // Aborts the analysis by aborting all modules and never executing
343 // further module funtions.
344
345 // no way known to propagate the stop of analysis in PROOF from
346 // one slave to the other slaves (and master).
347 Fatal("AbortAnalysis", "Analysis aborted!");
348
349 fAModules->DeactivateAll();
350 fAnalysisAborted = kTRUE;
351 }
352
353
354 //______________________________________________________________________________
355 void TAMSelector::AbortEvent()
356 {
357 // Aborts the current event by setting all modules inactive.
358
359 fAModules->DeactivateAll();
360 fEventAborted = kTRUE;
361 }
362
363
364 //______________________________________________________________________________
365 void TAMSelector::AbortModule(TAModule *mod)
366 {
367 // Abort the specified module by setting it (and its sub modules) inactive.
368
369 mod->DeactivateAll();
370 fModAborted = kTRUE;
371 }
372
373
374 //______________________________________________________________________________
375 void TAMSelector::AddInput(TAModule *mod)
376 {
377 // Adds the module to the top-most module in the hierarchy.
378 // The "misnomer" on the function name is intentional:
379 // This allows users to call gProof->AddInput(myMod) when
380 // using proof and mySelector->AddInput(myMod) when not
381 // using proof.
382
383 fAModules->Add(mod);
384 }
385
386 //______________________________________________________________________________
387 Bool_t TAMSelector::AddObjThisEvt(TObject *obj)
388 {
389 // Add this object to the list of objects stored for this event.
390 // See further description below.
391
392 if (obj)
393 return AddObjThisEvt(obj,obj->GetName());
394 else {
395 Error("AddObjThisEvt","Can not add null object to event.");
396 return kFALSE;
397 }
398 }
399
400
401 //______________________________________________________________________________
402 Bool_t TAMSelector::AddObjThisEvt(TObject *obj, const char *name)
403 {
404 // Add this object to the list of objects stored for this event.
405 // NOTE:
406 // - The object must have a unique name.
407 // - The object must be on the heap.
408 // - The object will be owned by the selector and deleted at the
409 // end of the processing of the current event.
410 //
411 // Returns true iff the object meets the requirements and is added to
412 // the list successfully.
413
414 if (obj!=0) {
415 if (FindObjThisEvt(name)==0) {
416 if (obj->IsOnHeap()) {
417 fEventObjs.Add(new TAMEvtObj(obj,name));
418 return kTRUE;
419 } else {
420 Error("AddObjThisEvt",
421 "Object [%s] does not appear to be on heap. "
422 "Can not add object.",
423 name);
424 }
425 } else {
426 Error("AddObjThisEvt",
427 "Object with name [%s] already added to this event.",
428 name);
429 }
430 } else {
431 Error("AddObjThisEvt",
432 "Can not add null object to event.");
433 }
434 return kFALSE;
435 }
436
437
438 //______________________________________________________________________________
439 void TAMSelector::AddNewOutputLists()
440 {
441 // Make a new hierarchy of TAMOutput objects and add it to
442 // the output of this selector. Note that this should only be called
443 // ONCE (by SlaveBegin())!!
444
445 fAModules->NewOutputList(GetOutputList());
446 }
447
448
449 //______________________________________________________________________________
450 void TAMSelector::Begin(TTree */*tree*/)
451 {
452 // The Begin() function is called at the start of the query.
453 // When running with PROOF Begin() is only called on the client.
454 // The tree argument is deprecated (on PROOF 0 is passed).
455 // It checks the tree of modules to be sure each module is set
456 // up to use this selector.
457 // Adds the tree of modules to the input list of this selector.
458 // Builds the hierarchy of TAMOutput objects in the output list.
459 // Then calls Begin() on the TAModule(s). At the end, it adds the
460 // list of loaders to the input list.
461
462 if (fAnalysisAborted) {
463 return;
464 } else {
465 if (fInput==0) {
466 fOwnInput = new TList;
467 SetInputList(fOwnInput);
468 }
469 CopyModsFromInput();
470 fAModules->SetSelector(this);
471 if (fAModules->CheckSelectors(this)) {
472 if (fModAborted) {
473 fAModules->ResetAllActiveFlags();
474 fModAborted = kFALSE;
475 }
476 fAModules->ExecuteTask(&TAModule::kExecBegin);
477 if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
478 } else {
479 Error("Begin",
480 "One or more module is not set up to use this selector.");
481 R__ASSERT(0);
482 }
483 }
484
485 fInput->AddLast(&fLoaders);
486 }
487
488
489 //______________________________________________________________________________
490 void TAMSelector::CleanObjTable(TProcessID *pid, UInt_t lastKeptUID) const
491 {
492 // Clear from the object table of a given process id, all pointers for objects
493 // with uids after lastKeptUid.
494
495 TObjArray *objTable = pid->GetObjects();
496
497 Int_t lastIdxKept = lastKeptUID & 0xffffff;
498 Int_t last = objTable->GetLast();
499
500 if (last==-1)
501 return;
502
503 if (lastIdxKept>=0 && lastIdxKept<=last) {
504 TObject **cont = objTable->GetObjectRef(0);
505 memset(&cont[lastIdxKept+1],0,(last-lastIdxKept)*sizeof(TObject*));
506 objTable->SetLast(lastIdxKept);
507 }
508 else
509 Error("TAMSelector::CleanObjTable",
510 "Out of Bounds trying to clean object table from Process ID.");
511 }
512
513
514 //______________________________________________________________________________
515 void TAMSelector::ClearAllLoaders()
516 {
517 // Go through the list of requested branches and clear the
518 // loaders that were used.
519
520 TIter nextBr(fBranchTable.MakeIterator());
521 while (TAMBranchInfo *br = dynamic_cast<TAMBranchInfo*>(nextBr())) {
522
523 if (!br->fIsLoaded) continue;
524 // don't bother with branches that weren't loaded
525
526 TAMVirtualBranchLoader *l = br->GetLoader();
527 if (l) {
528 l->Clear();
529 } else {
530 Error("ClearAllLoaders",
531 "Could not get loader for [%s]. Unable to "
532 "try to clear loader for this branch.",
533 br->GetName());
534 }
535 }
536 }
537
538
539 //______________________________________________________________________________
540 void TAMSelector::CopyModsFromInput()
541 {
542 // Find all TAModules in the input list and copy them to fAModules.
543
544 R__ASSERT(fInput!=0);
545
546 if (fInput->IsEmpty()) return;
547
548 TObject *obj=fInput->First(), *tobj=0;
549 while (obj!=0) {
550 tobj = fInput->After(obj);
551 if (obj->InheritsFrom(TAModule::Class())) {
552 AddInput(dynamic_cast<TAModule*>(obj));
553 }
554 obj = tobj;
555 }
556 }
557
558
559 //______________________________________________________________________________
560 Bool_t TAMSelector::FindLoader(TAMBranchInfo *brInfo)
561 {
562 // Find the loader responsible for the given branch info. Return kFALSE
563 // if none could be found in the list of loaders.
564
565 const char *bname = brInfo->GetName();
566 TIter next(&fLoaders);
567
568 while( TAMVirtualLoader *l = dynamic_cast<TAMVirtualLoader*>(next()) ) {
569 TAMVirtualBranchLoader *bl = l->CreateBranchLoader(fTree, brInfo);
570 if (bl != 0) {
571 Info("FindLoader","branch '%s' use loader %s",
572 bname, bl->IsA()->GetName());
573 brInfo->SetLoader(bl);
574 return kTRUE;
575 }
576 }
577
578 Error("FindLoader","No loader found for branch '%s'", bname);
579 return kFALSE;
580 }
581
582
583 //______________________________________________________________________________
584 TAMOutput *TAMSelector::FindModOutput(const TAModule *mod)
585 {
586 // Find the TAMOutput object corresponding to the given module.
587
588 TAMOutput *obj=0, *tobj=0;
589 TIter nextObj(GetOutputList());
590 while ( (obj = dynamic_cast<TAMOutput*>(nextObj())) ) {
591 tobj = obj->FindModOutput(mod); // search mod and sub mods
592 if (tobj!=0) return tobj;
593 }
594 return 0;
595 }
596
597
598 //______________________________________________________________________________
599 TObject *TAMSelector::FindObjThisEvt(const Char_t *name) const
600 {
601 // Looks for the object with the specified name that was added to
602 // this event. If not found, returns zero.
603
604 TAMEvtObj *eo = dynamic_cast<TAMEvtObj*>(fEventObjs.FindObject(name));
605 if (eo!=0) {
606 return eo->fObj;
607 }
608 return 0;
609 }
610
611
612 //______________________________________________________________________________
613 TObject *TAMSelector::FindPublicObj(const Char_t *name) const
614 {
615 // Looks for the public object with the specified name. If not found,
616 // returns zero.
617 // Note: TAModules are not public objects and will not be found by this
618 // function.
619
620 if (fInput!=0) {
621 TIter nextObj(fInput);
622 TObject *obj=0;
623 TString nm(name);
624 while ( (obj = nextObj()) ) {
625 if ( (nm.CompareTo(obj->GetName())==0) &&
626 (obj->InheritsFrom(TAModule::Class())==kFALSE) ) {
627 return obj;
628 }
629 }
630 } else {
631 Error("FindPublicObj",
632 "Input list is null. No public objects exist.");
633 }
634 return 0;
635 }
636
637
638 //______________________________________________________________________________
639 const TFile *TAMSelector::GetCurrentFile() const
640 {
641 // Returns the current file that the tree is in.
642
643 return (fTree) ? (const_cast<const TFile *>(fTree->GetCurrentFile())) : 0;
644 }
645
646
647 //______________________________________________________________________________
648 TFile *TAMSelector::GetCurrentFile()
649 {
650 // Returns the current file that the tree is in.
651
652 return (fTree) ? (fTree->GetCurrentFile()) : 0;
653 }
654
655
656 //______________________________________________________________________________
657 const TAMOutput *TAMSelector::GetModOutput() const
658 {
659 // Return the top-most module output object.
660
661 return fAModules->GetModOutput();
662 }
663
664
665 //______________________________________________________________________________
666 TAMOutput *TAMSelector::GetModOutput()
667 {
668 // Return the top-most module output object.
669
670 return fAModules->GetModOutput();
671 }
672
673
674 //______________________________________________________________________________
675 TObject *TAMSelector::GetObjectWithID(UInt_t uid, TProcessID *pid)
676 {
677 // This function should be called by a reference class which is designed to
678 // use TAM. Branch loading via TAM is handled through the BranchProxy class.
679 // Optimized loading is used if the object table cleaning has been
680 // enabled in TAM.
681
682 return fProxy.GetObjectWithID(uid,pid);
683 }
684
685
686 //__________________________________________________________________________________________________
687 void TAMSelector::Init(TTree *tree)
688 {
689 // Set the tree for this selector. The Init() function is called when the selector needs to
690 // initialize a new tree (or chain). It will be called many times when running with PROOF. The
691 // list of requested branches must have been constructed already.
692
693 if (tree==0) {
694 Error("Init", "Specified tree is null.");
695 AbortAnalysis();
696 }
697
698 fTree = tree;
699
700 TIter nextBranch(fBranchTable.MakeIterator());
701 while ( TAMBranchInfo *brInfo =
702 dynamic_cast<TAMBranchInfo*>(nextBranch()) ) {
703 brInfo->Init();
704 }
705 }
706
707
708 //______________________________________________________________________________
709 void TAMSelector::LoadBranch(const Char_t *bname)
710 {
711 // Loads branch by name, getting the pointer to the corresponding
712 // TAMBranchInfo and then use it in the call of the protected LoadBranch
713 // function.
714
715 if(fCurEvt==-1) {
716 Error("LoadBranch",
717 "Can not load branch with name [%s] at this point (fCurEvt==-1).",
718 bname);
719 AbortAnalysis();
720 }
721
722 TAMBranchInfo *brInfo =
723 dynamic_cast<TAMBranchInfo*>( fBranchTable.FindObject(bname) );
724
725 if (brInfo==0) {
726 Error("LoadBranch",
727 "Could not find branch with name [%s] in requested branch list.",
728 bname);
729 AbortAnalysis();
730 }
731
732 LoadBranch(brInfo);
733 }
734
735
736 //______________________________________________________________________________
737 void TAMSelector::LoadBranch(TAMBranchInfo* brInfo)
738 {
739 // Loads the selected branch and get the current entry (number fCurEvt)
740 // if the branch has not yet been loaded for this event. It then makes
741 // sure each module's pointer to the branch object point to the address
742 // of this branch.
743
744 if (brInfo->IsLoaded())
745 return;
746
747 // find loader for branch info if needed and notify
748 if (brInfo->GetLoader() == 0) {
749
750 if ( !FindLoader(brInfo) ) {
751 Error("LoadBranch","Branch [%s] FindLoader() failed in file [%s].",
752 brInfo->GetName(),
753 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null");
754
755 AbortAnalysis();
756 }
757
758 if ( !brInfo->Notify(fTree) )
759 Error("LoadBranch","Branch [%s] Notify() failed in file [%s].",
760 brInfo->GetName(),
761 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null");
762
763 // have to reset our object counter to take care of objects
764 // created in the notify of the loader
765 //fObjCounter=TProcessID::GetObjectCount();
766 }
767
768 // load the entry (using the cache)
769 if (fTreeCache)
770 GetCurrentFile()->SetCacheRead(fTreeCache);
771 Int_t ret = brInfo->GetEntry(fCurEvt);
772 if (fTreeCache)
773 GetCurrentFile()->SetCacheRead(0);
774
775
776 if(ret<0) {
777 Error("LoadBranch",
778 "Error in file [%s] when accessing branch with name [%s] in "
779 "requested branch list.",
780 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
781 : "null", brInfo->GetName());
782
783 AbortAnalysis();
784 }
785
786 // make sure autoload proxy is enabled
787 if (fDoProxy)
788 fProxy.Enable();
789 }
790
791
792 //______________________________________________________________________________
793 Bool_t TAMSelector::Notify()
794 {
795 // Sets the branch pointers, checks that the types of the module's
796 // pointers correspond to what is in the tree and calls SetBranchAddress
797 // if necessary. Finally, it also notifies the modules.
798 // The Notify() function is called when a new file is opened. This
799 // can be either for a new TTree in a TChain or when a new TTree
800 // is started when using PROOF.
801
802 // we are just in Notify(), therefore we ignore this call
803 if(fActNotify) return kTRUE;
804 fActNotify = kTRUE; //"lock" to protect for recursive calls
805
806 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,0,0) && \
807 ROOT_VERSION_CODE < ROOT_VERSION(5,11,2)
808
809 // workaround for older ROOT: give file name to
810 // TFile that accidentally stripped the protocol
811 const TUrl *url = (GetCurrentFile()!=0)
812 ? GetCurrentFile()->GetEndpointUrl() : 0;
813
814 if (url==0) {
815 Warning("Notify","Could not get URL for file [%s].",
816 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
817 : "null");
818 } else {
819
820 if(GetCurrentFile()!=0)
821 GetCurrentFile()->SetName((const_cast<TUrl*>(url)->GetUrl()));
822 // the const_cast is for some version of
823 // 5.08.00 that didn't have GetUrl const.
824 }
825 #endif
826
827 if (fVerbosity>0) {
828 Info("Notify","Opening file [%s] at current event [%lld].",
829 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null",
830 fCurEvt);
831 }
832
833 // status (return value) of notify
834 Bool_t notifyStat = kTRUE;
835
836 // Set up the caching process
837 if (fCacheSize > 0) {
838 fTreeCache->SetLearnEntries(1);
839 fTree->SetCacheSize(128*1024*1024);
840 printf(" CurrentFile Name: %s\n",fTree->GetCurrentFile()->GetName());
841 if (fTreeCache)
842 delete fTreeCache;
843 fTreeCache = dynamic_cast<TTreeCache*>(fTree->GetCurrentFile()->GetCacheRead());
844 fTree->GetCurrentFile()->SetCacheRead(0);
845
846 //// Read all data products (even if we don't use them).
847 //// Remove the below lines to read minimal sets of products.
848 //// Removing would cause many more I/O operations and slow the cluster.
849 //fTreeCache->StartLearningPhase();
850 //fTreeCache->AddBranch("*", kTRUE);
851 //fTreeCache->StopLearningPhase();
852 }
853
854 // no event yet processed eg, no loaders assigned,
855 // so that the notify is being delayed to LoadBranch()
856 if(fCurEvt>=0) {
857
858 TIter nextBranch(fBranchTable.MakeIterator());
859
860 while ( TAMBranchInfo *brInfo =
861 dynamic_cast<TAMBranchInfo*>(nextBranch()) ) {
862
863 // notify the branchinfo and its corresponding loader
864 notifyStat &= brInfo->Notify(fTree);
865
866 // have to reset our object counter to take care of objects
867 // created in the notify of the loader
868 //fObjCounter=TProcessID::GetObjectCount();;
869
870 if (notifyStat==kFALSE) {
871 Error("Notify","Branch [%s] Notify() failed in file [%s].",
872 brInfo->GetName(),
873 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
874 : "null");
875
876 AbortAnalysis();
877 }
878 }
879
880 // status (return value) of notify
881 notifyStat = kTRUE;
882
883 }
884
885 if (notifyStat && (fAnalysisAborted==kFALSE)) {
886 notifyStat &= fAModules->NotifyAll();
887 }
888
889 //release "lock" on notify
890 fActNotify = kFALSE;
891
892 return notifyStat;
893 }
894
895
896 //______________________________________________________________________________
897 Bool_t TAMSelector::Process(Long64_t entry)
898 {
899 // Zero's all TAModule(s)'s branch addresses and calls Process()
900 // on the TAModule(s). Then clear any requested clones arrays and
901 // clear the list of event-stored objects.
902 //
903 // The Process() function is called for each entry in the tree (or possibly
904 // keyed object in the case of PROOF) to be processed.
905
906 if (fAnalysisAborted) {
907 // There is currently no reliable way to exit cleanly back to the
908 // interpreter, so simply return immediately.
909 return kFALSE;
910 }
911
912 // prepare for event
913 fCurEvt = entry;
914 ZeroAllBranches();
915 if (fModAborted) {
916 fAModules->ResetAllActiveFlags();
917 fModAborted = kFALSE;
918 } else if (fEventAborted) {
919 fAModules->ResetAllActiveFlags();
920 fEventAborted = kFALSE;
921 }
922
923 // store object counter for run boundaries
924 if (BeginRun()) {
925 fObjCounterRun=TProcessID::GetObjectCount();;
926 fAModules->ExecuteTask(&TAModule::kExecBeginRun);
927 }
928
929 // store object counter and process event
930 fObjCounter=TProcessID::GetObjectCount();;
931 TObjArray *pids = GetCurrentFile()->GetListOfProcessIDs();
932
933 // store uids for later cleaning for object tables from file
934 std::map<TProcessID*, UInt_t> lastUIDs;
935 if (fDoObjTabClean) {
936 for (Int_t i=0; i<pids->GetEntriesFast(); ++i) {
937 TProcessID *pid = static_cast<TProcessID*>(pids->At(i));
938 Int_t last = pid->GetObjects()->GetLast();
939 if (last==-1)
940 last = 0;
941 lastUIDs[pid] = last;
942 }
943 // set clean object table state variable to true
944 fObjTabClean = kTRUE;
945 }
946
947 if (fVerbosity>9) {
948 if ((entry % 100)==0) {
949 fprintf(stderr,"Processing entry %lld... \r",
950 entry);
951 }
952 }
953
954 fAModules->ExecuteTask(&TAModule::kExecProcess);
955
956 // update object counter on run boundaries
957 if (EndRun()) {
958 fAModules->ExecuteTask(&TAModule::kExecEndRun);
959 fObjCounter=fObjCounterRun;
960 }
961
962 // cleanup
963 ClearAllLoaders();
964 if (fEventObjs.IsEmpty()==kFALSE)
965 fEventObjs.Delete();
966
967 // set clean object table state variable to false
968 fObjTabClean = kFALSE;
969
970 // restore object counter
971 TProcessID::SetObjectCount(fObjCounter);
972
973 // Clean object table for current process id:
974 // This guarantees that objects which are not yet loaded in the
975 // current event have null pointers in the object table.
976 if (fDoObjTabClean) {
977 CleanObjTable(TProcessID::GetSessionProcessID(), fObjCounter);
978
979 //clean object tables for process ids being read from the file
980 for (Int_t i=0; i<pids->GetEntriesFast(); ++i) {
981 TProcessID *pid = static_cast<TProcessID*>(pids->At(i));
982 std::map<TProcessID*, UInt_t>::const_iterator lastUID = lastUIDs.find(pid);
983 if (lastUID != lastUIDs.end()) {
984 CleanObjTable(pid, lastUID->second);
985 }
986 else {
987 CleanObjTable(pid, 0);
988 }
989 }
990 }
991
992 // Clean object table for current process id.
993 // This guarantees that objects which are not yet loaded in the
994 // current event have null pointers in the object table.
995 if (fDoObjTabClean) {
996 CleanObjTable(TProcessID::GetSessionProcessID(), fObjCounter);
997
998 //clean object tables for process ids being read from the file
999 for (Int_t i=0; i<pids->GetEntriesFast(); ++i) {
1000 TProcessID *pid = static_cast<TProcessID*>(pids->At(i));
1001 std::map<TProcessID*, UInt_t>::const_iterator lastUID =
1002 lastUIDs.find(pid);
1003 if (lastUID != lastUIDs.end())
1004 CleanObjTable(pid, lastUID->second);
1005 else
1006 CleanObjTable(pid, 0);
1007 }
1008 }
1009
1010 return kTRUE;
1011 }
1012
1013
1014 //______________________________________________________________________________
1015 Bool_t TAMSelector::PublishObj(TObject *obj)
1016 {
1017 // Adds an object to a list of objects which is outside the module
1018 // hierarchy. This can be used to pass objects (for example, calibrations)
1019 // between modules. Objects in this list are available before Begin
1020 // until the end of SlaveTerminate. They are not guaranteed to be available
1021 // during or after Terminate.
1022 // Checks (by name) if the object is already in the list. If it is, returns
1023 // kFALSE and does not publish the object.
1024 // NOTE: These objects are NOT owned by the list! Whatever creates these
1025 // objects must take care to (1) remove the object from the list using
1026 // RetractObj() and (2) delete the object.
1027 // Also NOTE: This will not publish TAModule objects.
1028
1029 if (obj!=0) {
1030 TObject *ob = FindPublicObj(obj->GetName());
1031 if (ob==0) {
1032 if (obj->InheritsFrom(TAModule::Class())) {
1033 // Disallow publishing of TAModules since it breaks the assumption
1034 // that all TAModules in the input list were added by AddInput and
1035 // are intended to be executed. (Such modules would be found by
1036 // TakeModsFromInput and CopyModsFromInput.)
1037 Warning("PublishObj",
1038 "Can not publish a TAModule. Object named [%s] not "
1039 "published.",
1040 obj->GetName());
1041 } else {
1042 if (fInput!=0) {
1043 fInput->Add(obj);
1044 return kTRUE;
1045 } else {
1046 Error("PublishObj",
1047 "Input list is null. Could not publish object named [%s].",
1048 obj->GetName());
1049 }
1050 }
1051 } else {
1052 Warning("PublishObj",
1053 "Public object named [%s] already exists.",
1054 obj->GetName());
1055 }
1056 } else {
1057 Error("PublishObj",
1058 "Can not publish null object.");
1059 }
1060 return kFALSE;
1061 }
1062
1063
1064 //______________________________________________________________________________
1065 TObject *TAMSelector::RemoveObjThisEvt(const Char_t *name)
1066 {
1067 // Finds the object with the specified name and removes it from
1068 // the list of objects added to this event.
1069 // Returns the object that was removed.
1070
1071 TAMEvtObj *eo = dynamic_cast<TAMEvtObj*>(fEventObjs.FindObject(name));
1072 if (eo!=0) {
1073 fEventObjs.Remove(eo);
1074 TObject *obj = eo->fObj;
1075 eo->fObj = 0; // so it won't delete the object
1076 delete eo;
1077 return obj;
1078 }
1079 return 0;
1080 }
1081
1082
1083 //______________________________________________________________________________
1084 TObject *TAMSelector::RetractObj(const Char_t *name)
1085 {
1086 // Finds the public object with the specified name and removes it from
1087 // the list of public objects.
1088 // Returns the object that was retracted.
1089 // Note: TAmodules are not public objects and will not be removed by this
1090 // function.
1091
1092 TObject *obj = FindPublicObj(name);
1093 if (obj!=0) {
1094 return fInput->Remove(obj);
1095 }
1096 return 0;
1097 }
1098
1099
1100 //______________________________________________________________________________
1101 void TAMSelector::SlaveBegin(TTree *tree)
1102 {
1103 // Inits the tree and calls SlaveBegin() on the TAModule(s)
1104 //
1105 // The SlaveBegin() function is called after the Begin() function.
1106 // When running with PROOF SlaveBegin() is called on each slave server.
1107 // The tree argument is deprecated (on PROOF 0 is passed).
1108
1109 if (fAnalysisAborted) {
1110 return;
1111 } else {
1112 // call SlaveBegin first so the modules can call ReqBranch and
1113 // build the fBranchTable
1114 if (fModAborted) {
1115 fAModules->ResetAllActiveFlags();
1116 fModAborted = kFALSE;
1117 }
1118 // remove the modules from the input list and put them in the top-most
1119 // module of this selector. make sure they use this selector
1120 TakeLoadersFromInput();
1121 TakeModsFromInput();
1122 fAModules->SetSelector(this);
1123 if (fAModules->CheckSelectors(this)) {
1124 // build the module output hierarchy
1125 AddNewOutputLists();
1126 // set up the module's output members
1127 if (fAModules->fOutput != 0) {
1128 fAModules->fOutput->SetAllOutputMembers(kFALSE);
1129 }
1130
1131 fAModules->ExecuteTask(&TAModule::kExecSlaveBegin);
1132 } else {
1133 Error("SlaveBegin",
1134 "One or more module is not set up to use this selector.");
1135 R__ASSERT(0);
1136 }
1137
1138 // init requires fBranchTable to be built already
1139 // in Proof, this is called automatically when a new tree is loaded
1140 if (tree)
1141 Init(tree);
1142 if (fEventObjs.IsEmpty()==kFALSE)
1143 fEventObjs.Delete();
1144 }
1145 }
1146
1147
1148 //______________________________________________________________________________
1149 void TAMSelector::SlaveTerminate()
1150 {
1151 // Calls SlaveTerminate() on the TAModule(s)
1152 // The SlaveTerminate() function is called after all entries or objects
1153 // have been processed. When running with PROOF SlaveTerminate() is called
1154 // on each slave server.
1155
1156 if (fAnalysisAborted) {
1157 return;
1158 } else {
1159 if (fModAborted) {
1160 fAModules->ResetAllActiveFlags();
1161 fModAborted = kFALSE;
1162 }
1163 fAModules->ExecuteTask(&TAModule::kExecSlaveTerminate);
1164 if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
1165 }
1166 }
1167
1168
1169 //______________________________________________________________________________
1170 void TAMSelector::TakeModsFromInput()
1171 {
1172 // Find all TAModules in the input list and move them to fAModules.
1173
1174 R__ASSERT(fInput!=0);
1175
1176 if (fInput->IsEmpty()==kFALSE) {
1177 TObject *obj=fInput->First(), *tobj=0;
1178 while (obj!=0) {
1179 tobj = fInput->After(obj);
1180 if (obj->InheritsFrom(TAModule::Class())) {
1181 AddInput(dynamic_cast<TAModule*>(obj));
1182 fInput->Remove(obj);
1183 }
1184 obj = tobj;
1185 }
1186 }
1187 }
1188
1189
1190 //______________________________________________________________________________
1191 void TAMSelector::TakeLoadersFromInput()
1192 {
1193 // Find all TAModules in the input list and copy them to fAModules.
1194
1195 R__ASSERT(fInput!=0);
1196
1197 TList *loaders = dynamic_cast<TList*>(fInput->FindObject("TAM_LOADERS"));
1198 if (loaders != 0) {
1199 TIter next(loaders);
1200 while ( TAMVirtualLoader *l =
1201 dynamic_cast<TAMVirtualLoader*>(next()) ) {
1202 if (loaders != &fLoaders) fLoaders.AddLast(l);
1203 }
1204 }
1205
1206 fLoaders.AddLast(new TAMTreeLoader());
1207 }
1208
1209
1210 //______________________________________________________________________________
1211 void TAMSelector::Terminate()
1212 {
1213 // Calls Terminate() on the TAModule(s).
1214 // When running under Proof, will copy the TAMOutput object
1215 // from the fOutput list to the top most TAModule object. Assumes
1216 // that the only TAMOutput object in fOutput is the one belonging
1217 // to the top most module.
1218 // The Terminate() function is the last function to be called during
1219 // a query. It always runs on the client, it can be used to present
1220 // the results graphically or save the results to file.
1221
1222 if (fAnalysisAborted) {
1223 return;
1224 }
1225
1226 if (fModAborted) {
1227 fAModules->ResetAllActiveFlags();
1228 fModAborted = kFALSE;
1229 }
1230
1231 if (fAModules->GetModOutput()==0) {
1232 // When running under Proof, copy the module output hierarchy to
1233 // this selector's top most module.
1234 TIter nextObj(GetOutputList());
1235 TAMOutput *tout=0;
1236 TObject *obj=0;
1237 Bool_t alreadySet=kFALSE;
1238 while ( (obj = nextObj()) ) {
1239 if (obj->InheritsFrom(TAMOutput::Class())) {
1240 tout = dynamic_cast<TAMOutput*>(obj);
1241 if (alreadySet) {
1242 Warning("Terminate",
1243 "Found more than one TAMOutput object in the "
1244 "output list. Assuming the first one is from the "
1245 "top-most module. The output list contains:");
1246 GetOutputList()->ls();
1247 } else {
1248 // copy module output hierarchy
1249 fAModules->SetAllModOutput(tout);
1250 // try to set module's pointers to their output objects
1251 tout->SetAllOutputMembers(kTRUE);
1252 alreadySet=kTRUE;
1253 }
1254 }
1255 }
1256 if (alreadySet==kFALSE) {
1257 Error("Terminate",
1258 "Did not find TAMOutput object in the output list! "
1259 "The output list contains:");
1260 GetOutputList()->ls();
1261 }
1262 }
1263
1264 // move output objs from current objects to stored objects
1265 // incase the module wants to write output to a file
1266 if (fAModules->GetModOutput()!=0) {
1267 fAModules->GetModOutput()->StoreAllOutputObjs();
1268 } else {
1269 Error("Terminate",
1270 "Could not store output objects from this process run.");
1271 }
1272
1273 fAModules->ExecuteTask(&TAModule::kExecTerminate);
1274 if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
1275
1276 // store output objects again, in case a module added any output
1277 // objects during terminate
1278 if (fAModules->GetModOutput()!=0) {
1279 fAModules->GetModOutput()->StoreAllOutputObjs();
1280 } else {
1281 Error("Terminate",
1282 "Could not store output objects after terminate.");
1283 }
1284
1285 // Delete the tree cache
1286 if (fTreeCache)
1287 delete fTreeCache;
1288 }
1289
1290
1291 //______________________________________________________________________________
1292 void TAMSelector::ZeroAllBranches()
1293 {
1294 // Loops through all branches in fBranchTable and sets all user addresses
1295 // for each branch to zero.
1296
1297 TIter nextBranch(fBranchTable.MakeIterator());
1298 while (TAMBranchInfo *brInfo =
1299 dynamic_cast<TAMBranchInfo*>(nextBranch())) {
1300 brInfo->ZeroUsrAddrs();
1301 }
1302 }