Re: moving a TDirectory from one TFile to another

Rene Brun (Rene.Brun@cern.ch)
Fri, 04 Dec 1998 11:40:11 +0100


Hi Stefan,
Your code below will work only for simple cases. It also implies
that your objects must be in memory first.
The development of a true Cp and Mv functions is more work.
Copying/Moving should not require the import in memory with object
expansion. A simple transfert of the stream of bytes is required.
The difficulty is to support trees in this mode.

Rene Brun

stefan kluth wrote:
>
> On Thu, 26 Nov 1998, Rene Brun wrote:
> > TDirectory/TFile do not provide the functionality to copy/move
> > directories between files. This could be implemented using
> > the normal Unix semantics (say TDirectory::Mv and Cp).
> > Currently you must loop yourself on all keys of a directory,
> > import the object in memory and write it on the new directory.
>
> Hi, here is some code which does almost what I want. It works fine on DEC
> unix, but crashes at the end of the job on Sun. Appearently, my code
> misses to fix something and ROOTs internal bookkeeping gets out of sync.
>
> ...
>
> // Make sure we at the top of the current file, then save:
> checkFile();
> gDirectory->cd( "/" );
> rtfilep->Write();
>
> // Get list of root objects in memory, then create the new file.
> // Iterate on list and transfer objects from old to new file.
> TList* list1= gDirectory->GetList();
> TIter iter( list1 );
> TFile* filep= new TFile( file, "RECREATE",
> "Created for you again by RooTupleManager" );
> TList* list2= filep->GetList();
> TObject* obj= 0;
> while( obj= iter.Next() ) {
> list1->Remove( obj );
> list2->Add( obj );
> if( obj->InheritsFrom( "TH1" ) ) {
> ((TH1*)obj)->SetDirectory( gDirectory );
> }
> else if( strcmp( obj->ClassName(), "TDirectory" ) == 0 ) {
> ((TDirectory*)obj)->SetMother( gDirectory );
> }
> }
>
> // Now we can safely get rid of the old file:
> delete rtfilep;
> rtfilep= filep;
>
> ...
>
> Here is a traceback of the crash on Sun:
>
> ...
> signal SEGV (no mapping at the fault address) in TObjectTable::Delete at
> line 190 in file "BASE_ObjectTable.cxx"
> 190 delete fTable[i];
> (dbx) where
> =>[1] TObjectTable::Delete(this = 0x346d08, _ARG1 = 0xef14dd1c ""), line
> 190 in "BASE_ObjectTable.cxx"
> [2] TCollection::EmptyGarbageCollection(), line 337 in
> "CONT_Collection.cxx"
> [3] TFile::Close(this = 0x347ac8, _ARG1 = 0xef5f0896 ""), line 486 in
> "BASE_File.cxx"
> [4] TFile::~TFile(this = 0x347ac8, delete = 3), line 319 in
> "BASE_File.cxx"
> [5] RooTupleManager::~RooTupleManager(this = 0x82ff8, delete = 3), line
> 39 in "RooTupleManager.cc"
> [6] main(), line 52 in "testRooTM3.cc"
> ...
>
> Any ideas what I am doing wrong/forgetting to do?
>
> cheers, Stefan
>
> BTW, this wouldn't work with TTrees, because TTree does not have a member
> function TTree::SetDirectory. I am not sure if it would be possible to
> transfer TTrees between TDirectories/TFiles anyway.
>
> ---Stefan Kluth---------------Lynen Fellow----------------|\--|\-------
> - LBNL, MS 50A 2160 - phone: +1 510 495 2376 - |/ |/ -
> - 1 Cyclotron Rd. - fax: +1 510 495 2957 - |\/\|\/\|' -
> ---Berkeley, CA94720, USA-----e-mail: SKluth@lbl.gov------|/\/|/\/|----