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

File Contents

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