]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/trains/ProofHelper.C
Mega commit of many changes to PWGLFforward
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / ProofHelper.C
1 /**
2  * @file   ProofHelper.C
3  * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4  * @date   Tue Oct 16 18:58:37 2012
5  * 
6  * @brief  
7  * 
8  *
9  * @ingroup pwglf_forward_trains_helper
10  * 
11  */
12 #ifndef PROOFHELPER_C
13 #define PROOFHELPER_C
14 #include "Helper.C"
15 #ifndef __CINT__
16 # include "OutputUtilities.C"
17 # include "ParUtilities.C"
18 # include "ChainBuilder.C"
19 # include <TUrl.h>
20 # include <TString.h>
21 # include <TProof.h>
22 # include <TProofLog.h>
23 # include <TProofDebug.h>
24 # include <AliAnalysisManager.h>
25 # include <TEnv.h>
26 # include <TChain.h>
27 // For SendFile
28 # include <TSystem.h>
29 # include <TSlave.h>
30 # include <TSocket.h>
31 # include <cerrno>
32 #else
33 class TUrl;
34 class TChain;
35 #endif
36
37 // ===================================================================
38 /**
39  * Handle analysis on a Proof farm. 
40  * 
41  * This helper is triggered by URIs of the form 
42  *
43  * @code
44  * proof://[<user>@]<host>[:<port>]/<dsname>[?<options>][#<treename>]
45  * @endcode 
46  * where 
47  * <dl>
48  *   <dt>&lt;user&gt;</dt>
49  *   <dd>Optional user name</dd>
50  *   <dt>&lt;host&gt;</dt>
51  *   <dd>PROOF cluster master host</dd>
52  *   <dt>&lt;port&gt;</dt>
53  *   <dd>Optional PROOF cluster port on master host</dd>
54  *   <dt>&lt;dsname&gt;</dt>
55  *   <dd>Data set name</dd>
56  *   <dt>&lt;treename&gt;</dt>
57  *   <dd>Optional tree name in data set, often <tt>esdTree</tt> or
58  *   <tt>aodTree</tt></dd>
59  *   <dt>&lt;options&gt;</dt>
60  *   <dd>List of options separated by an &amp;
61  *     <dl>
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>[=&lt;output dataset&gt;]</dt>
66  *       <dd>Register tree output (e.g., AOD) as a new data set on the
67  *         PROOF cluster. If &lt;output dataset&gt; 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 
72  *         are used. </dd>
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=&lt;url&gt;</tt></dt>
77  *       <dd>Specify a non-default storage location for special output
78  *         (e.g., AOD trees).  &lt;url&gt; should be a valid XRootd 
79  *         server URI accessible to the slaves - e.g., 
80  *         <tt>root://lxplus.cern.ch:10930//tmp</tt>.</dd>
81  *     </dl>
82  *   </dd>
83  * </dl>  
84  *
85  * @ingroup pwglf_forward_trains_helper
86  */
87 struct ProofHelper : public Helper
88 {
89   /** 
90    * Constructor 
91    * 
92    * @param url  Url 
93    * @param verbose Verbosity level
94    */
95   ProofHelper(const TUrl& url, Int_t verbose)
96     : Helper(url, verbose), 
97       fExtraLibs(""),
98       fExtraPars(""),
99       fExtraSrcs(""),
100       fUsePars(false), 
101       fBasePars(false),
102       fAuxFiles()
103   {
104     fOptions.Add("workers",  "N[x]", "Number of workers to use", 0);
105     fOptions.Add("dsname",   "NAME", "Make output dataset", "");
106     fOptions.Add("par",      "tasks|all", "Use par files",           "tasks");
107     fOptions.Add("mode",     "default|rec|sim", "AliROOT mode",      "default");
108     fOptions.Add("storage",  "URL", "Location for external storage", "");    
109     fOptions.Add("wrapper",  "CMD", "Wrapper command", "");
110     fOptions.Add("clear",    "PKGS", "Clear packages ','-separated", "");
111     fOptions.Add("reset",    "soft|hard", "Reset cluster", "hard");
112     if (!fUrl.GetUser() || fUrl.GetUser()[0] == '\0') 
113       fUrl.SetUser(gSystem->GetUserInfo()->fUser);
114     fAuxFiles.SetOwner();
115   }
116   ProofHelper(const ProofHelper& o) 
117     : Helper(o),
118       fExtraLibs(""),
119       fExtraPars(""),
120       fExtraSrcs(""),
121       fUsePars(false), 
122       fBasePars(false),
123       fAuxFiles()
124   {}
125   ProofHelper& operator=(const ProofHelper& o) 
126   {
127     if (&o == this) return *this;
128     Helper::operator=(o);
129     fExtraLibs = o.fExtraLibs;
130     fExtraPars = o.fExtraPars;
131     fExtraSrcs = o.fExtraSrcs;
132     fUsePars   = o.fUsePars;
133     fBasePars  = o.fBasePars;
134     // fAuxFiles;
135     return *this;
136   }
137   /** 
138    * Destructor 
139    */
140   virtual ~ProofHelper() {}
141   /** 
142    * Load a library/PAR/script 
143    * 
144    * @param name   Name 
145    * @param slaves If true, also load on slaves
146    * 
147    * @return true on success 
148    */
149   virtual Bool_t LoadLibrary(const TString& name, 
150                              Bool_t slaves=true)
151   {
152     if (!fUsePars) {
153       Int_t ret = gSystem->Load(MakeLibraryName(name));
154       if (ret < 0) return false;
155       if (slaves) fExtraLibs.Append(Form(":%s", name.Data()));
156     }
157     else { 
158       if (!ParUtilities::Find(name)) { 
159         Error("ProofHelper::LoadLibrary", "Failed to find PAR file %s", 
160               name.Data());
161         return false;
162       }
163       if (!ParUtilities::Build(name)) { 
164         Error("ProofHelper::LoadLibrary", "Failed to build PAR file %s", 
165               name.Data());
166         return false;
167       }
168       if (gProof->UploadPackage(name.Data(), TProof::kRemoveOld) < 0) {
169         Error("ProofHelper::LoadLibrary", "Failed to upload PAR file %s", 
170               name.Data());
171         return false;
172       }
173       fExtraPars.Append(Form(":%s", name.Data()));
174     }
175     return true;
176   }
177   /** 
178    * Load a source file, and compile it 
179    * 
180    * @param name Name of the source file 
181    * @param copy If true, copy not link 
182    * 
183    * @return true on success
184    */
185   virtual Bool_t LoadSource(const TString& name, bool copy=false)
186   {
187     if (!Helper::LoadSource(name, copy)) return false;
188     fExtraSrcs.Append(Form(":%s", gSystem->BaseName(name.Data())));
189     return true;
190   }
191   /** 
192    * Set-up to load the AliROOT libraries 
193    * 
194    * @return true on success
195    */
196   virtual Bool_t LoadAliROOT()
197   {
198     if (!gSystem->Getenv("ALICE_ROOT")) { 
199       Error("ProofHelper::LoadAliROOT", "Local AliROOT not available");
200       return false;
201     }
202
203     Bool_t tmp = fUsePars;
204     fUsePars   = fBasePars;
205     if (!LoadLibrary("STEERBase"))     return false;
206     if (!LoadLibrary("ESD"))           return false;
207     if (!LoadLibrary("AOD"))           return false;
208     if (!LoadLibrary("ANALYSIS"))      return false;
209     if (!LoadLibrary("OADB"))          return false;
210     if (!LoadLibrary("ANALYSISalice")) return false;
211     fUsePars = tmp;
212
213     return CreateAliROOTPar();
214   }
215   /** 
216    * Get the name of the AliROOT par file to use 
217    * 
218    * @return String 
219    */
220   virtual const char* AliROOTParName() const
221   {
222     return "ALIROOT";
223   }
224   /** 
225    * Create an AliROOT par file from the executing AliROOT.  This PAR
226    * file basically uses the environment of the client - that is, we
227    * assume that the used AliROOT is accessible on the slaves - e.g.,
228    * via an NFS export.
229    * 
230    * Note, the SETUP.C script take one argument - a TList of TNamed
231    * parameters.  Parameters processed are      
232    *
233    * - ALIROOT_MODE=[default,aliroot,rec,sim,train]
234    *   - default: Load base analysis libraries 
235    *   - aliroot: Load $ALICE_ROOT/macros/loadlibs.C
236    *   - rec:     Load $ALICE_ROOT/macros/loadlibsrec.C
237    *   - sim:     Load $ALICE_ROOT/macros/loadlibssim.C
238    * - ALIROOT_EXTRA_LIBS Colon separated list of additional (Ali)ROOT
239    *   libraries to load on the slaves.
240    * 
241    * The generated PAR file is uploaded but not enabled until we have 
242    * populated fExtraLibs.  The enabling takes place at the end of the 
243    * set-up. 
244    * 
245    * @return true on success, false otherwise.     */
246   virtual Bool_t CreateAliROOTPar()
247   {
248     if (fBasePars) return true;
249
250     TString parName(AliROOTParName());
251     TString parFile(Form("%s.par", parName.Data()));
252
253     // --- Check if we have the drirectory already -------------------
254     if (gSystem->AccessPathName(parName.Data()) == 0) { 
255       // Let's remove it to get a clean slate 
256       if (gSystem->Exec(Form("rm -rf %s", parName.Data())) != 0) {
257         Error("ProofHelper", "Failed to remove %s", parName.Data());
258         return false;
259       }
260     }
261     // --- Check if the PAR file is there, and remove it if so -------
262     if (gSystem->AccessPathName(parFile.Data()) == 0) { 
263       if (gSystem->Unlink(parFile.Data()) != 0) { 
264         Error("ProofHelper::CreateAliROOTPar", "Failed to remove %s", 
265               parFile.Data());
266         return false;
267       }
268     }
269       
270
271     // Set-up directories 
272     if (gSystem->MakeDirectory(parName) < 0) {
273       Error("ProofHelper::CreateAliROOTPar", "Could not make directory '%s'", 
274             parName.Data());
275       return false;
276     }
277     
278     if (gSystem->MakeDirectory(Form("%s/PROOF-INF", parName.Data()))) {
279       Error("ProofHelper::CreateAliROOTPar", 
280             "Could not make directory %s/PROOF-INF", 
281             parName.Data());
282       return false;
283     }
284
285     std::ofstream b(Form("%s/PROOF-INF/BUILD.sh",parName.Data()));
286     if (!b) { 
287       Error("ProofHelper::CreateAliROOTPar", 
288             "Failed to make BUILD.sh shell script");
289       return false;
290     }
291     b << "#!/bin/sh\n\n"
292       << "# echo Nothing to do\n"
293       << "exit 0\n"
294       << std::endl;
295     b.close();
296     gSystem->Exec(Form("chmod a+x %s/PROOF-INF/BUILD.sh",parName.Data()));
297
298     std::ofstream s(Form("%s/PROOF-INF/SETUP.C", parName.Data()));
299     if (!s) { 
300       Error("ProofHelper::CreateAliROOTPar", 
301             "Failed to make SETUP.C ROOT script");
302       return false;
303     }
304     s << "void SETUP(TList* opts) {\n"
305       << "  gSystem->Setenv(\"ALICE\",\"" 
306       << gSystem->Getenv("ALICE") << "\");\n"
307       << "  gSystem->Setenv(\"ALICE_ROOT\",\"" 
308       << gSystem->Getenv("ALICE_ROOT") << "\");\n"
309       << "  gSystem->Setenv(\"ALICE_TARGET\",\"" 
310       << gSystem->Getenv("ALICE_TARGET") << "\");\n"
311       << "  gSystem->AddDynamicPath("
312       << "\"$(ALICE_ROOT)/lib/tgt_$(ALICE_TARGET)\");\n";
313     if (gSystem->Getenv("OADB_PATH")) 
314       s << "  gSystem->Setenv(\"OADB_PATH\",\"" 
315         << gSystem->Getenv("OADB_PATH") << "\");\n";
316     s << "  \n"
317       << "  // Info(\"SETUP\",\"Loading ROOT libraries\");\n"
318       << "  gSystem->Load(\"libTree\");\n"
319       << "  gSystem->Load(\"libGeom\");\n"
320       << "  gSystem->Load(\"libVMC\");\n"
321       << "  gSystem->Load(\"libPhysics\");\n"
322       << "  gSystem->Load(\"libMinuit\");\n"
323       << "  \n";
324     s << "  // Info(\"SETUP\",\"Parameter list:\");\n"
325       << "  if (!opts) return;\n"
326       << "  //opts->ls();\n"
327       << "  \n";
328     s << "  TObject* par = opts->FindObject(\"ALIROOT_MODE\");\n"
329       << "  if (par) {\n"
330       << "    // Info(\"SETUP\",\"ALIROOT mode: %s\", par->GetTitle());\n"
331       << "    TString mode(par->GetTitle());\n"
332       << "    if (mode.EqualTo(\"default\",TString::kIgnoreCase)) {\n"
333       << "      gSystem->Load(\"libSTEERBase\");\n"
334       << "      gSystem->Load(\"libESD\");\n"
335       << "      gSystem->Load(\"libAOD\");\n"
336       << "      gSystem->Load(\"libANALYSIS\");\n"
337       << "      gSystem->Load(\"libOADB\");\n"
338       << "      gSystem->Load(\"libANALYSISalice\");\n"
339       << "    }\n"
340       << "    else if (mode.EqualTo(\"aliroot\",TString::kIgnoreCase)) \n"
341       << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibs.C\");\n"
342       << "    else if (mode.EqualTo(\"rec\",TString::kIgnoreCase)) \n"
343       << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibsrec.C\");\n"
344       << "    else if (mode.EqualTo(\"sim\",TString::kIgnoreCase)) \n"
345       << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibssim.C\");\n"
346       << "    else if (mode.EqualTo(\"train\",TString::kIgnoreCase)) \n"
347       << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibstrain.C\");\n"
348       << "    else if (mode.EqualTo(\"custom\",TString::kIgnoreCase)) \n"
349       << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibstrain.C\");\n"
350       << "  }\n"
351       << "  \n";
352     s << "  par = opts->FindObject(\"ALIROOT_EXTRA_LIBS\");\n"
353       << "  if (par) {\n"
354       << "    Info(\"SETUP\",\"Libaries to load: %s\n\",par->GetTitle());\n"
355       << "    TString tit(par->GetTitle());\n"
356       << "    TObjArray* tokens = tit.Tokenize(\":\");\n"
357       << "    TObject*   lib    = 0;\n"
358       << "    TIter      next(tokens);\n"
359       << "    while ((lib = next())) {\n"
360       << "      TString libName(lib->GetName());\n"
361       << "      if (!libName.BeginsWith(\"lib\")) libName.Prepend(\"lib\");\n"
362       << "      // Info(\"SETUP\",\"Loading %s ...\",libName.Data());\n"
363       << "      gSystem->Load(Form(\"lib%s\",lib->GetName()));\n"
364       << "    }\n"
365       << "  }\n"
366       << "}\n"
367       << std::endl;
368     s.close();
369
370     Int_t ret = gSystem->Exec(Form("tar -czf %s %s",
371                                    parFile.Data(), parName.Data()));
372     if (ret != 0) { 
373       Error("ProofHelper::CreateAliROOTPar", "Failed to pack up PAR file %s",
374             parFile.Data());
375       return false;
376     }
377
378     ret = gProof->UploadPackage(parFile.Data(),TProof::kRemoveOld);
379     if (ret != 0) { 
380       Error("ProofHelper::CreateAliROOTPar", 
381             "Failed to upload the AliROOT PAR file");
382       return false;
383     }
384     // Note, the PAR isn't enabled until much later when we've
385     // collected all the needed libraries in fExtraLibs
386     return true;
387   }
388   /** 
389    * Get the mode identifier 
390    * 
391    * @return Always kProof
392    */
393   virtual UShort_t Mode() const { return kProof; }
394   /**
395    * Get the mode string used for AliAnalysisManager::StartAnalysis
396    */
397   virtual const char* ModeString() const { return "proof"; }
398   /** 
399    * Set-up done before task set-ups 
400    * 
401    * @return true on success 
402    */
403   virtual Bool_t PreSetup()
404   {
405     // --- Set prefered GSI method ---------------------------------
406     gEnv->SetValue("XSec.GSI.DelegProxy", "2");
407
408     // --- Add ALICE_ROOT directory to search path for packages ----
409     // Info("ProofHelper::PreSetup", "Set location of packages");
410     gEnv->SetValue("Proof.GlobalPackageDirs", 
411                    Form("%s:%s", 
412                         gEnv->GetValue("Proof.GlobalPackageDirs", "."), 
413                         gSystem->Getenv("ALICE_ROOT")));
414
415     // --- Forming the URI we use to connect with --------------------
416     TUrl connect(fUrl);
417     connect.SetAnchor("");
418     connect.SetFile("");
419     connect.SetOptions("");
420
421     // --- Check if we need to reset first ---------------------------
422     if (fOptions.Has("reset")) { 
423       TString reset = fOptions.Get("reset");
424       Bool_t  hard  = (reset.IsNull() || 
425                        reset.EqualTo("hard", TString::kIgnoreCase));
426       Info("ProofHelper::PreSetup", "Doing a %s reset of %s", 
427            hard ? "hard" : "soft", connect.GetUrl());
428       TProof::Reset(connect.GetUrl(), hard);
429       Int_t secs = 3;
430       Info("ProofHelper::PreSetup", 
431            "Waiting for %d second%s for things to settle", secs,
432            secs > 1 ? "s" : "");
433       gSystem->Sleep(1000*secs);
434     }
435       
436     // --- Check if we're using a wrapper ----------------------------
437     if (fOptions.Has("wrapper")) { 
438       TString wrapper = fOptions.Get("wrapper");
439       if (wrapper.IsNull()) 
440         // In case of no argument, use GDB 
441         // Just run and backtrace 
442         wrapper = "/usr/bin/gdb --batch -ex run -ex bt --args";
443       Info("ProofHelper::PreSetup", "Using wrapper command: %s", 
444            wrapper.Data());
445       TProof::AddEnvVar("PROOF_WRAPPERCMD", wrapper);
446     }
447
448     // --- PAR parameters --------------------------------------------
449     fUsePars  = fOptions.Has("par");
450     fBasePars = (fUsePars && 
451                  fOptions.Get("par").EqualTo("all",TString::kIgnoreCase));
452
453     // --- Connect to the cluster ------------------------------------
454     TString opts;
455     if (fOptions.Has("workers")) 
456       opts.Append(Form("workers=%s", fOptions.Get("workers").Data()));
457       
458     Info("ProofHelper::PreSetup", "Connecting to %s with %soptions %s", 
459          connect.GetUrl(), 
460          opts.IsNull() ? "no " : "", 
461          opts.Data());
462     TString proto(connect.GetProtocol());
463     if (proto.BeginsWith("lite") && fOptions.Has("workers")) 
464       TProof::Open(opts);
465     else 
466       TProof::Open(connect.GetUrl(), opts);
467     // TProof::Open(connect.GetHost(), opts);
468     if (!gProof) { 
469       Error("ProofHelper::PreSetup", "Failed to open Proof connection %s", 
470             connect.GetUrl());
471       return false;
472     }
473     
474     // --- Check if we need to clear packages ------------------------
475     if (fOptions.Has("clear")) {
476       TString pkgs = fOptions.Get("clear");
477       if (pkgs.IsNull() || pkgs.EqualTo("all", TString::kIgnoreCase)) { 
478         // No value given, clear all 
479         if (gProof->ClearPackages() != 0) 
480           Warning("ProofHelper::PreSetup", "Failed to lear all packages");
481       }
482       else { 
483         // Tokenize on ',' and clear each package 
484         TObjArray* pars = pkgs.Tokenize(",");
485         TObject*   pkg  = 0;
486         TIter      next(pars); 
487         while ((pkg = next())) { 
488           if (gProof->ClearPackage(pkg->GetName()) != 0)
489             Warning("ProofHelper::PreSetup", "Failed to clear package %s", 
490                     pkg->GetName());
491         }
492         pars->Delete();
493       }
494     }
495     return true;
496   }
497   /** 
498    * Set-up done after the task set-ups 
499    *
500    * @return true on success 
501    */
502   virtual Bool_t PostSetup() 
503   {
504     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
505     if (!mgr) { 
506       Error("ProofHelper::PostSetup", "No analysis manager defined");
507       return false;
508     }
509
510     // --- Check for output ------------------------------------------
511     if (fOptions.Has("dsname")) 
512       OutputUtilities::RegisterDataset(fOptions.Get("dsname"));
513     if (fOptions.Has("storage"))
514       OutputUtilities::RegisterStorage(fOptions.Get("storage"));
515
516     // --- If we are not using PARs for Base, enable special PAR -----
517     if (!fBasePars) {
518       TString tmp(fExtraLibs.Strip(TString::kBoth,':'));
519       TList* params = new TList;
520       params->SetOwner(true);
521       params->Add(new TNamed("ALIROOT_EXTRA_LIBS", tmp.Data()));
522       if (fOptions.Has("mode"))
523         params->Add(new TNamed("ALIROOT_MODE", fOptions.Get("mode").Data()));
524       else
525         params->Add(new TNamed("ALIROOT_MODE", "default"));
526       Int_t ret = gProof->EnablePackage(AliROOTParName(), params, true);
527       if (ret < 0) {
528         Error("ProofHelper::EnableAliROOT", "Failed to enable AliROOT PAR %s", 
529               AliROOTParName());
530         return false;
531       }
532     }
533
534     // --- Make PAR file of Aux Files --------------------------------
535     if (fAuxFiles.GetEntries() > 0) { 
536       TString name = TString::Format("%s_auxfiles", mgr->GetName());
537       ParUtilities::MakeAuxFilePAR(fAuxFiles, name);
538
539       if (gProof->UploadPackage(name.Data(), TProof::kRemoveOld) < 0) 
540         Error("ProofHelper::PostSetup", "Failed to upload PAR file %s", 
541               name.Data());
542       else 
543         fExtraPars.Append(Form(":%s", name.Data()));
544     }
545     
546     // --- Load par files --------------------------------------------
547     TString    tmp  = fExtraPars.Strip(TString::kBoth,':');
548     TObjArray* pars = tmp.Tokenize(":");
549     TObject*   obj  = 0;
550     TIter      next(pars);
551     while ((obj = next())) { 
552       // Enable the package, but do not build on client - already done
553       Int_t ret = gProof->EnablePackage(obj->GetName(), true);
554       if (ret < 0) { 
555         Error("ProofHelper::PostSetup", "Failed to enable PAR %s",
556               obj->GetName());
557         return false;
558       }
559     }
560     
561     // --- Load extra sources ----------------------------------------
562     TString    tmp2 = fExtraSrcs.Strip(TString::kBoth, ':');
563     TObjArray* srcs = tmp2.Tokenize(":");
564     TIter      next2(srcs);
565     while ((obj = next())) { 
566       Int_t ret = gProof->Load(Form("%s++g", obj->GetName()), true);
567       if (ret < 0) { 
568         Error("ProofHelper::PostSetup", "Failed to compile %s", obj->GetName());
569         return false;
570       }
571     }
572     return true;
573   }
574   /** 
575    * Start the analysis 
576    * 
577    * @param nEvents Number of events to analyse 
578    * 
579    * @return The return value of AliAnalysisManager::StartAnalysis
580    */
581   virtual Long64_t Run(Long64_t nEvents=-1) 
582   {
583     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
584     gProof->SetLogLevel(TMath::Max(fVerbose-2,0), 
585                         /* TProofDebug::kPacketizer| */
586                         TProofDebug::kLoop|
587                         /* TProofDebug::kSelector|
588                         TProofDebug::kOutput|
589                         TProofDebug::kInput|
590                         TProofDebug::kGlobal|*/
591                         TProofDebug::kPackage);
592     TString dsName(fUrl.GetFile());
593     // if (fUrl.GetAnchor() && fUrl.GetAnchor()[0] != '\0') 
594     //   dsName.Append(Form("#%s", fUrl.GetAnchor()));
595     Long64_t ret = mgr->StartAnalysis(fUrl.GetProtocol(), dsName, nEvents);
596     
597     if (fVerbose > 10) 
598       TProof::Mgr(fUrl.GetUrl())->GetSessionLogs()->Save("*","proof.log");
599     return ret;
600   }
601   /** 
602    * Print information to standard output
603    * 
604    * @param option 
605    */
606   virtual void Print(Option_t* option="") const 
607   {
608     Helper::Print(option);
609     std::cout << std::boolalpha 
610               << "  --- Other settings -------\n"
611               << "  Extra libraries  : " << fExtraLibs << "\n"
612               << "  Extra PARs       : " << fExtraPars << "\n"
613               << "  Extra sources    : " << fExtraSrcs << "\n"
614               << "  Use PARs of tasks: " << fUsePars   << "\n"
615               << "  Use PARs of base : " << fBasePars  
616               << std::noboolalpha << std::endl;
617   }
618   /** 
619    * Link an auxilary file to working directory 
620    * 
621    * @param name Name of the file
622    * @param copy Copy rather than link
623    *
624    * @return true on success
625    */
626   virtual Bool_t AuxFile(const TString& name, bool copy=false)
627   {
628     Bool_t ret = Helper::AuxFile(name, copy);
629     if (!name.BeginsWith("/")) {
630       fAuxFiles.Add(new TObjString(name));
631     }
632 #if 0
633     if (ret && name.EndsWith(".root")) { 
634       TFile* file = TFile::Open(name, "READ");
635       if (file) {
636         Info("AuxFile", "Adding input file %s", name.Data());
637         gProof->AddInputData(file, true);
638       }
639     }
640 #endif
641     return ret;
642   }
643   Int_t SendFile(const TString& fileName) 
644   {
645     Int_t    bufSize = 32768;
646     Char_t   buf[bufSize];
647     Long64_t size = 0;
648     Long_t   id = 0, flags = 0, modtime = 0;
649     if (gSystem->GetPathInfo(fileName.Data(), &id, &size, &flags, &modtime)==1 
650         || size <= 0) {
651       Error("SendFile", "Cannot stat %s", fileName.Data());
652       return -1;
653     }
654     TString fn(gSystem->BaseName(fileName.Data()));
655     TList*  slaves = 0; // gProof->GetListOfActiveSlaves(); - protected
656     TIter   next(slaves);
657     TSlave* sl   = 0;
658     Int_t   ret  = 0;
659     Int_t   fd = open(fileName.Data(), O_RDONLY);
660     while ((sl = static_cast<TSlave*>(next()))) {
661       if (!sl->IsValid()) continue;
662       if (sl->GetSlaveType() != TSlave::kSlave) continue;
663       
664       // Always binary (first 1), never forward (last 0).
665       snprintf(buf,bufSize,"%s %d %lld %d", fn.Data(), 1, size, 0);
666       if (sl->GetSocket()->Send(buf, kPROOF_SENDFILE) == -1) {
667         Warning("SendFile", "Could not send kPROOF_SENDFILE request");
668         continue;
669       }
670
671       // Go to the beginning of the file 
672       lseek(fd, 0, SEEK_SET);
673       Int_t len = 0;
674       do { 
675         while ((len = read(fd, buf, bufSize)) < 0 && 
676                TSystem::GetErrno() == EINTR)
677           TSystem::ResetErrno();
678         if (len < 0) { 
679           Error("SendFile", "error reading input");
680           close(fd);
681           return -1;
682         }
683         if (len > 0 && sl->GetSocket()->SendRaw(buf, len) == -1) {
684           Error("SendFile", "error writing to slave");
685           sl = 0;
686           break;
687         }
688       } while (len > 0);
689       ret ++;
690
691       // Wait for slave - private
692       // if (sl) gProof->Collect(sl,gEnv->GetValue("Proof.CollectTimeout",-1));
693     }
694
695     // Close the file 
696     close(fd);
697
698     return ret;
699   }
700   /** 
701    * Path of output 
702    * 
703    * @return Path to output - possibly a data set
704    */
705   virtual TString OutputPath() const 
706   {
707     TString ret;
708     if (fOptions.Has("dsname")) {
709       ret = Form("/%s/%s/", gProof->GetGroup(), gProof->GetUser());
710       ret.Append(OutputUtilities::RegisteredDataset());
711     }
712     return ret;
713   }
714   /** 
715    * @return URL help string
716    */
717   virtual const Char_t* UrlHelp() const 
718   {
719     return "proof://<host>[:<port>]/[<dataset>|<path>][?<options>][#<treeName>]";
720   }
721   /** 
722    * @return Short description 
723    */
724   virtual const char* Desc() const { return "PROOF"; }
725   TString fExtraLibs;
726   TString fExtraPars;
727   TString fExtraSrcs;
728   Bool_t  fUsePars;
729   Bool_t  fBasePars;
730   TList   fAuxFiles;
731 };
732 #endif
733 //
734 // EOF
735 //