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