]>
Commit | Line | Data |
---|---|---|
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 | ||
119 | ClassImp(AliJob) // Class implementation to enable ROOT I/O | |
120 | ||
121 | AliJob::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 | /////////////////////////////////////////////////////////////////////////// | |
138 | AliJob::~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 | /////////////////////////////////////////////////////////////////////////// | |
173 | void 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 | 190 | void 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 | 228 | void 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 | 239 | TFolder* AliJob::GetFolder() const |
240 | { | |
241 | // Provide pointer to the whiteboard folder. | |
242 | return fFolder; | |
243 | } | |
244 | /////////////////////////////////////////////////////////////////////////// | |
245 | TObject* AliJob::GetMainObject() const | |
246 | { | |
247 | // Provide pointer to the main object structure. | |
248 | return fMainObject; | |
249 | } | |
250 | /////////////////////////////////////////////////////////////////////////// | |
251 | void 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 | /////////////////////////////////////////////////////////////////////////// | |
261 | void 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 | /////////////////////////////////////////////////////////////////////////// | |
303 | void 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 | /////////////////////////////////////////////////////////////////////////// | |
317 | void 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 | /////////////////////////////////////////////////////////////////////////// | |
338 | void 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 | /////////////////////////////////////////////////////////////////////////// | |
364 | TObject* 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 | /////////////////////////////////////////////////////////////////////////// | |
377 | TObject* 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 | /////////////////////////////////////////////////////////////////////////// | |
396 | TObjArray* AliJob::GetObjects() const | |
397 | { | |
398 | // Provide pointers of all the stored objects. | |
399 | return fObjects; | |
400 | } | |
401 | /////////////////////////////////////////////////////////////////////////// | |
402 | TObjArray* 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 | 425 | void 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 | /////////////////////////////////////////////////////////////////////////// |