Coverity fixes.
[u/mrichter/AliRoot.git] / RALICE / AliJob.cxx
CommitLineData
5481c137 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16// $Id$
17
18///////////////////////////////////////////////////////////////////////////
19// Class AliJob
20// Base class for the top level processor class in a task based procedure.
21// It allows stepwise invokation of various sub-tasks by the derived
22// (user defined) top level processor, based on looping over a certain
23// main object structure (e.g. AliEvent for event-by-event processing).
24// The main object structure (if needed) may be specified by the derived
25// top level processor class and will be stored automatically in the
3bd8f3ec 26// working environment (see below).
27//
28// However, being designed as a base class for a user defined top level
29// processor, this class can also be used as a "hook" to specify
30// various sub-tasks in an (interactive) user environment.
31// Usage of the memberfunction ProcessObject() allows an (interactive)
32// event-by-event processing of the various specified subtasks.
33//
5481c137 34// This base class provides a working environment for the derived
35// (user defined) processor class and all of its subtasks.
36//
1c9018c6 37// The default working environment consists of :
38//
39// * An array containing pointers to the objects which are stored
40// via the AddObject() facility of this AliJob class.
41// From this storage the objects can be directly accessed via the
42// GetObject() and GetObjects() memberfunctions.
43// * A pointer to the main object structure during job processing.
44// This pointer can be initiated/updated only by the derived top level
45// processor via the SetMainObject() facility but all sub-tasks can access
46// it via the above array facilities or the GetMainObject() memberfunction.
47// The latter provides faster access to the main object structure than
48// the GetObject (search) based procedures.
49//
9f575717 50// Optionally one may invoke the MakeFolder() memberfunction or use the
51// "mode" argument of ExecuteJob (see below) to provide in addition to the above
52// the following job-specific folder structure :
1c9018c6 53//
5481c137 54// * A folder which may serve as a whiteboard for transferring pointers to
55// objects which are posted there by the top level processor or any
56// of its subtasks.
57// Objects can be posted in the job folder via the AddObject() facility
58// of this AliJob class.
59// Access to the job folder is obtained via the GetFolder() memberfunction
60// and from this the various objects can be accessed via the usual TFolder
61// FindObject and/or iterator facilities.
5481c137 62//
63// Notes :
64// -------
65// 1) This AliJob class is derived from TTask, which implies that every
66// (user defined) top level processor class is itself also a TTask.
67// This allows sub-tasks to be introduced to the top level processor
68// using the standard TTask facilities.
69//
70// 2) Only references to the various introduced objects are stored.
71// It is the user's responsibility to delete all introduced objects,
1c9018c6 72// either in the Exec() or destructor of the derived top level processor class
5481c137 73// or via Clear() facility as provided by the TTask machinery.
74//
75// 3) The top level processor instance is entered into the standard ROOT
76// ListOfTasks under the name which was provided by the user in the
77// constructor of the top level processor.
78// The name of the top level processor is passed automatically as the
79// opt argument to the Exec(Option_t* opt) memberfunctions of the
80// various sub-tasks by the ExecuteJob() memberfunction (see below).
81// This allows all sub-tasks to obtain the pointer to the top level
82// processor instance from its name via the statement :
83//
84// AliJob* parent=(AliJob*)gROOT->GetListOfTasks()->FindObject(opt)
85//
1c9018c6 86// 4) If selected, the job-specific folder will be created in the generic folder
87// called "AliJob-folders" as a sub-folder under the same name as the one
5481c137 88// introduced in the constructor of the derived top level processor class.
1c9018c6 89// The folder will only be created if the MakeFolder() member function has been
9f575717 90// invoked or when selected explicitly by the "mode" argument of ExecuteJob().
91// Actual creation of the folder environment (and internal array storage as well)
92// only takes place when the first object is posted via the AddObject()
1c9018c6 93// or SetMainObject() facilities.
5481c137 94//
95// Execution of the (user defined) top level processor has to be invoked via
96// the memberfunction ExecuteJob() of this AliJob base class.
1c9018c6 97// This will set the default gROOT as the global working directory and then
98// invoke the (user written) Exec() memberfunction of the top level
5481c137 99// processor class with as argument the name of the top level processor instance
100// as specified by the user in the top level processor constructor.
101// This will allow stepwise (e.g. event-by-event) execution of the various sub-tasks.
9f575717 102// In addition the "mode" argument of ExecuteJob() may be used to select/overrule
103// creation of the folder environment for the complete job.
104// See the docs of ExecuteJob() for further details.
5481c137 105//
106// It is the user's responsibility to invoke the sub-tasks via the
107// ExecuteTasks() statement at the appropriate location in the top level
9c826438 108// processor class if auto-execution was not explicitly selected via the
109// "mode" argument of the ExecuteJob() memberfunction.
5481c137 110//
111//--- Author: Nick van Eijndhoven 07-may-2005 Utrecht University
112//- Modified: NvE $Date$ Utrecht University
113///////////////////////////////////////////////////////////////////////////
114
b09247a2 115#include <cstdlib>
5481c137 116#include "AliJob.h"
117#include "Riostream.h"
118
119ClassImp(AliJob) // Class implementation to enable ROOT I/O
120
121AliJob::AliJob(const char* name,const char* title) : TTask(name,title)
122{
123// Default constructor.
124// Initialise the working environment for general data access
125// by the derived task and its subtasks.
126
1c9018c6 127 fMakefolder=0;
5481c137 128 fMainObject=0;
129 fFolder=0;
130 fObjects=0;
131 fSelect=0;
132
133 // Introduce this AliJob based instance into the ROOT task list
134 TSeqCollection* tasks=gROOT->GetListOfTasks();
135 if (tasks) tasks->Add(this);
136}
137///////////////////////////////////////////////////////////////////////////
138AliJob::~AliJob()
139{
140// Default destructor.
1c9018c6 141// The internal array and job specific folder (if any) holding the various
142// references are deleted.
143// Note : The objects belonging to the various pointers in the array/folder
5481c137 144// and the main processing object are NOT deleted by this base class.
145
9f575717 146 // Remove this AliJob based instance into the ROOT task list
147 TSeqCollection* tasks=gROOT->GetListOfTasks();
148 if (tasks) tasks->Remove(this);
149
5481c137 150 if (fObjects)
151 {
152 delete fObjects;
153 fObjects=0;
154 }
155 if (fFolder)
156 {
1c9018c6 157 TList* list=gROOT->GetListOfBrowsables();
158 if (list)
159 {
160 TFolder* top=(TFolder*)list->FindObject("AliJob-folders");
161 if (top) RecursiveRemove(fFolder);
162 }
5481c137 163 delete fFolder;
164 fFolder=0;
165 }
166 if (fSelect)
167 {
168 delete fSelect;
169 fSelect=0;
170 }
171}
172///////////////////////////////////////////////////////////////////////////
173void AliJob::ListEnvironment()
174{
175// Provide listing of the job environment.
176
177 cout << " ***" << endl;
178 cout << " *** Environment of job " << GetName() << " ***" << endl;
179 cout << " ***" << endl;
180 cout << " === Available (sub)tasks : " << endl;
181 ls();
1c9018c6 182 if (fFolder)
183 {
184 cout << " === Current job-folder contents : " << endl;
185 fFolder->ls();
186 }
5481c137 187 cout << endl;
188}
189///////////////////////////////////////////////////////////////////////////
9f575717 190void AliJob::ExecuteJob(Int_t mode)
5481c137 191{
192// Invokation of the top level processor via its Exec() memberfunction.
9f575717 193// The input argument "mode" can be used to explicitly specify the
9c826438 194// (de)selection of the folder environment creation and automatic
195// invokation of all subtasks after execution of the top level
196// Exec() memberfunction.
197// The latter is convenient if an AliJob instance is used directly
198// by the user (e.g. in a ROOT macro) in order to provide a hook
3bd8f3ec 199// for event-by-event processing of various subtasks.
200// An even more convenient alternative to achieve this is invokation of the
201// memberfunction ProcessObject().
9f575717 202//
203// mode = -1 : Explicitly prohibit folder creation for the complete job
204// 0 : Folder creation selection steered by MakeFolder()
205// 1 : Explicitly select creation of the folder environment
206// for the complete job.
9c826438 207// -11 : Same as mode=-1 but also auto-execution of subtasks after Exec()
208// 10 : Same as mode=0 but also auto-execution of subtasks after Exec()
209// 11 : Same as mode=1 but also auto-execution of subtasks after Exec()
9f575717 210//
211// The default is mode=0.
212//
1c9018c6 213// Note : Before execution gROOT is set as the global working directory.
9f575717 214
215 if (mode<0) fMakefolder=-1;
9c826438 216 if (mode==1 || mode==11) fMakefolder=1;
9f575717 217
1c9018c6 218 gROOT->cd();
5481c137 219 Exec(GetName());
9c826438 220
221 if (abs(mode)>9)
222 {
223 CleanTasks();
224 ExecuteTasks(GetName());
225 }
5481c137 226}
227///////////////////////////////////////////////////////////////////////////
1c9018c6 228void AliJob::MakeFolder()
229{
230// Select creation of the folder structure in addition to the internal
231// array storage of objects.
9f575717 232// Creation of the folder structure is only activated if it was not
233// explicitly forbidden by the specified "mode" on invokation of the
234// ExecuteJob() memberfunction.
235
236 if (!fMakefolder) fMakefolder=1;
1c9018c6 237}
238///////////////////////////////////////////////////////////////////////////
5481c137 239TFolder* AliJob::GetFolder() const
240{
241// Provide pointer to the whiteboard folder.
242 return fFolder;
243}
244///////////////////////////////////////////////////////////////////////////
245TObject* AliJob::GetMainObject() const
246{
247// Provide pointer to the main object structure.
248 return fMainObject;
249}
250///////////////////////////////////////////////////////////////////////////
251void AliJob::SetMainObject(TObject* obj)
252{
253// Store pointer to the main object structure.
254 if (obj)
255 {
256 fMainObject=obj;
257 AddObject(obj);
258 }
259}
260///////////////////////////////////////////////////////////////////////////
261void AliJob::AddObject(TObject* obj)
262{
263// Store pointer of specified object in the working environment.
264
265 if (!obj) return;
266
267 if (!fObjects) fObjects=new TObjArray();
268
9f575717 269 if (fMakefolder>0 && !fFolder)
5481c137 270 {
271 // Create the top level environment folder for all AliJobs if needed
272 TList* list=gROOT->GetListOfBrowsables();
273 if (list)
274 {
275 TFolder* top=(TFolder*)list->FindObject("AliJob-folders");
276 if (!top)
277 {
278 top=new TFolder("AliJob-folders","Environment for all AliJob derived tasks");
279 list->Add(top,"AliJob-folders");
280 }
281 // Create the task-specific folder as a sub-folder in the top folder
282 fFolder=top->AddFolder(GetName(),GetTitle());
283 }
284 }
285
286 // Add object pointer to array and folder if it doesn't already exist
287 Int_t exist=0;
288 for (Int_t i=0; i<fObjects->GetEntries(); i++)
289 {
290 if (obj==fObjects->At(i))
291 {
292 exist=1;
293 break;
294 }
295 }
296 if (!exist)
297 {
298 fObjects->Add(obj);
1c9018c6 299 if (fFolder) fFolder->Add(obj);
5481c137 300 }
301}
302///////////////////////////////////////////////////////////////////////////
303void AliJob::AddObjects(TObjArray* arr)
304{
305// Store pointers of all the array objects individually in the working environment.
306
307 if (!arr) return;
308
309 TObject* obj=0;
310 for (Int_t i=0; i<arr->GetSize(); i++)
311 {
312 obj=arr->At(i);
313 if (obj) AddObject(obj);
314 }
315}
316///////////////////////////////////////////////////////////////////////////
317void AliJob::RemoveObject(TObject* obj)
318{
319// Remove pointer of specified object from the working environment.
1c9018c6 320// In case the specified object is also the main object, the main object
321// pointer will be set to 0 as well.
5481c137 322
323 if (!obj) return;
324
325 if (fObjects)
326 {
327 TObject* test=fObjects->Remove(obj);
1c9018c6 328 if (test)
329 {
330 fObjects->Compress();
331 if (test==fMainObject) fMainObject=0;
332 }
5481c137 333 }
334
335 if (fFolder) fFolder->Remove(obj);
336}
337///////////////////////////////////////////////////////////////////////////
338void AliJob::RemoveObjects(const char* classname)
339{
340// Remove all stored objects inheriting from classname.
1c9018c6 341// In case one of the removed objects is also the main object, the main object
342// pointer will be set to 0 as well.
5481c137 343
344 if (!fObjects) return;
345
346 Int_t remove=0;
347 for (Int_t i=0; i<fObjects->GetEntries(); i++)
348 {
349 TObject* obj=fObjects->At(i);
350 if (obj->InheritsFrom(classname))
351 {
352 TObject* test=fObjects->Remove(obj);
1c9018c6 353 if (test)
354 {
355 remove=1;
356 if (test==fMainObject) fMainObject=0;
357 }
5481c137 358 if (fFolder) fFolder->Remove(obj);
359 }
360 }
361 if (remove) fObjects->Compress();
362}
363///////////////////////////////////////////////////////////////////////////
364TObject* AliJob::GetObject(Int_t j) const
365{
366// Provide pointer to j-th stored object.
367// Note : j=1 indicates the first object.
368
369 if (!fObjects || j<1) return 0;
370
371 TObject* obj=0;
372
373 if (j<=fObjects->GetEntries()) obj=fObjects->At(j-1);
374 return obj;
375}
376///////////////////////////////////////////////////////////////////////////
377TObject* AliJob::GetObject(const char* classname) const
378{
379// Provide pointer to the first stored object which inherits from classname.
380
381 if (!fObjects) return 0;
382
383 TObject* obj=0;
384 for (Int_t i=0; i<fObjects->GetEntries(); i++)
385 {
386 TObject* obx=fObjects->At(i);
387 if (obx->InheritsFrom(classname))
388 {
389 obj=obx;
390 break;
391 }
392 }
393 return obj;
394}
395///////////////////////////////////////////////////////////////////////////
396TObjArray* AliJob::GetObjects() const
397{
398// Provide pointers of all the stored objects.
399 return fObjects;
400}
401///////////////////////////////////////////////////////////////////////////
402TObjArray* AliJob::GetObjects(const char* classname)
403{
404// Provide pointers to all stored objects inheriting from classname.
405
406 if (!fObjects) return 0;
407
408 if (fSelect)
409 {
410 fSelect->Clear();
411 }
412 else
413 {
414 fSelect=new TObjArray();
415 }
416
417 for (Int_t i=0; i<fObjects->GetEntries(); i++)
418 {
419 TObject* obj=fObjects->At(i);
420 if (obj->InheritsFrom(classname)) fSelect->Add(obj);
421 }
422 return fSelect;
423}
424///////////////////////////////////////////////////////////////////////////
3bd8f3ec 425void AliJob::ProcessObject(TObject* obj)
426{
427// Invokation of all user defined sub-tasks for the specified object.
428// This facility is very convenient when performing a task based
429// event-by-event analysis in an (interactive) user application.
430//
431// Note :
432// ------
433// Before processing gROOT is set as the global working directory.
434// The specified object will be added to the job's object list
435// as main object before the processing starts.
436// This will allow the various sub-tasks to access the object in the
437// usual way.
438// After the processing of this object has been performed, the object
439// will be removed from the object list and the main object pointer will
440// be set to zero.
441
442 if (!obj) return;
443
444 SetMainObject(obj);
445
446 gROOT->cd();
447 CleanTasks();
448 ExecuteTasks(GetName());
449
450 RemoveObject(obj);
451}
452///////////////////////////////////////////////////////////////////////////