ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMSelector.cxx
Revision: 1.15
Committed: Mon Apr 27 08:11:08 2009 UTC (16 years ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_009c, Mit_009b, Mit_009a
Changes since 1.14: +6 -3 lines
Log Message:
Fix for cases where no branch ref table was built. (fOrig==0).

File Contents

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