StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StDbBroker.cxx
1 /***************************************************************************
2  *
3  * $Id: StDbBroker.cxx,v 1.63 2021/05/10 21:15:08 perev Exp $
4  *
5  * Author: S. Vanyashin, V. Perevoztchikov
6  * Updated by: R. Jeff Porter
7  ***************************************************************************
8  *
9  * Description: Offline Interface from the Offline Maker interface to the
10  * Database interface.
11  *
12  ***************************************************************************
13  *
14  * $Log: StDbBroker.cxx,v $
15  * Revision 1.63 2021/05/10 21:15:08 perev
16  * RemoveApi.h
17  *
18  * Revision 1.62 2016/05/24 17:44:16 dmitry
19  * first batch of fixes for Coverity findings
20  *
21  * Revision 1.61 2015/05/21 21:51:34 dmitry
22  * avoid memleak by moving check to the entrance of the func
23  *
24  * Revision 1.60 2015/05/21 18:29:06 dmitry
25  * small memory leak and type conversion warnings fixed
26  *
27  * Revision 1.59 2014/07/28 14:58:27 dmitry
28  * fixed templated call to make it compliant with gcc 4.8.2
29  *
30  * Revision 1.58 2011/11/28 17:03:07 dmitry
31  * dbv override support in StDbLib,StDbBroker,St_db_Maker
32  *
33  * Revision 1.57 2011/02/10 17:31:01 dmitry
34  * added an option to blacklist domains
35  *
36  * Revision 1.56 2009/11/10 20:24:00 fisyak
37  * Use SafeDelete
38  *
39  * Revision 1.55 2008/01/17 20:55:00 deph
40  * Removed annoying repetative printing of Statistics
41  *
42  * Revision 1.54 2008/01/15 20:37:44 deph
43  * Removed DbFill and corresponding calls from StDbBroker
44  *
45  * Revision 1.53 2007/12/11 20:31:08 deph
46  * moved print statistics call to close db function so only prints upon a real close
47  *
48  * Revision 1.52 2007/10/10 15:29:10 deph
49  * Removed debug statements
50  *
51  * Revision 1.51 2007/09/10 02:36:08 perev
52  * StDbBroker::Release added
53  *
54  * Revision 1.50 2007/05/16 22:47:54 deph
55  * Replaced cerr with LOG_ERROR <<endm; for logger
56  *
57  * Revision 1.49 2006/01/13 21:09:41 deph
58  * Fixed minor memory leak
59  *
60  * Revision 1.48 2006/01/13 20:44:40 deph
61  * Fixed small memory leak
62  *
63  * Revision 1.47 2005/12/19 15:47:37 deph
64  * Grabbing rowsize from St_db_maker and passing it on to StDbTableDescriptor (ssdPadding)
65  *
66  * Revision 1.46 2005/12/06 21:35:43 deph
67  * Cleaned up to remove warnings
68  *
69  * Revision 1.45 2004/07/14 18:46:51 perev
70  * UInt=>Int for new ROOT
71  *
72  * Revision 1.44 2004/01/14 23:13:08 fisyak
73  * Replace ostringstream => StString
74  *
75  * Revision 1.43 2003/09/15 19:16:39 porter
76  * added #include <sstream> to fix rh7.2 compile problem introduced with recent fix
77  * for rh8 compilation.
78  *
79  * Revision 1.42 2003/09/12 01:48:06 porter
80  * removed all strstream objects in favor of stringstream+string directly
81  *
82  * Revision 1.41 2003/09/02 17:55:35 perev
83  * gcc 3.2 updates + WarnOff
84  *
85  * Revision 1.40 2003/01/08 19:43:10 perev
86  * CleanUp
87  *
88  * Revision 1.39 2002/02/25 19:21:51 porter
89  * removed <<ends from prodTime protection on run queries
90  *
91  * Revision 1.38 2002/02/25 17:52:10 porter
92  * prodTime check for run level queries
93  *
94  * Revision 1.37 2002/02/22 22:17:43 porter
95  * run test added on runs>=year1
96  *
97  * Revision 1.36 2002/02/20 04:01:46 porter
98  * changed test on runNumber from !=0 to >0 for initiating query by runNumber
99  *
100  * Revision 1.35 2002/01/15 17:15:36 porter
101  * moved timestamp translation to a separate method
102  *
103  * Revision 1.34 2001/12/21 04:55:31 porter
104  * changed some ostrstream usage for insure tests
105  *
106  * Revision 1.33 2001/10/30 21:59:32 porter
107  * same timestamp fix for runlevel query... but works..
108  *
109  * Revision 1.32 2001/10/30 20:43:29 porter
110  * timestamp set for failure on query by runNumber
111  *
112  * Revision 1.31 2001/10/26 21:40:03 porter
113  * added protection for query by runNumber until Victor can implement his side
114  *
115  * Revision 1.30 2001/10/26 15:44:02 porter
116  * add query by runNumber
117  *
118  * Revision 1.29 2001/10/24 04:05:56 porter
119  * added zombie designation per Victor's suggestion
120  *
121  * Revision 1.28 2001/09/13 16:54:54 porter
122  * propogate falvor by table through the brokery
123  *
124  * Revision 1.27 2001/02/09 23:07:16 porter
125  * replaced several ostrstream into buffer for root+solarisCC5 iostream
126  * with ostrstream creating the buffer
127  *
128  * Revision 1.26 2001/01/22 18:40:24 porter
129  * Added a wrapper for StMessage so one can use it in StDbLib
130  *
131  * Revision 1.25 2000/11/03 18:57:53 porter
132  * modified sanity check from "IsNode()" to the results of a dynamic_cast
133  * this check prevents mistaking a directory for a table
134  *
135  * Revision 1.24 2000/08/15 22:53:14 porter
136  * Added 2 write methods.
137  * - 1 works once "list" is requested from database
138  * - 1 works just by specifying the full path from which
139  * the code extracts the database name.
140  *
141  * Revision 1.23 2000/06/30 02:00:42 porter
142  * fixed memory leak introduced when making sure top level returned to
143  * offline is always a database type name
144  *
145  * Revision 1.22 2000/06/14 13:39:05 didenko
146  * Add ClassDef/ClassImp
147  *
148  * Revision 1.21 2000/06/05 22:13:53 vanyashi
149  * added const needed for tableDescriptor
150  *
151  * Revision 1.20 2000/04/25 18:27:48 porter
152  * Added flavor and production time as query fields to pass to db-api
153  *
154  * Revision 1.19 2000/04/14 14:46:41 fine
155  * new method for Victor has been introduced
156  *
157  * Revision 1.18 2000/04/13 20:22:57 porter
158  * - reconnected tableDescriptor that had been broken via St_tableDescriptor.
159  * - added unix timestamp as standard
160  * - top node returned via InitConfig will be a database type
161  *
162  * Revision 1.17 2000/04/04 14:04:07 perev
163  * table descriptor modif
164  *
165  * Revision 1.16 2000/03/26 16:47:13 fine
166  * Adjusted to ROOT 2.24
167  *
168  * Revision 1.15 2000/03/04 18:56:20 porter
169  * fixed return of endtime, it was returning beginTime for both begin & end
170  *
171  * Revision 1.14 2000/02/28 15:24:19 porter
172  * add more StDbLib methods to broker: this time, StDbManager::closeAllConnections()
173  *
174  * Revision 1.13 2000/02/14 23:36:36 porter
175  * fixed unsigned int <-> int comparison & timestamp string
176  *
177  * Revision 1.12 2000/01/31 17:11:18 porter
178  * fix break caused by the interaction design between
179  * 'StRoot/St_base/tableDescriptor.h' & 'StDbBroker::Descriptor'
180  * Now StDbBroker::Descriptor==tableDescriptor_st
181  * And StDbBroker::GetTableDescriptor() returns abstract StTableDescriptorI*
182  * Interface to StDbLib is (and was) handle correctly.
183  * StDbBroker is now tied to StRoot/St_base via tableDescriptor.h
184  * No problems would have occured if St_base interactions were based
185  * on StTableDesciptorI in the first place.
186  *
187  * Revision 1.11 2000/01/27 20:30:40 porter
188  * cleaned up dtor & error logic
189  *
190  * Revision 1.10 2000/01/27 05:56:03 porter
191  * update for compiling on CC5+HPUX-aCC+KCC
192  *
193  * Revision 1.9 2000/01/24 15:12:19 porter
194  * verbose check before resetting StDbManager verbose setting
195  * + timestamp check from St_db_Maker where time and date are
196  * separate integers.
197  *
198  * Revision 1.8 2000/01/19 20:21:48 porter
199  * change of TableIter to StDbTableIter
200  *
201  * Revision 1.7 2000/01/14 14:49:10 porter
202  * set verbose level for checking, added $Id & $Logs, & made node container
203  * more robust for interactions with StDbLib
204  *
205  * Revision 1.6 2000/01/10 20:31:16 porter
206  * modified StDbBroker to be an interface to the DB-interface, StDbLib.
207  * - old functionality is retained for the short-term & modifications
208  * are extensions
209  *
210  *
211  **************************************************************************/
212 #include <StString.h>
213 #include <Stiostream.h>
214 #include <stdlib.h>
215 
216 #include "TString.h"
217 #include "StMessMgr.h"
218 
219 // needed for GetComments
220 #include "TROOT.h"
221 #include "TBuffer.h"
222 #include "TClass.h"
223 #include "St_Table.h"
224 #include "TRealData.h"
225 #include "TDataMember.h"
226 #include "TDataType.h"
227 
228 #include "StDbBroker.h"
229 #include "StDbLib/StDbManager.hh"
230 #include "StDbLib/StDbConfigNode.hh"
231 #include "StDbLib/StDbTable.h"
232 #include "dbNodes.h"
233 #include "StDbLib/StDbTableIter.hh"
234 #include "StDbLib/StDbBuffer.h" // for inputting the descriptor
235 #include "StDbLib/StDbTableDescriptor.h"
236 #include "StDbWrappedMessenger.hh"
237 
238 #define __CLASS__ "StDbBroker"
239 
240 //
241 ClassImp(StDbBroker)
242 //______________________________________________________________________________
243 //the only remaining St_Table dependence is in this function
244 char **StDbBroker::GetComments(St_Table *parentTable)
245 {
246  if (!parentTable) {
247  // MakeZombie();
248  return NULL;
249  }
250  TClass *classPtr = parentTable->GetRowClass();
251  if (!classPtr) return NULL;
252 
253  if (!classPtr->GetListOfRealData()) classPtr->BuildRealData();
254 
255  TIter next(classPtr->GetListOfDataMembers());
256  TDataMember *member = 0;
257  UInt_t i=0, j=0;
258  char **ElementComment = new char*[m_nElements];
259 
260  while ( (member = (TDataMember *) next()) ) {
261  ElementComment[i] = strdup(member->GetTitle());
262  // strip trailing blanks from Comments (they are stripped in mysql anyway)
263  j=strlen(ElementComment[i]);
264  while (j != 0 && ElementComment[i][j-1] == ' ') j--;
265  ElementComment[i][j]='\0';
266  i++;
267  }
268  return ElementComment;
269 }
270 
271 //_____________________________________________________________________________
272 StDbBroker::StDbBroker(): m_structName(0), m_tableName(0), m_requestTimeStamp(0), m_tableVersion(0), m_database(0), m_ParentType(0), m_isVerbose(0), m_Nodes(0), m_Tree(0), m_flavor(0), m_prodTime(0) {
273 
274  m_runNumber=0;
275  m_node = 0;
276  mgr=StDbManager::Instance();
278  mgr->setMessenger(ms);
279 
280 }
281 
282 //_____________________________________________________________________________
283 StDbBroker::~StDbBroker(){
284  printStatistics();
285  if(m_tableName) delete [] m_tableName;
286  if(m_structName) delete [] m_structName;
287  if(m_tableVersion) delete [] m_tableVersion;
288  if(m_database) delete [] m_database;
289  if(m_flavor) delete [] m_flavor;
290  SafeDelete(m_Nodes);
291  SafeDelete(m_Tree);
292  SafeDelete(mgr);
293 }
294 
295 //_____________________________________________________________________________
296 void StDbBroker::printStatistics(){
297  if(m_Tree)m_Tree->printNumberStats();
298  if(mgr) mgr->printTimeStats();
299 }
300 //_____________________________________________________________________________
301 
302 void StDbBroker::CloseAllConnections(){
303  if(mgr){
304  mgr->closeAllConnections();
305 // StDbBroker::printStatistics();
306  }
307 // cout<<"MPD:GOT HERE connection to db closed"<<endl;
308 };
309 
310 //_____________________________________________________________________________
311 
312 void StDbBroker::Release(){
313 //a general close (cut loose function) for use by
314 //st_db_maker (Victor did not want to call CloseAllConnections to
315 //mainain abstraction) Also could add other utilities here later on.
316  StDbBroker::CloseAllConnections();
317 // cout<<"MPD:connection to db closed"<<endl;
318 }
319 
320 //_____________________________________________________________________________
321 //void StDbBroker::Fill(void * pArray, const char **Comments)
322 //{
323 // if ( m_nElements==0 ) return;
324  //char **Comments = new char*[m_nElements];
325  //TString Comment;
326 
327 // UInt_t i;
328 // for (i=0;i<m_nElements;i++) {
329 
330 // if(m_descriptor[i].fDimensions>1)
331 // {
332 // LOG_ERROR<<"dim>1, can't handle yet"<<endm;
333 // return;
334 // }
335 
336 // m_descriptor[i].fColumnName[31]='\0';
337 // }
338 
339 // Int_t date, time;
340  //VP TDatime::GetDateTime(m_DateTime, date, time);
341 // date = m_DateTime[0]; time = m_DateTime[1];
342 // uint datetime[4]={0,0,0,0};
343 // datetime[0]=date;
344 // datetime[1]=time;
345 
346 // ::DbFill(datetime, (const char*) m_tableName, (const char*) m_structName, m_nElements,m_descriptor,Comments,m_nRows,m_sizeOfStruct,pArray);
347 
348 // delete [] Comments;
349 //}
350 
351 //_____________________________________________________________________________
352 const char *StDbBroker::GetFlavor()
353 {
354  return (m_node)? m_node->getFlavor():0;
355 }
356 
357 //_____________________________________________________________________________
359 StDbBroker::GetTableDescriptor(){
360 
361 StDbBuffer buff;
362 StDbTableDescriptor* descriptor = new StDbTableDescriptor();
363 unsigned int numElements = mdescriptor->NumberOfColumns();
364 
365  for(int i=0;i<(int)numElements;i++){
366 
367  buff.WriteScalar(mdescriptor->ColumnName(i),"name");
368 
369  // array designation & lengths
370  if(!mdescriptor->Dimensions(i)){
371  buff.WriteScalar("1","length");
372  } else {
373  StString os;
374  const unsigned int* index = mdescriptor->IndexArray(i);
375  for(int k=0; k<(int)mdescriptor->Dimensions(i)-1;k++)
376  os<<index[k]<<",";
377  os<<index[mdescriptor->Dimensions(i)-1];
378  const char* lengthString = (os.str()).c_str();
379  buff.WriteScalar(lengthString,"length");
380  // os.freeze(0);
381  // delete [] lengthString;
382  }
383 
384  // position in struct
385  buff.WriteScalar(i+1,"position");
386 
387  // Type identification
388  switch ((EColumnType)mdescriptor->ColumnType(i)) {
389  case kFloat:
390  {
391  buff.WriteScalar("float","type");
392  break;
393  }
394  case kInt:
395  {
396  buff.WriteScalar("int","type");
397  break;
398  }
399  case kLong:
400  {
401  buff.WriteScalar("long","type");
402  break;
403  }
404  case kShort:
405  {
406  buff.WriteScalar("short","type");
407  break;
408  }
409  case kDouble:
410  {
411  buff.WriteScalar("double","type");
412  break;
413  }
414  case kUInt:
415  {
416  buff.WriteScalar("uint","type");
417  break;
418  }
419  case kULong:
420  {
421  buff.WriteScalar("ulong","type");
422  break;
423  }
424  case kUShort:
425  {
426  buff.WriteScalar("ushort","type");
427  break;
428  }
429  case kUChar:
430  {
431  buff.WriteScalar("uchar","type");
432  break;
433  }
434  case kChar:
435  {
436  buff.WriteScalar("char","type");
437  break;
438  }
439  default:
440  {
441  break;
442  }
443  }
444 
445  descriptor->fillElement(&buff,0); // 0 means use this .... don't check
446  // about internal schemaID's
447  buff.Raz();
448 
449  }
450 
451 return descriptor;
452 }
453 
454 void
455 StDbBroker::addBlacklistedDomain(const char* domainName) {
456  mgr->blacklistDbDomain(domainName);
457 }
458 
459 //_____________________________________________________________________________
460 void
461 StDbBroker::SetDateTime(Int_t date, Int_t time)
462 {
463  // 20000127 002502
464  m_DateTime[0] = date;
465  m_DateTime[1]= time;
466 
467  StString ds;
468  StString ts;
469 
470  ts<<m_DateTime[1];
471  int len = (ts.str()).length();
472  ds<<m_DateTime[0];
473  for(int i=0;i<6-len;i++)ds<<"0";
474  ds<<m_DateTime[1];
475 
476  const char* dateTime = (ds.str()).c_str();
477  mgr->setRequestTime(dateTime);
478 }
479 
480 //____________________________________________________________________________
481 void StDbBroker::SetProdTime(UInt_t ptime){
482  if(m_Tree)m_Tree->setProdTime(ptime);
483  m_prodTime = ptime;
484 }
485 
486 //____________________________________________________________________________
487 void StDbBroker::AddProdTimeOverride(UInt_t ptime, char* dbType, char* dbDomain) {
488  if (m_Tree) {
489  m_Tree->setProdTimeOverride(ptime, dbType, dbDomain);
490  //std::cout << "SPECIAL: StDbBroker - setting override " << dbType << " / " << dbDomain << " = " << ptime << "\n";
491  } else {
492  //std::cout << "SPECIAL: StDbBroker - override was not set, no m_Tree! \n";
493  }
494  m_prodTimeOverride.insert( std::make_pair( std::make_pair(dbType,dbDomain), ptime ) );
495 }
496 
497 //____________________________________________________________________________
498 void StDbBroker::SetFlavor(const char* flavor){
499 
500  if(!flavor)return;
501  m_flavor = new char[strlen(flavor)+1];
502  strcpy(m_flavor,flavor);
503  if(m_Tree)m_Tree->setFlavor(m_flavor);
504 
505 }
506 
507 //____________________________________________________________________________
508 void StDbBroker::SetTableFlavor(const char* flavor, int tabID, int parID)
509 {
510  StDbNode* anode = m_Nodes->getNode(tabID);
511  StDbTable* node=dynamic_cast<StDbTable*>(anode);
512 
513  if(!node) return;
514  node->setFlavor(flavor);
515 }
516 
517 
518 //____________________________________________________________________________
519 void * StDbBroker::Use(int tabID, int parID)
520 {
521 
522  // This is an "Offline" requirement of only 31 char per element name
523  // UInt_t i;
524  // for (i=0;i<m_nElements;i++) {
525  // m_descriptor[i].fColumnName[31]='\0';
526  // }
527  void* pData = 0;
528  m_nRows = 0;
529  SetNRows(0);
530  SetBeginDate(19950101);
531  SetBeginTimeStamp(788918400);
532  SetBeginTime(0);
533  SetEndDate(20380101);
534  SetEndTimeStamp(2145916799);
535  SetEndTime(0);
536  SetZombie(false);
537 
538  //Store the the TTABLE padded size
540  TD->storeRowSize(m_sizeOfStruct);
541  delete TD;
542 
543  StDbNode* anode = m_Nodes->getNode(tabID);
544  m_node=dynamic_cast<StDbTable*>(anode);
545 
546  if(!m_node) return pData;
547  if(!m_node->hasDescriptor())m_node->setDescriptor(GetTableDescriptor());
548 
549  // I would do this in a separate function but this would require
550  // redoing it all with
551 
552  bool fetchStatus;
553  if(m_node->getDbType()==dbRunLog &&
554  m_node->getDbDomain() != dbStar &&
555  m_runNumber>1000000 ){
556  fetchStatus=UseRunLog(m_node);
557  } else {
558  fetchStatus=mgr->fetchDbTable(m_node);
559  }
560 
561  // success or failure yields an endtime ... so get it.
562 
563  if(fetchStatus){
564 
565  char* thisTime;
566  m_endTimeStamp = m_node->getEndTime();
567  thisTime = m_node->getEndDateTime();
568  makeDateTime(thisTime,m_EndDate,m_EndTime);
569  m_nRows= m_node->GetNRows();
570  pData = m_node->GetTableCpy(); // gives the "malloc'd version"
571 
572  m_beginTimeStamp = m_node->getBeginTime();
573  thisTime = m_node->getBeginDateTime();
574  makeDateTime(thisTime,m_BeginDate,m_BeginTime);
575 
576  } else {
577  SetZombie(true);
578  }
579 
580 return pData;
581 }
582 
583 //_____________________________________________________________________________
584 void StDbBroker::makeDateTime(const char* dateTime,Int_t & iDate,Int_t & iTime){
585 
586  char* tmp1 = new char[strlen(dateTime)+1];
587  char* tmp2 = new char[strlen(dateTime)+1];
588  strcpy(tmp1,dateTime);
589  strcpy(tmp2,tmp1); tmp1[8]='\0';tmp2+=8;
590 
591  iDate = atoi(tmp1);
592  iTime = atoi(tmp2);
593  delete [] tmp1; tmp2-=8; delete [] tmp2;
594 
595 }
596 
597 //_____________________________________________________________________________
598 bool StDbBroker::UseRunLog(StDbTable* table){
599 
600  unsigned int prodTime=table->getProdTime();
601  StString rq;
602  rq<<" where runNumber="<<m_runNumber;
603 
604  if(prodTime==0){
605  rq<<" AND deactive=0 ";
606  } else {
607  rq<<" AND (deactive=0 OR deactive>="<<prodTime<<")";
608  rq<<" AND unix_timestamp(entryTime)<="<<prodTime;
609  }
610 
611  bool fetchStatus=mgr->fetchDbTable(table,(char*)(rq.str()).c_str());
612 
613 
614 return fetchStatus;
615 }
616 
617 //_____________________________________________________________________________
618 Int_t StDbBroker::WriteToDb(void* pArray, int tabID){
619 #define __METHOD__ "WriteToDb(pArray,tabID)"
620 
621  StString em;
622  if(!pArray || tabID==0) {
623  em<<" Write Failed -> either data-array or tableID is incomplete";
624  return mgr->printInfo((em.str()).c_str(),dbMErr,__LINE__,__CLASS__,__METHOD__);
625  }
626  if(!m_Nodes){
627  em<<"Write Failed -> incomplete table context. Try InitConfig() 1st";
628  return mgr->printInfo((em.str()).c_str(),dbMErr,__LINE__,__CLASS__,__METHOD__);
629  }
630  StDbNode* anode= m_Nodes->getNode(tabID);
631  StDbTable* table=dynamic_cast<StDbTable*>(anode);
632  if(!table){
633  em<<"Write Failed -> tableID="<<tabID<<" is not known ";
634  return mgr->printInfo((em.str()).c_str(),dbMErr,__LINE__,__CLASS__,__METHOD__);
635  }
636 
637  if(!table->hasDescriptor())table->setDescriptor(GetTableDescriptor());
638  table->SetTable((char*)pArray,m_nRows);
639 
640  // WARNING :: A Cludge -> StDbManager has separate
641  //'store' & 'request' times whilr StDbBroker does not
642  mgr->setStoreTime(mgr->getUnixCheckTime());
643  if(!mgr->storeDbTable(table))return 0;
644  return 1;
645 #undef __METHOD__
646 }
647 
648 //_____________________________________________________________________________
649 Int_t StDbBroker::WriteToDb(void* pArray, const char* fullPath, int* idList){
650 #define __METHOD__ "WriteToDb(pArray,fullPath,idList)"
651  StString em;
652 
653  if(!pArray || !fullPath) {
654  em<<" Write Failed:: either data-array or path is incomplete";
655  return mgr->printInfo((em.str()).c_str(),dbMErr,__LINE__,__CLASS__,__METHOD__);
656  }
657 
658  char* path=new char[strlen(fullPath)+1];
659  strcpy(path,fullPath);
660 
661  // chop off a trailing "/" if found
662  char* tmp=path;
663  tmp+=strlen(path)-1;
664  if(*tmp=='/')*tmp='\0';
665 
666  // Algorithm is if path = "A/B/C/D", we try to connect to
667  // databases "D", "C_D" (& "C") , "B_C" ( & "B"), "A_B" (& "A")
668  // quiting when table is found. Note, by design if database
669  // "C_D" does not exist, the DB-API tries to find database "C".
670 
671  char* a1=path;
672  char* a2;
673  char** aword = new char*[20];
674 
675  int icount=0;
676  aword[icount]=a1;
677  while((a2=strstr(a1,"/"))){
678  *a2='\0'; a2++;
679  icount++;
680  aword[icount]=a2;
681  a1=a2;
682  }
683 
684  char tmpName[128];
685  char* dbName =0;
686  StDbTable* table = 0;
687  for(int i=icount;i>0;i--){
688  if(i==icount){
689  dbName=aword[i];
690  } else {
691  sprintf(tmpName,"%s_%s",aword[i-1],aword[i]);
692  dbName=(char*)tmpName;
693  }
694  table=findTable(dbName);
695  if(table)break;
696  }
697 
698  if (!table){
699  em<<"Write Failed table="<<m_tableName<<" not found in db="<<dbName;
700  delete [] path;
701  delete [] aword;
702  return mgr->printInfo((em.str()).c_str(),dbMErr,__LINE__,__CLASS__,__METHOD__);
703  }
704 
705  table->setDescriptor(GetTableDescriptor());
706  table->SetTable((char*)pArray,m_nRows,idList);
707  mgr->setStoreTime(mgr->getUnixCheckTime());
708  bool iswritten=mgr->storeDbTable(table);
709  delete table;
710 
711  delete [] aword;
712  return (iswritten) ? 1 : 0;
713 #undef __METHOD__
714 }
715 
716 //_____________________________________________________________________________
717 StDbTable*
718 StDbBroker::findTable(const char* databaseName){
719 
720  StDbTable* table=0;
721  StDbConfigNode* node= mgr->initConfig(databaseName);
722  StDbTable* tmp=node->addDbTable(m_tableName);
723  if(tmp)table=new StDbTable(*tmp);
724  delete node;
725 
726  return table;
727 }
728 
729 //_____________________________________________________________________________
730 void * StDbBroker::Use()
731 {
732 //convert event datetime to date and time
733  Int_t date, time;
734 //VP TDatime::GetDateTime(m_DateTime, date, time);
735  date = m_DateTime[0]; time = m_DateTime[1];
736  uint datetime[4]={0,0,0,0};
737  datetime[0]=date;
738  datetime[1]=time;
739  uint nRows=0;
740 
741 
742  UInt_t i;
743  for (i=0;i<m_nElements;i++) {
744  m_descriptor[i].fColumnName[31]='\0';
745  }
746 
747  // Check if request is a "hierarchy" : if so send request to "params" DB
748  char* id = strstr(m_tableName,"_hierarchy");
749  if(id){
750  char* tmpName = new char[strlen(m_tableName)+1];
751  strcpy(tmpName,m_tableName);
752  char* id2 = strstr(tmpName,"_hierarchy");
753  *id2 = '\0';
754  if(strcmp(tmpName,"Calib")==0){
755  m_database = new char[strlen("Calibrations_tpc")+1];
756  strcpy(m_database,"Calibrations_tpc");
757  } else if(strstr(tmpName,"Geom")){
758  m_database = new char[strlen("Geometry_tpc")+1];
759  strcpy(m_database,"Geometry_tpc");
760  } else if(strstr(tmpName,"RunParam")){
761  m_database = new char[strlen("RunParams_tpc")+1];
762  strcpy(m_database,"RunParams_tpc");
763  } else {
764  m_database = new char[strlen("params")+1];
765  strcpy(m_database,"params");
766  }
767  *id2='_';
768  delete [] tmpName;
769  }
770 
771  void *pDbData;
772 
773  if(id || strcmp(m_database,"params")==0){
774 
775  cout << "Looking for Table "<<m_tableName<<" In Db= "<<m_database<<endl;
776 
777  pDbData = ::DbUse(&nRows, datetime, (const char*)m_tableName,(const char*)m_structName,m_nElements,m_sizeOfStruct,m_descriptor);
778 
779  } else {
780 
781  pDbData = ::DbRead(&nRows, datetime,(const char*)m_tableName,(const char*)m_structName,m_nElements,m_sizeOfStruct,m_descriptor,(const char*)m_database, (const char*)m_tableVersion );
782 
783 }
784 
785  if (pDbData==NULL)
786  {
787  SetNRows(0);
788  SetBeginDate(19950101);
789  SetBeginTime(0);
790  SetEndDate(20380101);
791  SetEndTime(0);
792  }
793  else
794  {
795  SetNRows((UInt_t)nRows);
796  SetBeginDate(datetime[0]);
797  SetBeginTime(datetime[1]);
798  SetEndDate (datetime[2]);
799  SetEndTime (datetime[3]);
800  }
801 
802  return pDbData;
803 }
804 //_____________________________________________________________________________
805 
806 dbConfig_st*
807 StDbBroker::InitConfig(const char* configName, int& numRows, char* versionName)
808 {
809 
810  if(m_Nodes){
811  delete m_Nodes;
812  m_Nodes = 0;
813  }
814 
815 if(m_Tree) delete m_Tree;
816 
817  char* dbTypeName=0;
818  char* dbDomainName=0;
819 if(m_ParentType) delete [] m_ParentType;
820 m_ParentType = 0;
821 
822  if(mgr->getDataBaseInfo(configName,dbTypeName,dbDomainName)){
823  if(strcmp(dbDomainName,"Star")!=0){
824  int tlen = strlen(dbTypeName);
825  m_ParentType = new char[tlen+1];
826  strcpy(m_ParentType,dbTypeName);
827  }
828  }
829 
830  delete [] dbTypeName;
831  delete [] dbDomainName;
832 
833  if(m_isVerbose)mgr->setVerbose(true);
834 if(!versionName){
835  m_Tree=mgr->initConfig(configName,"reconV0",1); // 1=don't get db-descriptors
836 }else{
837  m_Tree=mgr->initConfig(configName,versionName,1);//1=don't get db-descriptors
838 }
839 
840  dbConfig_st* configTable = 0;
841  if(!m_Tree) return configTable;
842 
843  if(m_prodTime!=0) {
844  m_Tree->setProdTime(m_prodTime);
845  for (std::map<std::pair<char*,char*>, unsigned int>::iterator it = m_prodTimeOverride.begin(); it != m_prodTimeOverride.end(); it++ ) {
846  //if ( (*it).first.first ) {
847  //std::cout << "SPECIAL: StDbBroker - Setting override to m_Tree : " << (*it).first.first << " _ " << (*it).first.second << " = " << (*it).second << "\n";
848  //} else {
849  //std::cout << "SPECIAL: StDbBroker - Setting override to m_Tree : [all domains] _ " << (*it).first.second << " = " << (*it).second << "\n";
850  //}
851  m_Tree->setProdTimeOverride((*it).second, (*it).first.first, (*it).first.second);
852  }
853  }
854  if(m_flavor)m_Tree->setFlavor(m_flavor);
855 
856  if(m_isVerbose){
857  cout << "****************************************************************"<<endl;
858  cout << "*** Will Print the Tree "<<endl;
859  bool verbCheck = mgr->IsVerbose();
860  if(!verbCheck)mgr->setVerbose(true);
861  m_Tree->printTree(0);
862  if(!verbCheck)mgr->setVerbose(false);
863  cout << "*** End Print the Tree "<<endl;
864  cout << "****************************************************************"<<endl;
865  };
866 numRows = 0;
867 
868 if(!buildNodes(m_Tree,0)) return configTable;
869 
870 //numRows = m_Nodes->getNumNodes()-1;
871 return buildConfig(numRows);
872 }
873 
874 //_____________________________________________________________________________
875 
876 int
877 StDbBroker::buildNodes(StDbConfigNode* parentNode, int pID){
878 
879 if(!parentNode) return 0;
880 if(!m_Nodes) {
881  m_Nodes=new dbNodes;
882  m_Nodes->addNode(parentNode,0);
883 }
884 
885 int cID;
886 
887 // check for tables in this Node
888  if( (parentNode->hasData()) ){
889  StDbTableIter* itr = parentNode->getStDbTableIter();
890  while( !itr->done() ) { m_Nodes->addNode(itr->next(),pID); }
891  delete itr;
892  }
893 
894  StDbConfigNode* next;
895 
896 // check for children of this Node
897  if((parentNode->hasChildren())){
898  next=parentNode->getFirstChildNode();
899  cID=m_Nodes->addNode(next,pID);
900  if(!buildNodes(next, cID))return 0;
901  }
902 
903 // check for siblings of this Node
904  int parID;
905  if( (next=parentNode->getNextNode()) ){
906  parID=m_Nodes->getParentID(pID);
907  cID=m_Nodes->addNode(next,parID);
908  if(!buildNodes(next, cID))return 0;
909  }
910 
911 return 1;
912 }
913 
914 //_____________________________________________________________________________
916 StDbBroker::buildConfig(int& numRows){
917 
918 dbConfig_st* cTab= 0;
919 m_Nodes->reset();
920 int numNodes = m_Nodes->getNumNodes();
921 
922 StDbNode* node;
923 StDbNode* parent;
924 char* parName;
925 char* nodeName;
926 char* id;
927 unsigned int parsize=sizeof(cTab[0].parname)-1;
928 unsigned int tabsize=sizeof(cTab[0].tabname)-1;
929 unsigned int typsize=sizeof(cTab[0].tabtype)-1;
930 int parID;
931 int cRow;
932 
933  numRows = numNodes;
934 
935  cTab=(dbConfig_st*)calloc(numRows,sizeof(dbConfig_st));
936  node = m_Nodes->getNode(0);
937  strncpy(cTab[0].tabname,node->printName(),tabsize);
938  cTab[0].tabname[tabsize]='\0';
939  strncpy(cTab[0].tabtype,".node",typsize);
940  cTab[0].tabtype[typsize]='\0';
941  cTab[0].parID=cTab[0].tabID=0;
942  cRow = 1;
943 
944  if(m_ParentType){
945  strncpy(cTab[0].parname,m_ParentType,parsize);
946  } else {
947  strncpy(cTab[0].parname,node->printName(),parsize);
948  }
949  cTab[0].parname[parsize]='\0';
950 
951  for(int i=1; i<numNodes;i++){
952 
953  node = m_Nodes->getNode(i);
954  parent= m_Nodes->getParent(i);
955  parID = m_Nodes->getParentID(i);
956 
957  nodeName = node->printName();
958  parName = parent->printName();
959 
960  strncpy(cTab[cRow].parname,parName,parsize);
961  cTab[cRow].parname[parsize]='\0';
962  strncpy(cTab[cRow].tabname,nodeName,tabsize);
963  cTab[cRow].tabname[tabsize]='\0';
964 
965  id=cTab[cRow].tabtype; *id='.'; id++;
966  if(node->IsTable()){
967  strcpy(id,((StDbTable*)node)->printCstructName());
968  } else {
969  strcpy(id,"node");
970  }
971  cTab[cRow].tabtype[typsize]='\0';
972 
973  cTab[cRow].tabID=i;
974  cTab[cRow].parID=parID;
975  cRow++;
976  }
977 
978 if(m_isVerbose){
979  cout <<"****************************************************"<<endl;
980  cout <<"********* Will print dbConfig table "<<endl;
981  for(int k=0; k<numRows; k++) {
982  cout << "row "<<k<<" name =" << cTab[k].tabname<< " tid= "<< cTab[k].tabID;
983  cout << " type = "<<cTab[k].tabtype;
984  cout << " parent =" << cTab[k].parname << " pid= " << cTab[k].parID<<endl;
985  }
986  cout <<"********* End print dbConfig table "<<endl;
987  cout <<"****************************************************"<<endl;
988 }
989 
990 return cTab;
991 }
992 
993 //_____________________________________________________________________________
994 int StDbBroker::DbInit(const char * dbName) { return ::DbInit(dbName) ;}
995 
996 #undef __CLASS__
virtual void SetTable(char *data, int nrows, int *idList=0)
calloc&#39;d version of data for StRoot
Definition: StDbTable.cc:550
Definition: TTable.h:48
static StDbManager * Instance()
strdup(..) is not ANSI
Definition: StDbManager.cc:155