#include "TProofFile.h"
#include <TEnv.h>
#include <TFileMerger.h>
#include <TFile.h>
#include <TList.h>
#include <TObjArray.h>
#include <TObject.h>
#include <TObjString.h>
#include <TProofServ.h>
#include <TSystem.h>
#include <TUUID.h>
ClassImp(TProofFile)
TFileMerger *TProofFile::fgMerger = 0;
TProofFile::TProofFile(const char* path, const char* location, const char* mode)
: TNamed(path,"")
{
fMerged = kFALSE;
TUrl u(path, kTRUE);
fFileName = u.GetFile();
fFileName1 = GetTmpName(fFileName.Data());
fIsLocal = kFALSE;
fDir = u.GetUrl();
Int_t pos = fDir.Index(fFileName);
if (pos != kNPOS)
fDir.Remove(pos);
if (fDir == "file:") {
fIsLocal = kTRUE;
TString pfx = gEnv->GetValue("Path.Localroot","");
fDir = Form("root://%s",gSystem->HostName());
if (gSystem->Getenv("XRDPORT")) {
TString sp(gSystem->Getenv("XRDPORT"));
if (sp.IsDigit())
fDir += Form(":%s", sp.Data());
}
TString dirPath = gSystem->WorkingDirectory();
if (!pfx.IsNull())
dirPath.Remove(0, pfx.Length());
fDir += Form("/%s", dirPath.Data());
}
if (gDebug > 1)
Info("TProofFile", "dir: %s", fDir.Data());
fLocation = "REMOTE";
if (location && strlen(location) > 0) {
fLocation = location;
if (fLocation.CompareTo("LOCAL", TString::kIgnoreCase) &&
fLocation.CompareTo("REMOTE", TString::kIgnoreCase)) {
Warning("TProofFile","unknown location %s: ignore (use: \"REMOTE\")", location);
fLocation = "REMOTE";
}
fLocation.ToUpper();
}
fMode = "CENTRAL";
if (mode && strlen(mode) > 0) {
fMode = mode;
if (fMode.CompareTo("CENTRAL", TString::kIgnoreCase) &&
fMode.CompareTo("SEQUENTIAL", TString::kIgnoreCase)) {
Warning("TProofFile","unknown mode %s: ignore (use: \"CENTRAL\")", mode);
fMode = "CENTRAL";
}
fMode.ToUpper();
}
}
TString TProofFile::GetTmpName(const char* name)
{
TUUID uuid;
TString tmpName(name);
Ssiz_t pos = tmpName.Last('.');
if (pos != kNPOS)
tmpName.Insert(pos,Form("-%s",uuid.AsString()));
else
tmpName += Form("-%s",uuid.AsString());
return tmpName;
}
void TProofFile::SetFileName(const char* name)
{
fFileName = name;
fFileName1 = GetTmpName(name);
}
void TProofFile::SetOutputFileName(const char *name)
{
if (name && strlen(name) > 0) {
fOutputFileName = name;
} else {
fOutputFileName = "";
}
}
TFile* TProofFile::OpenFile(const char* opt)
{
if (fFileName1.IsNull())
return 0;
TString fileLoc = (fIsLocal || fDir.IsNull()) ? fFileName1
: Form("%s/%s", fDir.Data(), fFileName1.Data());
TFile *retFile = TFile::Open(fileLoc, opt);
return retFile;
}
Long64_t TProofFile::Merge(TCollection* list)
{
if(!list || list->IsEmpty())
return 0;
TString fileLoc;
TString outputFileLoc = (fOutputFileName.IsNull()) ? fFileName : fOutputFileName;
if (fMode == "SEQUENTIAL") {
TFileMerger* merger = new TFileMerger;
if (fLocation == "LOCAL") {
merger->OutputFile(outputFileLoc);
if (!fMerged) {
fileLoc = Form("%s/%s", fDir.Data(), GetFileName());
AddFile(merger, fileLoc);
Unlink(outputFileLoc);
} else {
AddFile(merger, outputFileLoc);
Unlink(outputFileLoc);
}
TList* elist = new TList;
elist->AddAll(list);
TIter next(elist);
TProofFile* pFile = 0;
while ((pFile = (TProofFile*)next())) {
fileLoc = Form("%s/%s", pFile->GetDir(), pFile->GetFileName());
AddFile(merger, fileLoc);
}
Bool_t result = merger->Merge();
if (!result) {
NotifyError("TProofFile::Merge: error from TFileMerger::Merge()");
return -1;
}
if (!fMerged) {
fileLoc = Form("%s/%s", fDir.Data(), GetFileName());
Unlink(fileLoc);
fMerged = kTRUE;
}
next.Reset();
while ((pFile = (TProofFile*)next())) {
fileLoc = Form("%s/%s", pFile->GetDir(), pFile->GetFileName());
Unlink(fileLoc);
}
} else if (fLocation == "REMOTE") {
TString outputFileLoc2 = GetTmpName(fOutputFileName);
TString tmpOutputLoc = (outputFileLoc.BeginsWith("root://")) ? GetTmpName(fFileName) : "";
TList* fileList = new TList;
if (!fMerged) {
fileLoc = Form("%s/%s", fDir.Data(), GetFileName());
TFile* fCurrFile = TFile::Open(fileLoc,"READ");
if (!fCurrFile) {
Warning("Merge","Cannot open file: %s", fileLoc.Data());
} else {
fileList->Add(fCurrFile);
Info("Merge", "now adding file :%s\n", fCurrFile->GetPath());
}
Unlink(outputFileLoc);
} else {
if (tmpOutputLoc.IsNull()) {
gSystem->Rename(outputFileLoc,outputFileLoc2);
} else {
TFile::Cp(outputFileLoc, outputFileLoc2);
Unlink(outputFileLoc);
}
TFile* fCurrOutputFile = TFile::Open(outputFileLoc2,"READ");
if (!fCurrOutputFile) {
Warning("Merge","Cannot open tmp output file: %s", outputFileLoc2.Data());
} else {
fileList->Add(fCurrOutputFile);
}
}
TList* elist = new TList;
elist->AddAll(list);
TIter next(elist);
TProofFile* pFile = 0;
while ((pFile = (TProofFile*)next())) {
fileLoc = Form("%s/%s", pFile->GetDir(), pFile->GetFileName());
TFile* fCurrFile = TFile::Open(fileLoc.Data(),"READ");
if (!fCurrFile) {
Warning("Merge","Cannot open file: %s", fileLoc.Data());
continue;
} else {
fileList->Add(fCurrFile);
}
}
TFile* outputFile;
if (tmpOutputLoc.IsNull()) {
outputFile = TFile::Open(outputFileLoc, "RECREATE");
} else {
outputFile = TFile::Open(tmpOutputLoc,"RECREATE");
}
if (!outputFile) {
Error("Merge","cannot open output file %s",outputFileLoc.Data());
return -1;
}
Bool_t result = merger->MergeRecursive(outputFile, fileList, 0);
if (!result) {
NotifyError("TProofFile::Merge: error from TFileMerger::MergeRecursive()");
TIter fnext(fileList);
TFile *fCurrFile = 0;
while ((fCurrFile = (TFile*)fnext())) {
fCurrFile->Close();
}
return -1;
} else {
outputFile->Write();
outputFile->Close();
TIter fnext(fileList);
TFile *fCurrFile = 0;
while ((fCurrFile = (TFile*)fnext())) {
fCurrFile->Close();
}
if (!fMerged) {
fileLoc = Form("%s/%s", fDir.Data(), GetFileName());
Unlink(fileLoc);
fMerged = kTRUE;
}
next.Reset();
while ((pFile = (TProofFile *)next())) {
fileLoc = Form("%s/%s", pFile->GetDir(), pFile->GetFileName());
Unlink(fileLoc);
}
Unlink(outputFileLoc2);
if (!tmpOutputLoc.IsNull()) {
TFile::Cp(tmpOutputLoc,outputFileLoc);
Unlink(tmpOutputLoc);
}
}
} else {
Error("Merge", "invalid location value: %s", fLocation.Data());
return -1;
}
SafeDelete(merger);
} else if (fMode == "CENTRAL") {
if (fLocation != "REMOTE" && fLocation != "LOCAL") {
Error("Merge", "invalid location value: %s", fLocation.Data());
return -1;
}
Bool_t isLocal = (fLocation == "REMOTE") ? kFALSE : kTRUE;
TFileMerger *merger = GetFileMerger(isLocal);
if (!merger) {
Error("Merge", "could not instantiate the file merger");
return -1;
}
if (!fMerged) {
merger->OutputFile(outputFileLoc);
Unlink(outputFileLoc);
fileLoc = Form("%s/%s", fDir.Data(), GetFileName());
AddFile(merger, fileLoc);
fMerged = kTRUE;
}
TList* elist = new TList;
elist->AddAll(list);
TIter next(elist);
TProofFile* pFile = 0;
while((pFile = (TProofFile*)next())) {
fileLoc = Form("%s/%s", pFile->GetDir(), pFile->GetFileName());
AddFile(merger, fileLoc);
}
} else {
Error("Merge", "invalid mode value: %s", fMode.Data());
return -1;
}
return 0;
}
void TProofFile::Print(Option_t *) const
{
Info("Print","-------------- %s : start ------------", GetName());
Info("Print"," dir: %s", fDir.Data());
Info("Print"," file name: %s", fFileName.Data());
Info("Print"," location: %s", fLocation.Data());
Info("Print"," mode: %s", fMode.Data());
Info("Print"," output file name: %s", fOutputFileName.Data());
Info("Print"," ordinal: %s", fWorkerOrdinal.Data());
Info("Print","-------------- %s : done -------------", GetName());
return;
}
void TProofFile::NotifyError(const char *msg)
{
if (msg) {
if (gProofServ)
gProofServ->SendAsynMessage(msg);
else
Printf(msg);
} else {
Info("NotifyError","called with empty message");
}
return;
}
void TProofFile::AddFile(TFileMerger *merger, const char *path)
{
if (merger && path) {
if (!merger->AddFile(path))
NotifyError(Form("TProofFile::AddFile:"
" error from TFileMerger::AddFile(%s)", path));
}
}
void TProofFile::Unlink(const char *path)
{
if (path) {
if (!gSystem->AccessPathName(path)) {
if (gSystem->Unlink(path) != 0)
NotifyError(Form("TProofFile::Unlink:"
" error from TSystem::Unlink(%s)", path));
}
}
}
TFileMerger *TProofFile::GetFileMerger(Bool_t local)
{
if (!fgMerger)
fgMerger = new TFileMerger(local);
return fgMerger;
}
Last update: Thu Jan 17 09:01:46 2008
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.