Hello,
I have a revised version of my code on roottalk which will correctly
handle TH1 derivatives and TDirectories in memory. Of course you are right
that requirering things to be in memory is a limitation. For general
interest, here is the code.
...
bool RooTupleManager::setFileName( const char* file ) {
// Make sure we are at the top of the current file, then save:
checkFile();
rtfilep->cd();
write();
// Create the new file and transfer all objects from existing to new
// file. Function movedir will call itself recursively for directories.
TFile* filep= new TFile( file, "RECREATE",
"Created for you again by RooTupleManager" );
movedir( rtfilep, filep );
// Now we can safely get rid of the old file:
delete rtfilep;
rtfilep= filep;
// The End:
return true;
}
// Recursively move contents of olddir to newdir:
void RooTupleManager::movedir( TDirectory* olddir, TDirectory* newdir ) {
TList* list1= olddir->GetList();
TIter iter( list1 );
TObject* obj= 0;
while( obj= iter.Next() ) {
if( obj->InheritsFrom( "TH1" ) ) {
// TH1::SetDirectory does all the work for us:
((TH1*)obj)->SetDirectory( newdir );
}
else if( strcmp( obj->ClassName(), "TDirectory" ) == 0 ) {
// Have to do it by hand recursively for TDirectory:
list1->Remove( obj );
TDirectory* dir= newdir->mkdir( obj->GetName() );
movedir( (TDirectory*)obj, dir );
}
}
return;
}
...
I have to create new TDirectories when I move their contents, because they
know about their file and this can't be changed.
It would perhaps be better, if TDirectory would not hold a pointer to the
file, but would rather ask its "mother" for the file pointer. You could
have (public) member functions
TFile* TDirectory::GetFile() { return fmother->GetFile(); }
and
TFile* Tfile::GetFile() { return this; }
So, when you need to the know the file a TDirectory is attached to the
call will cascade up the directory tree until you hit the current TFile.
If you move a TDirectory to another directory tree rooted in a different
file everything will be ok. Objects (entries) in a TDirectory should not
hold their own file pointers, but should rather call
fDirectory->GetFile(). In this way you could move a whole TDirectory and
everything below it in one go.
Just a thought, cheers, Stefan
---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------|/\/|/\/|----