#include "TDSet.h"
#include "Riostream.h"
#include "TChain.h"
#include "TClass.h"
#include "TClassTable.h"
#include "TCut.h"
#include "TDataSetManager.h"
#include "TError.h"
#include "TEntryList.h"
#include "TEnv.h"
#include "TEventList.h"
#include "TFile.h"
#include "TFileInfo.h"
#include "TFileStager.h"
#include "TFriendElement.h"
#include "TKey.h"
#include "THashList.h"
#include "TMap.h"
#include "TROOT.h"
#include "TTimeStamp.h"
#include "TTree.h"
#include "TUrl.h"
#include "TRegexp.h"
#include "TVirtualPerfStats.h"
#include "TProof.h"
#include "TProofChain.h"
#include "TProofServ.h"
#include "TPluginManager.h"
#include "TChain.h"
#include "TChainElement.h"
#include "TSystem.h"
#include "THashList.h"
#include "TSelector.h"
#include "TVirtualStreamerInfo.h"
#include "TClassRef.h"
ClassImp(TDSetElement)
ClassImp(TDSet)
TDSetElement::TDSetElement() : TNamed("",""),
fDirectory(), fFirst(0), fNum(0), fMsd(),
fTDSetOffset(0), fEntryList(0), fValid(kFALSE),
fEntries(0), fFriends(0), fDataSet(), fAssocObjList(0),
fMaxProcTime(-1)
{
ResetBit(kWriteV3);
ResetBit(kHasBeenLookedUp);
ResetBit(kEmpty);
ResetBit(kCorrupted);
ResetBit(kNewRun);
ResetBit(kNewPacket);
}
TDSetElement::TDSetElement(const char *file, const char *objname, const char *dir,
Long64_t first, Long64_t num,
const char *msd, const char *dataset)
: TNamed(file, objname)
{
if (first < 0) {
Warning("TDSetElement", "first must be >= 0, %lld is not allowed - setting to 0", first);
fFirst = 0;
} else {
fFirst = first;
}
if (num < -1) {
Warning("TDSetElement", "num must be >= -1, %lld is not allowed - setting to -1", num);
fNum = -1;
} else {
fNum = num;
}
fMsd = msd;
fTDSetOffset = 0;
fEntryList = 0;
fFriends = 0;
fValid = kFALSE;
fEntries = -1;
fDataSet = dataset;
fAssocObjList = 0;
if (dir)
fDirectory = dir;
fMaxProcTime = -1.;
ResetBit(kWriteV3);
ResetBit(kHasBeenLookedUp);
ResetBit(kEmpty);
ResetBit(kCorrupted);
ResetBit(kNewRun);
ResetBit(kNewPacket);
}
TDSetElement::TDSetElement(const TDSetElement& elem)
: TNamed(elem.GetFileName(), elem.GetObjName())
{
fDirectory = elem.GetDirectory();
fFirst = elem.fFirst;
fNum = elem.fNum;
fMsd = elem.fMsd;
fTDSetOffset = elem.fTDSetOffset;
fEntryList = 0;
fValid = elem.fValid;
fEntries = elem.fEntries;
fFriends = 0;
fDataSet = elem.fDataSet;
fAssocObjList = 0;
fMaxProcTime = elem.fMaxProcTime;
ResetBit(kWriteV3);
ResetBit(kHasBeenLookedUp);
ResetBit(kEmpty);
ResetBit(kCorrupted);
ResetBit(kNewRun);
ResetBit(kNewPacket);
}
TDSetElement::~TDSetElement()
{
DeleteFriends();
if (fAssocObjList) {
fAssocObjList->SetOwner(kTRUE);
SafeDelete(fAssocObjList);
}
}
Int_t TDSetElement::MergeElement(TDSetElement *elem)
{
if (!elem) return -1;
if (strcmp(GetName(), elem->GetName()) || strcmp(GetTitle(), elem->GetTitle()))
return -1;
Int_t rc = -1;
if (fFirst == 0 && fNum == -1) {
rc = 1;
} else if (elem->GetFirst() == 0 && elem->GetNum() == -1) {
fFirst = 0;
fNum = -1;
fEntries = elem->GetEntries();
rc = 1;
} else if (fFirst >= 0 && fNum > 0 && elem->GetFirst() >= 0 && elem->GetNum() > 0) {
Long64_t last = fFirst + fNum - 1, lastref = 0;
Long64_t lastelem = elem->GetFirst() + elem->GetNum() - 1;
if (elem->GetFirst() == last + 1) {
lastref = lastelem;
rc = 0;
} else if (fFirst == lastelem + 1) {
fFirst += elem->GetFirst();
lastref = last;
rc = 0;
} else if (elem->GetFirst() < last + 1 && elem->GetFirst() >= fFirst) {
lastref = (lastelem > last) ? lastelem : last;
rc = 1;
} else if (fFirst < lastelem + 1 && fFirst >= elem->GetFirst()) {
fFirst += elem->GetFirst();
lastref = (lastelem > last) ? lastelem : last;
rc = 1;
}
fNum = lastref - fFirst + 1;
}
if (rc >= 0 && fEntries < 0 && elem->GetEntries() > 0) fEntries = elem->GetEntries();
return rc;
}
TFileInfo *TDSetElement::GetFileInfo(const char *type)
{
TFileInfoMeta *meta = 0;
Long64_t entries = (fEntries < 0 && fNum > 0) ? fNum : fEntries;
Printf("entries: %lld (%lld)", entries, fNum);
if (!strcmp(type, "TTree")) {
meta = new TFileInfoMeta(GetTitle(), "TTree", entries, fFirst,
fFirst + entries - 1);
} else {
meta = new TFileInfoMeta(GetTitle(), fDirectory, type, entries, fFirst,
fFirst + entries - 1);
}
TFileInfo *fi = new TFileInfo(GetName(), 0, 0, 0, meta);
if (!fDataSet.IsNull()) fi->SetTitle(fDataSet.Data());
if (TestBit(TDSetElement::kCorrupted)) fi->SetBit(TFileInfo::kCorrupted);
return fi;
}
const char *TDSetElement::GetDirectory() const
{
return fDirectory;
}
void TDSetElement::Print(Option_t *opt) const
{
if (opt && opt[0] == 'a') {
Printf("%s file=\"%s\" dir=\"%s\" obj=\"%s\" first=%lld num=%lld msd=\"%s\"",
IsA()->GetName(), GetName(), fDirectory.Data(), GetTitle(),
fFirst, fNum, fMsd.Data());
} else {
Printf("\tLFN: %s", GetName());
}
}
void TDSetElement::Validate(Bool_t isTree)
{
Long64_t entries = GetEntries(isTree);
if (entries < 0) return;
if (fFirst < entries) {
if (fNum == -1) {
fNum = entries - fFirst;
fValid = kTRUE;
} else {
if (fNum <= entries - fFirst) {
fValid = kTRUE;
} else {
Error("Validate", "TDSetElement has only %lld entries starting"
" with entry %lld, while %lld were requested",
entries - fFirst, fFirst, fNum);
}
}
} else {
Error("Validate", "TDSetElement has only %lld entries with"
" first entry requested as %lld", entries, fFirst);
}
}
void TDSetElement::Validate(TDSetElement *elem)
{
if (!elem || !elem->GetValid()) {
Error("Validate", "TDSetElement to validate against is not valid");
return;
}
TString name = TUrl(GetFileName()).GetFileAndOptions();
TString elemname = TUrl(elem->GetFileName()).GetFileAndOptions();
if ((name == elemname) &&
!strcmp(GetDirectory(), elem->GetDirectory()) &&
!strcmp(GetObjName(), elem->GetObjName())) {
Long64_t entries = elem->fFirst + elem->fNum;
if (fFirst < entries) {
if (fNum == -1) {
fNum = entries - fFirst;
fValid = kTRUE;
} else {
if (fNum <= entries - fFirst) {
fValid = kTRUE;
} else {
Error("Validate", "TDSetElement requests %lld entries starting"
" with entry %lld, while TDSetElement to validate against"
" has only %lld entries", fNum, fFirst, entries);
}
}
} else {
Error("Validate", "TDSetElement to validate against has only %lld"
" entries, but this TDSetElement requested %lld as its first"
" entry", entries, fFirst);
}
} else {
Error("Validate", "TDSetElements do not refer to same objects");
}
}
Int_t TDSetElement::Compare(const TObject *obj) const
{
if (this == obj) return 0;
const TDSetElement *elem = dynamic_cast<const TDSetElement*>(obj);
if (!elem) {
if (obj)
return (strncmp(GetName(),obj->GetName(),strlen(GetName()))) ? 1 : 0;
return -1;
}
Int_t order = strncmp(GetName(),elem->GetFileName(),strlen(GetName()));
if (order == 0) {
if (GetFirst() < elem->GetFirst())
return -1;
else if (GetFirst() > elem->GetFirst())
return 1;
return 0;
}
return order;
}
void TDSetElement::AddFriend(TDSetElement *friendElement, const char *alias)
{
if (!friendElement) {
Error("AddFriend", "The friend TDSetElement is null!");
return;
}
if (!fFriends) {
fFriends = new TList();
fFriends->SetOwner();
}
if (alias && strlen(alias) > 0) {
TUrl uf(friendElement->GetName());
TString uo(uf.GetOptions());
uo += TString::Format("friend_alias=%s|", alias);
uf.SetOptions(uo);
friendElement->SetName(uf.GetUrl());
}
fFriends->Add(new TDSetElement(*friendElement));
}
void TDSetElement::DeleteFriends()
{
if (!fFriends)
return;
fFriends->SetOwner(kTRUE);
delete fFriends;
fFriends = 0;
}
TDSetElement *TDSet::Next(Long64_t )
{
if (!fIterator) {
fIterator = new TIter(fElements);
}
fCurrent = (TDSetElement *) fIterator->Next();
return fCurrent;
}
Long64_t TDSetElement::GetEntries(Bool_t isTree, Bool_t openfile)
{
if (fEntries > -1 || !openfile)
return fEntries;
Double_t start = 0;
if (gPerfStats) start = TTimeStamp();
TFile::EFileType typ = TFile::kDefault;
TString fname = gEnv->GetValue("Path.Localroot",""), pfx(fname);
Int_t oldLevel = gErrorIgnoreLevel;
gErrorIgnoreLevel = kError+1;
if ((typ = TFile::GetType(GetName(), "", &fname)) != TFile::kLocal) fname = GetName();
gErrorIgnoreLevel = oldLevel;
TFile *file = TFile::Open(fname);
if (gPerfStats)
gPerfStats->FileOpenEvent(file, GetName(), start);
if (file == 0) {
::SysError("TDSetElement::GetEntries",
"cannot open file %s (type: %d, pfx: %s)", GetName(), typ, pfx.Data());
return -1;
}
if (Lookup(kFALSE) != 0) Warning("GetEntries", "lookup problems for %s", GetName());
TDirectory *dirsave = gDirectory;
if (!file->cd(fDirectory)) {
Error("GetEntries", "cannot cd to %s", fDirectory.Data());
delete file;
return -1;
}
TDirectory *dir = gDirectory;
dirsave->cd();
if (isTree) {
TString on(GetTitle());
TString sreg(GetTitle());
if (sreg.Length() <= 0 || sreg == "" || sreg.Contains("*")) {
if (sreg.Contains("*"))
sreg.ReplaceAll("*", ".*");
else
sreg = ".*";
TRegexp re(sreg);
if (dir->GetListOfKeys()) {
TIter nxk(dir->GetListOfKeys());
TKey *k = 0;
Bool_t notfound = kTRUE;
while ((k = (TKey *) nxk())) {
if (!strcmp(k->GetClassName(), "TTree")) {
TString kn(k->GetName());
if (kn.Index(re) != kNPOS) {
if (notfound) {
on = kn;
notfound = kFALSE;
} else if (kn != on) {
Warning("GetEntries",
"additional tree found in the file: %s", kn.Data());
}
}
}
}
}
}
TKey *key = dir->GetKey(on);
if (key == 0) {
Error("GetEntries", "cannot find tree \"%s\" in %s",
GetTitle(), GetName());
delete file;
return -1;
}
TTree *tree = (TTree *) key->ReadObj();
if (tree == 0) {
delete file;
return -1;
}
fEntries = tree->GetEntries();
delete tree;
} else {
TList *keys = dir->GetListOfKeys();
fEntries = keys->GetSize();
}
delete file;
return fEntries;
}
Int_t TDSetElement::Lookup(Bool_t force)
{
static Int_t xNetPluginOK = -1;
static TFileStager *xStager = 0;
Int_t retVal = 0;
if (!force && HasBeenLookedUp())
return retVal;
TUrl url(GetName());
TString anch = url.GetAnchor();
TString opts = url.GetOptions();
TString name(url.GetUrl());
Bool_t doit = kFALSE;
TFile::EFileType type = TFile::GetType(name, "");
if (type == TFile::kNet) {
TPluginHandler *h = 0;
if (xNetPluginOK == -1) {
xNetPluginOK = 0;
if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
!strcmp(h->GetClass(),"TXNetFile") && h->LoadPlugin() == 0)
xNetPluginOK = 1;
}
doit = (xNetPluginOK == 1) ? kTRUE : kFALSE;
}
if (doit) {
if (!xStager || !xStager->Matches(name)) {
SafeDelete(xStager);
if (!(xStager = TFileStager::Open(name))) {
Error("Lookup", "TFileStager instance cannot be instantiated");
retVal = -1;
}
}
if (xStager && xStager->Locate(name.Data(), name) == 0) {
url.SetUrl(name);
url.SetOptions(opts);
url.SetAnchor(anch);
fName = url.GetUrl();
} else {
Error("Lookup", "couldn't lookup %s", name.Data());
retVal = -1;
}
}
SetBit(kHasBeenLookedUp);
return retVal;
}
void TDSetElement::SetEntryList(TObject *aList, Long64_t first, Long64_t num)
{
if (!aList)
return;
TEventList *evl = 0;
TEntryList *enl = dynamic_cast<TEntryList*>(aList);
if (!enl)
evl = dynamic_cast<TEventList*>(aList);
if (!enl && !evl) {
Error("SetEntryList", "type of input object must be either TEntryList "
"or TEventList (found: '%s' - do nothing", aList->ClassName());
return;
}
if (enl) {
enl->SetEntriesToProcess(num);
} else {
for (; num > 0; num--, first++)
evl->Enter(evl->GetEntry((Int_t)first));
}
fEntryList = aList;
return;
}
void TDSetElement::AddAssocObj(TObject *assocobj)
{
if (assocobj) {
if (!fAssocObjList) fAssocObjList = new TList;
if (fAssocObjList) fAssocObjList->Add(assocobj);
}
}
TObject *TDSetElement::GetAssocObj(Long64_t i, Bool_t isentry)
{
TObject *o = 0;
if (!fAssocObjList || fAssocObjList->GetSize() <= 0) return o;
TString s;
Int_t pos = -1;
if (isentry) {
if (i < fFirst) return o;
s.Form("%lld", i - fFirst);
} else {
if (i < 0) return o;
s.Form("%lld", i);
}
if (!(s.IsDigit())) return o;
pos = s.Atoi();
if (pos > fAssocObjList->GetSize() - 1) pos %= fAssocObjList->GetSize();
return fAssocObjList->At(pos);
}
TDSet::TDSet()
{
fElements = new THashList;
fElements->SetOwner();
fIsTree = kFALSE;
fIterator = 0;
fCurrent = 0;
fEntryList = 0;
fProofChain = 0;
fSrvMaps = 0;
fSrvMapsIter = 0;
ResetBit(kWriteV3);
ResetBit(kEmpty);
ResetBit(kValidityChecked);
ResetBit(kSomeInvalid);
ResetBit(kMultiDSet);
gROOT->GetListOfDataSets()->Add(this);
}
TDSet::TDSet(const char *name,
const char *objname, const char *dir, const char *type)
{
fElements = new THashList;
fElements->SetOwner();
fIterator = 0;
fCurrent = 0;
fEntryList = 0;
fProofChain = 0;
fSrvMaps = 0;
fSrvMapsIter = 0;
ResetBit(kWriteV3);
ResetBit(kEmpty);
ResetBit(kValidityChecked);
ResetBit(kSomeInvalid);
ResetBit(kMultiDSet);
fType = "TTree";
TClass *c = 0;
if (name && strlen(name) > 0) {
if (!type) {
TString cn(name);
if (cn.Contains(':')) cn.Remove(0, cn.Index(":")+1);
if (TClass::GetClass(cn))
fType = cn;
else
fName = name;
} else {
fName = name;
if (strlen(type) > 0)
if (TClass::GetClass(type))
fType = type;
}
} else if (type && strlen(type) > 0) {
if (TClass::GetClass(type))
fType = type;
}
c = TClass::GetClass(fType);
fIsTree = (c->InheritsFrom(TTree::Class())) ? kTRUE : kFALSE;
if (objname)
fObjName = objname;
if (dir)
fDir = dir;
if (fName.Length() <= 0)
fName = TString::Format("TDSet:%s", fObjName.Data());
fTitle = fType;
gROOT->GetListOfDataSets()->Add(this);
}
TDSet::TDSet(const TChain &chain, Bool_t withfriends)
{
fElements = new THashList;
fElements->SetOwner();
fIterator = 0;
fCurrent = 0;
fEntryList = 0;
fProofChain = 0;
fSrvMaps = 0;
fSrvMapsIter = 0;
ResetBit(kWriteV3);
ResetBit(kEmpty);
ResetBit(kValidityChecked);
ResetBit(kSomeInvalid);
ResetBit(kMultiDSet);
fType = "TTree";
fIsTree = kTRUE;
fObjName = chain.GetName();
fName = TString::Format("TChain:%s", chain.GetName());
TIter next(chain.GetListOfFiles());
TChainElement *elem = 0;
TString key;
while ((elem = (TChainElement *)next())) {
TString file(elem->GetTitle());
TString tree(elem->GetName());
Int_t isl = tree.Last('/');
TString dir = "/";
if (isl >= 0) {
TString behindSlash = tree(isl + 1, tree.Length() - isl - 1);
tree.Remove(isl);
dir = tree;
tree = behindSlash;
}
TString msd(TUrl(file).GetOptions());
Int_t imsd = kNPOS;
if ((imsd = msd.Index("msd=")) != kNPOS) {
msd.Remove(0, imsd+4);
} else {
msd = "";
}
Long64_t nent = (elem->GetEntries() > 0 &&
elem->GetEntries() != TChain::kBigNumber) ? elem->GetEntries() : -1;
if (Add(file, tree, dir, 0, nent, ((msd.IsNull()) ? 0 : msd.Data()))) {
if (elem->HasBeenLookedUp()) {
TDSetElement *dse = (TDSetElement *) fElements->Last();
if (dse) dse->SetLookedUp();
}
}
}
SetDirectory(0);
if (withfriends) {
TList processed;
TList chainsQueue;
chainsQueue.Add((TObject *)&chain);
processed.Add((TObject *)&chain);
while (chainsQueue.GetSize() > 0) {
TChain *c = (TChain *) chainsQueue.First();
chainsQueue.Remove(c);
TIter friendsIter(c->GetListOfFriends());
while(TFriendElement *fe = dynamic_cast<TFriendElement*> (friendsIter()) ) {
if (TChain *fc = dynamic_cast<TChain*>(fe->GetTree())) {
if (!processed.FindObject(fc)) {
processed.AddFirst(fc);
AddFriend(new TDSet((const TChain &)(*fc), kFALSE), fe->GetName());
chainsQueue.Add(fc);
}
} else {
Reset();
Error("TDSet", "Only TChains supported. Found illegal tree %s",
fe->GetTree()->GetName());
return;
}
}
}
}
}
TDSet::~TDSet()
{
SafeDelete(fElements);
SafeDelete(fIterator);
SafeDelete(fProofChain);
fSrvMaps = 0;
fSrvMapsIter = 0;
gROOT->GetListOfDataSets()->Remove(this);
}
Long64_t TDSet::Process(TSelector *selector, Option_t *option, Long64_t nentries,
Long64_t first, TObject *enl)
{
if (!IsValid() || !fElements->GetSize()) {
Error("Process", "not a correctly initialized TDSet");
return -1;
}
SetEntryList(enl);
if (gProof)
return gProof->Process(this, selector, option, nentries, first);
Error("Process", "no active PROOF session");
return -1;
}
Long64_t TDSet::Process(const char *selector, Option_t *option, Long64_t nentries,
Long64_t first, TObject *enl)
{
if (!IsValid() || !fElements->GetSize()) {
Error("Process", "not a correctly initialized TDSet");
return -1;
}
SetEntryList(enl);
if (gProof)
return gProof->Process(this, selector, option, nentries, first);
Error("Process", "no active PROOF session");
return -1;
}
void TDSet::AddInput(TObject *obj)
{
if (gProof) {
gProof->AddInput(obj);
} else {
Error("AddInput","No PROOF session active");
}
}
void TDSet::ClearInput()
{
if (gProof)
gProof->ClearInput();
}
TObject *TDSet::GetOutput(const char *name)
{
if (gProof)
return gProof->GetOutput(name);
return 0;
}
TList *TDSet::GetOutputList()
{
if (gProof)
return gProof->GetOutputList();
return 0;
}
void TDSet::Print(const Option_t *opt) const
{
const char *clnm = (IsA()) ? IsA()->GetName() : "TDSet";
Printf("OBJ: %s\ttype %s\t%s\tin %s\telements %d", clnm, GetName(),
fObjName.Data(), GetTitle(), GetListOfElements()->GetSize());
if (opt && opt[0] == 'a') {
TIter next(GetListOfElements());
TObject *obj;
while ((obj = next())) {
obj->Print(opt);
}
}
}
void TDSet::SetObjName(const char *objname)
{
if (objname) {
fObjName = objname;
TIter next(GetListOfElements());
TDSetElement *e;
while ((e = (TDSetElement *) next())) {
e->SetTitle(objname);
}
}
}
void TDSet::SetDirectory(const char *dir)
{
if (dir)
fDir = dir;
}
Bool_t TDSet::Add(const char *file, const char *objname, const char *dir,
Long64_t first, Long64_t num, const char *msd)
{
if (!file || !*file) {
Error("Add", "file name must be specified");
return kFALSE;
}
TString fn = file;
if (gProof && gProof->IsLite()) {
TUrl u(file, kTRUE);
if (!strcmp(u.GetProtocol(), "file")) {
fn = u.GetFileAndOptions();
gSystem->ExpandPathName(fn);
if (!gSystem->IsAbsoluteFileName(fn))
gSystem->PrependPathName(gSystem->WorkingDirectory(), fn);
}
}
TDSetElement *el = (TDSetElement *) fElements->FindObject(fn);
if (!el) {
if (!objname)
objname = GetObjName();
if (!dir)
dir = GetDirectory();
fElements->Add(new TDSetElement(fn, objname, dir, first, num, msd));
} else {
TString msg;
msg.Form("duplication detected: %40s is already in dataset - ignored", fn.Data());
Warning("Add", "%s", msg.Data());
if (gProofServ) {
msg.Insert(0, "WARNING: ");
gProofServ->SendAsynMessage(msg);
}
}
return kTRUE;
}
Bool_t TDSet::Add(TDSet *dset)
{
if (!dset)
return kFALSE;
if (TestBit(TDSet::kMultiDSet)) {
fElements->Add(dset);
return kTRUE;
}
if (fType != dset->GetType()) {
Error("Add", "cannot add a set with a different type");
return kFALSE;
}
TDSetElement *el;
TIter next(dset->fElements);
TObject *last = (dset == this) ? fElements->Last() : 0;
while ((el = (TDSetElement*) next())) {
Add(el->GetFileName(), el->GetObjName(), el->GetDirectory(),
el->GetFirst(), el->GetNum(), el->GetMsd());
if (el == last) break;
}
return kTRUE;
}
Bool_t TDSet::Add(TCollection *filelist, const char *meta, Bool_t availableOnly,
TCollection *badlist)
{
if (!filelist)
return kFALSE;
TObject *o = 0;
TIter next(filelist);
while ((o = next())) {
TString cn(o->ClassName());
if (cn == "TFileInfo") {
TFileInfo *fi = (TFileInfo *)o;
if (!availableOnly ||
(fi->TestBit(TFileInfo::kStaged) &&
!fi->TestBit(TFileInfo::kCorrupted))) {
Int_t nf = fElements->GetSize();
if (!Add(fi, meta)) return kFALSE;
if (fElements->GetSize() <= nf && badlist) badlist->Add(fi);
} else if (badlist) {
badlist->Add(fi);
}
} else if (cn == "TUrl") {
Add(((TUrl *)o)->GetUrl());
} else if (cn == "TObjString") {
Add(((TObjString *)o)->GetName());
} else {
Warning("Add","found object fo unexpected type %s - ignoring", cn.Data());
}
}
return kTRUE;
}
void TDSet::SetSrvMaps(TList *srvmaps)
{
fSrvMaps = srvmaps;
SafeDelete(fSrvMapsIter);
if (fSrvMaps) fSrvMapsIter = new TIter(fSrvMaps);
}
Bool_t TDSet::Add(TFileInfo *fi, const char *meta)
{
if (!fi) {
Error("Add", "TFileInfo object name must be specified");
return kFALSE;
}
TString msg;
const char *file = fi->GetFirstUrl()->GetUrl();
Bool_t setLookedUp = kTRUE;
TString file1;
if (TDataSetManager::CheckDataSetSrvMaps(fi->GetFirstUrl(), file1, fSrvMaps) &&
!(file1.IsNull())) {
file = file1.Data();
setLookedUp = kFALSE;
}
if (fElements->FindObject(file)) {
msg.Form("duplication detected: %40s is already in dataset - ignored", file);
Warning("Add", "%s", msg.Data());
if (gProofServ) {
msg.Insert(0, "WARNING: ");
gProofServ->SendAsynMessage(msg);
}
return kTRUE;
}
TFileInfoMeta *m = 0;
if (!meta || strlen(meta) <= 0 || !strcmp(meta, "/")) {
TList *fil = 0;
if ((fil = fi->GetMetaDataList()) && fil->GetSize() > 1) {
msg.Form("\n Object name unspecified and several objects available.\n");
msg += " Please choose one from the list below:\n";
TIter nx(fil);
while ((m = (TFileInfoMeta *) nx())) {
TString nm(m->GetName());
if (nm.BeginsWith("/")) nm.Remove(0,1);
msg += Form(" %s -> TProof::Process(\"%s#%s\",...)\n",
nm.Data(), GetName(), nm.Data());
}
if (gProofServ)
gProofServ->SendAsynMessage(msg);
else
Warning("Add", "%s", msg.Data());
return kFALSE;
}
}
m = fi->GetMetaData(meta);
const char *objname = 0;
const char *dir = 0;
Long64_t first = 0;
Long64_t num = -1;
if (!m) {
objname = GetObjName();
dir = GetDirectory();
} else {
objname = (m->GetObject() && strlen(m->GetObject())) ? m->GetObject() : GetObjName();
dir = (m->GetDirectory() && strlen(m->GetDirectory())) ? m->GetDirectory() : GetDirectory();
first = m->GetFirst();
num = m->GetEntries();
}
const char *dataset = 0;
if (strcmp(fi->GetTitle(), "TFileInfo")) dataset = fi->GetTitle();
TDSetElement *el = new TDSetElement(file, objname, dir, first, -1, 0, dataset);
el->SetEntries(num);
if (fi->TestBit(TFileInfo::kStaged) && setLookedUp)
el->SetBit(TDSetElement::kHasBeenLookedUp);
if (fi->TestBit(TFileInfo::kCorrupted))
el->SetBit(TDSetElement::kCorrupted);
fElements->Add(el);
return kTRUE;
}
Int_t TDSet::ExportFileList(const char *fpath, Option_t *opt)
{
if (!fElements)
return -1;
if (fElements->GetSize() <= 0)
return 0;
Bool_t force = (opt[0] == 'F' || opt[0] == 'f');
if (gSystem->AccessPathName(fpath, kFileExists) == kFALSE) {
if (force) {
if (gSystem->Unlink(fpath)) {
Info("ExportFileList","error removing dataset file: %s", fpath);
return -1;
}
}
}
TList *fileinfo = new TList;
fileinfo->SetOwner();
TDSetElement *dse = 0;
TIter next(fElements);
while ((dse = (TDSetElement *) next())) {
TFileInfoMeta *m = new TFileInfoMeta(dse->GetTitle(), dse->GetDirectory(), GetType(),
dse->GetNum(), dse->GetFirst());
TFileInfo *fi = new TFileInfo(dse->GetFileName());
fi->AddMetaData(m);
fileinfo->Add(fi);
}
TFile *f = TFile::Open(fpath, "RECREATE");
if (f) {
f->cd();
fileinfo->Write("fileList", TObject::kSingleKey);
f->Close();
} else {
Info("ExportFileList","error creating dataset file: %s", fpath);
SafeDelete(fileinfo);
return -1;
}
SafeDelete(f);
SafeDelete(fileinfo);
return 0;
}
void TDSet::AddFriend(TDSet *friendset, const char* alias)
{
if (!friendset) {
Error("AddFriend", "The friend TDSet is null!");
return;
}
if (!fIsTree) {
Error("AddFriend", "a friend set can only be added to a TTree TDSet");
return;
}
TList *thisList = GetListOfElements();
TList *friendsList = friendset->GetListOfElements();
if (thisList->GetSize() != friendsList->GetSize() && friendsList->GetSize() != 1) {
Error("AddFriend", "the friend dataset has %d elements while the main one has %d",
thisList->GetSize(), friendsList->GetSize());
return;
}
TIter next(thisList);
TIter next2(friendsList);
TDSetElement *friendElem = 0;
if (friendsList->GetSize() == 1)
friendElem = dynamic_cast<TDSetElement*> (friendsList->First());
while(TDSetElement* e = dynamic_cast<TDSetElement*> (next())) {
if (friendElem)
e->AddFriend(friendElem, alias);
else
e->AddFriend(dynamic_cast<TDSetElement*> (next2()), alias);
}
}
void TDSet::Reset()
{
if (!fIterator) {
fIterator = new TIter(fElements);
} else {
fIterator->Reset();
}
}
Long64_t TDSet::GetEntries(Bool_t isTree, const char *filename, const char *path,
TString &objname)
{
Double_t start = 0;
if (gPerfStats) start = TTimeStamp();
TFile::EFileType typ = TFile::kDefault;
TString fname = gEnv->GetValue("Path.Localroot",""), pfx(fname);
Int_t oldLevel = gErrorIgnoreLevel;
gErrorIgnoreLevel = kError+1;
if ((typ = TFile::GetType(filename, "", &fname)) != TFile::kLocal) fname = filename;
gErrorIgnoreLevel = oldLevel;
TFile *file = TFile::Open(fname);
if (gPerfStats)
gPerfStats->FileOpenEvent(file, filename, start);
if (file == 0) {
::SysError("TDSet::GetEntries",
"cannot open file %s (type: %d, pfx: %s)", filename, typ, pfx.Data());
return -1;
}
TDirectory *dirsave = gDirectory;
if (!file->cd(path)) {
::Error("TDSet::GetEntries", "cannot cd to %s", path);
delete file;
return -1;
}
TDirectory *dir = gDirectory;
dirsave->cd();
Long64_t entries;
Bool_t fillname = kFALSE;
if (isTree) {
TString on(objname);
TString sreg(objname);
if (sreg.Length() <= 0 || sreg == "" || sreg.Contains("*")) {
fillname = kTRUE;
if (sreg.Contains("*"))
sreg.ReplaceAll("*", ".*");
else
sreg = ".*";
TRegexp re(sreg);
if (dir->GetListOfKeys()) {
TIter nxk(dir->GetListOfKeys());
TKey *k = 0;
Bool_t notfound = kTRUE;
while ((k = (TKey *) nxk())) {
if (!strcmp(k->GetClassName(), "TTree")) {
TString kn(k->GetName());
if (kn.Index(re) != kNPOS) {
if (notfound) {
on = kn;
notfound = kFALSE;
} else if (kn != on) {
::Warning("TDSet::GetEntries",
"additional tree found in the file: %s", kn.Data());
}
}
}
}
}
}
TKey *key = dir->GetKey(on);
if (key == 0) {
::Error("TDSet::GetEntries", "cannot find tree \"%s\" in %s",
objname.Data(), filename);
delete file;
return -1;
}
TTree *tree = (TTree *) key->ReadObj();
if (tree == 0) {
delete file;
return -1;
}
entries = tree->GetEntries();
delete tree;
objname = (fillname) ? on : objname;
} else {
TList *keys = dir->GetListOfKeys();
entries = keys->GetSize();
}
delete file;
return entries;
}
Long64_t TDSet::Draw(const char *varexp, const TCut &selection, Option_t *option,
Long64_t nentries, Long64_t firstentry)
{
return Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
}
Long64_t TDSet::Draw(const char *varexp, const char *selection, Option_t *option,
Long64_t nentries, Long64_t firstentry)
{
if (!IsValid() || !fElements->GetSize()) {
Error("Draw", "not a correctly initialized TDSet");
return -1;
}
if (gProof)
return gProof->DrawSelect(this, varexp, selection, option, nentries,
firstentry);
Error("Draw", "no active PROOF session");
return -1;
}
void TDSet::StartViewer()
{
if (gROOT->IsBatch()) {
Warning("StartViewer", "viewer cannot run in batch mode");
return;
}
if (!gProof) {
Error("StartViewer", "no PROOF found");
return;
}
if (!IsTree()) {
Error("StartViewer", "TDSet contents should be of type TTree (or subtype)");
return;
}
fProofChain = new TProofChain(this, kTRUE);
TPluginHandler *h;
if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer"))) {
if (h->LoadPlugin() == -1)
return;
h->ExecPlugin(1,fProofChain);
}
}
TTree* TDSet::GetTreeHeader(TProof* proof)
{
return proof->GetTreeHeader(this);
}
Bool_t TDSet::ElementsValid()
{
if (TestBit(TDSet::kValidityChecked))
return (TestBit(TDSet::kSomeInvalid) ? kFALSE : kTRUE);
SetBit(TDSet::kValidityChecked);
ResetBit(TDSet::kSomeInvalid);
TIter nextElem(GetListOfElements());
while (TDSetElement *elem = dynamic_cast<TDSetElement*>(nextElem())) {
if (!elem->GetValid()) {
SetBit(TDSet::kSomeInvalid);
return kFALSE;
}
}
return kTRUE;
}
Int_t TDSet::Remove(TDSetElement *elem, Bool_t deleteElem)
{
if (!elem || !(((THashList *)(GetListOfElements()))->Remove(elem)))
return -1;
if (deleteElem)
SafeDelete(elem);
return 0;
}
void TDSet::Validate()
{
TIter nextElem(GetListOfElements());
while (TDSetElement *elem = dynamic_cast<TDSetElement*>(nextElem())) {
if (!elem->GetValid())
elem->Validate(IsTree());
}
}
void TDSet::Lookup(Bool_t removeMissing, TList **listOfMissingFiles)
{
SplitEntryList();
TString msg("Looking up for exact location of files");
UInt_t n = 0;
UInt_t ng = 0;
UInt_t tot = GetListOfElements()->GetSize();
UInt_t n2 = (tot > 50) ? (UInt_t) tot / 50 : 1;
Bool_t st = kTRUE;
TIter nextElem(GetListOfElements());
while (TDSetElement *elem = dynamic_cast<TDSetElement*>(nextElem())) {
if (elem->GetNum() != 0) {
ng++;
if (!elem->GetValid())
if (elem->Lookup(kFALSE))
if (removeMissing) {
if (Remove(elem, kFALSE))
Error("Lookup", "Error removing a missing file");
if (listOfMissingFiles)
(*listOfMissingFiles)->Add(elem->GetFileInfo(fType));
}
}
n++;
if (gProof && (n > 0 && !(n % n2)))
gProof->SendDataSetStatus(msg, n, tot, st);
if (gProof && gProof->GetRunStatus() != TProof::kRunning)
break;
}
if (ng < tot && gProofServ) {
msg = Form("Files with entries to be processed: %d (out of %d)\n", ng, tot);
gProofServ->SendAsynMessage(msg);
} else {
if (gProof) gProof->SendDataSetStatus(msg, n, tot, st);
}
return;
}
void TDSet::SetLookedUp()
{
TIter nextElem(GetListOfElements());
while (TDSetElement *elem = dynamic_cast<TDSetElement*>(nextElem()))
elem->SetLookedUp();
}
void TDSet::Validate(TDSet* dset)
{
THashList bestElements;
bestElements.SetOwner();
TList namedHolder;
namedHolder.SetOwner();
TIter nextOtherElem(dset->GetListOfElements());
while (TDSetElement *elem = dynamic_cast<TDSetElement*>(nextOtherElem())) {
if (!elem->GetValid()) continue;
TString dir_file_obj = elem->GetDirectory();
dir_file_obj += "_";
dir_file_obj += TUrl(elem->GetFileName()).GetFileAndOptions();
dir_file_obj += "_";
dir_file_obj += elem->GetObjName();
TPair *p = dynamic_cast<TPair*>(bestElements.FindObject(dir_file_obj));
if (p) {
TDSetElement *prevelem = dynamic_cast<TDSetElement*>(p->Value());
if (prevelem) {
Long64_t entries = prevelem->GetFirst()+prevelem->GetNum();
if (entries<elem->GetFirst()+elem->GetNum()) {
bestElements.Remove(p);
bestElements.Add(new TPair(p->Key(), elem));
delete p;
}
}
} else {
TNamed* named = new TNamed(dir_file_obj, dir_file_obj);
namedHolder.Add(named);
bestElements.Add(new TPair(named, elem));
}
}
TIter nextElem(GetListOfElements());
while (TDSetElement *elem = dynamic_cast<TDSetElement*>(nextElem())) {
if (!elem->GetValid()) {
TString dir_file_obj = elem->GetDirectory();
dir_file_obj += "_";
dir_file_obj += TUrl(elem->GetFileName()).GetFileAndOptions();
dir_file_obj += "_";
dir_file_obj += elem->GetObjName();
if (TPair *p = dynamic_cast<TPair*>(bestElements.FindObject(dir_file_obj))) {
TDSetElement* validelem = dynamic_cast<TDSetElement*>(p->Value());
elem->Validate(validelem);
}
}
}
}
void TDSetElement::Streamer(TBuffer &R__b)
{
if (R__b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
ResetBit(kWriteV3);
if (R__v > 4) {
R__b.ReadClassBuffer(TDSetElement::Class(), this, R__v, R__s, R__c);
} else {
SetBit(kWriteV3);
if (R__v > 3) {
TNamed::Streamer(R__b);
} else {
TObject::Streamer(R__b);
TString name, title;
R__b >> name >> title;
SetNameTitle(name, title);
}
R__b >> fDirectory;
R__b >> fFirst;
R__b >> fNum;
R__b >> fMsd;
R__b >> fTDSetOffset;
TEventList *evl;
R__b >> evl;
R__b >> fValid;
R__b >> fEntries;
FriendsList_t *friends = new FriendsList_t;
static TClassRef classFriendsList = TClass::GetClass(typeid(FriendsList_t));
R__b.ReadClassBuffer( classFriendsList, friends, classFriendsList->GetClassVersion(), 0, 0);
if (friends) {
fFriends = new TList();
fFriends->SetOwner();
for (FriendsList_t::iterator i = friends->begin();
i != friends->end(); ++i) {
TDSetElement *dse = (TDSetElement *) i->first->Clone();
fFriends->Add(new TPair(dse, new TObjString(i->second.Data())));
}
}
Bool_t tmpIsTree;
R__b >> tmpIsTree;
R__b.CheckByteCount(R__s, R__c, TDSetElement::IsA());
}
} else {
if (TestBit(kWriteV3)) {
R__b << Version_t(3);
TObject::Streamer(R__b);
R__b << TString(GetName());
R__b << TString(GetTitle());
R__b << fDirectory;
R__b << fFirst;
R__b << fNum;
R__b << fMsd;
R__b << fTDSetOffset;
R__b << (TEventList *)0;
R__b << fValid;
R__b << fEntries;
FriendsList_t *friends = new FriendsList_t;
if (fFriends) {
TIter nxf(fFriends);
TPair *p = 0;
while ((p = (TPair *)nxf()))
friends->push_back(std::make_pair((TDSetElement *)p->Key(),
TString(((TObjString *)p->Value())->GetName())));
}
static TClassRef classFriendsList = TClass::GetClass(typeid(FriendsList_t));
R__b.WriteClassBuffer( classFriendsList, &friends );
R__b << kFALSE;
} else {
R__b.WriteClassBuffer(TDSetElement::Class(),this);
}
}
}
void TDSet::Streamer(TBuffer &R__b)
{
if (R__b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
ResetBit(kWriteV3);
if (R__v > 3) {
R__b.ReadClassBuffer(TDSet::Class(), this, R__v, R__s, R__c);
} else {
SetBit(kWriteV3);
TNamed::Streamer(R__b);
R__b >> fDir;
R__b >> fType;
R__b >> fObjName;
TList elems;
elems.Streamer(R__b);
elems.SetOwner(kFALSE);
if (elems.GetSize() > 0) {
fElements = new THashList;
fElements->SetOwner();
TDSetElement *e = 0;
TIter nxe(&elems);
while ((e = (TDSetElement *)nxe())) {
fElements->Add(e);
}
} else {
fElements = 0;
}
R__b >> fIsTree;
}
} else {
if (TestBit(kWriteV3)) {
R__b << Version_t(3);
TNamed::Streamer(R__b);
R__b << fDir;
R__b << fType;
R__b << fObjName;
TList elems;
if (fElements) {
elems.SetOwner(kFALSE);
if (fElements->GetSize() > 0) {
TDSetElement *e = 0;
TIter nxe(fElements);
while ((e = (TDSetElement *)nxe()))
elems.Add(e);
}
}
elems.Streamer(R__b);
R__b << fIsTree;
} else {
R__b.WriteClassBuffer(TDSet::Class(),this);
}
}
}
void TDSet::SetWriteV3(Bool_t on)
{
if (on)
SetBit(TDSet::kWriteV3);
else
ResetBit(TDSet::kWriteV3);
TIter nxe(GetListOfElements());
TObject *o = 0;
while ((o = nxe()))
if (on)
o->SetBit(TDSetElement::kWriteV3);
else
o->ResetBit(TDSetElement::kWriteV3);
}
void TDSet::SetEntryList(TObject *aList)
{
if (!aList)
return;
if (TestBit(TDSet::kMultiDSet)) {
TIter nxds(fElements);
TDSet *ds = 0;
while ((ds = (TDSet *) nxds()))
ds->SetEntryList(aList);
} else {
TEventList *evl = 0;
TEntryList *enl = dynamic_cast<TEntryList*>(aList);
if (!enl)
evl = dynamic_cast<TEventList*>(aList);
if (!enl && !evl) {
Error("SetEntryList", "type of input object must be either TEntryList "
"or TEventList (found: '%s' - do nothing", aList->ClassName());
return;
}
fEntryList = (enl) ? enl : (TEntryList *)evl;
}
return;
}
void TDSet::SplitEntryList()
{
if (TestBit(TDSet::kMultiDSet)) {
TIter nxds(fElements);
TDSet *ds = 0;
while ((ds = (TDSet *) nxds()))
ds->SplitEntryList();
return;
}
if (!fEntryList) {
if (gDebug > 0)
Info("SplitEntryList", "no entry- (or event-) list to split - do nothing");
return;
}
TEntryList *enl = dynamic_cast<TEntryList *>(fEntryList);
if (enl) {
TIter next(fElements);
TDSetElement *el=0;
TEntryList *sublist = 0;
while ((el=(TDSetElement*)next())){
sublist = enl->GetEntryList(el->GetObjName(), el->GetFileName());
if (sublist){
el->SetEntryList(sublist);
el->SetNum(sublist->GetN());
} else {
sublist = new TEntryList("", "");
el->SetEntryList(sublist);
el->SetNum(0);
}
}
} else {
TEventList *evl = dynamic_cast<TEventList *>(fEntryList);
if (evl) {
TIter next(fElements);
TDSetElement *el, *prev;
prev = dynamic_cast<TDSetElement*> (next());
if (!prev)
return;
Long64_t low = prev->GetTDSetOffset();
Long64_t high = low;
Long64_t currPos = 0;
do {
el = dynamic_cast<TDSetElement*> (next());
high = (el == 0) ? kMaxLong64 : el->GetTDSetOffset();
#ifdef DEBUG
while (currPos < evl->GetN() && evl->GetEntry(currPos) < low) {
Error("SplitEntryList",
"TEventList: event outside of the range of any of the TDSetElements");
currPos++;
}
#endif
TEventList* nevl = new TEventList();
while (currPos < evl->GetN() && evl->GetEntry((Int_t)currPos) < high) {
nevl->Enter(evl->GetEntry((Int_t)currPos) - low);
currPos++;
}
prev->SetEntryList(nevl);
prev->SetNum(nevl->GetN());
low = high;
prev = el;
} while (el);
}
}
}
Int_t TDSet::GetNumOfFiles()
{
Int_t nf = -1;
if (fElements) {
nf = 0;
if (TestBit(TDSet::kMultiDSet)) {
TIter nxds(fElements);
TDSet *ds = 0;
while ((ds = (TDSet *) nxds()))
if (ds->GetListOfElements()) nf += ds->GetListOfElements()->GetSize();
} else {
nf = fElements->GetSize();
}
}
return nf;
}