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

# User Rev Content
1 loizides 1.1 //
2 bendavid 1.22 // $Id: TAMSelector.cxx,v 1.21 2012/03/28 12:15:37 paus Exp $
3 loizides 1.1 //
4    
5 loizides 1.17 #include "MitAna/TAM/interface/TAMSelector.h"
6 loizides 1.1
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 loizides 1.6 #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 loizides 1.1 #ifndef TAM_TAModule
48 loizides 1.17 #include "MitAna/TAM/interface/TAModule.h"
49 loizides 1.1 #endif
50     #ifndef TAM_TAMOutput
51 loizides 1.17 #include "MitAna/TAM/interface/TAMOutput.h"
52 loizides 1.1 #endif
53     #ifndef TAM_TAMVirtualLoader
54 loizides 1.17 #include "MitAna/TAM/interface/TAMVirtualLoader.h"
55 loizides 1.1 #endif
56     #ifndef TAM_TAMVirtualBranchLoader
57 loizides 1.17 #include "MitAna/TAM/interface/TAMVirtualBranchLoader.h"
58 loizides 1.1 #endif
59     #ifndef TAM_TAMTreeLoader
60 loizides 1.17 #include "MitAna/TAM/interface/TAMTreeLoader.h"
61 loizides 1.1 #endif
62 bendavid 1.10 #include <map>
63 loizides 1.1
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 loizides 1.6 //______________________________________________________________________________
96 loizides 1.14 TAMSelector::BranchProxy::BranchProxy(TAMSelector *sel, Bool_t e) :
97     fSel(sel),
98     fOrig(0),
99 loizides 1.15 fFake(new TRefTable(this, 10)),
100 loizides 1.14 fCurEntry(-1)
101     {
102     // Default constructor.
103    
104     memset(fBrRead, 0, 1024*sizeof(Bool_t));
105 loizides 1.15
106 loizides 1.14 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 paus 1.21
153     // printf("enter TAMSelector::BranchProxy::GetObjectWithID: %d\n",uid);
154 loizides 1.14
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 paus 1.21
166     //printf(" br table loaded %p\n",(void*)br);
167    
168 loizides 1.14 TRefTable *table = br->GetRefTable();
169     if (!table)
170     return pid->GetObjectWithID(uid);
171 paus 1.21
172     //printf(" ref table loaded %p\n",(void*)table);
173    
174 loizides 1.14 table->SetUID(uid,pid);
175    
176 paus 1.21
177     //printf("loading\n");
178 loizides 1.14 Load(uid,pid,br,table);
179 paus 1.21 //printf(" loaded %p\n",(void*)pid->GetObjectWithID(uid));
180 loizides 1.14
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 bendavid 1.22 Long64_t readentry = fSel->fCurEvt;
193 bendavid 1.18 Long64_t chainentry = readentry + fSel->GetTree()->GetChainOffset();
194    
195 loizides 1.14 // read branchref if needed
196 bendavid 1.18 if (fCurEntry != chainentry) {
197 loizides 1.14 Int_t bytes = br->GetEntry(readentry);
198     if (bytes<0) {
199 bendavid 1.19 Fatal("Load", "Could not get entry %lld from %s branch",
200 loizides 1.14 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 bendavid 1.18 if (fCurEntry != chainentry)
213 loizides 1.14 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 bendavid 1.18 fCurEntry = chainentry;
240 loizides 1.14
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 loizides 1.15 if (!fOrig)
278     return kFALSE;
279    
280 loizides 1.14 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 loizides 1.1 TAMSelector::TAMSelector() :
296     fTree(0),
297 paus 1.20 fTreeCache(0),
298     fCacheSize(0),
299 loizides 1.5 fBranchTable(TCollection::kInitHashTableCapacity, 1),
300     fEventObjs(TCollection::kInitHashTableCapacity, 1),
301 loizides 1.1 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 loizides 1.14 fProxy(this),
312 loizides 1.6 fDoProxy(kFALSE),
313 loizides 1.14 fDoObjTabClean(kFALSE),
314     fObjTabClean(kFALSE),
315     fLoaders()
316 loizides 1.1 {
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 paus 1.4 if (obj)
393 loizides 1.1 return AddObjThisEvt(obj,obj->GetName());
394     else {
395 paus 1.4 Error("AddObjThisEvt","Can not add null object to event.");
396 loizides 1.1 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 loizides 1.5 return kTRUE;
419 loizides 1.1 } 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 loizides 1.14
489 bendavid 1.10 //______________________________________________________________________________
490     void TAMSelector::CleanObjTable(TProcessID *pid, UInt_t lastKeptUID) const
491     {
492 loizides 1.14 // Clear from the object table of a given process id, all pointers for objects
493     // with uids after lastKeptUid.
494 bendavid 1.11
495 bendavid 1.10 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 loizides 1.1
513 loizides 1.14
514 loizides 1.1 //______________________________________________________________________________
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 paus 1.4 while (TAMBranchInfo *br = dynamic_cast<TAMBranchInfo*>(nextBr())) {
522 loizides 1.1
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 loizides 1.5 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 loizides 1.1 {
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 loizides 1.14
674 bendavid 1.12 //______________________________________________________________________________
675     TObject *TAMSelector::GetObjectWithID(UInt_t uid, TProcessID *pid)
676     {
677 loizides 1.14 // 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 bendavid 1.12
682 loizides 1.14 return fProxy.GetObjectWithID(uid,pid);
683     }
684 bendavid 1.12
685 loizides 1.1
686 paus 1.20 //__________________________________________________________________________________________________
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 loizides 1.1
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 paus 1.20 dynamic_cast<TAMBranchInfo*>(nextBranch()) ) {
703     brInfo->Init();
704 loizides 1.1 }
705     }
706    
707 loizides 1.14
708 loizides 1.1 //______________________________________________________________________________
709 bendavid 1.8 void TAMSelector::LoadBranch(const Char_t *bname)
710 loizides 1.1 {
711 bendavid 1.8 // Loads branch by name, getting the pointer to the corresponding
712 loizides 1.9 // TAMBranchInfo and then use it in the call of the protected LoadBranch
713     // function.
714 bendavid 1.8
715 loizides 1.1 if(fCurEvt==-1) {
716     Error("LoadBranch",
717 loizides 1.2 "Can not load branch with name [%s] at this point (fCurEvt==-1).",
718 loizides 1.1 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 bendavid 1.8 }
731    
732     LoadBranch(brInfo);
733     }
734    
735 loizides 1.14
736 bendavid 1.8 //______________________________________________________________________________
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 loizides 1.1
744 loizides 1.6 if (brInfo->IsLoaded())
745 loizides 1.1 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 loizides 1.6 //fObjCounter=TProcessID::GetObjectCount();
766     }
767 loizides 1.1
768 paus 1.20 // load the entry (using the cache)
769     if (fTreeCache)
770     GetCurrentFile()->SetCacheRead(fTreeCache);
771 loizides 1.1 Int_t ret = brInfo->GetEntry(fCurEvt);
772 paus 1.20 if (fTreeCache)
773     GetCurrentFile()->SetCacheRead(0);
774    
775    
776 loizides 1.1 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 bendavid 1.8 : "null", brInfo->GetName());
782 loizides 1.1
783     AbortAnalysis();
784     }
785 loizides 1.6
786     // make sure autoload proxy is enabled
787 loizides 1.7 if (fDoProxy)
788 loizides 1.14 fProxy.Enable();
789 loizides 1.1 }
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 loizides 1.6 // we are just in Notify(), therefore we ignore this call
803 loizides 1.1 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 loizides 1.6 // workaround for older ROOT: give file name to
810 loizides 1.1 // TFile that accidentally stripped the protocol
811 loizides 1.6 const TUrl *url = (GetCurrentFile()!=0)
812     ? GetCurrentFile()->GetEndpointUrl() : 0;
813 loizides 1.1
814 loizides 1.6 if (url==0) {
815     Warning("Notify","Could not get URL for file [%s].",
816     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
817     : "null");
818     } else {
819 loizides 1.1
820 loizides 1.6 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 loizides 1.1 #endif
826    
827     if (fVerbosity>0) {
828 bendavid 1.19 Info("Notify","Opening file [%s] at current event [%lld].",
829 loizides 1.1 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null",
830     fCurEvt);
831     }
832    
833 loizides 1.6 // status (return value) of notify
834 loizides 1.1 Bool_t notifyStat = kTRUE;
835    
836 paus 1.20 // 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 loizides 1.1 // 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 loizides 1.6 //fObjCounter=TProcessID::GetObjectCount();;
869 loizides 1.1
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 paus 1.20
880     // status (return value) of notify
881     notifyStat = kTRUE;
882    
883 loizides 1.1 }
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 loizides 1.2 }
911 loizides 1.1
912 loizides 1.6 // prepare for event
913 loizides 1.2 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 loizides 1.1
923 loizides 1.6 // store object counter for run boundaries
924 loizides 1.2 if (BeginRun()) {
925     fObjCounterRun=TProcessID::GetObjectCount();;
926     fAModules->ExecuteTask(&TAModule::kExecBeginRun);
927     }
928 loizides 1.1
929 loizides 1.6 // store object counter and process event
930 loizides 1.2 fObjCounter=TProcessID::GetObjectCount();;
931 bendavid 1.10 TObjArray *pids = GetCurrentFile()->GetListOfProcessIDs();
932 loizides 1.14
933     // store uids for later cleaning for object tables from file
934 bendavid 1.10 std::map<TProcessID*, UInt_t> lastUIDs;
935 loizides 1.14 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 bendavid 1.10 }
946    
947 loizides 1.2 if (fVerbosity>9) {
948     if ((entry % 100)==0) {
949     fprintf(stderr,"Processing entry %lld... \r",
950     entry);
951     }
952     }
953 loizides 1.6
954 loizides 1.2 fAModules->ExecuteTask(&TAModule::kExecProcess);
955    
956 loizides 1.6 // update object counter on run boundaries
957 loizides 1.2 if (EndRun()) {
958     fAModules->ExecuteTask(&TAModule::kExecEndRun);
959     fObjCounter=fObjCounterRun;
960     }
961    
962 loizides 1.6 // cleanup
963 loizides 1.2 ClearAllLoaders();
964     if (fEventObjs.IsEmpty()==kFALSE)
965     fEventObjs.Delete();
966 loizides 1.1
967 loizides 1.14 // set clean object table state variable to false
968     fObjTabClean = kFALSE;
969    
970 loizides 1.2 // restore object counter
971     TProcessID::SetObjectCount(fObjCounter);
972 loizides 1.16
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 loizides 1.14 if (fDoObjTabClean) {
977 bendavid 1.12 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 bendavid 1.10 }
991 loizides 1.1
992 loizides 1.16 // 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 loizides 1.14 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 loizides 1.16 std::map<TProcessID*, UInt_t>::const_iterator lastUID =
1002     lastUIDs.find(pid);
1003 loizides 1.14 if (lastUID != lastUIDs.end())
1004     CleanObjTable(pid, lastUID->second);
1005     else
1006     CleanObjTable(pid, 0);
1007     }
1008     }
1009    
1010 loizides 1.1 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 loizides 1.6 if (tree)
1141     Init(tree);
1142     if (fEventObjs.IsEmpty()==kFALSE)
1143     fEventObjs.Delete();
1144 loizides 1.1 }
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 paus 1.20
1285     // Delete the tree cache
1286     if (fTreeCache)
1287     delete fTreeCache;
1288 loizides 1.1 }
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 paus 1.4 while (TAMBranchInfo *brInfo =
1299     dynamic_cast<TAMBranchInfo*>(nextBranch())) {
1300 loizides 1.1 brInfo->ZeroUsrAddrs();
1301     }
1302     }