Logo ROOT  
Reference Guide
TKey.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Rene Brun 28/12/94
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 TKey
14 \ingroup IO
15 
16  Book space in a file, create I/O buffers, to fill them, (un)compress them.
17 
18  The TKey class includes functions to book space in a file, to create I/O
19  buffers, to fill these buffers, to compress/uncompress data buffers.
20  Before saving (making persistent) an object in a file, a key must
21  be created. The key structure contains all the information to
22  uniquely identify a persistent object in a file.
23  | Data Member | Explanation |
24  |-------------|-------------|
25  | fNbytes | Number of bytes for the compressed object and key. |
26  | fObjlen | Length of uncompressed object. |
27  | fDatime | Date/Time when the object was written. |
28  | fKeylen | Number of bytes for the key structure. |
29  | fCycle | Cycle number of the object. |
30  | fSeekKey | Address of the object on file (points to fNbytes). This is a redundant information used to cross-check the data base integrity. |
31  | fSeekPdir | Pointer to the directory supporting this object.|
32  | fClassName | Object class name. |
33  | fName | Name of the object. |
34  | fTitle | Title of the object. |
35 
36  In the 16 highest bits of fSeekPdir is encoded a pid offset. This
37  offset is to be added to the pid index stored in the TRef object
38  and the referenced TObject.
39 
40  The TKey class is used by ROOT to:
41  - Write an object in the current directory
42  - Write a new ntuple buffer
43 
44  The structure of a file is shown in TFile::TFile.
45  The structure of a directory is shown in TDirectoryFile::TDirectoryFile.
46  The TKey class is used by the TBasket class.
47  See also TTree.
48 */
49 
50 #include <atomic>
51 
52 #include "Riostream.h"
53 #include "TROOT.h"
54 #include "TClass.h"
55 #include "TDirectoryFile.h"
56 #include "TFile.h"
57 #include "TKey.h"
58 #include "TBufferFile.h"
59 #include "TFree.h"
60 #include "TBrowser.h"
61 #include "Bytes.h"
62 #include "TInterpreter.h"
63 #include "TError.h"
64 #include "TVirtualStreamerInfo.h"
65 #include "TSchemaRuleSet.h"
66 #include "ThreadLocalStorage.h"
67 
68 #include "RZip.h"
69 
70 const Int_t kTitleMax = 32000;
71 #if 0
72 const Int_t kMAXFILEBUFFER = 262144;
73 #endif
74 
75 #if !defined(_MSC_VER) || (_MSC_VER>1300)
76 const ULong64_t kPidOffsetMask = 0xffffffffffffULL;
77 #else
78 const ULong64_t kPidOffsetMask = 0xffffffffffffUL;
79 #endif
81 
82 const static TString gTDirectoryString("TDirectory");
83 std::atomic<UInt_t> keyAbsNumber{0};
84 
85 ClassImp(TKey);
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// TKey default constructor.
89 
90 TKey::TKey() : TNamed(), fDatime((UInt_t)0)
91 {
92  Build(0, "", 0);
93 
94  fKeylen = Sizeof();
95 
97 }
98 
99 ////////////////////////////////////////////////////////////////////////////////
100 /// TKey default constructor.
101 
102 TKey::TKey(TDirectory* motherDir) : TNamed(), fDatime((UInt_t)0)
103 {
104  Build(motherDir, "", 0);
105 
106  fKeylen = Sizeof();
107 
109 }
110 
111 ////////////////////////////////////////////////////////////////////////////////
112 /// Copy a TKey from its original directory to the new 'motherDir'
113 
114 TKey::TKey(TDirectory* motherDir, const TKey &orig, UShort_t pidOffset) : TNamed(), fDatime((UInt_t)0)
115 {
116  fMotherDir = motherDir;
117 
118  fPidOffset = orig.fPidOffset + pidOffset;
119  fNbytes = orig.fNbytes;
120  fObjlen = orig.fObjlen;
121  fClassName = orig.fClassName;
122  fName = orig.fName;
123  fTitle = orig.fTitle;
124 
125  fCycle = fMotherDir->AppendKey(this);
126  fSeekPdir = 0;
127  fSeekKey = 0;
128  fLeft = 0;
129 
130  fVersion = TKey::Class_Version();
131  Long64_t filepos = GetFile()->GetEND();
132  if (filepos > TFile::kStartBigFile || fPidOffset) fVersion += 1000;
133 
134  fKeylen = Sizeof(); // fVersion must be set.
135 
136  UInt_t bufferDecOffset = 0;
137  UInt_t bufferIncOffset = 0;
138  UInt_t alloc = fNbytes + sizeof(Int_t); // The extra Int_t is for any free space information.
139  if (fKeylen < orig.fKeylen) {
140  bufferDecOffset = orig.fKeylen - fKeylen;
141  fNbytes -= bufferDecOffset;
142  } else if (fKeylen > orig.fKeylen) {
143  bufferIncOffset = fKeylen - orig.fKeylen;
144  alloc += bufferIncOffset;
145  fNbytes += bufferIncOffset;
146  }
147 
148  fBufferRef = new TBufferFile(TBuffer::kWrite, alloc);
150 
151  // Steal the data from the old key.
152 
153  TFile* f = orig.GetFile();
154  if (f) {
155  Int_t nsize = orig.fNbytes;
156  f->Seek(orig.fSeekKey);
157  if( f->ReadBuffer(fBuffer+bufferIncOffset,nsize) )
158  {
159  Error("ReadFile", "Failed to read data.");
160  return;
161  }
162  if (gDebug) {
163  std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
164  }
165  }
166  fBuffer += bufferDecOffset; // Reset the buffer to be appropriate for this key.
167  Int_t nout = fNbytes - fKeylen;
168  Create(nout);
169  fBufferRef->SetBufferOffset(bufferDecOffset);
170  Streamer(*fBufferRef); //write key itself again
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Create a TKey object to read keys.
175 /// Constructor called by TDirectoryFile::ReadKeys and by TFile::TFile.
176 /// A TKey object is created to read the keys structure itself.
177 
178 TKey::TKey(Long64_t pointer, Int_t nbytes, TDirectory* motherDir) : TNamed()
179 {
180  Build(motherDir, "", pointer);
181 
182  fSeekKey = pointer;
183  fNbytes = nbytes;
184  fBuffer = new char[nbytes];
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Create a TKey object with the specified name, title for the given class.
190 ///
191 /// WARNING: in name avoid special characters like '^','$','.' that are used
192 /// by the regular expression parser (see TRegexp).
193 
194 TKey::TKey(const char *name, const char *title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
195  : TNamed(name,title)
196 {
197  Build(motherDir, cl->GetName(), -1);
198 
199  fKeylen = Sizeof();
200  fObjlen = nbytes;
201  Create(nbytes);
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Create a TKey object with the specified name, title for the given class.
206 ///
207 /// WARNING: in name avoid special characters like '^','$','.' that are used
208 /// by the regular expression parser (see TRegexp).
209 
210 TKey::TKey(const TString &name, const TString &title, const TClass *cl, Int_t nbytes, TDirectory* motherDir)
211  : TNamed(name,title)
212 {
213  Build(motherDir, cl->GetName(), -1);
214 
215  fKeylen = Sizeof();
216  fObjlen = nbytes;
217  Create(nbytes);
218 }
219 
220 ////////////////////////////////////////////////////////////////////////////////
221 /// Create a TKey object for a TObject* and fill output buffer
222 ///
223 /// WARNING: in name avoid special characters like '^','$','.' that are used
224 /// by the regular expression parser (see TRegexp).
225 
226 TKey::TKey(const TObject *obj, const char *name, Int_t bufsize, TDirectory* motherDir)
227  : TNamed(name, obj->GetTitle())
228 {
229  R__ASSERT(obj);
230 
231  if (!obj->IsA()->HasDefaultConstructor()) {
232  Warning("TKey", "since %s has no public constructor\n"
233  "\twhich can be called without argument, objects of this class\n"
234  "\tcan not be read with the current library. You will need to\n"
235  "\tadd a default constructor before attempting to read it.",
236  obj->ClassName());
237  }
238 
239  Build(motherDir, obj->ClassName(), -1);
240 
241  Int_t lbuf, nout, noutot, bufmax, nzip;
242  fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize);
244  fCycle = fMotherDir->AppendKey(this);
245 
246  Streamer(*fBufferRef); //write key itself
248  fBufferRef->MapObject(obj); //register obj in map in case of self reference
249  ((TObject*)obj)->Streamer(*fBufferRef); //write object
250  lbuf = fBufferRef->Length();
251  fObjlen = lbuf - fKeylen;
252 
253  Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0;
255  if (cxlevel > 0 && fObjlen > 256) {
256  Int_t nbuffers = 1 + (fObjlen - 1)/kMAXZIPBUF;
257  Int_t buflen = TMath::Max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
258  fBuffer = new char[buflen];
259  char *objbuf = fBufferRef->Buffer() + fKeylen;
260  char *bufcur = &fBuffer[fKeylen];
261  noutot = 0;
262  nzip = 0;
263  for (Int_t i = 0; i < nbuffers; ++i) {
264  if (i == nbuffers - 1) bufmax = fObjlen - nzip;
265  else bufmax = kMAXZIPBUF;
266  R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
267  if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
269  Create(fObjlen);
271  Streamer(*fBufferRef); //write key itself again
272  return;
273  }
274  bufcur += nout;
275  noutot += nout;
276  objbuf += kMAXZIPBUF;
277  nzip += kMAXZIPBUF;
278  }
279  Create(noutot);
281  Streamer(*fBufferRef); //write key itself again
282  memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
283  delete fBufferRef; fBufferRef = 0;
284  } else {
286  Create(fObjlen);
288  Streamer(*fBufferRef); //write key itself again
289  }
290 }
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 /// Create a TKey object for any object obj of class cl d and fill
294 /// output buffer.
295 ///
296 /// WARNING: in name avoid special characters like '^','$','.' that are used
297 /// by the regular expression parser (see TRegexp).
298 
299 TKey::TKey(const void *obj, const TClass *cl, const char *name, Int_t bufsize, TDirectory* motherDir)
300  : TNamed(name, "object title")
301 {
302  R__ASSERT(obj && cl);
303 
304  if (!cl->HasDefaultConstructor()) {
305  Warning("TKey", "since %s has no public constructor\n"
306  "\twhich can be called without argument, objects of this class\n"
307  "\tcan not be read with the current library. You will need to\n"
308  "\tadd a default constructor before attempting to read it.",
309  cl->GetName());
310  }
311 
312  TClass *clActual = cl->GetActualClass(obj);
313  const void* actualStart;
314  if (clActual) {
315  const char *temp = (const char*) obj;
316  // clActual->GetStreamerInfo();
317  Int_t offset = (cl != clActual) ?
318  clActual->GetBaseClassOffset(cl) : 0;
319  temp -= offset;
320  actualStart = temp;
321  } else {
322  // We could not determine the real type of this object,
323  // let's assume it is the one given by the caller.
324  clActual = const_cast<TClass*>(cl);
325  actualStart = obj;
326  }
327 
328  Build(motherDir, clActual->GetName(), -1);
329 
330  fBufferRef = new TBufferFile(TBuffer::kWrite, bufsize);
332  fCycle = fMotherDir->AppendKey(this);
333 
334  Streamer(*fBufferRef); //write key itself
336 
337  Int_t lbuf, nout, noutot, bufmax, nzip;
338 
339  fBufferRef->MapObject(actualStart,clActual); //register obj in map in case of self reference
340  clActual->Streamer((void*)actualStart, *fBufferRef); //write object
341  lbuf = fBufferRef->Length();
342  fObjlen = lbuf - fKeylen;
343 
344  Int_t cxlevel = GetFile() ? GetFile()->GetCompressionLevel() : 0;
346  if (cxlevel > 0 && fObjlen > 256) {
347  Int_t nbuffers = 1 + (fObjlen - 1)/kMAXZIPBUF;
348  Int_t buflen = TMath::Max(512,fKeylen + fObjlen + 9*nbuffers + 28); //add 28 bytes in case object is placed in a deleted gap
349  fBuffer = new char[buflen];
350  char *objbuf = fBufferRef->Buffer() + fKeylen;
351  char *bufcur = &fBuffer[fKeylen];
352  noutot = 0;
353  nzip = 0;
354  for (Int_t i = 0; i < nbuffers; ++i) {
355  if (i == nbuffers - 1) bufmax = fObjlen - nzip;
356  else bufmax = kMAXZIPBUF;
357  R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
358  if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
360  Create(fObjlen);
362  Streamer(*fBufferRef); //write key itself again
363  return;
364  }
365  bufcur += nout;
366  noutot += nout;
367  objbuf += kMAXZIPBUF;
368  nzip += kMAXZIPBUF;
369  }
370  Create(noutot);
372  Streamer(*fBufferRef); //write key itself again
373  memcpy(fBuffer,fBufferRef->Buffer(),fKeylen);
374  delete fBufferRef; fBufferRef = 0;
375  } else {
377  Create(fObjlen);
379  Streamer(*fBufferRef); //write key itself again
380  }
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// Method used in all TKey constructor to initialize basic data fields.
385 ///
386 /// The member filepos is used to calculate correct version number of key
387 /// if filepos==-1, end of file position is used.
388 
389 void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos)
390 {
391  fMotherDir = motherDir;
392 
393  fPidOffset = 0;
394  fNbytes = 0;
395  fBuffer = 0;
396  fKeylen = 0;
397  fObjlen = 0;
398  fBufferRef = 0;
399  fCycle = 0;
400  fSeekPdir = 0;
401  fSeekKey = 0;
402  fLeft = 0;
403 
404  fClassName = classname;
405  //the following test required for forward and backward compatibility
406  if (fClassName == "TDirectoryFile") SetBit(kIsDirectoryFile);
407 
408  fVersion = TKey::Class_Version();
409 
410  if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND();
411  if (filepos > TFile::kStartBigFile) fVersion += 1000;
412 
414 
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 /// Read object from disk and call its Browse() method.
421 ///
422 /// If object with same name already exist in memory delete it (like
423 /// TDirectoryFile::Get() is doing), except when the key references a
424 /// folder in which case we don't want to re-read the folder object
425 /// since it might contain new objects not yet saved.
426 
428 {
429  if (fMotherDir==0) return;
430 
432 
433  void* obj = fMotherDir->GetList()->FindObject(GetName());
434  if (obj && objcl->IsTObject()) {
435  TObject *tobj = (TObject*) objcl->DynamicCast(TObject::Class(), obj);
436  if (!tobj->IsFolder()) {
437  if (tobj->InheritsFrom(TCollection::Class()))
438  tobj->Delete(); // delete also collection elements
439  delete tobj;
440  obj = 0;
441  }
442  }
443 
444  if (!obj)
445  obj = ReadObj();
446 
447  if (b && obj) {
448  objcl->Browse(obj,b);
449  b->SetRefreshFlag(kTRUE);
450  }
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Create a TKey object of specified size.
455 ///
456 /// If externFile!=0, key will be allocated in specified file, otherwise file
457 /// of mother directory will be used.
458 
459 void TKey::Create(Int_t nbytes, TFile* externFile)
460 {
462 
463  TFile *f = externFile;
464  if (!f) f = GetFile();
465  if (!f) {
466  Error("Create","Cannot create key without file");
467  return;
468  }
469 
470  Int_t nsize = nbytes + fKeylen;
471  TList *lfree = f->GetListOfFree();
472  TFree *f1 = (TFree*)lfree->First();
473 //*-*-------------------find free segment
474 //*-* =================
475  TFree *bestfree = f1->GetBestFree(lfree,nsize);
476  if (bestfree == 0) {
477  Error("Create","Cannot allocate %d bytes for ID = %s Title = %s",
478  nsize,GetName(),GetTitle());
479  return;
480  }
481 
482  if (f->TestBit(TFile::kReproducible))
484 
485  fDatime.Set();
486  fSeekKey = bestfree->GetFirst();
487 //*-*----------------- Case Add at the end of the file
488  if (fSeekKey >= f->GetEND()) {
489  f->SetEND(fSeekKey+nsize);
490  bestfree->SetFirst(fSeekKey+nsize);
491  if (f->GetEND() > bestfree->GetLast()) {
492  bestfree->SetLast(bestfree->GetLast() + 1000000000);
493  }
494  fLeft = -1;
495  if (!fBuffer) fBuffer = new char[nsize];
496  } else {
497  fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1);
498  }
499 //*-*----------------- Case where new object fills exactly a deleted gap
500  fNbytes = nsize;
501  if (fLeft == 0) {
502  if (!fBuffer) {
503  fBuffer = new char[nsize];
504  }
505  lfree->Remove(bestfree);
506  delete bestfree;
507  }
508 //*-*----------------- Case where new object is placed in a deleted gap larger than itself
509  if (fLeft > 0) { // found a bigger segment
510  if (!fBuffer) {
511  fBuffer = new char[nsize+sizeof(Int_t)];
512  }
513  char *buffer = fBuffer+nsize;
514  Int_t nbytesleft = -fLeft; // set header of remaining record
515  tobuf(buffer, nbytesleft);
516  bestfree->SetFirst(fSeekKey+nsize);
517  }
518 
519  fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir();
520 }
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// TKey default destructor.
524 
526 {
528  fMotherDir->GetListOfKeys()->Remove(this);
530 }
531 
532 ////////////////////////////////////////////////////////////////////////////////
533 /// Delete an object from the file.
534 ///
535 /// Note: the key is not deleted. You still have to call "delete key".
536 /// This is different from the behaviour of TObject::Delete()!
537 
538 void TKey::Delete(Option_t *option)
539 {
540  if (TestBit(kIsDirectoryFile)) {
541  // TDirectoryFile assumes that its location on file never change (for example updates are partial)
542  // and never checks if the space might have been released and thus over-write any data that might
543  // have been written there.
544  if (option && option[0] == 'v')
545  printf("Rejected attempt to delete TDirectoryFile key: %s at address %lld, nbytes = %d\n",
546  GetName(), fSeekKey, fNbytes);
547  return;
548  }
549  if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes);
551  Long64_t last = fSeekKey + fNbytes -1;
552  if (GetFile()) GetFile()->MakeFree(first, last); // release space used by this key
553  fMotherDir->GetListOfKeys()->Remove(this);
554 }
555 
556 ////////////////////////////////////////////////////////////////////////////////
557 /// Delete key buffer(s).
558 
560 {
561  if (fBufferRef) {
562  delete fBufferRef;
563  fBufferRef = 0;
564  } else {
565  // We only need to delete fBuffer if fBufferRef is zero because
566  // if fBufferRef exists, we delegate ownership of fBuffer to fBufferRef.
567  if (fBuffer) {
568  delete [] fBuffer;
569  }
570  }
571  fBuffer = 0;
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////////
575 /// Return cycle number associated to this key.
576 
578 {
579  return ((fCycle >0) ? fCycle : -fCycle);
580 }
581 
582 ////////////////////////////////////////////////////////////////////////////////
583 /// Returns file to which key belong.
584 
586 {
587  return fMotherDir!=0 ? fMotherDir->GetFile() : gFile;
588 }
589 
590 ////////////////////////////////////////////////////////////////////////////////
591 /// Returns the "KEEP" status.
592 
594 {
595  return ((fCycle >0) ? 0 : 1);
596 }
597 
598 ////////////////////////////////////////////////////////////////////////////////
599 /// Encode key header into output buffer.
600 
601 void TKey::FillBuffer(char *&buffer)
602 {
603  tobuf(buffer, fNbytes);
604  Version_t version = fVersion;
605  tobuf(buffer, version);
606 
607  tobuf(buffer, fObjlen);
609  TDatime((UInt_t) 1).FillBuffer(buffer);
610  else
611  fDatime.FillBuffer(buffer);
612  tobuf(buffer, fKeylen);
613  tobuf(buffer, fCycle);
614  if (fVersion > 1000) {
615  tobuf(buffer, fSeekKey);
616 
617  // We currently store in the 16 highest bit of fSeekPdir the value of
618  // fPidOffset. This offset is used when a key (or basket) is transfered from one
619  // file to the other. In this case the TRef and TObject might have stored a
620  // pid index (to retrieve TProcessIDs) which refered to their order on the original
621  // file, the fPidOffset is to be added to those values to correctly find the
622  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
623  // and need to be zero for new key/basket.
625  tobuf(buffer, pdir);
626  } else {
627  tobuf(buffer, (Int_t)fSeekKey);
628  tobuf(buffer, (Int_t)fSeekPdir);
629  }
630  if (TestBit(kIsDirectoryFile)) {
631  // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
633  } else {
634  fClassName.FillBuffer(buffer);
635  }
636  fName.FillBuffer(buffer);
637  fTitle.FillBuffer(buffer);
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Increment fPidOffset by 'offset'.
642 ///
643 /// This offset is used when a key (or basket) is transfered from one file to
644 /// the other. In this case the TRef and TObject might have stored a pid
645 /// index (to retrieve TProcessIDs) which refered to their order on the
646 /// original file, the fPidOffset is to be added to those values to correctly
647 /// find the TProcessID. This fPidOffset needs to be increment if the
648 /// key/basket is copied and need to be zero for new key/basket.
649 
651 {
652  fPidOffset += offset;
653  if (fPidOffset) {
654  // We currently store fPidOffset in the 16 highest bit of fSeekPdir, which
655  // need to be store as a 64 bit integer. So we require this key to be
656  // a 'large file' key.
657  if (fVersion<1000) fVersion += 1000;
658  }
659 }
660 
661 ////////////////////////////////////////////////////////////////////////////////
662 /// Check if object referenced by the key is a folder.
663 
665 {
666  Bool_t ret = kFALSE;
667 
668  TClass *classPtr = TClass::GetClass((const char *) fClassName);
669  if (classPtr && classPtr->GetState() > TClass::kEmulated && classPtr->IsTObject()) {
670  TObject *obj = (TObject *) classPtr->DynamicCast(TObject::Class(), classPtr->New(TClass::kDummyNew));
671  if (obj) {
672  ret = obj->IsFolder();
673  delete obj;
674  }
675  }
676 
677  return ret;
678 }
679 
680 ////////////////////////////////////////////////////////////////////////////////
681 /// Set the "KEEP" status.
682 ///
683 /// When the KEEP flag is set to 1 the object cannot be purged.
684 
686 {
687  if (fCycle >0) fCycle = -fCycle;
688 }
689 
690 ////////////////////////////////////////////////////////////////////////////////
691 /// List Key contents.
692 
693 void TKey::ls(Option_t *) const
694 {
696  std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<std::endl;
697 }
698 
699 ////////////////////////////////////////////////////////////////////////////////
700 /// Print key contents.
701 
702 void TKey::Print(Option_t *) const
703 {
704  printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
705 }
706 
707 ////////////////////////////////////////////////////////////////////////////////
708 /// To read a TObject* from the file.
709 ///
710 /// The object associated to this key is read from the file into memory
711 /// Once the key structure is read (via Streamer) the class identifier
712 /// of the object is known.
713 /// Using the class identifier we find the TClass object for this class.
714 /// A TClass object contains a full description (i.e. dictionary) of the
715 /// associated class. In particular the TClass object can create a new
716 /// object of the class type it describes. This new object now calls its
717 /// Streamer function to rebuilt itself.
718 ///
719 /// Use TKey::ReadObjectAny to read any object non-derived from TObject
720 ///
721 /// ### Note
722 /// A C style cast can only be used in the case where the final class
723 /// of this object derives from TObject as a first inheritance, otherwise
724 /// one must use a dynamic_cast.
725 ///
726 /// #### Example1: simplified case
727 /// class MyClass : public TObject, public AnotherClass
728 /// then on return, one get away with using:
729 /// MyClass *obj = (MyClass*)key->ReadObj();
730 ///
731 /// #### Example2: Usual case (recommended unless performance is critical)
732 /// MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj());
733 /// which support also the more complex inheritance like:
734 /// class MyClass : public AnotherClass, public TObject
735 ///
736 /// Of course, dynamic_cast<> can also be used in the example 1.
737 
739 {
741  if (!cl) {
742  Error("ReadObj", "Unknown class %s", fClassName.Data());
743  return 0;
744  }
745  if (!cl->IsTObject()) {
746  // in principle user should call TKey::ReadObjectAny!
747  return (TObject*)ReadObjectAny(0);
748  }
749 
751  if (!bufferRef.Buffer()) {
752  Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
753  return 0;
754  }
755  if (GetFile()==0) return 0;
756  bufferRef.SetParent(GetFile());
757  bufferRef.SetPidOffset(fPidOffset);
758 
759  std::unique_ptr<char []> compressedBuffer;
760  auto storeBuffer = fBuffer;
761  if (fObjlen > fNbytes-fKeylen) {
762  compressedBuffer.reset(new char[fNbytes]);
763  fBuffer = compressedBuffer.get();
764  if( !ReadFile() ) //Read object structure from file
765  {
766  fBuffer = 0;
767  return 0;
768  }
769  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
770  } else {
771  fBuffer = bufferRef.Buffer();
772  if( !ReadFile() ) { //Read object structure from file
773 
774  fBuffer = 0;
775  return 0;
776  }
777  }
778  fBuffer = storeBuffer;
779 
780  // get version of key
781  bufferRef.SetBufferOffset(sizeof(fNbytes));
782  Version_t kvers = bufferRef.ReadVersion();
783 
784  bufferRef.SetBufferOffset(fKeylen);
785  TObject *tobj = 0;
786  // Create an instance of this class
787 
788  char *pobj = (char*)cl->New();
789  if (!pobj) {
790  Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
791  return 0;
792  }
793  Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
794  if (baseOffset==-1) {
795  // cl does not inherit from TObject.
796  // Since this is not possible yet, the only reason we could reach this code
797  // is because something is screw up in the ROOT code.
798  Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
799  fClassName.Data());
800  }
801  tobj = (TObject*)(pobj+baseOffset);
802  if (kvers > 1)
803  bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
804 
805  if (fObjlen > fNbytes-fKeylen) {
806  char *objbuf = bufferRef.Buffer() + fKeylen;
807  UChar_t *bufcur = (UChar_t *)&compressedBuffer[fKeylen];
808  Int_t nin, nout = 0, nbuf;
809  Int_t noutot = 0;
810  while (1) {
811  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
812  if (hc!=0) break;
813  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
814  if (!nout) break;
815  noutot += nout;
816  if (noutot >= fObjlen) break;
817  bufcur += nin;
818  objbuf += nout;
819  }
820  compressedBuffer.reset(nullptr);
821  if (nout) {
822  tobj->Streamer(bufferRef); //does not work with example 2 above
823  } else {
824  // Even-though we have a TObject, if the class is emulated the virtual
825  // table may not be 'right', so let's go via the TClass.
826  cl->Destructor(pobj);
827  return nullptr;
828  }
829  } else {
830  tobj->Streamer(bufferRef);
831  }
832 
833  if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
834 
835  if (cl->InheritsFrom(TDirectoryFile::Class())) {
836  TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
837  dir->SetName(GetName());
838  dir->SetTitle(GetTitle());
839  dir->SetMother(fMotherDir);
840  fMotherDir->Append(dir);
841  }
842 
843  // Append the object to the directory if requested:
844  {
845  ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
846  if (addfunc) {
847  addfunc(pobj, fMotherDir);
848  }
849  }
850 
851  return tobj;
852 }
853 
854 ////////////////////////////////////////////////////////////////////////////////
855 /// To read a TObject* from bufferRead.
856 ///
857 /// This function is identical to TKey::ReadObj, but it reads directly from
858 /// bufferRead instead of reading from a file.
859 /// The object associated to this key is read from the buffer into memory
860 /// Using the class identifier we find the TClass object for this class.
861 /// A TClass object contains a full description (i.e. dictionary) of the
862 /// associated class. In particular the TClass object can create a new
863 /// object of the class type it describes. This new object now calls its
864 /// Streamer function to rebuilt itself.
865 ///
866 /// ### Note
867 /// This function is called only internally by ROOT classes.
868 /// Although being public it is not supposed to be used outside ROOT.
869 /// If used, you must make sure that the bufferRead is large enough to
870 /// accomodate the object being read.
871 
873 {
874 
876  if (!cl) {
877  Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
878  return 0;
879  }
880  if (!cl->IsTObject()) {
881  // in principle user should call TKey::ReadObjectAny!
882  return (TObject*)ReadObjectAny(0);
883  }
884 
886  if (!bufferRef.Buffer()) {
887  Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
888  return 0;
889  }
890  if (GetFile()==0) return 0;
891  bufferRef.SetParent(GetFile());
892  bufferRef.SetPidOffset(fPidOffset);
893 
894  auto storeBuffer = fBuffer;
895  if (fObjlen > fNbytes-fKeylen) {
896  fBuffer = bufferRead;
897  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
898  } else {
899  fBuffer = bufferRef.Buffer();
900  ReadFile(); //Read object structure from file
901  }
902  fBuffer = storeBuffer;
903 
904  // get version of key
905  bufferRef.SetBufferOffset(sizeof(fNbytes));
906  Version_t kvers = bufferRef.ReadVersion();
907 
908  bufferRef.SetBufferOffset(fKeylen);
909  TObject *tobj = 0;
910  // Create an instance of this class
911 
912  char *pobj = (char*)cl->New();
913  if (!pobj) {
914  Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
915  return 0;
916  }
917  Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
918  if (baseOffset==-1) {
919  // cl does not inherit from TObject.
920  // Since this is not possible yet, the only reason we could reach this code
921  // is because something is screw up in the ROOT code.
922  Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
923  fClassName.Data());
924  }
925  tobj = (TObject*)(pobj+baseOffset);
926 
927  if (kvers > 1)
928  bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
929 
930  if (fObjlen > fNbytes-fKeylen) {
931  char *objbuf = bufferRef.Buffer() + fKeylen;
932  UChar_t *bufcur = (UChar_t *)&bufferRead[fKeylen];
933  Int_t nin, nout = 0, nbuf;
934  Int_t noutot = 0;
935  while (1) {
936  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
937  if (hc!=0) break;
938  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
939  if (!nout) break;
940  noutot += nout;
941  if (noutot >= fObjlen) break;
942  bufcur += nin;
943  objbuf += nout;
944  }
945  if (nout) {
946  tobj->Streamer(bufferRef); //does not work with example 2 above
947  } else {
948  // Even-though we have a TObject, if the class is emulated the virtual
949  // table may not be 'right', so let's go via the TClass.
950  cl->Destructor(pobj);
951  return nullptr;
952  }
953  } else {
954  tobj->Streamer(bufferRef);
955  }
956 
957  if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
958 
959  if (cl->InheritsFrom(TDirectoryFile::Class())) {
960  TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
961  dir->SetName(GetName());
962  dir->SetTitle(GetTitle());
963  dir->SetMother(fMotherDir);
964  fMotherDir->Append(dir);
965  }
966 
967  // Append the object to the directory if requested:
968  {
969  ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
970  if (addfunc) {
971  addfunc(pobj, fMotherDir);
972  }
973  }
974 
975  return tobj;
976 }
977 
978 ////////////////////////////////////////////////////////////////////////////////
979 /// To read an object (non deriving from TObject) from the file.
980 ///
981 /// If expectedClass is not null, we checked that that actual class of the
982 /// object stored is suitable to be stored in a pointer pointing to an object
983 /// of class 'expectedClass'. We also adjust the value of the returned address
984 /// so that it is suitable to be cast (C-Style)
985 /// a pointer pointing to an object of class 'expectedClass'.
986 ///
987 /// So for example if the class Bottom inherits from Top and the object
988 /// stored is of type Bottom you can safely do:
989 /// ~~~{.cpp}
990 /// auto TopClass = TClass::GetClass("Top");
991 /// auto ptr = (Top*) key->ReadObjectAny( TopClass );
992 /// if (ptr==0) printError("the object stored in the key is not of the expected type\n");
993 /// ~~~
994 /// The object associated to this key is read from the file into memory.
995 /// Once the key structure is read (via Streamer) the class identifier
996 /// of the object is known.
997 /// Using the class identifier we find the TClass object for this class.
998 /// A TClass object contains a full description (i.e. dictionary) of the
999 /// associated class. In particular the TClass object can create a new
1000 /// object of the class type it describes. This new object now calls its
1001 /// Streamer function to rebuilt itself.
1002 
1003 void *TKey::ReadObjectAny(const TClass* expectedClass)
1004 {
1006  if (!bufferRef.Buffer()) {
1007  Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
1008  return 0;
1009  }
1010  if (GetFile()==0) return 0;
1011  bufferRef.SetParent(GetFile());
1012  bufferRef.SetPidOffset(fPidOffset);
1013 
1014  std::unique_ptr<char []> compressedBuffer;
1015  auto storeBuffer = fBuffer;
1016  if (fObjlen > fNbytes-fKeylen) {
1017  compressedBuffer.reset(new char[fNbytes]);
1018  fBuffer = compressedBuffer.get();
1019  ReadFile(); //Read object structure from file
1020  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1021  } else {
1022  fBuffer = bufferRef.Buffer();
1023  ReadFile(); //Read object structure from file
1024  }
1025  fBuffer = storeBuffer;
1026 
1027  // get version of key
1028  bufferRef.SetBufferOffset(sizeof(fNbytes));
1029  Version_t kvers = bufferRef.ReadVersion();
1030 
1031  bufferRef.SetBufferOffset(fKeylen);
1033  TClass *clOnfile = 0;
1034  if (!cl) {
1035  Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
1036  return 0;
1037  }
1038  Int_t baseOffset = 0;
1039  if (expectedClass) {
1040  // baseOffset will be -1 if cl does not inherit from expectedClass
1041  baseOffset = cl->GetBaseClassOffset(expectedClass);
1042  if (baseOffset == -1) {
1043  // The 2 classes are unrelated, maybe there is a converter between the 2.
1044 
1045  if (!expectedClass->GetSchemaRules() ||
1046  !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
1047  {
1048  // There is no converter
1049  return 0;
1050  }
1051  baseOffset = 0; // For now we do not support requesting from a class that is the base of one of the class for which there is transformation to ....
1052  clOnfile = cl;
1053  cl = const_cast<TClass*>(expectedClass);
1054  Info("ReadObjectAny","Using Converter StreamerInfo from %s to %s",clOnfile->GetName(),expectedClass->GetName());
1055  }
1056  if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
1057  //we cannot mix a compiled class with an emulated class in the inheritance
1058  Warning("ReadObjectAny",
1059  "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
1060  cl->GetName(),expectedClass->GetName());
1061  }
1062  }
1063  // Create an instance of this class
1064 
1065  void *pobj = cl->New();
1066  if (!pobj) {
1067  Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
1068  return 0;
1069  }
1070 
1071  if (kvers > 1)
1072  bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
1073 
1074  if (fObjlen > fNbytes-fKeylen) {
1075  char *objbuf = bufferRef.Buffer() + fKeylen;
1076  UChar_t *bufcur = (UChar_t *)&compressedBuffer[fKeylen];
1077  Int_t nin, nout = 0, nbuf;
1078  Int_t noutot = 0;
1079  while (1) {
1080  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
1081  if (hc!=0) break;
1082  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1083  if (!nout) break;
1084  noutot += nout;
1085  if (noutot >= fObjlen) break;
1086  bufcur += nin;
1087  objbuf += nout;
1088  }
1089  if (nout) {
1090  cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1091  } else {
1092  cl->Destructor(pobj);
1093  return nullptr;
1094  }
1095  } else {
1096  cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1097  }
1098 
1099  if (cl->IsTObject()) {
1100  auto tobjBaseOffset = cl->GetBaseClassOffset(TObject::Class());
1101  if (tobjBaseOffset == -1) {
1102  Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
1103  fClassName.Data());
1104  }
1105  TObject *tobj = (TObject*)( ((char*)pobj) + tobjBaseOffset);
1106 
1107  // See similar adjustments in ReadObj
1108  if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1109 
1110  if (cl->InheritsFrom(TDirectoryFile::Class())) {
1111  TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1112  dir->SetName(GetName());
1113  dir->SetTitle(GetTitle());
1114  dir->SetMother(fMotherDir);
1115  fMotherDir->Append(dir);
1116  }
1117  }
1118 
1119  {
1120  // Append the object to the directory if requested:
1121  ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
1122  if (addfunc) {
1123  addfunc(pobj, fMotherDir);
1124  }
1125  }
1126 
1127  return ( ((char*)pobj) + baseOffset );
1128 }
1129 
1130 ////////////////////////////////////////////////////////////////////////////////
1131 /// To read an object from the file.
1132 ///
1133 /// The object associated to this key is read from the file into memory.
1134 /// Before invoking this function, obj has been created via the
1135 /// default constructor.
1136 
1138 {
1139  if (!obj || (GetFile()==0)) return 0;
1140 
1142  bufferRef.SetParent(GetFile());
1143  bufferRef.SetPidOffset(fPidOffset);
1144 
1145  if (fVersion > 1)
1146  bufferRef.MapObject(obj); //register obj in map to handle self reference
1147 
1148  std::unique_ptr<char []> compressedBuffer;
1149  auto storeBuffer = fBuffer;
1150  if (fObjlen > fNbytes-fKeylen) {
1151  compressedBuffer.reset(new char[fNbytes]);
1152  fBuffer = compressedBuffer.get();
1153  ReadFile(); //Read object structure from file
1154  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1155  } else {
1156  fBuffer = bufferRef.Buffer();
1157  ReadFile(); //Read object structure from file
1158  }
1159  fBuffer = storeBuffer;
1160 
1161  bufferRef.SetBufferOffset(fKeylen);
1162  if (fObjlen > fNbytes-fKeylen) {
1163  char *objbuf = bufferRef.Buffer() + fKeylen;
1164  UChar_t *bufcur = (UChar_t *)&compressedBuffer[fKeylen];
1165  Int_t nin, nout = 0, nbuf;
1166  Int_t noutot = 0;
1167  while (1) {
1168  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
1169  if (hc!=0) break;
1170  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1171  if (!nout) break;
1172  noutot += nout;
1173  if (noutot >= fObjlen) break;
1174  bufcur += nin;
1175  objbuf += nout;
1176  }
1177  if (nout) obj->Streamer(bufferRef);
1178  } else {
1179  obj->Streamer(bufferRef);
1180  }
1181 
1182  // Append the object to the directory if requested:
1183  {
1184  ROOT::DirAutoAdd_t addfunc = obj->IsA()->GetDirectoryAutoAdd();
1185  if (addfunc) {
1186  addfunc(obj, fMotherDir);
1187  }
1188  }
1189 
1190  return fNbytes;
1191 }
1192 
1193 ////////////////////////////////////////////////////////////////////////////////
1194 /// Decode input buffer.
1195 ///
1196 /// In some situation will add key to gDirectory.
1197 
1198 void TKey::ReadBuffer(char *&buffer)
1199 {
1200  ReadKeyBuffer(buffer);
1201 
1202  if (!gROOT->ReadingObject() && gDirectory) {
1203  if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this);
1204  }
1205 }
1206 
1207 ////////////////////////////////////////////////////////////////////////////////
1208 /// Decode input buffer.
1209 
1210 void TKey::ReadKeyBuffer(char *&buffer)
1211 {
1212  frombuf(buffer, &fNbytes);
1213  Version_t version;
1214  frombuf(buffer,&version);
1215  fVersion = (Int_t)version;
1216  frombuf(buffer, &fObjlen);
1217  fDatime.ReadBuffer(buffer);
1218  frombuf(buffer, &fKeylen);
1219  frombuf(buffer, &fCycle);
1220  if (fVersion > 1000) {
1221  frombuf(buffer, &fSeekKey);
1222 
1223  // We currently store in the 16 highest bit of fSeekPdir the value of
1224  // fPidOffset. This offset is used when a key (or basket) is transfered from one
1225  // file to the other. In this case the TRef and TObject might have stored a
1226  // pid index (to retrieve TProcessIDs) which refered to their order on the original
1227  // file, the fPidOffset is to be added to those values to correctly find the
1228  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1229  // and need to be zero for new key/basket.
1230  Long64_t pdir;
1231  frombuf(buffer, &pdir);
1232  fPidOffset = pdir >> kPidOffsetShift;
1233  fSeekPdir = pdir & kPidOffsetMask;
1234  } else {
1235  UInt_t seekkey,seekdir;
1236  frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
1237  frombuf(buffer, &seekdir); fSeekPdir= (Long64_t)seekdir;
1238  }
1239  fClassName.ReadBuffer(buffer);
1240  //the following test required for forward and backward compatibility
1241  if (fClassName == "TDirectory") {
1242  fClassName = "TDirectoryFile";
1244  }
1245 
1246  fName.ReadBuffer(buffer);
1247  fTitle.ReadBuffer(buffer);
1248 }
1249 
1250 ////////////////////////////////////////////////////////////////////////////////
1251 /// Read the key structure from the file
1252 
1254 {
1255  TFile* f = GetFile();
1256  if (f==0) return kFALSE;
1257 
1258  Int_t nsize = fNbytes;
1259  f->Seek(fSeekKey);
1260 #if 0
1261  for (Int_t i = 0; i < nsize; i += kMAXFILEBUFFER) {
1262  int nb = kMAXFILEBUFFER;
1263  if (i+nb > nsize) nb = nsize - i;
1264  f->ReadBuffer(fBuffer+i,nb);
1265  }
1266 #else
1267  if( f->ReadBuffer(fBuffer,nsize) )
1268  {
1269  Error("ReadFile", "Failed to read data.");
1270  return kFALSE;
1271  }
1272 #endif
1273  if (gDebug) {
1274  std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
1275  }
1276  return kTRUE;
1277 }
1278 
1279 ////////////////////////////////////////////////////////////////////////////////
1280 /// Set parent in key buffer.
1281 
1282 void TKey::SetParent(const TObject *parent)
1283 {
1284  if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
1285 }
1286 
1287 ////////////////////////////////////////////////////////////////////////////////
1288 /// Reset the key as it had not been 'filled' yet.
1289 
1291 {
1292  fPidOffset = 0;
1293  fNbytes = 0;
1294  fBuffer = 0;
1295  fObjlen = 0;
1296  fCycle = 0;
1297  fSeekPdir = 0;
1298  fSeekKey = 0;
1299  fLeft = 0;
1300  fDatime = (UInt_t)0;
1301 
1302  // fBufferRef and fKeylen intentionally not reset/changed
1303 
1305 }
1306 
1307 ////////////////////////////////////////////////////////////////////////////////
1308 /// Return the size in bytes of the key header structure.
1309 ///
1310 /// An explaination about the nbytes (Int_t nbytes) variable used in the
1311 /// function. The size of fSeekKey and fSeekPdir is 8 instead of 4 if version is
1312 /// greater than 1000.
1313 /// | Component | Sizeof |
1314 /// |-------------------|--------|
1315 /// | fNbytes | 4 |
1316 /// | sizeof(Version_t) | 2 |
1317 /// | fObjlen | 4 |
1318 /// | fKeylen | 2 |
1319 /// | fCycle | 2 |
1320 /// | fSeekKey | 4 or 8 |
1321 /// | fSeekPdir | 4 or 8 |
1322 /// | **TOTAL** | 22 |
1323 
1325 {
1326  Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
1327  nbytes += fDatime.Sizeof();
1328  if (TestBit(kIsDirectoryFile)) {
1329  nbytes += 11; // strlen("TDirectory")+1
1330  } else {
1331  nbytes += fClassName.Sizeof();
1332  }
1333  nbytes += fName.Sizeof();
1334  nbytes += fTitle.Sizeof();
1335  return nbytes;
1336 }
1337 
1338 ////////////////////////////////////////////////////////////////////////////////
1339 /// Stream a class object.
1340 
1341 void TKey::Streamer(TBuffer &b)
1342 {
1343  Version_t version;
1344  if (b.IsReading()) {
1345  b >> fNbytes;
1346  b >> version; fVersion = (Int_t)version;
1347  b >> fObjlen;
1348  fDatime.Streamer(b);
1349  b >> fKeylen;
1350  b >> fCycle;
1351  if (fVersion > 1000) {
1352  b >> fSeekKey;
1353 
1354  // We currently store in the 16 highest bit of fSeekPdir the value of
1355  // fPidOffset. This offset is used when a key (or basket) is transfered from one
1356  // file to the other. In this case the TRef and TObject might have stored a
1357  // pid index (to retrieve TProcessIDs) which refered to their order on the original
1358  // file, the fPidOffset is to be added to those values to correctly find the
1359  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1360  // and need to be zero for new key/basket.
1361  Long64_t pdir;
1362  b >> pdir;
1363  fPidOffset = pdir >> kPidOffsetShift;
1364  fSeekPdir = pdir & kPidOffsetMask;
1365  } else {
1366  UInt_t seekkey, seekdir;
1367  b >> seekkey; fSeekKey = (Long64_t)seekkey;
1368  b >> seekdir; fSeekPdir= (Long64_t)seekdir;
1369  }
1370  fClassName.Streamer(b);
1371  //the following test required for forward and backward compatibility
1372  if (fClassName == "TDirectory") {
1373  fClassName = "TDirectoryFile";
1375  }
1376  fName.Streamer(b);
1377  fTitle.Streamer(b);
1378  if (fKeylen < 0) {
1379  Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
1380  MakeZombie();
1381  fKeylen = 0;
1382  }
1383  if (fObjlen < 0) {
1384  Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
1385  MakeZombie();
1386  fObjlen = 0;
1387  }
1388  if (fNbytes < 0) {
1389  Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
1390  MakeZombie();
1391  fNbytes = 0;
1392  }
1393 
1394  } else {
1395  b << fNbytes;
1396  version = (Version_t)fVersion;
1397  b << version;
1398  b << fObjlen;
1399  if (fDatime.Get() == 0) fDatime.Set();
1401  TDatime((UInt_t) 1).Streamer(b);
1402  else
1403  fDatime.Streamer(b);
1404  b << fKeylen;
1405  b << fCycle;
1406  if (fVersion > 1000) {
1407  b << fSeekKey;
1408 
1409  // We currently store in the 16 highest bit of fSeekPdir the value of
1410  // fPidOffset. This offset is used when a key (or basket) is transfered from one
1411  // file to the other. In this case the TRef and TObject might have stored a
1412  // pid index (to retrieve TProcessIDs) which refered to their order on the original
1413  // file, the fPidOffset is to be added to those values to correctly find the
1414  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1415  // and need to be zero for new key/basket.
1417  b << pdir;
1418  } else {
1419  b << (Int_t)fSeekKey;
1420  b << (Int_t)fSeekPdir;
1421  }
1422  if (TestBit(kIsDirectoryFile)) {
1423  // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
1424  b.WriteTString(gTDirectoryString);
1425  } else {
1426  fClassName.Streamer(b);
1427  }
1428  fName.Streamer(b);
1429  fTitle.Streamer(b);
1430  }
1431 }
1432 
1433 ////////////////////////////////////////////////////////////////////////////////
1434 /// Write the encoded object supported by this key.
1435 /// The function returns the number of bytes committed to the file.
1436 /// If a write error occurs, the number of bytes returned is -1.
1437 
1439 {
1440  if (!f) f = GetFile();
1441  if (!f) return -1;
1442 
1443  Int_t nsize = fNbytes;
1444  char *buffer = fBuffer;
1445  if (cycle) {
1446  fCycle = cycle;
1447  FillBuffer(buffer);
1448  buffer = fBuffer;
1449  }
1450 
1451  if (fLeft > 0) nsize += sizeof(Int_t);
1452  f->Seek(fSeekKey);
1453 #if 0
1454  for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) {
1455  Int_t nb = kMAXFILEBUFFER;
1456  if (i+nb > nsize) nb = nsize - i;
1457  f->WriteBuffer(buffer,nb);
1458  buffer += nb;
1459  }
1460 #else
1461  Bool_t result = f->WriteBuffer(buffer,nsize);
1462 #endif
1463  //f->Flush(); Flushing takes too much time.
1464  // Let user flush the file when they want.
1465  if (gDebug) {
1466  std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1467  <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1468  }
1469 
1470  DeleteBuffer();
1471  return result==kTRUE ? -1 : nsize;
1472 }
1473 
1474 ////////////////////////////////////////////////////////////////////////////////
1475 /// Write the encoded object supported by this key.
1476 /// The function returns the number of bytes committed to the file.
1477 /// If a write error occurs, the number of bytes returned is -1.
1478 
1480 {
1481  if (!f) f = GetFile();
1482  if (!f) return -1;
1483 
1484  Int_t nsize = fNbytes;
1485  char *buffer = fBuffer;
1486 
1487  if (fLeft > 0) nsize += sizeof(Int_t);
1488  f->Seek(fSeekKey);
1489 #if 0
1490  for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) {
1491  Int_t nb = kMAXFILEBUFFER;
1492  if (i+nb > nsize) nb = nsize - i;
1493  f->WriteBuffer(buffer,nb);
1494  buffer += nb;
1495  }
1496 #else
1497  Bool_t result = f->WriteBuffer(buffer,nsize);
1498 #endif
1499  //f->Flush(); Flushing takes too much time.
1500  // Let user flush the file when they want.
1501  if (gDebug) {
1502  std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1503  <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1504  }
1505 
1506  return result==kTRUE ? -1 : nsize;
1507 }
1508 
1509 ////////////////////////////////////////////////////////////////////////////////
1510 /// Title can keep 32x32 xpm thumbnail/icon of the parent object.
1511 
1512 const char *TKey::GetIconName() const
1513 {
1514  return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
1515 }
1516 
1517 ////////////////////////////////////////////////////////////////////////////////
1518 /// Returns title (title can contain 32x32 xpm thumbnail/icon).
1519 
1520 const char *TKey::GetTitle() const
1521 {
1522  if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail
1523  static TString ret;
1524  int start = fTitle.Index("/*") + 3;
1525  int stop = fTitle.Index("*/") - 1;
1526  ret = fTitle(start, stop - start);
1527  return ret.Data();
1528  }
1529  return fTitle.Data();
1530 }
TClass::Browse
virtual void Browse(TBrowser *b)
This method is called by a browser to get the class information.
Definition: TClass.cxx:1979
TString::ReadBuffer
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition: TString.cxx:1264
first
Definition: first.py:1
TBrowser
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
TKey::fLeft
Int_t fLeft
Number of bytes left in current segment.
Definition: TKey.h:48
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:89
TDirectory::GetList
virtual TList * GetList() const
Definition: TDirectory.h:165
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
TFree.h
Version_t
short Version_t
Definition: RtypesCore.h:63
TClass::Streamer
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:602
TDatime::Get
UInt_t Get() const
Return raw date/time as encoded by TDatime.
Definition: TDatime.cxx:239
TDirectory::GetListOfKeys
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:166
f
#define f(i)
Definition: RSha256.hxx:104
Option_t
const char Option_t
Definition: RtypesCore.h:64
TMath::Max
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
TBuffer::kRead
@ kRead
Definition: TBuffer.h:72
TKey::GetKeep
Short_t GetKeep() const
Returns the "KEEP" status.
Definition: TKey.cxx:593
TClass::GetActualClass
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2577
UShort_t
unsigned short UShort_t
Definition: RtypesCore.h:38
TList::FindObject
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
TBufferIO::SetPidOffset
void SetPidOffset(UShort_t offset) override
This offset is used when a key (or basket) is transfered from one file to the other.
Definition: TBufferIO.cxx:319
TKey::fVersion
Int_t fVersion
Key version identifier.
Definition: TKey.h:39
TString::Data
const char * Data() const
Definition: TString.h:364
R__unzip
void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout)
TKey::ReadObjectAny
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition: TKey.cxx:1003
ROOT::RCompressionSetting::EAlgorithm::EValues
EValues
Note: this is only temporarily a struct and will become a enum class hence the name.
Definition: Compression.h:83
TDatime::ReadBuffer
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition: TDatime.cxx:277
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:361
TKey::fPidOffset
UShort_t fPidOffset
!Offset to be added to the pid index in this key/buffer. This is actually saved in the high bits of f...
Definition: TKey.h:51
TKey::TKey
TKey()
TKey default constructor.
Definition: TKey.cxx:90
tobuf
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:57
TKey::DeleteBuffer
virtual void DeleteBuffer()
Delete key buffer(s).
Definition: TKey.cxx:559
TObject::Info
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
Long64_t
long long Long64_t
Definition: RtypesCore.h:71
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
TBuffer::MapObject
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
gFile
#define gFile
Definition: TFile.h:342
TClass::HasDefaultConstructor
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
TKey::fSeekPdir
Long64_t fSeekPdir
Location of parent directory on file.
Definition: TKey.h:46
TFree::GetLast
Long64_t GetLast() const
Definition: TFree.h:41
TObject::Fatal
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:919
TDatime::Sizeof
Int_t Sizeof() const
Definition: TDatime.h:81
R__unzip_header
int R__unzip_header(Int_t *nin, UChar_t *bufin, Int_t *lout)
Int_t
int Int_t
Definition: RtypesCore.h:43
TBrowser.h
TNamed::fName
TString fName
Definition: TNamed.h:32
TBuffer::Buffer
char * Buffer() const
Definition: TBuffer.h:95
TString::Length
Ssiz_t Length() const
Definition: TString.h:405
TKey::WriteFile
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1438
TClass.h
TBufferIO::MapObject
void MapObject(const TObject *obj, UInt_t offset=1) override
Add object to the fMap container.
Definition: TBufferIO.cxx:163
ROOT::Detail::TSchemaRuleSet::HasRuleWithSourceClass
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
Definition: TSchemaRuleSet.cxx:198
keyAbsNumber
std::atomic< UInt_t > keyAbsNumber
Definition: TKey.cxx:83
TKey::fMotherDir
TDirectory * fMotherDir
!pointer to mother directory
Definition: TKey.h:52
TKey::fBuffer
char * fBuffer
Object buffer.
Definition: TKey.h:49
TBuffer
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
TKey::FillBuffer
virtual void FillBuffer(char *&buffer)
Encode key header into output buffer.
Definition: TKey.cxx:601
TKey::fBufferRef
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition: TKey.h:50
TKey::Browse
virtual void Browse(TBrowser *b)
Read object from disk and call its Browse() method.
Definition: TKey.cxx:427
TKey::Build
void Build(TDirectory *motherDir, const char *classname, Long64_t filepos)
Method used in all TKey constructor to initialize basic data fields.
Definition: TKey.cxx:389
TString
Basic string class.
Definition: TString.h:131
TKey::ReadFile
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition: TKey.cxx:1253
TClass::GetSchemaRules
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1901
TBuffer::SetBufferOffset
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:92
TObject::InheritsFrom
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
b
#define b(i)
Definition: RSha256.hxx:100
TFile.h
bool
TDatime::Set
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:288
ROOT::DirAutoAdd_t
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:111
TNamed::fTitle
TString fTitle
Definition: TNamed.h:33
TKey::Print
virtual void Print(Option_t *option="") const
Print key contents.
Definition: TKey.cxx:702
TKey::kReproducible
@ kReproducible
Definition: TKey.h:33
TROOT.h
TKey::Sizeof
virtual Int_t Sizeof() const
Return the size in bytes of the key header structure.
Definition: TKey.cxx:1324
TFile::kReproducible
@ kReproducible
Definition: TFile.h:188
TList::First
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:658
TClass::kEmulated
@ kEmulated
Definition: TClass.h:125
TBuffer::Length
Int_t Length() const
Definition: TBuffer.h:99
TFile::GetCompressionAlgorithm
Int_t GetCompressionAlgorithm() const
Definition: TFile.h:386
TFree::SetLast
void SetLast(Long64_t last)
Definition: TFree.h:45
TObject::UseCurrentStyle
virtual void UseCurrentStyle()
Set current style settings in this object This function is called when either TCanvas::UseCurrentStyl...
Definition: TObject.cxx:715
TDirectory::Append
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:191
TClass::InheritsFrom
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4844
TString::Resize
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1095
TKey::GetClassName
virtual const char * GetClassName() const
Definition: TKey.h:76
TKey::ReadBuffer
virtual void ReadBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1198
TClass::New
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4948
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
TKey::GetFile
TFile * GetFile() const
Returns file to which key belong.
Definition: TKey.cxx:585
TFile::kStartBigFile
@ kStartBigFile
Definition: TFile.h:191
TNamed
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TKey::fClassName
TString fClassName
Object Class name.
Definition: TKey.h:47
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:90
TDirectory::AppendKey
virtual Int_t AppendKey(TKey *)
Definition: TDirectory.h:130
TKey::ls
virtual void ls(Option_t *option="") const
List Key contents.
Definition: TKey.cxx:693
gDebug
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
TKey::Delete
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:538
gDirectory
#define gDirectory
Definition: TDirectory.h:229
TDirectoryFile.h
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:44
TString::BeginsWith
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
TKey::IsFolder
Bool_t IsFolder() const
Check if object referenced by the key is a folder.
Definition: TKey.cxx:664
TClass::GetClass
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:2937
TObject::MakeZombie
void MakeZombie()
Definition: TObject.h:49
Short_t
short Short_t
Definition: RtypesCore.h:37
TDirectoryFile::GetSeekDir
Long64_t GetSeekDir() const override
Definition: TDirectoryFile.h:99
TKey::IncrementPidOffset
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by 'offset'.
Definition: TKey.cxx:650
TNamed::SetTitle
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
TFile::MakeFree
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1394
TObject::Warning
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
TClass::IsTObject
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5908
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:53
TROOT::IndentLevel
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2781
kPidOffsetShift
const UChar_t kPidOffsetShift
Definition: TKey.cxx:80
TKey::ReadObjWithBuffer
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition: TKey.cxx:872
unsigned int
TKey::fKeylen
Short_t fKeylen
Number of bytes for the key itself.
Definition: TKey.h:43
TKey::SetParent
virtual void SetParent(const TObject *parent)
Set parent in key buffer.
Definition: TKey.cxx:1282
TKey::GetIconName
virtual const char * GetIconName() const
Title can keep 32x32 xpm thumbnail/icon of the parent object.
Definition: TKey.cxx:1512
TString::Index
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
TVirtualStreamerInfo.h
TKey
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:28
TFree::GetFirst
Long64_t GetFirst() const
Definition: TFree.h:40
TKey::ReadObj
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition: TKey.cxx:738
kTitleMax
const Int_t kTitleMax
Definition: TKey.cxx:70
TString::Sizeof
virtual Int_t Sizeof() const
Returns size string will occupy on I/O buffer.
Definition: TString.cxx:1334
TDatime::FillBuffer
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition: TDatime.cxx:228
ULong64_t
unsigned long long ULong64_t
Definition: RtypesCore.h:72
TKey::fDatime
TDatime fDatime
Date/Time of insertion in file.
Definition: TKey.h:42
TDirectory::GetSeekDir
virtual Long64_t GetSeekDir() const
Definition: TDirectory.h:171
TFree::SetFirst
void SetFirst(Long64_t first)
Definition: TFree.h:44
TKey::fCycle
Short_t fCycle
Cycle number.
Definition: TKey.h:44
f1
TF1 * f1
Definition: legend1.C:11
TString::IsNull
Bool_t IsNull() const
Definition: TString.h:402
TClass::DynamicCast
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition: TClass.cxx:4885
TKey::WriteFileKeepBuffer
virtual Int_t WriteFileKeepBuffer(TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1479
TKey::Reset
void Reset()
Reset the key as it had not been 'filled' yet.
Definition: TKey.cxx:1290
R__ASSERT
#define R__ASSERT(e)
Definition: TError.h:96
TClass::GetDirectoryAutoAdd
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
kPidOffsetMask
const ULong64_t kPidOffsetMask
Definition: TKey.cxx:76
TKey::fNbytes
Int_t fNbytes
Number of bytes for the object on file.
Definition: TKey.h:40
TList::Remove
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:821
TKey::~TKey
virtual ~TKey()
TKey default destructor.
Definition: TKey.cxx:525
TInterpreter.h
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
frombuf
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:280
UChar_t
unsigned char UChar_t
Definition: RtypesCore.h:36
TClass::Destructor
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5370
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
TBufferFile.h
TKey::GetCycle
Short_t GetCycle() const
Return cycle number associated to this key.
Definition: TKey.cxx:577
Bytes.h
TFile::GetCompressionLevel
Int_t GetCompressionLevel() const
Definition: TFile.h:392
TClass::GetBaseClassOffset
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2760
TDirectory::GetFile
virtual TFile * GetFile() const
Definition: TDirectory.h:163
TKey::fObjlen
Int_t fObjlen
Length of uncompressed object in bytes.
Definition: TKey.h:41
name
char name[80]
Definition: TGX11.cxx:109
TObject::Delete
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:169
TSchemaRuleSet.h
TDirectory
Describe directory structure in memory.
Definition: TDirectory.h:40
TClass::GetState
EState GetState() const
Definition: TClass.h:485
gTDirectoryString
static const TString gTDirectoryString("TDirectory")
TFree
Service class for TFile.
Definition: TFree.h:27
TFile::GetEND
virtual Long64_t GetEND() const
Definition: TFile.h:222
TKey::GetTitle
virtual const char * GetTitle() const
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition: TKey.cxx:1520
TDatime
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
TKey::Keep
virtual void Keep()
Set the "KEEP" status.
Definition: TKey.cxx:685
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TKey::Read
virtual Int_t Read(const char *name)
Read contents of object with specified name from the current directory.
Definition: TKey.h:54
TDirectory::SetName
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
Definition: TDirectory.cxx:1227
TKey.h
TBuffer::SetParent
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:270
Class
void Class()
Definition: Class.C:29
TDirectoryFile
A ROOT file is structured in Directories (like a file system).
Definition: TDirectoryFile.h:34
Riostream.h
TKey::fSeekKey
Long64_t fSeekKey
Location of object on file.
Definition: TKey.h:45
TKey::Create
virtual void Create(Int_t nbytes, TFile *f=0)
Create a TKey object of specified size.
Definition: TKey.cxx:459
TObject::ClassName
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
TObject::IsFolder
virtual Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition: TObject.cxx:473
TString::FillBuffer
virtual void FillBuffer(char *&buffer) const
Copy string into I/O buffer.
Definition: TString.cxx:1243
TBufferFile
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
TKey::kIsDirectoryFile
@ kIsDirectoryFile
Definition: TKey.h:32
ThreadLocalStorage.h
TKey::ReadKeyBuffer
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1210
TDirectory::SetMother
virtual void SetMother(TObject *mother)
Definition: TDirectory.h:200
TBufferFile::ReadVersion
Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr) override
Read class version from I/O buffer.
Definition: TBufferFile.cxx:2761
TList
A doubly linked list.
Definition: TList.h:44
TBuffer::kWrite
@ kWrite
Definition: TBuffer.h:72
TObject::SetUniqueID
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
TClass::kDummyNew
@ kDummyNew
Definition: TClass.h:107
gROOT
#define gROOT
Definition: TROOT.h:406
int
TError.h