ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMSelector.cxx
Revision: 1.11
Committed: Tue Feb 17 14:34:58 2009 UTC (16 years, 2 months ago) by bendavid
Content type: text/plain
Branch: MAIN
Changes since 1.10: +7 -1 lines
Log Message:
Add additional comments about object table cleaning

File Contents

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