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 #include <iostream>
52 
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 /// Add indicator of whether it is the current item or a backup copy.
693 
694 void TKey::ls(Bool_t current) const
695 {
697  std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle();
698  std::cout << (current ? " [current cycle]" : " [backup cycle]");
699  std::cout <<std::endl;
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// List Key contents.
704 
705 void TKey::ls(Option_t *) const
706 {
708  std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<std::endl;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 /// Print key contents.
713 
714 void TKey::Print(Option_t *) const
715 {
716  printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
717 }
718 
719 ////////////////////////////////////////////////////////////////////////////////
720 /// To read a TObject* from the file.
721 ///
722 /// The object associated to this key is read from the file into memory
723 /// Once the key structure is read (via Streamer) the class identifier
724 /// of the object is known.
725 /// Using the class identifier we find the TClass object for this class.
726 /// A TClass object contains a full description (i.e. dictionary) of the
727 /// associated class. In particular the TClass object can create a new
728 /// object of the class type it describes. This new object now calls its
729 /// Streamer function to rebuilt itself.
730 ///
731 /// Use TKey::ReadObjectAny to read any object non-derived from TObject
732 ///
733 /// ### Note
734 /// A C style cast can only be used in the case where the final class
735 /// of this object derives from TObject as a first inheritance, otherwise
736 /// one must use a dynamic_cast.
737 ///
738 /// #### Example1: simplified case
739 /// class MyClass : public TObject, public AnotherClass
740 /// then on return, one get away with using:
741 /// MyClass *obj = (MyClass*)key->ReadObj();
742 ///
743 /// #### Example2: Usual case (recommended unless performance is critical)
744 /// MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj());
745 /// which support also the more complex inheritance like:
746 /// class MyClass : public AnotherClass, public TObject
747 ///
748 /// Of course, dynamic_cast<> can also be used in the example 1.
749 
751 {
753  if (!cl) {
754  Error("ReadObj", "Unknown class %s", fClassName.Data());
755  return 0;
756  }
757  if (!cl->IsTObject()) {
758  // in principle user should call TKey::ReadObjectAny!
759  return (TObject*)ReadObjectAny(0);
760  }
761 
763  if (!bufferRef.Buffer()) {
764  Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
765  return 0;
766  }
767  if (GetFile()==0) return 0;
768  bufferRef.SetParent(GetFile());
769  bufferRef.SetPidOffset(fPidOffset);
770 
771  std::unique_ptr<char []> compressedBuffer;
772  auto storeBuffer = fBuffer;
773  if (fObjlen > fNbytes-fKeylen) {
774  compressedBuffer.reset(new char[fNbytes]);
775  fBuffer = compressedBuffer.get();
776  if( !ReadFile() ) //Read object structure from file
777  {
778  fBuffer = 0;
779  return 0;
780  }
781  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
782  } else {
783  fBuffer = bufferRef.Buffer();
784  if( !ReadFile() ) { //Read object structure from file
785 
786  fBuffer = 0;
787  return 0;
788  }
789  }
790  fBuffer = storeBuffer;
791 
792  // get version of key
793  bufferRef.SetBufferOffset(sizeof(fNbytes));
794  Version_t kvers = bufferRef.ReadVersion();
795 
796  bufferRef.SetBufferOffset(fKeylen);
797  TObject *tobj = 0;
798  // Create an instance of this class
799 
800  char *pobj = (char*)cl->New();
801  if (!pobj) {
802  Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
803  return 0;
804  }
805  Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
806  if (baseOffset==-1) {
807  // cl does not inherit from TObject.
808  // Since this is not possible yet, the only reason we could reach this code
809  // is because something is screw up in the ROOT code.
810  Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
811  fClassName.Data());
812  }
813  tobj = (TObject*)(pobj+baseOffset);
814  if (kvers > 1)
815  bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
816 
817  if (fObjlen > fNbytes-fKeylen) {
818  char *objbuf = bufferRef.Buffer() + fKeylen;
819  UChar_t *bufcur = (UChar_t *)&compressedBuffer[fKeylen];
820  Int_t nin, nout = 0, nbuf;
821  Int_t noutot = 0;
822  while (1) {
823  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
824  if (hc!=0) break;
825  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
826  if (!nout) break;
827  noutot += nout;
828  if (noutot >= fObjlen) break;
829  bufcur += nin;
830  objbuf += nout;
831  }
832  compressedBuffer.reset(nullptr);
833  if (nout) {
834  tobj->Streamer(bufferRef); //does not work with example 2 above
835  } else {
836  // Even-though we have a TObject, if the class is emulated the virtual
837  // table may not be 'right', so let's go via the TClass.
838  cl->Destructor(pobj);
839  return nullptr;
840  }
841  } else {
842  tobj->Streamer(bufferRef);
843  }
844 
845  if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
846 
847  if (cl->InheritsFrom(TDirectoryFile::Class())) {
848  TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
849  dir->SetName(GetName());
850  dir->SetTitle(GetTitle());
851  dir->SetMother(fMotherDir);
852  fMotherDir->Append(dir);
853  }
854 
855  // Append the object to the directory if requested:
856  {
857  ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
858  if (addfunc) {
859  addfunc(pobj, fMotherDir);
860  }
861  }
862 
863  return tobj;
864 }
865 
866 ////////////////////////////////////////////////////////////////////////////////
867 /// To read a TObject* from bufferRead.
868 ///
869 /// This function is identical to TKey::ReadObj, but it reads directly from
870 /// bufferRead instead of reading from a file.
871 /// The object associated to this key is read from the buffer into memory
872 /// Using the class identifier we find the TClass object for this class.
873 /// A TClass object contains a full description (i.e. dictionary) of the
874 /// associated class. In particular the TClass object can create a new
875 /// object of the class type it describes. This new object now calls its
876 /// Streamer function to rebuilt itself.
877 ///
878 /// ### Note
879 /// This function is called only internally by ROOT classes.
880 /// Although being public it is not supposed to be used outside ROOT.
881 /// If used, you must make sure that the bufferRead is large enough to
882 /// accomodate the object being read.
883 
885 {
886 
888  if (!cl) {
889  Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
890  return 0;
891  }
892  if (!cl->IsTObject()) {
893  // in principle user should call TKey::ReadObjectAny!
894  return (TObject*)ReadObjectAny(0);
895  }
896 
898  if (!bufferRef.Buffer()) {
899  Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
900  return 0;
901  }
902  if (GetFile()==0) return 0;
903  bufferRef.SetParent(GetFile());
904  bufferRef.SetPidOffset(fPidOffset);
905 
906  auto storeBuffer = fBuffer;
907  if (fObjlen > fNbytes-fKeylen) {
908  fBuffer = bufferRead;
909  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
910  } else {
911  fBuffer = bufferRef.Buffer();
912  ReadFile(); //Read object structure from file
913  }
914  fBuffer = storeBuffer;
915 
916  // get version of key
917  bufferRef.SetBufferOffset(sizeof(fNbytes));
918  Version_t kvers = bufferRef.ReadVersion();
919 
920  bufferRef.SetBufferOffset(fKeylen);
921  TObject *tobj = 0;
922  // Create an instance of this class
923 
924  char *pobj = (char*)cl->New();
925  if (!pobj) {
926  Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
927  return 0;
928  }
929  Int_t baseOffset = cl->GetBaseClassOffset(TObject::Class());
930  if (baseOffset==-1) {
931  // cl does not inherit from TObject.
932  // Since this is not possible yet, the only reason we could reach this code
933  // is because something is screw up in the ROOT code.
934  Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
935  fClassName.Data());
936  }
937  tobj = (TObject*)(pobj+baseOffset);
938 
939  if (kvers > 1)
940  bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
941 
942  if (fObjlen > fNbytes-fKeylen) {
943  char *objbuf = bufferRef.Buffer() + fKeylen;
944  UChar_t *bufcur = (UChar_t *)&bufferRead[fKeylen];
945  Int_t nin, nout = 0, nbuf;
946  Int_t noutot = 0;
947  while (1) {
948  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
949  if (hc!=0) break;
950  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
951  if (!nout) break;
952  noutot += nout;
953  if (noutot >= fObjlen) break;
954  bufcur += nin;
955  objbuf += nout;
956  }
957  if (nout) {
958  tobj->Streamer(bufferRef); //does not work with example 2 above
959  } else {
960  // Even-though we have a TObject, if the class is emulated the virtual
961  // table may not be 'right', so let's go via the TClass.
962  cl->Destructor(pobj);
963  return nullptr;
964  }
965  } else {
966  tobj->Streamer(bufferRef);
967  }
968 
969  if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
970 
971  if (cl->InheritsFrom(TDirectoryFile::Class())) {
972  TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
973  dir->SetName(GetName());
974  dir->SetTitle(GetTitle());
975  dir->SetMother(fMotherDir);
976  fMotherDir->Append(dir);
977  }
978 
979  // Append the object to the directory if requested:
980  {
981  ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
982  if (addfunc) {
983  addfunc(pobj, fMotherDir);
984  }
985  }
986 
987  return tobj;
988 }
989 
990 ////////////////////////////////////////////////////////////////////////////////
991 /// To read an object (non deriving from TObject) from the file.
992 ///
993 /// If expectedClass is not null, we checked that that actual class of the
994 /// object stored is suitable to be stored in a pointer pointing to an object
995 /// of class 'expectedClass'. We also adjust the value of the returned address
996 /// so that it is suitable to be cast (C-Style)
997 /// a pointer pointing to an object of class 'expectedClass'.
998 ///
999 /// So for example if the class Bottom inherits from Top and the object
1000 /// stored is of type Bottom you can safely do:
1001 /// ~~~{.cpp}
1002 /// auto TopClass = TClass::GetClass("Top");
1003 /// auto ptr = (Top*) key->ReadObjectAny( TopClass );
1004 /// if (ptr==0) printError("the object stored in the key is not of the expected type\n");
1005 /// ~~~
1006 /// The object associated to this key is read from the file into memory.
1007 /// Once the key structure is read (via Streamer) the class identifier
1008 /// of the object is known.
1009 /// Using the class identifier we find the TClass object for this class.
1010 /// A TClass object contains a full description (i.e. dictionary) of the
1011 /// associated class. In particular the TClass object can create a new
1012 /// object of the class type it describes. This new object now calls its
1013 /// Streamer function to rebuilt itself.
1014 
1015 void *TKey::ReadObjectAny(const TClass* expectedClass)
1016 {
1018  if (!bufferRef.Buffer()) {
1019  Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
1020  return 0;
1021  }
1022  if (GetFile()==0) return 0;
1023  bufferRef.SetParent(GetFile());
1024  bufferRef.SetPidOffset(fPidOffset);
1025 
1026  std::unique_ptr<char []> compressedBuffer;
1027  auto storeBuffer = fBuffer;
1028  if (fObjlen > fNbytes-fKeylen) {
1029  compressedBuffer.reset(new char[fNbytes]);
1030  fBuffer = compressedBuffer.get();
1031  ReadFile(); //Read object structure from file
1032  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1033  } else {
1034  fBuffer = bufferRef.Buffer();
1035  ReadFile(); //Read object structure from file
1036  }
1037  fBuffer = storeBuffer;
1038 
1039  // get version of key
1040  bufferRef.SetBufferOffset(sizeof(fNbytes));
1041  Version_t kvers = bufferRef.ReadVersion();
1042 
1043  bufferRef.SetBufferOffset(fKeylen);
1045  TClass *clOnfile = 0;
1046  if (!cl) {
1047  Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
1048  return 0;
1049  }
1050  Int_t baseOffset = 0;
1051  if (expectedClass) {
1052  // baseOffset will be -1 if cl does not inherit from expectedClass
1053  baseOffset = cl->GetBaseClassOffset(expectedClass);
1054  if (baseOffset == -1) {
1055  // The 2 classes are unrelated, maybe there is a converter between the 2.
1056 
1057  if (!expectedClass->GetSchemaRules() ||
1058  !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
1059  {
1060  // There is no converter
1061  return 0;
1062  }
1063  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 ....
1064  clOnfile = cl;
1065  cl = const_cast<TClass*>(expectedClass);
1066  Info("ReadObjectAny","Using Converter StreamerInfo from %s to %s",clOnfile->GetName(),expectedClass->GetName());
1067  }
1068  if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
1069  //we cannot mix a compiled class with an emulated class in the inheritance
1070  Warning("ReadObjectAny",
1071  "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
1072  cl->GetName(),expectedClass->GetName());
1073  }
1074  }
1075  // Create an instance of this class
1076 
1077  void *pobj = cl->New();
1078  if (!pobj) {
1079  Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
1080  return 0;
1081  }
1082 
1083  if (kvers > 1)
1084  bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
1085 
1086  if (fObjlen > fNbytes-fKeylen) {
1087  char *objbuf = bufferRef.Buffer() + fKeylen;
1088  UChar_t *bufcur = (UChar_t *)&compressedBuffer[fKeylen];
1089  Int_t nin, nout = 0, nbuf;
1090  Int_t noutot = 0;
1091  while (1) {
1092  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
1093  if (hc!=0) break;
1094  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1095  if (!nout) break;
1096  noutot += nout;
1097  if (noutot >= fObjlen) break;
1098  bufcur += nin;
1099  objbuf += nout;
1100  }
1101  if (nout) {
1102  cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1103  } else {
1104  cl->Destructor(pobj);
1105  return nullptr;
1106  }
1107  } else {
1108  cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1109  }
1110 
1111  if (cl->IsTObject()) {
1112  auto tobjBaseOffset = cl->GetBaseClassOffset(TObject::Class());
1113  if (tobjBaseOffset == -1) {
1114  Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
1115  fClassName.Data());
1116  }
1117  TObject *tobj = (TObject*)( ((char*)pobj) + tobjBaseOffset);
1118 
1119  // See similar adjustments in ReadObj
1120  if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1121 
1122  if (cl->InheritsFrom(TDirectoryFile::Class())) {
1123  TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1124  dir->SetName(GetName());
1125  dir->SetTitle(GetTitle());
1126  dir->SetMother(fMotherDir);
1127  fMotherDir->Append(dir);
1128  }
1129  }
1130 
1131  {
1132  // Append the object to the directory if requested:
1133  ROOT::DirAutoAdd_t addfunc = cl->GetDirectoryAutoAdd();
1134  if (addfunc) {
1135  addfunc(pobj, fMotherDir);
1136  }
1137  }
1138 
1139  return ( ((char*)pobj) + baseOffset );
1140 }
1141 
1142 ////////////////////////////////////////////////////////////////////////////////
1143 /// To read an object from the file.
1144 ///
1145 /// The object associated to this key is read from the file into memory.
1146 /// Before invoking this function, obj has been created via the
1147 /// default constructor.
1148 
1150 {
1151  if (!obj || (GetFile()==0)) return 0;
1152 
1154  bufferRef.SetParent(GetFile());
1155  bufferRef.SetPidOffset(fPidOffset);
1156 
1157  if (fVersion > 1)
1158  bufferRef.MapObject(obj); //register obj in map to handle self reference
1159 
1160  std::unique_ptr<char []> compressedBuffer;
1161  auto storeBuffer = fBuffer;
1162  if (fObjlen > fNbytes-fKeylen) {
1163  compressedBuffer.reset(new char[fNbytes]);
1164  fBuffer = compressedBuffer.get();
1165  ReadFile(); //Read object structure from file
1166  memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1167  } else {
1168  fBuffer = bufferRef.Buffer();
1169  ReadFile(); //Read object structure from file
1170  }
1171  fBuffer = storeBuffer;
1172 
1173  bufferRef.SetBufferOffset(fKeylen);
1174  if (fObjlen > fNbytes-fKeylen) {
1175  char *objbuf = bufferRef.Buffer() + fKeylen;
1176  UChar_t *bufcur = (UChar_t *)&compressedBuffer[fKeylen];
1177  Int_t nin, nout = 0, nbuf;
1178  Int_t noutot = 0;
1179  while (1) {
1180  Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
1181  if (hc!=0) break;
1182  R__unzip(&nin, bufcur, &nbuf, (unsigned char*) objbuf, &nout);
1183  if (!nout) break;
1184  noutot += nout;
1185  if (noutot >= fObjlen) break;
1186  bufcur += nin;
1187  objbuf += nout;
1188  }
1189  if (nout) obj->Streamer(bufferRef);
1190  } else {
1191  obj->Streamer(bufferRef);
1192  }
1193 
1194  // Append the object to the directory if requested:
1195  {
1196  ROOT::DirAutoAdd_t addfunc = obj->IsA()->GetDirectoryAutoAdd();
1197  if (addfunc) {
1198  addfunc(obj, fMotherDir);
1199  }
1200  }
1201 
1202  return fNbytes;
1203 }
1204 
1205 ////////////////////////////////////////////////////////////////////////////////
1206 /// Decode input buffer.
1207 ///
1208 /// In some situation will add key to gDirectory.
1209 
1210 void TKey::ReadBuffer(char *&buffer)
1211 {
1212  ReadKeyBuffer(buffer);
1213 
1214  if (!gROOT->ReadingObject() && gDirectory) {
1215  if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this);
1216  }
1217 }
1218 
1219 ////////////////////////////////////////////////////////////////////////////////
1220 /// Decode input buffer.
1221 
1222 void TKey::ReadKeyBuffer(char *&buffer)
1223 {
1224  frombuf(buffer, &fNbytes);
1225  Version_t version;
1226  frombuf(buffer,&version);
1227  fVersion = (Int_t)version;
1228  frombuf(buffer, &fObjlen);
1229  fDatime.ReadBuffer(buffer);
1230  frombuf(buffer, &fKeylen);
1231  frombuf(buffer, &fCycle);
1232  if (fVersion > 1000) {
1233  frombuf(buffer, &fSeekKey);
1234 
1235  // We currently store in the 16 highest bit of fSeekPdir the value of
1236  // fPidOffset. This offset is used when a key (or basket) is transfered from one
1237  // file to the other. In this case the TRef and TObject might have stored a
1238  // pid index (to retrieve TProcessIDs) which refered to their order on the original
1239  // file, the fPidOffset is to be added to those values to correctly find the
1240  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1241  // and need to be zero for new key/basket.
1242  Long64_t pdir;
1243  frombuf(buffer, &pdir);
1244  fPidOffset = pdir >> kPidOffsetShift;
1245  fSeekPdir = pdir & kPidOffsetMask;
1246  } else {
1247  UInt_t seekkey,seekdir;
1248  frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
1249  frombuf(buffer, &seekdir); fSeekPdir= (Long64_t)seekdir;
1250  }
1251  fClassName.ReadBuffer(buffer);
1252  //the following test required for forward and backward compatibility
1253  if (fClassName == "TDirectory") {
1254  fClassName = "TDirectoryFile";
1256  }
1257 
1258  fName.ReadBuffer(buffer);
1259  fTitle.ReadBuffer(buffer);
1260 }
1261 
1262 ////////////////////////////////////////////////////////////////////////////////
1263 /// Read the key structure from the file
1264 
1266 {
1267  TFile* f = GetFile();
1268  if (f==0) return kFALSE;
1269 
1270  Int_t nsize = fNbytes;
1271  f->Seek(fSeekKey);
1272 #if 0
1273  for (Int_t i = 0; i < nsize; i += kMAXFILEBUFFER) {
1274  int nb = kMAXFILEBUFFER;
1275  if (i+nb > nsize) nb = nsize - i;
1276  f->ReadBuffer(fBuffer+i,nb);
1277  }
1278 #else
1279  if( f->ReadBuffer(fBuffer,nsize) )
1280  {
1281  Error("ReadFile", "Failed to read data.");
1282  return kFALSE;
1283  }
1284 #endif
1285  if (gDebug) {
1286  std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
1287  }
1288  return kTRUE;
1289 }
1290 
1291 ////////////////////////////////////////////////////////////////////////////////
1292 /// Set parent in key buffer.
1293 
1294 void TKey::SetParent(const TObject *parent)
1295 {
1296  if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
1297 }
1298 
1299 ////////////////////////////////////////////////////////////////////////////////
1300 /// Reset the key as it had not been 'filled' yet.
1301 
1303 {
1304  fPidOffset = 0;
1305  fNbytes = 0;
1306  fBuffer = 0;
1307  fObjlen = 0;
1308  fCycle = 0;
1309  fSeekPdir = 0;
1310  fSeekKey = 0;
1311  fLeft = 0;
1312  fDatime = (UInt_t)0;
1313 
1314  // fBufferRef and fKeylen intentionally not reset/changed
1315 
1317 }
1318 
1319 ////////////////////////////////////////////////////////////////////////////////
1320 /// Return the size in bytes of the key header structure.
1321 ///
1322 /// An explaination about the nbytes (Int_t nbytes) variable used in the
1323 /// function. The size of fSeekKey and fSeekPdir is 8 instead of 4 if version is
1324 /// greater than 1000.
1325 /// | Component | Sizeof |
1326 /// |-------------------|--------|
1327 /// | fNbytes | 4 |
1328 /// | sizeof(Version_t) | 2 |
1329 /// | fObjlen | 4 |
1330 /// | fKeylen | 2 |
1331 /// | fCycle | 2 |
1332 /// | fSeekKey | 4 or 8 |
1333 /// | fSeekPdir | 4 or 8 |
1334 /// | **TOTAL** | 22 |
1335 
1337 {
1338  Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
1339  nbytes += fDatime.Sizeof();
1340  if (TestBit(kIsDirectoryFile)) {
1341  nbytes += 11; // strlen("TDirectory")+1
1342  } else {
1343  nbytes += fClassName.Sizeof();
1344  }
1345  nbytes += fName.Sizeof();
1346  nbytes += fTitle.Sizeof();
1347  return nbytes;
1348 }
1349 
1350 ////////////////////////////////////////////////////////////////////////////////
1351 /// Stream a class object.
1352 
1353 void TKey::Streamer(TBuffer &b)
1354 {
1355  Version_t version;
1356  if (b.IsReading()) {
1357  b >> fNbytes;
1358  b >> version; fVersion = (Int_t)version;
1359  b >> fObjlen;
1360  fDatime.Streamer(b);
1361  b >> fKeylen;
1362  b >> fCycle;
1363  if (fVersion > 1000) {
1364  b >> fSeekKey;
1365 
1366  // We currently store in the 16 highest bit of fSeekPdir the value of
1367  // fPidOffset. This offset is used when a key (or basket) is transfered from one
1368  // file to the other. In this case the TRef and TObject might have stored a
1369  // pid index (to retrieve TProcessIDs) which refered to their order on the original
1370  // file, the fPidOffset is to be added to those values to correctly find the
1371  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1372  // and need to be zero for new key/basket.
1373  Long64_t pdir;
1374  b >> pdir;
1375  fPidOffset = pdir >> kPidOffsetShift;
1376  fSeekPdir = pdir & kPidOffsetMask;
1377  } else {
1378  UInt_t seekkey, seekdir;
1379  b >> seekkey; fSeekKey = (Long64_t)seekkey;
1380  b >> seekdir; fSeekPdir= (Long64_t)seekdir;
1381  }
1382  fClassName.Streamer(b);
1383  //the following test required for forward and backward compatibility
1384  if (fClassName == "TDirectory") {
1385  fClassName = "TDirectoryFile";
1387  }
1388  fName.Streamer(b);
1389  fTitle.Streamer(b);
1390  if (fKeylen < 0) {
1391  Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
1392  MakeZombie();
1393  fKeylen = 0;
1394  }
1395  if (fObjlen < 0) {
1396  Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
1397  MakeZombie();
1398  fObjlen = 0;
1399  }
1400  if (fNbytes < 0) {
1401  Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
1402  MakeZombie();
1403  fNbytes = 0;
1404  }
1405 
1406  } else {
1407  b << fNbytes;
1408  version = (Version_t)fVersion;
1409  b << version;
1410  b << fObjlen;
1411  if (fDatime.Get() == 0) fDatime.Set();
1413  TDatime((UInt_t) 1).Streamer(b);
1414  else
1415  fDatime.Streamer(b);
1416  b << fKeylen;
1417  b << fCycle;
1418  if (fVersion > 1000) {
1419  b << fSeekKey;
1420 
1421  // We currently store in the 16 highest bit of fSeekPdir the value of
1422  // fPidOffset. This offset is used when a key (or basket) is transfered from one
1423  // file to the other. In this case the TRef and TObject might have stored a
1424  // pid index (to retrieve TProcessIDs) which refered to their order on the original
1425  // file, the fPidOffset is to be added to those values to correctly find the
1426  // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1427  // and need to be zero for new key/basket.
1429  b << pdir;
1430  } else {
1431  b << (Int_t)fSeekKey;
1432  b << (Int_t)fSeekPdir;
1433  }
1434  if (TestBit(kIsDirectoryFile)) {
1435  // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
1436  b.WriteTString(gTDirectoryString);
1437  } else {
1438  fClassName.Streamer(b);
1439  }
1440  fName.Streamer(b);
1441  fTitle.Streamer(b);
1442  }
1443 }
1444 
1445 ////////////////////////////////////////////////////////////////////////////////
1446 /// Write the encoded object supported by this key.
1447 /// The function returns the number of bytes committed to the file.
1448 /// If a write error occurs, the number of bytes returned is -1.
1449 
1451 {
1452  if (!f) f = GetFile();
1453  if (!f) return -1;
1454 
1455  Int_t nsize = fNbytes;
1456  char *buffer = fBuffer;
1457  if (cycle) {
1458  fCycle = cycle;
1459  FillBuffer(buffer);
1460  buffer = fBuffer;
1461  }
1462 
1463  if (fLeft > 0) nsize += sizeof(Int_t);
1464  f->Seek(fSeekKey);
1465 #if 0
1466  for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) {
1467  Int_t nb = kMAXFILEBUFFER;
1468  if (i+nb > nsize) nb = nsize - i;
1469  f->WriteBuffer(buffer,nb);
1470  buffer += nb;
1471  }
1472 #else
1473  Bool_t result = f->WriteBuffer(buffer,nsize);
1474 #endif
1475  //f->Flush(); Flushing takes too much time.
1476  // Let user flush the file when they want.
1477  if (gDebug) {
1478  std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1479  <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1480  }
1481 
1482  DeleteBuffer();
1483  return result==kTRUE ? -1 : nsize;
1484 }
1485 
1486 ////////////////////////////////////////////////////////////////////////////////
1487 /// Write the encoded object supported by this key.
1488 /// The function returns the number of bytes committed to the file.
1489 /// If a write error occurs, the number of bytes returned is -1.
1490 
1492 {
1493  if (!f) f = GetFile();
1494  if (!f) return -1;
1495 
1496  Int_t nsize = fNbytes;
1497  char *buffer = fBuffer;
1498 
1499  if (fLeft > 0) nsize += sizeof(Int_t);
1500  f->Seek(fSeekKey);
1501 #if 0
1502  for (Int_t i=0;i<nsize;i+=kMAXFILEBUFFER) {
1503  Int_t nb = kMAXFILEBUFFER;
1504  if (i+nb > nsize) nb = nsize - i;
1505  f->WriteBuffer(buffer,nb);
1506  buffer += nb;
1507  }
1508 #else
1509  Bool_t result = f->WriteBuffer(buffer,nsize);
1510 #endif
1511  //f->Flush(); Flushing takes too much time.
1512  // Let user flush the file when they want.
1513  if (gDebug) {
1514  std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1515  <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1516  }
1517 
1518  return result==kTRUE ? -1 : nsize;
1519 }
1520 
1521 ////////////////////////////////////////////////////////////////////////////////
1522 /// Title can keep 32x32 xpm thumbnail/icon of the parent object.
1523 
1524 const char *TKey::GetIconName() const
1525 {
1526  return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
1527 }
1528 
1529 ////////////////////////////////////////////////////////////////////////////////
1530 /// Returns title (title can contain 32x32 xpm thumbnail/icon).
1531 
1532 const char *TKey::GetTitle() const
1533 {
1534  if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail
1535  static TString ret;
1536  int start = fTitle.Index("/*") + 3;
1537  int stop = fTitle.Index("*/") - 1;
1538  ret = fTitle(start, stop - start);
1539  return ret.Data();
1540  }
1541  return fTitle.Data();
1542 }
TClass::Browse
virtual void Browse(TBrowser *b)
This method is called by a browser to get the class information.
Definition: TClass.cxx:1959
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:91
TDirectory::GetList
virtual TList * GetList() const
Definition: TDirectory.h:167
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
TFree.h
Version_t
short Version_t
Definition: RtypesCore.h:65
TClass::Streamer
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:554
TDatime::Get
UInt_t Get() const
Return raw date/time as encoded by TDatime.
Definition: TDatime.cxx:240
TKey::ls
virtual void ls(Bool_t current) const
List Key contents.
Definition: TKey.cxx:694
TDirectory::GetListOfKeys
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:168
f
#define f(i)
Definition: RSha256.hxx:104
Option_t
const char Option_t
Definition: RtypesCore.h:66
TMath::Max
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
TBuffer::kRead
@ kRead
Definition: TBuffer.h:73
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:2565
UShort_t
unsigned short UShort_t
Definition: RtypesCore.h:40
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:369
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:1015
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:278
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
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:55
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:864
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:890
TBuffer::MapObject
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
gFile
#define gFile
Definition: TFile.h:343
TClass::HasDefaultConstructor
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition: TClass.cxx:7130
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:918
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:45
TBrowser.h
TNamed::fName
TString fName
Definition: TNamed.h:32
TBuffer::Buffer
char * Buffer() const
Definition: TBuffer.h:96
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
TKey::WriteFile
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1450
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:43
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:136
TKey::ReadFile
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition: TKey.cxx:1265
TClass::GetSchemaRules
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1881
TBuffer::SetBufferOffset
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:93
TObject::InheritsFrom
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:445
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:289
ROOT::DirAutoAdd_t
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition: Rtypes.h:113
TNamed::fTitle
TString fTitle
Definition: TNamed.h:33
TKey::Print
virtual void Print(Option_t *option="") const
Print key contents.
Definition: TKey.cxx:714
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:1336
TFile::kReproducible
@ kReproducible
Definition: TFile.h:189
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:124
TBuffer::Length
Int_t Length() const
Definition: TBuffer.h:100
TFile::GetCompressionAlgorithm
Int_t GetCompressionAlgorithm() const
Definition: TFile.h:387
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:717
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:4772
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:1210
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:4876
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
TKey::GetFile
TFile * GetFile() const
Returns file to which key belong.
Definition: TKey.cxx:585
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:92
TDirectory::AppendKey
virtual Int_t AppendKey(TKey *)
Definition: TDirectory.h:130
TKey::Delete
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:538
gDirectory
#define gDirectory
Definition: TDirectory.h:236
TDirectoryFile.h
gDebug
Int_t gDebug
Definition: TROOT.cxx:590
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:46
TString::BeginsWith
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
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:2925
TObject::MakeZombie
void MakeZombie()
Definition: TObject.h:49
Short_t
short Short_t
Definition: RtypesCore.h:39
TDirectoryFile::GetSeekDir
Long64_t GetSeekDir() const override
Definition: TDirectoryFile.h:97
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:1397
TObject::Warning
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:876
TClass::IsTObject
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5752
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
TROOT::IndentLevel
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2806
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:884
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:1294
TKey::GetIconName
virtual const char * GetIconName() const
Title can keep 32x32 xpm thumbnail/icon of the parent object.
Definition: TKey.cxx:1524
TString::Index
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
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:750
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:229
ULong64_t
unsigned long long ULong64_t
Definition: RtypesCore.h:74
TKey::fDatime
TDatime fDatime
Date/Time of insertion in file.
Definition: TKey.h:42
TDirectory::GetSeekDir
virtual Long64_t GetSeekDir() const
Definition: TDirectory.h:173
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:407
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:4813
TKey::WriteFileKeepBuffer
virtual Int_t WriteFileKeepBuffer(TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1491
TKey::Reset
void Reset()
Reset the key as it had not been 'filled' yet.
Definition: TKey.cxx:1302
R__ASSERT
#define R__ASSERT(e)
Definition: TError.h:120
TClass::GetDirectoryAutoAdd
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition: TClass.cxx:7224
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:278
UChar_t
unsigned char UChar_t
Definition: RtypesCore.h:38
TClass::Destructor
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5233
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:393
TClass::GetBaseClassOffset
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2748
TDirectory::GetFile
virtual TFile * GetFile() const
Definition: TDirectory.h:165
TKey::fObjlen
Int_t fObjlen
Length of uncompressed object in bytes.
Definition: TKey.h:41
name
char name[80]
Definition: TGX11.cxx:110
TObject::Delete
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:171
TSchemaRuleSet.h
TDirectory
Describe directory structure in memory.
Definition: TDirectory.h:40
TClass::GetState
EState GetState() const
Definition: TClass.h:444
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:223
TKey::GetTitle
virtual const char * GetTitle() const
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition: TKey.cxx:1532
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
TFile::kStartBigFile
@ kStartBigFile
Definition: TFile.h:192
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:32
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:130
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:475
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:47
TKey::kIsDirectoryFile
@ kIsDirectoryFile
Definition: TKey.h:32
ThreadLocalStorage.h
TKey::ReadKeyBuffer
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1222
TDirectory::SetMother
virtual void SetMother(TObject *mother)
Definition: TDirectory.h:202
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:2760
TList
A doubly linked list.
Definition: TList.h:44
TBuffer::kWrite
@ kWrite
Definition: TBuffer.h:73
TObject::SetUniqueID
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:707
TClass::kDummyNew
@ kDummyNew
Definition: TClass.h:106
gROOT
#define gROOT
Definition: TROOT.h:406
int
TError.h