Re: moving a TDirectory from one TFile to another

From: Rene Brun (Rene.Brun@cern.ch)
Date: Fri Dec 04 1998 - 11:40:11 MET


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------|/\/|/\/|----



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:40 MET