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