]>
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 | ||
115 | #include "AliJob.h" | |
116 | #include "Riostream.h" | |
117 | ||
118 | ClassImp(AliJob) // Class implementation to enable ROOT I/O | |
119 | ||
120 | AliJob::AliJob(const char* name,const char* title) : TTask(name,title) | |
121 | { | |
122 | // Default constructor. | |
123 | // Initialise the working environment for general data access | |
124 | // by the derived task and its subtasks. | |
125 | ||
1c9018c6 | 126 | fMakefolder=0; |
5481c137 | 127 | fMainObject=0; |
128 | fFolder=0; | |
129 | fObjects=0; | |
130 | fSelect=0; | |
131 | ||
132 | // Introduce this AliJob based instance into the ROOT task list | |
133 | TSeqCollection* tasks=gROOT->GetListOfTasks(); | |
134 | if (tasks) tasks->Add(this); | |
135 | } | |
136 | /////////////////////////////////////////////////////////////////////////// | |
137 | AliJob::~AliJob() | |
138 | { | |
139 | // Default destructor. | |
1c9018c6 | 140 | // The internal array and job specific folder (if any) holding the various |
141 | // references are deleted. | |
142 | // Note : The objects belonging to the various pointers in the array/folder | |
5481c137 | 143 | // and the main processing object are NOT deleted by this base class. |
144 | ||
9f575717 | 145 | // Remove this AliJob based instance into the ROOT task list |
146 | TSeqCollection* tasks=gROOT->GetListOfTasks(); | |
147 | if (tasks) tasks->Remove(this); | |
148 | ||
5481c137 | 149 | if (fObjects) |
150 | { | |
151 | delete fObjects; | |
152 | fObjects=0; | |
153 | } | |
154 | if (fFolder) | |
155 | { | |
1c9018c6 | 156 | TList* list=gROOT->GetListOfBrowsables(); |
157 | if (list) | |
158 | { | |
159 | TFolder* top=(TFolder*)list->FindObject("AliJob-folders"); | |
160 | if (top) RecursiveRemove(fFolder); | |
161 | } | |
5481c137 | 162 | delete fFolder; |
163 | fFolder=0; | |
164 | } | |
165 | if (fSelect) | |
166 | { | |
167 | delete fSelect; | |
168 | fSelect=0; | |
169 | } | |
170 | } | |
171 | /////////////////////////////////////////////////////////////////////////// | |
172 | void AliJob::ListEnvironment() | |
173 | { | |
174 | // Provide listing of the job environment. | |
175 | ||
176 | cout << " ***" << endl; | |
177 | cout << " *** Environment of job " << GetName() << " ***" << endl; | |
178 | cout << " ***" << endl; | |
179 | cout << " === Available (sub)tasks : " << endl; | |
180 | ls(); | |
1c9018c6 | 181 | if (fFolder) |
182 | { | |
183 | cout << " === Current job-folder contents : " << endl; | |
184 | fFolder->ls(); | |
185 | } | |
5481c137 | 186 | cout << endl; |
187 | } | |
188 | /////////////////////////////////////////////////////////////////////////// | |
9f575717 | 189 | void AliJob::ExecuteJob(Int_t mode) |
5481c137 | 190 | { |
191 | // Invokation of the top level processor via its Exec() memberfunction. | |
9f575717 | 192 | // The input argument "mode" can be used to explicitly specify the |
9c826438 | 193 | // (de)selection of the folder environment creation and automatic |
194 | // invokation of all subtasks after execution of the top level | |
195 | // Exec() memberfunction. | |
196 | // The latter is convenient if an AliJob instance is used directly | |
197 | // by the user (e.g. in a ROOT macro) in order to provide a hook | |
3bd8f3ec | 198 | // for event-by-event processing of various subtasks. |
199 | // An even more convenient alternative to achieve this is invokation of the | |
200 | // memberfunction ProcessObject(). | |
9f575717 | 201 | // |
202 | // mode = -1 : Explicitly prohibit folder creation for the complete job | |
203 | // 0 : Folder creation selection steered by MakeFolder() | |
204 | // 1 : Explicitly select creation of the folder environment | |
205 | // for the complete job. | |
9c826438 | 206 | // -11 : Same as mode=-1 but also auto-execution of subtasks after Exec() |
207 | // 10 : Same as mode=0 but also auto-execution of subtasks after Exec() | |
208 | // 11 : Same as mode=1 but also auto-execution of subtasks after Exec() | |
9f575717 | 209 | // |
210 | // The default is mode=0. | |
211 | // | |
1c9018c6 | 212 | // Note : Before execution gROOT is set as the global working directory. |
9f575717 | 213 | |
214 | if (mode<0) fMakefolder=-1; | |
9c826438 | 215 | if (mode==1 || mode==11) fMakefolder=1; |
9f575717 | 216 | |
1c9018c6 | 217 | gROOT->cd(); |
5481c137 | 218 | Exec(GetName()); |
9c826438 | 219 | |
220 | if (abs(mode)>9) | |
221 | { | |
222 | CleanTasks(); | |
223 | ExecuteTasks(GetName()); | |
224 | } | |
5481c137 | 225 | } |
226 | /////////////////////////////////////////////////////////////////////////// | |
1c9018c6 | 227 | void AliJob::MakeFolder() |
228 | { | |
229 | // Select creation of the folder structure in addition to the internal | |
230 | // array storage of objects. | |
9f575717 | 231 | // Creation of the folder structure is only activated if it was not |
232 | // explicitly forbidden by the specified "mode" on invokation of the | |
233 | // ExecuteJob() memberfunction. | |
234 | ||
235 | if (!fMakefolder) fMakefolder=1; | |
1c9018c6 | 236 | } |
237 | /////////////////////////////////////////////////////////////////////////// | |
5481c137 | 238 | TFolder* AliJob::GetFolder() const |
239 | { | |
240 | // Provide pointer to the whiteboard folder. | |
241 | return fFolder; | |
242 | } | |
243 | /////////////////////////////////////////////////////////////////////////// | |
244 | TObject* AliJob::GetMainObject() const | |
245 | { | |
246 | // Provide pointer to the main object structure. | |
247 | return fMainObject; | |
248 | } | |
249 | /////////////////////////////////////////////////////////////////////////// | |
250 | void AliJob::SetMainObject(TObject* obj) | |
251 | { | |
252 | // Store pointer to the main object structure. | |
253 | if (obj) | |
254 | { | |
255 | fMainObject=obj; | |
256 | AddObject(obj); | |
257 | } | |
258 | } | |
259 | /////////////////////////////////////////////////////////////////////////// | |
260 | void AliJob::AddObject(TObject* obj) | |
261 | { | |
262 | // Store pointer of specified object in the working environment. | |
263 | ||
264 | if (!obj) return; | |
265 | ||
266 | if (!fObjects) fObjects=new TObjArray(); | |
267 | ||
9f575717 | 268 | if (fMakefolder>0 && !fFolder) |
5481c137 | 269 | { |
270 | // Create the top level environment folder for all AliJobs if needed | |
271 | TList* list=gROOT->GetListOfBrowsables(); | |
272 | if (list) | |
273 | { | |
274 | TFolder* top=(TFolder*)list->FindObject("AliJob-folders"); | |
275 | if (!top) | |
276 | { | |
277 | top=new TFolder("AliJob-folders","Environment for all AliJob derived tasks"); | |
278 | list->Add(top,"AliJob-folders"); | |
279 | } | |
280 | // Create the task-specific folder as a sub-folder in the top folder | |
281 | fFolder=top->AddFolder(GetName(),GetTitle()); | |
282 | } | |
283 | } | |
284 | ||
285 | // Add object pointer to array and folder if it doesn't already exist | |
286 | Int_t exist=0; | |
287 | for (Int_t i=0; i<fObjects->GetEntries(); i++) | |
288 | { | |
289 | if (obj==fObjects->At(i)) | |
290 | { | |
291 | exist=1; | |
292 | break; | |
293 | } | |
294 | } | |
295 | if (!exist) | |
296 | { | |
297 | fObjects->Add(obj); | |
1c9018c6 | 298 | if (fFolder) fFolder->Add(obj); |
5481c137 | 299 | } |
300 | } | |
301 | /////////////////////////////////////////////////////////////////////////// | |
302 | void AliJob::AddObjects(TObjArray* arr) | |
303 | { | |
304 | // Store pointers of all the array objects individually in the working environment. | |
305 | ||
306 | if (!arr) return; | |
307 | ||
308 | TObject* obj=0; | |
309 | for (Int_t i=0; i<arr->GetSize(); i++) | |
310 | { | |
311 | obj=arr->At(i); | |
312 | if (obj) AddObject(obj); | |
313 | } | |
314 | } | |
315 | /////////////////////////////////////////////////////////////////////////// | |
316 | void AliJob::RemoveObject(TObject* obj) | |
317 | { | |
318 | // Remove pointer of specified object from the working environment. | |
1c9018c6 | 319 | // In case the specified object is also the main object, the main object |
320 | // pointer will be set to 0 as well. | |
5481c137 | 321 | |
322 | if (!obj) return; | |
323 | ||
324 | if (fObjects) | |
325 | { | |
326 | TObject* test=fObjects->Remove(obj); | |
1c9018c6 | 327 | if (test) |
328 | { | |
329 | fObjects->Compress(); | |
330 | if (test==fMainObject) fMainObject=0; | |
331 | } | |
5481c137 | 332 | } |
333 | ||
334 | if (fFolder) fFolder->Remove(obj); | |
335 | } | |
336 | /////////////////////////////////////////////////////////////////////////// | |
337 | void AliJob::RemoveObjects(const char* classname) | |
338 | { | |
339 | // Remove all stored objects inheriting from classname. | |
1c9018c6 | 340 | // In case one of the removed objects is also the main object, the main object |
341 | // pointer will be set to 0 as well. | |
5481c137 | 342 | |
343 | if (!fObjects) return; | |
344 | ||
345 | Int_t remove=0; | |
346 | for (Int_t i=0; i<fObjects->GetEntries(); i++) | |
347 | { | |
348 | TObject* obj=fObjects->At(i); | |
349 | if (obj->InheritsFrom(classname)) | |
350 | { | |
351 | TObject* test=fObjects->Remove(obj); | |
1c9018c6 | 352 | if (test) |
353 | { | |
354 | remove=1; | |
355 | if (test==fMainObject) fMainObject=0; | |
356 | } | |
5481c137 | 357 | if (fFolder) fFolder->Remove(obj); |
358 | } | |
359 | } | |
360 | if (remove) fObjects->Compress(); | |
361 | } | |
362 | /////////////////////////////////////////////////////////////////////////// | |
363 | TObject* AliJob::GetObject(Int_t j) const | |
364 | { | |
365 | // Provide pointer to j-th stored object. | |
366 | // Note : j=1 indicates the first object. | |
367 | ||
368 | if (!fObjects || j<1) return 0; | |
369 | ||
370 | TObject* obj=0; | |
371 | ||
372 | if (j<=fObjects->GetEntries()) obj=fObjects->At(j-1); | |
373 | return obj; | |
374 | } | |
375 | /////////////////////////////////////////////////////////////////////////// | |
376 | TObject* AliJob::GetObject(const char* classname) const | |
377 | { | |
378 | // Provide pointer to the first stored object which inherits from classname. | |
379 | ||
380 | if (!fObjects) return 0; | |
381 | ||
382 | TObject* obj=0; | |
383 | for (Int_t i=0; i<fObjects->GetEntries(); i++) | |
384 | { | |
385 | TObject* obx=fObjects->At(i); | |
386 | if (obx->InheritsFrom(classname)) | |
387 | { | |
388 | obj=obx; | |
389 | break; | |
390 | } | |
391 | } | |
392 | return obj; | |
393 | } | |
394 | /////////////////////////////////////////////////////////////////////////// | |
395 | TObjArray* AliJob::GetObjects() const | |
396 | { | |
397 | // Provide pointers of all the stored objects. | |
398 | return fObjects; | |
399 | } | |
400 | /////////////////////////////////////////////////////////////////////////// | |
401 | TObjArray* AliJob::GetObjects(const char* classname) | |
402 | { | |
403 | // Provide pointers to all stored objects inheriting from classname. | |
404 | ||
405 | if (!fObjects) return 0; | |
406 | ||
407 | if (fSelect) | |
408 | { | |
409 | fSelect->Clear(); | |
410 | } | |
411 | else | |
412 | { | |
413 | fSelect=new TObjArray(); | |
414 | } | |
415 | ||
416 | for (Int_t i=0; i<fObjects->GetEntries(); i++) | |
417 | { | |
418 | TObject* obj=fObjects->At(i); | |
419 | if (obj->InheritsFrom(classname)) fSelect->Add(obj); | |
420 | } | |
421 | return fSelect; | |
422 | } | |
423 | /////////////////////////////////////////////////////////////////////////// | |
3bd8f3ec | 424 | void AliJob::ProcessObject(TObject* obj) |
425 | { | |
426 | // Invokation of all user defined sub-tasks for the specified object. | |
427 | // This facility is very convenient when performing a task based | |
428 | // event-by-event analysis in an (interactive) user application. | |
429 | // | |
430 | // Note : | |
431 | // ------ | |
432 | // Before processing gROOT is set as the global working directory. | |
433 | // The specified object will be added to the job's object list | |
434 | // as main object before the processing starts. | |
435 | // This will allow the various sub-tasks to access the object in the | |
436 | // usual way. | |
437 | // After the processing of this object has been performed, the object | |
438 | // will be removed from the object list and the main object pointer will | |
439 | // be set to zero. | |
440 | ||
441 | if (!obj) return; | |
442 | ||
443 | SetMainObject(obj); | |
444 | ||
445 | gROOT->cd(); | |
446 | CleanTasks(); | |
447 | ExecuteTasks(GetName()); | |
448 | ||
449 | RemoveObject(obj); | |
450 | } | |
451 | /////////////////////////////////////////////////////////////////////////// |