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