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