00001 #include <stdio.h>
00002 #include "Stypes.h"
00003 #include "StTree.h"
00004 #include "TRegexp.h"
00005 #include "TDirIter.h"
00006 #include "TKey.h"
00007 #include "TError.h"
00008 #include <stdlib.h>
00009
00010 #ifdef __RFIO__
00011 #include "TRFIOFile.h"
00012 #endif
00013
00014 void DummyErrorHandlerFunc(int , Bool_t , const char *, const char *){;}
00015
00016
00017
00018
00019 const char* TFOPT[9] = {"0","READ","RECREATE","UPDATE",
00020 "0","READ","RECREATE","UPDATE",0};
00021 const char RWU[] = "0rwu0rnu0rcu";
00022 char IOMODE[] = "0";
00023
00024 Int_t StIO::fgDebug = 0;
00025
00026 static inline Int_t IntOMode(char ciomode)
00027 {
00028 char *c=(char *)strchr(RWU,tolower(ciomode));
00029 return (c) ? (c-RWU)&3 : 0;
00030 }
00031
00032 #ifdef __RFIO__
00033 extern "C" {
00034 int rfio_open(const char *filepath, int flags, int mode);
00035 int rfio_close(int s);
00036 int rfio_read(int s, char *ptr, int size);
00037 int rfio_write(int s, char *ptr, int size);
00038 int rfio_lseek(int s, int offset, int how);
00039 int rfio_access(const char *filepath, int mode);
00040 int rfio_unlink(const char *filepath);
00041 int rfio_parse(const char *name, char **host, char **path);
00042 };
00043 #endif
00044
00045 class Cat : public TNamed {
00046 public:
00047 Cat(){fNGeant=0;fNKeys=0;fNRecs=0;fSize=0;fNFiles=0;};
00048 double fSize;
00049 int fNGeant;
00050 int fNKeys;
00051 int fNRecs;
00052 int fNFiles;
00053 };
00054
00055 ClassImp(StIOEvent)
00056 StIOEvent::StIOEvent():TObject(){fObj=(TObject*)(-1);};
00057
00058 void StIOEvent::Browse(TBrowser *b)
00059 {
00060 if (b && fObj && (Long_t)fObj != (-1)) fObj->Browse(b);
00061 }
00062
00063 void StIOEvent::Streamer(TBuffer &R__b)
00064 {
00065
00066
00067 if (R__b.IsReading()) {
00068 Version_t R__v = R__b.ReadVersion(); if (R__v) { }
00069 TObject::Streamer(R__b);
00070 R__b >> fObj;
00071 } else {
00072 R__b.WriteVersion(StIOEvent::IsA());
00073 TObject::Streamer(R__b);
00074 R__b << fObj;
00075 }
00076 }
00077
00078
00079
00080 Int_t StIO::Write(TFile *file, const StUKey &ukey, TObject *obj)
00081 {
00082 assert(file);
00083 if (!obj) return kStWarn;
00084
00085 StIOEvent event;
00086 event.fObj = obj; event.SetUniqueID(ukey.GetSum());
00087 TFile *bakfile = gFile; TDirectory *bakdir = gDirectory; file->cd();
00088
00089 event.Write(ukey.GetKey(),TObject::kOverwrite|TObject::kSingleKey);
00090 gFile->Flush();
00091 gFile=bakfile; gDirectory=bakdir;
00092 return 0;
00093 }
00094
00095 TObject *StIO::Read(TFile *file, const char *name)
00096 {
00097 TObject *toread=0;
00098 TKey *key = 0;
00099 assert(file);
00100
00101 TFile *bakfile = gFile; TDirectory *bakdir = gDirectory; file->cd();
00102
00103 if (!gFile) { printf("<StIO::Read> No file open \n"); goto RETURN;}
00104
00105 if (name[0]=='*') {
00106 key = (TKey*)gDirectory->GetListOfKeys()->At(0);
00107 if (strcmp(".StreamerList",key->GetName())==0)
00108 key = (TKey*)gDirectory->GetListOfKeys()->At(1);
00109 }
00110 else key = (TKey*)gDirectory->GetListOfKeys()->FindObject(name);
00111
00112 if (!key) {
00113 if(fgDebug) printf("<StIO::Read> Key %s not found\n",name);
00114 goto RETURN; }
00115
00116 if (name[0]!='*' && strcmp(key->GetClassName(),"StIOEvent"))
00117 { printf("<StIO::Read> Key %s has wrong className %s\n",
00118 key->GetName(),key->GetClassName());
00119 toread = (TObject*)(-1); goto RETURN; }
00120
00121 toread = key->ReadObj(); if (!toread) toread = (TObject*)(-1);
00122
00123 RETURN: gFile=bakfile; gDirectory=bakdir; return toread;
00124 }
00125
00126 TObject *StIO::Read(TFile *file, const StUKey &ukey)
00127 {
00128 StIOEvent *event = 0;
00129 TObject *retn = 0;
00130 retn = Read(file,ukey.GetKey());
00131 if (!retn) return 0;
00132 if (retn == (TObject*)(-1)) return retn;
00133 if (retn->IsA()!=StIOEvent::Class()) return retn;
00134 event = (StIOEvent*)retn;
00135 retn = event->fObj;
00136 assert( !retn || retn==(TObject*)(-1) || event->GetUniqueID()==ukey.GetSum());
00137 delete event;
00138 return retn;
00139 }
00140
00141 Int_t StIO::GetNextKey(TFile *file, StUKey &ukey,ULong_t &handle)
00142 {
00143 TObjLink *lnk; TList *lk; const char *kname; TObject *obj;
00144 enum { kSorted = 1};
00145 assert(file);
00146
00147 TString tk = ukey.GetKey(); ukey = kUMAX;
00148 const char* prevkey = (const char*)tk;
00149 int lname = strlen(ukey.GetName())+1;
00150
00151 lk = file->GetListOfKeys(); if(!lk) return 1;
00152 if (!lk->TestBit(kSorted)) {lk->Sort(); lk->SetBit(kSorted);handle = 0;}
00153
00154
00155
00156
00157
00158
00159 if (handle) {
00160 lnk = (TObjLink*)handle;
00161 handle = 0;
00162 obj = lnk->GetObject();
00163 if (strcmp(prevkey,obj->GetName())>0) lnk = lk->FirstLink();
00164 } else {
00165 lnk = lk->FirstLink();
00166 }
00167
00168 while (lnk) {
00169 obj = lnk->GetObject();
00170 kname = obj->GetName();
00171 if (strcmp(prevkey, kname)<0) break;
00172 lnk = lnk->Next();
00173 }
00174 if (!lnk) return 1;
00175 if (strncmp(prevkey,kname,lname)) lnk = 0;
00176 if (!lnk) return 1;
00177 ukey.SetKey(kname);
00178 handle = (ULong_t)lnk;
00179 return 0;
00180 }
00181
00182 TObject *StIO::ReadNext(TFile *file, StUKey &ukey, ULong_t &handle)
00183 {
00184 if(GetNextKey(file,ukey,handle)) return 0;;
00185 return Read(file,ukey);
00186 }
00187
00188 TString StIO::RFIOName(const char *name)
00189 {
00190 TString file(name);
00191 TNamed *tn;
00192 TList *rfiomap = (TList *)gROOT->GetListOfSpecials()->FindObject(".rfiomap");
00193 if (file.Contains(".daq")) rfiomap = 0;
00194 if (rfiomap) {
00195 TIter next(rfiomap);
00196 while ((tn = (TNamed*)next())) {
00197 int n = strlen(tn->GetName());
00198 if (!n) continue;
00199 if (strncmp(file,tn->GetName(),n)) continue;
00200 file.Replace(0,0,tn->GetTitle());
00201 break;
00202 }
00203 }
00204 return file;
00205 }
00206
00207 TFile *StIO::Open(const char *name, Option_t *option,const char *title,Int_t compress)
00208 {
00209
00210
00211 TString file = RFIOName(name);
00212 if(strcmp("READ",option)==0 && !IfExi(name)) return 0;
00213 if(strcmp("read",option)==0 && !IfExi(name)) return 0;
00214 if(strcmp("Read",option)==0 && !IfExi(name)) return 0;
00215 TFile *tf = TFile::Open(file,option,title,compress);
00216 if (!tf || !tf->IsZombie()) return tf;
00217 delete tf;
00218 return 0;
00219 }
00220
00221 Int_t StIO::IfExi(const char *name)
00222 {
00223 TString file = (name);
00224
00225
00226 gSystem->ExpandPathName(file);
00227
00228
00229 ErrorHandlerFunc_t dummy = &DummyErrorHandlerFunc;
00230 ErrorHandlerFunc_t curre = SetErrorHandler(dummy);
00231
00232
00233
00234 #if 0
00235 if (!gSystem->AccessPathName(file)){
00236 SetErrorHandler(curre);
00237 return 1;
00238
00239 } else
00240 #endif
00241 {
00242 int l = file.Length();
00243 if (file(l-5,5)!=".root"){
00244 SetErrorHandler(curre);
00245 return !gSystem->AccessPathName(file);
00246 } else {
00247
00248
00249
00250
00251
00252 TFile *tf = TFile::Open(file);
00253
00254 SetErrorHandler(curre);
00255
00256
00257 int z = (!tf || tf->IsZombie());
00258 delete tf;
00259 return !z;
00260 }
00261 }
00262 }
00263
00264
00265 ClassImp(StBranch)
00266
00267
00268 StBranch::StBranch(const char *name, StTree *parent,Option_t *opt):TDataSet(name,parent)
00269 {
00270
00271 SetTitle(".StBranch");
00272 fNEvents=0;fUKey=name;fUKey=0;fIOMode=0;fTFile=0;fDebug=0;fHandle=0;
00273 SetOption(opt);
00274
00275 }
00276 StBranch::~StBranch()
00277 {
00278 Close();
00279
00280 }
00281
00282 void StBranch::SetOption(Option_t *opt)
00283 {
00284 if (opt) fOption = opt;
00285 fOption.ToUpper();
00286 }
00287
00288 void StBranch::SetIOMode(Option_t *iomode)
00289 {
00290
00291 if (!iomode || !iomode[0]) return;
00292 fIOMode = ::IntOMode(iomode[0]);
00293 fHandle=0;
00294 }
00295
00296 Option_t *StBranch::GetIOMode()
00297 {
00298 IOMODE[0]=0; if (fIOMode>0) IOMODE[0] = RWU[int(fIOMode)]; return IOMODE;
00299 }
00300
00301
00302 Int_t StBranch::SetFile(const char *file,const char *mode,int insist)
00303 {
00304 fHandle=0;
00305 fIOMode = abs(fIOMode);
00306 if (fTFile && !insist) { Error("SetFile","File is already opened");return kStWarn;}
00307 if (file && file[0]) fFile=file;
00308 if (mode && mode[0]) SetIOMode(mode);
00309 return 0;
00310 }
00311
00312 Int_t StBranch::UpdateFile(const char *file)
00313 {
00314 fHandle=0;
00315 fIOMode = abs(fIOMode);
00316 TString bas[2],dir[2];
00317 TString nam(GetName()); nam.ReplaceAll("Branch","");
00318 nam.Insert(0,"."); nam += ".root";
00319 TString outFile = file; gSystem->ExpandPathName(outFile);
00320 dir[0] = gSystem->DirName (outFile);
00321 bas[0] = gSystem->BaseName(outFile);
00322
00323 if (strncmp(".none ",GetFile(),6)==0) {
00324
00325 TString ts(GetFile()); ts.Remove(0,6); SetFile(ts);
00326 }
00327
00328 dir[1] = gSystem->DirName (GetFile());
00329 bas[1] = gSystem->BaseName(GetFile());
00330
00331 if (bas[0] == bas[1] || bas[0].Contains(nam)) SetIOMode("r");
00332
00333 for (int d=0; d<2; d++) {
00334 for (int b=0; b<2; b++) {
00335 if (!bas[b].Contains(nam)) continue;
00336 char *newFile = gSystem->ConcatFileName(dir[d],bas[b]);
00337 if (StIO::IfExi(newFile)) {
00338 fFile = newFile;
00339 printf("<StBranch::UpdateFile> Branch=%s file %s\n",GetName(),newFile);
00340 delete [] newFile;
00341 return 0;
00342 } } }
00343 fIOMode = -abs(fIOMode);
00344 return 0;
00345 }
00346
00347 Int_t StBranch::SetTFile(TFile *tfile)
00348 {
00349 if (!tfile) return 0;
00350 if (fTFile==tfile) return 0;
00351 fHandle=0;
00352 if (fTFile) Close();
00353 fTFile=0;
00354 SetFile(tfile->GetName());
00355 Open();
00356 return 0;
00357 }
00358
00359
00360 void StBranch::Close(const char *)
00361 {
00362 fHandle=0;
00363 if (!fIOMode) return;
00364 if (!fTFile) return;
00365 if (strncmp(".none",GetFile(),4)==0) return;
00366 TFile *tf = fTFile;
00367 fTFile = 0;
00368 TString ts(tf->GetTitle());
00369 int idx = ts.Index("StBranch=Y");
00370 assert (idx>=0);
00371 ts.Replace(idx+9,1,"");
00372 tf->SetTitle(ts);
00373 if (ts.Contains("StBranch=Y")) return;
00374 tf->Close("");
00375 printf("** <StBranch::Close> Branch=%s \tFile=%s \tClosed **\n"
00376 ,GetName(),(const char*)fFile);
00377 delete tf;
00378 if (!(fIOMode&2)) return;
00379 ts = GetFile();
00380 ts.Replace(0,0,".none ");
00381 SetFile((const char*)ts);
00382 }
00383
00384 const char *StBranch::GetFile()
00385 {
00386 TString dir(fFile);
00387 int kase=0;
00388 if (!fFile.IsNull()) kase = 2;
00389 if (kase && fFile[fFile.Length()-1]=='/') kase = 1;
00390
00391 if (kase<2) {
00392 fFile=GetName(); fFile.ReplaceAll("Branch",""); fFile+=".root";
00393 StTree *tree = (StTree*)GetParent();
00394 if (tree) {
00395 const char* base = tree->GetBaseName();
00396 if (base) {fFile.Insert(0,"."); fFile.Insert(0,base);}}
00397 if (kase==1) fFile.Insert(0,dir);
00398 }
00399
00400 return (const char*)fFile;
00401 }
00402
00403
00404
00405 Int_t StBranch::Open()
00406 {
00407 if (fIOMode<=0) return 0;
00408 if (fTFile) return 0;
00409 if (strncmp(".none",GetFile(),4)==0) return 1;
00410 OpenTFile();
00411 return 0;
00412 }
00413
00414 Int_t StBranch::WriteEvent(const StUKey &ukey)
00415 {
00416 int iret;
00417 if (fIOMode<=0) return 0;
00418 if (!(fIOMode & 2)) return 0;
00419 fUKey.Update(ukey,GetName());
00420 if (!fList) return kStWarn;
00421 if (!fList->First()) return kStWarn;
00422 if(Open()) return 1;
00423 fNEvents++;
00424
00425 TList savList;
00426 SetParAll(0,this,&savList);
00427 if (IsOption("const")) {
00428 StUKey uk(fUKey); uk = (UInt_t)(-2);
00429 iret = StIO::Write(fTFile,uk, fList);
00430 fIOMode = -fIOMode;
00431 } else {
00432 iret = StIO::Write(fTFile,fUKey,fList);
00433 }
00434 SetParAll(&savList);
00435
00436 return 0;
00437 }
00438
00439
00440 Int_t StBranch::GetEvent(Int_t mode)
00441 {
00442 TObject *obj=0;
00443 if (fIOMode<=0) return 0;
00444 if (!(fIOMode&1)) return 0;
00445 Delete(); if (fList) delete fList; fList=0;
00446 if(Open()) return 1;
00447
00448 if (IsOption("const")) {
00449 StUKey uk(fUKey); uk = (UInt_t)(-2);
00450 obj = StIO::Read (fTFile,uk); fIOMode = -fIOMode;
00451
00452 } else if (mode) {
00453 obj = StIO::ReadNext(fTFile,fUKey,fHandle);
00454
00455 } else {
00456 obj = StIO::Read (fTFile,fUKey);
00457 }
00458
00459 if (obj == 0) return kStEOF;
00460 if (obj == (TObject*)(-1)) return kStErr;
00461 fList = (TList*)obj;
00462
00463 SetParAll(this,this,0);
00464
00465 return 0;
00466 }
00467
00468 Int_t StBranch::ReadEvent(const StUKey &ukey)
00469 {
00470 if (fIOMode<=0) return 0;
00471 if (!(fIOMode&1)) return 0;
00472 fUKey.Update(ukey,GetName());
00473 return GetEvent(0);
00474 }
00475
00476 Int_t StBranch::NextEvent()
00477 {
00478 if (fIOMode<=0) return 0;
00479 if (!(fIOMode&1)) return 0;
00480 Clear();
00481 return GetEvent(1);
00482 }
00483
00484
00485 Int_t StBranch::NextEvent (StUKey &ukey)
00486 {
00487 if (fIOMode<=0) return 0;
00488 if (!(fIOMode&1)) return 0;
00489 Clear();
00490 fUKey.Update(ukey,GetName());
00491 int iret = GetEvent(1);
00492 ukey.Update(fUKey);
00493 return iret;
00494 }
00495
00496 void StBranch::SetParAll(TDataSet *parNew,TDataSet *parOld,TList *savList)
00497 {
00498 TDataSetIter next(parOld);
00499 TDataSet *son,*p;
00500 while ((son=next())) {
00501 p = son->GetParent();
00502 son->SetParent(parNew);
00503 if (savList) {
00504 assert(p);
00505 savList->AddFirst(son); savList->AddFirst(p);
00506 SetParAll(son,son,savList);
00507 }
00508 }
00509 }
00510
00511 void StBranch::SetParAll(TList *savList)
00512 {
00513 assert(savList);
00514 TDataSet *son,*par;
00515 while ((par=(TDataSet*)savList->First())) {
00516 savList->Remove(par);
00517 son = (TDataSet*)savList->First(); assert(son);
00518 savList->Remove(son);
00519 son->SetParent(par);
00520 }
00521 }
00522
00523 void StBranch::OpenTFile()
00524 {
00525 if (fTFile) return;
00526 fHandle = 0;
00527 TFile *tf= gROOT->GetFile(GetFile());
00528 fTFile = tf;
00529 if (!fTFile) {
00530 fTFile = StIO::Open(GetFile(),TFOPT[int(fIOMode)],GetName());
00531
00532 }
00533 if (!fTFile) {
00534 Error("OpenTFile","File %s NOT OPENED ***\n",GetFile());
00535 Error("OpenTFile","Branch %s desactivated ***\n",GetName());
00536 delete fTFile; fTFile=0; SetIOMode("0");
00537 } else {
00538 TString ts(fTFile->GetTitle());
00539 if (ts.Contains("StBranch="))
00540 { ts.ReplaceAll("StBranch=","StBranch=Y");}
00541 else
00542 { ts += " StBranch=Y";}
00543 fTFile->SetTitle(ts);
00544 if (tf) return;
00545
00546 printf("** <StBranch::Open> Branch=%s \tMode=%s \tFile=%s \tOpened **\n"
00547 ,GetName(),TFOPT[int(fIOMode)],(const char*)fFile);
00548
00549 }
00550 }
00551
00552 void StBranch::Clear(Option_t *)
00553 {
00554 Delete();
00555 }
00556
00557
00558 ClassImp(StTree)
00559
00560
00561 StTree::StTree(const char *name):StBranch(name)
00562 {
00563 SetTitle(".StTree");
00564 }
00565
00566
00567 StTree::~StTree()
00568 { Close(); Delete();}
00569
00570
00571 void StTree::SetIOMode(Option_t *iomode)
00572 {
00573 StBranch::SetIOMode(iomode);
00574 TDataSetIter next(this);StBranch *br;
00575 while ((br=(StBranch*)next())) { br->SetIOMode(iomode);}
00576 }
00577
00578 Int_t StTree::SetFile(const char *file,const char *mode,int insist)
00579 {
00580 if (mode && *mode) StBranch::SetIOMode(mode);
00581 if (!file || !*file) return 0;
00582
00583 if (fIOMode&1) {
00584 UpdateFile(file);
00585
00586 }
00587 if (fIOMode&2) {
00588
00589 SetBaseName(file);
00590 }
00591 return 0;
00592 }
00593
00594
00595 void StTree::Clear(Option_t*)
00596 {
00597 TDataSetIter next(this);StBranch *br;
00598 while ((br=(StBranch*)next())) { br->Clear();}
00599 }
00600
00601
00602 Int_t StTree::Open()
00603 {
00604 TDataSetIter nextA(this);StBranch *brA;
00605 while ((brA=(StBranch*)nextA())) {
00606 if (brA->GetIOMode()[0]=='0') continue;
00607 if (brA->GetTFile()) continue;
00608 brA->Open();
00609 }
00610 return 0;
00611 }
00612
00613 Int_t StTree::UpdateFile(const char *file)
00614 {
00615 TDataSetIter next(this);StBranch *br;
00616 while ((br=(StBranch*)next())) br->UpdateFile(file);
00617 return 0;
00618 }
00619
00620
00621 Int_t StTree::WriteEvent(const StUKey &ukey)
00622 {
00623 fUKey.Update(ukey,GetName()); Open();
00624 TDataSetIter next(this);StBranch *br;
00625 while ((br=(StBranch*)next())) br->WriteEvent(fUKey);
00626 fNEvents++;
00627 return 0;
00628 }
00629
00630
00631 Int_t StTree::ReadEvent(const StUKey &ukey)
00632 {
00633 Int_t iret=0,num=0;
00634 fUKey.Update(ukey,GetName()); Open();
00635 TDataSetIter next(this);StBranch *br;
00636 while ((br=(StBranch*)next())) {
00637 if (! br->fIOMode<0) continue;
00638 if (! br->fIOMode&1) continue;
00639 iret=br->ReadEvent(fUKey);
00640 if (!iret) num++;
00641 if(iret==kStErr) return kStErr;
00642 }
00643 return (num)? 0:kStEOF;
00644 }
00645
00646
00647 Int_t StTree::NextKey()
00648 {
00649 if (Open()) return kStEOF;
00650 TDataSetIter next(this); StBranch *br;
00651 StUKey minKey = kUMAX;
00652 StUKey tryKey;
00653
00654
00655 while ((br=(StBranch*)next())) {
00656 if ( br->fIOMode<0) continue;
00657 if (! br->fIOMode&1) continue;
00658 if (br->IsOption("const")) continue;
00659 tryKey.Update(fUKey,br->GetName());
00660 if (StIO::GetNextKey(br->fTFile,tryKey,br->fHandle))continue;
00661 tryKey = "";
00662 if (tryKey.Compare(minKey)<0) minKey=tryKey;
00663 }
00664 fUKey = minKey;
00665 return minKey.EOK() ? kStEOF:0;
00666 }
00667
00668 Int_t StTree::Skip(int nskip)
00669 {
00670 for (; nskip; nskip--)
00671 {
00672 int ret = NextKey();
00673 if (ret) break;
00674 }
00675
00676 return nskip;
00677 }
00678
00679 Int_t StTree::NextEvent(StUKey &ukey)
00680 {
00681 fUKey.Update(ukey,GetName());int iret=NextEvent(); ukey.Update(fUKey); return iret;
00682 }
00683
00684 Int_t StTree::NextEvent()
00685 {
00686 int iret=0,nAkt=0;
00687 TDataSetIter next(this); StBranch *br=0;
00688
00689 int kase = 0; StBranch *br0=0;
00690 while ((br=(StBranch*)next())) {
00691 switch(kase) {
00692 case 0: kase=1; br0 = br;
00693 if ( br->fIOMode<0) return kStEOF;
00694 if (! br->fIOMode&1) return kStEOF;
00695 iret = br->NextEvent();
00696 if (iret) return iret;
00697 break;
00698 case 1:
00699 if ( br->fIOMode<0) continue;
00700 if (! br->fIOMode&1) continue;
00701 iret = br->ReadEvent(br0->GetUKey());
00702 }
00703 nAkt++;
00704 }
00705
00706 return (nAkt) ? 0:kStEOF;
00707 }
00708
00709
00710 void StTree::Close(const char* opt)
00711 {
00712 Clear();
00713 fUKey = 2000;
00714 TDataSetIter next(this); StBranch *br;
00715 while ((br=(StBranch*)next())) {
00716 br->fIOMode = abs(br->fIOMode);
00717 if (br->fIOMode&2) {
00718 br->Open();
00719 TFile *tfbr = br->GetTFile(); if(!tfbr) continue;
00720 if (tfbr->IsWritable()) {
00721 TDataSet *par = GetParent(); SetParent(0);
00722 StIO::Write(tfbr,fUKey,this);
00723 SetParent(par);}
00724 }
00725 if ((opt && strcmp(opt,"keep")==0)) continue;
00726 br->Close();
00727 }
00728 }
00729
00730
00731 StTree *StTree::GetTree(TFile *file, const char *treeName)
00732 {
00733 StUKey treeKey(treeName,2000);
00734 StTree *ret = (StTree*)StIO::Read(file,treeKey);
00735 if ((Long_t)ret == -1) return 0;
00736 TDataSetIter next(ret);StBranch *br=0;
00737 while ((br=(StBranch*)next())) {
00738 br->SetIOMode("0");
00739 br->fUKey = br->GetName();
00740 br->fUKey = 0;
00741 }
00742 return ret;
00743 }
00744
00745
00746 void StTree::SetBaseName(const char *baseName,const char *dirname)
00747 {
00748 const char *dot;
00749 fBaseName = gSystem->BaseName(baseName);
00750 if (dirname && *dirname) {
00751 TString ts(dirname);
00752 if (ts[ts.Length()-1]!='/') ts += "/";
00753 ts += fBaseName;
00754 fBaseName = ts;
00755 }
00756 dot = strrchr(fBaseName.Data(),'.');
00757 if (!dot) return;
00758 int fz = (strstr(".fz .fzd .daq",dot)!=0);
00759 fBaseName.Remove(dot-fBaseName.Data());
00760 if (fz) return;
00761 dot = strrchr(fBaseName.Data(),'.');
00762 if (!dot) return;
00763 if ('0' <=dot[1] && dot[1]<='9') return;
00764 fBaseName.Remove(dot-fBaseName.Data());
00765 }
00766
00767
00768 ClassImp(StFile)
00769 StFile::StFile(const char** fileList):StFileI("StFile")
00770 {
00771 fDS = new TDataSet();
00772 fIter = -1; fKeyIter = 0;
00773 SetTitle(" nbranches=1 ");
00774 if (fileList) AddFile(fileList);
00775 }
00776
00777 StFile::~StFile()
00778 {
00779 delete fDS; fDS = 0;
00780 fIter = -1;
00781 delete fKeyIter; fKeyIter = 0;
00782 }
00783
00784 Int_t StFile::GetNextBundle()
00785 {
00786 if (!fDS) return 1;
00787 if (fIter>-1 && !fDS->At(fIter)) return 1;
00788 return (!fDS->At(++fIter));
00789
00790 }
00791
00792 Int_t StFile::GetNBundles()
00793 {
00794 return fDS->GetListSize();
00795 }
00796
00797 Int_t StFile::GetNFiles()
00798 {
00799 return fDS->GetListSize();
00800 }
00801
00802 TDataSet *StFile::GetFileDS(Int_t idx)
00803 {
00804 TDataSet *fam = fDS->At(fIter);
00805 if (!fam) return 0;
00806 TDataSet *df = fam->At(idx);
00807 if (!df) return 0;
00808 SetInfo(df);
00809 return df;
00810 }
00811
00812 const char *StFile::GetFileName(Int_t idx)
00813 {
00814 if (idx == -1) { idx=0; if (GetNextBundle()) return 0;}
00815 TDataSet *df = GetFileDS(idx);
00816 if (!df) return 0;
00817 return strstr(df->GetTitle(),"file=")+5;
00818 }
00819
00820 const char *StFile::GetFormat(Int_t idx)
00821 {
00822 TDataSet *df = GetFileDS(idx);
00823 return GetAttr(df,"format=");
00824 }
00825
00826 const char *StFile::GetCompName(Int_t idx)
00827 {
00828 TDataSet *df = GetFileDS(idx);
00829 return GetAttr(df,"branch=");
00830 }
00831
00832 Int_t StFile::AddFile(const char **fileList)
00833 {
00834 const char *file;
00835 if (!fileList) return 0;
00836 for(int i=0; (file = fileList[i]);i++){
00837 if (file) AddFile(file);
00838 }
00839 return 0;
00840 }
00841
00842 Int_t StFile::AddFile(const char *file,const char *opt)
00843 {
00844
00845
00846
00847 TString tfile,tit,base,famy;
00848 if (strpbrk(file,"*\\[]#@")) return AddWild(file,opt);
00849 int remove = 0;
00850 if (opt && *opt) {
00851 TString ts(opt);
00852 if (ts.Contains("REMOVE" ,TString::kIgnoreCase)) remove=1;
00853 if (ts.Contains("EXCLUDE",TString::kIgnoreCase)) remove=1;
00854 }
00855
00856
00857 tfile = file; gSystem->ExpandPathName(tfile);
00858
00859
00860
00861 if (!StIO::IfExi(tfile)) {
00862 Warning("AddFile","*** IGNORED *** File %s does NOT exist \n",
00863 (const char*)tfile);
00864 return kStWarn;}
00865
00866 const char* cc = strrchr(tfile,'.');
00867 if (!cc || !strstr(".root .daq .dat",cc)){
00868 Warning("AddFile","*** IGNORED *** File %s has wrong extention \n",
00869 (const char *)tfile);
00870 return kStWarn;}
00871
00872 base = gSystem->BaseName(tfile);
00873
00874 famy = base;
00875 int dot = famy.Last('.');
00876 if (dot>0) famy.Replace(dot,999,"");
00877 dot = famy.Last('.');
00878 if (dot>0) famy.Replace(dot+1,999,"");
00879
00880 TDataSet *dsfam = fDS->Find(famy);
00881 if (!dsfam && remove) return 0;
00882 if (!dsfam) fDS->Add((dsfam = new TObjectSet(famy,0)));
00883
00884 TDataSet *twice = dsfam->Find(base);
00885 tit = tfile; tit.Replace(0,0," file=");
00886 if (twice) {
00887 if (!remove) {
00888
00889
00890 Warning("AddFile","File \"%s\" is already added from \"%s\",\n\tThe file \"%s\" is accepted anyway. \n"
00891 ,(const char *)base, twice->GetTitle(), (const char *)tit );
00892 } else { delete twice; return 0;}
00893 }
00894
00895
00896
00897
00898
00899
00900 TDataSet *ds = new TDataSet(base,dsfam);
00901 ds->SetTitle(tit);
00902
00903
00904 if (GetDebug()) printf("<%s::AddFile> Added file %s %s\n",
00905 ClassName(),ds->GetName(),ds->GetTitle());
00906
00907 return 0;
00908 }
00909
00910 Int_t StFile::AddWild(const char *file,const char *opt )
00911 {
00912 const char* fullname;
00913 TDirIter dirIter(file);
00914 while((fullname=dirIter.NextFile())) { AddFile(fullname,opt);}
00915
00916 return 0;
00917 }
00918
00919 Int_t StFile::AddEvent(UInt_t r,UInt_t e)
00920 {
00921 TObjectSet *dsfam = (TObjectSet*)fDS->Last(); if(!dsfam) return 1;
00922 TDataSet *dsfil = dsfam->Last(); if(!dsfil) return 1;
00923
00924 TDataSet *dskey = (TDataSet*)dsfam->GetObject();
00925 if (!dskey) { dskey = new TDataSet("uklist");dsfam->SetObject(dskey,1);}
00926 char cbuf[40];
00927 sprintf(cbuf,".%010u.%010u",r,e);
00928 new TDataSet(cbuf,dskey);
00929 return 0;
00930 }
00931
00932 StUKey StFile::GetNextEvent()
00933 {
00934 StUKey uk(kUMAX);
00935 if (!fDS) return uk;
00936 TDataSet *dsfam = fDS->At(fIter);
00937 if (!dsfam) return uk;
00938 uk = 0;
00939 TDataSet *dskeys = (TDataSet*)dsfam->GetObject();
00940 if (!dskeys) return uk;
00941 if (!fKeyIter) fKeyIter = new TDataSetIter(dskeys);
00942 TDataSet *dskey = fKeyIter->Next();
00943 if (!dskey){ uk = kUMAX; delete fKeyIter; fKeyIter=0; return uk;}
00944 uk.SetKey(dskey->GetName());
00945 return uk;
00946 }
00947
00948 void StFile::SetInfo(TDataSet *ds)
00949 {
00950 int i;
00951 TFile *tf=0;
00952
00953 if (!ds) return;
00954 TString tit(ds->GetTitle());
00955 Int_t known = 0;
00956 if (strstr(tit,"format=")) known += 1;
00957 if (strstr(tit,"branch=")) known += 2;
00958 if (known==3) return;
00959
00960 const char *fname = strstr(ds->GetTitle(),"file=")+5;
00961 const char *ext = strrchr(fname,'.');
00962 assert(ext);
00963
00964 tit.Replace(0,0," branch=NONE ");
00965
00966
00967 if (strcmp(".daq",ext)==0) {
00968 tit.Replace(0,0," format=daq ");
00969 known = 3;
00970 goto RETN;
00971 }
00972
00973
00974 if (strcmp(".dat",ext)==0) {
00975 tit.Replace(0,0," format=dat ");
00976 known = 3;
00977 goto RETN;
00978 }
00979
00980
00981 if (strcmp(".root",ext)==0) {
00982 int lfname = strlen(fname);
00983 if (strcmp(".MuDst.root",fname+lfname-11)==0){
00984 tit.Replace(0,0," format=mudst ");
00985 } else {
00986 tit.Replace(0,0," format=root " );
00987 }
00988 known |= 1;
00989
00990 TString bran = fname;
00991 bran.ReplaceAll(".root","");
00992 i = bran.Last('.');
00993 if (i>0) {
00994 bran.Replace(0,i+1,"");
00995 known = 3;
00996 i = tit.Index("branch=NONE"); assert(i>=0);
00997 tit.Replace(i+7,4,bran);
00998 goto RETN;
00999 }
01000
01001
01002
01003
01004 tf = TFile::Open(fname,"READ");
01005 assert(tf && !tf->IsZombie());
01006 TList *kl = gFile->GetListOfKeys();
01007 TIter nextKey(kl);
01008 TKey *ky;
01009 while ((ky = (TKey*)nextKey())) {
01010 if (strcmp("StIOEvent",ky->GetClassName())) continue;
01011 const char *bra=ky->GetName();
01012 if (strstr(bra,"tree")) continue;
01013 if (strstr(bra,"Tree")) continue;
01014 if (strstr(bra,".")==0) continue;
01015 i = tit.Index("branch=NONE"); assert(i>=0);
01016 tit.Replace(i+7,4,bra,strcspn(bra,"."));
01017 break;
01018 } }
01019
01020 RETN:;
01021 delete tf;
01022 ds->SetTitle(tit);
01023 }
01024
01025 void StFile::ls(Option_t *opt)
01026 {
01027 if (!fDS) return;
01028 if (opt && *opt ) {lsFull(opt); return;}
01029 TDataSetIter famIter(fDS);
01030 TDataSet *fam,*fil;
01031 int num = 0;
01032 while((fam=famIter.Next())) {
01033 if (!fam->First()) continue;
01034 TDataSetIter filIter(fam);
01035 while((fil=filIter.Next())) {
01036 const char *fname = strstr(fil->GetTitle(),"file=");
01037 if (!fname) continue;
01038 num++;
01039 printf("%3d - %s\n",num,fname+5);
01040 }
01041 }
01042 }
01043
01044 void StFile::lsFull(Option_t *opt)
01045 {
01046 TList blist;
01047 int ibr=0,i;
01048 Cat *cat;
01049 int savIter = fIter; fIter=-1;
01050 int numFile=0;
01051 TString oldirname("_");
01052 while (!GetNextBundle()) {
01053 for (int idx=0; idx<999; idx++) {
01054 const char *fil = GetFileName(idx);
01055 if (!fil) break;
01056 numFile++;
01057 TString dirname = gSystem->DirName(fil);
01058 TString basname = gSystem->BaseName(fil);
01059 TString br(basname);
01060 i = br.Last('.'); if (i<0) continue;
01061 br.Replace(i,999,"");
01062 i = br.Last('.');
01063 if (i<0) { br = "undef";} else { br.Replace(0,i+1,"");};
01064
01065 if (oldirname != dirname) {
01066 printf("\nDirName =%s\n\n",dirname.Data());
01067 oldirname.Replace(0,999,dirname);}
01068
01069 cat = (Cat*)(blist.FindObject(br));
01070 if (!cat) { cat = new Cat(); cat->SetName(br); blist.Add(cat);}
01071 cat->fNFiles++;
01072
01073 TFile *tf = 0;
01074 if (opt && opt[0]=='r') tf = StIO::Open(fil,"update");
01075 if (!tf) tf = StIO::Open(fil,"read" );
01076 if (!tf) continue;
01077
01078 TList *keys = tf->GetListOfKeys();
01079 int nkeys=0,nreks=0;
01080 double dsize=0;
01081
01082 TIter nextk(keys);
01083 TKey *key;
01084 while ((key=(TKey*)nextk())) {
01085 TString keyname(key->GetName());
01086 i = keyname.First('.');
01087 if (i>0) keyname.Replace(i,9999,"");
01088 keyname.ReplaceAll("Branch","");
01089 cat = (Cat*)(blist.FindObject(keyname));
01090 if (!cat) {
01091 cat = new Cat();
01092 cat->SetName(keyname);
01093 blist.Add(cat);
01094 }
01095 nkeys++;
01096 cat->fNKeys++;
01097 if (keyname==br) { nreks++; cat->fNRecs++;};
01098 dsize += key->GetObjlen();
01099 cat->fSize += key->GetObjlen();
01100 TString clasname(key->GetClassName());
01101 cat = (Cat*)(blist.FindObject(clasname));
01102 if (!cat) {
01103 cat = new Cat();
01104 cat->SetName(clasname);
01105 blist.Add(cat);
01106 }
01107 cat->fNKeys++;
01108 cat->fSize += key->GetObjlen();
01109
01110 }
01111 dsize/=1000000.;
01112 printf("%4d BR=%-7s NK=%-4d NR=%-4d SZ=%8.2fM File= %s\n",
01113 numFile,br.Data(),nkeys,nreks,dsize,basname.Data());
01114 delete tf;
01115
01116
01117 }
01118 }
01119
01120 printf("\n\n In Total ==================================================\n");
01121 blist.Sort();
01122 TIter nextBr(&blist);
01123 ibr = 0;
01124 while ( (cat = (Cat*)nextBr())){
01125 ibr++;
01126 printf("%4d BR=%-10s NK=%-4d NR=%-4d SZ=%8.2fM NFiles %4d\n",
01127 ibr,
01128 cat->GetName(),
01129 cat->fNKeys,
01130 cat->fNRecs,
01131 cat->fSize*1.e-6,
01132 cat->fNFiles);
01133 }
01134 blist.Delete();
01135 fIter = savIter;
01136 }
01137
01138 const char *StFile::GetAttr(TDataSet *ds,const char *att)
01139 {
01140 static TString brName;
01141 if (!ds) return 0;
01142 SetInfo(ds);
01143 const char *bn = strstr(ds->GetTitle(),att);
01144 if (!bn) return 0;
01145 bn += strlen(att);
01146 int n = strcspn(bn," ");
01147 brName.Replace(0,999,bn,n);
01148 return (const char*)brName;
01149 }