1    	#include <stdio.h>
2    	#include "Stypes.h"
3    	#include "StTree.h"
4    	#include "TRegexp.h"
5    	#include "TDirIter.h"
6    	#include "TKey.h"
7    	#include "TError.h"
8    	#include <stdlib.h>
9    	
10   	#ifdef __RFIO__
11   	#include "TRFIOFile.h"
12   	#endif
13   	
14   	void DummyErrorHandlerFunc(int , Bool_t , const char *, const char *){;}
15   	
16   	
17   	
18   	
19   	const char* TFOPT[9] = {"0","READ","RECREATE","UPDATE",
20   	                        "0","READ","RECREATE","UPDATE",0};
21   	const char  RWU[] = "0rwu0rnu0rcu";
22   	char IOMODE[] = "0";
23   	
24   	Int_t StIO::fgDebug = 0;
25   	
26   	static inline Int_t IntOMode(char ciomode)
27   	{
28   	char *c=(char *)strchr(RWU,tolower(ciomode));
29   	return (c) ? (c-RWU)&3 : 0;
30   	}
31   	
32   	#ifdef __RFIO__
33   	extern "C" {
34   	   int rfio_open(const char *filepath, int flags, int mode);
35   	   int rfio_close(int s);
36   	   int rfio_read(int s, char *ptr, int size);
37   	   int rfio_write(int s, char *ptr, int size);
38   	   int rfio_lseek(int s, int offset, int how);
39   	   int rfio_access(const char *filepath, int mode);
40   	   int rfio_unlink(const char *filepath);
41   	   int rfio_parse(const char *name, char **host, char **path);
42   	};
43   	#endif
44   	
45   	class Cat : public TNamed {
46   	public:
47   	  Cat(){fNGeant=0;fNKeys=0;fNRecs=0;fSize=0;fNFiles=0;};
48   	  double fSize;
49   	  int    fNGeant;
50   	  int    fNKeys;
51   	  int    fNRecs;
52   	  int    fNFiles;
53   	};
54   	
55   	ClassImp(StIOEvent)
56   	StIOEvent::StIOEvent():TObject(){fObj=(TObject*)(-1);};
57   	//______________________________________________________________________________
58   	void StIOEvent::Browse(TBrowser *b)
59   	{
60   	  if (b && fObj && (Long_t)fObj != (-1)) fObj->Browse(b);
61   	}
62   	//______________________________________________________________________________
63   	void StIOEvent::Streamer(TBuffer &R__b)
64   	{
65   	   // Stream an object of class StIOEvent.
66   	
67   	   if (R__b.IsReading()) {
68   	      Version_t R__v = R__b.ReadVersion(); if (R__v) { }
69   	      TObject::Streamer(R__b);
70   	      R__b >> fObj;
71   	   } else {
72   	      R__b.WriteVersion(StIOEvent::IsA());
73   	      TObject::Streamer(R__b);
74   	      R__b << fObj;
75   	   }
76   	}
77   	
78   	//_______________________________________________________________________________
79   	
80   	Int_t StIO::Write(TFile *file, const StUKey &ukey, TObject  *obj)
81   	{
82   	  assert(file);
83   	  if (!obj) return kStWarn;
84   	
85   	  StIOEvent event;
86   	  event.fObj = obj; event.SetUniqueID(ukey.GetSum());
87   	  //  TFile *bakfile = gFile; 
88   	  TDirectory *bakdir = gDirectory; file->cd();
89   	
90   	  event.Write(ukey.GetKey(),TObject::kOverwrite|TObject::kSingleKey);
91   	  if (gFile) gFile->Flush();
92   	  //  gFile=bakfile; 
93   	  gDirectory=bakdir;
94   	  return 0;
95   	}
96   	//_______________________________________________________________________________
97   	TObject *StIO::Read(TFile *file, const char *name)
98   	{
99   	  TObject *toread=0;
100  	  TKey *key = 0;
101  	  assert(file);
102  	
103  	  TFile *bakfile = gFile; TDirectory *bakdir = gDirectory; file->cd();
104  	
105  	  if (!gFile) { printf("<StIO::Read> No file open \n"); goto RETURN;}
106  	
107  	  if (name[0]=='*') {
108  	       key = (TKey*)gDirectory->GetListOfKeys()->At(0);
109  	       if (strcmp(".StreamerList",key->GetName())==0)
110  	       key = (TKey*)gDirectory->GetListOfKeys()->At(1);
111  	  }
112  	  else key = (TKey*)gDirectory->GetListOfKeys()->FindObject(name);
113  	
114  	  if (!key) {
115  	    if(fgDebug) printf("<StIO::Read> Key %s not found\n",name);
116  	    goto RETURN; }
117  	
118  	  if (name[0]!='*' && strcmp(key->GetClassName(),"StIOEvent"))
119  	             { printf("<StIO::Read> Key %s has wrong className %s\n",
120  	               key->GetName(),key->GetClassName());
121  	               toread = (TObject*)(-1); goto RETURN; }
122  	
123  	  toread = key->ReadObj(); if (!toread) toread = (TObject*)(-1);
124  	
125  	RETURN: 
126  	  //  gFile=bakfile; 
127  	  gDirectory=bakdir; return toread;
128  	}
129  	//_______________________________________________________________________________
130  	TObject *StIO::Read(TFile *file, const StUKey &ukey)
131  	{
132  	  StIOEvent *event = 0;
133  	  TObject   *retn  = 0;
134  	  retn = Read(file,ukey.GetKey());
135  	  if (!retn)            return 0;
136  	  if (retn == (TObject*)(-1)) return retn;
137  	  if (retn->IsA()!=StIOEvent::Class()) return retn;
138  	  event = (StIOEvent*)retn;
139  	  retn = event->fObj;
140  	  assert( !retn || retn==(TObject*)(-1) || event->GetUniqueID()==ukey.GetSum());
141  	  delete event;
142  	  return retn;
143  	}
144  	//_______________________________________________________________________________
145  	Int_t StIO::GetNextKey(TFile *file, StUKey &ukey,ULong_t &handle)
146  	{
147  	  TObjLink *lnk; TList *lk; const char *kname; TObject *obj;
148  	  enum { kSorted = 1};
149  	  assert(file);
150  	
151  	  TString tk = ukey.GetKey(); ukey = kUMAX;
152  	  const char* prevkey = (const char*)tk;
153  	  int lname = strlen(ukey.GetName())+1;
154  	
155  	  lk = file->GetListOfKeys();  if(!lk) return 1;
156  	  if (!lk->TestBit(kSorted)) {lk->Sort(); lk->SetBit(kSorted);handle = 0;}
157  	
158  	   // Find an object in this list using its name. Requires a sequential
159  	   // scan till the object has been found. Returns 0 if object with specified
160  	   // name is not found. This method overrides the generic FindObject()
161  	   // of TCollection for efficiency reasons.
162  	
163  	  if (handle) {
164  	     lnk = (TObjLink*)handle;
165  	     handle = 0;
166  	     obj = lnk->GetObject();
167  	     if (strcmp(prevkey,obj->GetName())>0) lnk = lk->FirstLink();
168  	  } else {
169  	     lnk = lk->FirstLink();
170  	  }
171  	
172  	  while (lnk) {
173  	    obj = lnk->GetObject();
174  	    kname = obj->GetName();
175  	    if (strcmp(prevkey, kname)<0) break;
176  	    lnk = lnk->Next();
177  	  }
178  	  if (!lnk) return 1;
179  	  if (strncmp(prevkey,kname,lname)) lnk = 0;
180  	  if (!lnk) return 1;
181  	  ukey.SetKey(kname);
182  	  handle = (ULong_t)lnk;
183  	  return 0;
184  	}
185  	//_______________________________________________________________________________
186  	TObject *StIO::ReadNext(TFile *file, StUKey &ukey, ULong_t &handle)
187  	{
188  	  if(GetNextKey(file,ukey,handle)) return 0;;
189  	  return Read(file,ukey);
190  	}
191  	//_______________________________________________________________________________
192  	TString StIO::RFIOName(const char *name)
193  	{
194  	  TString file(name);
195  	  TNamed *tn;
196  	  TList *rfiomap = (TList *)gROOT->GetListOfSpecials()->FindObject(".rfiomap");
197  	  if (file.Contains(".daq")) rfiomap = 0;       //no RFIO for .daq
198  	  if (rfiomap) {        // check the map
199  	    TIter next(rfiomap);
200  	    while ((tn = (TNamed*)next())) {//matching loop
201  	      int n = strlen(tn->GetName());
202  	      if (!n)                                   continue;
203  	      if (strncmp(file,tn->GetName(),n))        continue;
204  	      file.Replace(0,0,tn->GetTitle());
205  	      break;
206  	    }   //end matching loop
207  	  }  //end check the map
208  	  return file;
209  	}
210  	//_______________________________________________________________________________
211  	TFile *StIO::Open(const char *name, Option_t *option,const char *title,Int_t compress)
212  	{
213  	  //printf("DEBUG:: StIO::Open(%s)\n",name);
214  	
215  	  TString file = RFIOName(name);
216  	  if(strcmp("READ",option)==0 && !IfExi(name)) return 0;
217  	  if(strcmp("read",option)==0 && !IfExi(name)) return 0;
218  	  if(strcmp("Read",option)==0 && !IfExi(name)) return 0;
219  	  TFile *tf = TFile::Open(file,option,title,compress);
220  	  if (!tf  || !tf->IsZombie()) return tf;
221  	  delete tf;
222  	  return 0;
223  	}
224  	//_______________________________________________________________________________
225  	Int_t StIO::IfExi(const char *name)
226  	{
227  	  TString file = (name);
228  	
229  	  //printf("DEBUG:: StIO::IfExi Expanding(%s)\n",name);
230  	  gSystem->ExpandPathName(file); 
231  	
232  	  // Supress error message
233  	  ErrorHandlerFunc_t dummy = &DummyErrorHandlerFunc;
234  	  ErrorHandlerFunc_t curre = SetErrorHandler(dummy);
235  	
236  	  //printf("DEBUG:: StIO::IfExi AccessingPathName(%s)\n",file.Data());
237  	  // JL - This attempts to do a root auth even if xroot
238  	#if 0  
239  	  if (!gSystem->AccessPathName(file)){ 
240  	    SetErrorHandler(curre); 
241  	    return 1;
242  	
243  	  } else 
244  	#endif  
245  	  {
246  	    int l = file.Length();
247  	    if (file(l-5,5)!=".root"){
248  	      SetErrorHandler(curre); 
249  	      return !gSystem->AccessPathName(file);
250  	    } else {
251  	      //printf("DEBUG:: Opening %s\n",name);
252  	      // Workaround:
253  	      //  Due the ROOT (4.04.02) TSystem::FindHelper bug one can not 
254  	      //  use TSystem::AccessPathName method to test files on 
255  	      //  the "rootd" servers
256  	      TFile *tf = TFile::Open(file);
257  	      // return old error handler
258  	      SetErrorHandler(curre);
259  	      //printf("DEBUG:: Done with %s\n",name);
260  	
261  	      int z = (!tf || tf->IsZombie());
262  	      delete tf;   
263  	      return !z;
264  	    }
265  	  }
266  	}
267  	//===============================================================================
268  	
269  	ClassImp(StBranch)
270  	
271  	//_______________________________________________________________________________
272  	StBranch::StBranch(const char *name, StTree *parent,Option_t *opt):TDataSet(name,parent)
273  	{
274  	
275  	  SetTitle(".StBranch");
276  	  fNEvents=0;fUKey=name;fUKey=0;fIOMode=0;fTFile=0;fDebug=0;fHandle=0;
277  	  SetOption(opt);
278  	
279  	}
280  	StBranch::~StBranch()
281  	{
282  	 Close();
283  	
284  	}
285  	//_______________________________________________________________________________
286  	void StBranch::SetOption(Option_t *opt)
287  	{
288  	  if (opt) fOption = opt;
289  	  fOption.ToUpper();
290  	}
291  	//_______________________________________________________________________________
292  	void StBranch::SetIOMode(Option_t *iomode)
293  	{
294  	
295  	if (!iomode || !iomode[0]) return;
296  	fIOMode = ::IntOMode(iomode[0]);
297  	fHandle=0;
298  	}
299  	//_______________________________________________________________________________
300  	Option_t *StBranch::GetIOMode()
301  	{
302  	IOMODE[0]=0; if (fIOMode>0) IOMODE[0] = RWU[int(fIOMode)]; return IOMODE;
303  	}
304  	
305  	//_______________________________________________________________________________
306  	Int_t StBranch::SetFile(const char *file,const char *mode,int insist)
307  	{
308  	  fHandle=0;
309  	  fIOMode = abs(fIOMode);
310  	  if (fTFile && !insist) { Error("SetFile","File is already opened");return kStWarn;}
311  	  if (file && file[0]) fFile=file;
312  	  if (mode && mode[0]) SetIOMode(mode);
313  	  return 0;
314  	}
315  	//_______________________________________________________________________________
316  	Int_t StBranch::UpdateFile(const char *file)
317  	{
318  	fHandle=0;
319  	fIOMode = abs(fIOMode);
320  	TString bas[2],dir[2];
321  	TString nam(GetName()); nam.ReplaceAll("Branch","");
322  	nam.Insert(0,"."); nam += ".root";
323  	TString outFile = file; gSystem->ExpandPathName(outFile);
324  	        dir[0] = gSystem->DirName (outFile);
325  	        bas[0] = gSystem->BaseName(outFile);
326  	
327  	if (strncmp(".none ",GetFile(),6)==0) {//FileName was corrupted by old bug
328  	  
329  	  TString ts(GetFile()); ts.Remove(0,6); SetFile(ts);
330  	}
331  	
332  	  dir[1]  = gSystem->DirName (GetFile());
333  	  bas[1]  = gSystem->BaseName(GetFile());
334  	//VP  SetIOMode("0");
335  	  if (bas[0] == bas[1] || bas[0].Contains(nam)) SetIOMode("r");
336  	  //VP?? else                                  	bas[0]=bas[1];
337  	  for (int d=0; d<2; d++) {
338  	    for (int b=0; b<2; b++) {
339  	      if (!bas[b].Contains(nam)) continue;
340  	      char *newFile = gSystem->ConcatFileName(dir[d],bas[b]);
341  	      if (StIO::IfExi(newFile)) {        
342  	        fFile = newFile;
343  	        printf("<StBranch::UpdateFile> Branch=%s file %s\n",GetName(),newFile);
344  	        delete [] newFile;
345  	        return 0;
346  	  } } }
347  	  fIOMode = -abs(fIOMode);
348  	  return 0;
349  	}
350  	//_______________________________________________________________________________
351  	Int_t StBranch::SetTFile(TFile *tfile)
352  	{
353  	  if (!tfile)           return 0;
354  	  if (fTFile==tfile)    return 0;
355  	  fHandle=0;
356  	  if (fTFile) Close();  
357  	  fTFile=0;
358  	  SetFile(tfile->GetName());
359  	  Open();
360  	  return 0;
361  	}
362  	
363  	//_______________________________________________________________________________
364  	void StBranch::Close(const char *)
365  	{
366  	  fHandle=0;
367  	  if (!fIOMode) return;
368  	  if (!fTFile)  return;
369  	  if (strncmp(".none",GetFile(),4)==0) return;
370  	  TFile *tf = fTFile;
371  	  fTFile = 0;
372  	  TString ts(tf->GetTitle());
373  	  int idx = ts.Index("StBranch=Y");
374  	  assert (idx>=0);
375  	  ts.Replace(idx+9,1,"");
376  	  tf->SetTitle(ts);
377  	  if (ts.Contains("StBranch=Y")) return;
378  	  tf->Close("");
379  	  printf("** <StBranch::Close> Branch=%s \tFile=%s \tClosed **\n"
380  	        ,GetName(),(const char*)fFile);
381  	  delete tf;
382  	  if (!(fIOMode&2)) return;
383  	  ts = GetFile();
384  	  ts.Replace(0,0,".none ");
385  	  SetFile((const char*)ts);
386  	}
387  	//_______________________________________________________________________________
388  	const char *StBranch::GetFile()
389  	{
390  	  TString dir(fFile);
391  	  int kase=0;
392  	  if (!fFile.IsNull()) kase = 2;
393  	  if (kase && fFile[fFile.Length()-1]=='/') kase = 1;
394  	
395  	  if (kase<2) { // Construct file name
396  	    fFile=GetName(); fFile.ReplaceAll("Branch",""); fFile+=".root";
397  	    StTree *tree = (StTree*)GetParent();
398  	    if (tree) { // include base name
399  	      const char* base = tree->GetBaseName();
400  	      if (base) {fFile.Insert(0,"."); fFile.Insert(0,base);}}
401  	    if (kase==1) fFile.Insert(0,dir); 
402  	  }
403  	
404  	   return (const char*)fFile;
405  	}
406  	
407  	
408  	//_______________________________________________________________________________
409  	Int_t StBranch::Open()
410  	{
411  	  if (fIOMode<=0) return 0;
412  	  if (fTFile)   return 0;
413  	  if (strncmp(".none",GetFile(),4)==0) return 1;
414  	  OpenTFile();
415  	  return 0;
416  	}
417  	//_______________________________________________________________________________
418  	Int_t StBranch::WriteEvent(const StUKey &ukey)
419  	{
420  	  int iret;
421  	  if (  fIOMode<=0)   return 0;
422  	  if (!(fIOMode&2))   return 0;
423  	  fUKey.Update(ukey,GetName());
424  	  if (!fList)           return kStWarn; //empty
425  	  if (!fList->First())  return kStWarn; //empty
426  	  if(Open()) return 1;
427  	  fNEvents++;
428  	
429  	  TList savList;
430  	  SetParAll(0,this,&savList);
431  	  if (IsOption("const"))        {//Write constant branch (event independent)
432  	    StUKey uk(fUKey); uk = (UInt_t)(-2);
433  	    iret = StIO::Write(fTFile,uk,   fList);
434  	    fIOMode = -fIOMode;
435  	  } else {
436  	    iret = StIO::Write(fTFile,fUKey,fList);
437  	  }
438  	  SetParAll(&savList); 
439  	
440  	  return 0;
441  	}
442  	
443  	//_______________________________________________________________________________
444  	Int_t StBranch::GetEvent(Int_t mode)
445  	{
446  	  TObject *obj=0;
447  	  if (  fIOMode<=0)     return 0;
448  	  if (!(fIOMode&1))     return 0;
449  	  Delete(); if (fList)  delete fList; fList=0;
450  	  if(Open()) return 1;
451  	
452  	  if (IsOption("const"))        {//Read constant branch (event independent)
453  	    StUKey uk(fUKey); uk = (UInt_t)(-2);
454  	    obj = StIO::Read (fTFile,uk);  fIOMode = -fIOMode;
455  	
456  	  } else if (mode)                {//Read next
457  	    obj = StIO::ReadNext(fTFile,fUKey,fHandle);
458  	
459  	  } else                        {//Read this one
460  	    obj = StIO::Read    (fTFile,fUKey);
461  	  }
462  	
463  	  if (obj == 0)                 return kStEOF;
464  	  if (obj == (TObject*)(-1))    return kStErr;
465  	  fList = (TList*)obj;
466  	
467  	  SetParAll(this,this,0);
468  	
469  	  return 0;
470  	}
471  	//_______________________________________________________________________________
472  	Int_t StBranch::ReadEvent(const StUKey &ukey)
473  	{
474  	  if (  fIOMode<=0)     return 0;
475  	  if (!(fIOMode&1))     return 0;
476  	  fUKey.Update(ukey,GetName());
477  	  return GetEvent(0);
478  	}
479  	//_______________________________________________________________________________
480  	Int_t StBranch::NextEvent()
481  	{
482  	  if (  fIOMode<=0)     return 0;
483  	  if (!(fIOMode&1))     return 0;
484  	  Clear();
485  	  return GetEvent(1);
486  	}
487  	
488  	//_______________________________________________________________________________
489  	Int_t StBranch::NextEvent (StUKey &ukey)
490  	{
491  	  if (  fIOMode<=0)     return 0;
492  	  if (!(fIOMode&1))     return 0;
493  	  Clear();
494  	  fUKey.Update(ukey,GetName());
495  	  int iret = GetEvent(1); 
496  	  ukey.Update(fUKey); 
497  	  return iret;
498  	}
499  	//_______________________________________________________________________________
500  	void StBranch::SetParAll(TDataSet *parNew,TDataSet *parOld,TList *savList)
501  	{
502  	  TDataSetIter next(parOld);
503  	  TDataSet *son,*p;
504  	  while ((son=next())) {
505  	    p = son->GetParent();
506  	    son->SetParent(parNew);
507  	    if (savList) {
508  	       assert(p);
509  	       savList->AddFirst(son); savList->AddFirst(p); 
510  	       SetParAll(son,son,savList);
511  	    }
512  	  }// end while
513  	}
514  	//_______________________________________________________________________________
515  	void StBranch::SetParAll(TList *savList)
516  	{
517  	  assert(savList);
518  	  TDataSet *son,*par;
519  	  while ((par=(TDataSet*)savList->First())) {
520  	    savList->Remove(par);
521  	    son = (TDataSet*)savList->First(); assert(son);
522  	    savList->Remove(son);
523  	    son->SetParent(par);
524  	  }// end while
525  	}
526  	//_______________________________________________________________________________
527  	void StBranch::OpenTFile()
528  	{
529  	  if (fTFile) return;
530  	  fHandle = 0;
531  	  TFile *tf= gROOT->GetFile(GetFile());
532  	  fTFile = tf;
533  	  if (!fTFile) {
534  	    fTFile = StIO::Open(GetFile(),TFOPT[int(fIOMode)],GetName());
535  	
536  	  }
537  	  if (!fTFile) {
538  	    Error("OpenTFile","File %s NOT OPENED ***\n",GetFile());
539  	    Error("OpenTFile","Branch %s desactivated ***\n",GetName());
540  	    delete fTFile; fTFile=0; SetIOMode("0");
541  	  } else {
542  	    TString ts(fTFile->GetTitle());
543  	    if (ts.Contains("StBranch="))
544  	    {  ts.ReplaceAll("StBranch=","StBranch=Y");}
545  	    else
546  	    {  ts += " StBranch=Y";}
547  	    fTFile->SetTitle(ts);
548  	    if (tf) return;
549  	
550  	    printf("** <StBranch::Open> Branch=%s \tMode=%s \tFile=%s \tOpened **\n"
551  	        ,GetName(),TFOPT[int(fIOMode)],(const char*)fFile);
552  	
553  	  }
554  	}
555  	//_______________________________________________________________________________
556  	void StBranch::Clear(Option_t *)
557  	{
558  	  Delete();
559  	}
560  	//===============================================================================
561  	
562  	ClassImp(StTree)
563  	
564  	//_______________________________________________________________________________
565  	StTree::StTree(const char *name):StBranch(name)
566  	{
567  	  SetTitle(".StTree");
568  	}
569  	
570  	//_______________________________________________________________________________
571  	StTree::~StTree()
572  	{ Close(); Delete();}
573  	
574  	//_______________________________________________________________________________
575  	void StTree::SetIOMode(Option_t *iomode)
576  	{
577  	 StBranch::SetIOMode(iomode);
578  	 TDataSetIter next(this);StBranch *br;
579  	 while ((br=(StBranch*)next())) { br->SetIOMode(iomode);}
580  	}
581  	//_______________________________________________________________________________
582  	Int_t StTree::SetFile(const char *file,const char *mode,int /* insist */)
583  	{
584  	  if (mode && *mode) StBranch::SetIOMode(mode); 
585  	  if (!file || !*file) 	return 0;
586  	
587  	  if (fIOMode&1)  {	//ReadMode
588  	    UpdateFile(file);
589  	    
590  	  }
591  	  if (fIOMode&2)  {	//WriteMode
592  	  
593  	    SetBaseName(file);
594  	  }
595  	  return 0;
596  	}
597  	
598  	//_______________________________________________________________________________
599  	void StTree::Clear(Option_t*)
600  	{
601  	 TDataSetIter next(this);StBranch *br;
602  	 while ((br=(StBranch*)next())) {/*if(!br->IsOption("const"))*/ br->Clear();}
603  	}
604  	
605  	//_______________________________________________________________________________
606  	Int_t StTree::Open()
607  	{
608  	  TDataSetIter nextA(this);StBranch *brA;
609  	  while ((brA=(StBranch*)nextA())) {
610  	    if (brA->GetIOMode()[0]=='0')       continue;
611  	    if (brA->GetTFile())                continue;
612  	    brA->Open();
613  	  }
614  	  return 0;
615  	}
616  	//_______________________________________________________________________________
617  	Int_t StTree::UpdateFile(const char *file)
618  	{
619  	  TDataSetIter next(this);StBranch *br;
620  	  while ((br=(StBranch*)next())) br->UpdateFile(file);
621  	  return 0;
622  	}
623  	
624  	//_______________________________________________________________________________
625  	Int_t StTree::WriteEvent(const StUKey &ukey)
626  	{
627  	  fUKey.Update(ukey,GetName()); Open();
628  	  TDataSetIter next(this);StBranch *br;
629  	  while ((br=(StBranch*)next())) br->WriteEvent(fUKey);
630  	  fNEvents++;
631  	  return 0;
632  	}
633  	
634  	//_______________________________________________________________________________
635  	Int_t StTree::ReadEvent(const StUKey &ukey)
636  	{
637  	  Int_t iret=0,num=0;
638  	  fUKey.Update(ukey,GetName()); Open();
639  	  TDataSetIter next(this);StBranch *br;
640  	  while ((br=(StBranch*)next())) {      //Read all branches
641  	    if ( (br->fIOMode<0)) continue;
642  	    if (!(br->fIOMode&1)) continue;
643  	    iret=br->ReadEvent(fUKey);
644  	    if (!iret) num++;
645  	  if(iret==kStErr) return kStErr;
646  	  }
647  	  return (num)? 0:kStEOF;
648  	}
649  	
650  	//_______________________________________________________________________________
651  	Int_t StTree::NextKey()
652  	{
653  	  if (Open()) return kStEOF;
654  	  TDataSetIter next(this); StBranch *br;
655  	  StUKey minKey = kUMAX;
656  	  StUKey tryKey;
657  	
658  	
659  	  while ((br=(StBranch*)next())) {
660  	    if ( (br->fIOMode<0)) 				continue;
661  	    if (!(br->fIOMode&1)) 				continue;
662  	    if (br->IsOption("const"))				continue;
663  	    tryKey.Update(fUKey,br->GetName());
664  	    if (StIO::GetNextKey(br->fTFile,tryKey,br->fHandle))continue;
665  	    tryKey = "";
666  	    if (tryKey.Compare(minKey)<0) minKey=tryKey;
667  	  }
668  	  fUKey = minKey;
669  	  return minKey.EOK() ? kStEOF:0;
670  	}
671  	//_____________________________________________________________________________
672  	Int_t StTree::Skip(int nskip)
673  	{  
674  	  for (; nskip; nskip--) 
675  	  {
676  	    int ret = NextKey(); 
677  	    if (ret) break;
678  	  }
679  	
680  	  return nskip;
681  	}
682  	//_______________________________________________________________________________
683  	Int_t StTree::NextEvent(StUKey  &ukey)
684  	{
685  	  fUKey.Update(ukey,GetName());int iret=NextEvent(); ukey.Update(fUKey); return iret;
686  	}
687  	//_______________________________________________________________________________
688  	Int_t StTree::NextEvent()
689  	{
690  	  int iret=0,nAkt=0;
691  	  TDataSetIter next(this); StBranch *br=0;
692  	
693  	  int kase = 0; StBranch *br0=0;
694  	  while ((br=(StBranch*)next())) {
695  	    switch(kase) {
696  	    case 0: kase=1; br0 = br;
697  	     	if ( (br->fIOMode<0)) 	return kStEOF;
698  	     	if (!(br->fIOMode&1)) 	return kStEOF;
(1) Event value_overwrite: Overwriting previous write to "iret" with value from "br->NextEvent()".
Also see events: [returned_value]
699  		iret = br->NextEvent();
700  	        if (iret)		return iret;
701  		break;
702  	    case 1:
703  	     	if ( (br->fIOMode<0)) 	continue;
704  	     	if (!(br->fIOMode&1)) 	continue;
(2) Event returned_value: Assigning value from "br->ReadEvent(StUKey(br0->GetUKey()))" to "iret" here, but that stored value is overwritten before it can be used.
Also see events: [value_overwrite]
705  		iret = br->ReadEvent(br0->GetUKey());
706  	    }
707  	    nAkt++;
708  	  }
709  	  
710  	  return (nAkt) ? 0:kStEOF;
711  	}
712  	
713  	//_______________________________________________________________________________
714  	void StTree::Close(const char* opt)
715  	{
716  	  Clear();
717  	  fUKey = 2000;
718  	  TDataSetIter next(this); StBranch *br;
719  	  while ((br=(StBranch*)next())) { //branch loop
720  	    br->fIOMode = abs(br->fIOMode);
721  	    if (br->fIOMode&2) {
722  	      br->Open();
723  	      TFile *tfbr = br->GetTFile(); if(!tfbr)   continue;
724  	      if (tfbr->IsWritable()) {
725  	        TDataSet *par = GetParent(); SetParent(0);
726  	        StIO::Write(tfbr,fUKey,this);
727  	        SetParent(par);}
728  	    }
729  	    if ((opt && strcmp(opt,"keep")==0)) continue;
730  	    br->Close();
731  	  }// end branch loop
732  	}
733  	
734  	//_______________________________________________________________________________
735  	StTree *StTree::GetTree(TFile *file, const char *treeName)
736  	{
737  	  StUKey treeKey(treeName,2000); 
738  	  StTree *ret = (StTree*)StIO::Read(file,treeKey);
739  	  if ((Long_t)ret == -1) return 0;
740  	  TDataSetIter next(ret);StBranch *br=0;
741  	  while ((br=(StBranch*)next())) {
742  	     br->SetIOMode("0");
743  	     br->fUKey = br->GetName();
744  	     br->fUKey = 0;
745  	  }
746  	  return ret;
747  	}
748  	
749  	//_______________________________________________________________________________
750  	void StTree::SetBaseName(const char *baseName,const char *dirname)
751  	{
752  	  const char *dot;
753  	  fBaseName = gSystem->BaseName(baseName);
754  	  if (dirname && *dirname) {
755  	    TString ts(dirname); 
756  	    if (ts[ts.Length()-1]!='/') ts += "/";
757  	    ts += fBaseName;
758  	    fBaseName = ts;
759  	  }
760  	  dot = strrchr(fBaseName.Data(),'.');
761  	  if (!dot) 				return;
762  	  int fz = (strstr(".fz .fzd .daq",dot)!=0);
763  	  fBaseName.Remove(dot-fBaseName.Data());
764  	  if (fz) 				return;
765  	  dot = strrchr(fBaseName.Data(),'.');
766  	  if (!dot) 				return;
767  	  if ('0' <=dot[1] && dot[1]<='9') 	return;
768  	  fBaseName.Remove(dot-fBaseName.Data());
769  	}
770  	
771  	//_____________________________________________________________________________
772  	ClassImp(StFile)
773  	 StFile::StFile(const char** fileList):StFileI("StFile")
774  	{
775  	  fDS = new TDataSet();
776  	  fIter = -1; fKeyIter = 0;
777  	  SetTitle(" nbranches=1 ");
778  	  if (fileList) AddFile(fileList);
779  	}
780  	//_____________________________________________________________________________
781  	 StFile::~StFile()
782  	{
783  	  delete fDS;   	fDS      = 0;
784  	  fIter    = -1;
785  	  delete fKeyIter;	fKeyIter = 0;
786  	}
787  	//_____________________________________________________________________________
788  	Int_t StFile::GetNextBundle()
789  	{
790  	  if (!fDS)	return 1;
791  	  if (fIter>-1 && !fDS->At(fIter)) return 1;
792  	  return (!fDS->At(++fIter));
793  	  
794  	}
795  	//_____________________________________________________________________________
796  	Int_t StFile::GetNBundles()
797  	{
798  	  return fDS->GetListSize();
799  	}
800  	//_____________________________________________________________________________
801  	Int_t StFile::GetNFiles()
802  	{
803  	  return fDS->GetListSize();
804  	}
805  	//_____________________________________________________________________________
806  	TDataSet *StFile::GetFileDS(Int_t idx)
807  	{
808  	  TDataSet *fam = fDS->At(fIter);
809  	  if (!fam) return 0;
810  	  TDataSet *df = fam->At(idx);
811  	  if (!df) return 0;
812  	  SetInfo(df);
813  	  return df;
814  	}
815  	//_____________________________________________________________________________
816  	const char *StFile::GetFileName(Int_t idx)
817  	{
818  	  if (idx == -1) { idx=0; if (GetNextBundle()) return 0;}
819  	  TDataSet *df = GetFileDS(idx);
820  	  if (!df) return 0;
821  	  return strstr(df->GetTitle(),"file=")+5;
822  	}
823  	//_____________________________________________________________________________
824  	const char *StFile::GetFormat(Int_t idx)
825  	{
826  	  TDataSet *df = GetFileDS(idx);
827  	  return GetAttr(df,"format=");
828  	}
829  	//_____________________________________________________________________________
830  	const char *StFile::GetCompName(Int_t idx)
831  	{
832  	  TDataSet *df = GetFileDS(idx);
833  	  return GetAttr(df,"branch=");
834  	}
835  	//_____________________________________________________________________________
836  	Int_t StFile::AddFile(const char **fileList)
837  	{
838  	  const char *file;
839  	  if (!fileList) return 0;
840  	  for(int i=0; (file = fileList[i]);i++){
841  	    if (file) AddFile(file);
842  	  }
843  	  return 0;
844  	}
845  	//_____________________________________________________________________________
846  	Int_t StFile::AddFile(const char *file,const char *opt)
847  	{
848  	
849  	  //printf("DEBUG:: StFile::AddFile\n");
850  	
851  	  TString tfile,tit,base,famy;
852  	  if (strpbrk(file,"*\\[]#@")) return AddWild(file,opt);
853  	  int remove = 0;
854  	  if (opt && *opt) {
855  	    TString ts(opt);
856  	    if (ts.Contains("REMOVE" ,TString::kIgnoreCase)) remove=1;   
857  	    if (ts.Contains("EXCLUDE",TString::kIgnoreCase)) remove=1;   
858  	  }	  
859  		  
860  	  //printf("DEBUG:: StFile::AddFile - ExpandPathName\n");	    
861  	  tfile = file; gSystem->ExpandPathName(tfile);
862  	
863  	  //printf("DEBUG:: StFile::AddFile - testing IfExi\n");	    
864  	
865  	  if (!StIO::IfExi(tfile)) {// file does not exist
866  	    Warning("AddFile","*** IGNORED *** File %s does NOT exist \n",
867  	    (const char*)tfile);
868  	    return kStWarn;}
869  	
870  	  const char* cc = strrchr(tfile,'.');
871  	  if (!cc || !strstr(".root .daq .dat",cc)){// No extention
872  	    Warning("AddFile","*** IGNORED *** File %s has wrong extention \n",
873  	    (const char *)tfile);
874  	    return kStWarn;}
875  	
876  	  base = gSystem->BaseName(tfile);
877  	
878  	  famy = base;
879  	  int dot = famy.Last('.');
880  	  if (dot>0) famy.Replace(dot,999,"");
881  	  dot = famy.Last('.');
882  	  if (dot>0) famy.Replace(dot+1,999,"");
883  	
884  	  TDataSet *dsfam = fDS->Find(famy);
885  	  if (!dsfam && remove) return 0;
886  	  if (!dsfam) fDS->Add((dsfam = new TObjectSet(famy,0)));
887  	
888  	  TDataSet *twice = dsfam->Find(base);
889  	  tit = tfile; tit.Replace(0,0," file=");
890  	  if (twice) {
891  	    if (!remove) {
892  	       // compare the full path
893  	       // if (tit == twice->GetTitle() )
894  	          Warning("AddFile","File \"%s\" is already added from \"%s\",\n\tThe file \"%s\" is accepted anyway. \n"
895  	                ,(const char *)base, twice->GetTitle(), (const char *)tit );
896  	    } else       { delete twice; return 0;}
897  	  }
898  	  //  TDataSet *dss = dsfam->First();
899  	  //if (dss)
900  	  //  Warning("AddFile","Files %s and %s are from the same family \n",
901  	  //  (const char *)tfile,dss->GetName());
902  	
903  	
904  	  TDataSet *ds = new TDataSet(base,dsfam);
905  	  ds->SetTitle(tit);
906  	
907  	
908  	  if (GetDebug()) printf("<%s::AddFile> Added file %s %s\n",
909  	                  ClassName(),ds->GetName(),ds->GetTitle());
910  	
911  	  return 0;
912  	}
913  	//_____________________________________________________________________________
914  	Int_t StFile::AddWild(const char *file,const char *opt )
915  	{
916  	  const char* fullname;
917  	  TDirIter dirIter(file);
918  	  while((fullname=dirIter.NextFile())) { AddFile(fullname,opt);}
919  	  
920  	  return 0;
921  	}
922  	//_____________________________________________________________________________
923  	Int_t StFile::AddEvent(UInt_t r,UInt_t e)
924  	{
925  	  TObjectSet *dsfam = (TObjectSet*)fDS->Last();	if(!dsfam) return 1;
926  	  TDataSet   *dsfil = dsfam->Last();		if(!dsfil) return 1;
927  	    
928  	  TDataSet   *dskey = (TDataSet*)dsfam->GetObject(); 
929  	  if (!dskey) { dskey = new TDataSet("uklist");dsfam->SetObject(dskey,1);} 
930  	  char cbuf[40];
931  	  sprintf(cbuf,".%010u.%010u",r,e);
932  	  new TDataSet(cbuf,dskey);
933  	  return 0;
934  	}  
935  	//_____________________________________________________________________________
936  	StUKey StFile::GetNextEvent()
937  	{
938  	  StUKey uk(kUMAX);
939  	  if (!fDS) 		return uk;
940  	  TDataSet *dsfam = fDS->At(fIter); 
941  	  if (!dsfam) 		return uk;
942  	  uk = 0;
943  	  TDataSet *dskeys = (TDataSet*)dsfam->GetObject();
944  	  if (!dskeys)		return uk;
945  	  if (!fKeyIter) fKeyIter = new TDataSetIter(dskeys);
946  	  TDataSet *dskey = fKeyIter->Next();
947  	  if (!dskey){ uk = kUMAX; delete fKeyIter; fKeyIter=0;	return uk;}
948  	  uk.SetKey(dskey->GetName());
949  	  return uk;
950  	}
951  	//_____________________________________________________________________________
952  	void StFile::SetInfo(TDataSet *ds)
953  	{
954  	  int i;
955  	  TFile *tf=0;
956  	
957  	  if (!ds) return;
958  	  TString tit(ds->GetTitle());
959  	  Int_t known = 0;
960  	  if (strstr(tit,"format=")) known += 1;
961  	  if (strstr(tit,"branch=")) known += 2;
962  	  if (known==3) return;
963  	
964  	  const char *fname = strstr(ds->GetTitle(),"file=")+5;
965  	  const char *ext =   strrchr(fname,'.');
966  	  assert(ext);
967  	
968  	  tit.Replace(0,0," branch=NONE ");
969  	
970  	//              DAQ
971  	  if (strcmp(".daq",ext)==0) {
972  	    tit.Replace(0,0," format=daq ");
973  	    known = 3;
974  	    goto RETN;
975  	  }
976  	
977  	//              DAT
978  	  if (strcmp(".dat",ext)==0) {
979  	    tit.Replace(0,0," format=dat ");
980  	    known = 3;
981  	    goto RETN;
982  	  }
983  	
984  	//              ROOT
985  	  if (strcmp(".root",ext)==0) {
986  	    int lfname = strlen(fname);
987  	    if (strcmp(".MuDst.root",fname+lfname-11)==0){
988  	        tit.Replace(0,0," format=mudst ");
989  	    } else {
990  	        tit.Replace(0,0," format=root " );
991  	    }
992  	    known |= 1;
993  	//              ... now try to know branch name
994  	    TString bran = fname;
995  	    bran.ReplaceAll(".root","");
996  	    i = bran.Last('.');
997  	    if (i>0) {
998  	      bran.Replace(0,i+1,"");
999  	      known = 3;
1000 	      i = tit.Index("branch=NONE"); assert(i>=0);
1001 	      tit.Replace(i+7,4,bran);
1002 	      goto RETN;
1003 	    }
1004 	
1005 	
1006 	//              ... branch name still unknown
1007 	
1008 	    tf = TFile::Open(fname,"READ");
1009 	    assert(tf && !tf->IsZombie());
1010 	    TList *kl = gFile->GetListOfKeys();
1011 	    TIter nextKey(kl);
1012 	    TKey *ky;
1013 	    while ((ky = (TKey*)nextKey())) {
1014 	      if (strcmp("StIOEvent",ky->GetClassName()))       continue;
1015 	      const char *bra=ky->GetName();
1016 	      if (strstr(bra,"tree"))                           continue;
1017 	      if (strstr(bra,"Tree"))                           continue;
1018 	      if (strstr(bra,".")==0)				continue;
1019 	      i = tit.Index("branch=NONE"); assert(i>=0);
1020 	      tit.Replace(i+7,4,bra,strcspn(bra,"."));
1021 	      break;
1022 	  } }
1023 	
1024 	RETN:;
1025 	  delete tf;
1026 	  ds->SetTitle(tit);
1027 	}
1028 	//_____________________________________________________________________________
1029 	void StFile::ls(Option_t *opt)
1030 	{
1031 	   if (!fDS) return;
1032 	   if (opt && *opt ) {lsFull(opt); return;}
1033 	   TDataSetIter famIter(fDS);
1034 	   TDataSet *fam,*fil;
1035 	   int num = 0;
1036 	   while((fam=famIter.Next())) {
1037 	     if (!fam->First()) continue;
1038 	     TDataSetIter filIter(fam);
1039 	     while((fil=filIter.Next())) {
1040 	       const char *fname = strstr(fil->GetTitle(),"file=");
1041 	       if (!fname) continue;
1042 	       num++;
1043 	       printf("%3d - %s\n",num,fname+5);
1044 	     }
1045 	   }
1046 	}
1047 	//_____________________________________________________________________________
1048 	void StFile::lsFull(Option_t *opt)
1049 	{
1050 	  TList blist;
1051 	  int ibr=0,i;
1052 	  Cat *cat;
1053 	  int savIter = fIter; fIter=-1;
1054 	  int numFile=0;
1055 	  TString oldirname("_");
1056 	  while (!GetNextBundle()) {    //Bundle loop
1057 	    for (int idx=0; idx<999; idx++) {   //File loop
1058 	      const char *fil = GetFileName(idx);
1059 	      if (!fil)         break;
1060 	      numFile++;
1061 	      TString dirname = gSystem->DirName(fil);
1062 	      TString basname = gSystem->BaseName(fil);
1063 	      TString br(basname);
1064 	      i = br.Last('.'); if (i<0) continue;
1065 	      br.Replace(i,999,"");
1066 	      i = br.Last('.');
1067 	      if (i<0) { br = "undef";} else { br.Replace(0,i+1,"");};
1068 	
1069 	      if (oldirname != dirname) {
1070 	        printf("\nDirName  =%s\n\n",dirname.Data());
1071 	        oldirname.Replace(0,999,dirname);}
1072 	
1073 	      cat = (Cat*)(blist.FindObject(br));
1074 	      if (!cat) { cat = new Cat(); cat->SetName(br); blist.Add(cat);}
1075 	      cat->fNFiles++;
1076 	
1077 	      TFile *tf = 0;
1078 	      if (opt && opt[0]=='r')	tf = StIO::Open(fil,"update");
1079 	      if (!tf) 			tf = StIO::Open(fil,"read"  );
1080 	      if (!tf) 			continue;
1081 	
1082 	      TList *keys = tf->GetListOfKeys();
1083 	      int nkeys=0,nreks=0;
1084 	      double dsize=0;
1085 	
1086 	      TIter nextk(keys);
1087 	      TKey *key;
1088 	      while ((key=(TKey*)nextk())) {    //Key loop
1089 	        TString keyname(key->GetName());
1090 	        i = keyname.First('.');
1091 	        if (i>0) keyname.Replace(i,9999,"");
1092 	        keyname.ReplaceAll("Branch","");
1093 	        cat = (Cat*)(blist.FindObject(keyname));
1094 	        if (!cat) {
1095 	          cat = new Cat();
1096 	          cat->SetName(keyname);
1097 	          blist.Add(cat);
1098 	        }
1099 	        nkeys++;
1100 	        cat->fNKeys++;
1101 	        if (keyname==br) { nreks++;  cat->fNRecs++;};
1102 	        dsize +=      key->GetObjlen();
1103 	        cat->fSize += key->GetObjlen();
1104 	        TString clasname(key->GetClassName());
1105 	        cat = (Cat*)(blist.FindObject(clasname));
1106 	        if (!cat) {
1107 	          cat = new Cat();
1108 	          cat->SetName(clasname);
1109 	          blist.Add(cat);
1110 	        }
1111 	        cat->fNKeys++;
1112 	        cat->fSize += key->GetObjlen();
1113 	
1114 	      }// End key loop
1115 	      dsize/=1000000.;
1116 	      printf("%4d BR=%-7s NK=%-4d NR=%-4d SZ=%8.2fM File= %s\n",
1117 	             numFile,br.Data(),nkeys,nreks,dsize,basname.Data());
1118 	      delete tf;
1119 	
1120 	//  printf("%4d %s\n",numFile,fil);
1121 	    } //*end File loop*/
1122 	  }//*end Bundle loop*/
1123 	
1124 	  printf("\n\n  In Total ==================================================\n");
1125 	  blist.Sort();
1126 	  TIter nextBr(&blist);
1127 	  ibr = 0;
1128 	  while ( (cat = (Cat*)nextBr())){
1129 	    ibr++;
1130 	    printf("%4d BR=%-10s NK=%-4d NR=%-4d SZ=%8.2fM NFiles %4d\n",
1131 	             ibr,
1132 	             cat->GetName(),
1133 	             cat->fNKeys,
1134 	             cat->fNRecs,
1135 	             cat->fSize*1.e-6,
1136 	             cat->fNFiles);
1137 	  }
1138 	  blist.Delete();
1139 	  fIter = savIter;
1140 	}
1141 	//_____________________________________________________________________________
1142 	const char *StFile::GetAttr(TDataSet *ds,const char *att)
1143 	{
1144 	  static TString brName;
1145 	  if (!ds) return 0;
1146 	  SetInfo(ds);
1147 	  const char *bn = strstr(ds->GetTitle(),att);
1148 	  if (!bn) return 0;
1149 	  bn += strlen(att);
1150 	  int n = strcspn(bn," ");
1151 	  brName.Replace(0,999,bn,n);
1152 	  return (const char*)brName;
1153 	}
1154