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