Error in <TFile::ReadBuffer>

Hi all,
I am building a large chain out of many trees, and I get an error occasionally. I get the error for only a few of my runs (less than 1%), but it causes a segfault each time which is a pain. The error is:

Error in TFile::ReadBuffer: error reading all requested bytes from file filename.root, got 234 of 300

I looked up previous cases, but they all had “got 0 out of SomeNumber” and my case appears different because of getting some of the bytes.

My loop is:

  TTree *bush=(TTree*)fIN->Get("bush");
  if (!bush){ cout <<"--->NO first bush.\n"; return 0;}
  cout <<"--->Got the first bush.\n";
  TChain *fChain = new TChain("bush");
  fChain->SetMakeClass(1);
  
  TFile *f;TString fname;
  for(int i=firstRUN;i<lastRUN; i++){
    fname = inDIR + fileINbase + Form("%d.root",i);
    ifstream ifile(fname);
    if(!ifile) {cout <<"---->bush "<< i << " is missing.\n"; continue;}
    f = TFile::Open(fname.Data());
    if(!f) cout <<"The file could not be opened!";
    fChain->Add(fname.Data());
    f->Close();
    fname.Clear();
  }

Can anyone suggest either a way to eliminate this error, or to have better error handling? Or both?

Many thanks!

Hi,

[quote]Error in TFile::ReadBuffer: error reading all requested bytes from file filename.root, got 234 of 300

Can anyone suggest either a way to eliminate this error,[/quote]

Most likely those file are corrupted/truncated and can not be used (i.e. could a physical disk error).

In your code testing for the failing case try to useif (!f || f->IsZombie) { cout <<"The file could not be opened!"; delete f; } else { fChain->Add(fname.Data()); } fname.Clear();

Cheers,
Philippe.

Works great! Thanks!

I have shifted to a TList method. My code snippet is below:

   TString inDIR;
   inDIR=diectory_name;
   TSystemDirectory inDir(inDIR, inDIR);
   TList *files = inDir.GetListOfFiles();
   if (files) {
      TFile *file;
      TSystemFile *f;
      TString fname;
      TIter next(files);
      while ((f=(TSystemFile*)next())) {
         if (f->IsDirectory() ){delete f; continue;}
         fname = inDIR ;
         fname += f->GetName();
         TFile::Open(fname.Data());
         if(!file||file->IsZombie()){delete file; continue;}
         else{fChain->Add(fname.Data());}
         file->Close();
         file->Delete();
         fname.Clear();
         f->Delete();
     }
  }

But after only 30 files or so I get the error
SysError in TFile::TFile: file directory_name/fname can not be opened for reading (Too many open files)

I don’t understand why this should be so. I could open many files with the code in my previous post.

Hi,

In the code snippet included ‘file’ is never modified: file = TFile::Open(fname.Data()); if(!file||file->IsZombie()){delete file; continue;} else{fChain->Add(fname.Data());} delete file; // (includes calls to Close) Note that “file->Delete()” does not delete the TFile object, just the in-memory content (user objects) attached the TFile.

Cheers,
Philippe.

Thanks for that. I fixed that issue, but I still get the same error of too many files. Here is my loop as it stands:


  TFile *fIN  = TFile::Open(fINname);
  TTree *bush=(TTree*)fIN->Get("bush");
  TChain *fChain = new TChain("bush");
  fChain->SetMakeClass(1);
 
  TSystemDirectory inDir(inDIR, inDIR);
  TList *files = inDir.GetListOfFiles();
  if (files) {
     TFile *file;
     TSystemFile *f;
     TString fname;
     TIter next(files);
     while ((f=(TSystemFile*)next())) {
        if (f->IsDirectory()){delete f; continue;}
        fname = inDIR ;
        fname += f->GetName();
        file = TFile::Open(fname.Data());
        if(!file||file->IsZombie()){delete file; continue;}
        else{fChain->Add(fname.Data());}
        file->Delete();
        fname.Clear();
        f->Delete();
     }
  }
    

Hi,

Replace both file->Delete and f->Delete with call to the operator delete (delete file; delete f;)

Cheers,
Philippe.

That’s got it. Many thanks!