RE: Problem with the Streamer function of a class derived from TDirectory...

From: Philippe Canal <pcanal_at_fnal.gov>
Date: Wed, 19 Mar 2008 14:38:26 -0500


Hi Pierre-Luc,

The Streamer is not called when writing (it is done via FillBuffer instead).

> What I want to do is to index the objects contined in a TDirectory
> using a TObjArray in addition to the THashList.

Humm ... why? :) ... It might be easier to write an adapter class that is either created on the fly at read time and/or save in the TDirectory.

Cheers,
Philippe.

-----Original Message-----
From: Pierre-Luc Drouin [mailto:pldrouin_at_physics.carleton.ca] Sent: Wednesday, March 19, 2008 1:56 PM
To: Philippe Canal
Cc: 'Rene Brun'; roottalk_at_root.cern.ch
Subject: Re: [ROOT] Problem with the Streamer function of a class derived from TDirectory...

What I want to do is to index the objects contained in a TDirectory using a TObjArray in addition to the THashList.

I have tried to implement my own Streamer function in my simple class (QMyDir), but for some reason it does not seam to be called when I open a file, create an instance of my class and then save the file. How is the Streamer function of TDirectoryFile called exactly (for writing)? When I look at the constructor of TDirectoryFile and at TDirectoryFile::Write, it seams that it is always FillBuffer that is called...

Philippe Canal wrote:
> Hi Pierre-Luc,
>
> Actually (sorry for the confusion) TDirectory(File) is very special
> and overloading it require more updates that just the Streamer.
> In your case, think are likely to work if you write a custom streamer
> (i.e #pragma link C++ class QMyDir-; and implement the Streamer
> function by hand) which _only_ forward the call to
TDirectoryFile::Streamer
> (which should work somewhat since you do not have any member).
>
> Assumingly your intent is to add some member, in which case you would
> have to at least overload FillBuffer and ReadKeys to take in consideration
> the extra members.
>
> So, this begs the question :), what are you trying to achieve by
overloading
> TDirectoryFile and is there a simplier mean to achieve it?
>
> Cheers,
> Philippe.
>
> -----Original Message-----
> From: Pierre-Luc Drouin [mailto:pldrouin_at_physics.carleton.ca]
> Sent: Tuesday, March 18, 2008 10:50 AM
> To: Philippe Canal
> Cc: 'Rene Brun'; roottalk_at_root.cern.ch
> Subject: Re: [ROOT] Problem with the Streamer function of a class derived
> from TDirectory...
>
> I have modified my LinkDef file, recompiled everything, regenerated the
> root file and I got the same error:
>
> Error in <TBufferFile::ReadBuffer2>: class: TUUID, attempting to access
> a wrong version: 127, object skipped at offset 87
> Error in <TFile::ReadBuffer>: error reading all requested bytes from
> file file.root, got 0 of 2687036
> (class TObject*)0x8346328
>
> The autogenerated code for the Streamer function is the following:
>
> void QMyDir::Streamer(TBuffer &R__b)
> {
> // Stream an object of class QMyDir.
>
> if (R__b.IsReading()) {
> R__b.ReadClassBuffer(QMyDir::Class(),this);
> } else {
> R__b.WriteClassBuffer(QMyDir::Class(),this);
> }
> }
>
> Thank you
> Pierre-Luc Drouin
>
> Philippe Canal wrote:
>
>> Hi Pierre-Luc,
>>
>> Can you try after enabling the new I/O?
>> i.e:
>> #pragma link C++ class QMyDir+;
>>
>>
>> Cheers,
>> Philippe.
>>
>> -----Original Message-----
>> From: owner-roottalk_at_root.cern.ch [mailto:owner-roottalk_at_root.cern.ch] On
>> Behalf Of Pierre-Luc Drouin
>> Sent: Tuesday, March 18, 2008 10:27 AM
>> To: Rene Brun
>> Cc: roottalk_at_root.cern.ch
>> Subject: Re: [ROOT] Problem with the Streamer function of a class derived
>> from TDirectory...
>>
>> Hi,
>>
>> I have installed 5.18/00 (I was using 5.14/00e before) and I have
>> derived my class from TDirectoryFile. The code of my class is now the
>> following:
>>
>> #include "Rtypes.h"
>> #include "TObject.h"
>> #include "TDirectoryFile.h"
>>
>> class QMyDir: public TDirectoryFile
>> {
>> public:
>> QMyDir():TDirectoryFile(){}
>>
>> QMyDir(const QMyDir& newqds):TDirectoryFile(){}
>>
>> QMyDir(const char *name, const char *title, TDirectory* motherDir =
>> 0):TDirectoryFile(name,title,"QMyDir",motherDir){}
>>
>> virtual ~QMyDir(){}
>>
>> QMyDir& operator=(const QMyDir &rhs){fprintf(stderr,"Warning:
>> TDirectoryFile::operator= cannot be called from derived class
>> QMyDir\n"); return *this;}
>>
>> private:
>>
>> ClassDef(QMyDir,1) //QSigEx Data Structure Class
>> };
>>
>> I still get an error when I try to load the instance from the file. I
>> have stored and have tried to load the instance using the code I have
>> shown in my previous email. Here is the error I get:
>>
>> _file0->Get("dir")
>> Error in <TBufferFile::ReadBuffer2>: class: TUUID, attempting to access
>> a wrong version: 127, object skipped at offset 87
>> Error in <TFile::ReadBuffer>: error reading all requested bytes from
>> file file.root, got 0 of 2687036
>> (class TObject*)0x8345fa8
>>
>> Thank you
>> Pierre-Luc Drouin
>>
>> Rene Brun wrote:
>>
>>
>>> Pierre-Luc,
>>>
>>> Instead of TDirectory, you should derive from TDirectoryFile. In
>>> version 5.16, TDirectory
>>> became an abstract interface. See 5.16 Release Notes at:
>>> http://root.cern.ch/root/Version516.news.html
>>>
>>> Rene Brun
>>>
>>> Pierre-Luc Drouin wrote:
>>>
>>>
>>>> Hi,
>>>>
>>>> I have derived a class from TDirectory and I am trying to store and
>>>> retrieve an instance of this class to/from a ROOT file.
>>>>
>>>> I am using the autogenerated Streamer function and when I call
>>>> TDirectory
>>>> <http://root.cern.ch/root/html514/src/TDirectory.cxx.html#OUS8P>(const
>>>> char *name, const char *title, Option_t
>>>> <http://root.cern.ch/root/html514/ListOfTypes.html#Option_t>
>>>> *classname, TDirectory
>>>> <http://root.cern.ch/root/html514/TDirectory.html>* initMotherDir)
>>>> from the constructor of my class, I set classname to the name of my
>>>> class.
>>>>
>>>> I do not get any warning/error message when I Write the instance in
>>>> the root file, but I get the following error when I try to load the
>>>> instance using TFile::Get:
>>>>
>>>> Error in <TBuffer::ReadVersion>: Could not find the StreamerInfo with
>>>> a checksum of 0 for the class "TUUID" in file.root.
>>>> Error in <TBuffer::CheckByteCount>: object of class TUUID read too
>>>> few bytes: 22 instead of 898023151
>>>> Error in <TBuffer::CheckByteCount>: Byte count probably corrupted
>>>> around buffer position 85:
>>>> 898023151 for a possible maximum of 17
>>>> SysError in <TFile::Seek>: cannot seek to position 60235645022633984
>>>> in file file.root, retpos=-1 (Invalid argument)
>>>> Error in <TFile::ReadBuffer>: error reading all requested bytes from
>>>> file file.root, got 186 of 2687036
>>>>
>>>> Here is the code of a class that allows to reproduce the problem:
>>>>
>>>> class QMyDir: public TDirectory
>>>> {
>>>> public:
>>>> QMyDir():TDirectory(){}
>>>>
>>>> QMyDir(const QMyDir& newqds):TDirectory(){*this=newqds; }
>>>>
>>>> QMyDir(const char *name, const char *title, TDirectory* motherDir
>>>> = 0):TDirectory(name,title,"QMyDir",motherDir){}
>>>>
>>>> virtual ~QMyDir(){}
>>>>
>>>> QMyDir& operator=(const QMyDir &rhs){fprintf(stderr,"Warning:
>>>> TDirectory::operator= function is private and cannot be called by
>>>> derived class QMyDir\n"); return *this;}
>>>>
>>>> private:
>>>>
>>>> ClassDef(QMyDir,1) //QSigEx Data Structure Class
>>>> };
>>>>
>>>> Here is the code of the autogenerated Streamer function:
>>>>
>>>> void QMyDir::Streamer(TBuffer &R__b)
>>>> {
>>>> // Stream an object of class QMyDir.
>>>>
>>>> UInt_t R__s, R__c;
>>>> if (R__b.IsReading()) {
>>>> Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
>>>> TDirectory::Streamer(R__b);
>>>> R__b.CheckByteCount(R__s, R__c, QMyDir::IsA());
>>>> } else {
>>>> R__c = R__b.WriteVersion(QMyDir::IsA(), kTRUE);
>>>> TDirectory::Streamer(R__b);
>>>> R__b.SetByteCount(R__c, kTRUE);
>>>> } }
>>>>
>>>> Now how I get the error in CINT:
>>>>
>>>> root [0] TFile file("file.root","recreate")
>>>> root [1] QMyDir* dir=new QMyDir("dir","dir")
>>>> root [2] file.ls()
>>>> TFile** file.root
>>>> TFile* file.root
>>>> QMyDir* dir dir
>>>> KEY: QMyDir dir;1 dir
>>>> root [3] file.Write()
>>>> (Int_t)0
>>>> root [4] file.Close()
>>>> root [5] .q
>>>>
>>>> root [0] TFile file("file.root","read")
>>>> root [1] file.ls()
>>>> TFile** file.root
>>>> TFile* file.root
>>>> KEY: QMyDir dir;1 dir
>>>> root [2] QMyDir *dir=file.Get("dir")
>>>> Error in <TBuffer::ReadVersion>: Could not find the StreamerInfo with
>>>> a checksum of 0 for the class "TUUID" in file.root.
>>>> Error in <TBuffer::CheckByteCount>: object of class TUUID read too
>>>> few bytes: 22 instead of 898023151
>>>> Error in <TBuffer::CheckByteCount>: Byte count probably corrupted
>>>> around buffer position 85:
>>>> 898023151 for a possible maximum of 17
>>>> SysError in <TFile::Seek>: cannot seek to position 60235645022633984
>>>> in file file.root, retpos=-1 (Invalid argument)
>>>> Error in <TFile::ReadBuffer>: error reading all requested bytes from
>>>> file file.root, got 186 of 2687036
>>>>
>>>>
>>>> Thanks!
>>>> Pierre-Luc Drouin
>>>>
>>>>
>>>>
>>>>
>>
>>
>
>
>
Received on Wed Mar 19 2008 - 20:51:12 CET

This archive was generated by hypermail 2.2.0 : Thu Mar 20 2008 - 05:50:03 CET