ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMSelector.cxx
Revision: 1.17
Committed: Thu Jul 16 21:02:05 2009 UTC (15 years, 9 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_014d, Mit_014c, Mit_014b, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, Mit_012i, Mit_012h, Mit_012g, Mit_012f, Mit_012e, Mit_012d, Mit_012c, Mit_012b, Mit_012a, Mit_012, Mit_011a, Mit_011, Mit_010a, Mit_010
Changes since 1.16: +7 -7 lines
Log Message:
use same include paths as rest of code. Remember to always remove this when committing to the svn version.

File Contents

# Content
1 //
2 // $Id: TAMSelector.cxx,v 1.16 2009/07/13 19:20:25 loizides Exp $
3 //
4
5 #include "MitAna/TAM/interface/TAMSelector.h"
6
7
8 #ifndef ROOT_RVersion
9 #include <RVersion.h>
10 #endif
11 #ifndef ROOT_TFile
12 #include "TFile.h"
13 #endif
14 #ifndef ROOT_TTree
15 #include "TTree.h"
16 #endif
17 #ifndef ROOT_TError
18 #include "TError.h"
19 #endif
20 #ifndef ROOT_TROOT
21 #include "TROOT.h"
22 #endif
23 #ifndef ROOT_TList
24 #include "TList.h"
25 #endif
26 #ifndef ROOT_TClass
27 #include "TClass.h"
28 #endif
29 #ifndef ROOT_TProcessID
30 #include "TProcessID.h"
31 #endif
32 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,0,0) && \
33 ROOT_VERSION_CODE < ROOT_VERSION(5,11,2)
34 #ifndef ROOT_TUrl
35 #include "TUrl.h"
36 #endif
37 #endif
38 #ifndef ROOT_TRefTable
39 #include <TRefTable.h>
40 #endif
41 #ifndef ROOT_TBranchRef
42 #include <TBranchRef.h>
43 #endif
44 #ifndef ROOT_TFriendElement
45 #include "TFriendElement.h"
46 #endif
47 #ifndef TAM_TAModule
48 #include "MitAna/TAM/interface/TAModule.h"
49 #endif
50 #ifndef TAM_TAMOutput
51 #include "MitAna/TAM/interface/TAMOutput.h"
52 #endif
53 #ifndef TAM_TAMVirtualLoader
54 #include "MitAna/TAM/interface/TAMVirtualLoader.h"
55 #endif
56 #ifndef TAM_TAMVirtualBranchLoader
57 #include "MitAna/TAM/interface/TAMVirtualBranchLoader.h"
58 #endif
59 #ifndef TAM_TAMTreeLoader
60 #include "MitAna/TAM/interface/TAMTreeLoader.h"
61 #endif
62 #include <map>
63
64 //////////////////////////////////////////////////////////////////////////
65 // //
66 // TAMSelector //
67 // //
68 // A selector class for modular processing of a tree (or chain). //
69 // Processing is done by TAModule(s). //
70 // //
71 // Each TAModule contains pointers to the objects that will be read //
72 // in from the tree. For each such pointer, it will call //
73 // ReqBranch(name, pointer) to request that the branch be available for //
74 // processing by the module. The module's pointer would then be //
75 // automatically set to point to the object for the current event by //
76 // the TAMSelector, whenever the module calls LoadBranch. //
77 // //
78 // TAMSelector provides (and hides) all interaction with the tree //
79 // for the TAModule(s). //
80 // //
81 // Author : Corey Reed 07/20/2004 //
82 // Maarten Ballintijn 12/06/2005 //
83 // Constantin Loizides 12/06/2005 //
84 // //
85 //////////////////////////////////////////////////////////////////////////
86
87 ClassImp(TAMSelector)
88
89
90 #if ROOT_VERSION_CODE < ROOT_VERSION(5,11,3)
91 #define R__ASSERT(e) \
92 if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
93 #endif
94
95 //______________________________________________________________________________
96 TAMSelector::BranchProxy::BranchProxy(TAMSelector *sel, Bool_t e) :
97 fSel(sel),
98 fOrig(0),
99 fFake(new TRefTable(this, 10)),
100 fCurEntry(-1)
101 {
102 // Default constructor.
103
104 memset(fBrRead, 0, 1024*sizeof(Bool_t));
105
106 if (e)
107 Enable();
108 }
109
110
111 //______________________________________________________________________________
112 TAMSelector::BranchProxy::~BranchProxy()
113 {
114 // Destructor.
115
116 Disable();
117 delete fFake;
118 fFake = 0;
119 }
120
121
122 //______________________________________________________________________________
123 void TAMSelector::BranchProxy::Disable()
124 {
125 // Disable the auto branch loading via TAM.
126
127 if (fOrig)
128 TRefTable::SetRefTable(fOrig);
129 }
130
131
132 //______________________________________________________________________________
133 void TAMSelector::BranchProxy::Enable()
134 {
135 // Enable the auto branch loading via TAM.
136
137 TBranchRef *bref = fSel->GetTree()->GetTree()->GetBranchRef();
138 if (bref) {
139 fOrig = bref->GetRefTable();
140 TRefTable::SetRefTable(fFake);
141 }
142 }
143
144
145 //______________________________________________________________________________
146 TObject *TAMSelector::BranchProxy::GetObjectWithID(UInt_t uid, TProcessID *pid)
147 {
148 // This function should be called by a reference class which is designed to
149 // use TAM. Branch loading via TAM is handled through the BranchProxy class.
150 // Optimized loading is used if the object table cleaning has been
151 // enabled in TAM.
152
153 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 if (!fOrig)
273 return kFALSE;
274
275 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 TAMSelector::TAMSelector() :
291 fTree(0),
292 fBranchTable(TCollection::kInitHashTableCapacity, 1),
293 fEventObjs(TCollection::kInitHashTableCapacity, 1),
294 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 fProxy(this),
305 fDoProxy(kFALSE),
306 fDoObjTabClean(kFALSE),
307 fObjTabClean(kFALSE),
308 fLoaders()
309 {
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 if (obj)
386 return AddObjThisEvt(obj,obj->GetName());
387 else {
388 Error("AddObjThisEvt","Can not add null object to event.");
389 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 return kTRUE;
412 } 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
482 //______________________________________________________________________________
483 void TAMSelector::CleanObjTable(TProcessID *pid, UInt_t lastKeptUID) const
484 {
485 // Clear from the object table of a given process id, all pointers for objects
486 // with uids after lastKeptUid.
487
488 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
506
507 //______________________________________________________________________________
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 while (TAMBranchInfo *br = dynamic_cast<TAMBranchInfo*>(nextBr())) {
515
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 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 {
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
667 //______________________________________________________________________________
668 TObject *TAMSelector::GetObjectWithID(UInt_t uid, TProcessID *pid)
669 {
670 // 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
675 return fProxy.GetObjectWithID(uid,pid);
676 }
677
678
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
702 //______________________________________________________________________________
703 void TAMSelector::LoadBranch(const Char_t *bname)
704 {
705 // Loads branch by name, getting the pointer to the corresponding
706 // TAMBranchInfo and then use it in the call of the protected LoadBranch
707 // function.
708
709 if(fCurEvt==-1) {
710 Error("LoadBranch",
711 "Can not load branch with name [%s] at this point (fCurEvt==-1).",
712 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 }
725
726 LoadBranch(brInfo);
727 }
728
729
730 //______________________________________________________________________________
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
738 if (brInfo->IsLoaded())
739 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 //fObjCounter=TProcessID::GetObjectCount();
760 }
761
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 : "null", brInfo->GetName());
770
771 AbortAnalysis();
772 }
773
774 // make sure autoload proxy is enabled
775 if (fDoProxy)
776 fProxy.Enable();
777 }
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 // we are just in Notify(), therefore we ignore this call
791 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 // workaround for older ROOT: give file name to
798 // TFile that accidentally stripped the protocol
799 const TUrl *url = (GetCurrentFile()!=0)
800 ? GetCurrentFile()->GetEndpointUrl() : 0;
801
802 if (url==0) {
803 Warning("Notify","Could not get URL for file [%s].",
804 (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
805 : "null");
806 } else {
807
808 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 #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 // status (return value) of notify
822 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 //fObjCounter=TProcessID::GetObjectCount();;
839
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 }
877
878 // prepare for event
879 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
889 // store object counter for run boundaries
890 if (BeginRun()) {
891 fObjCounterRun=TProcessID::GetObjectCount();;
892 fAModules->ExecuteTask(&TAModule::kExecBeginRun);
893 }
894
895 // store object counter and process event
896 fObjCounter=TProcessID::GetObjectCount();;
897 TObjArray *pids = GetCurrentFile()->GetListOfProcessIDs();
898
899 // store uids for later cleaning for object tables from file
900 std::map<TProcessID*, UInt_t> lastUIDs;
901 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 }
912
913 if (fVerbosity>9) {
914 if ((entry % 100)==0) {
915 fprintf(stderr,"Processing entry %lld... \r",
916 entry);
917 }
918 }
919
920 fAModules->ExecuteTask(&TAModule::kExecProcess);
921
922 // update object counter on run boundaries
923 if (EndRun()) {
924 fAModules->ExecuteTask(&TAModule::kExecEndRun);
925 fObjCounter=fObjCounterRun;
926 }
927
928 // cleanup
929 ClearAllLoaders();
930 if (fEventObjs.IsEmpty()==kFALSE)
931 fEventObjs.Delete();
932
933 // set clean object table state variable to false
934 fObjTabClean = kFALSE;
935
936 // restore object counter
937 TProcessID::SetObjectCount(fObjCounter);
938
939 // Clean object table for current process id:
940 // This guarantees that objects which are not yet loaded in the
941 // current event have null pointers in the object table.
942 if (fDoObjTabClean) {
943 CleanObjTable(TProcessID::GetSessionProcessID(), fObjCounter);
944
945 //clean object tables for process ids being read from the file
946 for (Int_t i=0; i<pids->GetEntriesFast(); ++i) {
947 TProcessID *pid = static_cast<TProcessID*>(pids->At(i));
948 std::map<TProcessID*, UInt_t>::const_iterator lastUID = lastUIDs.find(pid);
949 if (lastUID != lastUIDs.end()) {
950 CleanObjTable(pid, lastUID->second);
951 }
952 else {
953 CleanObjTable(pid, 0);
954 }
955 }
956 }
957
958 // Clean object table for current process id.
959 // This guarantees that objects which are not yet loaded in the
960 // current event have null pointers in the object table.
961 if (fDoObjTabClean) {
962 CleanObjTable(TProcessID::GetSessionProcessID(), fObjCounter);
963
964 //clean object tables for process ids being read from the file
965 for (Int_t i=0; i<pids->GetEntriesFast(); ++i) {
966 TProcessID *pid = static_cast<TProcessID*>(pids->At(i));
967 std::map<TProcessID*, UInt_t>::const_iterator lastUID =
968 lastUIDs.find(pid);
969 if (lastUID != lastUIDs.end())
970 CleanObjTable(pid, lastUID->second);
971 else
972 CleanObjTable(pid, 0);
973 }
974 }
975
976 return kTRUE;
977 }
978
979
980 //______________________________________________________________________________
981 Bool_t TAMSelector::PublishObj(TObject *obj)
982 {
983 // Adds an object to a list of objects which is outside the module
984 // hierarchy. This can be used to pass objects (for example, calibrations)
985 // between modules. Objects in this list are available before Begin
986 // until the end of SlaveTerminate. They are not guaranteed to be available
987 // during or after Terminate.
988 // Checks (by name) if the object is already in the list. If it is, returns
989 // kFALSE and does not publish the object.
990 // NOTE: These objects are NOT owned by the list! Whatever creates these
991 // objects must take care to (1) remove the object from the list using
992 // RetractObj() and (2) delete the object.
993 // Also NOTE: This will not publish TAModule objects.
994
995 if (obj!=0) {
996 TObject *ob = FindPublicObj(obj->GetName());
997 if (ob==0) {
998 if (obj->InheritsFrom(TAModule::Class())) {
999 // Disallow publishing of TAModules since it breaks the assumption
1000 // that all TAModules in the input list were added by AddInput and
1001 // are intended to be executed. (Such modules would be found by
1002 // TakeModsFromInput and CopyModsFromInput.)
1003 Warning("PublishObj",
1004 "Can not publish a TAModule. Object named [%s] not "
1005 "published.",
1006 obj->GetName());
1007 } else {
1008 if (fInput!=0) {
1009 fInput->Add(obj);
1010 return kTRUE;
1011 } else {
1012 Error("PublishObj",
1013 "Input list is null. Could not publish object named [%s].",
1014 obj->GetName());
1015 }
1016 }
1017 } else {
1018 Warning("PublishObj",
1019 "Public object named [%s] already exists.",
1020 obj->GetName());
1021 }
1022 } else {
1023 Error("PublishObj",
1024 "Can not publish null object.");
1025 }
1026 return kFALSE;
1027 }
1028
1029
1030 //______________________________________________________________________________
1031 TObject *TAMSelector::RemoveObjThisEvt(const Char_t *name)
1032 {
1033 // Finds the object with the specified name and removes it from
1034 // the list of objects added to this event.
1035 // Returns the object that was removed.
1036
1037 TAMEvtObj *eo = dynamic_cast<TAMEvtObj*>(fEventObjs.FindObject(name));
1038 if (eo!=0) {
1039 fEventObjs.Remove(eo);
1040 TObject *obj = eo->fObj;
1041 eo->fObj = 0; // so it won't delete the object
1042 delete eo;
1043 return obj;
1044 }
1045 return 0;
1046 }
1047
1048
1049 //______________________________________________________________________________
1050 TObject *TAMSelector::RetractObj(const Char_t *name)
1051 {
1052 // Finds the public object with the specified name and removes it from
1053 // the list of public objects.
1054 // Returns the object that was retracted.
1055 // Note: TAmodules are not public objects and will not be removed by this
1056 // function.
1057
1058 TObject *obj = FindPublicObj(name);
1059 if (obj!=0) {
1060 return fInput->Remove(obj);
1061 }
1062 return 0;
1063 }
1064
1065
1066 //______________________________________________________________________________
1067 void TAMSelector::SlaveBegin(TTree *tree)
1068 {
1069 // Inits the tree and calls SlaveBegin() on the TAModule(s)
1070 //
1071 // The SlaveBegin() function is called after the Begin() function.
1072 // When running with PROOF SlaveBegin() is called on each slave server.
1073 // The tree argument is deprecated (on PROOF 0 is passed).
1074
1075 if (fAnalysisAborted) {
1076 return;
1077 } else {
1078 // call SlaveBegin first so the modules can call ReqBranch and
1079 // build the fBranchTable
1080 if (fModAborted) {
1081 fAModules->ResetAllActiveFlags();
1082 fModAborted = kFALSE;
1083 }
1084 // remove the modules from the input list and put them in the top-most
1085 // module of this selector. make sure they use this selector
1086 TakeLoadersFromInput();
1087 TakeModsFromInput();
1088 fAModules->SetSelector(this);
1089 if (fAModules->CheckSelectors(this)) {
1090 // build the module output hierarchy
1091 AddNewOutputLists();
1092 // set up the module's output members
1093 if (fAModules->fOutput != 0) {
1094 fAModules->fOutput->SetAllOutputMembers(kFALSE);
1095 }
1096
1097 fAModules->ExecuteTask(&TAModule::kExecSlaveBegin);
1098 } else {
1099 Error("SlaveBegin",
1100 "One or more module is not set up to use this selector.");
1101 R__ASSERT(0);
1102 }
1103
1104 // init requires fBranchTable to be built already
1105 // in Proof, this is called automatically when a new tree is loaded
1106 if (tree)
1107 Init(tree);
1108 if (fEventObjs.IsEmpty()==kFALSE)
1109 fEventObjs.Delete();
1110 }
1111 }
1112
1113
1114 //______________________________________________________________________________
1115 void TAMSelector::SlaveTerminate()
1116 {
1117 // Calls SlaveTerminate() on the TAModule(s)
1118 // The SlaveTerminate() function is called after all entries or objects
1119 // have been processed. When running with PROOF SlaveTerminate() is called
1120 // on each slave server.
1121
1122 if (fAnalysisAborted) {
1123 return;
1124 } else {
1125 if (fModAborted) {
1126 fAModules->ResetAllActiveFlags();
1127 fModAborted = kFALSE;
1128 }
1129 fAModules->ExecuteTask(&TAModule::kExecSlaveTerminate);
1130 if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
1131 }
1132 }
1133
1134
1135 //______________________________________________________________________________
1136 void TAMSelector::TakeModsFromInput()
1137 {
1138 // Find all TAModules in the input list and move them to fAModules.
1139
1140 R__ASSERT(fInput!=0);
1141
1142 if (fInput->IsEmpty()==kFALSE) {
1143 TObject *obj=fInput->First(), *tobj=0;
1144 while (obj!=0) {
1145 tobj = fInput->After(obj);
1146 if (obj->InheritsFrom(TAModule::Class())) {
1147 AddInput(dynamic_cast<TAModule*>(obj));
1148 fInput->Remove(obj);
1149 }
1150 obj = tobj;
1151 }
1152 }
1153 }
1154
1155
1156 //______________________________________________________________________________
1157 void TAMSelector::TakeLoadersFromInput()
1158 {
1159 // Find all TAModules in the input list and copy them to fAModules.
1160
1161 R__ASSERT(fInput!=0);
1162
1163 TList *loaders = dynamic_cast<TList*>(fInput->FindObject("TAM_LOADERS"));
1164 if (loaders != 0) {
1165 TIter next(loaders);
1166 while ( TAMVirtualLoader *l =
1167 dynamic_cast<TAMVirtualLoader*>(next()) ) {
1168 if (loaders != &fLoaders) fLoaders.AddLast(l);
1169 }
1170 }
1171
1172 fLoaders.AddLast(new TAMTreeLoader());
1173 }
1174
1175
1176 //______________________________________________________________________________
1177 void TAMSelector::Terminate()
1178 {
1179 // Calls Terminate() on the TAModule(s).
1180 // When running under Proof, will copy the TAMOutput object
1181 // from the fOutput list to the top most TAModule object. Assumes
1182 // that the only TAMOutput object in fOutput is the one belonging
1183 // to the top most module.
1184 // The Terminate() function is the last function to be called during
1185 // a query. It always runs on the client, it can be used to present
1186 // the results graphically or save the results to file.
1187
1188 if (fAnalysisAborted) {
1189 return;
1190 }
1191
1192 if (fModAborted) {
1193 fAModules->ResetAllActiveFlags();
1194 fModAborted = kFALSE;
1195 }
1196
1197 if (fAModules->GetModOutput()==0) {
1198 // When running under Proof, copy the module output hierarchy to
1199 // this selector's top most module.
1200 TIter nextObj(GetOutputList());
1201 TAMOutput *tout=0;
1202 TObject *obj=0;
1203 Bool_t alreadySet=kFALSE;
1204 while ( (obj = nextObj()) ) {
1205 if (obj->InheritsFrom(TAMOutput::Class())) {
1206 tout = dynamic_cast<TAMOutput*>(obj);
1207 if (alreadySet) {
1208 Warning("Terminate",
1209 "Found more than one TAMOutput object in the "
1210 "output list. Assuming the first one is from the "
1211 "top-most module. The output list contains:");
1212 GetOutputList()->ls();
1213 } else {
1214 // copy module output hierarchy
1215 fAModules->SetAllModOutput(tout);
1216 // try to set module's pointers to their output objects
1217 tout->SetAllOutputMembers(kTRUE);
1218 alreadySet=kTRUE;
1219 }
1220 }
1221 }
1222 if (alreadySet==kFALSE) {
1223 Error("Terminate",
1224 "Did not find TAMOutput object in the output list! "
1225 "The output list contains:");
1226 GetOutputList()->ls();
1227 }
1228 }
1229
1230 // move output objs from current objects to stored objects
1231 // incase the module wants to write output to a file
1232 if (fAModules->GetModOutput()!=0) {
1233 fAModules->GetModOutput()->StoreAllOutputObjs();
1234 } else {
1235 Error("Terminate",
1236 "Could not store output objects from this process run.");
1237 }
1238
1239 fAModules->ExecuteTask(&TAModule::kExecTerminate);
1240 if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
1241
1242 // store output objects again, in case a module added any output
1243 // objects during terminate
1244 if (fAModules->GetModOutput()!=0) {
1245 fAModules->GetModOutput()->StoreAllOutputObjs();
1246 } else {
1247 Error("Terminate",
1248 "Could not store output objects after terminate.");
1249 }
1250 }
1251
1252
1253 //______________________________________________________________________________
1254 void TAMSelector::ZeroAllBranches()
1255 {
1256 // Loops through all branches in fBranchTable and sets all user addresses
1257 // for each branch to zero.
1258
1259 TIter nextBranch(fBranchTable.MakeIterator());
1260 while (TAMBranchInfo *brInfo =
1261 dynamic_cast<TAMBranchInfo*>(nextBranch())) {
1262 brInfo->ZeroUsrAddrs();
1263 }
1264 }