ROOT records w/ sub-dirs

hi there,

I am a bit puzzled by the output of this ROOT macro:

void subdirs_root() {
	auto f = TFile::Open("subdirs.root", "RECREATE");
	auto dir1 = f->mkdir("dir-1");      dir1 ->cd();
	auto dir11 = dir1->mkdir("dir-11"); dir11->cd();
	auto obj = new TObjString("data-obj1");
	obj->Write("obj1");

	auto dir2 = f->mkdir("dir-2"); dir2->cd();
	auto obj2 = new TObjString("data-obj2");
	obj2->Write("obj2");

	f->Write(); f->Close();

	gSystem->Exit(0);
}

using root-ls (from groot) after having executed that macro above, I get:

$> root-ls ./subdirs.root
=== [./subdirs.root] ===
version: 61804
TDirectoryFile   dir-1   dir-1                    (cycle=1)
  TDirectoryFile dir-11  dir-11                   (cycle=1)
    TObjString   obj1    Collectable string class (cycle=1)
TDirectoryFile dir-2   dir-2                    (cycle=1)
  TObjString   obj2    Collectable string class (cycle=1)

which seems reasonable.

and the output of executing TFile::Map() on that ROOT file is:

20191008/180105  At:100    N=144       TFile         
20191008/180105  At:244    N=109       TDirectory    // -> "dir-1"
20191008/180105  At:353    N=111       TDirectory    // -> "dir-11"
20191008/180105  At:464    N=93        TObjString    // -> "obj1"
20191008/180105  At:557    N=109       TDirectory    // -> "dir-2"
20191008/180105  At:666    N=93        TObjString    // -> "obj2"
20191008/180105  At:759    N=122       TDirectory    // -> "dir-11"
20191008/180105  At:881    N=104       TDirectory    // -> "dir-1"
20191008/180105  At:985    N=120       TDirectory    // -> "dir-2"
20191008/180105  At:1105   N=160       KeysList      
20191008/180105  At:1265   N=281       StreamerInfo   CX =  1.54
20191008/180105  At:1546   N=68        FreeSegments  
20191008/180105  At:1614   N=1         END           

(I have added the name of the associated key)
there are duplicates, but ok (?).

but inspecting the fSeekXXX values of the directories leads to something peculiar:

>>> import ROOT
>>> f = ROOT.TFile.Open("./subdirs.root")

>>> dir1 = f.Get("dir-1")
>>> dir1.GetSeekDir()
244
>>> dir1.GetSeekParent()
100 ## ok.

>>> dir11 = dir1.Get("dir-11")
>>> dir11.GetSeekDir()
353
>>> dir11.GetSeekParent()
100 ## ???

ie: the sub dir dir-11 has as an on-disk parent the “root” directory instead of the expected "dir-1" one.
at least, that’s my understanding of this diagram:

(this threw me off when trying to implement nested sub-directories in groot.)

So, why is the fSeekParent field of directories and sub-directories always TFile::fBegin ?
(and why are there duplicates TDirectories ? they do not seem to be GAPs nor deleted keys…)

cheers,
-s


ROOT Version: 6.18/04
Platform: linuxx8664gcc
Compiler: gcc (GCC) 9.2.0


replace f->Write(); f->Close(); with delete f;

thanks, but I get the same (kind of) output:

>>> import ROOT
>>> f=ROOT.TFile.Open("subdirs.root")
>>> f.Map()
20191008/200126  At:100    N=144       TFile         
20191008/200126  At:244    N=109       TDirectory    
20191008/200126  At:353    N=111       TDirectory    
20191008/200126  At:464    N=93        TObjString    
20191008/200126  At:557    N=109       TDirectory    
20191008/200126  At:666    N=93        TObjString    
20191008/200126  At:759    N=281       StreamerInfo   CX =  1.54
20191008/200126  At:1040   N=160       KeysList      
20191008/200126  At:1200   N=104       TDirectory    
20191008/200126  At:1304   N=122       TDirectory    
20191008/200126  At:1426   N=120       TDirectory    
20191008/200126  At:1546   N=68        FreeSegments  
20191008/200126  At:1614   N=1         END    
>>> dir11 = f.Get("dir-1").Get("dir-11")       
>>> dir11.GetSeekParent()
100
>>> dir11.GetSeekDir()
353

Hi Sebastien,

Indeed, fSeekParent has been pointing to the top level directory in the file (aka the “root” directory) since the very beginning :frowning: . We probably should update the code to match the documentation :slight_smile:

(and why are there duplicates TDirectories ? they do not seem to be GAPs nor deleted keys…)

They are not duplicate. The information for TDirectory is stored in 2 parts. One fixed length (for a given directory name) that contains only meta data (name, location of the 2nd part, unique id, etc.) and a second one of variable length containing the TKey meta information for the directory.

Cheers,
Philippe.

ok.

I have created https://sft.its.cern.ch/jira/browse/ROOT-10352 to not forget about this.
(so I can implement the same thing in groot when it lands in ROOT)

thanks Philippe.