3 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4 * @date Tue Oct 16 18:58:37 2012
9 * @ingroup pwglf_forward_trains_helper
16 # include "OutputUtilities.C"
17 # include "ParUtilities.C"
18 # include "ChainBuilder.C"
22 # include <TProofLog.h>
23 # include <TProofDebug.h>
24 # include <AliAnalysisManager.h>
37 // ===================================================================
39 * Handle analysis on a Proof farm.
41 * This helper is triggered by URIs of the form
44 * proof://[<user>@]<host>[:<port>]/<dsname>[?<options>][#<treename>]
48 * <dt><user></dt>
49 * <dd>Optional user name</dd>
50 * <dt><host></dt>
51 * <dd>PROOF cluster master host</dd>
52 * <dt><port></dt>
53 * <dd>Optional PROOF cluster port on master host</dd>
54 * <dt><dsname></dt>
55 * <dd>Data set name</dd>
56 * <dt><treename></dt>
57 * <dd>Optional tree name in data set, often <tt>esdTree</tt> or
58 * <tt>aodTree</tt></dd>
59 * <dt><options></dt>
60 * <dd>List of options separated by an &
62 * <dt><tt>workers=N[x]</tt></dt>
63 * <dd>Set the number of workers to use. If <tt>x</tt> is appended,
64 * then it's maximum number of workers per slave</dd>
65 * <dt><tt>dsname</tt>[=<output dataset>]</dt>
66 * <dd>Register tree output (e.g., AOD) as a new data set on the
67 * PROOF cluster. If <output dataset> is not specified, take
68 * the name of the train.</dd>
69 * <dt><tt>par[=all]</tt></dt>
70 * <dd>Use PAR files. If the value <tt>all</tt> is given, then also
71 * PAR files of STEERBase, ESD, AOD, ANALYSIS, OADB, ANALYSISalice
73 * <dt><tt>mode=[default,rec,sim,train,custom]</tt></dt>
74 * <dd>Set the AliROOT mode. If not specified <tt>default</tt>
75 * is assumed. See also CreateAliROOTPar</dd>
76 * <dt><tt>storage=<url></tt></dt>
77 * <dd>Specify a non-default storage location for special output
78 * (e.g., AOD trees). <url> should be a valid XRootd
79 * server URI accessible to the slaves - e.g.,
80 * <tt>root://lxplus.cern.ch:10930//tmp</tt>.</dd>
85 * @ingroup pwglf_forward_trains_helper
87 struct ProofRailway : public Railway
93 * @param verbose Verbosity level
95 ProofRailway(const TUrl& url, Int_t verbose)
96 : Railway(url, verbose),
105 fOptions.Add("workers", "N[x]", "Number of workers to use", 0);
106 fOptions.Add("dsname", "NAME", "Make output dataset", "");
107 fOptions.Add("par", "tasks|all", "Use par files", "tasks");
108 fOptions.Add("mode", "default|rec|sim", "AliROOT mode", "default");
109 fOptions.Add("storage", "URL", "Location for external storage", "");
110 fOptions.Add("wrapper", "CMD", "Wrapper command", "");
111 fOptions.Add("clear", "PKGS", "Clear packages ','-separated", "");
112 fOptions.Add("reset", "soft|hard", "Reset cluster", "hard");
113 fOptions.Add("feedback", "Enable feedback mechanism");
114 fOptions.Add("env", "SCRIPT", "Script to set-up environment","-none-");
115 fOptions.Add("offset", "EVENTS", "Skip this number of events", 0);
116 fOptions.Add("testpar", "Test build PARs");
117 if (!fUrl.GetUser() || fUrl.GetUser()[0] == '\0')
118 fUrl.SetUser(gSystem->GetUserInfo()->fUser);
119 fAuxFiles.SetOwner();
121 ProofRailway(const ProofRailway& o)
131 ProofRailway& operator=(const ProofRailway& o)
133 if (&o == this) return *this;
134 Railway::operator=(o);
135 fExtraLibs = o.fExtraLibs;
136 fExtraPars = o.fExtraPars;
137 fExtraSrcs = o.fExtraSrcs;
138 fUsePars = o.fUsePars;
139 fBasePars = o.fBasePars;
140 fTestBuild = o.fTestBuild;
147 virtual ~ProofRailway() {}
149 * Load a library/PAR/script
152 * @param slaves If true, also load on slaves
154 * @return true on success
156 virtual Bool_t LoadLibrary(const TString& name,
159 Bool_t isBase = false;
161 if (name.EqualTo("STEERBase") ||
162 name.EqualTo("ESD") ||
163 name.EqualTo("AOD") ||
164 name.EqualTo("ANALYSIS") ||
165 name.EqualTo("OADB") ||
166 name.EqualTo("ANALYSISalice"))
169 if (!fUsePars || isBase) {
170 Int_t ret = gSystem->Load(MakeLibraryName(name));
171 if (ret < 0) return false;
172 if (slaves) fExtraLibs.Append(Form(":%s", name.Data()));
175 if (!ParUtilities::Find(name)) {
176 Error("ProofRailway::LoadLibrary", "Failed to find PAR file %s",
180 if (fTestBuild && !ParUtilities::Build(name)) {
181 Error("ProofRailway::LoadLibrary", "Failed to build PAR file %s",
185 if (gProof->UploadPackage(name.Data(), TProof::kRemoveOld) < 0) {
186 Error("ProofRailway::LoadLibrary", "Failed to upload PAR file %s",
190 fExtraPars.Append(Form(":%s", name.Data()));
195 * Load a source file, and compile it
197 * @param name Name of the source file
198 * @param copy If true, copy not link
200 * @return true on success
202 virtual Bool_t LoadSource(const TString& name, bool copy=false)
204 if (!Railway::LoadSource(name, copy)) return false;
205 fExtraSrcs.Append(Form(":%s", gSystem->BaseName(name.Data())));
209 * Set-up to load the AliROOT libraries
211 * @return true on success
213 virtual Bool_t LoadAliROOT()
215 if (!gSystem->Getenv("ALICE_ROOT")) {
216 Error("ProofRailway::LoadAliROOT", "Local AliROOT not available");
220 Bool_t tmp = fUsePars;
221 fUsePars = fBasePars;
222 if (!LoadLibrary("STEERBase")) return false;
223 if (!LoadLibrary("ESD")) return false;
224 if (!LoadLibrary("AOD")) return false;
225 if (!LoadLibrary("ANALYSIS")) return false;
226 if (!LoadLibrary("OADB")) return false;
227 if (!LoadLibrary("ANALYSISalice")) return false;
230 return CreateAliROOTPar();
233 * Get the name of the AliROOT par file to use
237 virtual const char* AliROOTParName() const
242 * Create an AliROOT par file from the executing AliROOT. This PAR
243 * file basically uses the environment of the client - that is, we
244 * assume that the used AliROOT is accessible on the slaves - e.g.,
247 * Note, the SETUP.C script take one argument - a TList of TNamed
248 * parameters. Parameters processed are
250 * - ALIROOT_MODE=[default,aliroot,rec,sim,train]
251 * - default: Load base analysis libraries
252 * - aliroot: Load $ALICE_ROOT/macros/loadlibs.C
253 * - rec: Load $ALICE_ROOT/macros/loadlibsrec.C
254 * - sim: Load $ALICE_ROOT/macros/loadlibssim.C
255 * - ALIROOT_EXTRA_LIBS Colon separated list of additional (Ali)ROOT
256 * libraries to load on the slaves.
258 * The generated PAR file is uploaded but not enabled until we have
259 * populated fExtraLibs. The enabling takes place at the end of the
262 * @return true on success, false otherwise. */
263 virtual Bool_t CreateAliROOTPar()
265 if (fBasePars) return true;
267 TString parName(AliROOTParName());
268 TString parFile(Form("%s.par", parName.Data()));
270 // --- Check if we have the drirectory already -------------------
271 if (gSystem->AccessPathName(parName.Data()) == 0) {
272 // Let's remove it to get a clean slate
273 if (gSystem->Exec(Form("rm -rf %s", parName.Data())) != 0) {
274 Error("ProofRailway", "Failed to remove %s", parName.Data());
278 // --- Check if the PAR file is there, and remove it if so -------
279 if (gSystem->AccessPathName(parFile.Data()) == 0) {
280 if (gSystem->Unlink(parFile.Data()) != 0) {
281 Error("ProofRailway::CreateAliROOTPar", "Failed to remove %s",
288 // Set-up directories
289 if (gSystem->MakeDirectory(parName) < 0) {
290 Error("ProofRailway::CreateAliROOTPar", "Could not make directory '%s'",
295 if (gSystem->MakeDirectory(Form("%s/PROOF-INF", parName.Data()))) {
296 Error("ProofRailway::CreateAliROOTPar",
297 "Could not make directory %s/PROOF-INF",
302 std::ofstream b(Form("%s/PROOF-INF/BUILD.sh",parName.Data()));
304 Error("ProofRailway::CreateAliROOTPar",
305 "Failed to make BUILD.sh shell script");
309 << "# echo Nothing to do\n"
313 gSystem->Exec(Form("chmod a+x %s/PROOF-INF/BUILD.sh",parName.Data()));
315 TString envScript = fOptions.Get("env");
316 if (envScript.EqualTo("-none-", TString::kIgnoreCase))
318 if (!envScript.IsNull()) {
319 // If an environment script was specified, copy that to the par
320 if (gSystem->AccessPathName(envScript.Data()) == 0) {
322 if (gSystem->Exec(Form("cp %s %s/PROOF-INF/", envScript.Data(),
323 parName.Data())) != 0) {
324 Error("ProofRailway", "Failed to copy %s", envScript.Data());
329 Warning("CreateALIROOTPar", "Couldn't read %s", envScript.Data());
333 std::ofstream s(Form("%s/PROOF-INF/SETUP.C", parName.Data()));
335 Error("ProofRailway::CreateAliROOTPar",
336 "Failed to make SETUP.C ROOT script");
339 s << "void SETUP(TList* opts) {\n";
340 if (envScript.IsNull()) {
341 s << " gSystem->Setenv(\"ALICE\",\""
342 << gSystem->Getenv("ALICE") << "\");\n"
343 << " gSystem->Setenv(\"ALICE_ROOT\",\""
344 << gSystem->Getenv("ALICE_ROOT") << "\");\n"
345 << " gSystem->Setenv(\"ALICE_TARGET\",\""
346 << gSystem->Getenv("ALICE_TARGET") << "\");\n";
347 if (gSystem->Getenv("OADB_PATH"))
348 s << " gSystem->Setenv(\"OADB_PATH\",\""
349 << gSystem->Getenv("OADB_PATH") << "\");\n";
352 s << " gROOT->Macro(\"PROOF-INF/" << gSystem->BaseName(envScript.Data())
355 s << " gSystem->AddDynamicPath("
356 << "\"$(ALICE_ROOT)/lib/tgt_$(ALICE_TARGET)\");\n";
358 << " // Info(\"SETUP\",\"Loading ROOT libraries\");\n"
359 << " gSystem->Load(\"libTree\");\n"
360 << " gSystem->Load(\"libGeom\");\n"
361 << " gSystem->Load(\"libVMC\");\n"
362 << " gSystem->Load(\"libPhysics\");\n"
363 << " gSystem->Load(\"libMinuit\");\n"
365 s << " // Info(\"SETUP\",\"Parameter list:\");\n"
366 << " if (!opts) return;\n"
367 << " //opts->ls();\n"
369 s << " TObject* par = opts->FindObject(\"ALIROOT_MODE\");\n"
371 << " // Info(\"SETUP\",\"ALIROOT mode: %s\", par->GetTitle());\n"
372 << " TString mode(par->GetTitle());\n"
373 << " if (mode.EqualTo(\"default\",TString::kIgnoreCase)) {\n"
374 << " gSystem->Load(\"libSTEERBase\");\n"
375 << " gSystem->Load(\"libESD\");\n"
376 << " gSystem->Load(\"libAOD\");\n"
377 << " gSystem->Load(\"libANALYSIS\");\n"
378 << " gSystem->Load(\"libOADB\");\n"
379 << " gSystem->Load(\"libANALYSISalice\");\n"
381 << " else if (mode.EqualTo(\"aliroot\",TString::kIgnoreCase)) \n"
382 << " gROOT->Macro(\"$ALICE_ROOT/macros/loadlibs.C\");\n"
383 << " else if (mode.EqualTo(\"rec\",TString::kIgnoreCase)) \n"
384 << " gROOT->Macro(\"$ALICE_ROOT/macros/loadlibsrec.C\");\n"
385 << " else if (mode.EqualTo(\"sim\",TString::kIgnoreCase)) \n"
386 << " gROOT->Macro(\"$ALICE_ROOT/macros/loadlibssim.C\");\n"
387 << " else if (mode.EqualTo(\"train\",TString::kIgnoreCase)) \n"
388 << " gROOT->Macro(\"$ALICE_ROOT/macros/loadlibstrain.C\");\n"
389 << " else if (mode.EqualTo(\"custom\",TString::kIgnoreCase)) \n"
390 << " gROOT->Macro(\"$ALICE_ROOT/macros/loadlibstrain.C\");\n"
393 s << " par = opts->FindObject(\"ALIROOT_EXTRA_LIBS\");\n"
395 << " Info(\"SETUP\",\"Libaries to load: %s\\n\",par->GetTitle());\n"
396 << " TString tit(par->GetTitle());\n"
397 << " TObjArray* tokens = tit.Tokenize(\":\");\n"
398 << " TObject* lib = 0;\n"
399 << " TIter next(tokens);\n"
400 << " while ((lib = next())) {\n"
401 << " TString libName(lib->GetName());\n"
402 << " if (!libName.BeginsWith(\"lib\")) libName.Prepend(\"lib\");\n"
403 << " // Info(\"SETUP\",\"Loading %s ...\",libName.Data());\n"
404 << " gSystem->Load(libName.Data());\n"
411 Int_t ret = gSystem->Exec(Form("tar -czf %s %s",
412 parFile.Data(), parName.Data()));
414 Error("ProofRailway::CreateAliROOTPar", "Failed to pack up PAR file %s",
419 ret = gProof->UploadPackage(parFile.Data(),TProof::kRemoveOld);
421 Error("ProofRailway::CreateAliROOTPar",
422 "Failed to upload the AliROOT PAR file");
425 // Note, the PAR isn't enabled until much later when we've
426 // collected all the needed libraries in fExtraLibs
430 * Get the mode identifier
432 * @return Always kProof
434 virtual UShort_t Mode() const { return kProof; }
436 * Get the mode string used for AliAnalysisManager::StartAnalysis
438 virtual const char* ModeString() const { return "proof"; }
440 * Set-up done before task set-ups
442 * @return true on success
444 virtual Bool_t PreSetup()
446 // --- Set prefered GSI method ---------------------------------
447 gEnv->SetValue("XSec.GSI.DelegProxy", "2");
449 // --- Add ALICE_ROOT directory to search path for packages ----
450 // Info("ProofRailway::PreSetup", "Set location of packages");
451 gEnv->SetValue("Proof.GlobalPackageDirs",
453 gEnv->GetValue("Proof.GlobalPackageDirs", "."),
454 gSystem->Getenv("ALICE_ROOT")));
456 // --- Forming the URI we use to connect with --------------------
458 connect.SetAnchor("");
460 connect.SetOptions("");
462 // --- Check if we need to reset first ---------------------------
463 if (fOptions.Has("reset")) {
464 TString reset = fOptions.Get("reset");
465 Bool_t hard = (reset.IsNull() ||
466 reset.EqualTo("hard", TString::kIgnoreCase));
467 Info("ProofRailway::PreSetup", "Doing a %s reset of %s",
468 hard ? "hard" : "soft", connect.GetUrl());
469 TProof::Reset(connect.GetUrl(), hard);
471 Info("ProofRailway::PreSetup",
472 "Waiting for %d second%s for things to settle", secs,
473 secs > 1 ? "s" : "");
474 gSystem->Sleep(1000*secs);
477 // --- Check if we're using a wrapper ----------------------------
478 if (fOptions.Has("wrapper")) {
479 TString wrapper = fOptions.Get("wrapper");
480 if (wrapper.IsNull())
481 // In case of no argument, use GDB
482 // Just run and backtrace
483 wrapper = "/usr/bin/gdb --batch -ex run -ex bt --args";
484 Info("ProofRailway::PreSetup", "Using wrapper command: %s",
486 TProof::AddEnvVar("PROOF_WRAPPERCMD", wrapper);
489 // --- PAR parameters --------------------------------------------
490 fUsePars = fOptions.Has("par");
491 fBasePars = (fUsePars &&
492 fOptions.Get("par").EqualTo("all",TString::kIgnoreCase));
493 fTestBuild = fOptions.Has("testpar");
495 // --- Connect to the cluster ------------------------------------
497 if (fOptions.Has("workers"))
498 opts.Append(Form("workers=%s", fOptions.Get("workers").Data()));
500 Info("ProofRailway::PreSetup", "Connecting to %s with %soptions %s",
502 opts.IsNull() ? "no " : "",
504 TString proto(connect.GetProtocol());
505 if (proto.BeginsWith("lite") && fOptions.Has("workers"))
508 TProof::Open(connect.GetUrl(), opts);
509 // TProof::Open(connect.GetHost(), opts);
511 Error("ProofRailway::PreSetup", "Failed to open Proof connection %s",
516 // --- Check if we need to clear packages ------------------------
517 if (fOptions.Has("clear")) {
518 TString pkgs = fOptions.Get("clear");
519 if (pkgs.IsNull() || pkgs.EqualTo("all", TString::kIgnoreCase)) {
520 // No value given, clear all
521 if (gProof->ClearPackages() != 0)
522 Warning("ProofRailway::PreSetup", "Failed to lear all packages");
525 // Tokenize on ',' and clear each package
526 TObjArray* pars = pkgs.Tokenize(",");
529 while ((pkg = next())) {
530 if (gProof->ClearPackage(pkg->GetName()) != 0)
531 Warning("ProofRailway::PreSetup", "Failed to clear package %s",
540 * Set-up done after the task set-ups
542 * @return true on success
544 virtual Bool_t PostSetup()
546 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
548 Error("ProofRailway::PostSetup", "No analysis manager defined");
552 // --- Check for output ------------------------------------------
553 if (fOptions.Has("dsname"))
554 OutputUtilities::RegisterDataset(fOptions.Get("dsname"));
555 if (fOptions.Has("storage"))
556 OutputUtilities::RegisterStorage(fOptions.Get("storage"));
558 // --- Check for feedback mechanism ------------------------------
559 if (!fOptions.Has("feedback"))
560 gProof->ClearFeedback();
562 // --- If we are not using PARs for Base, enable special PAR -----
564 TString tmp(fExtraLibs.Strip(TString::kBoth,':'));
565 TList* params = new TList;
566 params->SetOwner(true);
567 params->Add(new TNamed("ALIROOT_EXTRA_LIBS", tmp.Data()));
568 if (fOptions.Has("mode"))
569 params->Add(new TNamed("ALIROOT_MODE", fOptions.Get("mode").Data()));
571 params->Add(new TNamed("ALIROOT_MODE", "default"));
572 Int_t ret = gProof->EnablePackage(AliROOTParName(), params, true);
574 Error("ProofRailway::EnableAliROOT", "Failed to enable AliROOT PAR %s",
580 // --- Make PAR file of Aux Files --------------------------------
581 if (fAuxFiles.GetEntries() > 0) {
582 TString name = TString::Format("%s_auxfiles", mgr->GetName());
583 ParUtilities::MakeAuxFilePAR(fAuxFiles, name);
585 if (gProof->UploadPackage(name.Data(), TProof::kRemoveOld) < 0)
586 Error("ProofRailway::PostSetup", "Failed to upload PAR file %s",
589 fExtraPars.Append(Form(":%s", name.Data()));
592 // --- Load par files --------------------------------------------
593 TString tmp = fExtraPars.Strip(TString::kBoth,':');
594 TObjArray* pars = tmp.Tokenize(":");
597 while ((obj = next())) {
598 // Enable the package, but do not build on client - already done
599 Int_t ret = gProof->EnablePackage(obj->GetName(), true);
601 Error("ProofRailway::PostSetup", "Failed to enable PAR %s",
607 // --- Load extra sources ----------------------------------------
608 TString tmp2 = fExtraSrcs.Strip(TString::kBoth, ':');
609 TObjArray* srcs = tmp2.Tokenize(":");
611 while ((obj = next())) {
612 Int_t ret = gProof->Load(Form("%s++g", obj->GetName()), true);
614 Error("ProofRailway::PostSetup", "Failed to compile %s", obj->GetName());
623 * @param nEvents Number of events to analyse
625 * @return The return value of AliAnalysisManager::StartAnalysis
627 virtual Long64_t Run(Long64_t nEvents=-1)
629 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
630 gProof->SetLogLevel(TMath::Max(fVerbose-2,0),
631 /* TProofDebug::kPacketizer| */
633 /* TProofDebug::kSelector|
634 TProofDebug::kOutput|
636 TProofDebug::kGlobal|*/
637 TProofDebug::kPackage);
638 TString dsName(fUrl.GetFile());
639 // if (fUrl.GetAnchor() && fUrl.GetAnchor()[0] != '\0')
640 // dsName.Append(Form("#%s", fUrl.GetAnchor()));
641 // Info("Run", "Output objects registered with PROOF:");
642 // gProof->GetOutputList()->ls();
643 Long64_t off = fOptions.AsLong("offset", 0);
644 if (nEvents > 0 && nEvents < off) {
645 Warning("Run", "Number of events %lld < offset (%lld), stopping",
649 Long64_t ret = mgr->StartAnalysis(fUrl.GetProtocol(), dsName, nEvents, off);
652 TProof::Mgr(fUrl.GetUrl())->GetSessionLogs()->Save("*","proof.log");
656 Bool_t AddMonitor(const TString& path)
658 if (path.IsNull()) return true;
660 TObjArray* tokens = path.Tokenize("/");
661 Int_t nTokens = tokens->GetEntries();
663 Error("AddMonitor", "Monitors must be of the form:\n"
664 " <task>[:<slot>]/<name>\n"
665 " <task>[:<slot>]/<path>/<name>");
668 // --- Get the manager
669 AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
671 // --- Extract task and possibly slot number
672 TString& sTask = static_cast<TObjString*>(tokens->At(0))->String();
674 Ssiz_t colon = sTask.Index(":");
675 if (colon != kNPOS) {
676 TString sSlot = sTask(colon+1, sTask.Length()-colon-1);
677 if (!sSlot.IsNull()) slotNo = sSlot.Atoi();
678 sTask.Remove(colon, sTask.Length()-colon);
681 AliAnalysisTask* task = mgr->GetTask(sTask);
683 Error("AddMonitor", "Task \"%s\" not registered with manager",
687 AliAnalysisDataSlot* slot = task->GetOutputSlot(slotNo);
689 Error("AddMonitor", "Task \"%s\" does not have an output slot at %d",
690 task->GetName(), slotNo);
693 AliAnalysisDataContainer* cont = slot->GetContainer();
695 Error("AddMonitor", "Output slot %d of task \"%s\" has no container",
696 slotNo, task->GetName());
700 TString& first = static_cast<TObjString*>(tokens->At(idx))->String();
701 if (first.EqualTo(cont->GetName())) {
704 TObject* data = cont->GetData();
706 for (; idx < nTokens; idx++) {
712 * Print information to standard output
716 virtual void Print(Option_t* option="") const
718 Railway::Print(option);
719 std::cout << std::boolalpha
720 << " --- Other settings -------\n"
721 << " Extra libraries : " << fExtraLibs << "\n"
722 << " Extra PARs : " << fExtraPars << "\n"
723 << " Extra sources : " << fExtraSrcs << "\n"
724 << " Use PARs of tasks: " << fUsePars << "\n"
725 << " Use PARs of base : " << fBasePars
726 << std::noboolalpha << std::endl;
729 * Link an auxilary file to working directory
731 * @param name Name of the file
732 * @param copy Copy rather than link
734 * @return true on success
736 virtual Bool_t AuxFile(const TString& name, bool copy=false)
738 Bool_t ret = Railway::AuxFile(name, copy);
739 if (!name.BeginsWith("/")) {
740 fAuxFiles.Add(new TObjString(name));
743 if (ret && name.EndsWith(".root")) {
744 TFile* file = TFile::Open(name, "READ");
746 Info("AuxFile", "Adding input file %s", name.Data());
747 gProof->AddInputData(file, true);
753 Int_t SendFile(const TString& fileName)
755 Int_t bufSize = 32768;
758 Long_t id = 0, flags = 0, modtime = 0;
759 if (gSystem->GetPathInfo(fileName.Data(), &id, &size, &flags, &modtime)==1
761 Error("SendFile", "Cannot stat %s", fileName.Data());
764 TString fn(gSystem->BaseName(fileName.Data()));
765 TList* slaves = 0; // gProof->GetListOfActiveSlaves(); - protected
769 Int_t fd = open(fileName.Data(), O_RDONLY);
770 while ((sl = static_cast<TSlave*>(next()))) {
771 if (!sl->IsValid()) continue;
772 if (sl->GetSlaveType() != TSlave::kSlave) continue;
774 // Always binary (first 1), never forward (last 0).
775 snprintf(buf,bufSize,"%s %d %lld %d", fn.Data(), 1, size, 0);
776 if (sl->GetSocket()->Send(buf, kPROOF_SENDFILE) == -1) {
777 Warning("SendFile", "Could not send kPROOF_SENDFILE request");
781 // Go to the beginning of the file
782 lseek(fd, 0, SEEK_SET);
785 while ((len = read(fd, buf, bufSize)) < 0 &&
786 TSystem::GetErrno() == EINTR)
787 TSystem::ResetErrno();
789 Error("SendFile", "error reading input");
793 if (len > 0 && sl->GetSocket()->SendRaw(buf, len) == -1) {
794 Error("SendFile", "error writing to slave");
801 // Wait for slave - private
802 // if (sl) gProof->Collect(sl,gEnv->GetValue("Proof.CollectTimeout",-1));
813 * @return Path to output - possibly a data set
815 virtual TString OutputPath() const
818 if (fOptions.Has("dsname")) {
819 ret = Form("/%s/%s/", gProof->GetGroup(), gProof->GetUser());
820 ret.Append(OutputUtilities::RegisteredDataset());
825 * @return URL help string
827 virtual const Char_t* UrlHelp() const
829 return "proof://<host>[:<port>]/[<dataset>|<path>][?<options>][#<treeName>]";
832 * @return Short description
834 virtual const char* Desc() const { return "PROOF"; }