StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
St_db_Maker.cxx
1 
11 // Most of the history moved at the bottom
12 //
13 // $Id: St_db_Maker.cxx,v 1.144 2020/01/15 02:07:47 perev Exp $
14 // $Log: St_db_Maker.cxx,v $
15 // Revision 1.144 2020/01/15 02:07:47 perev
16 // Cleanup
17 //
18 // Revision 1.143 2019/03/21 19:00:37 jeromel
19 // Added ATTENTION message
20 //
21 // Revision 1.142 2019/01/16 23:38:29 perev
22 // Fix wrong order in if (Jason)
23 //
24 // Revision 1.141 2018/01/17 17:15:59 perev
25 // Enhanced test to skip wrong file name corrected
26 //
27 // Revision 1.139 2018/01/16 19:50:44 perev
28 // Test to skip wrong file name is enhanced
29 //
30 // Revision 1.138 2017/04/26 20:20:24 perev
31 // Hide m_DataSet
32 //
33 // Revision 1.137 2015/05/19 20:34:47 perev
34 // Remove old commented coded
35 //
36 // Revision 1.136 2015/05/16 02:34:05 perev
37 // bug #3101 Cleanup
38 //
39 // Revision 1.135 2015/05/05 21:05:52 dmitry
40 // Updated db disconnect handling. Keep connection if less than 30 sec passed since last data retrieval
41 //
42 // Revision 1.134 2015/05/05 20:42:14 dmitry
43 // dynamic db disconnects handling
44 //
45 // Revision 1.133 2014/07/28 14:19:36 dmitry
46 // fixed templated call to make it compliant with gcc 4.8.2
47 //
48 // Revision 1.132 2013/07/18 14:00:32 fisyak
49 // expand no. of possible databases from 4 to 10
50 //
51 // Revision 1.131 2012/05/04 19:42:34 perev
52 // Ignore wrong timing for RunLog tables
53 //
54 // Revision 1.130 2012/04/19 16:20:38 perev
55 // Add test for unrecognized file
56 //
57 // Revision 1.129 2012/03/20 23:44:00 perev
58 // FullFileName() bug #2303 fix
59 //
60 // Revision 1.128 2012/03/16 19:36:18 dmitry
61 // converted dangled char pointers to std::string objects + fixed typo
62 //
63 // Revision 1.127 2012/01/24 02:55:43 perev
64 // Errors check added
65 //
66 // Revision 1.126 2011/11/28 23:23:35 dmitry
67 // case conversion update for overrides
68 //
69 // Revision 1.125 2011/11/28 17:03:09 dmitry
70 // dbv override support in StDbLib,StDbBroker,St_db_Maker
71 //
72 // Revision 1.124 2011/03/19 02:48:07 perev
73 // blacklist added
74 //
75 // Revision 1.122 2010/05/05 20:44:15 dmitry
76 // Fixed check for db broker in file mode
77 //
78 // Revision 1.121 2010/05/05 18:35:03 dmitry
79 // addon: single datasets also saved
80 //
81 // Revision 1.120 2010/05/05 15:25:51 dmitry
82 // refactored snapshot code, to include Valeri's patch (save .root files)
83 //
84 // Revision 1.119 2010/04/28 07:23:40 dmitry
85 // =new method to save snapshot+one subsequent dataset for each table in db
86 //
87 // Revision 1.118 2010/04/21 19:04:31 perev
88 // Save changed to account changed internal structure
89 //
90 // Revision 1.117 2010/04/17 02:08:33 perev
91 // ::SetDateTime set time also StMaker::SetDateTime
92 //
93 // Revision 1.116 2010/01/27 21:34:20 perev
94 // GetValidity now is static
95 //
96 // Revision 1.115 2009/11/16 20:16:23 fine
97 // Make the TDatime const interfaces
98 //
99 // Revision 1.114 2008/04/02 20:22:32 perev
100 // WarnOff
101 //
102 // Revision 1.113 2008/01/20 00:39:40 perev
103 // improve dbStat print
104 //
105 // Revision 1.112 2008/01/09 20:44:46 perev
106 // Improve printout in Finish()
107 //
108 // Revision 1.111 2007/12/29 01:43:32 perev
109 // More dbStat
110 //
111 // Revision 1.110 2007/09/10 02:19:25 perev
112 // StDbBroker::Release used
113 //
114 // Revision 1.109 2007/07/02 19:36:39 fisyak
115 // Add parameter currenTime (== requested time) in FindLeft
116 //
117 // Revision 1.108 2007/05/15 18:45:11 perev
118 // Add StMaker::Init() into Init
119 //
120 // Revision 1.107 2007/04/26 04:17:45 perev
121 // Correct printout
122 //
123 // Revision 1.106 2007/04/17 01:37:05 perev
124 // assert improved
125 //
126 // Revision 1.105 2007/04/16 00:20:23 perev
127 // Feature in TTable workaround
128 //
129 // Revision 1.104 2007/04/15 20:57:42 fisyak
130 // By pass bug in TTable::New
131 //
132 // Revision 1.103 2007/03/22 04:27:47 perev
133 // BugFix for user time
134 //
135 // Revision 1.102 2007/03/09 20:01:03 perev
136 // Request by user defined time now allowed
137 //
138 // Revision 1.101 2007/02/15 18:39:40 perev
139 // dbSnapshot fixes
140 //
141 // Revision 1.100 2006/11/23 01:55:44 perev
142 // Non init variable fixed. Thanks Yuri
143 //
144 // Revision 1.99 2006/08/15 21:42:20 jeromel
145 // Fix rhic -> rhic.bnl.gov
146 //
147 // Revision 1.98 2006/05/31 03:55:52 fisyak
148 // Set default fMaxEntryTime='now'
149 //
150 // Revision 1.97 2006/02/06 20:07:48 perev
151 // Decrease level of aliases 2==>1 to avoid name clashes
152 //
153 // Revision 1.96 2005/12/31 01:32:10 perev
154 // test for memory curruption added
155 //
156 // Revision 1.95 2005/10/06 18:46:30 fisyak
157 // Add protection for validity date < 19950101
158 //
159 // Revision 1.94 2005/08/29 21:44:20 fisyak
160 // switch from fBits to fStatus for StMaker control bits; account replacing of UInt_t by Int_t for m_runNumber
161 //
162 // Revision 1.93 2005/08/08 18:00:37 perev
163 // Move test of crazy date in SetFlavor to the end
164 //
165 // Revision 1.92 2005/08/05 23:44:33 perev
166 // Test for unseted time in SetFlavor added
167 //
168 // Revision 1.91 2005/07/26 16:48:13 perev
169 // SetFlavor/fDbBroker bug fixed
170 //
171 // Revision 1.90 2005/07/25 03:01:58 perev
172 // SetFlavor was not called if (fDbBroker==0)
173 //
174 // Revision 1.89 2005/07/20 17:41:34 perev
175 // Cleanup
176 //
177 // Revision 1.88 2005/05/13 19:39:11 perev
178 // Zero validity test added
179 //
180 // Revision 1.87 2005/04/01 21:38:31 perev
181 // call Make after SetFlavor
182 //
183 // Revision 1.86 2004/09/16 02:05:18 perev
184 // Add option to use saved dbConfig file. speedup
185 //
186 // Revision 1.85 2004/08/18 20:33:56 perev
187 // Timers added for MySQL and maker itself
188 //
189 // Revision 1.84 2004/07/22 20:47:40 perev
190 // Cleanup. 0 nrows for no table found
191 //
192 // Revision 1.83 2004/04/29 02:03:37 jeromel
193 // y2004a addded
194 //
195 // Revision 1.82 2004/04/14 22:55:56 jeromel
196 // Bundle changes for chain adjustements
197 //
198 // Revision 1.81 2004/04/08 00:28:53 perev
199 // AliasDate & AliasTime now static methods
200 //
201 // Revision 1.80 2004/04/08 00:13:09 perev
202 // Again move from .data to .const
203 //
204 // Revision 1.79 2004/04/07 18:17:45 perev
205 // Cleanup, DB data now in .const as should be
206 //
207 // Revision 1.78 2004/03/16 04:00:16 jeromel
208 // Improper number of elements times[] array fixed
209 //
210 // Revision 1.77 2004/01/06 23:58:01 perev
211 // (JL) More printing ...
212 //
213 // Revision 1.76 2004/01/06 16:44:42 jeromel
214 // Logic error not(()&&())
215 //
216 // Revision 1.75 2003/11/13 02:55:39 perev
217 // Safe destructor of TDataSet like object used
218 //
219 // Revision 1.74 2003/11/09 20:58:33 jeromel
220 // new timestamps
221 //
222 // Revision 1.73 2003/11/07 17:33:19 perev
223 // Add more clear message if no timestamp
224 //
225 // Revision 1.72 2003/10/06 04:05:33 perev
226 // deletes to be pleasant to Insure
227 //
228 // Revision 1.71 2003/10/01 21:51:31 jeromel
229 // Adjust as well
230 //
231 // Revision 1.70 2003/09/28 21:11:30 jeromel
232 // Unsued variable ldsname removed
233 //
234 // Revision 1.69 2003/09/23 01:04:55 jeromel
235 // READ_BAD_INDEX fixed
236 //
237 // Revision 1.68 2003/09/13 00:42:32 perev
238 // XDF obsolete + small fixes
239 //
240 // Revision 1.67 2003/09/02 17:59:25 perev
241 // gcc 3.2 updates + WarnOff
242 //
243 // Revision 1.66 2003/08/21 16:11:08 jeromel
244 // Labelling consistency correction
245 //
246 // Revision 1.65 2003/07/16 19:58:34 perev
247 // Cleanup of StTriggerData2003 at all
248 //
249 // Revision 1.64 2003/07/03 18:25:51 jeromel
250 // y2003x = 20021115 as for year2003
251 //
252 // Revision 1.63 2002/12/20 03:28:37 perev
253 // Save method improved
254 //
255 // Revision 1.62 2002/12/16 17:29:56 jeromel
256 // Fixed timestamp (final)
257 //
258 // Revision 1.61 2002/11/27 03:12:26 jeromel
259 // Expand array for a new geometry time stamp. Beware, timestamp not fixed yet
260 // (had to revert to the preceeding one as the new timeline does not exists but
261 // any stamp ended with garbage).Next commit will make it right ...
262 //
263 
264 // Example + explanation of DB maker statistics
265 //==============================================================================
266 // St_db_Maker::Init //Init without MySQL
267 // Real time 0:00:00, CP time 0.330, 3 slices
268 //
269 // MySQL::Init // It is clear
270 // Real time 0:00:10, CP time 1.110, 2 slices
271 //
272 // St_db_Maker::Make // All work without MySql
273 // Real time 0:00:03, CP time 3.200, 3177 slices
274 // MySQL::Make // MySql work
275 // Real time 0:01:10, CP time 6.440, 3104 slices
276 // MySQL::Data // Part of MySQL::Make with data transfer
277 // Real time 0:01:10, CP time 6.420, 252 slices
278 //
279 // St_db_Maker:INFO - St_db_Maker::dbStat : Evts = 3 dbEvts=1 Evts/dbEvts = 3.0
280 // // Evts =number of events, dbEvts = number of DB calls
281 //
282 // St_db_Maker:INFO - St_db_Maker::dbStat : dbData = 91.1 dbTime=25.3689 dbData/dbTime=3.59187
283 // // dbData = megabytes read from DB
284 //
285 // St_db_Maker:INFO - St_db_Maker::dbStat : dbTime = 25.4 dbEvts=1 dbTime/dbEvts =25.3689
286 //
287 // St_db_Maker:INFO - St_db_Maker::dbStat : dbCpu = 6.4 dbEvts=1 dbCpu/dbEvts =6.42
288 //
289 // St_db_Maker:INFO - St_db_Maker::dbStat : dbTime/tot = 60.81% dbCpu/tot= 15.39%
290 // // dbTime/tot = percent(%) of total time spent in DB
291 // // dbCpu/tot = percent(%) of total CPU spent in DB
292 //==============================================================================
293 
294 
295 
296 #define MYSQLON 1999
297 
298 #include <Stiostream.h>
299 #include "Stiostream.h"
300 #include <stdlib.h>
301 #include <string.h>
302 #include <time.h>
303 #include "TError.h"
304 #include "TBrowser.h"
305 #include "TDatime.h"
306 #include "TRegexp.h"
307 #include "TInterpreter.h"
308 #include "TFile.h"
309 #include "TSystem.h"
310 #include "St_db_Maker.h"
311 #include "TDataSetIter.h"
312 #include "TFileSet.h"
313 //VP#include "St_XDFFile.h"
314 #include "StTree.h"
315 #include "TTableDescriptor.h"
316 #include "TTable.h"
317 #include "TUnixTime.h"
318 #include "StDbBroker/StDbBroker.h"
319 #include "TAttr.h"
320 #include "StValiSet.h"
321 
322 #include <numeric>
323 
324 enum eKIND { kXDFkind = 1, kCkind=2, kROOTkind = 3};
325 enum eDBMAKER { kUNIXOBJ = 0x2000};
326 
328 //
329 // Class St_dbConfig wraps the STAF table dbConfig
330 // It has been generated by automatic. Please don't change it "by hand"
331 //
333 //_____________________________________________________________________________
334 TString FullFileName(const TDataSet* ds)
335 {
336  TString dbfile(ds->GetTitle()+5);
337  TString dbDir(gSystem->BaseName(dbfile.Data()));
338  dbDir.Append("/");
339  TString full(ds->Path());
340 //
341  do { //Remove redundant like "*/StarDb/"
342  int idx = full.Index(dbDir);if (idx<0) break;
343  full.Remove(0,idx+dbDir.Length()-1);
344  } while(1);
345 
346  TString name(ds->GetName());
347  int idx = name.Index("."); if (idx>=0) name.Remove(idx,999);
348  name.Insert(0,"/.");
349  full.ReplaceAll(name,"");
350  full.Insert(0,dbfile);
351  gSystem->ExpandPathName(full);
352  return full;
353 }
354 
355 TableClassImpl(St_dbConfig,dbConfig_st)
356 //__________________________ class St_db_Maker ____________________________
357 //__________________________ class St_db_Maker ____________________________
358 ClassImp(St_db_Maker)
359 //_____________________________________________________________________________
360 St_db_Maker::St_db_Maker(const char *name
361  , const char *dir0
362  , const char *dir1
363  , const char *dir2
364  , const char *dir3
365  , const char *dir4
366  , const char *dir5
367  , const char *dir6
368  , const char *dir7
369  , const char *dir8
370  , const char *dir9
371 )
372 :StMaker(name)
373 {
374  for (int i=0;i<5;i++) {fTimer[i].Stop();}
375  fTimer[5].Start(0);
376 
377  memset(fEvents,0,sizeof(fEvents)+sizeof(fDataSize));
378 
379  fDirs[0] = dir0;
380  fDirs[1] = dir1;
381  fDirs[2] = dir2;
382  fDirs[3] = dir3;
383  fDirs[4] = dir4;
384  fDirs[5] = dir5;
385  fDirs[6] = dir6;
386  fDirs[7] = dir7;
387  fDirs[8] = dir8;
388  fDirs[9] = dir9;
389 
390  fDBBroker = 0;
391 
392  fHierarchy = 0;
393  fIsDBTime = 0;
394 
395  fDataBase = 0;
396  fUpdateMode = 0;
397  TUnixTime ut;
398  fQueryTs = time(NULL);
399  fMaxEntryTime = ut.GetUTime();
400 }
401 //_____________________________________________________________________________
402 St_db_Maker::~St_db_Maker()
403 {
404 delete fDBBroker; fDBBroker =0;
405  fDataBase =0;
406 delete fHierarchy;fHierarchy=0;
407 }
408 //_____________________________________________________________________________
409 Int_t St_db_Maker::InitRun(int runumber)
410 {
411  if (!fDBBroker || !runumber) return 0;
412  fTimer[3].Start(0);
413  fDBBroker->SetRunNumber(runumber);
414  fTimer[3].Stop();
415  return 0;
416 }
417 //_____________________________________________________________________________
418 Int_t St_db_Maker::Init()
419 {
420  TDataSet *fileset;
421  TString dir;
422  fTimer[0].Start(0);
423  SetBIT(kInitBeg);
424  fDataBase=0;
425  Snapshot(0);
426  int snap = fDataBase!=0;
427  for (int idir=0;!snap && idir < 10 && !fDirs[idir].IsNull(); idir++) {//loop over dirs
428 
429  dir = fDirs[idir];
430  gSystem->ExpandPathName(dir);
431  if (strncmp("MySQL:", (const char*)dir,6)==0){
432  fileset = OpenMySQL(((const char*)dir)+6);
433  if (!fileset) return kStErr;
434  fileset->Pass(PrepareDB,0);
435  } else {
436 
437 // recreate a memory resided data-structure
438  fileset = new TFileSet(dir,gSystem->BaseName(dir));
439  if (!fileset->First()) {delete fileset; fileset = 0; continue;}
440  fileset->Purge();
441  fileset->Sort();
442  fileset->Pass(PrepareDB,&dir);
443  fileset->Purge();
444  }
445  if (fDataBase) {
446  assert(strcmp(fDataBase->GetName(),fileset->GetName())==0);
447  fDataBase->Update(fileset); delete fileset;
448  } else {fDataBase = fileset; }
449  }
450 
451  if (fDataBase) {
452  AddConst(fDataBase);
453  SetOutputAll(fDataBase,1); // Only 1 level of aliases
454 
455  if (Debug()>1) fDataBase->ls("*");
456  }
457  OnOff();
458  SetFlavor(0,0); // Apply all collected before flavors
459  ResetBIT(kInitBeg); SetBIT(kInitEnd);
460  fTimer[0].Stop ();
461  return StMaker::Init();
462 }
463 //_____________________________________________________________________________
465 {
466  Snapshot(1);
467  for (int i=0;i<6;i++) fTimer[i].Stop();
468  Printf("St_db_Maker::Init ");fTimer[0].Print();
469  Printf(" MySQL::Init ");fTimer[2].Print();
470  Printf("St_db_Maker::Make ");fTimer[1].Print();
471  Printf(" MySQL::Make ");fTimer[3].Print();
472  Printf(" MySQL::Data ");fTimer[4].Print();
473 
474  if (fEvents[1]<=0) return 0;
475  double estiTime = fTimer[4].RealTime()*fTimer[5].CpuTime()/fTimer[5].RealTime();
476  double eachEvt = double(fEvents[0]) /(fEvents[1]+3e-33);
477  double MperTim = (fDataSize[1]*1e-6)/(estiTime+3e-33);
478  double timPerE = estiTime/(fEvents[1]+3e-33);
479  double cpuPerE = fTimer[4].CpuTime() /(fEvents[1]+3e-33);
480  double timPct = fTimer[4].RealTime()/fTimer[5].RealTime() *100;
481  double cpuPct = fTimer[4].CpuTime() /fTimer[5].CpuTime() *100;
482 
483  Info("dbStat","Evts = %d dbEvts=%d Evts/dbEvts = %4.1f\n"
484  ,fEvents[0], fEvents[1],eachEvt);
485 
486  Info("dbStat","dbData =%10.1f dbTime=%g dbData/dbTime=%g\n"
487  ,fDataSize[1]*1e-6,estiTime,MperTim);
488 
489  Info("dbStat","dbTime =%10.1f dbEvts=%d dbTime/dbEvts =%g\n"
490  ,estiTime,fEvents[1],timPerE);
491 
492  Info("dbStat","dbCpu =%10.1f dbEvts=%d dbCpu/dbEvts =%g\n"
493  ,fTimer[4].CpuTime() ,fEvents[1],cpuPerE);
494 
495  Info("dbStat","dbTime/tot =%10.2f dbCpu/tot=%10.2f \n"
496  ,timPct,cpuPct);
497 
498  return 0;
499 }
500 
501 
502 //_____________________________________________________________________________
504 {
505 
506  fTimer[1].Start(0);
507  TDatime td = GetDateTime();
508  if (td.GetDate() >= 20330101) {
509  Error("Make", "TimeStamp not set. Can not make request to DB");
510  return kStFatal;
511  }
512  fUpdateMode = 1;
513  UpdateDB(fDataBase);
514  fUpdateMode = 0;
515  fTimer[1].Stop();
516  return kStOK;
517 }
518 //_____________________________________________________________________________
519 void St_db_Maker::Clear(const char *)
520 {
521  if (!fDBBroker) return;
522  fEvents[0]++;
523  if (fDataSize[0]) fEvents[1]++;
524  fDataSize[1]+=fDataSize[0];
525  fDataSize[0]=0;
526 
527  time_t now = time(NULL);
528  if ( ( now - fQueryTs ) < 30 ) { return; } // do not call dbbroker->release if less than 30 sec from last query
529 
530  fDBBroker->Release();
531 }
532 //_____________________________________________________________________________
533 TDatime St_db_Maker::Time(const char *filename)
534 {
535  int lfilename,lname,idate,itime;
536 
537  TDatime time; time.Set(kMaxTime,0);//time is defined as a far future to ignore wrong file
538  TString tfilename(filename);
539  tfilename.ReplaceAll(".C","");
540  tfilename.ReplaceAll(".root","");
541 
542  lfilename = tfilename.Length();
543  lname = strcspn(tfilename.Data(),".");
544  if (lfilename== lname) { //simple case xxx.C
545  time.Set(kMinTime,0);
546  return time;
547  }
548  idate = AliasDate(tfilename.Data()+lname+1);
549  itime = AliasTime(tfilename.Data()+lname+1);
550 
551  if (idate) {
552  time.Set(idate,itime);return time;
553  }
554 
555  if (lname+16 <= lfilename &&
556  tfilename[lname+0 ]=='.' &&
557  tfilename[lname+9 ]=='.' ) {// file name format: <name>.YYYYMMDD.hhmmss.<ext>
558  idate = atoi(tfilename.Data()+lname+ 1);
559  itime = atoi(tfilename.Data()+lname+10);
560  } else { // file name is wrong
561  ::Error("St_db_Maker::Time", "Unrecognised File name %s IGNORED",filename);
562  return time;
563  }
564  time.Set(idate,itime); return time;
565 
566 }
567 
568 int St_db_Maker::Kind(const char *filename)
569 {
570  int lfilename;
571 
572  lfilename = strlen(filename);
573  if (!strcmp(filename+lfilename-4,".xdf" )) return kXDFkind;
574  if (!strcmp(filename+lfilename-2,".C" )) return kCkind;
575  if (!strcmp(filename+lfilename-2,".c" )) return kCkind;
576  if (!strcmp(filename+lfilename-5,".root")) return kROOTkind;
577  return 0;
578 }
579 //_____________________________________________________________________________
580 TDataSet *St_db_Maker::OpenMySQL(const char *dbname)
581 {
582  int nrows,irow,jrow;
583  dbConfig_st *thy,*ihy,*jhy;
584  TDataSet *top,*node,*ds;
585 
586  fTimer[0].Stop(); fTimer[2].Start(0);
587  fDBBroker = new StDbBroker();
588  if (Debug() > 1) fDBBroker->setVerbose(1);
589  if (fMaxEntryTime) {
590  fDBBroker->SetProdTime(fMaxEntryTime);
591  for (std::map<std::pair<std::string,std::string>,UInt_t>::iterator it = fMaxEntryTimeOverride.begin(); it != fMaxEntryTimeOverride.end(); it++ ) {
592  fDBBroker->AddProdTimeOverride((*it).second, (char*)((*it).first.first).c_str(), (char*)((*it).first.second).c_str());
593  }
594  }
595  const TAttr *attl = GetAttr();
596  if (attl) {
597  TIter next(attl);
598  TObject *obj;
599  while ((obj = next())) {
600  if (strcmp("blacklist",obj->GetName())!=0) continue;
601  fDBBroker->addBlacklistedDomain(obj->GetTitle());
602  Info("OpenMySQL","Block domain %s",obj->GetTitle());
603  }
604  }
605  TString ts(dbname); ts+="_hierarchy";
606  fHierarchy = new St_dbConfig((char*)ts.Data());
607  thy = fDBBroker->InitConfig(dbname,nrows);
608  fTimer[0].Start(0); fTimer[2].Stop();
609  if (!thy || !nrows){
610  Warning("OpenMySQL","***Can not open MySQL DB %s ***",dbname);
611  return 0;}
612 
613  fHierarchy->Adopt(nrows,thy);
614  if (GetDebug()>1) fHierarchy->Print(0,nrows);
615 
616  top = new TDataSet(thy->parname);
617  top->SetTitle("directory");
618 
619  TDataSet **dss = new TDataSet*[nrows];
620  memset(dss,0,nrows*sizeof(void*));
621 
622  // First pass: directories only
623  for (irow=0,ihy=thy; irow <nrows ; irow++,ihy++)
624  {
625  if (strcmp(ihy->tabtype,".node")==0) {// new node
626  ds = new TDataSet(ihy->tabname);
627  ds->SetTitle("directory");
628  } else { // new table
629  const char *ty = ihy->tabtype;
630  if (ty[0]=='.') ty++;
631  ds = TTable::New(ihy->tabname,ty,0,0);
632  if (!ds) {
633  Warning("OpenMySQL","Unknown table %s/%s.%s",ihy->parname,ihy->tabname,ihy->tabtype); continue;}
634  }
635  if (ds) ds->SetUniqueID(ihy->tabID);
636  dss[irow] = ds;
637  }
638 
639 // Second pass: set relations
640  for (irow=0,ihy=thy; irow <nrows ; irow++,ihy++)
641  {
642  ds = dss[irow]; if (!ds) continue;
643  if (strcmp(ihy->parname,top->GetName())==0) top->Add(ds);
644  if(ds->GetParent()) continue;
645  for (jrow=0,jhy=thy; jrow <nrows ; jrow++,jhy++)
646  {
647  if (jrow==irow) continue;
648  if (ihy->parID != jhy->tabID) continue;
649  if (strcmp(".node" ,jhy->tabtype)) continue;
650  if (strcmp(ihy->parname,jhy->tabname)) continue;
651  node = dss[jrow]; if (!node) continue;
652  node->Add(ds); break;
653  }/*end j for*/
654  if (ds->GetParent()) continue;
655  delete ds; dss[irow]=0;
656  Error("OpenMySQL","WRONG parent %s/%s\n",ihy->parname,ihy->tabname);
657  }/*end i for*/
658 
659 
660  delete [] dss;
661  // top->ls(99);
662  return top;
663 }
664 
665 
666 //_____________________________________________________________________________
667 TDataSet *St_db_Maker::UpdateDB(TDataSet* ds)
668 {
669  if(!ds) return 0;
670  ds->Pass(&UpdateDB,this);
671  return ds;
672 }
673 //_____________________________________________________________________________
674 int St_db_Maker::UpdateTable(UInt_t parId, TTable* dat
675  ,const TDatime &req,TDatime val[2] )
676 {
677 
678  assert(fDBBroker);assert(dat);
679 
680 
681 
682  fDBBroker->SetDateTime(req.GetDate(),req.GetTime());
683  TTableDescriptor *rowTL = ((TTable*)dat)->GetRowDescriptors();
684  fTimer[1].Stop();
685  fTimer[3].Start(0);
686  fTimer[4].Start(0);
687  fDBBroker->SetDictionary(rowTL);
688  fDBBroker->SetTableName (dat->GetName());
689  fDBBroker->SetStructName(dat->GetTitle());
690  fDBBroker->SetStructSize(dat->GetRowSize());
691 
692  // if descriptor filled, no need for newdat
693  void *dbstruct = fDBBroker->Use(dat->GetUniqueID(),parId);
694 // printf("FLAVOR: %s.%s\n",dat->GetName(),fDBBroker->GetFlavor());
695  Int_t d1 = fDBBroker->GetBeginDate();
696  Int_t t1 = fDBBroker->GetBeginTime();
697  if (d1 < 19950101) {
698  Warning("UpdateTable","Table %s.%s Unacceptable Begin Date/Time %d/%d reset to 19950101/000001",
699  dat->GetName(),dat->GetTitle(),d1,t1);
700  d1 = 19950101; t1 = 1;
701  }
702  Int_t d2 = fDBBroker->GetEndDate ();
703  Int_t t2 = fDBBroker->GetEndTime ();
704  if (d2 < 19950101) {
705  Warning("UpdateTable","Table %s.%s Unacceptable End Date/Time %d/%d reset to 19950101/000001",
706  dat->GetName(),dat->GetTitle(),d2,t2);
707  d2 = 19950101; t2 = 1;
708  }
709  val[0].Set(d1,t1);
710  val[1].Set(d2,t2);
711 
712  // small debug statement
713  if ( val[0].Get() >= val[1].Get()) {
714  Error("UpdateTable","val[0].Get() = %u >= val[1].Get() = %u\n",val[0].Get(),val[1].Get());
715  Error("UpdateTable:","Table %s.%s Suspicious Ranges Date/Time %d/%d->%d/%d\n",
716  dat->GetName(),dat->GetTitle(),d1,t1,d2,t2);
717  Error("UpdateTable","Table %s.%s Suspicious Ranges Date/Time %d/%d->%d/%d",
718  dat->GetName(),dat->GetTitle(),d1,t1,d2,t2);
719  assert(! ( val[0].Get() >= val[1].Get()));
720  }
721 
722  fTimer[1].Start(0); fTimer[3].Stop();fTimer[4].Stop();
723 
724  if (!dbstruct) {
725  dat->SetNRows(0);
726  if(Debug()>1) Warning("UpdateTable","Table %s.%s Not FOUND in DB",dat->GetName(),dat->GetTitle());
727  return 1;
728  }
729 
730  int nRows = fDBBroker->GetNRows();
731  // Adopt DB data in the new TTable
732  dat->Adopt(nRows,dbstruct);
733 // check size.
734  fDataSize[0]+=nRows*dat->GetRowSize();
735  if (!nRows || ((char*)dbstruct)[dat->GetRowSize()*nRows-1]) {}
736 
737  // dat->Print(0,1);
738 
739  // printf("BegVal=%s\n",val[0].AsString());
740  // printf("EndVal=%s\n",val[1].AsString());
741  return 0;
742 
743 }
744 //_____________________________________________________________________________
745 EDataSetPass St_db_Maker::UpdateDB(TDataSet* ds,void *user )
746 {
747  StValiSet *val;
748  if (strcmp("directory",ds->GetTitle())==0) return kContinue;
749  if (strcmp(".Val" ,ds->GetTitle())!=0) return kPrune;
750  //
751  // It is our place.
752  val = (StValiSet*)ds;
753  St_db_Maker *mk = (St_db_Maker*)user;
754  if (mk->fUpdateMode && !val->IsModified()) return kPrune;
755 
756  TDatime currenTime = mk->GetDateTime();
757  UInt_t uevent = currenTime.Get();
758 
759  // Check validity
760 
761  if (val->fTimeMin.Get() <= uevent
762  && val->fTimeMax.Get() > uevent) return kPrune;
763 
764  TObjectSet set("dbSnapshot",0);
765  const char *fname = mk->SAttr("dbSnapshot");
766  if (!fname || !*fname) {
767  // not in a snapshot mode
768  } else {
769  if (!mk->fDBBroker) {
770  mk->Error("UpdateDB","DbSnapshot mode: wrong validity for %s ignored( ???? )"
771  ,val->GetName());
772  return kPrune;
773  }
774  }
775  TDataSet *par = val->GetParent();
776  par->Remove(val->fDat);
777  mk->UpdateValiSet(val,currenTime);
778  if (val->fGood) par->AddFirst(val->fDat);
779  return kPrune;
780 }
781 //_____________________________________________________________________________
782 int St_db_Maker::UpdateValiSet(StValiSet *val,const TDatime &currenTimep)
783 {
784 static int nCall=0; nCall++;
785  TDatime currenTime(currenTimep);
786  if (currenTime.GetDate() >=kMaxTime) currenTime.Set(kMaxTime-1,0);
787  TDataSet *left;
788  TDatime valsCINT[2],valsSQL[2];
789  UInt_t uevent = currenTime.Get();
790 // Start loop
791 
792  val->fTimeMin.Set(kMaxTime,0);
793  val->fTimeMax.Set(kMinTime,0);
794  val->fGood=0;
795  int kase = 0;
796  valsSQL[0].Set(kMinTime,0);
797  valsSQL[1].Set(kMaxTime,0);
798  if (fDBBroker && val->fTabId ) { // Try to load from MySQL
799  assert(val->fTabId==val->fDat->GetUniqueID());
800  int ierr = UpdateTable(val->fParId,(TTable*)val->fDat,currenTime,valsSQL );
801  if (!ierr) kase = 1;
802  fQueryTs = time(NULL);
803  }
804 
805  left = FindLeft(val,valsCINT,currenTime);
806  if (left) kase+=2;
807  TDataSet *newGuy=0;
808 SWITCH: switch (kase) {
809 
810  case 0: // No SQL or CINT objects
811  val->fTimeMin = valsSQL[0]; val->fTimeMax = valsSQL[1];
812  kase=4; goto SWITCH;
813 
814  case 1: // Only SQL object
815  val->fTimeMin = valsSQL[0]; val->fTimeMax = valsSQL[1];
816  val->fGood=1; kase=4; goto SWITCH;
817 
818  case 2: // Only CINT object
819  newGuy = LoadTable(left);
820  if (!val->fDat) { val->fDat = newGuy; val->AddFirst(newGuy);}
821  else if(val->fDat->InheritsFrom(TTable::Class()))
822  { val->fDat->Update(newGuy); delete newGuy ;}
823  else { delete val->fDat; val->fDat = newGuy ;}
824  val->fTimeMin = valsCINT[0]; val->fTimeMax = valsCINT[1];
825  val->fGood=1; kase=4; goto SWITCH;
826 
827  case 3: // Both SQL and CINT objects
828  if (valsCINT[0].Get()>=valsSQL[0].Get()) {
829  kase = 2;
830  if (valsCINT[1].Get()>valsSQL[1].Get()) valsCINT[1] = valsSQL[1];
831  } else {
832  kase = 1;
833  if (valsSQL[1].Get()>valsCINT[1].Get()) valsSQL[1] = valsCINT[1];
834  }
835  goto SWITCH;
836 
837  case 4:
838  if( ! ((val->fTimeMin.Get()<= uevent) && (uevent<val->fTimeMax.Get()) )){
839 // wrong timing. We can forgive it, if it is RunLog. Akio case
840  if (val->Path().Contains("RunLog/onl")) break;
841 
842  //
843  // ATTENTION: do not change te format of the next line.
844  // CheckFail is verified by production parsers to detect
845  // fatal DB initialization issues.
846  //
847  (void) printf("CheckFail:: Assert will fail for Table %s TimeMin=%d TimeMax=%d uevent=%d\n",
848  val->GetName(),val->fTimeMin.Get(),val->fTimeMax.Get(),uevent);
849  (void) printf("\tTimeMin "); val->fTimeMin.Print();
850  (void) printf("\tuevent "); currenTime.Print();
851  (void) printf("\tTimeMax "); val->fTimeMax.Print();
852  }
853  assert((val->fTimeMin.Get()<= uevent) && (val->fTimeMax.Get()>uevent));
854 
855  break;
856 
857  default: assert(0);
858  }
859  val->fVers++;
860  val->Modified(1);
861  if (val->fTimeMin.Get() == val->fTimeMax.Get()) {
862  Warning("UpdateDB","Zero size validity for %s",val->GetName());
863  printf("\tTimeMin "); val->fTimeMin.Print();
864  printf("\tuevent "); currenTime.Print();
865  printf("\tTimeMax "); val->fTimeMax.Print();
866  Warning("UpdateDB","Ask Mike DeFillips WHY!!!!!");
867  }
868  return val->fGood;
869 }
870 
871 //_____________________________________________________________________________
872 TDataSet *St_db_Maker::FindLeft(StValiSet *val, TDatime vals[2], const TDatime &currenTime)
873 {
874 
875 // Search left object among ONLY CINT_DB objects. MySQL objects ignored here
876 // Start loop
877  UInt_t uevent = currenTime.Get();
878 
879  vals[0].Set(kMinTime,0);
880  vals[1].Set(kMaxTime,0);
881  UInt_t utmp,udifleft=(UInt_t)(-1),udifrite=(UInt_t)(-1);
882  TDataSet *left=0,*rite=0,*set=0;
883  TListIter next(val->GetList());
884  while ((set = (TDataSet*)next())) {
885  if (set == val->fDat) continue; //MySQL object ignored
886  const char *filename = set->GetName();
887  UInt_t ucur = St_db_Maker::Time(filename).Get();
888  if (!ucur) {
889  Warning("FindLeft","*** Unrecognozed file %s ***",filename);
890  continue;
891  } else if (uevent < ucur) {
892  utmp = ucur - uevent;
893  if (utmp <= udifrite) { udifrite=utmp; rite=set;}
894  }else{
895  utmp = uevent - ucur;
896  if (utmp <= udifleft) { udifleft=utmp; left=set;}
897  }
898  }// end while
899 
900 
901  if (left) vals[0] = St_db_Maker::Time(left->GetName());
902  if (rite) vals[1] = St_db_Maker::Time(rite->GetName());
903  return left;
904 }
905 
906 
907 //_____________________________________________________________________________
908 TDataSet *St_db_Maker::LoadTable(TDataSet* left)
909 {
910  TFile *tf =0;
911  TObject *to =0;
912  TString command;
913  TDataSet *newdat = 0;
914  TString dbfile(FullFileName(left));
915  assert(dbfile.Length()>0);
916 
917  int kind = Kind(left->GetName());
918  switch (kind) {
919 
920  case kXDFkind: // .xdf file
921  assert(0);
922  // newdat = St_XDFFile::GetXdFile(dbfile);assert (newdat);
923  if (GetDebug()) printf("Load XdfFile: %s\n",(const char*)dbfile);
924  break;
925 
926  case kCkind: // .C file
927 
928  command = ".L "; command += dbfile;
929  if (GetDebug()) printf("LoadTable: %s\n",(const char*)command);
930  TInterpreter::EErrorCode ee;
931  gInterpreter->ProcessLine(command,&ee);
932  assert(!ee);
933  newdat = (TDataSet *) gInterpreter->Calc("CreateTable()",&ee);
934  assert(!ee);
935  command.ReplaceAll(".L ",".U ");
936  gInterpreter->ProcessLine(command,&ee);
937  assert(!ee);
938 
939  break;
940 
941  case kROOTkind: // .root file
942 
943  tf = new TFile(dbfile);
944  to = StIO::Read (tf, "*");
945  delete tf;
946  if (!to) break;
947  if (GetDebug()) printf("Load TFile: %s\n",(const char*)dbfile);
948  if (strcmp(to->ClassName(),"StIOEvent")==0) to = ((StIOEvent*)to)->fObj;
949  if (!to) break;
950  if (to->InheritsFrom(TDataSet::Class())) {
951  newdat = (TDataSet*)to;
952  } else {
953  newdat = new TObjectSet(to->GetName());
954  newdat->SetObject(to);
955  }
956  break;
957 
958  default: assert(0);
959  }
960  if (newdat) newdat->SetUniqueID(kUNIXOBJ+kind);
961 
962  return newdat;
963 }
964 
965 //_____________________________________________________________________________
966 EDataSetPass St_db_Maker::PrepareDB(TDataSet* ds, void *user)
967 {
968  TDataSet *set;
969  StValiSet *pseudo = 0;
970  const char *dsname,*filename,*dot;
971  char psname[100];
972  //int ldsname,lpsname;
973  int lpsname;
974 
975  TList *list = ds->GetList();
976  if (!list) return kContinue;
977  if (strcmp("directory",ds->GetTitle())!=0) return kPrune;
978  dsname = ds->GetName(); ;
979  if (!strcmp("CVS",dsname)) { delete ds; return kPrune;}
980  //ldsname= strlen(dsname);
981  TString newTitle = "file ";
982  if (user) newTitle += *((TString*)user);
983 
984 // Start loop
985  pseudo = 0; psname[0]='.'; psname[1]=0;
986  TListIter next(list);
987  while ((set = (TDataSet*)next())) {
988  filename = set->GetName();
989  int isSql =(set->InheritsFrom(TTable::Class())!=0);
990  if (isSql) { // Sql object
991  lpsname = strlen(filename);
992  } else { // Cint object
993  if (strncmp("file",set->GetTitle(),4)!=0) continue;
994  if (!(dot = strchr(filename,'.'))) continue;
995  int k = Kind(filename);
996  if (k==kCkind) { //case of *.C
997  }
998  if (!k){ delete set; continue;}
999  set->SetTitle(newTitle);
1000  lpsname = dot - filename;
1001  }
1002  if (strncmp(filename,psname+1,lpsname)) {// make new pseudo directory
1003  psname[1]=0; strncat(psname,filename,lpsname);
1004  pseudo = new StValiSet(psname,ds); //VP strcat(psname,".");
1005  pseudo->fParId = ds->GetUniqueID();
1006  }
1007 
1008  set->Shunt(pseudo);
1009  if (isSql) {
1010  assert(pseudo);
1011  pseudo->fTabId = set->GetUniqueID(); // save SQL Id
1012  pseudo->fDat=set; // save SQL object
1013  // for future validity requests
1014  }
1015  }
1016  return kContinue;
1017 }
1018 //______________________________________________________________________________
1019 TDataSet *St_db_Maker::GetDataBase(const char* logInput,const TDatime *td)
1020 {
1021  fTimer[1].Start(0);
1022  TString ts;
1023  TDataSet *ds=0;
1024  int idir = 1,lst;
1025  ds = GetDataSet(logInput);
1026  if (!ds || strncmp(ds->GetTitle(),"directory",9)!=0)
1027  { // We did not find it or it is not a directory.
1028  // May be concrete object name is here
1029  idir = 0;
1030  lst =-1;
1031  for (int i=0;logInput[i];i++) if (logInput[i]=='/') lst=i;
1032  if (lst<0) { ds=0; goto RETN;}
1033 // path/obj ==> path/.obj
1034  ts = logInput;
1035  ts.Insert(lst+1,".");
1036  ds = GetDataSet(ts.Data());
1037  if (!ds) goto RETN;
1038  }
1039 
1040  if (td) { //Case when time is defined by user. User will be owner
1041  if (idir) {
1042  Error("GetDataBase","Request for directory %s with user time is FORBIDDEN"
1043  ,ds->GetName());
1044  assert(!idir);
1045  }
1046  assert(!strcmp(".Val",ds->GetTitle()));
1047  StValiSet *vs = (StValiSet*)ds;
1048  StValiSet *myVS = new StValiSet(vs->GetName(),0);
1049  myVS->fTabId = vs->fTabId;
1050  myVS->fParId = vs->fParId;
1051  myVS->Modified(1);
1052  if (vs->fParId) {
1053  TTable *tb = (TTable *)vs->fDat;
1054  TString ty(tb->GetType());
1055  if (ty.EndsWith("_st")) ty.Remove(ty.Length()-3,99);
1056  myVS->fDat = TTable::New(tb->GetName(),ty,0,0);
1057  myVS->fDat->SetUniqueID(myVS->fTabId);
1058  }
1059  TDataSetIter next(vs);
1060  TDataSet *to=0;
1061  while ((to=(TDataSet*)next())){ myVS->Add(to);}
1062 
1063  UpdateValiSet(myVS,*td);
1064  myVS->GetList()->Clear("nodelete");
1065  if (myVS->fGood) { //object is found
1066  myVS->fDat->Add(myVS);
1067  return myVS->fDat;
1068  }
1069  delete myVS->fDat;
1070  delete myVS;
1071  return 0;
1072  }
1073 
1074 
1075  UpdateDB(ds);
1076  if (idir) goto RETN;
1077  ds = GetDataSet(logInput);
1078 RETN: fTimer[1].Stop(); return ds;
1079 }
1080 //_____________________________________________________________________________
1081 const TDatime &St_db_Maker::GetDateTime() const
1082 {
1083  if (!fIsDBTime) return StMaker::GetDateTime();
1084  //(void )printf("**** fIsDBTime is set, returning its value\n");
1085  return fDBTime;
1086 }
1087 //_____________________________________________________________________________
1088 void St_db_Maker::SetDateTime(Int_t idat,Int_t itim)
1089 {
1090  fIsDBTime=0; if (idat==0) return;
1091  fIsDBTime=1; fDBTime.Set(idat,itim);
1092  Info("SetDateTime","Setting Startup Date=%d Time=%d",idat,itim);
1093  StMaker::SetDateTime(idat,itim);
1094 }
1095 //_____________________________________________________________________________
1096 void St_db_Maker::SetDateTime(const char *alias)
1097 {
1098  fIsDBTime=1;
1099  int idat = AliasDate(alias);// <name>.YYYYMMDD.hhmmss.<ext>
1100  int itim = AliasTime(alias);
1101  assert(idat);
1102  Info("SetDateTime","(\"%s\") == Startup Date=%d Time=%d",alias,idat,itim);
1103  fDBTime.Set(idat,itim);
1104  StMaker::SetDateTime(idat,itim);
1105 }
1106 //_____________________________________________________________________________
1107 void St_db_Maker::SetOn(const char *path)
1108 { AddAlias("On" ,path,".onoff"); OnOff();}
1109 //_____________________________________________________________________________
1110 Int_t St_db_Maker::Save(const char *path,const TDatime *newtime)
1111 {
1112  ofstream out;
1113  int nakt=0,i,l;
1114  TDataSet *top,*ds;
1115  TTable *tb;
1116  TString ts,dir;
1117  TDatime val[2];
1118  char cbuf[20];
1119  top = GetDataBase(path);
1120  if (!top) return 1;
1121  TDataSetIter nextDS(top,999);
1122  TDataSet::EDataSetPass mode = TDataSet::kContinue;
1123  while((ds = nextDS(mode))) {
1124  mode = TDataSet::kContinue;
1125  if (ds->GetName()[0]=='.') { mode = TDataSet::kPrune; continue; }
1126  if (!ds->InheritsFrom(TTable::Class()))continue;
1127  ts = ds->Path();
1128  i = ts.Index(".const/"); assert(i>0); ts.Replace(0 ,i+7,"");
1129  int jdot = ts.Index(".",(Ssiz_t)1,(Ssiz_t)0 ,TString::kExact);
1130  assert(jdot>0);
1131  int jsla = ts.Index("/",(Ssiz_t)1,(Ssiz_t)jdot,TString::kExact);
1132  assert(jsla>0);
1133  ts.Remove(jdot,jsla-jdot+1);
1134  l = ts.Length();
1135  for (i=0;i<l;i++) {
1136  if (ts[i]!='/') continue;
1137  dir.Replace(0,999,ts,i);
1138  gSystem->MakeDirectory(dir);
1139  }
1140  tb = (TTable*)ds;
1141  if (newtime) { val[0] = *newtime;}
1142  else {i = GetValidity(tb,val); assert(i>=0);}
1143  sprintf(cbuf,".%08d.%06d.C",val[0].GetDate(),val[0].GetTime());
1144  ts += cbuf;
1145  out.open((const char*)ts);
1146  tb->SavePrimitive(out,"");
1147  out.close();
1148  nakt++;
1149  }
1150  return (!nakt);
1151 }
1152 //_____________________________________________________________________________
1153 Int_t St_db_Maker::SaveDataSet(TDataSet* ds, int type, bool savenext) {
1154  if (!ds || !ds->InheritsFrom(TTable::Class())) {
1155  // dataset is not inherited from TTable
1156  return 0;
1157  }
1158  int i = 0;
1159  int jdot = 0, jsla = 0; // used for recursive directory creation
1160  TString ts;
1161  TString dir; // DataSet directory on disk
1162  ts = ds->Path();
1163  i = 0; i = ts.Index(".const/"); assert(i>0); ts.Replace(0,i+7,"");
1164  jdot = 0; jdot = ts.Index(".",(Ssiz_t)1,(Ssiz_t)0 ,TString::kExact); assert(jdot>0);
1165  jsla = 0; jsla = ts.Index("/",(Ssiz_t)1,(Ssiz_t)jdot,TString::kExact); assert(jsla>0);
1166  ts.Remove(jdot, jsla-jdot + 1);
1167  int l = ts.Length();
1168 
1169  for (i = 0; i < l; i++) {
1170  if (ts[i]!='/') continue;
1171  dir.Replace(0,999,ts,i);
1172  gSystem->MakeDirectory(dir);
1173  }
1174  switch(type) {
1175  case 0:
1176  return SaveDataSetAsRootFile((TTable*)ds, ts, savenext);
1177  break;
1178  case 1:
1179  return SaveDataSetAsCMacro((TTable*)ds, ts, savenext);
1180  break;
1181  default:
1182  // requested format is not known to St_db_Maker, sorry!
1183  break;
1184  }
1185  return 1;
1186 }
1187 
1188 //_____________________________________________________________________________
1189 Int_t St_db_Maker::SaveDataSetAsCMacro(TTable* tb, TString ts, bool savenext) {
1190  TDatime val[2]; // validity of original sets
1191  std::ofstream out; // output file handle
1192  int i = 0; i = GetValidity(tb,val); assert(i>=0);
1193  std::stringstream ostr;
1194  ostr << ts << "." << std::setw(6) << std::setfill('0') <<val[0].GetDate() << "." << std::setw(6) << std::setfill('0')
1195  << val[0].GetTime() << ".C";
1196  out.open( ostr.str().c_str() );
1197  tb->SavePrimitive(out,"");
1198  out.close();
1199 
1200  if (savenext == true) {
1201  std::string tbname( std::string(ts.Data()).substr(7) ); // name of data set to search for
1202  if (val[1].GetDate() < 20330101 ) { // table has more values, let's store +1 dataset
1203  TDataSet* ds_r = 0;
1204  ds_r = GetDataBase(tbname.c_str(), &val[1]);
1205  if (ds_r) {
1206  SaveDataSetAsCMacro((TTable*)ds_r, ts, false);
1207  delete ds_r;
1208  }
1209  }
1210  }
1211  return 0;
1212 }
1213 
1214 Int_t St_db_Maker::SaveDataSetAsRootFile(TTable* tb, TString ts, bool savenext) {
1215  TDatime val[2]; // validity of original sets
1216  int i = 0; i = GetValidity(tb,val); assert(i>=0);
1217  std::stringstream ostr;
1218  ostr << ts << "." << std::setw(6) << std::setfill('0') <<val[0].GetDate() << "." << std::setw(6) << std::setfill('0')
1219  << val[0].GetTime() << ".root";
1220  TFile ofile(ostr.str().c_str(),"RECREATE" );
1221  tb->Write();
1222  ofile.Close();
1223 
1224  if (savenext == true) {
1225  std::string tbname( std::string(ts.Data()).substr(7) ); // name of data set to search for
1226  if (val[1].GetDate() < 20330101 ) { // table has more values, let's store +1 dataset
1227  TDataSet* ds_r = 0;
1228  ds_r = GetDataBase(tbname.c_str(), &val[1]);
1229  if (ds_r) {
1230  SaveDataSetAsRootFile((TTable*)ds_r, ts, false);
1231  delete ds_r;
1232  }
1233  }
1234  }
1235 
1236  return 0;
1237 }
1238 
1239 //_____________________________________________________________________________
1240 Int_t St_db_Maker::SaveSnapshotPlus(char* path, int type)
1241 {
1242  TDataSet *top = 0, *ds = 0;
1243  TString ts; // DataSet path
1244  TDataSet::EDataSetPass mode = TDataSet::kContinue;
1245  TDatime maxDbTime;
1246  maxDbTime.Set(kMaxTime,0);
1247 
1248  // request DataSets from database
1249  top = GetDataBase(path);
1250  if (!top) {
1251  // can't find requested database name
1252  return 1;
1253  }
1254  TDataSetIter nextDS(top,999);
1255  ds = nextDS(mode);
1256  if (!ds) {
1257  // no subtrees found, let's save this lonely dataset
1258  SaveDataSet(top, type, true);
1259  return 0;
1260  }
1261  // cycle through available datasets
1262  while ((ds = nextDS(mode))) {
1263  mode = TDataSet::kContinue;
1264  if (ds->GetName()[0]=='.') { mode = TDataSet::kPrune; continue; }
1265  SaveDataSet(ds, type, true);
1266  }
1267  return 0;
1268 }
1269 
1270 //_____________________________________________________________________________
1271 void St_db_Maker::SetFlavor(const char *flav,const char *tabname)
1272 {
1273  TDataSet *fl=0;
1274  TDataSet *flaDir =0;
1275  if (flav) {
1276  fl = 0;
1277  flaDir = Find(".flavor");
1278  if (flaDir) fl = flaDir->Find(tabname);
1279  if (fl && strcmp(fl->GetTitle(),flav)==0) return;
1280  if (fl) delete fl;
1281  fl = new TDataSet(tabname);
1282  fl->SetTitle(flav);
1283  AddData(fl,".flavor");
1284  }
1285  if (!fDBBroker) return;
1286  int nAkt = 0;
1287  flaDir = Find(".flavor");
1288  if (!flaDir) return;
1289  StValiSet *val;
1290  TDataSetIter valNext(GetConst(),999);
1291  while ((val = (StValiSet*)valNext())) { //DB objects loop
1292  const char *tabName = val->GetName();
1293  if (tabName[0] != '.') continue;
1294  if (strcmp(val->GetTitle(),".Val")!=0) continue;
1295  tabName++;
1296  if (val->fDat==0) continue;
1297  if (val->fDat->GetUniqueID() >= kUNIXOBJ) continue;
1298 
1299  TDataSetIter flaNext(flaDir);
1300  while((fl = flaNext())) { // Flavor loop
1301  const char *flaName = fl->GetName();
1302  if (strcmp(flaName,".all" )!=0
1303  && strcmp(flaName,tabName)!=0) continue;
1304  const char *flaType = fl->GetTitle();
1305  if (val->fFla == flaType) continue;
1306 
1307  TDataSet *par = val->GetParent();
1308  val->fFla = flaType;
1309  nAkt++;
1310  val->fTimeMin.Set(kMaxTime,0);
1311  val->fTimeMax.Set(kMinTime,0);
1312  int tabID = (int)val->fDat->GetUniqueID();
1313  int parID = (int)par->GetUniqueID();
1314 
1315  fTimer[1].Stop(); fTimer[3].Start(0);
1316  fDBBroker->SetTableFlavor(flaType,tabID, parID);
1317  fTimer[1].Start(0); fTimer[3].Stop();
1318  fl->SetUniqueID(fl->GetUniqueID()+1);
1319 
1320  if (Debug()<2) continue;
1321  if (strcmp("ofl",flaType)==0) continue;
1322  printf("<St_db_Maker::SetFlavor> Set flavor %s to %s\n",flaType,tabName);
1323 
1324  }// End Flavor loop
1325 
1326  }//End DB objects loop
1327 
1328  TDataSetIter flaNext(flaDir);
1329  while((fl = flaNext())) { // 2nd Flavor loop
1330  if (fl->GetUniqueID()) continue;
1331  if (strcmp(fl->GetName(),".all" )==0) continue;
1332  Warning("SetFlavor","Flavor %s for table %s was NOT USED",
1333  fl->GetTitle(),fl->GetName());
1334  }
1335 
1336  delete flaDir;
1337  if (GetDateTime().GetDate() >= 20330101) return;
1338  if(nAkt) Make();
1339 
1340 }
1341 //_____________________________________________________________________________
1342 Int_t St_db_Maker::GetValidity(const TTable *tb, TDatime *const val)
1343 {
1344  if (!tb) return -1;
1345  TString ts("."); ts+=tb->GetName();
1346  TDataSet *pa = tb->GetParent();
1347  const StValiSet *vs =0;
1348  if (pa) { vs = (StValiSet*)pa->Find(ts);}
1349  else { vs = (StValiSet*)tb->Find(ts);}
1350  if (!vs) return -2;
1351  if (val) {
1352  val[0] = vs->fTimeMin;
1353  val[1] = vs->fTimeMax;
1354  }
1355  return vs->fVers;
1356 }
1357 //_____________________________________________________________________________
1358 Int_t St_db_Maker::Drop(TDataSet *ds)
1359 {
1360  if (!ds) return -1;
1361  TString ts("."); ts+=ds->GetName();
1362  TDataSet *pa = ds->GetParent();
1363  assert(pa);
1364  assert(ts == pa->GetName());
1365  StValiSet *vs = (StValiSet*)pa;
1366  assert(ds == vs->fDat);
1367  TDataSet *ppa = pa->GetParent();
1368  ppa->Remove(ds);
1369  pa->Remove(ds);
1370  vs->fDat=0;
1371  delete ds;
1372  return 0;
1373 }
1374 //_____________________________________________________________________________
1375 void St_db_Maker::SetOff(const char *path)
1376 { AddAlias("Off",path,".onoff"); OnOff();}
1377 //_____________________________________________________________________________
1378 void St_db_Maker::OnOff()
1379 {
1380  int Off,len;
1381  if (!fDataBase) return;
1382  TDataSet *onoff = Find(".onoff");
1383  if (!onoff) return;
1384 
1385  TString tsBase,tsDir,tsTit;
1386  TDataSet *ono;
1387  TDataSetIter onoffNext(onoff);
1388  while((ono=onoffNext())) {// loop onoffs
1389  Off = (strcmp("Off",ono->GetName())==0);
1390  tsDir = gSystem->DirName(ono->GetTitle());
1391  tsBase = gSystem->BaseName(ono->GetTitle());
1392  TRegexp rex(tsBase,1);
1393  TDataSet *dsDir = GetDataSet(tsDir);
1394  if (!dsDir) continue;
1395  if (GetMaker(dsDir) != this) continue;
1396  TDataSetIter nextVal(dsDir);
1397  TDataSet *val;
1398  while ((val=nextVal())) {//loop over val's
1399  const char *name = val->GetName();
1400  if(name[0]!='.') continue;
1401  tsTit = val->GetTitle();
1402  int ival = tsTit.Index(".Val");
1403  if (ival<0) continue;
1404  if (Off != (ival==0)) continue;
1405  if (rex.Index(name+1,&len)!=0) continue;
1406  if ( Off) tsTit.Replace(0,0,".Off");
1407  if (!Off) tsTit.Replace(0,4,"" );
1408  val->SetTitle(tsTit);
1409  printf("<%s::Set%s> %s/%s\n"
1410  ,ClassName(),ono->GetName(),(const char*)tsDir,val->GetName()+1);
1411  }//end loop over val's
1412  }// end loop onoffs
1413 }
1414 //_____________________________________________________________________________
1415 void St_db_Maker::SetMaxEntryTime(Int_t idate,Int_t itime)
1416 {
1417  TUnixTime ut;
1418  ut.SetGTime(idate,itime);
1419  fMaxEntryTime = ut.GetUTime();
1420 }
1421 
1422 //_____________________________________________________________________________
1423 void St_db_Maker::AddMaxEntryTimeOverride(Int_t idate,Int_t itime, char* dbType, char* dbDomain) {
1424 
1425  std::string mDbType = "";
1426  std::string mDbDomain = "";
1427 
1428  if (dbType) {
1429  for (char* p = dbType; *p != '\0'; p++) {
1430  *p = (char)std::tolower(*p);
1431  }
1432  dbType[0] = std::toupper(dbType[0]);
1433  mDbType = dbType;
1434  }
1435 
1436  if (dbDomain) {
1437  for (char* p = dbDomain; *p != '\0'; p++) {
1438  *p = (char)std::tolower(*p);
1439  }
1440  mDbDomain = dbDomain;
1441  }
1442 
1443  TUnixTime ut;
1444  ut.SetGTime(idate,itime);
1445  fMaxEntryTimeOverride.insert( std::make_pair( std::make_pair(mDbType,mDbDomain), ut.GetUTime() ) );
1446 }
1447 
1448 // Now very UGLY trick
1449 #define private public
1450 #include "TGeoManager.h"
1451 //_____________________________________________________________________________
1452 int St_db_Maker::Snapshot (int flag)
1453 {
1454  int ians=0;
1455  TFile *tfSnap = 0;
1456  TObjectSet set("dbSnapshot",0);
1457  const char *fname = SAttr("dbSnapshot");
1458  if (!fname || !*fname) return 0;
1459  switch (flag) {
1460  case 0://Read
1461  if (gSystem->AccessPathName(fname, kFileExists)) return 0;
1462  if (gSystem->AccessPathName(fname, kReadPermission)) return 0;
1463  tfSnap = TFile::Open(fname,"READ");
1464  if (!tfSnap) return 0;
1465  if (tfSnap->IsZombie()) {delete tfSnap; return 0;}
1466 
1467  Info("Snapshot","Use DB from file %s\n",fname);
1468  ians = set.Read("dbSnapshot");
1469  fDataBase = (TDataSet*)set.GetObject();
1470  set.DoOwner(0);
1471  assert(fDataBase);
1472 // {
1473 // // Special case TGeo geometry must be touched
1474 // TDataSet *geo = (TDataSet*)fDataBase->FindObject(".Geometry");
1475 // if (geo) {
1476 // geo = ((StValiSet*)geo)->fDat;
1477 // TGeoManager *gm = (TGeoManager*)geo->GetObject();
1478 // if (gm) { gm->fClosed=0; gm->CloseGeometry(); }
1479 // } }
1480  break;
1481 
1482  case 1://Write
1483  if (!gSystem->AccessPathName(fname, kFileExists)) return 0;
1485  tfSnap = TFile::Open(fname,"NEW");
1486  if (!tfSnap || tfSnap->IsZombie()) {
1487  Error("Snapshot","Can not open file for write");
1488  return 0;
1489  }
1490 // // TGeo geometry must not be saved
1491 // TDataSet *geo = (TDataSet*)fDataBase->FindObject(".Geometry");
1492 // if (geo) {
1493 // geo = ((StValiSet*)geo)->fDat;
1494 // Drop(geo);
1495 // }
1496  TDataSet *parent = fDataBase->GetParent();
1497  fDataBase->Shunt(0);
1498  set.SetObject(fDataBase);
1499  Info("Snapshot","Save DB to file %s\n",fname);
1500  ians = set.Write("dbSnapshot",TObject::kOverwrite);
1501  fDataBase->Shunt(parent);
1502  tfSnap->Close();
1503  break;
1504  }
1505  delete tfSnap;
1506  return ians;
1507 }
1508 
1509 
1510 
1511 //*-- Author : Valery Fine(fine@bnl.gov) 10/08/98
1512 //
1513 // Revision 1.60 2002/06/14 14:48:00 jeromel
1514 // Last change moved after Use()
1515 //
1516 // Revision 1.59 2002/06/14 14:03:11 jeromel
1517 // Added warning if start=end fro date and time (i.e. 0 everywhere) for a table.
1518 //
1519 // Revision 1.58 2002/05/18 01:04:52 jeromel
1520 // Small modif adding more debugging of what it's doing ... In perticular,
1521 // the association string <-> DateTime is shown.
1522 //
1523 // Revision 1.57 2002/03/04 16:38:58 jeromel
1524 // More info printed before assert()
1525 //
1526 // Revision 1.56 2002/03/01 14:56:42 jeromel
1527 // Finalized the timestamp as per June 15th.
1528 //
1529 // Revision 1.55 2002/02/28 23:34:04 jeromel
1530 // Since the svt geant geometry appears to have changed in Spectember 5th 2001,
1531 // the definition of y2001 geometry must have changed since MDC4 (where y2001
1532 // was used but the geometry did not have those recent updates). Furthermore,
1533 // y2001 equates to year_2b for St_db_Maker, that is, timestamp 20010501 that's
1534 // May 1st 2001. The 'db' entries for svt should also be different. So, we
1535 // added a hacked entry to correct this very very very confusing issue.
1536 //
1537 // MDC4New chain added
1538 // Timestamp for this y2001n, will equate to egant geometry y2001
1539 // but a new timestamp in St_db_maker .
1540 //
1541 // This allows for re-running through the geant MDC4 produced files using
1542 // MDC4 chain option in the reco pass and find the same result.
1543 //
1544 // Revision 1.54 2002/01/18 16:18:03 perev
1545 // TimeStamp for absent table fix
1546 //
1547 // Revision 1.53 2002/01/17 23:45:32 perev
1548 // TimeStamp for nonexisting table fixed
1549 //
1550 // Revision 1.52 2001/11/07 18:02:28 perev
1551 // reurn into InitRun added
1552 //
1553 // Revision 1.51 2001/10/27 21:48:32 perev
1554 // SetRunNumber added
1555 //
1556 // Revision 1.50 2001/10/13 20:23:16 perev
1557 // SetFlavor working before and after Init()
1558 //
1559 // Revision 1.49 2001/09/26 23:24:04 perev
1560 // SetFlavor for table added
1561 //
1562 // Revision 1.48 2001/04/14 02:03:46 perev
1563 // const added
1564 //
1565 // Revision 1.47 2001/04/13 21:21:34 perev
1566 // small fix (fine) + cons's
1567 //
1568 // Revision 1.46 2001/04/13 01:28:42 perev
1569 // Small bug fixed (fine found)
1570 //
1571 // Revision 1.45 2001/03/21 23:06:13 didenko
1572 // Set time for year to 20000614.175430 instead of 20000501.0
1573 //
1574 // Revision 1.44 2001/03/07 20:43:46 perev
1575 // assert for wrong time added
1576 //
1577 // Revision 1.43 2001/02/18 20:09:58 perev
1578 // Distinction between UNIX FS objects and MySql added
1579 //
1580 // Revision 1.42 2001/01/31 17:12:05 fisyak
1581 // Introduce year-2b for STAR 2001
1582 //
1583 // Revision 1.41 2000/11/07 15:02:05 fisyak
1584 // Fix typo
1585 //
1586 // Revision 1.40 2000/11/07 01:48:25 fisyak
1587 // Add one more protection agaist fDataBase==NULL
1588 //
1589 // Revision 1.39 2000/11/02 16:02:20 fisyak
1590 // Jeff request to allow a top level directory (e.g. database) have ID=0 which is ok
1591 //
1592 // Revision 1.38 2000/09/16 02:45:09 didenko
1593 // commit Victor's changes
1594 //
1595 // Revision 1.37 2000/07/14 02:39:21 perev
1596 // SetMaxEntryTime method added
1597 //
1598 // Revision 1.36 2000/06/29 15:58:04 perev
1599 // bug in Init fixed, wrong {}
1600 //
1601 // Revision 1.35 2000/06/26 20:58:41 perev
1602 // multiple DBs
1603 //
1604 // Revision 1.33 2000/06/20 20:39:49 fisyak
1605 // Add debug print out
1606 //
1607 // Revision 1.32 2000/05/20 01:00:43 perev
1608 // SetFlavor() added
1609 //
1610 // Revision 1.31 2000/05/12 15:10:19 fine
1611 // new Table macro introduced
1612 //
1613 // Revision 1.30 2000/05/11 01:27:54 fisyak
1614 // Change y1h from 03/01/2000 to 05/01/2000
1615 //
1616 // Revision 1.29 2000/04/14 14:49:59 perev
1617 // Communication via descriptor struct -> class
1618 //
1619 // Revision 1.28 2000/04/13 02:58:47 perev
1620 // Method Save is added & default CintDB loaded if exists
1621 //
1622 // Revision 1.27 2000/04/07 15:44:42 perev
1623 // Error return when MySQL is not available
1624 //
1625 // Revision 1.26 2000/03/23 14:55:55 fine
1626 // Adjusted to libSTAR and ROOT 2.24
1627 //
1628 //
1630 // //
1631 // St_db_Maker class for Makers //
1632 // //
1633 // This class is C++ implementation of the Begin_html <a href="http://www.rhic.bnl.gov/afs/rhic.bnl.gov/star/doc/www/packages_l/pro/pams/db/sdb/doc/index.html">Simple Database Manager</a> End_html //
1634 // //
virtual TDataSet * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TDataSet.cxx:403
virtual void Clear(Option_t *opt="")
User defined functions.
Definition: FJcore.h:367
virtual EDataSetPass Pass(EDataSetPass(*callback)(TDataSet *), Int_t depth=0)
Definition: TDataSet.cxx:689
virtual Long_t GetRowSize() const
Returns the size (in bytes) of one table row.
Definition: TTable.cxx:1395
virtual void AddData(TDataSet *data, const char *dir=".data")
User methods.
Definition: StMaker.cxx:332
virtual const Char_t * GetType() const
Returns the type of the wrapped C-structure kept as the TNamed title.
Definition: TTable.cxx:1444
virtual void Remove(TDataSet *set)
Remiove the &quot;set&quot; from this TDataSet.
Definition: TDataSet.cxx:641
virtual Int_t Make()
virtual void SetObject(TObject *obj)
The depricated method (left here for the sake of the backward compatibility)
Definition: TDataSet.cxx:480
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream &quot;out&quot;.
Definition: TTable.cxx:1810
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Definition: TDataSet.cxx:893
Definition: TAttr.h:17
virtual void SetBIT(EMakerStatus k)
Maker Status Bits.
Definition: StMaker.h:204
virtual TTableDescriptor * GetRowDescriptors() const
to be documented
Definition: TTable.cxx:2222
virtual Int_t Finish()
virtual void ls(Option_t *option="") const
Definition: TDataSet.cxx:495
virtual TObject * GetObject() const
The depricated method (left here for the sake of the backward compatibility)
Definition: TDataSet.cxx:428
virtual void AddFirst(TDataSet *dataset)
Add TDataSet object at the beginning of the dataset list of this dataset.
Definition: TDataSet.cxx:283
Definition: Stypes.h:40
virtual Int_t Purge(Option_t *opt="")
Definition: TDataSet.cxx:758
static TTable * New(const Char_t *name, const Char_t *type, void *array, UInt_t size)
This static method creates a new TTable object if provided.
Definition: TTable.cxx:1515
virtual void Shunt(TDataSet *newParent=0)
Definition: TDataSet.cxx:810
Definition: TTable.h:48
virtual void Sort()
Sort recursively all members of the TDataSet with TList::Sort method.
Definition: TDataSet.cxx:874
virtual void Update()
Definition: TDataSet.cxx:864
virtual TString Path() const
return the full path of this data set
Definition: TDataSet.cxx:626
Definition: Stypes.h:44
virtual Char_t * Print(Char_t *buf, Int_t n) const
Create IDL table defintion (to be used for XDF I/O)
Definition: TTable.cxx:1548
virtual void Adopt(Int_t n, void *array)
Definition: TTable.cxx:1107
virtual TDataSet * Find(const char *path) const
Definition: TDataSet.cxx:362