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