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 |
}
|