ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMOutput.cxx
Revision: 1.3
Committed: Wed Nov 26 17:08:36 2008 UTC (16 years, 5 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_009, Mit_008, Mit_008pre2, Mit_008pre1, Mit_006b, Mit_006a
Changes since 1.2: +19 -7 lines
Log Message:
Write out TDirectories instead of TAMOutput modules in case the folder hierarchy is supposed to be kept (former kSingleKey option).

File Contents

# Content
1 //
2 // $Id: TAMOutput.cxx,v 1.2 2008/09/27 06:03:36 loizides Exp $
3 //
4
5 #include "TAMOutput.h"
6
7
8 #ifndef G__API_H
9 #include "Api.h"
10 #endif
11 #ifndef ROOT_Riostream
12 #include "Riostream.h"
13 #endif
14 #ifndef ROOT_RVersion
15 #include "RVersion.h"
16 #endif
17 #ifndef ROOT_TIterator
18 #include "TIterator.h"
19 #endif
20 #ifndef ROOT_TObjArray
21 #include "TObjArray.h"
22 #endif
23 #ifndef ROOT_TError
24 #include "TError.h"
25 #endif
26 #ifndef ROOT_TH1
27 #include "TH1.h"
28 #endif
29 #ifndef ROOT_TROOT
30 #include "TROOT.h"
31 #endif
32 #ifndef ROOT_TDataMember
33 #include "TDataMember.h"
34 #endif
35 #ifndef TAM_TAModule
36 #include "TAModule.h"
37 #endif
38 #ifndef TAM_TDirectory
39 #include "TDirectory.h"
40 #endif
41
42 //////////////////////////////////////////////////////////////////////////
43 // //
44 // TAMOutput //
45 // //
46 // Stores the output objects of a module for use with the Proof //
47 // facility. This object is itself a list of all sub modules output //
48 // objects, so that whatever TAModule hierarchy exists is duplicated in //
49 // the TAMOutput hierarchy. Thus, only the tree of TAMOutput objects //
50 // needs to be streamed in to the master from the worker computers when //
51 // merging output objects in a Proof analsys, and not the complete //
52 // TAModule objects themselves. This is useful since an TAModule object //
53 // is in principal arbitrarily large, and only the list of output //
54 // objects needs to be merged. //
55 // //
56 // This class provides the functionality to merge the list of output //
57 // objects correctly throughout the hierarchy of TAMOutput objects. //
58 // //
59 // The existence of this class is hidden to classes inheritting from //
60 // TAModule. Such end-user modules need only add the desired output //
61 // objects (such as histograms) to their output list by calling //
62 // TAModule::AddOutput(TObject*&). //
63 // //
64 // Author : Corey Reed 07/20/2004 //
65 // //
66 //////////////////////////////////////////////////////////////////////////
67
68 ClassImp(TAMOutput)
69 ClassImp(TAMOutput::TAMModInspector)
70 ClassImp(TAMOutput::TAMModInspector::TAMModMember)
71
72
73 #if ROOT_VERSION_CODE < ROOT_VERSION(5,11,3)
74 #define R__ASSERT(e) \
75 if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
76 #endif
77
78
79 //______________________________________________________________________________
80 TAMOutput::TAMModInspector::TAMModInspector() :
81 fOutputMembers(TCollection::kInitHashTableCapacity, 1)
82 {
83 // Default constructor.
84
85 fOutputMembers.SetOwner(kTRUE);
86 }
87
88
89 //______________________________________________________________________________
90 TAMOutput::TAMModInspector::~TAMModInspector()
91 {
92 // Destructor.
93 }
94
95
96 //______________________________________________________________________________
97 void TAMOutput::TAMModInspector::AddOutput(TObject* obj, const void* adr)
98 {
99 // Set the title of the TAMModMember for this object to the name of the obj.
100
101 TAMModMember* mem = FindModMemberWithAddr(adr);
102 if (mem!=0) {
103 mem->SetName(obj->GetName());
104 } // else output object is not (pointed to by) a member of the module
105 }
106
107
108 //______________________________________________________________________________
109 void TAMOutput::TAMModInspector::Inspect(TClass* cl, const Char_t* parent,
110 const Char_t* name, const void* addr)
111 {
112 // Set the address of the mod member to addr.
113 // If no mod member yet exists for this member, make it (but with no name).
114
115 if (cl->InheritsFrom(TAModule::Class())) {
116 TAMModMember* mem = FindModMemberWithMemberName(name);
117 if (mem==0) {
118 if ( (cl!=0) && (name!=0) && (addr!=0) ) {
119 TString fullname(parent);
120 fullname.Append(name);
121 fOutputMembers.Add(new TAMModMember(0, fullname.Data(),
122 const_cast<void*>(addr), cl));
123 } else {
124 ::Error("TAMOutput::TAMModInspector::Inspect",
125 "Can not store TAMModMember with class at %p, "
126 "name=%s, addr=%p",
127 static_cast<void*>(cl),
128 name, static_cast<const void*>(addr));
129 }
130 } else {
131 mem->fAddr = const_cast<void*>(addr);
132 }
133 } // else don't bother; it can't point to an output object
134 }
135
136
137 //______________________________________________________________________________
138 void TAMOutput::TAMModInspector::RemoveOutput(TObject* obj)
139 {
140 // Remove the TAMModMember for this object.
141
142 TAMModMember* mem = dynamic_cast<TAMModMember*>(
143 fOutputMembers.FindObject(obj->GetName()));
144 if (mem!=0) {
145 fOutputMembers.Remove(mem);
146 }
147 }
148
149
150 //______________________________________________________________________________
151 TAMOutput::TAMModInspector::TAMModMember*
152 TAMOutput::TAMModInspector::FindModMemberWithAddr(const void* addr)
153 {
154 // Find the mod member that has the specified address
155
156 TIter nextmem(fOutputMembers.MakeIterator());
157 TAMModMember* mem=0;
158 while ( (mem = dynamic_cast<TAMModMember*>(nextmem())) ) {
159 if (mem->fAddr == addr) return mem;
160 }
161 return 0;
162 }
163
164
165 //______________________________________________________________________________
166 TAMOutput::TAMModInspector::TAMModMember*
167 TAMOutput::TAMModInspector::FindModMemberWithMemberName(const Char_t* mn)
168 {
169 // Find the mod member that has the specified member name.
170
171 TIter nextmem(fOutputMembers.MakeIterator());
172 TString memname(mn);
173 TAMModMember* mem=0;
174 while ( (mem = dynamic_cast<TAMModMember*>(nextmem())) ) {
175 if (memname.CompareTo(mem->GetTitle())==0) return mem;
176 }
177 return 0;
178 }
179
180
181 //______________________________________________________________________________
182 void TAMOutput::TAMModInspector::SetMemberAddrFor(TObject* obj,
183 const UInt_t verbose)
184 {
185 // Find the specified module's member for the specified object
186 // and make the member point to the specified object.
187 // If the member is not a pointer, does nothing.
188
189 if (obj!=0) {
190 TAMModMember* mem = dynamic_cast<TAMModMember*>(
191 fOutputMembers.FindObject(obj->GetName()));
192 if (mem!=0) {
193 // it's silly, but mem->fMClass comes from IsA(), which does
194 // not "load" the class, so the data member list is empty.
195 TClass* cl = TClass::GetClass(mem->fMClass->GetName());
196 if (cl!=0) {
197 // test if the module's member is actually a pointer to a class
198 // (as opposed to an array of pointers,
199 // an instance of the class, etc.)
200 TDataMember* dm = cl->GetDataMember(mem->GetTitle());
201 if (dm!=0) {
202 TString memberString(dm->GetTypeName());
203 memberString += "*";
204 if (memberString.CompareTo(dm->GetFullTypeName())==0) {
205 void*& modobj = *(static_cast<void**>(mem->fAddr));
206 if (modobj!=obj) {
207 if (modobj!=0) {
208 ::Warning("TAMOutput::TAMModInspector::"
209 "SetMemberAddrFor",
210 "Module pointer [%s] is pointing to "
211 "non-zero address "
212 "%p. Setting it to point to "
213 "output object [%s] at %p. "
214 "Possible memory leak/stomp.",
215 mem->GetTitle(),
216 static_cast<void*>(modobj),
217 obj->GetName(),
218 static_cast<void*>(obj));
219 }
220 modobj = obj;
221 } // else it's already pointing to the right place
222 } else {
223 // not a pointer to a class
224 if (verbose>9) {
225 ::Warning("TAMOutput::TAMModInspector::"
226 "SetMemberAddrFor",
227 "Module member [%s] is of type "
228 "[%s], not a pointer "
229 "to a class (inheriting from TObject). "
230 "Could not "
231 "automatically make this member "
232 "point to [%s] "
233 "from the output list.\n"
234 "Set verbosity below 10 to "
235 "remove this message.",
236 mem->GetTitle(), dm->GetFullTypeName(),
237 obj->GetName());
238 }
239 }
240 } else {
241 ::Error("TAMOutput::TAMModInspector::SetMemberAddrFor",
242 "Could not get data member (%p) [%s] of module [%s]. "
243 "Could not set member address for object [%s].",
244 static_cast<void*>(dm),
245 mem->GetTitle(), mem->fMClass->GetName(),
246 obj->GetName());
247 }
248 } else {
249 ::Error("TAMOutput::TAMModInspector::SetMemberAddrFor",
250 "No class info for the module. "
251 "Can not set member address for [%s].",
252 obj->GetName());
253 }
254 } // else output object is not (pointed to by) a member of the module
255 } else {
256 ::Error("TAMOutput::TAMModInspector::SetMemberAddrFor",
257 "Can not set member address for null object.");
258 }
259 }
260
261
262 //______________________________________________________________________________
263 void TAMOutput::TAMModInspector::Streamer(TBuffer &R__b)
264 {
265 // Stream an object of class TAMOutput::TAMModInspector.
266
267 //This works around a msvc bug and should be harmless on other platforms
268 typedef TAMOutput::TAMModInspector thisClass;
269 UInt_t R__s, R__c;
270 if (R__b.IsReading()) {
271 Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
272 fOutputMembers.Streamer(R__b);
273 R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
274 } else {
275 R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
276 fOutputMembers.Streamer(R__b);
277 R__b.SetByteCount(R__c, kTRUE);
278 }
279 }
280
281
282 //______________________________________________________________________________
283 TAMOutput::TAMOutput() :
284 fMod(0)
285 {
286 // Default constructor.
287
288 SetOwner(kTRUE);
289 fOutput.SetOwner(kFALSE);
290 }
291
292
293 //______________________________________________________________________________
294 TAMOutput::TAMOutput(TAModule* mod) :
295 fMod(mod)
296 {
297 // Normal constructor.
298
299 SetOwner(kTRUE);
300 fOutput.SetOwner(kFALSE);
301 fCurOutput.SetOwner(kFALSE);
302 if (mod!=0) SetName(mod->GetName());
303 }
304
305
306 //______________________________________________________________________________
307 TAMOutput::~TAMOutput()
308 {
309 // Destructor.
310 }
311
312
313 //______________________________________________________________________________
314 void TAMOutput::Browse(TBrowser* b)
315 {
316 // Browse the output of this module
317
318 fOutput.Browse(b);
319 TList::Browse(b);
320 }
321
322
323 //______________________________________________________________________________
324 void TAMOutput::CallMerge(TObject* obj, TList& list)
325 {
326 // Uses CINT to call merge on 'obj' given a list of all the
327 // objects from the worker computers that correspond to 'obj'.
328 // If no merge function exists for 'obj', it simply adds all the
329 // objects in list to the output list of this module.
330 // To be called only by MergeOutput(TCollection*)
331
332 R__ASSERT(obj);
333
334 Long_t offset=0;
335 G__ClassInfo ci(obj->ClassName());
336 G__CallFunc cf;
337
338 if (ci.IsValid()) {
339 cf.SetFuncProto(&ci, "Merge", "TCollection*", &offset);
340 }
341 if (cf.IsValid()) {
342 cf.SetArg((Long_t)&list);
343 cf.Exec(obj);
344 } else {
345 // No Merge interface, return individual objects
346 TObject* obj=0;
347 while ( (obj = list.First()) ) {
348 fCurOutput.Add(obj);
349 list.Remove(obj);
350 }
351 }
352 }
353
354
355 //______________________________________________________________________________
356 void TAMOutput::CheckHistDir(TObject* obj)
357 {
358 // If obj is a histogram, set directory to null.
359
360 if (obj->InheritsFrom(TH1::Class())) {
361 TH1* hist = dynamic_cast<TH1*>(obj);
362 if (hist!=0) hist->SetDirectory(0);
363 }
364 }
365
366
367 //______________________________________________________________________________
368 void TAMOutput::DeleteIterators(vector<TIterator*>& iters) {
369 // Deletes each iterator in the vector.
370
371 vector<TIterator*>::const_iterator send = iters.end();
372 for (vector<TIterator*>::iterator siter = iters.begin();
373 siter!=send; siter++) {
374 delete (*siter);
375 }
376 }
377
378
379 //______________________________________________________________________________
380 TAMOutput* TAMOutput::FindModOutput(const TAModule* mod)
381 {
382 // Finds the TAMOutput object associated with the specified TAModule
383 // (either being this one, or one of its sub modules).
384 // Returns 0 if no such TAMOutput object is found.
385
386 if (fMod==mod) {
387 return this;
388 } else {
389 TIter nextModOutput(MakeIterator());
390 TAMOutput* out=0, * tout=0;
391 while ( (out = dynamic_cast<TAMOutput*>(nextModOutput())) ) {
392 tout = out->FindModOutput(mod);
393 if (tout!=0) return tout;
394 }
395 }
396 return 0;
397 }
398
399
400 //______________________________________________________________________________
401 TAMOutput* TAMOutput::FindModOutput(const Char_t* name)
402 {
403 // Finds the (first) TAMOutput object with the specified name
404 // (either being this one, or one of its sub modules)
405 // Returns 0 if no such TAMOutput object is found.
406 TString nm(name);
407 if (nm.CompareTo(GetName())==0) {
408 return this;
409 } else {
410 TIter nextModOutput(MakeIterator());
411 TAMOutput* out=0, * tout=0;
412 while ( (out = dynamic_cast<TAMOutput*>(nextModOutput())) ) {
413 tout = out->FindModOutput(name);
414 if (tout!=0) return tout;
415 }
416 }
417 return 0;
418 }
419
420
421 //______________________________________________________________________________
422 TObject* TAMOutput::FindOutput(const Char_t* obj)
423 {
424 // Finds the object with the specified name in the list of output objects
425 // of this module.
426 // First check the saved output, then check the output for this current
427 // processing.
428
429 TObject* fobj = fOutput.FindObject(obj);
430 if (fobj==0) {
431 fobj = fCurOutput.FindObject(obj);
432 }
433 return fobj;
434 }
435
436
437 //______________________________________________________________________________
438 TObject* TAMOutput::FindOutput(const TObject* obj)
439 {
440 // Finds the specified object in the list of output objects of this module.
441 // First check the saved output, then check the output for this current
442 // processing.
443
444 TObject* fobj = fOutput.FindObject(obj);
445 if (fobj==0) {
446 fobj = fCurOutput.FindObject(obj);
447 }
448 return fobj;
449
450 }
451
452
453 //______________________________________________________________________________
454 TObject* TAMOutput::FindOutput(const Char_t* module, const Char_t* obj) {
455 // Finds the specified object from the output of the specified module
456 // Note: "module" must be either this module, or a submodule of this module
457 // First check the saved output, then check the output for this current
458 // processing.
459
460 TAMOutput* outmod = FindModOutput(module);
461 if (outmod!=0) {
462 TObject* outp = outmod->FindOutput(obj);
463 if (outp==0) {
464 Warning("FindOutput",
465 "Could not find output named [%s] in module [%s].",
466 obj, outmod->GetName());
467 }
468 return outp;
469 } else {
470 Warning("FindOutput","Could not find (sub)module with name [%s].",
471 module);
472 }
473 return 0;
474 }
475
476
477 //______________________________________________________________________________
478 void TAMOutput::ls(Option_t* option) const
479 {
480 // List the output objects inside this module and its submodules.
481
482 TROOT::IndentLevel();
483 cout << "Output of " << GetName() << ":" << endl;
484
485 fOutput.ls(option);
486
487 TROOT::IncreaseDirLevel();
488 TList::ls(option);
489 TROOT::DecreaseDirLevel();
490 }
491
492
493 //______________________________________________________________________________
494 void TAMOutput::Merge(TCollection* list)
495 {
496 // Called by Proof after SlaveTerminate() and before Terminate()
497 // to merge the output objects from each worker ("slave") computer.
498 // First merge the actual output objects from this module, then
499 // recursively proceed through the sub modules to merge their objects.
500
501 // merge this module's output objects
502 MergeOutput(list);
503
504 // then merge its sub modules' objects:
505 if (!IsEmpty()) { // (if we have any sub modules)
506 TAMOutput* out=0, * tout=0;
507 // for each slave, get an iterator over sub modules
508 // can't use any TCollection since TIterators are not TObjects
509 vector<TIterator*> slaveIters;
510 TIter nextSlave(list);
511 while ( (tout = dynamic_cast<TAMOutput*>(nextSlave())) ) {
512 slaveIters.push_back(tout->MakeIterator());
513 }
514
515 // loop over sub modules
516 TIter nextModOutput(MakeIterator());
517 while ( (out = dynamic_cast<TAMOutput*>(nextModOutput())) ) {
518 // make a list of sub modules from each slave
519 TObjArray subList(list->GetSize());
520
521 vector<TIterator*>::const_iterator send = slaveIters.end();
522 for (vector<TIterator*>::iterator siter = slaveIters.begin();
523 siter!=send; siter++) {
524 // add the object corresponding to 'out' from each slave
525 subList.Add((*siter)->Next());
526 }
527 // merge the list of sub modules
528 out->Merge(&subList);
529 }
530
531 // cleanup
532 DeleteIterators(slaveIters);
533 }
534
535 }
536
537
538 //______________________________________________________________________________
539 void TAMOutput::MergeOutput(TCollection* list)
540 {
541 // Merges the actual output objects in fCurOutput given a list of
542 // all the TAMOutput objects from the worker computers that
543 // correspond to this one.
544 // To be called only by Merge(TCollection*)
545
546 if (!(fCurOutput.IsEmpty())) { // (if there are any output objects)
547 TAMOutput* tout=0;
548 // for each slave, get an iterator over the fCurOutput list
549 // can't use any TCollection since TIterators are not TObjects
550 vector<TIterator*> slaveIters;
551 TIter nextSlave(list);
552 while ( (tout = dynamic_cast<TAMOutput*>(nextSlave())) ) {
553 slaveIters.push_back(tout->GetCurOutputList()->MakeIterator());
554 }
555
556 // loop over fCurOutput
557 TIter nextOutputObj(fCurOutput.MakeIterator());
558 TObject* outObj=0;
559 while ( (outObj = nextOutputObj()) ) {
560 // make a list of 'outObj' from each slave
561 TList objsToMerge;
562
563 vector<TIterator*>::const_iterator send = slaveIters.end();
564 for (vector<TIterator*>::iterator siter = slaveIters.begin();
565 siter!=send; siter++) {
566 // add the object corresponding to 'outObj' from each slave
567 objsToMerge.AddLast((*siter)->Next());
568 }
569 // merge 'outObj'
570 CallMerge(outObj, objsToMerge);
571 }
572
573 // cleanup
574 DeleteIterators(slaveIters);
575 }
576
577 }
578
579
580 //______________________________________________________________________________
581 void TAMOutput::NullClassFor(void* adr, const Char_t* tid) const
582 {
583 // Print warning that the class for the pointer sent to AddOutput() is not
584 // in the ROOT class dictionary.
585
586 Error("AddOutput",
587 "(%s): Could not get class info for object at %p with typeid %s.",
588 GetName(), adr, tid);
589 }
590
591
592 //______________________________________________________________________________
593 void TAMOutput::NullObjInAddOutput() const
594 {
595 // Print warning that a null pointer was sent to AddOutput().
596 Error("AddOutput",
597 "(%s): Can not add null object to output.", GetName());
598 }
599
600
601 //______________________________________________________________________________
602 void TAMOutput::Print(Option_t *wildcard) const
603 {
604 // Print the output objects inside this module and its submodules.
605
606 TROOT::IndentLevel();
607 cout << "Output of " << GetName() << ":" << endl;
608
609 fOutput.Print(wildcard);
610
611 TROOT::IncreaseDirLevel();
612 TList::Print(wildcard);
613 TROOT::DecreaseDirLevel();
614 }
615
616
617 //______________________________________________________________________________
618 void TAMOutput::Print(Option_t* wildcard, Option_t* option) const
619 {
620 // Print the output objects inside this module and its submodules.
621
622 #if ROOT_VERSION_CODE > ROOT_VERSION(4,0,8)
623 cout << "Output of " << GetName() << ":" << endl;
624 fOutput.Print(wildcard,option);
625 TList::Print(wildcard,option);
626 #else
627 // backward compatible
628 Warning("Print","This version of Root does not handle wildcards.");
629 Print(option);
630 #endif
631 }
632
633
634 //______________________________________________________________________________
635 void TAMOutput::RemoveOutput(TObject* obj)
636 {
637 // Removes the object from the list of output objects of this module.
638
639 fInspector.RemoveOutput(obj);
640 fOutput.Remove(obj);
641 fCurOutput.Remove(obj);
642 }
643
644
645 //______________________________________________________________________________
646 void TAMOutput::SetAllOutputMembers(const Bool_t setAddresses) {
647 // Recursively set the module's output members.
648 // If setAddresses is true, make them point to the output objects.
649
650 SetOutputMembers(setAddresses);
651
652 TIter nextout(MakeIterator());
653 TAMOutput* out=0;
654 while ( (out = dynamic_cast<TAMOutput*>(nextout())) ) {
655 out->SetAllOutputMembers(setAddresses);
656 }
657 }
658
659
660 //______________________________________________________________________________
661 void TAMOutput::SetOutputMembers(const Bool_t setAddresses)
662 {
663 // Det the module's output members.
664 // If setAddresses is true, make them point to the output objects.
665
666 R__ASSERT(fMod!=0);
667
668 // first update the addresses of the members
669 Char_t parent[kParentStrLen];
670 memset(parent, 0, kParentStrLen * sizeof(Char_t));
671 fMod->ShowMembers(fInspector, parent);
672
673 if (setAddresses) {
674 // loop through output objects and set the corresponding members
675 TIter nextout(fCurOutput.MakeIterator());
676 TObject* obj=0;
677 while ( (obj = nextout()) ) {
678 fInspector.SetMemberAddrFor(obj, fMod->GetVerbosity());
679 }
680 }
681 }
682
683
684 //______________________________________________________________________________
685 void TAMOutput::StoreAllOutputObjs()
686 {
687 // Recursively set move output objects from fCutOutput to fOutput
688 // to be called after Merge, but before Terminate.
689 // To be called only by TAModule.
690
691 StoreOutputObjs();
692
693 TIter nextout(MakeIterator());
694 TAMOutput* out=0;
695 while ( (out = dynamic_cast<TAMOutput*>(nextout())) ) {
696 out->StoreAllOutputObjs();
697 }
698 }
699
700
701 //______________________________________________________________________________
702 void TAMOutput::StoreOutputObjs()
703 {
704 // Iterate over fCurOutput and move the objects to fOutput
705 // to be called after Merge, but before Terminate.
706 // To be called only by StoreAllOutputObjs.
707
708 if (fCurOutput.IsEmpty()==kFALSE) { // (if there are any output objects)
709 // loop over fCurOutput
710 TIter nextOutputObj(fCurOutput.MakeIterator());
711 TObject* outObj=0;
712 while ( (outObj = nextOutputObj()) ) {
713 fOutput.Add(outObj);
714 }
715 fCurOutput.Clear("nodelete");
716 }
717 }
718
719
720 //______________________________________________________________________________
721 void TAMOutput::WarnNameDuplicate(const TObject* obj) const
722 {
723 // Print warning that the output list already contains an object with
724 // the same name.
725
726 Warning("AddOutput",
727 "(%s): Output list already contains object with name [%s]. "
728 "Adding object at %p with duplicate name.",
729 GetName(),
730 (obj!=0) ? obj->GetName() : "",
731 static_cast<const void*>(obj));
732 }
733
734
735 #if ROOT_VERSION_CODE > ROOT_VERSION(4,0,8)
736 //______________________________________________________________________________
737 Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize)
738 {
739 // For this (newer) root version, put the code in the const function.
740 // Wow this is ugly.. but it's backward compatible!
741
742 return (static_cast<const TAMOutput*>(this))->Write(name,option,bsize);
743 }
744
745 Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize) const
746 #else
747 //______________________________________________________________________________
748 Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize) const
749 {
750 // For older root, put the code in the non-const function (so TList::Write
751 // can be called).
752 // Wow this is ugly.. but it's backward compatible!
753
754 return (const_cast<TAMOutput*>(this))->Write(name,option,bsize);
755 }
756
757 //______________________________________________________________________________
758 Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize)
759 #endif
760 {
761 // Write all output objects.
762 // Default behavior is to go through this module and all sub modules and
763 // write all the output objects, flattening the module hierarchy.
764 // If the 'TObject::kSingleKey' option is specified, the TAMOutput
765 // objects themselves will be written, thus preserving the module hierarchy.
766 // If option==-99, the module hierarchy will be preserved, but TDirectories
767 // will be used instead of TAMOutput objects.
768
769 if (option == -99) {
770 Int_t nbytes = fOutput.Write(name, 0, bsize);
771 TIter nextMod(MakeIterator());
772 TObject* obj=0;
773 while ( (obj = nextMod()) ) {
774 TDirectory *newdir = gDirectory->mkdir(obj->GetName());
775 TDirectory::TContext context(newdir);
776 nbytes += obj->Write(name, option, bsize);
777 }
778 return nbytes;
779 } else if ( (option & TObject::kSingleKey) ) {
780 // here, the TList write will work just fine since it will actually
781 // call the streamer on the module output objects
782 // (through TObject::Write)
783 return TList::Write(name, option, bsize);
784 } else {
785 // flatten the module hierarchy and dump all output objects to the file
786 Int_t nbytes = fOutput.Write(name, option, bsize);
787 TIter nextMod(MakeIterator());
788 TObject* obj=0;
789 while ( (obj = nextMod()) ) {
790 nbytes += obj->Write(name, option, bsize);
791 }
792 return nbytes;
793 }
794 }