StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TFileIter.cxx
1 // @(#)root/table:$Id$
2 // Author: Valery Fine(fine@bnl.gov) 01/03/2001
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * Copyright (C) 2001 [BNL] Brookhaven National Laboratory. *
7  * All rights reserved. *
8  * *
9  * For the licensing terms see $ROOTSYS/LICENSE. *
10  * For the list of contributors see $ROOTSYS/README/CREDITS. *
11  *************************************************************************/
12 
14 // //
15 // Class to iterate (read / write ) the events written to TFile. //
16 // The event is supposed to assign an unique ID in form of //
17 // //
18 // TKey <event Id> ::= eventName "." run_number "." event_number //
19 // //
20 // and stored as the TKey name of the object written //
21 // //
22 // /////// ////////// //////// /////// //////
23 //
24 // void TesTFileIter(){
25 // // This macros tests the various methods of TFileIter class.
26 // gSystem->Load("libTable");
27 //
28 // //First create simple ROOT file
29 // TDataSet *ds = new TDataSet("event");
30 // TObject *nextObject = 0;
31 // TRandom run;
32 // TRandom event;
33 // {
34 // TFileIter outSet("test.root","RECREATE");
35 // UInt_t totalEvent = 10;
36 // UInt_t runNumber = 20010301;
37 // Int_t i=0;
38 // Int_t j=0;
39 // for (;j < 10;j++) {
40 // for (i = 1;i<totalEvent;i++) {
41 // outSet.NextEventPut(ds,UInt_t(i),UInt_t(runNumber+j+10*run.Rndm()-5));
42 // }
43 // }
44 // }
45 // printf(" ----------------------> TFile has been created <--------------------\n");
46 // TFile *f = new TFile("test.root");
47 // TFileIter readObj(f);
48 // // the number of the object available directly from "MyDataSet.root"
49 // Int_t size = readObj.TotalKeys();
50 // printf(" The total number of the objects: %d\n",size);
51 //
52 // //-----------------------------------------------------------------------
53 // // Loop over all objects, read them in to memory one by one
54 //
55 // printf(" -- > Loop over all objects, read them in to memory one by one < -- \n");
56 // for( readObj = 0; int(readObj) < size; ++readObj){
57 // nextObject = *readObj;
58 // printf(" %d bytes of the object \"%s\" of class \"%s\" written with TKey \"%s\" has been read from file\n"
59 // ,readObj.GetObjlen()
60 // ,nextObject->GetName()
61 // ,nextObject->IsA()->GetName()
62 // ,(const char *)readObj
63 // );
64 // delete nextObject;
65 // }
66 // //-----------------------------------------------------------------------
67 // // Now loop over all objects in inverse order
68 // printf(" -- > Now loop over all objects in inverse order < -- \n");
69 // for( readObj = size-1; (int)readObj >= 0; --readObj)
70 // {
71 // nextObject = *readObj;
72 // if (nextObject) {
73 // printf(" Object \"%s\" of class \"%s\" written with TKey \"%s\" has been read from file\n"
74 // ,nextObject->GetName()
75 // , nextObject->IsA()->GetName()
76 // ,(const char *)readObj
77 // );
78 // delete nextObject;
79 // } else {
80 // printf("Error reading file by index\n");
81 // }
82 // }
83 // //-----------------------------------------------------------------------
84 // // Loop over the objects starting from the object with the key name "event.02.01"
85 // printf(" -- > Loop over the objects starting from the object with the key name \"event.02.01\" < -- \n");
86 // for( readObj = "event.02.01"; (const char *)readObj != 0; ++readObj){
87 // nextObject = *readObj;
88 // printf(" Object \"%s\" of class \"%s\" written with Tkey \"%s\" has been read from file\n"
89 // , nextObject->GetName()
90 // , nextObject->IsA()->GetName()
91 // , (const char *)readObj
92 // );
93 // delete nextObject;
94 // }
95 //
96 // printf(" -- > Loop over the objects starting from the 86-th object" < -- \n");
97 // for( readObj = (const char *)(readObj = 86); (const char *)readObj != 0; ++readObj){
98 // nextObject = *readObj;
99 // printf(" Object \"%s\" of class \"%s\" written with Tkey \"%s\" has been read from file\n"
100 // , nextObject->GetName()
101 // , nextObject->IsA()->GetName()
102 // , (const char *)readObj
103 // );
104 // delete nextObject;
105 // }
106 //
107 // }
108 //-----------------------------------------------------------------------
110 
111 
112 #include <assert.h>
113 
114 #include "TEnv.h"
115 #include "TSystem.h"
116 #include "TFile.h"
117 #include "TKey.h"
118 
119 #include "TFileIter.h"
120 #include "TDsKey.h"
121 
122 ClassImp(TFileIter);
123 
126 
127 TFileIter::TFileIter(TFile *file) : fNestedIterator(0)
128  , fRootFile(file)
129  , fEventName("event"), fRunNumber(UInt_t(-1)),fEventNumber(UInt_t(-1))
130  , fCursorPosition(-1), fOwnTFile(kFALSE)
131 {
132  Initialize();
133 }
134 
137 
138 TFileIter::TFileIter(TDirectory *directory) : fNestedIterator(0)
139  , fRootFile(directory)
140  , fEventName("event"), fRunNumber(UInt_t(-1)),fEventNumber(UInt_t(-1))
141  , fCursorPosition(-1), fOwnTFile(kFALSE)
142 {
143  Initialize();
144 }
148 
149 TFileIter::TFileIter(const char *name, Option_t *option, const char *ftitle
150  , Int_t compress, Int_t /*netopt*/) : fNestedIterator(0)
151  ,fRootFile(0)
152  ,fEventName("event"), fRunNumber(UInt_t(-1)) ,fEventNumber(UInt_t(-1))
153  ,fCursorPosition(-1), fOwnTFile(kFALSE)
154 {
155  if (name && name[0]) {
156  fOwnTFile = kTRUE;
157  // Map a special file system to rfio
158  // /hpss/in2p3.fr/group/atlas/cppm/data/genz
159  // #setenv HPSSIN bnlhpss:/home/atlasgen/evgen
160  // #example for castor: /castor/cern.ch/user/p/paniccia/evgen
161  fRootFile = TFile::Open(MapName(name),option,ftitle,compress);
162  Initialize();
163  }
164 }
165 
170 
171 TFileIter::TFileIter(const TFileIter &dst) : TListIter()
172  , fNestedIterator(0)
173  ,fRootFile(dst.fRootFile),fEventName(dst.fEventName), fRunNumber(dst.fRunNumber)
174  ,fEventNumber(dst.fRunNumber),
175  fCursorPosition(-1), fOwnTFile(dst.fOwnTFile)
176 {
177  if (fRootFile && fOwnTFile) {
178  // Reopen the file
179  if (fRootFile->InheritsFrom(TFile::Class()))
180  {
181  TFile *thisFile = (TFile *)fRootFile;
182  fRootFile = TFile::Open(MapName(fRootFile->GetName())
183  ,fRootFile->GetOption()
184  ,fRootFile->GetTitle()
185  ,thisFile->GetCompressionSettings());
186  }
187  }
188 
189  Initialize();
190  // Adjust this iterator position
191  SkipObjects(dst.fCursorPosition);
192 }
195 
197 {
198  TFileIter *deleteit = fNestedIterator; fNestedIterator = 0;
199  delete deleteit;
200  if (fRootFile && fOwnTFile ) { // delete own TFile if any
201  if (fRootFile->IsWritable()) fRootFile->Write();
202  fRootFile->Close();
203  delete fRootFile;
204  fRootFile = 0;
205  }
206 }
207 
210 
212 {
213  if (fRootFile) {
214  fDirection = kIterForward;
215  if (IsOpen()) Reset();
216  else {
217  if (fRootFile && fOwnTFile ) delete fRootFile;
218  fRootFile = 0;
219  }
220  }
221 }
225 
226 Bool_t TFileIter::IsOpen() const
227 {
228  Bool_t iOpen = kFALSE;
229  if (fRootFile && !fRootFile->IsZombie() ) {
230  iOpen = kTRUE;
231  if (fRootFile->InheritsFrom(TFile::Class()) && !((TFile*)fRootFile)->IsOpen())
232  iOpen = kFALSE;
233  }
234  return iOpen;
235 }
236 
239 
241 {
242  return ((TFileIter*)this)->SkipObjects(0);
243 }
247 
248 Int_t TFileIter::GetDepth() const
249 {
250  return fNestedIterator ? fNestedIterator->GetDepth()+1 : 0;
251 }
252 
255 
256 const char *TFileIter::GetKeyName() const
257 {
258  const char *name = 0;
259  TKey *key = GetCurrentKey();
260  if (key) name = key->GetName();
261  return name;
262 }
272 
273 TObject *TFileIter::GetObject() const
274 {
275  return ReadObj(GetCurrentKey());
276 }
279 
280 Int_t TFileIter::GetObjlen() const
281 {
282  Int_t lenObj = 0;
283  TKey *key = GetCurrentKey();
284  if (key) lenObj = ((TKey *)key)->GetObjlen();
285  return lenObj;
286 }
293 
294 Int_t TFileIter::TotalKeys() const
295 {
296  Int_t size = 0;
297  if(fList) size += fList->GetSize();
298  return size;
299 }
304 
305 TObject *TFileIter::Next(Int_t nSkip)
306 {
307  SkipObjects(nSkip);
308  return GetObject();
309 }
310 
315 
316 void TFileIter::PurgeKeys(TList *listOfKeys)
317 {
318  assert(listOfKeys);
319  listOfKeys->Sort();
320  TObjLink *lnk = listOfKeys->FirstLink();
321  while(lnk) {
322  TKey *key = (TKey *)lnk->GetObject();
323  Short_t cycle = key->GetCycle();
324  const char *keyName = key->GetName();
325  // Check next object
326  lnk = lnk->Next();
327  if (lnk) {
328  TKey *nextkey = 0;
329  TObjLink *lnkThis = lnk;
330  while ( lnk
331  && (nextkey = (TKey *)lnk->GetObject())
332  && !strcmp(nextkey->GetName(), keyName)
333  ) {
334  // compare the cycles
335  Short_t nextCycle = nextkey->GetCycle() ;
336  //printf(" TFileIter::PurgeKeys found new cycle %s :%d : %d\n",
337  // keyName,cycle ,nextCycle);
338  assert(cycle != nextCycle);
339  TObjLink *lnkNext = lnk->Next();
340  if (cycle > nextCycle ) {
341  delete listOfKeys->Remove(lnk);
342  } else {
343  delete listOfKeys->Remove(lnkThis);
344  cycle = nextCycle;
345  lnkThis = lnk;
346  }
347  lnk = lnkNext;
348  }
349  }
350  }
351 }
352 
355 
357 {
358  if (fNestedIterator) {
359  TFileIter *it = fNestedIterator;
360  fNestedIterator=0;
361  delete it;
362  }
363  TListIter::Reset();
364  if (!fRootFile->IsWritable()) {
365  TList *listOfKeys = fRootFile->GetListOfKeys();
366  if (listOfKeys) {
367  if (!listOfKeys->IsSorted()) PurgeKeys(listOfKeys);
368  fList = listOfKeys;
369  if (fDirection == kIterForward) {
370  fCursorPosition = 0;
371  fCurCursor = fList->FirstLink()->shared_from_this();
372  if (fCurCursor) fCursor = fCurCursor->NextSP();
373  } else {
374  fCursorPosition = fList->GetSize()-1;
375  fCurCursor = fList->LastLink()->shared_from_this();
376  if (fCurCursor) fCursor = fCurCursor->PrevSP();
377  }
378  }
379  }
380 }
383 
384 void TFileIter::SetCursorPosition(const char *keyNameToFind)
385 {
386  Reset();
387  while( (*this != keyNameToFind) && SkipObjects() ) {;}
388 }
400 
401 TKey *TFileIter::SkipObjects(Int_t nSkip)
402 {
403  TKey *nextObject = fNestedIterator ? fNestedIterator->SkipObjects(nSkip): 0;
404  if (!nextObject) {
405  if (fNestedIterator) {
406  TFileIter *it = fNestedIterator;
407  fNestedIterator = 0;
408  delete it;
409  }
410  Int_t collectionSize = 0;
411  if (fList && (collectionSize = fList->GetSize()) ) {
412  if (fDirection !=kIterForward) nSkip = -nSkip;
413  Int_t newPos = fCursorPosition + nSkip;
414  if (0 <= newPos && newPos < collectionSize) {
415  do {
416  if (fCursorPosition < newPos) {
417  fCursorPosition++;
418  fCurCursor = fCursor;
419  fCursor = fCursor->NextSP();
420  } else if (fCursorPosition > newPos) {
421  fCursorPosition--;
422  fCurCursor = fCursor;
423  fCursor = fCursor->PrevSP();
424  }
425  } while (fCursorPosition != newPos);
426  if (fCurCursor) nextObject = dynamic_cast<TKey *>(fCurCursor->GetObject());
427  } else {
428  fCurCursor = fCursor = 0;
429  if (newPos < 0) {
430  fCursorPosition = -1;
431  if (fList) fCursor = fList->FirstLink()->shared_from_this();
432  } else {
433  fCursorPosition = collectionSize;
434  if (fList) fCursor = fList->LastLink()->shared_from_this();
435  }
436  }
437  }
438  }
439  return nextObject;
440 }
442 
443 TKey *TFileIter::NextEventKey(UInt_t eventNumber, UInt_t runNumber, const char *name)
444 {
445  // Return the key that name matches the "event" . "run number" . "event number" schema
446 
447  Bool_t reset = kFALSE;
448  if (name && name[0] && name[0] != '*') { if (fEventName > name) reset = kTRUE; fEventName = name; }
449  if (runNumber !=UInt_t(-1) ) { if (fRunNumber > runNumber) reset = kTRUE; fRunNumber = runNumber;}
450  if (eventNumber !=UInt_t(-1) ) { if (fEventNumber > eventNumber) reset = kTRUE; fEventNumber = eventNumber;}
451 
452  if (reset) Reset();
453  // TIter &nextKey = *fKeysIterator;
454  TKey *key = 0;
455  TDsKey thisKey;
456  while ( (key = SkipObjects()) ) {
457  if (fDirection==kIterForward) fCursorPosition++;
458  else fCursorPosition--;
459  if ( name && name[0] != '*') {
460  thisKey.SetKey(key->GetName());
461  if (thisKey.GetName() < name) continue;
462  if (thisKey.GetName() > name) { key = 0; break; }
463  }
464  // Check "run number"
465  if (runNumber != UInt_t(-1)) {
466  UInt_t thisRunNumber = thisKey.RunNumber();
467  if (thisRunNumber < runNumber) continue;
468  if (thisRunNumber > runNumber) { key = 0; break; }
469  }
470  // Check "event number"
471  if (eventNumber != UInt_t(-1)) {
472  UInt_t thisEventNumber = thisKey.EventNumber();
473  if (thisEventNumber < eventNumber) continue;
474  if (thisEventNumber > eventNumber) {key = 0; break; }
475  }
476  break;
477  }
478  return key;
479 }
486 
487 TObject *TFileIter::NextEventGet(UInt_t eventNumber, UInt_t runNumber, const char *name)
488 {
489  return ReadObj(NextEventKey(eventNumber,runNumber,name));
490 }
491 
494 
495 TObject *TFileIter::ReadObj(const TKey *key) const
496 {
497  TObject *obj = 0;
498  if (fNestedIterator) obj = fNestedIterator->ReadObj(key);
499  else if (key) {
500  obj = ((TKey *)key)->ReadObj();
501  if (obj && obj->InheritsFrom(TDirectory::Class()) )
502  {
503  // create the next iteration level.
504  assert(!fNestedIterator);
505  ((TFileIter*)this)->fNestedIterator = new TFileIter((TDirectory *)obj);
506  // FIXME: needs to set fDirection if needed 02/11/2007 vf
507  }
508  }
509  return obj;
510 }
511 
514 
515 Int_t TFileIter::NextEventPut(TObject *obj, UInt_t eventNum, UInt_t runNumber
516  , const char *name)
517 {
518  Int_t wBytes = 0;
519  if (obj && IsOpen() && fRootFile->IsWritable()) {
520  TDsKey thisKey(runNumber,eventNum);
521  if (name && name[0])
522  thisKey.SetName(name);
523  else
524  thisKey.SetName(obj->GetName());
525 
526  TDirectory::TContext ctxt(fRootFile); // Store the current directory, cd to fRootFile and at the end of the block restore the current directory.
527 
528  wBytes = obj->Write(thisKey.GetKey());
529  if (fRootFile->InheritsFrom(TFile::Class())) ((TFile*)fRootFile)->Flush();
530  }
531  return wBytes;
532 }
546 
547 TString TFileIter::MapName(const char *name, const char *localSystemKey,const char *mountedFileSystemKey)
548 {
549  // 2. If the "io.config" file found then it defines the mapping as follows:
550  //
551  // TFileIter.LocalFileSystem /castor
552  // TFileIter.MountedFileSystem rfio:/castor
553 
554  // If "io.config" doesn't exist then no mapping is to be performed
555  // and all file names are treated "as is"
556 
557  if ( !localSystemKey) localSystemKey = GetLocalFileNameKey();
558  if ( !mountedFileSystemKey) mountedFileSystemKey = GetForeignFileSystemKey();
559  TString newName = name;
560  TString fileMap = gEnv->GetValue(GetResourceName(),GetDefaultMapFileName());
561  const char *localName = 0;
562  const char *foreignName = 0;
563  if ( gSystem->AccessPathName(fileMap) == 0 ){
564  TEnv myMapResource(fileMap);
565  localName = myMapResource.Defined(localSystemKey) ?
566  myMapResource.GetValue(localSystemKey,"") : 0;
567  foreignName = myMapResource.Defined(mountedFileSystemKey) ?
568  myMapResource.GetValue(mountedFileSystemKey,""):0;
569  } else {
570  localName = "/castor"; // This is the default CERN name
571  foreignName = "rfio:/castor"; // and it needs "RFIO"
572  }
573  if (localName && localName[0]
574  && foreignName
575  && foreignName[0]
576  && newName.BeginsWith(localName) )
577  newName.Replace(0,strlen(localName),foreignName);
578  return newName;
579 }
virtual ~TFileIter()
TFileIter dtor.
Definition: TFileIter.cxx:196
virtual Int_t GetDepth() const
Definition: TFileIter.cxx:248
const char * GetKeyName() const
return the name of the current TKey
Definition: TFileIter.cxx:256
TKey * GetCurrentKey() const
return the pointer to the current TKey
Definition: TFileIter.cxx:240
TObject * ReadObj(const TKey *key) const
Read the next TObject from for the TDirectory by TKey provided.
Definition: TFileIter.cxx:495
virtual TObject * NextEventGet(UInt_t eventNumber=UInt_t(-1), UInt_t runNumber=UInt_t(-1), const char *name="*")
Definition: TFileIter.cxx:487
static TString MapName(const char *name, const char *localSystemKey=0, const char *mountedFileSystemKey=0)
Definition: TFileIter.cxx:547
virtual Int_t NextEventPut(TObject *obj, UInt_t eventNum, UInt_t runNumber, const char *name=0)
Create a special TKey name with obj provided and write it out.
Definition: TFileIter.cxx:515
virtual TObject * GetObject() const
Definition: TFileIter.cxx:273
virtual TString GetKey() const
to be documented
Definition: TDsKey.cxx:111
void Initialize()
to be documented
Definition: TFileIter.cxx:211
virtual Bool_t IsOpen() const
Definition: TFileIter.cxx:226
virtual Int_t TotalKeys() const
Definition: TFileIter.cxx:294
virtual void Reset()
Reset the status of the iterator.
Definition: TFileIter.cxx:356
virtual TKey * SkipObjects(Int_t nSkip=1)
Definition: TFileIter.cxx:401
TFileIter(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Definition: TFileIter.cxx:149
Definition: TDsKey.h:21
static void PurgeKeys(TList *listOfKeys)
Definition: TFileIter.cxx:316
Int_t GetObjlen() const
Returns the uncompressed length of the current object.
Definition: TFileIter.cxx:280
virtual void SetKey(const char *key)
to be documented
Definition: TDsKey.cxx:126