// @(#)root/proof:$Name: $:$Id: TEventIter.cxx,v 1.21 2006/01/17 14:23:40 rdm Exp $
// Author: Maarten Ballintijn 07/01/02
/*************************************************************************
* Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TEventIter //
// //
//////////////////////////////////////////////////////////////////////////
#include "TEventIter.h"
#include "TCollection.h"
#include "TDSet.h"
#include "TFile.h"
#include "TKey.h"
#include "TProofDebug.h"
#include "TSelector.h"
#include "TTimeStamp.h"
#include "TTree.h"
#include "TVirtualPerfStats.h"
#include "TEventList.h"
TEventIterTree::TFileCache *TEventIterTree::TFileCache::fgInstance = 0;
TEventIterTree::TDirectoryCache *TEventIterTree::TDirectoryCache::fgInstance = 0;
ClassImp(TEventIter)
//______________________________________________________________________________
TEventIter::TEventIter()
{
fDSet = 0;
fElem = 0;
fFile = 0;
fDir = 0;
fSel = 0;
fFirst = 0;
fCur = -1;
fNum = 0;
fStop = kFALSE;
}
//______________________________________________________________________________
TEventIter::TEventIter(TDSet *dset, TSelector *sel, Long64_t first, Long64_t num)
: fDSet(dset), fSel(sel)
{
fElem = 0;
fFile = 0;
fDir = 0;
fFirst = first;
fCur = -1;
fNum = num;
fStop = kFALSE;
fEventList = 0;
fEventListPos = 0;
}
//______________________________________________________________________________
TEventIter::~TEventIter()
{
delete fFile;
}
//______________________________________________________________________________
void TEventIter::StopProcess(Bool_t /*abort*/)
{
fStop = kTRUE;
}
//______________________________________________________________________________
TEventIter *TEventIter::Create(TDSet *dset, TSelector *sel, Long64_t first, Long64_t num)
{
if ( dset->IsTree() ) {
return new TEventIterTree(dset, sel, first, num);
} else {
return new TEventIterObj(dset, sel, first, num);
}
}
//______________________________________________________________________________
Int_t TEventIter::LoadDir()
{
Int_t ret = 0;
// Check Filename
if ( fFile == 0 || fFilename != fElem->GetFileName() ) {
fDir = 0;
delete fFile; fFile = 0;
fFilename = fElem->GetFileName();
TDirectory *dirsave = gDirectory;
Double_t start = 0;
if (gPerfStats != 0) start = TTimeStamp();
fFile = TFile::Open(fFilename);
if (gPerfStats != 0) {
gPerfStats->FileOpenEvent(fFile, fFilename, double(TTimeStamp())-start);
fOldBytesRead = 0;
}
if (dirsave) dirsave->cd();
if (!fFile || fFile->IsZombie() ) {
if (fFile)
Error("Process","Cannot open file: %s (%s)",
fFilename.Data(), strerror(fFile->GetErrno()) );
else
Error("Process","Cannot open file: %s (errno unavailable)",
fFilename.Data());
// cleanup ?
return -1;
}
PDB(kLoop,2) Info("LoadDir","Opening file: %s", fFilename.Data() );
ret = 1;
}
// Check Directory
if ( fDir == 0 || fPath != fElem->GetDirectory() ) {
TDirectory *dirsave = gDirectory;
fPath = fElem->GetDirectory();
if ( !fFile->cd(fPath) ) {
Error("Process","Cannot cd to: %s",
fPath.Data() );
return -1;
}
PDB(kLoop,2) Info("Process","Cd to: %s", fPath.Data() );
fDir = gDirectory;
if (dirsave) dirsave->cd();
ret = 1;
}
return ret;
}
//------------------------------------------------------------------------
ClassImp(TEventIterObj)
//______________________________________________________________________________
TEventIterObj::TEventIterObj()
{
// Default ctor.
fKeys = 0;
fNextKey = 0;
fObj = 0;
}
//______________________________________________________________________________
TEventIterObj::TEventIterObj(TDSet *dset, TSelector *sel, Long64_t first, Long64_t num)
: TEventIter(dset,sel,first,num)
{
fClassName = dset->GetType();
fKeys = 0;
fNextKey = 0;
fObj = 0;
}
//______________________________________________________________________________
TEventIterObj::~TEventIterObj()
{
// delete fKeys ?
delete fNextKey;
delete fObj;
}
//______________________________________________________________________________
Long64_t TEventIterObj::GetNextEvent()
{
if (fStop || fNum == 0) return -1;
while ( fElem == 0 || fElemNum == 0 || fCur < fFirst-1 ) {
if (gPerfStats != 0 && fFile != 0) {
Long64_t bytesRead = fFile->GetBytesRead();
gPerfStats->SetBytesRead(bytesRead - fOldBytesRead);
fOldBytesRead = bytesRead;
}
fElem = fDSet->Next(fKeys->GetSize());
if (fElem->GetEventList()) {
Error("GetNextEvent", "EventLists not implemented");
return -1;
}
if ( fElem == 0 ) {
fNum = 0;
return -1;
}
Int_t r = LoadDir();
if ( r == -1 ) {
// Error has been reported
fNum = 0;
return -1;
} else if ( r == 1 ) {
// New file and/or directory
fKeys = fDir->GetListOfKeys();
fNextKey = new TIter(fKeys);
}
// Validate values for this element
fElemFirst = fElem->GetFirst();
fElemNum = fElem->GetNum();
fEventList = fElem->GetEventList();
fEventListPos = 0;
if (fEventList) {
fElemNum = fEventList->GetN();
}
Long64_t num = fKeys->GetSize();
if ( fElemFirst > num ) {
Error("GetNextEvent","First (%d) higher then number of keys (%d) in %d",
fElemFirst, num, fElem->GetName() );
fNum = 0;
return -1;
}
if ( fElemNum == -1 ) {
fElemNum = num - fElemFirst;
} else if ( fElemFirst+fElemNum > num ) {
Error("GetNextEvent","Num (%d) + First (%d) larger then number of keys (%d) in %s",
fElemNum, fElemFirst, num, fElem->GetDirectory() );
fElemNum = num - fElemFirst;
}
// Skip this element completely?
if ( fCur + fElemNum < fFirst ) {
fCur += fElemNum;
continue;
}
// Position within this element. TODO: more efficient?
fNextKey->Reset();
for(fElemCur = -1; fElemCur < fElemFirst-1 ; fElemCur++, fNextKey->Next());
}
--fElemNum;
++fElemCur;
--fNum;
++fCur;
TKey *key = (TKey*) fNextKey->Next();
TDirectory *dirsave = gDirectory;
fDir->cd();
fObj = key->ReadObj();
if (dirsave) dirsave->cd();
fSel->SetObject( fObj );
return fElemCur;
}
//------------------------------------------------------------------------
ClassImp(TEventIterTree)
//______________________________________________________________________________
TEventIterTree::TEventIterTree()
{
// Default ctor.
fTree = 0;
}
//______________________________________________________________________________
TEventIterTree::TEventIterTree(TDSet *dset, TSelector *sel, Long64_t first, Long64_t num)
: TEventIter(dset,sel,first,num)
{
fTreeName = dset->GetObjName();
fTree = 0;
fTreeCache = 0;
}
//______________________________________________________________________________
TEventIterTree::~TEventIterTree()
{
ReleaseAllTrees();
}
//______________________________________________________________________________
void TEventIterTree::ReleaseAllTrees() {
// release all acquired trees.
for (std::list<TTree*>::iterator i = fAcquiredTrees.begin(); i != fAcquiredTrees.end(); ++i) {
fTreeCache->Release(*i);
}
fAcquiredTrees.clear();
SafeDelete(fTreeCache);
}
//______________________________________________________________________________
TTree* TEventIterTree::GetTrees(TDSetElement *elem)
{
// Create a Tree for the main TDSetElement and for all the friends.
// Returns the main tree or 0 in case of an error.
if (!fTreeCache)
fTreeCache = new TTreeCache;
TTree* main = fTreeCache->Acquire(elem->GetFileName(),
elem->GetDirectory(), elem->GetObjName());
if (!main)
return 0;
fAcquiredTrees.push_front(main);
TDSetElement::FriendsList_t* friends = elem->GetListOfFriends();
for (TDSetElement::FriendsList_t::iterator i = friends->begin();
i != friends->end(); ++i) {
TTree* friendTree = fTreeCache->Acquire(i->first->GetFileName(),
i->first->GetDirectory(),
i->first->GetObjName());
if (friendTree) {
fAcquiredTrees.push_front(friendTree);
main->AddFriend(friendTree, i->second);
}
else {
ReleaseAllTrees();
return 0;
}
}
return main;
}
//______________________________________________________________________________
Long64_t TEventIterTree::GetNextEvent()
{
if (fStop || fNum == 0) return -1;
Bool_t attach = kFALSE;
while ( fElem == 0 || fElemNum == 0 || fCur < fFirst-1 ) {
if (gPerfStats != 0 && fFile != 0) {
Long64_t bytesRead = fFile->GetBytesRead();
gPerfStats->SetBytesRead(bytesRead - fOldBytesRead);
fOldBytesRead = bytesRead;
}
if (fTree) {
fElem = fDSet->Next(fTree->GetEntries());
} else {
fElem = fDSet->Next();
}
if ( fElem == 0 ) {
fNum = 0;
return -1;
}
ReleaseAllTrees();
fTree = GetTrees(fElem);
if (!fTree) {
// Error has been reported
fNum = 0;
return -1;
}
attach = kTRUE;
// Validate values for this element
fElemFirst = fElem->GetFirst();
fElemNum = fElem->GetNum();
fEventList = fElem->GetEventList();
fEventListPos = 0;
if (fEventList)
fElemNum = fEventList->GetN();
Long64_t num = (Long64_t) fTree->GetEntries();
if (!fEventList) {
if ( fElemFirst > num ) {
Error("GetNextEvent","First (%d) higher then number of entries (%d) in %s",
fElemFirst, num, fElem->GetObjName() );
fNum = 0;
return -1;
}
if ( fElemNum == -1 ) {
fElemNum = num - fElemFirst;
} else if ( fElemFirst+fElemNum > num ) {
Error("GetNextEvent","Num (%d) + First (%d) larger then number of entries (%d) in %s",
fElemNum, fElemFirst, num, fElem->GetName() );
fElemNum = num - fElemFirst;
}
// Skip this element completely?
if ( fCur + fElemNum < fFirst ) {
fCur += fElemNum;
continue;
}
// Position within this element. TODO: more efficient?
fElemCur = fElemFirst-1;
}
}
if ( attach ) {
PDB(kLoop,1) Info("GetNextEvent","Call Init(%p)",fTree);
fSel->Init( fTree );
if( !fSel->Notify()) {
// the error has been reported
return -1;
}
attach = kFALSE;
}
if (!fEventList) {
--fElemNum;
++fElemCur;
--fNum;
++fCur;
return fElemCur;
}
else {
--fElemNum;
int rv = fEventList->GetEntry(fEventListPos);
fEventListPos++;
return rv;
}
}
//______________________________________________________________________________
TEventIterTree::TFileCache::ObjectAndBool_t TEventIterTree::TFileCache::Load(const TString &fileName)
{
// Loads a file given its filename. See TObjectCache::Load().
TDirectory *dirsave = gDirectory;
Double_t start = 0;
if (gPerfStats != 0) start = TTimeStamp();
TFile* file = TFile::Open(fileName.Data());
if (gPerfStats != 0) {
gPerfStats->FileOpenEvent(file, fileName, double(TTimeStamp())-start);
}
if (dirsave) dirsave->cd();
if (!file || file->IsZombie() ) {
if (file) {
::Error("TEventIterTree::TFileCache::Load","Cannot open file: %s (%s)",
fileName.Data(), strerror(file->GetErrno()) );
delete file;
file = 0;
}
else
::Error("TEventIterTree::TFileCache::Load",
"Cannot open file: %s (errno unavailable)", fileName.Data());
return std::make_pair((TFile*)0, kFALSE);
}
PDB(kLoop,2) ::Info("TEventIterTree::TFileCache::Load","Opening file: %s", fileName.Data());
return std::make_pair(file, kTRUE);
}
//______________________________________________________________________________
void TEventIterTree::TFileCache::Unload(TFile* &f)
{
// Deletes the file. See TObjectCache::Load().
delete f;
}
//______________________________________________________________________________
TEventIterTree::TFileCache* TEventIterTree::TFileCache::Instance()
{
// Returns an instance (only one in the system) of the class.
if (fgInstance == 0)
fgInstance = new TFileCache();
return fgInstance;
}
//______________________________________________________________________________
TEventIterTree::TDirectoryCache::ObjectAndBool_t TEventIterTree::TDirectoryCache::Load(const TCacheKey &k)
{
// Loads a directory given the file name and the directory name.
// See TObjectCache::Acquire().
const TString fileName = k.first;
const TString dirName = k.second;
using namespace std;
TDirectory *dirsave = gDirectory;
TFile *file = TFileCache::Instance()->Acquire(fileName);
if (!file)
return make_pair((TDirectory*)0, kFALSE);
if (!file->cd(dirName)) {
:: Error("TEventIterTree::TDirectoryCache::Load","Cannot cd to: %s", dirName.Data() );
TFileCache::Instance()->Release(file);
return make_pair((TDirectory*)0, kFALSE);
}
PDB(kLoop,2) ::Info("TEventIterTree::TDirectoryCache::Load","Cd to: %s", dirName.Data() );
TDirectory *dir = gDirectory;
if (dirsave) dirsave->cd();
fDirectoryFiles[dir] = file;
return make_pair(dir, kTRUE);
}
//______________________________________________________________________________
void TEventIterTree::TDirectoryCache::Unload(TDirectory* &dir)
{
// Releases the file in which the directory was stored.
// The directory itself is not deleted. It will be deleted when the file
// is closed.
TFileCache::Instance()->Release(fDirectoryFiles[dir]);
fDirectoryFiles.erase(dir);
}
//______________________________________________________________________________
TEventIterTree::TDirectoryCache* TEventIterTree::TDirectoryCache::Instance()
{
// Returns an instance (only one in the system) of the class.
if (fgInstance == 0)
fgInstance = new TDirectoryCache();
return fgInstance;
}
//______________________________________________________________________________
void TEventIterTree::TTreeCache::Unload(TTree* &tree)
{
// Deleted the tree. Releases the file in which it was stored.
delete tree;
TDirectoryCache::Instance()->Release(fTreeDirectories[tree]);
fTreeDirectories.erase(tree);
}
//______________________________________________________________________________
TEventIterTree::TTreeCache::ObjectAndBool_t TEventIterTree::TTreeCache::Load(const TCacheKey &k)
{
// Loads a tree given the file name where it's stored, the directory name in the file
// and the tree name. See TObjectCache::Acquire().
const TString fileName = k.first;
const TString dirName = k.second.first;
const TString treeName = k.second.second;
using namespace std;
TDirectory *dir = TDirectoryCache::Instance()->Acquire(fileName, dirName);
if (!dir)
return make_pair((TTree*)0, kFALSE);
TKey *key = dir->GetKey(treeName);
if (key == 0) {
::Error("TEventIterTree::TTreeCache::Load","Cannot find tree \"%s\" in %s",
treeName.Data(), fileName.Data());
TDirectoryCache::Instance()->Release(dir);
return make_pair((TTree*)0, kFALSE);
}
PDB(kLoop,2) ::Info("TEventIterTree::TTreeCache::Load","Reading: %s", treeName.Data() );
TDirectory *dirsave = gDirectory;
dir->cd();
TTree *tree = dynamic_cast<TTree*> (key->ReadObj());
if (dirsave) dirsave->cd();
if (tree == 0) {
TDirectoryCache::Instance()->Release(dir);
return make_pair((TTree*)0, kFALSE);
}
fTreeDirectories[tree] = dir;
return make_pair(tree, kTRUE);
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.