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