#include "TProofOutputFile.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(TProofOutputFile)
TProofOutputFile::TProofOutputFile(const char* path,
const char* location, const char* mode)
: TNamed(path,"")
{
fMerged = kFALSE;
fMerger = 0;
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 dirPath = gSystem->WorkingDirectory();
if (gSystem->Getenv("XRDCF")) {
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());
}
if (!pfx.IsNull())
dirPath.Remove(0, pfx.Length());
} else {
fDir += "/";
}
fDir += Form("/%s", dirPath.Data());
}
Info("TProofOutputFile", "dir: %s", fDir.Data());
fOutputFileName = gEnv->GetValue("Proof.OutputFile", "");
if (!fOutputFileName.IsNull() && !fOutputFileName.EndsWith("/"))
fOutputFileName += "/";
fOutputFileName += path;
if (!fOutputFileName.EndsWith(".root"))
fOutputFileName += ".root";
ResolveKeywords(fOutputFileName);
Info("TProofOutputFile", "output file url: %s", fOutputFileName.Data());
fLocation = "REMOTE";
if (location && strlen(location) > 0) {
fLocation = location;
if (fLocation.CompareTo("LOCAL", TString::kIgnoreCase) &&
fLocation.CompareTo("REMOTE", TString::kIgnoreCase)) {
Warning("TProofOutputFile","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("TProofOutputFile","unknown mode %s: ignore (use: \"CENTRAL\")", mode);
fMode = "CENTRAL";
}
fMode.ToUpper();
}
}
TProofOutputFile::~TProofOutputFile()
{
if (fMerger) delete fMerger;
}
TString TProofOutputFile::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 TProofOutputFile::SetFileName(const char* name)
{
fFileName = name;
fFileName1 = GetTmpName(name);
}
void TProofOutputFile::SetOutputFileName(const char *name)
{
if (name && strlen(name) > 0) {
fOutputFileName = name;
ResolveKeywords(fOutputFileName);
Info("SetOutputFileName", "output file url: %s", fOutputFileName.Data());
} else {
fOutputFileName = "";
}
}
void TProofOutputFile::ResolveKeywords(TString &fname)
{
if (fname.Contains("<user>")) {
TString user = "nouser";
UserGroup_t *pw = gSystem->GetUserInfo();
if (pw) {
user = pw->fUser;
delete pw;
}
fname.ReplaceAll("<user>", user);
}
if (fname.Contains("<group>")) {
if (gProofServ && gProofServ->GetGroup() && strlen(gProofServ->GetGroup()))
fname.ReplaceAll("<group>", gProofServ->GetGroup());
else
fname.ReplaceAll("<group>", "default");
}
}
TFile* TProofOutputFile::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;
}
Int_t TProofOutputFile::AdoptFile(TFile *f)
{
if (!f || f->IsZombie())
return -1;
TUrl u(*(f->GetEndpointUrl()));
fIsLocal = kFALSE;
if (!strcmp(u.GetProtocol(), "file")) {
fIsLocal = kTRUE;
fDir = u.GetFile();
} else {
fDir = u.GetUrl();
}
fFileName1 = gSystem->BaseName(fDir.Data());
fFileName = fFileName1;
fDir.ReplaceAll(fFileName1, "");
return 0;
}
Long64_t TProofOutputFile::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);
TProofOutputFile* pFile = 0;
while ((pFile = (TProofOutputFile*)next())) {
fileLoc = Form("%s/%s", pFile->GetDir(), pFile->GetFileName());
AddFile(merger, fileLoc);
}
Bool_t result = merger->Merge();
if (!result) {
NotifyError("TProofOutputFile::Merge: error from TFileMerger::Merge()");
return -1;
}
if (!fMerged) {
fileLoc = Form("%s/%s", fDir.Data(), GetFileName());
Unlink(fileLoc);
fMerged = kTRUE;
}
next.Reset();
while ((pFile = (TProofOutputFile*)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);
TProofOutputFile* pFile = 0;
while ((pFile = (TProofOutputFile*)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("TProofOutputFile::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 = (TProofOutputFile *)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);
TProofOutputFile* pFile = 0;
while((pFile = (TProofOutputFile*)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 TProofOutputFile::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 TProofOutputFile::NotifyError(const char *msg)
{
if (msg) {
if (gProofServ)
gProofServ->SendAsynMessage(msg);
else
Printf(msg);
} else {
Info("NotifyError","called with empty message");
}
return;
}
void TProofOutputFile::AddFile(TFileMerger *merger, const char *path)
{
if (merger && path) {
if (!merger->AddFile(path))
NotifyError(Form("TProofOutputFile::AddFile:"
" error from TFileMerger::AddFile(%s)", path));
}
}
void TProofOutputFile::Unlink(const char *path)
{
if (path) {
if (!gSystem->AccessPathName(path)) {
if (gSystem->Unlink(path) != 0)
NotifyError(Form("TProofOutputFile::Unlink:"
" error from TSystem::Unlink(%s)", path));
}
}
}
TFileMerger *TProofOutputFile::GetFileMerger(Bool_t local)
{
if (!fMerger)
fMerger = new TFileMerger(local);
return fMerger;
}
Last change: Mon Oct 27 08:03:23 2008
Last generated: 2008-10-27 08:03
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.