ROOT  6.06/09
Reference Guide
TDirectoryFile.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Rene Brun 22/01/2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**
13  \class TDirectoryFile
14  \ingroup IO
15 
16  A ROOT file is structured in Directories (like a file system).
17  Each Directory has a list of Keys (see TKeys) and a list of objects
18  in memory. A Key is a small object that describes the type and location
19  of a persistent object in a file. The persistent object may be a directory.
20 Begin_Macro
21 ../../../tutorials/io/fildir.C
22 End_Macro
23  The structure of a file is shown in TFile::TFile
24 */
25 
26 #include "Riostream.h"
27 #include "Strlen.h"
28 #include "TDirectoryFile.h"
29 #include "TFile.h"
30 #include "TBufferFile.h"
31 #include "TMapFile.h"
32 #include "TClassTable.h"
33 #include "TInterpreter.h"
34 #include "THashList.h"
35 #include "TBrowser.h"
36 #include "TFree.h"
37 #include "TKey.h"
38 #include "TStreamerInfo.h"
39 #include "TROOT.h"
40 #include "TError.h"
41 #include "Bytes.h"
42 #include "TClass.h"
43 #include "TRegexp.h"
44 #include "TSystem.h"
45 #include "TStreamerElement.h"
46 #include "TProcessUUID.h"
47 #include "TVirtualMutex.h"
49 
50 const UInt_t kIsBigFile = BIT(16);
51 const Int_t kMaxLen = 2048;
52 
54 
55 
56 ////////////////////////////////////////////////////////////////////////////////
57 /// Default Constructor
58 
60  , fModified(kFALSE), fWritable(kFALSE), fNbytesKeys(0), fNbytesName(0)
61  , fBufferSize(0), fSeekDir(0), fSeekParent(0), fSeekKeys(0)
62  , fFile(0), fKeys(0)
63 {
64 }
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 /// Create a new TDirectoryFile
68 ///
69 /// A new directory with a name and a title is created in the current directory.
70 /// The directory header information is immediatly saved on the file
71 /// A new key is added in the parent directory.
72 /// When this constructor is called from a class directly derived
73 /// from TDirectoryFile, the third argument, classname, MUST be specified.
74 /// In this case, classname must be the name of the derived class.
75 ///
76 /// Note that the directory name cannot contain slashes.
77 
78 TDirectoryFile::TDirectoryFile(const char *name, const char *title, Option_t *classname, TDirectory* initMotherDir)
80  , fModified(kFALSE), fWritable(kFALSE), fNbytesKeys(0), fNbytesName(0)
81  , fBufferSize(0), fSeekDir(0), fSeekParent(0), fSeekKeys(0)
82  , fFile(0), fKeys(0)
83 {
84  fName = name;
85  fTitle = title;
86 
87  if (initMotherDir==0) initMotherDir = gDirectory;
88 
89  if (strchr(name,'/')) {
90  ::Error("TDirectoryFile","directory name (%s) cannot contain a slash", name);
91  gDirectory = 0;
92  return;
93  }
94  if (strlen(GetName()) == 0) {
95  ::Error("TDirectoryFile","directory name cannot be \"\"");
96  gDirectory = 0;
97  return;
98  }
99 
100  Build(initMotherDir ? initMotherDir->GetFile() : 0, initMotherDir);
101 
102  TDirectory* motherdir = GetMotherDir();
103  TFile* f = GetFile();
104 
105  if ((motherdir==0) || (f==0)) return;
106  if (!f->IsWritable()) return; //*-* in case of a directory in memory
107  if (motherdir->GetKey(name)) {
108  Error("TDirectoryFile","An object with name %s exists already", name);
109  return;
110  }
111  TClass *cl = 0;
112  if (classname[0]) {
113  cl = TClass::GetClass(classname);
114  if (!cl) {
115  Error("TDirectoryFile","Invalid class name: %s",classname);
116  return;
117  }
118  } else {
119  cl = IsA();
120  }
121 
122  fBufferSize = 0;
123  fWritable = kTRUE;
124 
125  Init(cl);
126 
127  fModified = kFALSE;
128 
130  gROOT->GetUUIDs()->AddUUID(fUUID,this);
131 }
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 /// Initialize the key associated with this directory (and the related
135 /// data members.
136 
138 {
139  TFile* f = GetFile();
140  if (f->IsBinary()) {
141  if (cl==0) {
142  cl = IsA();
143  }
144  TDirectory* motherdir = GetMotherDir();
145  fSeekParent = f->GetSeekDir();
146  Int_t nbytes = TDirectoryFile::Sizeof();
147  TKey *key = new TKey(fName,fTitle,cl,nbytes,motherdir);
148  fNbytesName = key->GetKeylen();
149  fSeekDir = key->GetSeekKey();
150  if (fSeekDir == 0) return;
151  char *buffer = key->GetBuffer();
153  Int_t cycle = motherdir ? motherdir->AppendKey(key) : 0;
154  key->WriteFile(cycle);
155  } else {
156  fSeekParent = 0;
157  fNbytesName = 0;
158  fSeekDir = f->DirCreateEntry(this);
159  if (fSeekDir == 0) return;
160  }
161 
162 }
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// Copy constructor.
166 
167 TDirectoryFile::TDirectoryFile(const TDirectoryFile & directory) : TDirectory(directory)
168  , fModified(kFALSE), fWritable(kFALSE), fNbytesKeys(0), fNbytesName(0)
169  , fBufferSize(0), fSeekDir(0), fSeekParent(0), fSeekKeys(0)
170  , fFile(0), fKeys(0)
171 {
172  ((TDirectoryFile&)directory).Copy(*this);
173 }
174 
175 ////////////////////////////////////////////////////////////////////////////////
176 /// Destructor.
177 
179 {
180  if (fKeys) {
181  fKeys->Delete("slow");
182  SafeDelete(fKeys);
183  }
184 
185  CleanTargets();
186 
187  // Delete our content before we become somewhat invalid
188  // since some those objects (TTree for example) needs information
189  // from this object. Note that on some platform after the end
190  // of the body (i.e. thus during ~TDirectory which is also
191  // contains this code) the exeuction of 'this->GetFile()' fails
192  // to return the 'proper' value (because it uses the wrong
193  // virtual function).
194  if (fList) {
195  fList->Delete("slow");
196  SafeDelete(fList);
197  }
198 
199  if (gDebug) {
200  Info("~TDirectoryFile", "dtor called for %s", GetName());
201  }
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Append object to this directory.
206 ///
207 /// If replace is true:
208 /// remove any existing objects with the same same (if the name is not ""
209 
210 void TDirectoryFile::Append(TObject *obj, Bool_t replace /* = kFALSE */)
211 {
212  if (obj == 0 || fList == 0) return;
213 
214  TDirectory::Append(obj,replace);
215 
216  if (!fMother) return;
217  if (fMother->IsA() == TMapFile::Class()) {
218  TMapFile *mfile = (TMapFile*)fMother;
219  mfile->Add(obj);
220  }
221 }
222 
223 ////////////////////////////////////////////////////////////////////////////////
224 /// Insert key in the linked list of keys of this directory.
225 
227 {
228  fModified = kTRUE;
229 
230  key->SetMotherDir(this);
231 
232  // This is a fast hash lookup in case the key does not already exist
233  TKey *oldkey = (TKey*)fKeys->FindObject(key->GetName());
234  if (!oldkey) {
235  fKeys->Add(key);
236  return 1;
237  }
238 
239  // If the key name already exists we have to make a scan for it
240  // and insert the new key ahead of the current one
241  TObjLink *lnk = fKeys->FirstLink();
242  while (lnk) {
243  oldkey = (TKey*)lnk->GetObject();
244  if (!strcmp(oldkey->GetName(), key->GetName()))
245  break;
246  lnk = lnk->Next();
247  }
248 
249  fKeys->AddBefore(lnk, key);
250  return oldkey->GetCycle() + 1;
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// Browse the content of the directory.
255 
257 {
258  TString name;
259 
260  if (b) {
261  TObject *obj = 0;
262  TIter nextin(fList);
263  TKey *key = 0, *keyo = 0;
264  TIter next(fKeys);
265 
266  cd();
267 
268  //Add objects that are only in memory
269  while ((obj = nextin())) {
270  if (fKeys->FindObject(obj->GetName())) continue;
271  b->Add(obj, obj->GetName());
272  }
273 
274  //Add keys
275  while ((key = (TKey *) next())) {
276  int skip = 0;
277  if (!keyo || (keyo && strcmp(keyo->GetName(), key->GetName()))) {
278  skip = 0;
279  obj = fList->FindObject(key->GetName());
280 
281  if (obj) {
282  b->Add(obj, obj->GetName());
283  if (obj->IsFolder() && !obj->InheritsFrom("TTree"))
284  skip = 1;
285  }
286  }
287 
288  if (!skip) {
289  name.Form("%s;%d", key->GetName(), key->GetCycle());
290  b->Add(key, name);
291  }
292 
293  keyo = key;
294  }
295  }
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Initialise directory to defaults.
300 
301 void TDirectoryFile::Build(TFile* motherFile, TDirectory* motherDir)
302 {
303  // If directory is created via default ctor (when dir is read from file)
304  // don't add it here to the directory since its name is not yet known.
305  // It will be added to the directory in TKey::ReadObj().
306 
307  if (motherDir && strlen(GetName()) != 0) motherDir->Append(this);
308 
309  fModified = kTRUE;
310  fWritable = kFALSE;
311  fDatimeC.Set();
312  fDatimeM.Set();
313  fNbytesKeys = 0;
314  fSeekDir = 0;
315  fSeekParent = 0;
316  fSeekKeys = 0;
317  fList = new THashList(100,50);
318  fKeys = new THashList(100,50);
319  fMother = motherDir;
320  fFile = motherFile ? motherFile : TFile::CurrentFile();
322 }
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Change current directory to "this" directory.
326 /// Using path one can
327 /// change the current directory to "path". The absolute path syntax is:
328 ///
329 /// file.root:/dir1/dir2
330 ///
331 /// where file.root is the file and /dir1/dir2 the desired subdirectory
332 /// in the file. Relative syntax is relative to "this" directory. E.g:
333 /// ../aa. Returns kTRUE in case of success.
334 
335 Bool_t TDirectoryFile::cd(const char *path)
336 {
337  Bool_t ok = TDirectory::cd(path);
338  if (ok) TFile::CurrentFile() = fFile;
339  return ok;
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Clean the pointers to this object (gDirectory, TContext, etc.)
344 
346 {
347 
348  // After CleanTargets either gFile was changed appropriately
349  // by a cd() or needs to be set to zero.
350  if (gFile == this) {
351  gFile = 0;
352  }
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Make a clone of an object using the Streamer facility.
358 ///
359 /// If the object derives from TNamed, this function is called
360 /// by TNamed::Clone. TNamed::Clone uses the optional argument newname to set
361 /// a new name to the newly created object.
362 ///
363 /// If autoadd is true and if the object class has a
364 /// DirectoryAutoAdd function, it will be called at the end of the
365 /// function with the parameter gDirectory. This usually means that
366 /// the object will be appended to the current ROOT directory.
367 
368 TObject *TDirectoryFile::CloneObject(const TObject *obj, Bool_t autoadd /* = kTRUE */)
369 {
370  // if no default ctor return immediately (error issued by New())
371  char *pobj = (char*)obj->IsA()->New();
372  if (!pobj) return 0;
373 
374  Int_t baseOffset = obj->IsA()->GetBaseClassOffset(TObject::Class());
375  if (baseOffset==-1) {
376  // cl does not inherit from TObject.
377  // Since this is not supported in this function, the only reason we could reach this code
378  // is because something is screwed up in the ROOT code.
379  Fatal("CloneObject","Incorrect detection of the inheritance from TObject for class %s.\n",
380  obj->IsA()->GetName());
381  }
382  TObject *newobj = (TObject*)(pobj+baseOffset);
383 
384  //create a buffer where the object will be streamed
385  {
386  // NOTE: do we still need to make this change to gFile?
387  // NOTE: This can not be 'gDirectory=0' as at least roofit expect gDirectory to not be null
388  // during the streaming ....
389  TFile *filsav = gFile;
390  gFile = 0;
391  const Int_t bufsize = 10000;
392  TBufferFile buffer(TBuffer::kWrite,bufsize);
393  buffer.MapObject(obj); //register obj in map to handle self reference
394  {
395  Bool_t isRef = obj->TestBit(kIsReferenced);
396  ((TObject*)obj)->ResetBit(kIsReferenced);
397 
398  ((TObject*)obj)->Streamer(buffer);
399 
400  if (isRef) ((TObject*)obj)->SetBit(kIsReferenced);
401  }
402 
403  // read new object from buffer
404  buffer.SetReadMode();
405  buffer.ResetMap();
406  buffer.SetBufferOffset(0);
407  buffer.MapObject(newobj); //register obj in map to handle self reference
408  newobj->Streamer(buffer);
409  newobj->ResetBit(kIsReferenced);
410  newobj->ResetBit(kCanDelete);
411  gFile = filsav;
412  }
413 
414  if (autoadd) {
415  ROOT::DirAutoAdd_t func = obj->IsA()->GetDirectoryAutoAdd();
416  if (func) {
417  func(newobj,this);
418  }
419  }
420  return newobj;
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Scan the memory lists of all files for an object with name
425 
427 {
428  TFile *f;
430  TIter next(gROOT->GetListOfFiles());
431  while ((f = (TFile*)next())) {
432  TObject *obj = f->GetList()->FindObject(name);
433  if (obj) return obj;
434  }
435  return 0;
436 }
437 
438 
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// Find a directory named "apath".
442 ///
443 /// It apath is null or empty, returns "this" directory.
444 /// Otherwise use the name "apath" to find a directory.
445 /// The absolute path syntax is:
446 ///
447 /// file.root:/dir1/dir2
448 ///
449 /// where file.root is the file and /dir1/dir2 the desired subdirectory
450 /// in the file. Relative syntax is relative to "this" directory. E.g:
451 /// ../aa.
452 /// Returns 0 in case path does not exist.
453 /// If printError is true, use Error with 'funcname' to issue an error message.
454 
455 TDirectory *TDirectoryFile::GetDirectory(const char *apath,
456  Bool_t printError, const char *funcname)
457 {
458  Int_t nch = 0;
459  if (apath) nch = strlen(apath);
460  if (!nch) {
461  return this;
462  }
463 
464  if (funcname==0 || strlen(funcname)==0) funcname = "GetDirectory";
465 
466  TDirectory *result = this;
467 
468  char *path = new char[nch+1]; path[0] = 0;
469  if (nch) strlcpy(path,apath,nch+1);
470  char *s = (char*)strchr(path, ':');
471  if (s) {
472  *s = '\0';
474  TDirectory *f = (TDirectory *)gROOT->GetListOfFiles()->FindObject(path);
475  if (!f && !strcmp(gROOT->GetName(), path)) f = gROOT;
476  if (s) *s = ':';
477  if (f) {
478  result = f;
479  if (s && *(s+1)) result = f->GetDirectory(s+1,printError,funcname);
480  delete [] path; return result;
481  } else {
482  if (printError) Error(funcname, "No such file %s", path);
483  delete [] path; return 0;
484  }
485  }
486 
487  // path starts with a slash (assumes current file)
488  if (path[0] == '/') {
489  TDirectory *td = fFile;
490  if (!fFile) td = gROOT;
491  result = td->GetDirectory(path+1,printError,funcname);
492  delete [] path; return result;
493  }
494 
496  char *slash = (char*)strchr(path,'/');
497  if (!slash) { // we are at the lowest level
498  if (!strcmp(path, "..")) {
499  result = GetMotherDir();
500  delete [] path; return result;
501  }
502  GetObject(path,obj);
503  if (!obj) {
504  if (printError) Error(funcname,"Unknown directory %s", path);
505  delete [] path; return 0;
506  }
507 
508  delete [] path; return obj;
509  }
510 
511  TString subdir(path);
512  slash = (char*)strchr(subdir.Data(),'/');
513  *slash = 0;
514  //Get object with path from current directory/file
515  if (!strcmp(subdir, "..")) {
516  TDirectory* mom = GetMotherDir();
517  if (mom)
518  result = mom->GetDirectory(slash+1,printError,funcname);
519  delete [] path; return result;
520  }
521  GetObject(subdir,obj);
522  if (!obj) {
523  if (printError) Error(funcname,"Unknown directory %s", subdir.Data());
524  delete [] path; return 0;
525  }
526 
527  result = ((TDirectory*)obj)->GetDirectory(slash+1,printError,funcname);
528  delete [] path; return result;
529 }
530 
531 ////////////////////////////////////////////////////////////////////////////////
532 /// Delete all objects from memory and directory structure itself.
533 
535 {
536  if (!fList || !fSeekDir) {
537  return;
538  }
539 
540  // Save the directory key list and header
541  Save();
542 
543  Bool_t fast = kTRUE;
544  TObjLink *lnk = fList->FirstLink();
545  while (lnk) {
546  if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;break;}
547  lnk = lnk->Next();
548  }
549  // Delete objects from directory list, this in turn, recursively closes all
550  // sub-directories (that were allocated on the heap)
551  // if this dir contains subdirs, we must use the slow option for Delete!
552  // we must avoid "slow" as much as possible, in particular Delete("slow")
553  // with a large number of objects (eg >10^5) would take for ever.
554  {
556  if (fast) fList->Delete();
557  else fList->Delete("slow");
558  }
559 
560  // Delete keys from key list (but don't delete the list header)
561  if (fKeys) {
562  fKeys->Delete("slow");
563  }
564 
565  CleanTargets();
566 }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Delete Objects or/and keys in a directory
570 ///
571 /// Properties of the namecycle string:
572 /// - namecycle has the format name;cycle
573 /// - namecycle = "" is same as namecycle ="T*"
574 /// - name = * means all
575 /// - cycle = * means all cycles (memory and keys)
576 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
577 /// When name=* use T* to delete subdirectories also
578 ///
579 /// To delete one directory, you must specify the directory cycle,
580 /// eg. file.Delete("dir1;1");
581 ///
582 /// Examples:
583 /// | Pattern | Description |
584 /// |---------|-------------|
585 /// | foo | delete object named foo in memory |
586 /// | foo* | delete all objects with a name starting with foo |
587 /// | foo;1 | delete cycle 1 of foo on file |
588 /// | foo;* | delete all cycles of foo on file and also from memory |
589 /// | *;2 | delete all objects on file having the cycle 2 |
590 /// | *;* | delete all objects from memory and file |
591 /// | T*;* | delete all objects from memory and file and all subdirectories |
592 ///
593 /// ## WARNING
594 /// If the key to be deleted contains special characters ("+","^","?", etc
595 /// that have a special meaning for the regular expression parser (see TRegexp)
596 /// then you must specify 2 backslash characters to escape the regular expression.
597 /// For example, if the key to be deleted is namecycle = "C++", you must call
598 ///
599 /// mydir.Delete("C\\+\\+"));
600 ///
601 
602 void TDirectoryFile::Delete(const char *namecycle)
603 {
604  if (gDebug)
605  Info("Delete","Call for this = %s namecycle = %s",
606  GetName(), (namecycle ? namecycle : "null"));
607 
608  TDirectory::TContext ctxt(this);
609  Short_t cycle;
610  char name[kMaxLen];
611  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
612 
613  Int_t deleteall = 0;
614  Int_t deletetree = 0;
615  if(strcmp(name,"*") == 0) deleteall = 1;
616  if(strcmp(name,"*T") == 0){ deleteall = 1; deletetree = 1;}
617  if(strcmp(name,"T*") == 0){ deleteall = 1; deletetree = 1;}
618  if(namecycle==0 || !namecycle[0]){ deleteall = 1; deletetree = 1;}
619  TRegexp re(name,kTRUE);
620  TString s;
621  Int_t deleteOK = 0;
622 
623 //*-*---------------------Case of Object in memory---------------------
624 // ========================
625  if (cycle >= 9999 ) {
626  TNamed *idcur;
627  TIter next(fList);
628  while ((idcur = (TNamed *) next())) {
629  deleteOK = 0;
630  s = idcur->GetName();
631  if (deleteall || s.Index(re) != kNPOS) {
632  deleteOK = 1;
633  if (idcur->IsA() == TDirectoryFile::Class()) {
634  deleteOK = 2;
635  if (!deletetree && deleteall) deleteOK = 0;
636  }
637  }
638  if (deleteOK != 0) {
639  fList->Remove(idcur);
640  if (deleteOK==2) {
641  // read subdirectories to correctly delete them
642  if (deletetree)
643  ((TDirectory*) idcur)->ReadAll("dirs");
644  idcur->Delete(deletetree ? "T*;*" : "*");
645  delete idcur;
646  } else
647  idcur->Delete(name);
648  }
649  }
650 // if (deleteOK == 2) {
651 // Info("Delete","Dir:%lx %s", fList->FindObject(name), name);
652 // delete fList->FindObject(name); //deleting a TDirectory
653 // }
654  }
655 //*-*---------------------Case of Key---------------------
656 // ===========
657  if (cycle != 9999 ) {
658  if (IsWritable()) {
659  TKey *key;
660  TIter nextkey(GetListOfKeys());
661  while ((key = (TKey *) nextkey())) {
662  deleteOK = 0;
663  s = key->GetName();
664  if (deleteall || s.Index(re) != kNPOS) {
665  if (cycle == key->GetCycle()) deleteOK = 1;
666  if (cycle > 9999) deleteOK = 1;
667  //if (!strcmp(key->GetClassName(),"TDirectory")) {
668  if (strstr(key->GetClassName(),"TDirectory")) {
669  deleteOK = 2;
670  if (!deletetree && deleteall) deleteOK = 0;
671  if (cycle == key->GetCycle()) deleteOK = 2;
672  }
673  }
674  if (deleteOK) {
675  if (deleteOK==2) {
676  // read directory with subdirectories to correctly delete and free key structure
677  TDirectory* dir = GetDirectory(key->GetName(), kTRUE, "Delete");
678  if (dir!=0) {
679  dir->Delete("T*;*");
680  fList->Remove(dir);
681  delete dir;
682  }
683  }
684 
685  key->Delete();
686  fKeys->Remove(key);
687  fModified = kTRUE;
688  delete key;
689  }
690  }
691  TFile* f = GetFile();
692  if (fModified && (f!=0)) {
693  WriteKeys(); //*-* Write new keys structure
694  WriteDirHeader(); //*-* Write new directory header
695  f->WriteFree(); //*-* Write new free segments list
696  f->WriteHeader(); //*-* Write new file header
697  }
698  }
699  }
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Encode directory header into output buffer
704 
705 void TDirectoryFile::FillBuffer(char *&buffer)
706 {
707  Version_t version = TDirectoryFile::Class_Version();
711  {
712  // One of the address is larger than 2GB we need to use longer onfile
713  // integer, thus we increase the verison number.
714  // Note that fSeekDir and fSeekKey are not necessarily correlated, if
715  // some object are 'removed' from the file and the holes are reused.
716  version += 1000;
717  }
718  tobuf(buffer, version);
719  fDatimeC.FillBuffer(buffer);
720  fDatimeM.FillBuffer(buffer);
721  tobuf(buffer, fNbytesKeys);
722  tobuf(buffer, fNbytesName);
723  if (version > 1000) {
724  tobuf(buffer, fSeekDir);
725  tobuf(buffer, fSeekParent);
726  tobuf(buffer, fSeekKeys);
727  } else {
728  tobuf(buffer, (Int_t)fSeekDir);
729  tobuf(buffer, (Int_t)fSeekParent);
730  tobuf(buffer, (Int_t)fSeekKeys);
731  }
732  fUUID.FillBuffer(buffer);
733  if (fFile && fFile->GetVersion() < 40000) return;
734  if (version <=1000) for (Int_t i=0;i<3;i++) tobuf(buffer,Int_t(0));
735 }
736 
737 ////////////////////////////////////////////////////////////////////////////////
738 /// Find key with name keyname in the current directory
739 
740 TKey *TDirectoryFile::FindKey(const char *keyname) const
741 {
742  Short_t cycle;
743  char name[kMaxLen];
744 
745  DecodeNameCycle(keyname, name, cycle, kMaxLen);
746  return GetKey(name,cycle);
747 }
748 
749 ////////////////////////////////////////////////////////////////////////////////
750 /// Find key with name keyname in the current directory or
751 /// its subdirectories.
752 ///
753 /// NOTE: that If a key is found, the directory containing the key becomes
754 /// the current directory
755 
756 TKey *TDirectoryFile::FindKeyAny(const char *keyname) const
757 {
758  TDirectory *dirsav = gDirectory;
759  Short_t cycle;
760  char name[kMaxLen];
761 
762  DecodeNameCycle(keyname, name, cycle, kMaxLen);
763 
765  TKey *key;
766  while ((key = (TKey *) next())) {
767  if (!strcmp(name, key->GetName()))
768  if ((cycle == 9999) || (cycle >= key->GetCycle())) {
769  ((TDirectory*)this)->cd(); // may be we should not make cd ???
770  return key;
771  }
772  }
773  //try with subdirectories
774  next.Reset();
775  while ((key = (TKey *) next())) {
776  //if (!strcmp(key->GetClassName(),"TDirectory")) {
777  if (strstr(key->GetClassName(),"TDirectory")) {
778  TDirectory* subdir =
779  ((TDirectory*)this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny");
780  TKey *k = (subdir!=0) ? subdir->FindKeyAny(keyname) : 0;
781  if (k) return k;
782  }
783  }
784  if (dirsav) dirsav->cd();
785  return 0;
786 }
787 
788 ////////////////////////////////////////////////////////////////////////////////
789 /// Find object by name in the list of memory objects of the current
790 /// directory or its sub-directories.
791 ///
792 /// After this call the current directory is not changed.
793 /// To automatically set the current directory where the object is found,
794 /// use FindKeyAny(aname)->ReadObj().
795 
796 TObject *TDirectoryFile::FindObjectAny(const char *aname) const
797 {
798  //object may be already in the list of objects in memory
800  if (obj) return obj;
801 
802  TDirectory *dirsav = gDirectory;
803  Short_t cycle;
804  char name[kMaxLen];
805 
806  DecodeNameCycle(aname, name, cycle, kMaxLen);
807 
809  TKey *key;
810  //may be a key in the current directory
811  while ((key = (TKey *) next())) {
812  if (!strcmp(name, key->GetName())) {
813  if (cycle == 9999) return key->ReadObj();
814  if (cycle >= key->GetCycle()) return key->ReadObj();
815  }
816  }
817  //try with subdirectories
818  next.Reset();
819  while ((key = (TKey *) next())) {
820  //if (!strcmp(key->GetClassName(),"TDirectory")) {
821  if (strstr(key->GetClassName(),"TDirectory")) {
822  TDirectory* subdir =
823  ((TDirectory*)this)->GetDirectory(key->GetName(), kTRUE, "FindKeyAny");
824  TKey *k = subdir==0 ? 0 : subdir->FindKeyAny(aname);
825  if (k) { if (dirsav) dirsav->cd(); return k->ReadObj();}
826  }
827  }
828  if (dirsav) dirsav->cd();
829  return 0;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// Return pointer to object identified by namecycle.
834 ///
835 /// Properties:
836 /// - namecycle has the format name;cycle
837 /// - name = * is illegal, cycle = * is illegal
838 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
839 ///
840 /// Examples:
841 /// | Pattern | Explanation |
842 /// |---------|-------------|
843 /// | foo | get object named foo in memory if object is not in memory, try with highest cycle from file |
844 /// | foo;1 | get cycle 1 of foo on file |
845 ///
846 /// The retrieved object should in principle derive from TObject.
847 /// If not, the function TDirectoryFile::GetObject should be called.
848 /// However, this function will still work for a non-TObject, provided that
849 /// the calling application cast the return type to the correct type (which
850 /// is the actual type of the object).
851 ///
852 /// ### The GetObjectMethod
853 /// The method GetObject offers better protection and avoids the need
854 /// for any cast:
855 /// ~~~{.cpp}
856 /// MyClass *obj;
857 /// directory->GetObject("some object",obj);
858 /// if (obj) { ... the object exist and inherits from MyClass ... }
859 /// ~~~
860 ///
861 /// ### Very important note about inheritance
862 /// In case the class of this object derives from TObject but not
863 /// as a first inheritance, one must use dynamic_cast<>().
864 ///
865 /// #### Example 1 - Normal case:
866 ///
867 /// class MyClass : public TObject, public AnotherClass
868 ///
869 /// then on return, one can adopt a C style cast:
870 ///
871 /// auto objPtr = (MyClass*)directory->Get("some object of MyClass");
872 ///
873 /// #### Example 2 - Special case:
874 ///
875 /// class MyClass : public AnotherClass, public TObject
876 ///
877 /// then on return, one must do:
878 ///
879 /// auto objPtr = dynamic_cast<MyClass*>(directory->Get("some object of MyClass"));
880 ///
881 /// Of course, dynamic_cast<> can also be used in the example 1.
882 ///
883 
884 TObject *TDirectoryFile::Get(const char *namecycle)
885 {
886  Short_t cycle;
887  char name[kMaxLen];
888 
889  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
890  Int_t nch = strlen(name);
891  for (Int_t i = nch-1; i > 0; i--) {
892  if (name[i] == '/') {
893  name[i] = 0;
894  TDirectory* dirToSearch=GetDirectory(name);
895  const char *subnamecycle = namecycle + i + 1;
896  name[i] = '/';
897  return dirToSearch?dirToSearch->Get(subnamecycle):0;
898  }
899  }
900  const char *namobj = name;
901 
902 //*-*---------------------Case of Object in memory---------------------
903 // ========================
904  TObject *idcur = fList ? fList->FindObject(namobj) : nullptr;
905  if (idcur) {
906  if (idcur==this && strlen(namobj)!=0) {
907  // The object has the same name has the directory and
908  // that's what we picked-up! We just need to ignore
909  // it ...
910  idcur = 0;
911  } else if (cycle == 9999) {
912  return idcur;
913  } else {
914  if (idcur->InheritsFrom(TCollection::Class()))
915  idcur->Delete(); // delete also list elements
916  delete idcur;
917  idcur = 0;
918  }
919  }
920 
921 //*-*---------------------Case of Key---------------------
922 // ===========
923  TKey *key;
924  TIter nextkey(GetListOfKeys());
925  while ((key = (TKey *) nextkey())) {
926  if (strcmp(namobj,key->GetName()) == 0) {
927  if ((cycle == 9999) || (cycle == key->GetCycle())) {
928  TDirectory::TContext ctxt(this);
929  idcur = key->ReadObj();
930  break;
931  }
932  }
933  }
934 
935  return idcur;
936 }
937 
938 ////////////////////////////////////////////////////////////////////////////////
939 /// Return pointer to object identified by namecycle.
940 ///
941 /// The returned object may or may not derive from TObject.
942 ///
943 /// - namecycle has the format name;cycle
944 /// - name = * is illegal, cycle = * is illegal
945 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
946 ///
947 /// ## Very important note
948 /// The calling application must cast the returned object to
949 /// the final type, e.g.
950 ///
951 /// auto objPtr = (MyClass*)directory->GetObject("some object of MyClass");
952 
953 void *TDirectoryFile::GetObjectUnchecked(const char *namecycle)
954 {
955  return GetObjectChecked(namecycle,(TClass*)0);
956 }
957 
958 ////////////////////////////////////////////////////////////////////////////////
959 /// See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl)
960 
961 void *TDirectoryFile::GetObjectChecked(const char *namecycle, const char* classname)
962 {
963  return GetObjectChecked(namecycle,TClass::GetClass(classname));
964 }
965 
966 
967 ////////////////////////////////////////////////////////////////////////////////
968 /// Return pointer to object identified by namecycle if and only if the actual
969 /// object is a type suitable to be stored as a pointer to a "expectedClass"
970 /// If expectedClass is null, no check is performed.
971 ///
972 /// - namecycle has the format name;cycle
973 /// - name = * is illegal, cycle = * is illegal
974 /// - cycle = "" or cycle = 9999 ==> apply to a memory object
975 ///
976 /// ### Very important note
977 /// The calling application must cast the returned pointer to
978 /// the type described by the 2 arguments (i.e. cl):
979 ///
980 /// auto objPtr = (MyClass*)directory->GetObjectChecked("some object of MyClass","MyClass"));
981 ///
982 /// Note: We recommend using the method TDirectoryFile::GetObject:
983 /// ~~~{.cpp}
984 /// MyClass *obj = nullptr;
985 /// directory->GetObject("some object inheriting from MyClass",obj);
986 /// if (obj) { ... we found what we are looking for ... }
987 /// ~~~
988 
989 void *TDirectoryFile::GetObjectChecked(const char *namecycle, const TClass* expectedClass)
990 {
991  Short_t cycle;
992  char name[kMaxLen];
993 
994  DecodeNameCycle(namecycle, name, cycle, kMaxLen);
995  Int_t nch = strlen(name);
996  for (Int_t i = nch-1; i > 0; i--) {
997  if (name[i] == '/') {
998  name[i] = 0;
999  TDirectory* dirToSearch=GetDirectory(name);
1000  const char *subnamecycle = namecycle + i + 1;
1001  name[i] = '/';
1002  if (dirToSearch) {
1003  return dirToSearch->GetObjectChecked(subnamecycle, expectedClass);
1004  } else {
1005  return 0;
1006  }
1007  }
1008  }
1009  const char *namobj = name;
1010 
1011 //*-*---------------------Case of Object in memory---------------------
1012 // ========================
1013  if (expectedClass==0 || expectedClass->IsTObject()) {
1014  TObject *objcur = fList ? fList->FindObject(namobj) : 0;
1015  if (objcur) {
1016  if (objcur==this && strlen(namobj)!=0) {
1017  // The object has the same name has the directory and
1018  // that's what we picked-up! We just need to ignore
1019  // it ...
1020  objcur = 0;
1021  } else if (cycle == 9999) {
1022  // Check type
1023  if (expectedClass && objcur->IsA()->GetBaseClassOffset(expectedClass) == -1) return 0;
1024  else return objcur;
1025  } else {
1026  if (objcur->InheritsFrom(TCollection::Class()))
1027  objcur->Delete(); // delete also list elements
1028  delete objcur;
1029  objcur = 0;
1030  }
1031  }
1032  }
1033 
1034 //*-*---------------------Case of Key---------------------
1035 // ===========
1036  void *idcur = 0;
1037  TKey *key;
1038  TIter nextkey(GetListOfKeys());
1039  while ((key = (TKey *) nextkey())) {
1040  if (strcmp(namobj,key->GetName()) == 0) {
1041  if ((cycle == 9999) || (cycle == key->GetCycle())) {
1042  TDirectory::TContext ctxt(this);
1043  idcur = key->ReadObjectAny(expectedClass);
1044  break;
1045  }
1046  }
1047  }
1048 
1049  return idcur;
1050 }
1051 
1052 ////////////////////////////////////////////////////////////////////////////////
1053 /// Return the buffer size to create new TKeys.
1054 ///
1055 /// If the stored fBufferSize is null, the value returned is the average
1056 /// buffer size of objects in the file so far.
1057 
1060  if (fBufferSize <= 0) return fFile->GetBestBuffer();
1061  else return fBufferSize;
1062 }
1063 
1064 
1065 ////////////////////////////////////////////////////////////////////////////////
1066 /// Return pointer to key with name,cycle
1067 ///
1068 /// if cycle = 9999 returns highest cycle
1069 
1070 TKey *TDirectoryFile::GetKey(const char *name, Short_t cycle) const
1072  // TIter::TIter() already checks for null pointers
1073  TIter next( ((THashList *)(GetListOfKeys()))->GetListForObject(name) );
1074 
1075  TKey *key;
1076  while (( key = (TKey *)next() )) {
1077  if (!strcmp(name, key->GetName())) {
1078  if ((cycle == 9999) || (cycle >= key->GetCycle()))
1079  return key;
1080  }
1081  }
1082 
1083  return 0;
1084 }
1085 
1086 ////////////////////////////////////////////////////////////////////////////////
1087 /// List Directory contents
1088 ///
1089 /// Indentation is used to identify the directory tree
1090 /// Subdirectories are listed first, then objects in memory, then objects on the file
1091 ///
1092 /// The option can has the following format: <b>[-d |-m][<regexp>]</b>
1093 /// Options:
1094 /// - -d: only list objects in the file
1095 /// - -m: only list objects in memory
1096 /// The <regexp> will be used to match the name of the objects.
1097 /// By default memory and disk objects are listed.
1098 
1099 void TDirectoryFile::ls(Option_t *option) const
1102  std::cout <<ClassName()<<"*\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1104 
1105  TString opta = option;
1106  TString opt = opta.Strip(TString::kBoth);
1107  Bool_t memobj = kTRUE;
1108  Bool_t diskobj = kTRUE;
1109  TString reg = "*";
1110  if (opt.BeginsWith("-m")) {
1111  diskobj = kFALSE;
1112  if (opt.Length() > 2)
1113  reg = opt(2,opt.Length());
1114  } else if (opt.BeginsWith("-d")) {
1115  memobj = kFALSE;
1116  if (opt.Length() > 2)
1117  reg = opt(2,opt.Length());
1118  } else if (!opt.IsNull())
1119  reg = opt;
1120 
1121  TRegexp re(reg, kTRUE);
1122 
1123  if (memobj) {
1124  TObject *obj;
1125  TIter nextobj(fList);
1126  while ((obj = (TObject *) nextobj())) {
1127  TString s = obj->GetName();
1128  if (s.Index(re) == kNPOS) continue;
1129  obj->ls(option); //*-* Loop on all the objects in memory
1130  }
1131  }
1132 
1133  if (diskobj) {
1134  TKey *key;
1136  while ((key = (TKey *) next())) {
1137  TString s = key->GetName();
1138  if (s.Index(re) == kNPOS) continue;
1139  key->ls(); //*-* Loop on all the keys
1140  }
1141  }
1143 }
1144 
1145 ////////////////////////////////////////////////////////////////////////////////
1146 /// Interface to TFile::Open
1147 
1148 TFile *TDirectoryFile::OpenFile(const char *name, Option_t *option,const char *ftitle, Int_t compress, Int_t netopt)
1150  return TFile::Open(name,option,ftitle,compress,netopt);
1151 
1152 }
1153 
1154 
1155 ////////////////////////////////////////////////////////////////////////////////
1156 /// Create a sub-directory and return a pointer to the created directory.
1157 ///
1158 /// Returns 0 in case of error.
1159 /// Returns 0 if a directory with the same name already exists.
1160 /// Note that the directory name may be of the form "a/b/c" to create a hierarchy of directories.
1161 /// In this case, the function returns the pointer to the "a" directory if the operation is successful.
1162 
1163 TDirectory *TDirectoryFile::mkdir(const char *name, const char *title)
1165  if (!name || !title || !name[0]) return 0;
1166  if (!title[0]) title = name;
1167  if (GetKey(name)) {
1168  Error("mkdir","An object with name %s exists already",name);
1169  return 0;
1170  }
1171  TDirectoryFile *newdir = 0;
1172  if (const char *slash = strchr(name,'/')) {
1173  Long_t size = Long_t(slash-name);
1174  char *workname = new char[size+1];
1175  strncpy(workname, name, size);
1176  workname[size] = 0;
1177  TDirectoryFile *tmpdir;
1178  GetObject(workname,tmpdir);
1179  if (!tmpdir) {
1180  tmpdir = (TDirectoryFile*)mkdir(workname,title);
1181  if (!tmpdir) return 0;
1182  }
1183  if (!newdir) newdir = tmpdir;
1184  tmpdir->mkdir(slash+1);
1185  delete[] workname;
1186  return newdir;
1187  }
1188 
1189  TDirectory::TContext ctxt(this);
1190 
1191  newdir = new TDirectoryFile(name, title, "", this);
1192 
1193  return newdir;
1194 }
1195 
1196 ////////////////////////////////////////////////////////////////////////////////
1197 /// Purge lowest key cycles in a directory.
1198 ///
1199 /// By default, only the highest cycle of a key is kept. Keys for which
1200 /// the "KEEP" flag has been set are not removed. See TKey::Keep().
1201 
1204  if (!IsWritable()) return;
1205 
1206  TDirectory::TContext ctxt(this);
1207 
1208  TKey *key;
1210 
1211  while ((key = (TKey*)prev())) { // reverse loop on keys
1212  TKey *keyprev = (TKey*)GetListOfKeys()->Before(key);
1213  if (!keyprev) break;
1214  if (key->GetKeep() == 0) {
1215  if (strcmp(key->GetName(), keyprev->GetName()) == 0) {
1216  key->Delete(); // Remove from the file.
1217  delete key; // Remove from memory.
1218  }
1219  }
1220  }
1221  TFile* f = GetFile();
1222  if (fModified && (f!=0)) {
1223  WriteKeys(); // Write new keys structure
1224  WriteDirHeader(); // Write new directory header
1225  f->WriteFree(); // Write new free segments list
1226  f->WriteHeader(); // Write new file header
1227  }
1228 }
1229 
1230 ////////////////////////////////////////////////////////////////////////////////
1231 /// Read objects from a ROOT file directory into memory.
1232 ///
1233 /// If an object is already in memory, the memory copy is deleted
1234 /// and the object is again read from the file.
1235 /// If opt=="dirs", only subdirectories will be read
1236 /// If opt=="dirs*" complete directory tree will be read
1237 
1240  TDirectory::TContext ctxt(this);
1241 
1242  TKey *key;
1244 
1245  Bool_t readdirs = ((opt!=0) && ((strcmp(opt,"dirs")==0) || (strcmp(opt,"dirs*")==0)));
1246 
1247  if (readdirs)
1248  while ((key = (TKey *) next())) {
1249 
1250  //if (strcmp(key->GetClassName(),"TDirectory")!=0) continue;
1251  if (strstr(key->GetClassName(),"TDirectory")==0) continue;
1252 
1253  TDirectory *dir = GetDirectory(key->GetName(), kTRUE, "ReadAll");
1254 
1255  if ((dir!=0) && (strcmp(opt,"dirs*")==0)) dir->ReadAll("dirs*");
1256  }
1257  else
1258  while ((key = (TKey *) next())) {
1259  TObject *thing = GetList()->FindObject(key->GetName());
1260  if (thing) { delete thing; }
1261  key->ReadObj();
1262  }
1263 }
1264 
1265 ////////////////////////////////////////////////////////////////////////////////
1266 /// Read the linked list of keys.
1267 ///
1268 /// Every directory has a linked list (fKeys). This linked list has been
1269 /// written on the file via WriteKeys as a single data record.
1270 ///
1271 /// It is interesting to call this function in the following situation.
1272 /// Assume another process1 is connecting this directory in Update mode
1273 /// - Process1 is adding/updating objects in this directory
1274 /// - You want to see the latest status from process1.
1275 /// Example Process1:
1276 /// ~~~{.cpp}
1277 /// obj1.Write();
1278 /// obj2.Write();
1279 /// gDirectory->SaveSelf();
1280 /// ~~~
1281 ///
1282 /// Example Process2:
1283 /// ~~~{.cpp}
1284 /// gDirectory->ReadKeys();
1285 /// obj1->Draw();
1286 /// ~~~
1287 /// This is an efficient way (without opening/closing files) to view
1288 /// the latest updates of a file being modified by another process
1289 /// as it is typically the case in a data acquisition system.
1290 
1293  if (fFile==0) return 0;
1294 
1295  if (!fFile->IsBinary())
1296  return fFile->DirReadKeys(this);
1297 
1298  TDirectory::TContext ctxt(this);
1299 
1300  char *buffer;
1301  if (forceRead) {
1302  fKeys->Delete();
1303  //In case directory was updated by another process, read new
1304  //position for the keys
1305  Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof();
1306  char *header = new char[nbytes];
1307  buffer = header;
1308  fFile->Seek(fSeekDir);
1309  if ( fFile->ReadBuffer(buffer,nbytes) ) {
1310  // ReadBuffer return kTRUE in case of failure.
1311  delete [] header;
1312  return 0;
1313  }
1314  buffer += fNbytesName;
1315  Version_t versiondir;
1316  frombuf(buffer,&versiondir);
1317  fDatimeC.ReadBuffer(buffer);
1318  fDatimeM.ReadBuffer(buffer);
1319  frombuf(buffer, &fNbytesKeys);
1320  frombuf(buffer, &fNbytesName);
1321  if (versiondir > 1000) {
1322  frombuf(buffer, &fSeekDir);
1323  frombuf(buffer, &fSeekParent);
1324  frombuf(buffer, &fSeekKeys);
1325  } else {
1326  Int_t sdir,sparent,skeys;
1327  frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir;
1328  frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
1329  frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys;
1330  }
1331  delete [] header;
1332  }
1333 
1334  Int_t nkeys = 0;
1335  Long64_t fsize = fFile->GetSize();
1336  if ( fSeekKeys > 0) {
1337  TKey *headerkey = new TKey(fSeekKeys, fNbytesKeys, this);
1338  headerkey->ReadFile();
1339  buffer = headerkey->GetBuffer();
1340  headerkey->ReadKeyBuffer(buffer);
1341 
1342  TKey *key;
1343  frombuf(buffer, &nkeys);
1344  for (Int_t i = 0; i < nkeys; i++) {
1345  key = new TKey(this);
1346  key->ReadKeyBuffer(buffer);
1347  if (key->GetSeekKey() < 64 || key->GetSeekKey() > fsize) {
1348  Error("ReadKeys","reading illegal key, exiting after %d keys",i);
1349  fKeys->Remove(key);
1350  nkeys = i;
1351  break;
1352  }
1353  if (key->GetSeekPdir() < 64 || key->GetSeekPdir() > fsize) {
1354  Error("ReadKeys","reading illegal key, exiting after %d keys",i);
1355  fKeys->Remove(key);
1356  nkeys = i;
1357  break;
1358  }
1359  fKeys->Add(key);
1360  }
1361  delete headerkey;
1362  }
1363 
1364  return nkeys;
1365 }
1366 
1367 
1368 ////////////////////////////////////////////////////////////////////////////////
1369 /// Read object with keyname from the current directory
1370 ///
1371 /// Read contents of object with specified name from the current directory.
1372 /// First the key with keyname is searched in the current directory,
1373 /// next the key buffer is deserialized into the object.
1374 /// The object must have been created before via the default constructor.
1375 /// See TObject::Write().
1376 
1377 Int_t TDirectoryFile::ReadTObject(TObject *obj, const char *keyname)
1379  if (!fFile) { Error("Read","No file open"); return 0; }
1380  TKey *key = 0;
1381  TIter nextkey(GetListOfKeys());
1382  while ((key = (TKey *) nextkey())) {
1383  if (strcmp(keyname,key->GetName()) == 0) {
1384  return key->Read(obj);
1385  }
1386  }
1387  Error("Read","Key not found");
1388  return 0;
1389 }
1390 
1391 ////////////////////////////////////////////////////////////////////////////////
1392 /// Reset the TDirectory after its content has been merged into another
1393 /// Directory.
1394 ///
1395 /// This returns the TDirectoryFile object back to its state
1396 /// before any data has been written to the file.
1397 /// The object in the in-memory list are assumed to also have been reset.
1398 
1401  // There is nothing to reset in the base class (TDirectory) since
1402  // we do want to key the list of in-memory object as is.
1403  fModified = kFALSE;
1404  // Does not change: fWritable
1405  fDatimeC.Set();
1406  fDatimeM.Set();
1407  fNbytesKeys = 0; // updated when the keys are written
1408  fNbytesName = 0; // updated by Init
1409  // Does not change (user customization): fBufferSize;
1410  fSeekDir = 0; // updated by Init
1411  fSeekParent = 0; // updated by Init
1412  fSeekKeys = 0; // updated by Init
1413  // Does not change: fFile
1414  TKey *key = (TKey*)fKeys->FindObject(fName);
1415  TClass *cl = IsA();
1416  if (key) {
1417  cl = TClass::GetClass(key->GetClassName());
1418  }
1419  // NOTE: We should check that the content is really mergeable and in
1420  // the in-mmeory list, before deleting the keys.
1421  if (fKeys) {
1422  fKeys->Delete("slow");
1423  }
1424 
1425  Init(cl);
1426 
1427  // Do the same with the sub-directories.
1428  TIter next(GetList());
1429  TObject *idcur;
1430  while ((idcur = next())) {
1431  if (idcur->IsA() == TDirectoryFile::Class()) {
1432  ((TDirectoryFile*)idcur)->ResetAfterMerge(info);
1433  }
1434  }
1435 
1436 }
1437 
1438 ////////////////////////////////////////////////////////////////////////////////
1439 /// Removes subdirectory from the directory
1440 ///
1441 /// When diredctory is deleted, all keys in all subdirectories will be
1442 /// read first and deleted from file (if exists)
1443 /// Equivalent call is Delete("name;*");
1444 
1445 void TDirectoryFile::rmdir(const char *name)
1447  if ((name==0) || (*name==0)) return;
1448 
1449  TString mask(name);
1450  mask+=";*";
1451  Delete(mask);
1452 }
1453 
1454 ////////////////////////////////////////////////////////////////////////////////
1455 /// Save recursively all directory keys and headers
1456 
1457 void TDirectoryFile::Save()
1459  TDirectory::TContext ctxt(this);
1460 
1461  SaveSelf();
1462 
1463  // recursively save all sub-directories
1464  if (fList) {
1465  TObject *idcur;
1466  TIter next(fList);
1467  while ((idcur = next())) {
1468  if (idcur->InheritsFrom(TDirectoryFile::Class())) {
1469  TDirectoryFile *dir = (TDirectoryFile*)idcur;
1470  dir->Save();
1471  }
1472  }
1473  }
1474 }
1475 
1476 ////////////////////////////////////////////////////////////////////////////////
1477 /// Save object in filename.
1478 ///
1479 /// If filename is 0 or "", a file with "objectname.root" is created.
1480 /// The name of the key is the object name.
1481 /// If the operation is successful, it returns the number of bytes written to the file
1482 /// otherwise it returns 0.
1483 /// By default a message is printed. Use option "q" to not print the message.
1484 
1485 Int_t TDirectoryFile::SaveObjectAs(const TObject *obj, const char *filename, Option_t *option) const
1487  if (!obj) return 0;
1488  TDirectory *dirsav = gDirectory;
1489  TString fname = filename;
1490  if (!filename || !filename[0]) {
1491  fname.Form("%s.root",obj->GetName());
1492  }
1493  TFile *local = TFile::Open(fname.Data(),"recreate");
1494  if (!local) return 0;
1495  Int_t nbytes = obj->Write();
1496  delete local;
1497  if (dirsav) dirsav->cd();
1498  TString opt = option;
1499  opt.ToLower();
1500  if (!opt.Contains("q")) {
1501  if (!gSystem->AccessPathName(fname.Data())) obj->Info("SaveAs", "ROOT file %s has been created", fname.Data());
1502  }
1503  return nbytes;
1504 }
1505 
1506 ////////////////////////////////////////////////////////////////////////////////
1507 /// Save Directory keys and header
1508 ///
1509 /// If the directory has been modified (fModified set), write the keys
1510 /// and the directory header. This function assumes the cd is correctly set.
1511 ///
1512 /// It is recommended to use this function in the following situation:
1513 /// Assume a process1 using a directory in Update mode
1514 /// - New objects or modified objects have been written to the directory.
1515 /// - You do not want to close the file.
1516 /// - You want your changes be visible from another process2 already connected
1517 /// to this directory in read mode.
1518 /// - Call this function.
1519 /// - In process2, use TDirectoryFile::ReadKeys to refresh the directory.
1520 
1521 void TDirectoryFile::SaveSelf(Bool_t force)
1523  if (IsWritable() && (fModified || force) && fFile) {
1524  Bool_t dowrite = kTRUE;
1525  if (fFile->GetListOfFree())
1526  dowrite = fFile->GetListOfFree()->First() != 0;
1527  if (dowrite) {
1528  TDirectory *dirsav = gDirectory;
1529  if (dirsav != this) cd();
1530  WriteKeys(); //*-*- Write keys record
1531  WriteDirHeader(); //*-*- Update directory record
1532  if (dirsav && dirsav != this) dirsav->cd();
1533  }
1534  }
1535 }
1536 
1537 ////////////////////////////////////////////////////////////////////////////////
1538 /// Set the default buffer size when creating new TKeys.
1539 ///
1540 /// See also TDirectoryFile::GetBufferSize
1541 
1544  fBufferSize = bufsize;
1545 }
1546 
1547 ////////////////////////////////////////////////////////////////////////////////
1548 /// Find the action to be executed in the dictionary of the parent class
1549 /// and store the corresponding exec number into fBits.
1550 ///
1551 /// This function searches a data member in the class of parent with an
1552 /// offset corresponding to this.
1553 /// If a comment "TEXEC:" is found in the comment field of the data member,
1554 /// the function stores the exec identifier of the exec statement
1555 /// following this keyword.
1556 
1557 void TDirectoryFile::SetTRefAction(TObject *ref, TObject *parent)
1559  Int_t offset = (char*)ref - (char*)parent;
1560  TClass *cl = parent->IsA();
1561  cl->BuildRealData(parent);
1563  TIter next(info->GetElements());
1564  TStreamerElement *element;
1565  while((element = (TStreamerElement*)next())) {
1566  if (element->GetOffset() != offset) continue;
1567  Int_t execid = element->GetExecID();
1568  if (execid > 0) ref->SetBit(execid << 8);
1569  return;
1570  }
1571 }
1572 
1573 ////////////////////////////////////////////////////////////////////////////////
1574 /// Set the new value of fWritable recursively
1575 
1576 void TDirectoryFile::SetWritable(Bool_t writable)
1578  TDirectory::TContext ctxt(this);
1579 
1580  fWritable = writable;
1581 
1582  // recursively set all sub-directories
1583  if (fList) {
1584  TObject *idcur;
1585  TIter next(fList);
1586  while ((idcur = next())) {
1587  if (idcur->InheritsFrom(TDirectoryFile::Class())) {
1588  TDirectoryFile *dir = (TDirectoryFile*)idcur;
1589  dir->SetWritable(writable);
1590  }
1591  }
1592  }
1593 }
1594 
1595 
1596 ////////////////////////////////////////////////////////////////////////////////
1597 /// Return the size in bytes of the directory header
1598 
1601  Int_t nbytes = 22;
1602 
1603  nbytes += fDatimeC.Sizeof();
1604  nbytes += fDatimeM.Sizeof();
1605  nbytes += fUUID.Sizeof();
1606  //assume that the file may be above 2 Gbytes if file version is > 4
1607  if (fFile && fFile->GetVersion() >= 40000) nbytes += 12;
1608  return nbytes;
1609 }
1610 
1611 
1612 ////////////////////////////////////////////////////////////////////////////////
1613 /// Stream a class object
1614 
1615 void TDirectoryFile::Streamer(TBuffer &b)
1616 {
1617  Version_t v,version;
1618  if (b.IsReading()) {
1619  Build((TFile*)b.GetParent(), 0);
1620  if (fFile && fFile->IsWritable()) fWritable = kTRUE;
1621 
1622  if (fFile && !fFile->IsBinary()) {
1623  Version_t R__v = b.ReadVersion(0, 0);
1624 
1625  TClass* dirclass = (R__v < 5) ? TDirectory::Class() : TDirectoryFile::Class();
1626 
1627  b.ClassBegin(dirclass, R__v);
1628 
1629  TString sbuf;
1630 
1631  b.ClassMember("CreateTime","TString");
1632  sbuf.Streamer(b);
1633  TDatime timeC(sbuf.Data());
1634  fDatimeC = timeC;
1635 
1636  b.ClassMember("ModifyTime","TString");
1637  sbuf.Streamer(b);
1638  TDatime timeM(sbuf.Data());
1639  fDatimeM = timeM;
1640 
1641  b.ClassMember("UUID","TString");
1642  sbuf.Streamer(b);
1643  TUUID id(sbuf.Data());
1644  fUUID = id;
1645 
1646  b.ClassEnd(dirclass);
1647 
1648  fSeekKeys = 0; // read keys later in the TKeySQL class
1649  } else {
1650  b >> version;
1651  fDatimeC.Streamer(b);
1652  fDatimeM.Streamer(b);
1653  b >> fNbytesKeys;
1654  b >> fNbytesName;
1655  if (version > 1000) {
1656  SetBit(kIsBigFile);
1657  b >> fSeekDir;
1658  b >> fSeekParent;
1659  b >> fSeekKeys;
1660  } else {
1661  Int_t sdir,sparent,skeys;
1662  b >> sdir; fSeekDir = (Long64_t)sdir;
1663  b >> sparent; fSeekParent = (Long64_t)sparent;
1664  b >> skeys; fSeekKeys = (Long64_t)skeys;
1665  }
1666  v = version%1000;
1667  if (v == 2) {
1668  fUUID.StreamerV1(b);
1669  } else if (v > 2) {
1670  fUUID.Streamer(b);
1671  }
1672  }
1674  gROOT->GetUUIDs()->AddUUID(fUUID,this);
1675  if (fSeekKeys) ReadKeys();
1676  } else {
1677  if (fFile && !fFile->IsBinary()) {
1679 
1680  TString sbuf;
1681 
1683 
1684  b.ClassMember("CreateTime","TString");
1685  sbuf = fDatimeC.AsSQLString();
1686  sbuf.Streamer(b);
1687 
1688  b.ClassMember("ModifyTime","TString");
1689  fDatimeM.Set();
1690  sbuf = fDatimeM.AsSQLString();
1691  sbuf.Streamer(b);
1692 
1693  b.ClassMember("UUID","TString");
1694  sbuf = fUUID.AsString();
1695  sbuf.Streamer(b);
1696 
1698  } else {
1699  version = TDirectoryFile::Class_Version();
1700  if (fFile && fFile->GetEND() > TFile::kStartBigFile) version += 1000;
1701  b << version;
1702  fDatimeC.Streamer(b);
1703  fDatimeM.Streamer(b);
1704  b << fNbytesKeys;
1705  b << fNbytesName;
1706  if (version > 1000) {
1707  b << fSeekDir;
1708  b << fSeekParent;
1709  b << fSeekKeys;
1710  } else {
1711  b << (Int_t)fSeekDir;
1712  b << (Int_t)fSeekParent;
1713  b << (Int_t)fSeekKeys;
1714  }
1715  fUUID.Streamer(b);
1716  if (version <=1000) for (Int_t i=0;i<3;i++) b << Int_t(0);
1717  }
1718  }
1719 }
1720 
1721 ////////////////////////////////////////////////////////////////////////////////
1722 /// Write all objects in memory to disk.
1723 ///
1724 /// Loop on all objects in memory (including subdirectories).
1725 /// A new key is created in the keys linked list for each object.
1726 /// For allowed options see TObject::Write().
1727 /// The directory header info is rewritten on the directory header record.
1728 
1729 Int_t TDirectoryFile::Write(const char *, Int_t opt, Int_t bufsize)
1731  if (!IsWritable()) return 0;
1732  TDirectory::TContext ctxt(this);
1733 
1734  // Loop on all objects (including subdirs)
1735  TIter next(fList);
1736  TObject *obj;
1737  Int_t nbytes = 0;
1738  while ((obj=next())) {
1739  nbytes += obj->Write(0,opt,bufsize);
1740  }
1741  SaveSelf(kTRUE); // force save itself
1742 
1743  return nbytes;
1744 }
1745 
1746 ////////////////////////////////////////////////////////////////////////////////
1747 /// One can not save a const TDirectory object.
1748 
1749 Int_t TDirectoryFile::Write(const char *n, Int_t opt, Int_t bufsize) const
1751  Error("Write const","A const TDirectory object should not be saved. We try to proceed anyway.");
1752  return const_cast<TDirectoryFile*>(this)->Write(n, opt, bufsize);
1753 }
1754 
1755 ////////////////////////////////////////////////////////////////////////////////
1756 /// Write object obj to this directory.
1757 ///
1758 /// The data structure corresponding to this object is serialized.
1759 /// The corresponding buffer is written to this directory
1760 /// with an associated key with name "name".
1761 ///
1762 /// Writing an object to a file involves the following steps:
1763 /// - Creation of a support TKey object in the directory. The TKey object
1764 /// creates a TBuffer object.
1765 /// - The TBuffer object is filled via the class::Streamer function.
1766 /// - If the file is compressed (default) a second buffer is created to hold
1767 /// the compressed buffer.
1768 /// - Reservation of the corresponding space in the file by looking in the
1769 /// TFree list of free blocks of the file.
1770 /// - The buffer is written to the file.
1771 ///
1772 /// By default, the buffersize will be taken from the average buffer size
1773 /// of all objects written to the current file so far.
1774 /// Use TDirectoryFile::SetBufferSize to force a given buffer size.
1775 ///
1776 /// If a name is specified, it will be the name of the key.
1777 /// If name is not given, the name of the key will be the name as returned
1778 /// by obj->GetName().
1779 ///
1780 /// The option can be a combination of:
1781 /// - "SingleKey"
1782 /// - "Overwrite"
1783 /// - "WriteDelete"
1784 /// Using the "Overwrite" option a previous key with the same name is
1785 /// overwritten. The previous key is deleted before writing the new object.
1786 /// Using the "WriteDelete" option a previous key with the same name is
1787 /// deleted only after the new object has been written. This option
1788 /// is safer than kOverwrite but it is slower.
1789 /// The "SingleKey" option is only used by TCollection::Write() to write
1790 /// a container with a single key instead of each object in the container
1791 /// with its own key.
1792 /// An object is read from this directory via TDirectoryFile::Get.
1793 /// The function returns the total number of bytes written to the directory.
1794 /// It returns 0 if the object cannot be written.
1795 ///
1796 /// WARNING: avoid special characters like '^','$','.' in the name as they
1797 /// are used by the regular expression parser (see TRegexp).
1798 
1799 Int_t TDirectoryFile::WriteTObject(const TObject *obj, const char *name, Option_t *option, Int_t bufsize)
1801  TDirectory::TContext ctxt(this);
1802 
1803  if (fFile==0) {
1804  const char *objname = "no name specified";
1805  if (name) objname = name;
1806  else if (obj) objname = obj->GetName();
1807  Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.",GetName(),objname);
1808  return 0;
1809  }
1810 
1811  if (!fFile->IsWritable()) {
1812  if (!fFile->TestBit(TFile::kWriteError)) {
1813  // Do not print the error if the file already had a SysError.
1814  Error("WriteTObject","Directory %s is not writable", fFile->GetName());
1815  }
1816  return 0;
1817  }
1818 
1819  if (!obj) return 0;
1820 
1821  TString opt = option;
1822  opt.ToLower();
1823 
1824  TKey *key=0, *oldkey=0;
1826  if (bufsize > 0) bsize = bufsize;
1827 
1828  const char *oname;
1829  if (name && *name)
1830  oname = name;
1831  else
1832  oname = obj->GetName();
1833 
1834  // Remove trailing blanks in object name
1835  Int_t nch = strlen(oname);
1836  char *newName = 0;
1837  if (nch && oname[nch-1] == ' ') {
1838  newName = new char[nch+1];
1839  strlcpy(newName,oname,nch+1);
1840  for (Int_t i=0;i<nch;i++) {
1841  if (newName[nch-i-1] != ' ') break;
1842  newName[nch-i-1] = 0;
1843  }
1844  oname = newName;
1845  }
1846 
1847  if (opt.Contains("overwrite")) {
1848  //One must use GetKey. FindObject would return the lowest cycle of the key!
1849  //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname);
1850  key = GetKey(oname);
1851  if (key) {
1852  key->Delete();
1853  delete key;
1854  }
1855  }
1856  if (opt.Contains("writedelete")) {
1857  oldkey = GetKey(oname);
1858  }
1859  key = fFile->CreateKey(this, obj, oname, bsize);
1860  if (newName) delete [] newName;
1861 
1862  if (!key->GetSeekKey()) {
1863  fKeys->Remove(key);
1864  delete key;
1865  if (bufsize) fFile->SetBufferSize(bufsize);
1866  return 0;
1867  }
1868  fFile->SumBuffer(key->GetObjlen());
1869  Int_t nbytes = key->WriteFile(0);
1871  if (bufsize) fFile->SetBufferSize(bufsize);
1872  return 0;
1873  }
1874  if (oldkey) {
1875  oldkey->Delete();
1876  delete oldkey;
1877  }
1878  if (bufsize) fFile->SetBufferSize(bufsize);
1879 
1880  return nbytes;
1881 }
1882 
1883 ////////////////////////////////////////////////////////////////////////////////
1884 /// Write object from pointer of class classname in this directory.
1885 ///
1886 /// obj may not derive from TObject. See TDirectoryFile::WriteTObject for comments
1887 ///
1888 /// ## Very important note
1889 /// The value passed as 'obj' needs to be from a pointer to the type described by classname.
1890 /// For example:
1891 /// ~~~{.cpp}
1892 /// TopClass *top;
1893 /// BottomClass *bottom;
1894 /// top = bottom;
1895 /// ~~~
1896 /// you can do:
1897 /// ~~~{.cpp}
1898 /// directory->WriteObjectAny(top,"top","name of object");
1899 /// directory->WriteObjectAny(bottom,"bottom","name of object");
1900 /// ~~~
1901 /// <b>BUT YOU CAN NOT DO</b> the following since it will fail with multiple inheritance:
1902 /// ~~~{.cpp}
1903 /// directory->WriteObjectAny(top,"bottom","name of object");
1904 /// ~~~
1905 /// We <b>STRONGLY</b> recommend to use
1906 /// ~~~{.cpp}
1907 /// TopClass *top = ....;
1908 /// directory->WriteObject(top,"name of object")
1909 /// ~~~
1910 /// See laso remarks in TDirectoryFile::WriteTObject
1911 
1912 Int_t TDirectoryFile::WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option, Int_t bufsize)
1914  TClass *cl = TClass::GetClass(classname);
1915  if (cl == 0) {
1916  TObject *info_obj = *(TObject**)obj;
1917  TVirtualStreamerInfo *info = dynamic_cast<TVirtualStreamerInfo*>(info_obj);
1918  if (info == 0) {
1919  Error("WriteObjectAny","Unknown class: %s",classname);
1920  return 0;
1921  } else {
1922  cl = info->GetClass();
1923  }
1924  }
1925  return WriteObjectAny(obj,cl,name,option,bufsize);
1926 }
1927 
1928 ////////////////////////////////////////////////////////////////////////////////
1929 /// Write object of class with dictionary cl in this directory.
1930 ///
1931 /// obj may not derive from TObject
1932 /// To get the TClass* cl pointer, one can use
1933 ///
1934 /// TClass *cl = TClass::GetClass("classname");
1935 ///
1936 /// An alternative is to call the function WriteObjectAny above.
1937 /// see TDirectoryFile::WriteTObject for comments
1938 
1939 Int_t TDirectoryFile::WriteObjectAny(const void *obj, const TClass *cl, const char *name, Option_t *option, Int_t bufsize)
1941  TDirectory::TContext ctxt(this);
1942 
1943  if (fFile==0) return 0;
1944 
1945  if (!cl) {
1946  Error("WriteObject","Unknown type for %s, it can not be written.",name);
1947  return 0;
1948  }
1949 
1950  if (!fFile->IsWritable()) {
1951  if (!fFile->TestBit(TFile::kWriteError)) {
1952  // Do not print the error if the file already had a SysError.
1953  Error("WriteObject","File %s is not writable", fFile->GetName());
1954  }
1955  return 0;
1956  }
1957 
1958  if (!obj) return 0;
1959 
1960  const char *className = cl->GetName();
1961  const char *oname;
1962  if (name && *name)
1963  oname = name;
1964  else
1965  oname = className;
1966 
1967  if (cl && cl->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(cl->GetCollectionProxy())) {
1968  Error("WriteObjectAny",
1969  "The class requested (%s) for the key name \"%s\""
1970  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1971  " Please generate the dictionary for this collection (%s). No data will be written.",
1972  className, oname, className);
1973  return 0;
1974  }
1975 
1976  TKey *key, *oldkey=0;
1978  if (bufsize > 0) bsize = bufsize;
1979 
1980  TString opt = option;
1981  opt.ToLower();
1982 
1983  // Remove trailing blanks in object name
1984  Int_t nch = strlen(oname);
1985  char *newName = 0;
1986  if (nch && oname[nch-1] == ' ') {
1987  newName = new char[nch+1];
1988  strlcpy(newName,oname,nch+1);
1989  for (Int_t i=0;i<nch;i++) {
1990  if (newName[nch-i-1] != ' ') break;
1991  newName[nch-i-1] = 0;
1992  }
1993  oname = newName;
1994  }
1995 
1996  if (opt.Contains("overwrite")) {
1997  //One must use GetKey. FindObject would return the lowest cycle of the key!
1998  //key = (TKey*)gDirectory->GetListOfKeys()->FindObject(oname);
1999  key = GetKey(oname);
2000  if (key) {
2001  key->Delete();
2002  delete key;
2003  }
2004  }
2005  if (opt.Contains("writedelete")) {
2006  oldkey = GetKey(oname);
2007  }
2008  key = fFile->CreateKey(this, obj, cl, oname, bsize);
2009  if (newName) delete [] newName;
2010 
2011  if (!key->GetSeekKey()) {
2012  fKeys->Remove(key);
2013  delete key;
2014  return 0;
2015  }
2016  fFile->SumBuffer(key->GetObjlen());
2017  Int_t nbytes = key->WriteFile(0);
2018  if (fFile->TestBit(TFile::kWriteError)) return 0;
2019 
2020  if (oldkey) {
2021  oldkey->Delete();
2022  delete oldkey;
2023  }
2024 
2025  return nbytes;
2026 }
2027 
2028 ////////////////////////////////////////////////////////////////////////////////
2029 /// Overwrite the Directory header record.
2030 
2033  TFile* f = GetFile();
2034  if (f==0) return;
2035 
2036  if (!f->IsBinary()) {
2037  fDatimeM.Set();
2038  f->DirWriteHeader(this);
2039  return;
2040  }
2041 
2042  Int_t nbytes = TDirectoryFile::Sizeof(); //Warning ! TFile has a Sizeof()
2043  char * header = new char[nbytes];
2044  char * buffer = header;
2045  fDatimeM.Set();
2047  Long64_t pointer = fSeekDir + fNbytesName; // do not overwrite the name/title part
2048  fModified = kFALSE;
2049  f->Seek(pointer);
2050  f->WriteBuffer(header, nbytes);
2051  if (f->MustFlush()) f->Flush();
2052  delete [] header;
2053 }
2054 
2055 ////////////////////////////////////////////////////////////////////////////////
2056 /// Write Keys linked list on the file.
2057 ///
2058 /// The linked list of keys (fKeys) is written as a single data record
2059 
2062  TFile* f = GetFile();
2063  if (f==0) return;
2064 
2065  if (!f->IsBinary()) {
2066  f->DirWriteKeys(this);
2067  return;
2068  }
2069 
2070 //*-* Delete the old keys structure if it exists
2071  if (fSeekKeys != 0) {
2072  f->MakeFree(fSeekKeys, fSeekKeys + fNbytesKeys -1);
2073  }
2074 //*-* Write new keys record
2075  TIter next(fKeys);
2076  TKey *key;
2077  Int_t nkeys = fKeys->GetSize();
2078  Int_t nbytes = sizeof nkeys; //*-* Compute size of all keys
2079  if (f->GetEND() > TFile::kStartBigFile) nbytes += 8;
2080  while ((key = (TKey*)next())) {
2081  nbytes += key->Sizeof();
2082  }
2083  TKey *headerkey = new TKey(fName,fTitle,IsA(),nbytes,this);
2084  if (headerkey->GetSeekKey() == 0) {
2085  delete headerkey;
2086  return;
2087  }
2088  char *buffer = headerkey->GetBuffer();
2089  next.Reset();
2090  tobuf(buffer, nkeys);
2091  while ((key = (TKey*)next())) {
2092  key->FillBuffer(buffer);
2093  }
2094 
2095  fSeekKeys = headerkey->GetSeekKey();
2096  fNbytesKeys = headerkey->GetNbytes();
2097  headerkey->WriteFile();
2098  delete headerkey;
2099 }
TString fTitle
Definition: TNamed.h:37
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:229
void Add(TObject *obj, const char *name=0, Int_t check=-1)
Add object with name to browser.
Definition: TBrowser.cxx:259
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
virtual void DirWriteKeys(TDirectory *)
Definition: TFile.h:138
virtual Bool_t MustFlush() const
Definition: TFile.h:228
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:823
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1265
virtual void ReadAll(Option_t *option="")
Read objects from a ROOT file directory into memory.
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:88
virtual TDirectory * mkdir(const char *name, const char *title="")
Create a sub-directory and return a pointer to the created directory.
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:282
virtual void ReadAll(Option_t *="")
Definition: TDirectory.h:178
virtual Long64_t GetSize() const
Returns the current file size.
Definition: TFile.cxx:1279
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2390
virtual void ClassBegin(const TClass *, Version_t=-1)=0
virtual TObject * CloneObject(const TObject *obj, Bool_t autoadd=kTRUE)
Make a clone of an object using the Streamer facility.
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
virtual void SetBufferSize(Int_t bufsize)
Set the default buffer size when creating new TKeys.
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:51
long long Long64_t
Definition: RtypesCore.h:69
virtual TKey * FindKeyAny(const char *keyname) const
Find key with name keyname in the current directory or its subdirectories.
This class implements a shared memory region mapped to a file.
Definition: TMapFile.h:34
Bool_t IsReading() const
Definition: TBuffer.h:81
Bool_t IsBinary() const
Definition: TFile.h:219
virtual void ls(Option_t *option="") const
List Key contents.
Definition: TKey.cxx:682
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
Long64_t fSeekParent
Location of parent directory on file.
short Version_t
Definition: RtypesCore.h:61
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:727
virtual void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.)
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Ssiz_t Length() const
Definition: TString.h:390
virtual TClass * GetClass() const =0
Long64_t fSeekKeys
Location of Keys record on file.
virtual TObject * FindObjectAny(const char *name) const
Find object by name in the list of memory objects of the current directory or its sub-directories...
Definition: TDirectory.cxx:657
virtual Int_t ReadTObject(TObject *obj, const char *keyname)
Read object with keyname from the current directory.
const char Option_t
Definition: RtypesCore.h:62
virtual Int_t WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option="", Int_t bufsize=0)
Write object from pointer of class classname in this directory.
virtual void Save()
Save recursively all directory keys and headers.
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1080
TList * fList
Definition: TDirectory.h:96
virtual TKey * CreateKey(TDirectory *mother, const TObject *obj, const char *name, Int_t bufsize)
Creates key for object and converts data to buffer.
Definition: TFile.cxx:995
virtual void SetTRefAction(TObject *ref, TObject *parent)
Find the action to be executed in the dictionary of the parent class and store the corresponding exec...
#define gDirectory
Definition: TDirectory.h:218
TList * GetListOfFree() const
Definition: TFile.h:197
virtual TList * GetListOfKeys() const
#define BIT(n)
Definition: Rtypes.h:120
virtual TList * GetList() const
Definition: TDirectory.h:154
virtual TObject * FindObjectAny(const char *name) const
Find object by name in the list of memory objects of the current directory or its sub-directories...
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5552
Int_t fBufferSize
Default buffer size to create new TKeys.
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
Definition: TFile.cxx:2085
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
virtual void DirWriteHeader(TDirectory *)
Definition: TFile.h:139
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition: TFile.cxx:1596
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition: TKey.cxx:1005
Short_t GetCycle() const
Return cycle number associated to this key.
Definition: TKey.cxx:561
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Regular expression class.
Definition: TRegexp.h:35
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
virtual TKey * GetKey(const char *name, Short_t cycle=9999) const
Return pointer to key with name,cycle.
virtual Long64_t GetSeekPdir() const
Definition: TKey.h:92
static const char * filename()
const UInt_t kIsBigFile
#define gROOT
Definition: TROOT.h:340
Basic string class.
Definition: TString.h:137
virtual const char * GetClassName() const
Definition: TKey.h:77
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1088
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects)...
Definition: TObject.cxx:517
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
virtual void * GetObjectUnchecked(const char *namecycle)
Return pointer to object identified by namecycle.
virtual Int_t Write(const char *name=0, Int_t opt=0, Int_t bufsize=0)
Write all objects in memory to disk.
virtual Long64_t GetEND() const
Definition: TFile.h:191
void MapObject(const TObject *obj, UInt_t offset=1)
Add object to the fMap container.
virtual TKey * FindKey(const char *keyname) const
Find key with name keyname in the current directory.
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
const Int_t kMaxLen
virtual Int_t GetBufferSize() const
Return the buffer size to create new TKeys.
Streamer around an arbitrary STL like container, which implements basic container functionality...
virtual void FillBuffer(char *&buffer)
Encode key header into output buffer.
Definition: TKey.cxx:585
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
virtual Long64_t GetSeekKey() const
Definition: TKey.h:91
Int_t GetBestBuffer() const
Return the best buffer size of objects on this file.
Definition: TFile.cxx:1122
virtual void FillBuffer(char *&buffer)
Encode directory header into output buffer.
void Reset()
Definition: TCollection.h:161
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition: TFile.cxx:2229
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectory::GetObjectCheck(const char *namecycle, const TClass *cl) ...
Definition: TDirectory.cxx:790
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *option="", Int_t bufsize=0)
Write object obj to this directory.
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3851
virtual char * GetBuffer() const
Definition: TKey.h:80
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition: TUUID.h:44
const char * Data() const
Definition: TString.h:349
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:946
virtual void ClassMember(const char *, const char *=0, Int_t=-1, Int_t=-1)=0
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition: TObject.cxx:536
#define SafeDelete(p)
Definition: RConfig.h:436
void Init(TClass *cl=0)
Initialize the key associated with this directory (and the related data members.
void Class()
Definition: Class.C:29
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:36
virtual void WriteFree()
Write FREE linked list on the file.
Definition: TFile.cxx:2355
Int_t bsize[]
Definition: SparseFit4.cxx:31
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
Int_t GetNbytes() const
Definition: TKey.h:88
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:118
virtual void WriteKeys()
Write Keys linked list on the file.
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1440
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Bool_t IsWritable() const
virtual Int_t Sizeof() const
Return the size in bytes of the key header structure.
Definition: TKey.cxx:1329
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:59
virtual ~TDirectoryFile()
Destructor.
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
XFontStruct * id
Definition: TGX11.cxx:108
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Long64_t fSeekDir
Location of directory on file.
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:531
void Error(const char *location, const char *msgfmt,...)
void GetObject(const char *namecycle, T *&ptr)
virtual void Delete(const char *namecycle="")
Delete Objects or/and keys in a directory.
Definition: TDirectory.cxx:573
void Add(const TObject *obj, const char *name="")
Add an object to the list of objects to be stored in shared memory.
Definition: TMapFile.cxx:561
virtual TFile * GetFile() const
Definition: TDirectory.h:152
virtual Long64_t DirCreateEntry(TDirectory *)
Definition: TFile.h:136
virtual Int_t Sizeof() const
Return the size in bytes of the directory header.
virtual void ls(Option_t *option="") const
List Directory contents.
void ResetMap()
Delete existing fMap and reset map counter.
virtual Long64_t GetSeekDir() const
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1937
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:228
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
virtual void SaveSelf(Bool_t force=kFALSE)
Save Directory keys and header.
TObjArray * GetElements() const
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
TList * fKeys
Pointer to keys list in memory.
virtual TObject * Before(const TObject *obj) const
Returns the object before object obj.
Definition: TList.cxx:321
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4337
SVector< double, 2 > v
Definition: Dict.h:5
A ROOT file is structured in Directories (like a file system).
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:187
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
virtual Bool_t WriteBuffer(const char *buf, Int_t len)
Write a buffer to the file.
Definition: TFile.cxx:2288
TClass * IsA() const
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition: TKey.cxx:1258
virtual Int_t GetExecID() const
Returns the TExec id for the EXEC instruction in the comment field of a TRef data member...
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1388
Int_t fNbytesName
Number of bytes in TNamed at creation time.
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:151
virtual Int_t DirReadKeys(TDirectory *)
Definition: TFile.h:137
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:269
short Short_t
Definition: RtypesCore.h:35
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1069
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void Browse(TBrowser *b)
Browse the content of the directory.
virtual void Delete(const char *namecycle="")
Delete Objects or/and keys in a directory.
void Build(TFile *motherFile=0, TDirectory *motherDir=0)
Initialise directory to defaults.
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:152
Bool_t IsNull() const
Definition: TString.h:387
virtual TObjLink * FirstLink() const
Definition: TList.h:101
virtual TDirectory * GetDirectory(const char *apath, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory named "apath".
virtual void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Definition: TList.cxx:172
TString fName
Definition: TNamed.h:36
static TFile *& CurrentFile()
Return the current ROOT file if any.
Definition: TFile.cxx:1015
Bool_t fWritable
True if directory is writable.
Int_t AppendKey(TKey *key)
Insert key in the linked list of keys of this directory.
TObject * fMother
Definition: TDirectory.h:95
virtual void WriteDirHeader()
Overwrite the Directory header record.
virtual Int_t AppendKey(TKey *)
Definition: TDirectory.h:124
void SetMotherDir(TDirectory *dir)
Definition: TKey.h:108
long Long_t
Definition: RtypesCore.h:50
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1215
TFile * fFile
Pointer to current file in memory.
virtual Int_t GetSize() const
Definition: TCollection.h:95
double f(double x)
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
virtual Int_t ReadKeys(Bool_t forceRead=kTRUE)
Read the linked list of keys.
Describe directory structure in memory.
Definition: TDirectory.h:41
virtual void Copy(TObject &) const
Copy this to obj.
Definition: TDirectory.h:131
void SetWritable(Bool_t writable=kTRUE)
Set the new value of fWritable recursively.
Int_t GetObjlen() const
Definition: TKey.h:89
double func(double *x, double *p)
Definition: stressTF1.cxx:213
Int_t GetKeylen() const
Definition: TKey.h:86
virtual TObject * FindObjectAnyFile(const char *name) const
Scan the memory lists of all files for an object with name.
static void DecodeNameCycle(const char *namecycle, char *name, Short_t &cycle, const size_t namesize=0)
Decode a namecycle "aap;2" into name "aap" and cycle "2".
ClassImp(TDirectoryFile) TDirectoryFile
Default Constructor.
virtual void * GetObjectChecked(const char *namecycle, const char *classname)
See documentation of TDirectoryFile::GetObjectCheck(const char *namecycle, const TClass *cl) ...
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
TCanvas * slash()
Definition: slash.C:1
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
virtual TDirectory * GetMotherDir() const
Definition: TDirectory.h:157
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2810
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
virtual void rmdir(const char *name)
Removes subdirectory from the directory.
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:556
Bool_t fModified
True if directory has been modified.
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2453
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition: TKey.cxx:727
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:433
virtual TFile * GetFile() const
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
virtual void ClassEnd(const TClass *)=0
Int_t GetVersion() const
Definition: TFile.h:205
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
Definition: TDirectory.cxx:336
virtual TFile * OpenFile(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Interface to TFile::Open.
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2461
double result[121]
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset the TDirectory after its content has been merged into another Directory.
void ResetBit(UInt_t f)
Definition: TObject.h:172
virtual Int_t Read(const char *name)
Read contents of object with specified name from the current directory.
Definition: TKey.h:55
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2396
const Bool_t kIterBackward
Definition: TCollection.h:44
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
Abstract Interface class describing Streamer information for one class.
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
static char * skip(char **buf, const char *delimiters)
Definition: civetweb.c:1014
virtual TKey * FindKeyAny(const char *) const
Definition: TDirectory.h:137
const Int_t n
Definition: legend1.C:16
Short_t GetKeep() const
Returns the "KEEP" status.
Definition: TKey.cxx:577
virtual void CleanTargets()
Clean the pointers to this object (gDirectory, TContext, etc.).
Definition: TDirectory.cxx:210
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:39
Int_t fNbytesKeys
Number of bytes for the keys.
virtual void Purge(Short_t nkeep=1)
Purge lowest key cycles in a directory.
virtual Int_t SaveObjectAs(const TObject *obj, const char *filename="", Option_t *option="") const
Save object in filename.
#define gFile
Definition: TFile.h:307