problems updating root file

Eddy Offermann (eddy@rentec.com)
Thu, 1 Oct 98 21:18:59 EDT


Dear Rooters,

I have a problem when adding data to a tree and NOT performing a purge. After
the 10'th time I can not read the tree anymore and get the message:

Fatal in <operator new>: storage exhausted
aborting

I have tried to make a compact example. It consists out of:

1) sharable library libMylib.so which is made through
makefile, myClass.h and myClass.C

------------------------
makefile:
------------------------

ROOTLIBS = -L$(ROOTSYS)/lib -lNew -lBase -lCint -lClib -lCont -lFunc \
-lGraf -lGraf3d -lHist -lHtml -lMatrix -lMeta -lMinuit -lNet \
-lPostscript -lProof -lTree -lUnix -lZip
ROOTGLIBS = -lGpad -lGui -lGX11 -lX3d

# Solaris
CXX = CC
CXXFLAGS = -g -KPIC -I./ -I$(ROOTSYS)/include
LD = CC
LDFLAGS = -g
SOFLAGS = -G
LIBS = $(ROOTLIBS) -lm -lsocket -lgen -L/opt/SUNWspro/lib -lsunmath

.C.o:
$(CXX) $(CXXFLAGS) -c $<
all: libMylib.so
clean:
rm -f $(OBJS) *~ myClassDict.? myClassFile.? core

libMylib.so: myClass.o myClassDict.o
$(LD) $(SOFLAGS) $(LDFLAGS) myClass.o myClassDict.o -o libMylib.so

myClass.o: myClass.h
myClassDict.C: myClass.h
@rootcint -f myClassDict.C -c myClass.h

------------------------
myClass.h:
------------------------

#ifndef ROOT_MYCLASS
#define ROOT_MYCLASS

#include "TTree.h"
#include "TObject.h"
#include <unistd.h>
#include <assert.h>
#include <iostream.h>

class myClass : public TObject {
public:
Float_t a;
Float_t b;
Int_t seqNumber;

myClass();
~myClass();
void dump();

ClassDef(myClass,1)
};

#endif

------------------------
myClass.C:
------------------------

#include <myClass.h>

ClassImp(myClass)

myClass::myClass()
{
}

myClass::~myClass()
{
}

void myClass::dump()
{
printf("%i %.2f %.2f\n",seqNumber,a,b);
}

2) the macro code.C

------------------------
code.C:
------------------------

make(Char_t filename[], Int_t new=0, Int_t nrEntries=100000)
{
TFile *hfile;
TTree *tree;
myClass *var = new myClass;

printf("----\nmake\n----\n");
if (new)
{
printf("creating file %s\n",filename);
hfile = new TFile(filename,"CREATE");
tree = new TTree("tree","tree");
Int_t split = 1;
Int_t bsize = 64000;
TBranch *branch = tree->Branch("ticks","myClass",&var,bsize,split);
}
else
{
printf("opening file %s\n",filename);
hfile = new TFile(filename,"UPDATE");
tree = (TTree*) hfile->Get("tree");
tree->SetBranchAddress("ticks",&var);
}

for (Int_t i = 0; i < nrEntries; i++)
{
var->seqNumber = i;
tree->Fill();
}
printf("added %d entries to %s\n",nrEntries,filename);

// hfile->Purge(1);
hfile->Write();
hfile->ls();
hfile->Close();
}

read(Char_t filename[])
{
printf("----\nread\n----\n");
TFile *hfile = new TFile(filename,"READ");
if (hfile == NULL)
{
printf("Can not open the root file\n");
exit(1);
}

myClass *var = new myClass;
TTree *tree = (TTree*) hfile->Get("tree");
if (tree == NULL)
{
printf("Can not find tree\n");
exit(1);
}
tree->SetBranchAddress("ticks", &var);

Int_t nrEntries = tree->GetEntries();
Int_t step = nrEntries/10;
printf("nrEntries : %d\n", nrEntries);
for (Int_t i = 0; i < nrEntries; i++)
{
tree->GetEvent(i);
if (i%step == 0)
{
printf("%d : ",i);
var->dump();
}
}

hfile->Close();
delete hfile;
}

3) the macro doit.C

------------------------
doit.C:
------------------------

{
system("rm -f test.root");
for (Int_t i = 0; i < 11; i++)
{
Int_t new = (i == 0) ? 1 : 0;
make("test.root",new,10000);
read("test.root");
}
}

After making the 'libMylib.so' , I give the following commands in
root (2.00/11):

root [0] gSystem->Load("libMylib.so")
(int)0
root [1] .L code.C
root [2] .x doit.C

the ouput on the screen is:

----
make
----
creating file test.root <---- first time in loop
added 10000 entries to test.root
TFile Writing Name=test.root
----
read
----
nrEntries : 10000
0 : 0 0.00 0.00
1000 : 1000 0.00 0.00
2000 : 2000 0.00 0.00
3000 : 3000 0.00 0.00
4000 : 4000 0.00 0.00
5000 : 5000 0.00 0.00
6000 : 6000 0.00 0.00
7000 : 7000 0.00 0.00
8000 : 8000 0.00 0.00
9000 : 9000 0.00 0.00
----
make
----
opening file test.root <---- 2nd time in loop
added 10000 entries to test.root
TFile Writing Name=test.root
TFile** test.root
TFile* test.root
OBJ: TTree tree tree : 0
KEY: TTree tree;1 tree
TFile Writing Name=test.root
----
read
.
.
.
.
.
.
.
.
.
----
make
----
opening file test.root <----- 10th time in loop
added 10000 entries to test.root
TFile Writing Name=test.root
TFile** test.root
TFile* test.root
OBJ: TTree tree tree : 0
KEY: TTree tree;10 tree
KEY: TTree tree;9 tree
KEY: TTree tree;8 tree
KEY: TTree tree;7 tree
KEY: TTree tree;6 tree
KEY: TTree tree;5 tree
KEY: TTree tree;4 tree
KEY: TTree tree;3 tree
KEY: TTree tree;2 tree
KEY: TTree tree;1 tree
TFile Writing Name=test.root
----
read
----
nrEntries : 100000
0 : 0 0.00 0.00
10000 : 0 0.00 0.00
20000 : 0 0.00 0.00
30000 : 0 0.00 0.00
40000 : 0 0.00 0.00
Fatal in <operator new>: storage exhausted
aborting

When changing the number of entries per cycle from 10000 to 100000, the
problem remains but decreasing it to 1000 removes the problem. For 10000,
I have played with the buffersize and changed it from 64000 to 32000 and the
problem happend in cycle 17.

Keeping 10 cycles might sound unreasoable but my fear is that depending on
data/buff size it could happen after 1 or 2 cycles, that way losing the
data.

Any clue what I did wrong ??

Best regards,
Eddy Offermann