]>
Commit | Line | Data |
---|---|---|
8449e3e0 | 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 | // |