]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/AliOADBForward.cxx
Mega commit of many changes to PWGLFforward
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliOADBForward.cxx
1 #include "AliOADBForward.h"
2 #include <TBrowser.h>
3 #include <TROOT.h>
4 #include <TKey.h>
5 #include <TList.h>
6 #include <TDatime.h>
7 #include <TTree.h>
8 #include <TFile.h>
9 #include <TError.h>
10 #include <TSystem.h>
11
12 #ifndef ALIROOT_SVN_REVISION
13 # define ALIROOT_SVN_REVISION 0
14 #endif
15
16
17 ClassImp(AliOADBForward)
18 #if 0
19 ; // Do not remove - for Emacs
20 #endif
21
22 //====================================================================
23 const char* 
24 AliOADBForward::Mode2String(ERunSelectMode mode)
25 {
26   switch (mode) { 
27   case kDefault:   return "default"; 
28   case kExact:     return "exact"; 
29   case kNewest:    return "newest";
30   case kNear:      return "near";
31   case kOlder:     return "older";
32   case kNewer:     return "newer";
33   }
34   return "?"; // Should never get here 
35 }
36 AliOADBForward::ERunSelectMode
37 AliOADBForward::String2Mode(const TString& str)
38 {
39   if      (str.EqualTo("default", TString::kIgnoreCase)) return kDefault;
40   else if (str.EqualTo("exact",   TString::kIgnoreCase)) return kExact;
41   else if (str.EqualTo("newest",  TString::kIgnoreCase)) return kNewest;
42   else if (str.EqualTo("near",    TString::kIgnoreCase)) return kNear;
43   else if (str.EqualTo("older",   TString::kIgnoreCase)) return kOlder;
44   else if (str.EqualTo("newer",   TString::kIgnoreCase)) return kNewer;
45   return kDefault;
46 }
47 AliOADBForward::ERunSelectMode
48 AliOADBForward::Int2Mode(Int_t mode)
49 {
50   switch (mode) { 
51   case kDefault:   return kDefault; 
52   case kExact:     return kExact; 
53   case kNewest:    return kNewest;
54   case kNear:      return kNear;
55   case kOlder:     return kOlder;
56   case kNewer:     return kNewer;
57   }
58   return kDefault; // Should never get here 
59 }
60
61
62 //====================================================================
63 AliOADBForward::Entry::Entry(ULong_t  runNo, 
64                              UShort_t sys, 
65                              UShort_t sNN, 
66                              Short_t  field, 
67                              Bool_t   mc, 
68                              Bool_t   sat,
69                              TObject* o)
70   : fRunNo(runNo), 
71     fSys(sys), 
72     fSNN(sNN), 
73     fField(field),
74     fMC(mc), 
75     fSatellite(sat),
76     fData(o),
77     fTimestamp(0), 
78     fAliROOTRevision(0),
79     fAuthor("unknown")
80 {
81   // 
82   // Constructor 
83   // 
84 }
85
86 //____________________________________________________________________
87 AliOADBForward::Entry::Entry(const Entry& o)
88   : TObject(o), 
89     fRunNo(o.fRunNo), 
90     fSys(o.fSys), 
91     fSNN(o.fSNN), 
92     fField(o.fField),
93     fMC(o.fMC), 
94     fSatellite(o.fSatellite), 
95     fData(o.fData),
96     fTimestamp(0), 
97     fAliROOTRevision(0),
98     fAuthor(o.fAuthor)
99 {
100   // 
101   // Copy constructor 
102   //
103 }
104 //____________________________________________________________________
105 AliOADBForward::Entry&
106 AliOADBForward::Entry::operator=(const Entry& o)
107 {
108   // 
109   // Assignment operator 
110   //
111   if (this == &o) return *this;
112   fRunNo              = o.fRunNo; 
113   fSys                = o.fSys; 
114   fSNN                = o.fSNN; 
115   fField              = o.fField;
116   fMC                 = o.fMC; 
117   fSatellite          = o.fSatellite;
118   fData               = o.fData;
119   fTimestamp          = o.fTimestamp;
120   fAliROOTRevision    = o.fAliROOTRevision;
121   fAuthor             = o.fAuthor;
122
123   return *this;
124 }
125 //____________________________________________________________________
126 const char*
127 AliOADBForward::Entry::GetTitle() const
128 {
129   TDatime d(fTimestamp);
130   return Form("%09ld, %4s, %4huGeV, %+2hd, %4s, %3s, %19s: %p (%s) by %s", 
131               (fRunNo == 0xFFFFFFFF ? -1 : fRunNo), 
132               (fSys == 1 ? "pp" : fSys == 2 ? "PbPb" : fSys == 3 ? "pPb" :"?"), 
133               fSNN, fField, (fMC ? "mc" : "real"),
134               (fSatellite ? "sat" : "nom"), d.AsSQLString(), fData,
135               (fData ? fData->GetName() : "?"), fAuthor.Data());
136   
137 }
138 //____________________________________________________________________
139 void
140 AliOADBForward::Entry::Print(Option_t* /*option*/) const 
141 {
142   Printf(GetTitle());
143 }
144 //====================================================================
145 AliOADBForward::Table::Table(TTree* tree, Bool_t isNew, ERunSelectMode mode)
146   : fTree(tree), fEntry(0), fVerbose(false), fMode(mode)
147 {
148   if (!tree) return;
149
150   if (isNew) {
151     fTree->Branch("e", "AliOADBForward::Entry", &fEntry);
152     fMode = String2Mode(fTree->GetTitle());
153   }
154   else {
155     if (fMode <= kDefault || fMode > kNewer) {
156       fMode = String2Mode(fTree->GetTitle());
157       if (fMode == kDefault) fMode = kNear;
158     }
159     fTree->SetBranchAddress("e", &fEntry);
160   }
161 }
162 //____________________________________________________________________
163 AliOADBForward::Table::Table(const Table& o)
164   : TObject(o), 
165     fTree(o.fTree), 
166     fEntry(o.fEntry), 
167     fVerbose(o.fVerbose),
168     fMode(o.fMode)
169 {
170   //
171   // Copy constructor 
172   if (!fTree) return;
173   fTree->SetBranchAddress("e", &fEntry);
174 }
175
176 //____________________________________________________________________
177 AliOADBForward::Table::~Table()
178 {
179   // 
180   // Close this table 
181   //
182   Close();
183 }
184 //____________________________________________________________________
185 AliOADBForward::Table&
186 AliOADBForward::Table::operator=(const Table& o)
187 {
188   // 
189   // Assignment operator 
190   // 
191   if (this == &o) return *this;
192   fTree    = o.fTree;
193   fEntry   = o.fEntry;
194   fVerbose = o.fVerbose;
195   fMode    = o.fMode;
196   if (fTree) fTree->SetBranchAddress("e", &fEntry);
197
198   return *this;
199 }
200
201 //____________________________________________________________________
202 const Char_t*
203 AliOADBForward::Table::GetTableName() const
204 {
205   // 
206   // Get the table name or null
207   if (!fTree) return 0;
208   return fTree->GetName();
209 }
210 //____________________________________________________________________
211 const Char_t*
212 AliOADBForward::Table::GetName() const
213 {
214   // 
215   // Overload of TObject::GetName
216   //
217   if (!fTree) return TObject::GetName();
218   return GetTableName();
219 }
220 //____________________________________________________________________
221 Bool_t
222 AliOADBForward::Table::Update()
223 {
224   // 
225   // Flush to disk 
226   //
227   if (!IsOpen()) { 
228     Error("Update", "No tree associated");
229     return false;
230   }
231       
232   TFile* file = fTree->GetCurrentFile();
233   if (!file) { 
234     Error("Update", "No file associated with tree");
235     return false;
236   }
237   if (!file->IsWritable()) { 
238     Error("Update", "File %s not writeable", file->GetName());
239     return false;
240   }
241       
242   Int_t nBytes = file->Write();
243       
244   return (nBytes >= 0);
245 }
246 //____________________________________________________________________
247 Bool_t
248 AliOADBForward::Table::Close()
249 {
250   // 
251   // Close the connection 
252   //
253   if (!IsOpen()) { 
254     Error("Close", "No tree associated");
255     return false;
256   }
257   
258   // if (fTree)  delete fTree; 
259   // if (fEntry) delete fEntry;
260   fTree  = 0;
261   fEntry = 0;
262   return true;
263
264 //____________________________________________________________________
265 Int_t
266 AliOADBForward::Table::Query(ULong_t        runNo,
267                              ERunSelectMode mode,
268                              UShort_t       sys,
269                              UShort_t       sNN, 
270                              Short_t        fld,
271                              Bool_t         mc,
272                              Bool_t         sat) const
273 {
274   // 
275   // Query the tree 
276   //
277   return Query(runNo, mode, Conditions(sys, sNN, fld, mc, sat));
278 }
279
280 //____________________________________________________________________
281 Int_t
282 AliOADBForward::Table::Query(ULong_t        runNo,
283                              ERunSelectMode mode,
284                              const TString& q) const
285 {
286   // 
287   // Run a query against the table 
288   // 
289   
290   // Check the tree 
291   if (!IsOpen()) { 
292     Error("Close", "No tree associated");
293     return -1;
294   }
295       
296   TString query = q;
297   const char* smode = "latest";
298   if (runNo > 0) {
299     if (mode <= kDefault || mode > kNewer) mode = fMode;
300     smode = Mode2String(mode);
301     switch (mode) { 
302     case kExact:  
303       AppendToQuery(query, Form("fRunNo == %lu", runNo)); 
304       break;
305     case kNewest: 
306       break;
307     case kNear:   
308       AppendToQuery(query, Form("abs(fRunNo-%lu)<=%d",
309                                 runNo,kMaxNearDistance)); 
310       break;
311     case kOlder: 
312       AppendToQuery(query, Form("fRunNo <= %lu", runNo));
313       break;
314     case kNewer: 
315       AppendToQuery(query, Form("fRunNo >= %lu", runNo));
316       break;
317     case kDefault: 
318       Fatal("Query", "Mode should never be 'default'");
319       break;
320     }
321   }
322       
323   if (query.IsNull()) {
324     Warning("Query", "Empty query!");
325     return -1;
326   }
327
328   if (fVerbose) 
329     Printf("%s: Query is '%s'", GetName(), query.Data());
330   fTree->Draw("Entry$:fRunNo:fTimestamp", query, "goff");
331   Int_t nRows = fTree->GetSelectedRows();
332   if (nRows <= 0) return -1;
333       
334   if (fVerbose) 
335     Printf("Query: %s (%s)\n"
336            " Entry  |    Run    | Timestamp \n"
337            "--------+-----------+------------------------", 
338            query.Data(), smode);
339       
340   ULong_t  oldRun  = (mode == kNewer ? 0xFFFFFFFF : 0);
341   ULong_t  oldTim  = 0;
342   ULong_t  oldDist = 0xFFFFFFFF;
343   Int_t    entry  = -1;
344   for (Int_t row = 0; row < nRows; row++) {
345     Int_t    ent  = fTree->GetV1()[row];
346     ULong_t  run  = fTree->GetV2()[row];
347     ULong_t  tim  = fTree->GetV3()[row];
348     ULong_t  dist = (run > runNo ? run - runNo : runNo - run);
349         
350     if (fVerbose) {
351       TDatime t(tim);
352       Printf(" %6d | %9ld | %19s ", ent, run > 0x7FFFFFFF ? -1 : run, 
353              t.AsSQLString());
354     }
355
356     switch (mode) { 
357     case kExact: break; // Done in the draw `query' 
358     case kNewest: // Fall-through 
359     case kOlder: 
360       if (run < oldRun) continue;
361       break;
362     case kNewer: 
363       if (run > oldRun) continue;
364       break;
365     case kNear: 
366       if (runNo > 0 && dist > oldDist) continue;
367       break;
368     case kDefault:
369       break;
370     }
371     // If we get here, then we have the best run according to the 
372     // criteria 
373             
374     // Finally, check the timestamp 
375     if (tim < oldTim) continue;
376         
377     // Now update last values and set current best entry 
378     oldTim  = tim;
379     oldDist = dist;
380     oldRun  = run;
381     entry   = ent;
382   }
383
384   if (fVerbose) {
385     Printf("Returning entry # %d", entry);
386   }
387   return entry;
388 }
389
390 //____________________________________________________________________
391 Bool_t
392 AliOADBForward::Table::Insert(TObject* o, 
393                               ULong_t  runNo, 
394                               UShort_t sys, 
395                               UShort_t sNN, 
396                               Short_t  field, 
397                               Bool_t   mc, 
398                               Bool_t   sat,
399                               ULong_t  aliRev,
400                               const TString& author) 
401 {
402   // 
403   // Insert a new row in the table 
404   //
405
406   // Check if the file is read/write 
407   if (fVerbose) 
408     Info("Insert", "Inserting object %p for run=%lu, sys=%hu, sNN=%4hu, "
409          "field=%+2hd, mc=%d, sat=%d", o,runNo, sys, sNN, field, mc, sat);
410
411   if (!IsOpen(true)) {
412     Warning("Insert", "No tree, or not write-able");
413     return false;
414   }
415       
416   // If the entry doesn't exists 
417   if (!fEntry) fEntry = new Entry;
418
419   // Make author 
420   TString auth(author);
421   if (auth.IsNull()) { 
422     UserGroup_t* u = gSystem->GetUserInfo();
423     TInetAddress i = gSystem->GetHostByName(gSystem->HostName());
424     auth = TString::Format("%s <%s@%s>", u->fRealName.Data(), 
425                            u->fUser.Data(), i.GetHostName());
426   }
427     
428   // Set fields 
429   fEntry->fData            = o;
430   fEntry->fRunNo           = runNo; // (runNo <= 0 ? 0xFFFFFFFF : runNo);
431   fEntry->fSys             = sys;
432   fEntry->fSNN             = sNN;
433   fEntry->fField           = field;
434   fEntry->fMC              = mc;
435   fEntry->fSatellite       = sat;
436   fEntry->fAliROOTRevision = (aliRev != 0 ? aliRev : ALIROOT_SVN_REVISION);
437   fEntry->fAuthor          = auth;
438
439   TDatime now;
440   fEntry->fTimestamp       = now.Convert(true);
441
442   // Fill into tree 
443   Int_t nBytes = fTree->Fill();
444   if (nBytes <= 0) {
445     Warning("Insert", "Failed to insert new entry");
446     return false;
447   }
448     
449   // do an Auto-save and flush-baskets now 
450   fTree->AutoSave("FlushBaskets SaveSelf");
451
452   return true;
453 }
454
455 //____________________________________________________________________
456 AliOADBForward::Entry*
457 AliOADBForward::Table::Get(ULong_t        run,
458                            ERunSelectMode mode,
459                            UShort_t       sys,
460                            UShort_t       sNN, 
461                            Short_t        fld,
462                            Bool_t         mc,
463                            Bool_t         sat) const
464 {
465   // Query the tree for an object.  The strategy is as follows. 
466   // 
467   //  - First query with all fields 
468   //    - If this returns a single entry, return that. 
469   //    - If not, then ignore the run number (if given)
470   //      - If this returns a single entry, return that 
471   //      - Otherwise, give up and return null
472   //
473   // This allow us to specify default objects for a period, and for
474   // collision system, energy, and field setting.
475   //
476   if (fVerbose)
477     Printf("run=%lu mode=%s sys=%hu sNN=%hu fld=%hd mc=%d sat=%d",
478            run, Mode2String(mode), sys, sNN, fld, mc, sat);
479   Int_t entry = Query(run, mode, sys, sNN, fld, mc, sat);
480   if (entry < 0 && run > 0) 
481     entry = Query(0, mode, sys, sNN, fld, mc, sat);
482   if (entry < 0) {
483     Warning("Get", "No valid object could be found");
484     return 0;
485   }
486   
487   Int_t nBytes = fTree->GetEntry(entry);
488   if (nBytes <= 0) { 
489     Warning("Get", "Failed to get entry # %d\n", entry);
490     return 0;
491   }
492   if (fVerbose) fEntry->Print();
493   return fEntry;
494 }
495 //____________________________________________________________________
496 TObject*
497 AliOADBForward::Table::GetData(ULong_t        run,
498                                ERunSelectMode mode,
499                                UShort_t       sys,
500                                UShort_t       sNN, 
501                                Short_t        fld,
502                                Bool_t         mc,
503                                Bool_t         sat) const
504 {
505   // 
506   // Get data associated with a row or null. 
507   // See also AliOADBForward::Get
508   // 
509   Entry* e = Get(run, mode, sys, sNN, fld, mc, sat);
510   if (!e) return 0;
511   return e->fData;
512 }
513 //____________________________________________________________________
514 void
515 AliOADBForward::Table::Print(Option_t* option) const
516 {
517   // 
518   // Print the full table 
519   //
520   if (!IsOpen()) return;
521
522   Printf("Table %s (default mode: %s)", GetName(), Mode2String(fMode));
523   Int_t n = fTree->GetEntries();
524   for (Int_t i = 0; i < n; i++) { 
525     fTree->GetEntry(i);
526     printf("%4d/%4d: ", i, n);
527     fEntry->Print(option);
528   }
529 }
530 //____________________________________________________________________
531 void
532 AliOADBForward::Table::Browse(TBrowser* b) 
533 {
534   // Browse this table 
535   if (fTree) b->Add(fTree);
536 }
537 //____________________________________________________________________
538 Bool_t
539 AliOADBForward::Table::IsOpen(Bool_t rw) const 
540
541   if (!fTree) return false;
542   if (!rw)    return true;
543   
544   return fTree->GetCurrentFile()->IsWritable();
545 }
546 //====================================================================
547 AliOADBForward::AliOADBForward() 
548   : TObject(),
549     fTables()
550 {
551   //
552   // Constructor 
553   //
554 }
555 #if 0
556 //____________________________________________________________________
557 AliOADBForward::AliOADBForward(const AliOADBForward& other)
558   : TObject(other), 
559     fTables(other.fTables)
560 {
561   // 
562   // Copy constructor 
563   // 
564 }
565 #endif
566 //____________________________________________________________________
567 AliOADBForward::~AliOADBForward()
568 {
569   // 
570   // Destructor 
571   // 
572   Close();
573 }
574 #if 0
575 //____________________________________________________________________
576 AliOADBForward&
577 AliOADBForward::operator=(const AliOADBForward& other)
578 {
579   // 
580   // Copy constructor 
581   // 
582   if (&other == this) return *this;
583
584   fTables = other.fTables;
585
586   return *this;
587 }
588 #endif 
589
590 //____________________________________________________________________
591 Bool_t
592 AliOADBForward::Open(const  TString& fileName, 
593                      const  TString& tables, 
594                      Bool_t          rw, 
595                      Bool_t          verb)
596 {
597   TString  absPath(gSystem->ExpandPathName(fileName));
598   if (absPath.IsNull()) { 
599     Error("Open", "Empty path for tables %s", tables.Data());
600     return false;
601   }
602   TObject* previous = gROOT->GetListOfFiles()->FindObject(absPath);
603   TFile*   file     = 0;
604   if (previous) {
605     file = static_cast<TFile*>(previous);
606   }
607   else { 
608     file = TFile::Open(fileName, (rw ? "UPDATE" : "READ"));
609   }
610   if (!file)  { 
611     Error("Open", "Failed to open %s", GetName());
612     return false;
613   }
614   return Open(file, tables, rw, verb);
615 }
616
617 //____________________________________________________________________
618 Bool_t
619 AliOADBForward::Open(TFile*         file,
620                      const TString& tables,
621                      Bool_t         rw, 
622                      Bool_t         verb) 
623 {
624   // 
625   // Open database file and find or create listed tables 
626   // 
627   if (!file) return false;
628   if (rw && !file->IsWritable()) {
629     Warning("Open", "Read+write access requested, but %s opened read-only",
630             file->GetName());
631     if (file->ReOpen("UPDATE") < 0) { 
632       Error("Open", "Failed to reopen file in read+write access mode");
633       return false;
634     }
635   }
636
637   if (tables.EqualTo("*")) {
638     if (rw) { 
639       Error("Open", "Cannot open with '*' in read/write mode");
640       return false;
641     }
642     TList* l = file->GetListOfKeys();
643     TIter  next(l);
644     TKey*  key = 0;
645     while ((key = static_cast<TKey*>(next()))) { 
646       TClass* cl = gROOT->GetClass(key->GetClassName());
647       if (!cl) continue; 
648       if (!cl->InheritsFrom(TTree::Class())) continue; 
649         
650       Table* t = GetTableFromFile(file, false, key->GetName(), "DEFAULT");
651       if (!t) continue;
652
653       fTables.Add(new TObjString(key->GetName()), t);
654       t->SetVerbose(verb);
655     }
656     // file->Close();
657     return true;
658   }
659   TObjArray*  tokens = tables.Tokenize(":,");
660   TObjString* token  = 0;
661   TIter       nextToken(tokens);
662   while ((token = static_cast<TObjString*>(nextToken()))) {
663     TString& tn = token->String();
664     if (tn.IsNull()) continue;
665      
666     TObjArray*  parts = tn.Tokenize("/");
667     TObjString* onam  = static_cast<TObjString*>(parts->At(0));
668     TString&    name  = onam->String();
669     TString     mode  = "DEFAULT";
670     if (parts->GetEntries() > 1) 
671       mode = static_cast<TObjString*>(parts->At(1))->String();
672     mode.ToUpper();
673     Table* t = GetTableFromFile(file, rw, name, mode);
674     if (!t) continue;
675
676     t->SetVerbose(verb);
677     fTables.Add(onam->Clone(), t);
678
679     delete parts;
680   }
681   delete tokens;
682
683   return true;
684 }
685
686 //____________________________________________________________________
687 Bool_t
688 AliOADBForward::Close()
689 {
690   // 
691   // Flush all tables and close all files 
692   // 
693   TList  files;
694   Int_t nFiles = GetFiles(files);
695   if (nFiles <= 0) { 
696     // Nothing to close 
697     return true;
698   }
699
700   TIter nextFile(&files);
701   TFile* file = 0;
702   while ((file = static_cast<TFile*>(nextFile()))) {
703     // if (file->IsWritable()) file->Write();
704
705     file->Close();
706   }
707     
708   fTables.DeleteAll();
709
710   return true;
711 }
712 //____________________________________________________________________
713 Bool_t
714 AliOADBForward::Update()
715 {
716   // 
717   // Flush all tables 
718   // 
719   TList  files;
720   Int_t nFiles = GetFiles(files);
721   if (nFiles <= 0) { 
722     // Nothing to close 
723     return true;
724   }
725
726   TIter nextFile(&files);
727   TFile* file = 0;
728   Int_t  nBytes = 0;
729   while ((file = static_cast<TFile*>(nextFile()))) {
730     if (!file->IsWritable()) { 
731       Error("Update", "File %s not writeable", file->GetName());
732       continue;
733     }
734
735     nBytes += file->Write();
736   }
737   return (nBytes >= 0);
738 }
739 //____________________________________________________________________
740 AliOADBForward::Entry*
741 AliOADBForward::Get(const TString& table, 
742                     ULong_t        run,
743                     ERunSelectMode mode, 
744                     UShort_t       sys,
745                     UShort_t       sNN, 
746                     Short_t        fld,
747                     Bool_t         mc,
748                     Bool_t         sat) const
749 {
750   // 
751   // Get a row from selected table 
752   // 
753   Table* t = FindTable(table);
754   if (!t) return 0;
755     
756   return t->Get(run, mode, sys, sNN, fld, mc, sat);
757 }
758 //____________________________________________________________________
759 TObject*
760 AliOADBForward::GetData(const TString& table, 
761                         ULong_t        run,
762                         ERunSelectMode mode, 
763                         UShort_t       sys,
764                         UShort_t       sNN, 
765                         Short_t        fld,
766                         Bool_t         mc,
767                         Bool_t         sat) const
768 {
769   Table* t = FindTable(table);
770   if (!t) return 0;
771
772   return t->GetData(run, mode, sys, sNN, fld, mc, sat);
773 }
774 //____________________________________________________________________
775 Bool_t
776 AliOADBForward::Insert(const TString& table, 
777                        TObject* o, 
778                        ULong_t  runNo, 
779                        UShort_t sys, 
780                        UShort_t sNN, 
781                        Short_t  field, 
782                        Bool_t   mc, 
783                        Bool_t   sat,
784                        ULong_t  aliRev,
785                        const TString& author) 
786 {
787   // 
788   // Insert a row into the selected table 
789   //
790   Table* t = FindTable(table);
791   if (!t) return false;
792
793   return t->Insert(o, runNo, sys, sNN, field, mc, sat, aliRev, author);
794 }           
795 //____________________________________________________________________
796 void
797 AliOADBForward::Print(const Option_t* option) const
798 {
799   // 
800   // Print everything 
801   //
802   TIter       nextTable(&fTables);
803   TObjString* key   = 0;
804   Table*      table  = 0;
805   while ((key = static_cast<TObjString*>(nextTable()))) {
806     Printf("Table: %p", key->GetName());
807     table = static_cast<Table*>(fTables.GetValue(key));
808     if (!table) continue;
809     table->Print(option);
810   }
811 }
812
813 //____________________________________________________________________
814 void
815 AliOADBForward::Browse(TBrowser* b) 
816 {
817   // 
818   // Browse this object
819   // 
820   TIter       nextTable(&fTables);
821   TObjString* key   = 0;
822   Table*      table  = 0;
823   while ((key = static_cast<TObjString*>(nextTable()))) {
824     table = static_cast<Table*>(fTables.GetValue(key));
825     if (!table) continue;
826     b->Add(table, key->GetName());
827   }
828 }
829 //____________________________________________________________________
830 AliOADBForward::Table*
831 AliOADBForward::FindTable(const TString& name, Bool_t quite) const
832 {
833   //
834   // Find a table by name 
835   // 
836   TPair* p = static_cast<TPair*>(fTables.FindObject(name));
837   if (!p) {
838     if (!quite)
839       Warning("FindTable", "Table %s not registered", name.Data());
840     return 0; 
841   }
842   return static_cast<Table*>(p->Value());
843 }
844 //____________________________________________________________________
845 Int_t
846 AliOADBForward::GetFiles(TList& files) const
847 {
848   // 
849   // Get all associated files 
850   // 
851   Int_t  ret    = 0;
852   TIter       nextTable(&fTables);
853   TObjString* key   = 0;
854   Table*      table  = 0;
855   while ((key = static_cast<TObjString*>(nextTable()))) {
856     table = static_cast<Table*>(fTables.GetValue(key));
857     if (!table->fTree) continue; 
858
859     TFile* f = table->fTree->GetCurrentFile();
860     if (!f) continue;
861
862     if (files.FindObject(f)) continue;
863     files.Add(f);
864     ret++;
865   }
866   return ret;
867 }
868 //____________________________________________________________________
869 AliOADBForward::Table*
870 AliOADBForward::GetTableFromFile(TFile*         file, 
871                                  Bool_t         rw, 
872                                  const TString& name,
873                                  const TString& mode) const
874 {
875   // 
876   // Get a table from a file, or make a new table 
877   // 
878   if (!file) return 0;
879   if (FindTable(name, true)) return 0;
880
881   TObject* o = file->Get(name);
882   TTree*   t = 0;
883   Bool_t   n = false;
884   if (!o) { 
885     if (!rw) { 
886       // We only fail if in read-only mode 
887       Error("Open", "No such object: %s in %s", name.Data(),
888             file->GetName());
889       return 0;
890     }
891     // Create the tree in the file 
892     t = new TTree(name, mode);
893     t->SetDirectory(file);
894     n = true;
895   }
896   else {
897     // Get the tree, and set the branch
898     t = static_cast<TTree*>(o);
899   }
900   Table* ret = new Table(t, n, String2Mode(mode));
901   return ret;
902 }
903 //____________________________________________________________________
904 void
905 AliOADBForward::AppendToQuery(TString& q, const TString& s, Bool_t andNotOr)
906 {
907   // 
908   // Helper function 
909   // 
910   if (!q.IsNull()) q.Append(andNotOr ? " && " : " || ");
911   q.Append(s);
912 }
913 //____________________________________________________________________
914 TString
915 AliOADBForward::Conditions(UShort_t       sys,
916                            UShort_t       sNN, 
917                            Short_t        fld,
918                            Bool_t         mc,
919                            Bool_t         sat)
920 {
921   // Build query string 
922   TString q;
923   if (sys   > 0)    AppendToQuery(q, Form("fSys == %hu",          sys));
924   if (sNN   > 0)    AppendToQuery(q, Form("abs(fSNN - %hu) < 11", sNN));
925   if (TMath::Abs(fld) < 10) AppendToQuery(q, Form("fField == %hd",fld));
926   // Boolean fields always queried.  In cases where these do not matter, 
927   // we always write down the false value, so we get the correct query 
928   // anyways. 
929   AppendToQuery(q, Form("%sfMC",        (mc  ? " " : "!")));
930   AppendToQuery(q, Form("%sfSatellite", (sat ? " " : "!")));
931
932   return q;
933 }
934
935 //____________________________________________________________________
936 void
937 AliOADBForward::TestGet(AliOADBForward& t, 
938                         const TString& table,
939                         ULong_t        runNo,
940                         ERunSelectMode mode,
941                         UShort_t       sys,
942                         UShort_t       sNN, 
943                         Short_t        fld,
944                         Bool_t         mc,
945                         Bool_t         sat)
946 {
947
948   Printf("=== Test query: t=%s r=%ld s=%d t=%d f=%d m=%d v=%d",
949          table.Data(), runNo, sys, sNN, fld, int(mc), int(sat));
950   AliOADBForward::Entry* e = t.Get(table, runNo, mode, sys, sNN, 
951                                    fld, mc, sat);
952   if (!e) return;
953   e->Print();
954 }
955 //____________________________________________________________________
956 void
957 AliOADBForward::TestInsert(AliOADBForward& t, 
958                            const TString&  table,
959                            ULong_t         runNo,
960                            UShort_t        sys,
961                            UShort_t        sNN, 
962                            Short_t         fld,
963                            Bool_t          mc,
964                            Bool_t          sat)
965 {
966   static Int_t cnt = 0;
967   TString what = TString::Format("%s-%03d", table.Data(), cnt++);
968   Printf("=== Insert: t=%s r=%ld s=%d t=%d f=%d m=%d v=%d w=%s",
969          table.Data(), runNo, sys, sNN, fld, int(mc), int(sat), what.Data());
970   t.Insert(table, new TObjString(what), runNo, sys, sNN, fld, mc, sat);
971   gSystem->Sleep(500);
972 }
973
974 //____________________________________________________________________
975 void
976 AliOADBForward::Test()
977 {
978   AliOADBForward* tt = new AliOADBForward();
979   if (!tt->Open("db.root", "A,B", true, true)) { 
980     ::Error("Test", "Failed to open DB");
981     return;
982   }
983   AliOADBForward& t  = *tt;
984   TestInsert(t, "A", 137161);
985   TestInsert(t, "A", 137161);
986   TestInsert(t, "A", 0     );
987   TestInsert(t, "A", 999999);
988   TestInsert(t, "A", 137166);
989
990
991   TestInsert(t, "B", 137161);
992   TestInsert(t, "B", 0     );
993   t.Print();
994   t.Close();
995
996   if (!t.Open("db.root", "A,B",false,true)) {
997     ::Error("Test", "Failed to open DB");
998     return;
999   }
1000
1001   TestGet(t, "A", 137161);
1002   TestGet(t, "A", 137160);
1003   TestGet(t, "A", 0     );
1004   TestGet(t, "A", 137160, kNewest);
1005   TestGet(t, "A", 137160, kNewer);
1006   TestGet(t, "A", 137168, kOlder);
1007   TestGet(t, "A", 137161, kExact);
1008
1009   new TBrowser("b", tt);
1010 }
1011
1012 //
1013 // EOF
1014 //