Fix for #63914: Increasing time per event
[u/mrichter/AliRoot.git] / STEER / STEER / AliDataLoader.cxx
1 /////////////////////////////////////////////////////////////////////////////////////////////
2 //                                                                                         //
3 //  class AliDataLoader                                                                    //
4 //                                                                                         //
5 //  Container of all data needed for full                                                  //
6 //  description of each data type                                                          //
7 //  (Hits, Kine, ...)                                                                      //
8 //                                                                                         //
9 //  Each data loader has a basic standard setup of BaseLoaders                             //
10 //  which can be identuified by indexes (defined by EStdBasicLoaders)                      //
11 //  Data managed by these standard base loaders has fixed naming convention                //
12 //  e.g. - tree with hits is always named TreeH                                            //
13 //                     (defined in AliLoader::fgkDefaultHitsContainerName)                 //
14 //       - task DtectorName+Name defined                                                   //
15 //                                                                                         //
16 //  EStdBasicLoaders   idx     Object Type        Description                              //
17 //      kData           0    TTree or TObject     main data itself (hits,digits,...)       //
18 //      kTask           1        TTask            object producing main data               //
19 //      kQA             2        TTree                quality assurance tree               //
20 //      kQATask         3        TTask            task producing QA object                 //
21 //                                                                                         //
22 //                                                                                         //
23 //  User can define and add more basic loaders even Run Time.                              //
24 //  Caution: in order to save information about added base loader                          //
25 //  user must rewrite Run Loader to galice.file, overwriting old setup                     //
26 //                                                                                         //
27 /////////////////////////////////////////////////////////////////////////////////////////////
28
29 /* $Id$ */
30
31 #include "AliDataLoader.h"
32 #include "AliRunLoader.h"
33 #include "AliLoader.h"
34 #include "AliObjectLoader.h"
35 #include "AliTreeLoader.h"
36 #include "AliTaskLoader.h"
37 #include "AliLog.h"
38
39 #include <TFile.h>
40 #include <TROOT.h>
41 #include <TString.h>
42 #include <TBits.h>
43
44 ClassImp(AliDataLoader)
45
46 //______________________________________________________________________________
47 AliDataLoader::AliDataLoader():
48  fFileName(0),
49  fFile(0x0),
50  fDirectory(0x0),
51  fFileOption(),
52  fCompressionLevel(2),
53  fNEventsPerFile(0),
54  fBaseLoaders(0x0),
55  fHasTask(kFALSE),
56  fTaskName(),
57  fParentalTask(0x0),
58  fEventFolder(0x0),
59  fFolder(0x0)
60 {
61   
62 }
63
64 //______________________________________________________________________________
65 AliDataLoader::AliDataLoader(const char* filename, const char* contname, 
66                              const char* name, Option_t* opt):
67  TNamed(name,name),
68  fFileName(filename),
69  fFile(0x0),
70  fDirectory(0x0),
71  fFileOption(0),
72  fCompressionLevel(2),
73  fNEventsPerFile(0),
74  fBaseLoaders(new TObjArray(4)),
75  fHasTask(kFALSE),
76  fTaskName(),
77  fParentalTask(0x0),
78  fEventFolder(0x0),
79  fFolder(0x0)
80 {
81   //constructor
82   // creates a 0 loader, depending on option, default "T" is specialized loader for trees
83   // else standard object loader
84   // trees needs special care, becouse we need to set dir before writing
85   AliDebug(1, Form("File name is %s",fFileName.Data()));
86   
87   TString option(opt);
88   AliBaseLoader* bl;
89   if (option.CompareTo("T",TString::kIgnoreCase) == 0)
90     bl = new AliTreeLoader(contname,this);
91   else 
92     bl = new AliObjectLoader(contname,this);
93   fBaseLoaders->AddAt(bl,kData);
94   
95 }
96
97 //______________________________________________________________________________
98 AliDataLoader::~AliDataLoader()
99 {
100   //
101   //dtor
102   //
103   UnloadAll();
104 }
105
106 //______________________________________________________________________________
107 Int_t  AliDataLoader::SetEvent()
108 {
109   //
110   // The same that GetEvent but do not post data to folders
111   //
112   AliRunLoader* rl = GetRunLoader();
113   if (rl == 0x0)
114     {
115       AliError("Can not get RunGettr");
116       return 1;
117     }
118   
119   Int_t evno = rl->GetEventNumber();
120   
121   TIter next(fBaseLoaders);
122   AliBaseLoader* bl;
123   while ((bl = (AliBaseLoader*)next()))
124     {
125       if (bl->DoNotReload() == kFALSE) bl->Clean();
126     }
127   
128   if(fFile)
129     {
130       if (CheckReload())
131         {
132           delete fFile;
133           fFile = 0x0;
134           AliDebug(1, Form("Reloading new file. File opt is %s",fFileOption.Data()));
135           OpenFile(fFileOption);
136         }
137       
138       fDirectory = AliLoader::ChangeDir(fFile,evno);
139       if (fDirectory == 0x0)
140         {
141           AliError(Form("Can not chage directory in file %s",fFile->GetName()));
142           return 1;
143         }
144     }
145   return 0;
146 }
147
148 //______________________________________________________________________________
149 Int_t  AliDataLoader::GetEvent()
150 {
151   // posts all loaded data from files to White Board
152   // event number is defined in RunLoader
153   // 
154   //returns:
155   //     0  - in case of no error
156   //     1  - event not found
157   //     
158   //for each base laoder post, if was loaded before GetEvent
159   
160   //call set event to switch to new directory in file
161   
162   
163   //post all data that were loaded before 
164   // ->SetEvent does not call Unload, but only cleans White Board
165   // such IsLoaded flag stays untached
166   
167   if ( AliLoader::TestFileOption(fFileOption) == kTRUE ) //if file is read or update mode try to post
168     {                                                     //in other case there is no sense to post: file is new
169       TIter nextbl(fBaseLoaders);
170       AliBaseLoader* bl;
171       while ((bl = (AliBaseLoader*)nextbl()))
172         {
173           if (bl->IsLoaded())
174             {
175               if (bl->DoNotReload() == kFALSE) bl->Post();
176             }
177         } 
178     }
179   return 0;
180 }
181
182 //______________________________________________________________________________
183 Int_t AliDataLoader::OpenFile(Option_t* opt)
184 {
185   //Opens file named 'filename', and assigns pointer to it to 'file'
186   //jumps to fDirectoryectory corresponding to current event and stores the pointer to it in 'fDirectory'
187   //option 'opt' is passed to TFile::Open
188   if (fFile)
189     {
190       if(fFile->IsOpen() == kTRUE)
191         {
192           AliWarning(Form(" File %s already opened. First close it.",fFile->GetName()));
193           return 0;
194         }
195       else
196         {
197           AliWarning(Form("Pointer to file %s is not null, but file is not opened",
198                           fFile->GetName()));
199           delete fFile;
200           fFile = 0x0;
201         }
202     }
203   
204   TString fname(SetFileOffset(fFileName));
205   
206   fFile = (TFile *)(gROOT->GetListOfFiles()->FindObject(fname));
207   if (fFile)
208     {
209       if(fFile->IsOpen() == kTRUE)
210         {
211           TString option1 = fFile->GetOption();
212           if (option1.CompareTo("read",TString::kIgnoreCase) == 0)
213             {
214               AliInfo(Form("File %s already opened in read mode.",fFile->GetName()));
215             }
216           else
217             {
218               TString option2 = opt;
219               if (option2.CompareTo("read",TString::kIgnoreCase) == 0)
220                 {
221                   AliInfo(Form("Open already opened file %s in read mode.",fFile->GetName()));
222                 }
223               else {
224                 AliWarning(Form("File %s already opened by sombody else. First close it.",
225                                 fFile->GetName()));
226                 return 0;
227               }
228             }
229         }
230     }
231   
232   fFileOption = opt;
233   fFile = TFile::Open(fname,fFileOption);//open the file
234   if (fFile == 0x0)
235     {//file is null
236       AliError(Form("Can not open file %s",fname.Data()));
237       return 1;
238     }
239   if (fFile->IsOpen() == kFALSE)
240     {//file is null
241       AliError(Form("Can not open file %s",fname.Data()));
242       return 1;
243     }
244   
245   fFile->SetCompressionLevel(fCompressionLevel);
246   
247   AliRunLoader* rg = GetRunLoader();
248   if (rg == 0x0)
249     {
250       AliError("Can not find Run-Loader in folder.");
251       return 2;
252     }
253   Int_t evno = rg->GetEventNumber();
254   
255   fDirectory = AliLoader::ChangeDir(fFile,evno);
256   if (fDirectory == 0x0)
257     {
258       AliError(Form("Can not chage fDirectory in file %s.",fFile->GetName()));
259       return 3; 
260     }
261   return 0;
262 }
263
264 //______________________________________________________________________________
265 void AliDataLoader::Unload()
266 {
267   //
268   //unloads main data -  shortcut method 
269   //
270   GetBaseLoader(0)->Unload();
271 }
272
273 //______________________________________________________________________________
274 void AliDataLoader::UnloadAll()
275 {
276   //
277   // Unloads all data and tasks
278   //
279   if ( fFile == 0x0 ) return; //nothing loaded
280   
281   TIter next(fBaseLoaders);
282   AliBaseLoader* bl;
283   while ((bl = (AliBaseLoader*)next()))
284     {
285       bl->Unload();
286     }
287 }
288
289
290 //______________________________________________________________________________
291 Int_t AliDataLoader::Reload()
292 {
293   //
294   // Unloads and loads data again
295   //
296   if ( fFile == 0x0 ) return 0;
297   
298   TBits loaded(fBaseLoaders->GetEntries());  
299   TIter next(fBaseLoaders);
300   AliBaseLoader* bl;
301   
302   Int_t i = 0;
303   while ((bl = (AliBaseLoader*)next()))
304     {
305       if (bl->IsLoaded())
306         {
307           loaded.SetBitNumber(i++,kTRUE);
308           bl->Unload();
309         }
310     }
311   
312   Int_t retval;
313   i = 0;  
314   next.Reset();
315   while ((bl = (AliBaseLoader*)next()))
316     {
317       if (loaded.TestBitNumber(i++))
318         {
319           retval = bl->Load(fFileOption);
320           if (retval) 
321             {
322               AliError(Form("Error occur while loading %s",bl->GetName()));
323               return retval;
324             }
325         }
326     }
327   return 0;
328 }
329
330
331 //______________________________________________________________________________
332 Int_t AliDataLoader::WriteData(Option_t* opt)
333 {
334   //
335   // Writes primary data ==  first BaseLoader
336   //
337   AliDebug(1, Form("Writing %s container for %s data. Option is %s.",
338                    GetBaseLoader(0)->GetName(),GetName(),opt));
339   return GetBaseLoader(0)->WriteData(opt);
340 }
341
342 //______________________________________________________________________________
343 Int_t AliDataLoader::Load(Option_t* opt)
344 {
345   //
346   // Writes primary data ==  first BaseLoader
347   //
348   return GetBaseLoader(0)->Load(opt);
349 }
350
351 //______________________________________________________________________________
352 Int_t  AliDataLoader::SetEventFolder(TFolder* eventfolder)
353 {
354   //
355   // Sets the event folder
356   //
357   if (eventfolder == 0x0)
358     {
359       AliError("Stupid joke. Argument is NULL");
360       return 1;
361     }
362   AliDebug(1, Form("name = %s Setting Event Folder named %s.",
363                    GetName(),eventfolder->GetName()));
364   
365   fEventFolder = eventfolder;
366   return 0;
367 }
368
369
370 //______________________________________________________________________________
371 Int_t  AliDataLoader::SetFolder(TFolder* folder)
372 {
373   // Sets the folder and the data loaders
374   if (folder == 0x0)
375     {
376       AliError("Stupid joke. Argument is NULL");
377     return 1;
378     }
379   
380   AliDebug(1, Form("name = %s Setting folder named %s.",GetName(),folder->GetName()));
381   
382   fFolder = folder;
383   TIter next(fBaseLoaders);
384   AliBaseLoader* bl;
385   
386   while ((bl = (AliBaseLoader*)next()))
387     {
388       bl->SetDataLoader(this);
389     }  
390   
391   return 0;
392 }
393
394 //______________________________________________________________________________
395 TFolder* AliDataLoader::GetEventFolder()
396 {
397   //
398   // Get EVENT folder
399   // Data that are changing from event to event, even in single run
400   //
401   AliDebug(1, "EF = %#x");
402   return fEventFolder;
403 }
404
405 //______________________________________________________________________________
406 AliRunLoader* AliDataLoader::GetRunLoader()
407 {
408   //
409   // Gets the run-loader from event folder
410   //
411   AliRunLoader* rg = 0x0;
412   TFolder* ef = GetEventFolder();
413   if (ef == 0x0)
414    {
415      AliError("Can not get event folder.");
416      return 0;
417    }
418   rg = dynamic_cast<AliRunLoader*>(ef->FindObject(AliRunLoader::GetRunLoaderName()));
419   return rg;
420 }
421
422 //______________________________________________________________________________
423 void AliDataLoader::CloseFile()
424 {
425   //
426   // Closes file
427   //
428   TIter next(fBaseLoaders);
429   AliBaseLoader* bl;
430   while ((bl = (AliBaseLoader*)next()))
431     {
432       if (bl->IsLoaded()) return;
433     }
434   
435   AliDebug(1, "Closing (object) file.");
436   
437   if (fFile) {
438     fFile->Close("R");
439     fFile = 0x0;
440   }
441   fDirectory = 0x0;
442 }
443
444
445 //______________________________________________________________________________
446 void AliDataLoader::Clean()
447 {
448   //
449   // Cleans main data
450   //
451   GetBaseLoader(0)->Clean();
452 }
453
454 //______________________________________________________________________________
455 void AliDataLoader::CleanAll()
456 {
457   //
458   // Cleans all folders and tasks
459   //
460   TIter next(fBaseLoaders);
461   AliBaseLoader* bl;
462   while ((bl = (AliBaseLoader*)next()))
463     {
464       bl->Clean();
465     }
466 }
467
468 //______________________________________________________________________________
469 void AliDataLoader::SetFileNameSuffix(const TString& suffix)
470 {
471   //
472   // adds the suffix before ".root", 
473   // e.g. TPC.Digits.root -> TPC.DigitsMerged.root
474   // made on Jiri Chudoba demand
475   //
476   AliDebug(1, Form("suffix=%s",suffix.Data()));
477   AliDebug(1, Form("   Digits File Name before: %s",fFileName.Data()));
478   
479   static const TString dotroot(".root");
480   const TString& suffixdotroot = suffix + dotroot;
481   fFileName = fFileName.ReplaceAll(dotroot,suffixdotroot);
482   
483   AliDebug(1, Form("                    after : %s",fFileName.Data()));
484 }
485
486 //______________________________________________________________________________
487 Bool_t AliDataLoader::CheckReload()
488 {
489   //
490   // Checks if we have to reload given file
491   //
492   if (fFile == 0x0) return kFALSE;
493   TString tmp = SetFileOffset(fFileName);
494   if (tmp.CompareTo(fFile->GetName())) return kTRUE;  //file must be reloaded
495   return  kFALSE;
496 }
497
498 //______________________________________________________________________________
499 const TString AliDataLoader::SetFileOffset(const TString& fname)
500 {
501   //
502   // Return fname
503   //
504   Long_t offset = (Long_t)GetRunLoader()->GetFileOffset();
505   if (fNEventsPerFile > 0) {
506     offset = GetRunLoader()->GetEventNumber()/fNEventsPerFile;
507   }
508   if (offset < 1) return fname;
509   
510   TString soffset;
511   soffset += offset;//automatic conversion to string
512   TString dotroot(".root");
513   const TString& offfsetdotroot = offset + dotroot;
514   TString out = fname;
515   out = out.ReplaceAll(dotroot,offfsetdotroot);
516   AliDebug(1, Form("in=%s  out=%s.",fname.Data(),out.Data()));
517   return out;
518 }
519
520 //______________________________________________________________________________
521 void AliDataLoader::SetFileOption(Option_t* newopt)
522 {
523   //
524   // Sets file option
525   //
526   if (fFileOption.CompareTo(newopt) == 0) return;
527   fFileOption = newopt;
528   Reload();
529 }
530
531 //______________________________________________________________________________
532 void AliDataLoader::SetCompressionLevel(Int_t cl)
533 {
534   //
535   // Sets comression level for data defined by di
536   //
537   fCompressionLevel = cl;
538   if (fFile) fFile->SetCompressionLevel(cl);
539 }
540
541 //______________________________________________________________________________
542 void AliDataLoader::MakeTree()
543 {
544   //
545   // Makes tree for the current data loader
546   //
547   AliTreeLoader* tl = dynamic_cast<AliTreeLoader*>(fBaseLoaders->At(0));
548   if (tl == 0x0)
549    {
550      AliError("Can not make a tree because main base loader is not a tree loader");
551      return;
552    }
553   tl->MakeTree();
554 }
555
556 //______________________________________________________________________________
557 Bool_t AliDataLoader::IsFileWritable() const
558 {
559   //
560   // Returns true if file is writable
561   //
562   return (fFile)?fFile->IsWritable():kFALSE;
563 }
564
565 //______________________________________________________________________________
566 Bool_t AliDataLoader::IsFileOpen() const
567 {
568   //
569   // Returns true if file is writable
570   //
571   return (fFile)?fFile->IsOpen():kFALSE;
572 }
573
574 //______________________________________________________________________________
575 Bool_t AliDataLoader::IsOptionContrary(const TString& option) const
576 {
577   // Checks if passed option is contrary with file open option 
578   // which is passed option "writable" and existing option not wriable
579   // in reverse case it is no harm so it is NOT contrary
580   if (fFile == 0x0) return kFALSE; //file is not opened - no problem
581   
582   if ( ( AliLoader::IsOptionWritable(option)      == kTRUE  ) &&     // passed option is writable and 
583        ( AliLoader::IsOptionWritable(fFileOption) == kFALSE )    )   // existing one is not writable
584     {
585       return kTRUE;
586     }
587   
588   return kFALSE;
589 }
590
591
592 //______________________________________________________________________________
593 void AliDataLoader::AddBaseLoader(AliBaseLoader* bl)
594 {
595   //Adds a base loader to lits of base loaders managed by this data loader
596   //Managed data/task will be stored in proper root directory,
597   //and posted to 
598   // - in case of tree/object - data folder connected with detector associated with this data loader
599   // - in case of task - parental task which defined in this AliTaskLoader 
600   
601   if (bl == 0x0)
602     {
603       AliWarning("Pointer is null.");
604       return;
605     }
606   
607   TObject* obj = fBaseLoaders->FindObject(bl->GetName());
608   if (obj)
609     {
610       AliError("Can not add this base loader.");
611       AliError(Form("There exists already base loader which manages data named %s for this detector.",obj->GetName()));
612       return;
613     }
614  
615   fBaseLoaders->Add(bl);
616 }
617
618 //______________________________________________________________________________
619 AliBaseLoader* AliDataLoader::GetBaseLoader(const TString& name) const
620 {
621   //
622   // Return pointer to base loader
623   //
624   return dynamic_cast<AliBaseLoader*>(fBaseLoaders->FindObject(name));
625 }
626
627 //______________________________________________________________________________
628 AliBaseLoader* AliDataLoader::GetBaseLoader(Int_t n) const
629 {
630   //
631   // Gets the n-th base loader (what is n?)
632   //
633   return dynamic_cast<AliBaseLoader*>(fBaseLoaders->At(n));
634 }
635
636 //______________________________________________________________________________
637 TTree* AliDataLoader::Tree() const
638 {
639   // Returns tree from the main base loader
640   // it is just shortcut method for comfort of user
641   // main storage object does not have to be Tree  - 
642   // that is why first we need to check if it is a TreeLoader 
643   AliTreeLoader* tl = dynamic_cast<AliTreeLoader*>(GetBaseLoader(0));
644   if (tl == 0x0) return 0x0;
645   return tl->Tree();
646 }
647
648 //______________________________________________________________________________
649 void  AliDataLoader::SetDirName(TString& dirname)
650 {
651   //
652   // Sets the directory name where the files will be stored
653   //
654   AliDebug(10, Form("FileName before %s",fFileName.Data()));
655   Int_t n = fFileName.Last('/');
656   AliDebug(10, Form("Slash found on pos %d",n));
657   if (n > 0) fFileName = fFileName.Remove(0,n+1);
658   AliDebug(10, Form("Core FileName %s",fFileName.Data()));
659   fFileName = dirname + fFileName;
660   AliDebug(10, Form("FileName after %s",fFileName.Data()));
661 }
662
663 //______________________________________________________________________________
664 AliObjectLoader* AliDataLoader::GetBaseDataLoader()
665 {
666   //
667   // Gets the base data loader
668   //
669   return dynamic_cast<AliObjectLoader*>(GetBaseLoader(kData));
670 }
671
672 //______________________________________________________________________________
673 AliTaskLoader* AliDataLoader::GetBaseTaskLoader()
674 {
675   //
676   // Gets the base task loader
677   //
678   return dynamic_cast<AliTaskLoader*>(GetBaseLoader(kTask));
679 }
680
681 //______________________________________________________________________________
682 AliBaseLoader* AliDataLoader::GetBaseQALoader()
683 {
684   //
685   // Gets the base QA loader
686   //
687   return GetBaseLoader(kQA);
688 }
689
690 //______________________________________________________________________________
691 AliTaskLoader* AliDataLoader::GetBaseQATaskLoader()
692 {
693   //
694   // Returns pointer to QA base loader
695   //
696   return dynamic_cast<AliTaskLoader*>(GetBaseLoader(kQATask));
697 }
698
699 //______________________________________________________________________________
700 void AliDataLoader::SetBaseDataLoader(AliBaseLoader* bl)
701 {
702   //
703   // Sets data base loader
704   //
705   if (bl == 0x0)
706     {
707       AliError("Parameter is null");
708       return;
709     }
710   if (GetBaseDataLoader()) delete GetBaseDataLoader();
711   fBaseLoaders->AddAt(bl,kData);
712 }
713
714 //______________________________________________________________________________
715 void AliDataLoader::SetBaseTaskLoader(AliTaskLoader* bl)
716 {
717   //
718   // Sets Task base loader
719   //
720   if (bl == 0x0)
721    {
722      AliError("Parameter is null");
723      return;
724    }
725   if (GetBaseTaskLoader()) delete GetBaseTaskLoader();
726   fBaseLoaders->AddAt(bl,kTask);
727 }
728
729 //______________________________________________________________________________
730 void AliDataLoader::SetBaseQALoader(AliBaseLoader* bl)
731 {
732   //
733   // Sets QA base loader
734   //
735   if (bl == 0x0)
736     {
737       AliError("Parameter is null");
738       return;
739     }
740   if (GetBaseQALoader()) delete GetBaseQALoader();
741   fBaseLoaders->AddAt(bl,kQA);
742 }
743
744 //______________________________________________________________________________
745 void AliDataLoader::SetBaseQATaskLoader(AliTaskLoader* bl)
746 {
747   //
748   // Sets QA Task base loader
749   //
750   if (bl == 0x0)
751     {
752       AliError("Parameter is null");
753       return;
754    }
755   if (GetBaseQATaskLoader()) delete GetBaseQATaskLoader();
756   fBaseLoaders->AddAt(bl,kQATask);
757 }
758
759 //______________________________________________________________________________
760 void AliDataLoader::Synchronize()
761 {
762   //
763   // Synchronizes all writable files 
764   //
765   if ( fFile ) fFile->Flush();
766 }
767
768
769