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_files
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/// Core of uncompressing the key payload. Returns number of bytes uncompressed.
399/// We expect that the compressedBuffer contains the entire key (key header + payload).
400/// The target buffer must have space for at least fObjLen bytes.
401/// Lastly, the object length must be larger than the key payload, i.e. we already know that
402/// we have a compressed payload.
404{
405 auto objbuf = reinterpret_cast<unsigned char *>(targetBuffer) + fKeylen;
406 auto bufcur = reinterpret_cast<const unsigned char *>(&compressedBuffer[fKeylen]);
407 Int_t nin, nout = 0, nbuf;
408 Int_t noutot = 0;
411 while (nbytesRemain >= ROOT::Internal::kZipHeaderSize) {
413 if ((hc != 0) || (nin > nbytesRemain) || (nbuf > objlenRemain))
414 return 0;
416 if (!nout)
417 return 0;
418 noutot += nout;
419 if (noutot >= fObjlen)
420 break;
421 bufcur += nin;
422 objbuf += nout;
423 nbytesRemain -= nin;
425 }
426 return nout;
427}
428
429////////////////////////////////////////////////////////////////////////////////
430/// Method used in all TKey constructor to initialize basic data fields.
431///
432/// The member filepos is used to calculate correct version number of key
433/// if filepos==-1, end of file position is used.
434
435void TKey::Build(TDirectory* motherDir, const char* classname, Long64_t filepos)
436{
438
439 fPidOffset = 0;
440 fNbytes = 0;
441 fBuffer = 0;
442 fKeylen = 0;
443 fObjlen = 0;
444 fBufferRef = 0;
445 fCycle = 0;
446 fSeekPdir = 0;
447 fSeekKey = 0;
448 fLeft = 0;
449
450 fClassName = classname;
451 //the following test required for forward and backward compatibility
452 if (fClassName == "TDirectoryFile") SetBit(kIsDirectoryFile);
453
455
456 if ((filepos==-1) && GetFile()) filepos = GetFile()->GetEND();
458
460
463}
464
465////////////////////////////////////////////////////////////////////////////////
466/// Read object from disk and call its Browse() method.
467///
468/// If object with same name already exist in memory delete it (like
469/// TDirectoryFile::Get() is doing), except when the key references a
470/// folder in which case we don't want to re-read the folder object
471/// since it might contain new objects not yet saved.
472
474{
475 if (fMotherDir==0) return;
476
478
479 void* obj = fMotherDir->GetList()->FindObject(GetName());
480 if (obj && objcl->IsTObject()) {
481 TObject *tobj = (TObject*) objcl->DynamicCast(TObject::Class(), obj);
482 if (!tobj->IsFolder()) {
483 if (tobj->InheritsFrom(TCollection::Class()))
484 tobj->Delete(); // delete also collection elements
485 delete tobj;
486 obj = 0;
487 }
488 }
489
490 if (!obj)
491 obj = ReadObj();
492
493 if (b && obj) {
494 objcl->Browse(obj,b);
495 b->SetRefreshFlag(kTRUE);
496 }
497}
498
499////////////////////////////////////////////////////////////////////////////////
500/// Create a TKey object of specified size.
501///
502/// If externFile!=0, key will be allocated in specified file, otherwise file
503/// of mother directory will be used.
504
506{
508
509 TFile *f = externFile;
510 if (!f) f = GetFile();
511 if (!f) {
512 Error("Create","Cannot create key without file");
513 return;
514 }
515
517 TList *lfree = f->GetListOfFree();
518 TFree *f1 = (TFree*)lfree->First();
519//*-*-------------------find free segment
520//*-* =================
521 TFree *bestfree = f1->GetBestFree(lfree,nsize);
522 if (bestfree == 0) {
523 Error("Create","Cannot allocate %d bytes for ID = %s Title = %s",
525 return;
526 }
527
528 if (f->TestBit(TFile::kReproducible))
530
531 fDatime.Set();
532 fSeekKey = bestfree->GetFirst();
533//*-*----------------- Case Add at the end of the file
534 if (fSeekKey >= f->GetEND()) {
535 f->SetEND(fSeekKey+nsize);
536 bestfree->SetFirst(fSeekKey+nsize);
537 if (f->GetEND() > bestfree->GetLast()) {
538 bestfree->SetLast(bestfree->GetLast() + 1000000000);
539 }
540 fLeft = -1;
541 if (!fBuffer) fBuffer = new char[nsize];
542 } else {
543 fLeft = Int_t(bestfree->GetLast() - fSeekKey - nsize + 1);
544 }
545//*-*----------------- Case where new object fills exactly a deleted gap
546 fNbytes = nsize;
547 if (fLeft == 0) {
548 if (!fBuffer) {
549 fBuffer = new char[nsize];
550 }
551 lfree->Remove(bestfree);
552 delete bestfree;
553 }
554//*-*----------------- Case where new object is placed in a deleted gap larger than itself
555 if (fLeft > 0) { // found a bigger segment
556 if (!fBuffer) {
557 fBuffer = new char[nsize+sizeof(Int_t)];
558 }
559 char *buffer = fBuffer+nsize;
560 Int_t nbytesleft = -fLeft; // set header of remaining record
561 tobuf(buffer, nbytesleft);
562 bestfree->SetFirst(fSeekKey+nsize);
563 }
564
565 fSeekPdir = externFile ? externFile->GetSeekDir() : fMotherDir->GetSeekDir();
566}
567
568////////////////////////////////////////////////////////////////////////////////
569/// TKey default destructor.
570
572{
574 fMotherDir->GetListOfKeys()->Remove(this);
576}
577
578////////////////////////////////////////////////////////////////////////////////
579/// Delete an object from the file.
580///
581/// Note: the key is not deleted. You still have to call "delete key".
582/// This is different from the behaviour of TObject::Delete()!
583
585{
587 // TDirectoryFile assumes that its location on file never change (for example updates are partial)
588 // and never checks if the space might have been released and thus over-write any data that might
589 // have been written there.
590 if (option && option[0] == 'v')
591 printf("Rejected attempt to delete TDirectoryFile key: %s at address %lld, nbytes = %d\n",
593 return;
594 }
595 if (option && option[0] == 'v') printf("Deleting key: %s at address %lld, nbytes = %d\n",GetName(),fSeekKey,fNbytes);
596 Long64_t first = fSeekKey;
597 Long64_t last = fSeekKey + fNbytes -1;
598 if (GetFile()) GetFile()->MakeFree(first, last); // release space used by this key
599 fMotherDir->GetListOfKeys()->Remove(this);
600}
601
602////////////////////////////////////////////////////////////////////////////////
603/// Delete key buffer(s).
604
606{
607 if (fBufferRef) {
608 delete fBufferRef;
609 fBufferRef = 0;
610 } else {
611 // We only need to delete fBuffer if fBufferRef is zero because
612 // if fBufferRef exists, we delegate ownership of fBuffer to fBufferRef.
613 if (fBuffer) {
614 delete [] fBuffer;
615 }
616 }
617 fBuffer = 0;
618}
619
620////////////////////////////////////////////////////////////////////////////////
621/// Return cycle number associated to this key.
622
624{
625 return ((fCycle >0) ? fCycle : -fCycle);
626}
627
628////////////////////////////////////////////////////////////////////////////////
629/// Returns file to which key belong.
630
632{
633 return fMotherDir!=0 ? fMotherDir->GetFile() : gFile;
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// Returns the "KEEP" status.
638
640{
641 return ((fCycle >0) ? 0 : 1);
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Encode key header into output buffer.
646
647void TKey::FillBuffer(char *&buffer)
648{
649 tobuf(buffer, fNbytes);
651 tobuf(buffer, version);
652
653 tobuf(buffer, fObjlen);
655 TDatime((UInt_t) 1).FillBuffer(buffer);
656 else
657 fDatime.FillBuffer(buffer);
658 tobuf(buffer, fKeylen);
659 tobuf(buffer, fCycle);
660 if (fVersion > 1000) {
661 tobuf(buffer, fSeekKey);
662
663 // We currently store in the 16 highest bit of fSeekPdir the value of
664 // fPidOffset. This offset is used when a key (or basket) is transferred from one
665 // file to the other. In this case the TRef and TObject might have stored a
666 // pid index (to retrieve TProcessIDs) which refered to their order on the original
667 // file, the fPidOffset is to be added to those values to correctly find the
668 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
669 // and need to be zero for new key/basket.
671 tobuf(buffer, pdir);
672 } else {
673 tobuf(buffer, (Int_t)fSeekKey);
674 tobuf(buffer, (Int_t)fSeekPdir);
675 }
677 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
678 gTDirectoryString.FillBuffer(buffer);
679 } else {
680 fClassName.FillBuffer(buffer);
681 }
682 fName.FillBuffer(buffer);
683 fTitle.FillBuffer(buffer);
684}
685
686////////////////////////////////////////////////////////////////////////////////
687/// Increment fPidOffset by 'offset'.
688///
689/// This offset is used when a key (or basket) is transferred from one file to
690/// the other. In this case the TRef and TObject might have stored a pid
691/// index (to retrieve TProcessIDs) which refered to their order on the
692/// original file, the fPidOffset is to be added to those values to correctly
693/// find the TProcessID. This fPidOffset needs to be increment if the
694/// key/basket is copied and need to be zero for new key/basket.
695
697{
699 if (fPidOffset) {
700 // We currently store fPidOffset in the 16 highest bit of fSeekPdir, which
701 // need to be store as a 64 bit integer. So we require this key to be
702 // a 'large file' key.
703 if (fVersion<1000) fVersion += 1000;
704 }
705}
706
707////////////////////////////////////////////////////////////////////////////////
708/// Check if object referenced by the key is a folder.
709
711{
712 Bool_t ret = kFALSE;
713
714 TClass *classPtr = TClass::GetClass((const char *) fClassName);
715 if (classPtr && classPtr->GetState() > TClass::kEmulated && classPtr->IsTObject()) {
716 TObject *obj = (TObject *) classPtr->DynamicCast(TObject::Class(), classPtr->New(TClass::kDummyNew));
717 if (obj) {
718 ret = obj->IsFolder();
719 delete obj;
720 }
721 }
722
723 return ret;
724}
725
726////////////////////////////////////////////////////////////////////////////////
727/// Set the "KEEP" status.
728///
729/// When the KEEP flag is set to 1 the object cannot be purged.
730
732{
733 if (fCycle >0) fCycle = -fCycle;
734}
735
736////////////////////////////////////////////////////////////////////////////////
737/// List Key contents.
738/// Add indicator of whether it is the current item or a backup copy.
739
740void TKey::ls(Bool_t current) const
741{
743 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle();
744 std::cout << (current ? " [current cycle]" : " [backup cycle]");
745 std::cout <<std::endl;
746}
747
748////////////////////////////////////////////////////////////////////////////////
749/// List Key contents.
750
751void TKey::ls(Option_t *) const
752{
754 std::cout <<"KEY: "<<fClassName<<"\t"<<GetName()<<";"<<GetCycle()<<"\t"<<GetTitle()<<std::endl;
755}
756
757////////////////////////////////////////////////////////////////////////////////
758/// Print key contents.
759
761{
762 printf("TKey Name = %s, Title = %s, Cycle = %d\n",GetName(),GetTitle(),GetCycle());
763}
764
765////////////////////////////////////////////////////////////////////////////////
766/// To read a TObject* from the file.
767///
768/// The object associated to this key is read from the file into memory
769/// Once the key structure is read (via Streamer) the class identifier
770/// of the object is known.
771/// Using the class identifier we find the TClass object for this class.
772/// A TClass object contains a full description (i.e. dictionary) of the
773/// associated class. In particular the TClass object can create a new
774/// object of the class type it describes. This new object now calls its
775/// Streamer function to rebuilt itself.
776///
777/// Use TKey::ReadObjectAny to read any object non-derived from TObject
778///
779/// ### Note
780/// A C style cast can only be used in the case where the final class
781/// of this object derives from TObject as a first inheritance, otherwise
782/// one must use a dynamic_cast.
783///
784/// #### Example1: simplified case
785/// ~~~{.cpp}
786/// class MyClass : public TObject, public AnotherClass
787/// ~~~
788/// then on return, one get away with using:
789/// ~~~{.cpp}
790/// MyClass *obj = (MyClass*)key->ReadObj();
791/// ~~~
792///
793/// #### Example2: Usual case (recommended unless performance is critical)
794/// ~~~{.cpp}
795/// MyClass *obj = dynamic_cast<MyClass*>(key->ReadObj());
796/// ~~~
797/// which support also the more complex inheritance like:
798/// ~~~{.cpp}
799/// class MyClass : public AnotherClass, public TObject
800/// ~~~
801///
802/// Of course, `dynamic_cast<>` can also be used in the example 1.
803
805{
807 if (!cl) {
808 Error("ReadObj", "Unknown class %s", fClassName.Data());
809 return 0;
810 }
811 if (!cl->IsTObject()) {
812 // in principle user should call TKey::ReadObjectAny!
813 return (TObject*)ReadObjectAny(0);
814 }
815
817 if (!bufferRef.Buffer()) {
818 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
819 return 0;
820 }
821 if (GetFile()==0) return 0;
822 bufferRef.SetParent(GetFile());
823 bufferRef.SetPidOffset(fPidOffset);
824
825 std::unique_ptr<char []> compressedBuffer;
826 auto storeBuffer = fBuffer;
827 if (fObjlen > fNbytes-fKeylen) {
828 compressedBuffer.reset(new char[fNbytes]);
830 if( !ReadFile() ) //Read object structure from file
831 {
832 fBuffer = 0;
833 return 0;
834 }
836 } else {
837 fBuffer = bufferRef.Buffer();
838 if( !ReadFile() ) { //Read object structure from file
839
840 fBuffer = 0;
841 return 0;
842 }
843 }
845
846 // get version of key
847 bufferRef.SetBufferOffset(sizeof(fNbytes));
848 Version_t kvers = bufferRef.ReadVersion();
849
850 bufferRef.SetBufferOffset(fKeylen);
851 TObject *tobj = 0;
852 // Create an instance of this class
853
854 char *pobj = (char*)cl->New();
855 if (!pobj) {
856 Error("ReadObj", "Cannot create new object of class %s", fClassName.Data());
857 return 0;
858 }
860 if (baseOffset==-1) {
861 // cl does not inherit from TObject.
862 // Since this is not possible yet, the only reason we could reach this code
863 // is because something is screw up in the ROOT code.
864 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
865 fClassName.Data());
866 }
868 if (kvers > 1)
869 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
870
871 if (fObjlen > fNbytes-fKeylen) {
873 compressedBuffer.reset(nullptr);
874 if (nout) {
875 tobj->Streamer(bufferRef); //does not work with example 2 above
876 } else {
877 // Even-though we have a TObject, if the class is emulated the virtual
878 // table may not be 'right', so let's go via the TClass.
879 cl->Destructor(pobj);
880 return nullptr;
881 }
882 } else {
883 tobj->Streamer(bufferRef);
884 }
885
886 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
887
889 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
890 dir->SetName(GetName());
891 dir->SetTitle(GetTitle());
892 dir->SetMother(fMotherDir);
893 fMotherDir->Append(dir);
894 }
895
896 // Append the object to the directory if requested:
897 {
899 if (addfunc) {
900 addfunc(pobj, fMotherDir);
901 }
902 }
903
904 return tobj;
905}
906
907////////////////////////////////////////////////////////////////////////////////
908/// To read a TObject* from bufferRead.
909///
910/// This function is identical to TKey::ReadObj, but it reads directly from
911/// bufferRead instead of reading from a file.
912/// The object associated to this key is read from the buffer into memory
913/// Using the class identifier we find the TClass object for this class.
914/// A TClass object contains a full description (i.e. dictionary) of the
915/// associated class. In particular the TClass object can create a new
916/// object of the class type it describes. This new object now calls its
917/// Streamer function to rebuilt itself.
918///
919/// ### Note
920/// This function is called only internally by ROOT classes.
921/// Although being public it is not supposed to be used outside ROOT.
922/// If used, you must make sure that the bufferRead is large enough to
923/// accommodate the object being read.
924
926{
927
929 if (!cl) {
930 Error("ReadObjWithBuffer", "Unknown class %s", fClassName.Data());
931 return 0;
932 }
933 if (!cl->IsTObject()) {
934 // in principle user should call TKey::ReadObjectAny!
935 return (TObject*)ReadObjectAny(0);
936 }
937
939 if (!bufferRef.Buffer()) {
940 Error("ReadObjWithBuffer", "Cannot allocate buffer: fObjlen = %d", fObjlen);
941 return 0;
942 }
943 if (GetFile()==0) return 0;
944 bufferRef.SetParent(GetFile());
945 bufferRef.SetPidOffset(fPidOffset);
946
947 auto storeBuffer = fBuffer;
948 if (fObjlen > fNbytes-fKeylen) {
951 } else {
952 fBuffer = bufferRef.Buffer();
953 ReadFile(); //Read object structure from file
954 }
956
957 // get version of key
958 bufferRef.SetBufferOffset(sizeof(fNbytes));
959 Version_t kvers = bufferRef.ReadVersion();
960
961 bufferRef.SetBufferOffset(fKeylen);
962 TObject *tobj = 0;
963 // Create an instance of this class
964
965 char *pobj = (char*)cl->New();
966 if (!pobj) {
967 Error("ReadObjWithBuffer", "Cannot create new object of class %s", fClassName.Data());
968 return 0;
969 }
971 if (baseOffset==-1) {
972 // cl does not inherit from TObject.
973 // Since this is not possible yet, the only reason we could reach this code
974 // is because something is screw up in the ROOT code.
975 Fatal("ReadObjWithBuffer","Incorrect detection of the inheritance from TObject for class %s.\n",
976 fClassName.Data());
977 }
979
980 if (kvers > 1)
981 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
982
983 if (fObjlen > fNbytes-fKeylen) {
985 if (nout) {
986 tobj->Streamer(bufferRef); //does not work with example 2 above
987 } else {
988 // Even-though we have a TObject, if the class is emulated the virtual
989 // table may not be 'right', so let's go via the TClass.
990 cl->Destructor(pobj);
991 return nullptr;
992 }
993 } else {
994 tobj->Streamer(bufferRef);
995 }
996
997 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
998
1000 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1001 dir->SetName(GetName());
1002 dir->SetTitle(GetTitle());
1003 dir->SetMother(fMotherDir);
1004 fMotherDir->Append(dir);
1005 }
1006
1007 // Append the object to the directory if requested:
1008 {
1010 if (addfunc) {
1011 addfunc(pobj, fMotherDir);
1012 }
1013 }
1014
1015 return tobj;
1016}
1017
1018////////////////////////////////////////////////////////////////////////////////
1019/// To read an object (non deriving from TObject) from the file.
1020///
1021/// If expectedClass is not null, we checked that that actual class of the
1022/// object stored is suitable to be stored in a pointer pointing to an object
1023/// of class 'expectedClass'. We also adjust the value of the returned address
1024/// so that it is suitable to be cast (C-Style)
1025/// a pointer pointing to an object of class 'expectedClass'.
1026///
1027/// So for example if the class Bottom inherits from Top and the object
1028/// stored is of type Bottom you can safely do:
1029/// ~~~{.cpp}
1030/// auto TopClass = TClass::GetClass("Top");
1031/// auto ptr = (Top*) key->ReadObjectAny( TopClass );
1032/// if (ptr==0) printError("the object stored in the key is not of the expected type\n");
1033/// ~~~
1034/// The object associated to this key is read from the file into memory.
1035/// Once the key structure is read (via Streamer) the class identifier
1036/// of the object is known.
1037/// Using the class identifier we find the TClass object for this class.
1038/// A TClass object contains a full description (i.e. dictionary) of the
1039/// associated class. In particular the TClass object can create a new
1040/// object of the class type it describes. This new object now calls its
1041/// Streamer function to rebuilt itself.
1042
1044{
1046 if (!bufferRef.Buffer()) {
1047 Error("ReadObj", "Cannot allocate buffer: fObjlen = %d", fObjlen);
1048 return 0;
1049 }
1050 if (GetFile()==0) return 0;
1051 bufferRef.SetParent(GetFile());
1052 bufferRef.SetPidOffset(fPidOffset);
1053
1054 std::unique_ptr<char []> compressedBuffer;
1055 auto storeBuffer = fBuffer;
1056 if (fObjlen > fNbytes-fKeylen) {
1057 compressedBuffer.reset(new char[fNbytes]);
1058 fBuffer = compressedBuffer.get();
1059 ReadFile(); //Read object structure from file
1060 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1061 } else {
1062 fBuffer = bufferRef.Buffer();
1063 ReadFile(); //Read object structure from file
1064 }
1066
1067 // get version of key
1068 bufferRef.SetBufferOffset(sizeof(fNbytes));
1069 Version_t kvers = bufferRef.ReadVersion();
1070
1071 bufferRef.SetBufferOffset(fKeylen);
1073 TClass *clOnfile = 0;
1074 if (!cl) {
1075 Error("ReadObjectAny", "Unknown class %s", fClassName.Data());
1076 return 0;
1077 }
1078 Int_t baseOffset = 0;
1079 if (expectedClass) {
1080 // baseOffset will be -1 if cl does not inherit from expectedClass
1082 if (baseOffset == -1) {
1083 // The 2 classes are unrelated, maybe there is a converter between the 2.
1084
1085 if (!expectedClass->GetSchemaRules() ||
1086 !expectedClass->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()))
1087 {
1088 // There is no converter
1089 return 0;
1090 }
1091 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 ....
1092 clOnfile = cl;
1093 cl = const_cast<TClass*>(expectedClass);
1094 if (gDebug > 0)
1095 Info("ReadObjectAny", "Using Converter StreamerInfo from %s to %s", clOnfile->GetName(),
1096 expectedClass->GetName());
1097 }
1098 if (cl->GetState() > TClass::kEmulated && expectedClass->GetState() <= TClass::kEmulated) {
1099 //we cannot mix a compiled class with an emulated class in the inheritance
1100 Warning("ReadObjectAny",
1101 "Trying to read an emulated class (%s) to store in a compiled pointer (%s)",
1102 cl->GetName(),expectedClass->GetName());
1103 }
1104 }
1105 // Create an instance of this class
1106
1107 void *pobj = cl->New();
1108 if (!pobj) {
1109 Error("ReadObjectAny", "Cannot create new object of class %s", fClassName.Data());
1110 return 0;
1111 }
1112
1113 if (kvers > 1)
1114 bufferRef.MapObject(pobj,cl); //register obj in map to handle self reference
1115
1116 if (fObjlen > fNbytes-fKeylen) {
1117 Int_t nout = UnzipBuffer(bufferRef.Buffer(), compressedBuffer.get());
1118 if (nout) {
1119 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1120 } else {
1121 cl->Destructor(pobj);
1122 return nullptr;
1123 }
1124 } else {
1125 cl->Streamer((void*)pobj, bufferRef, clOnfile); //read object
1126 }
1127
1128 if (cl->IsTObject()) {
1130 if (tobjBaseOffset == -1) {
1131 Fatal("ReadObj","Incorrect detection of the inheritance from TObject for class %s.\n",
1132 fClassName.Data());
1133 }
1134 TObject *tobj = (TObject*)( ((char*)pobj) + tobjBaseOffset);
1135
1136 // See similar adjustments in ReadObj
1137 if (gROOT->GetForceStyle()) tobj->UseCurrentStyle();
1138
1140 TDirectory *dir = static_cast<TDirectoryFile*>(tobj);
1141 dir->SetName(GetName());
1142 dir->SetTitle(GetTitle());
1143 dir->SetMother(fMotherDir);
1144 fMotherDir->Append(dir);
1145 }
1146 }
1147
1148 {
1149 // Append the object to the directory if requested:
1151 if (addfunc) {
1152 addfunc(pobj, fMotherDir);
1153 }
1154 }
1155
1156 return ( ((char*)pobj) + baseOffset );
1157}
1158
1159////////////////////////////////////////////////////////////////////////////////
1160/// To read an object from the file.
1161///
1162/// The object associated to this key is read from the file into memory.
1163/// Before invoking this function, obj has been created via the
1164/// default constructor.
1165
1167{
1168 if (!obj || (GetFile()==0)) return 0;
1169
1171 bufferRef.SetParent(GetFile());
1172 bufferRef.SetPidOffset(fPidOffset);
1173
1174 if (fVersion > 1)
1175 bufferRef.MapObject(obj); //register obj in map to handle self reference
1176
1177 std::unique_ptr<char []> compressedBuffer;
1178 auto storeBuffer = fBuffer;
1179 if (fObjlen > fNbytes-fKeylen) {
1180 compressedBuffer.reset(new char[fNbytes]);
1181 fBuffer = compressedBuffer.get();
1182 ReadFile(); //Read object structure from file
1183 memcpy(bufferRef.Buffer(),fBuffer,fKeylen);
1184 } else {
1185 fBuffer = bufferRef.Buffer();
1186 ReadFile(); //Read object structure from file
1187 }
1189
1190 bufferRef.SetBufferOffset(fKeylen);
1191 if (fObjlen > fNbytes-fKeylen) {
1192 Int_t nout = UnzipBuffer(bufferRef.Buffer(), compressedBuffer.get());
1193 if (nout)
1194 obj->Streamer(bufferRef);
1195 } else {
1196 obj->Streamer(bufferRef);
1197 }
1198
1199 // Append the object to the directory if requested:
1200 {
1201 ROOT::DirAutoAdd_t addfunc = obj->IsA()->GetDirectoryAutoAdd();
1202 if (addfunc) {
1203 addfunc(obj, fMotherDir);
1204 }
1205 }
1206
1207 return fNbytes;
1208}
1209
1210////////////////////////////////////////////////////////////////////////////////
1211/// Decode input buffer.
1212///
1213/// In some situation will add key to gDirectory.
1214
1215void TKey::ReadBuffer(char *&buffer)
1216{
1217 ReadKeyBuffer(buffer);
1218
1219 if (!gROOT->ReadingObject() && gDirectory) {
1220 if (fSeekPdir != gDirectory->GetSeekDir()) gDirectory->AppendKey(this);
1221 }
1222}
1223
1224////////////////////////////////////////////////////////////////////////////////
1225/// Decode input buffer.
1226
1227void TKey::ReadKeyBuffer(char *&buffer)
1228{
1229 frombuf(buffer, &fNbytes);
1230 if (fNbytes < 0) {
1231 Error("ReadKeyBuffer", "The value of fNbytes is negative (%d): cannot continue to read the key buffer.", fNbytes);
1232 MakeZombie();
1233 fNbytes = 0;
1234 return;
1235 }
1237 frombuf(buffer,&version);
1239 frombuf(buffer, &fObjlen);
1240 if (fObjlen < 0) {
1241 Error("ReadKeyBuffer", "The value of fObjlen is negative (%d): cannot continue to read the key buffer.", fObjlen);
1242 MakeZombie();
1243 fObjlen = 0;
1244 return;
1245 }
1246 fDatime.ReadBuffer(buffer);
1247 frombuf(buffer, &fKeylen);
1248 if (fKeylen < 0) {
1249 Error("ReadKeyBuffer", "The value of fKeylen is negative (%d): cannot continue to read the key buffer.", fKeylen);
1250 MakeZombie();
1251 fKeylen = 0;
1252 return;
1253 }
1254
1255 if (fNbytes < fKeylen) {
1256 Error("ReadKeyBuffer", "fNbytes (%d) < fKeylen (%d): cannot continue to read the key buffer.", fNbytes, fKeylen);
1257 MakeZombie();
1258 return;
1259 }
1260
1261 if(CheckKeyObjLenOverflow("ReadKeyBuffer", fKeylen, fObjlen)){
1262 fKeylen = 0;
1263 fObjlen = 0;
1264 MakeZombie();
1265 return;
1266 }
1267
1268 frombuf(buffer, &fCycle);
1269 if (fVersion > 1000) {
1270 frombuf(buffer, &fSeekKey);
1271
1272 // We currently store in the 16 highest bit of fSeekPdir the value of
1273 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1274 // file to the other. In this case the TRef and TObject might have stored a
1275 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1276 // file, the fPidOffset is to be added to those values to correctly find the
1277 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1278 // and need to be zero for new key/basket.
1279 Long64_t pdir;
1280 frombuf(buffer, &pdir);
1283 } else {
1285 frombuf(buffer, &seekkey); fSeekKey = (Long64_t)seekkey;
1287 }
1288 fClassName.ReadBuffer(buffer);
1289 //the following test required for forward and backward compatibility
1290 if (fClassName == "TDirectory") {
1291 fClassName = "TDirectoryFile";
1293 }
1294
1295 fName.ReadBuffer(buffer);
1296 fTitle.ReadBuffer(buffer);
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Read the key structure from the file
1301
1303{
1304 TFile* f = GetFile();
1305 if (f==0) return kFALSE;
1306
1308 f->Seek(fSeekKey);
1309 if( f->ReadBuffer(fBuffer,nsize) )
1310 {
1311 Error("ReadFile", "Failed to read data.");
1312 return kFALSE;
1313 }
1314 if (gDebug) {
1315 std::cout << "TKey Reading "<<nsize<< " bytes at address "<<fSeekKey<<std::endl;
1316 }
1317 return kTRUE;
1318}
1319
1320////////////////////////////////////////////////////////////////////////////////
1321/// Set parent in key buffer.
1322
1323void TKey::SetParent(const TObject *parent)
1324{
1325 if (fBufferRef) fBufferRef->SetParent((TObject*)parent);
1326}
1327
1328////////////////////////////////////////////////////////////////////////////////
1329/// Reset the key as it had not been 'filled' yet.
1330
1332{
1333 fPidOffset = 0;
1334 fNbytes = 0;
1335 fBuffer = 0;
1336 fObjlen = 0;
1337 fCycle = 0;
1338 fSeekPdir = 0;
1339 fSeekKey = 0;
1340 fLeft = 0;
1341 fDatime = (UInt_t)0;
1342
1343 // fBufferRef and fKeylen intentionally not reset/changed
1344
1346}
1347
1348////////////////////////////////////////////////////////////////////////////////
1349/// Return the size in bytes of the key header structure.
1350///
1351/// An explanation about the nbytes (Int_t nbytes) variable used in the
1352/// function. The size of fSeekKey and fSeekPdir is 8 instead of 4 if version is
1353/// greater than 1000.
1354/// | Component | Sizeof |
1355/// |-------------------|------------|
1356/// | fNbytes | 4 |
1357/// | sizeof(Version_t) | 2 |
1358/// | fObjlen | 4 |
1359/// | fDatime | 4 |
1360/// | fKeylen | 2 |
1361/// | fCycle | 2 |
1362/// | fSeekKey | 4 or 8 |
1363/// | fSeekPdir | 4 or 8 |
1364/// | **FIXED TOTAL** | 26 or 34 |
1365/// | fClassName | 1+ bytes |
1366/// | fName | 1+ bytes |
1367/// | fTitle | 1+ bytes |
1368/// | **TOTAL** | 29+ or 37+ |
1369
1371{
1372 Int_t nbytes = 22; if (fVersion > 1000) nbytes += 8;
1373 nbytes += fDatime.Sizeof();
1375 nbytes += 11; // strlen("TDirectory")+1
1376 } else {
1378 }
1379 nbytes += fName.Sizeof();
1380 nbytes += fTitle.Sizeof();
1381 return nbytes;
1382}
1383
1384////////////////////////////////////////////////////////////////////////////////
1385/// Stream a class object.
1386
1388{
1390 if (b.IsReading()) {
1391 b >> fNbytes;
1393 b >> fObjlen;
1395 b >> fKeylen;
1396 b >> fCycle;
1397 if (fVersion > 1000) {
1398 b >> fSeekKey;
1399
1400 // We currently store in the 16 highest bit of fSeekPdir the value of
1401 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1402 // file to the other. In this case the TRef and TObject might have stored a
1403 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1404 // file, the fPidOffset is to be added to those values to correctly find the
1405 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1406 // and need to be zero for new key/basket.
1407 Long64_t pdir;
1408 b >> pdir;
1411 } else {
1415 }
1417 //the following test required for forward and backward compatibility
1418 if (fClassName == "TDirectory") {
1419 fClassName = "TDirectoryFile";
1421 }
1422 fName.Streamer(b);
1423 fTitle.Streamer(b);
1424 if (fKeylen < 0) {
1425 Error("Streamer","The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero",fKeylen);
1426 MakeZombie();
1427 fKeylen = 0;
1428 }
1429 if (fObjlen < 0) {
1430 Error("Streamer","The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero",fObjlen);
1431 MakeZombie();
1432 fObjlen = 0;
1433 }
1434 if (fNbytes < 0) {
1435 Error("Streamer","The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero",fNbytes);
1436 MakeZombie();
1437 fNbytes = 0;
1438 }
1439 if (CheckKeyObjLenOverflow("Streamer", fKeylen, fObjlen)) {
1440 MakeZombie();
1441 return;
1442 }
1443
1444 } else {
1445 b << fNbytes;
1447 b << version;
1448 b << fObjlen;
1449 if (fDatime.Get() == 0) fDatime.Set();
1451 TDatime((UInt_t) 1).Streamer(b);
1452 else
1454 b << fKeylen;
1455 b << fCycle;
1456 if (fVersion > 1000) {
1457 b << fSeekKey;
1458
1459 // We currently store in the 16 highest bit of fSeekPdir the value of
1460 // fPidOffset. This offset is used when a key (or basket) is transferred from one
1461 // file to the other. In this case the TRef and TObject might have stored a
1462 // pid index (to retrieve TProcessIDs) which refered to their order on the original
1463 // file, the fPidOffset is to be added to those values to correctly find the
1464 // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1465 // and need to be zero for new key/basket.
1467 b << pdir;
1468 } else {
1469 b << (Int_t)fSeekKey;
1470 b << (Int_t)fSeekPdir;
1471 }
1473 // We want to record "TDirectory" instead of TDirectoryFile so that the file can be read by ancient version of ROOT.
1474 b.WriteTString(gTDirectoryString);
1475 } else {
1477 }
1478 fName.Streamer(b);
1479 fTitle.Streamer(b);
1480 }
1481}
1482
1483////////////////////////////////////////////////////////////////////////////////
1484/// Write the encoded object supported by this key.
1485/// The function returns the number of bytes committed to the file.
1486/// If a write error occurs, the number of bytes returned is -1.
1487
1489{
1490 if (!f) f = GetFile();
1491 if (!f) return -1;
1492
1494 char *buffer = fBuffer;
1495 if (cycle) {
1496 fCycle = cycle;
1497 FillBuffer(buffer);
1498 buffer = fBuffer;
1499 }
1500
1501 if (fLeft > 0) nsize += sizeof(Int_t);
1502 f->Seek(fSeekKey);
1503 Bool_t result = f->WriteBuffer(buffer,nsize);
1504 //f->Flush(); Flushing takes too much time.
1505 // Let user flush the file when they want.
1506 if (gDebug) {
1507 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1508 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1509 }
1510
1511 DeleteBuffer();
1512 return result==kTRUE ? -1 : nsize;
1513}
1514
1515////////////////////////////////////////////////////////////////////////////////
1516/// Write the encoded object supported by this key.
1517/// The function returns the number of bytes committed to the file.
1518/// If a write error occurs, the number of bytes returned is -1.
1519
1521{
1522 if (!f) f = GetFile();
1523 if (!f) return -1;
1524
1526 char *buffer = fBuffer;
1527
1528 if (fLeft > 0) nsize += sizeof(Int_t);
1529 f->Seek(fSeekKey);
1530 Bool_t result = f->WriteBuffer(buffer,nsize);
1531 //f->Flush(); Flushing takes too much time.
1532 // Let user flush the file when they want.
1533 if (gDebug) {
1534 std::cout <<" TKey Writing "<<nsize<< " bytes at address "<<fSeekKey
1535 <<" for ID= " <<GetName()<<" Title= "<<GetTitle()<<std::endl;
1536 }
1537
1538 return result==kTRUE ? -1 : nsize;
1539}
1540
1541////////////////////////////////////////////////////////////////////////////////
1542/// Title can keep 32x32 xpm thumbnail/icon of the parent object.
1543
1544const char *TKey::GetIconName() const
1545{
1546 return (!fTitle.IsNull() && fTitle.BeginsWith("/* ") ? fTitle.Data() : 0);
1547}
1548
1549////////////////////////////////////////////////////////////////////////////////
1550/// Returns title (title can contain 32x32 xpm thumbnail/icon).
1551
1552const char *TKey::GetTitle() const
1553{
1554 if (!fTitle.IsNull() && fTitle.BeginsWith("/* ")) { // title contains xpm thumbnail
1555 static TString ret;
1556 int start = fTitle.Index("/*") + 3;
1557 int stop = fTitle.Index("*/") - 1;
1558 ret = fTitle(start, stop - start);
1559 return ret.Data();
1560 }
1561 return fTitle.Data();
1562}
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:270
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:439
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:148
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:777
#define gROOT
Definition TROOT.h:417
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:626
EState GetState() const
Definition TClass.h:504
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5048
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5470
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7652
@ kDummyNew
Definition TClass.h:110
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6043
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4932
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2812
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7550
@ kEmulated
Definition TClass.h:128
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2614
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:2994
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:483
virtual Long64_t GetEND() const
Definition TFile.h:319
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1496
@ kStartBigFile
Definition TFile.h:278
Int_t GetCompressionAlgorithm() const
Definition TFile.h:477
@ kReproducible
Definition TFile.h:271
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:1552
static constexpr Version_t Class_Version()
Definition TKey.h:118
void Delete(Option_t *option="") override
Delete an object from the file.
Definition TKey.cxx:584
@ 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:1370
TKey()
TKey default constructor.
Definition TKey.cxx:99
~TKey() override
TKey default destructor.
Definition TKey.cxx:571
TFile * GetFile() const
Returns file to which key belong.
Definition TKey.cxx:631
virtual void Keep()
Set the "KEEP" status.
Definition TKey.cxx:731
const char * GetIconName() const override
Title can keep 32x32 xpm thumbnail/icon of the parent object.
Definition TKey.cxx:1544
Int_t Read(const char *name) override
Read contents of object with specified name from the current directory.
Definition TKey.h:56
Int_t UnzipBuffer(char *targetBuffer, const char *compressedBuffer) const
Core of uncompressing the key payload.
Definition TKey.cxx:403
TDatime fDatime
Date/Time of insertion in file.
Definition TKey.h:44
TBuffer * fBufferRef
Pointer to the TBuffer object.
Definition TKey.h:52
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:53
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by 'offset'.
Definition TKey.cxx:696
Short_t GetKeep() const
Returns the "KEEP" status.
Definition TKey.cxx:639
Int_t fVersion
Key version identifier.
Definition TKey.h:41
Bool_t IsFolder() const override
Check if object referenced by the key is a folder.
Definition TKey.cxx:710
Int_t fLeft
Number of bytes left in current segment.
Definition TKey.h:50
virtual const char * GetClassName() const
Definition TKey.h:77
Short_t fKeylen
Number of bytes for the key itself.
Definition TKey.h:45
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition TKey.cxx:1302
void Browse(TBrowser *b) override
Read object from disk and call its Browse() method.
Definition TKey.cxx:473
virtual Int_t WriteFileKeepBuffer(TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1520
Long64_t fSeekKey
Location of object on file.
Definition TKey.h:47
void Build(TDirectory *motherDir, const char *classname, Long64_t filepos)
Method used in all TKey constructor to initialize basic data fields.
Definition TKey.cxx:435
char * fBuffer
Object buffer.
Definition TKey.h:51
Long64_t fSeekPdir
Location of parent directory on file.
Definition TKey.h:48
virtual void SetParent(const TObject *parent)
Set parent in key buffer.
Definition TKey.cxx:1323
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition TKey.cxx:1043
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1227
Int_t fNbytes
Number of bytes for the whole key on file (key header and data)
Definition TKey.h:42
Int_t fObjlen
Length of uncompressed object in bytes.
Definition TKey.h:43
void Reset()
Reset the key as it had not been 'filled' yet.
Definition TKey.cxx:1331
Short_t fCycle
Cycle number.
Definition TKey.h:46
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition TKey.cxx:925
virtual void ls(Bool_t current) const
List Key contents.
Definition TKey.cxx:740
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:623
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:804
virtual void Create(Int_t nbytes, TFile *f=nullptr)
Create a TKey object of specified size.
Definition TKey.cxx:505
virtual void DeleteBuffer()
Delete key buffer(s).
Definition TKey.cxx:605
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1488
virtual void ReadBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1215
TDirectory * fMotherDir
!pointer to mother directory
Definition TKey.h:54
TString fClassName
Object Class name.
Definition TKey.h:49
void Print(Option_t *option="") const override
Print key contents.
Definition TKey.cxx:760
void FillBuffer(char *&buffer) override
Encode key header into output buffer.
Definition TKey.cxx:647
void Streamer(TBuffer &) override
Stream a class object.
Definition TKey.cxx:1387
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:42
virtual Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition TObject.cxx:579
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:997
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:227
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1084
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:888
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1126
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:899
virtual TClass * IsA() const
Definition TObject.h:248
void MakeZombie()
Definition TObject.h:55
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1072
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:3052
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