ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMSelector.cxx
Revision: 1.20
Committed: Mon Mar 21 15:58:37 2011 UTC (14 years, 1 month ago) by paus
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_025c_branch2, Mit_025c_branch1, Mit_025c_branch0, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1
Branch point for: Mit_025c_branch
Changes since 1.19: +44 -11 lines
Log Message:
Improved caching.

File Contents

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