ROOT logo
/**
 * @file   ProofRailway.C
 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
 * @date   Tue Oct 16 18:58:37 2012
 * 
 * @brief  
 * 
 *
 * @ingroup pwglf_forward_trains_helper
 * 
 */
#ifndef PROOFHELPER_C
#define PROOFHELPER_C
#include "Railway.C"
#ifndef __CINT__
# include "OutputUtilities.C"
# include "ParUtilities.C"
# include "ChainBuilder.C"
# include <TUrl.h>
# include <TString.h>
# include <TProof.h>
# include <TProofLog.h>
# include <TProofDebug.h>
# include <AliAnalysisManager.h>
# include <TEnv.h>
# include <TChain.h>
// For SendFile
# include <TSystem.h>
# include <TSlave.h>
# include <TSocket.h>
# include <cerrno>
#else
class TUrl;
class TChain;
#endif

// ===================================================================
/**
 * Handle analysis on a Proof farm. 
 * 
 * This helper is triggered by URIs of the form 
 *
 * @code
 * proof://[<user>@]<host>[:<port>]/<dsname>[?<options>][#<treename>]
 * @endcode 
 * where 
 * <dl>
 *   <dt>&lt;user&gt;</dt>
 *   <dd>Optional user name</dd>
 *   <dt>&lt;host&gt;</dt>
 *   <dd>PROOF cluster master host</dd>
 *   <dt>&lt;port&gt;</dt>
 *   <dd>Optional PROOF cluster port on master host</dd>
 *   <dt>&lt;dsname&gt;</dt>
 *   <dd>Data set name</dd>
 *   <dt>&lt;treename&gt;</dt>
 *   <dd>Optional tree name in data set, often <tt>esdTree</tt> or
 *   <tt>aodTree</tt></dd>
 *   <dt>&lt;options&gt;</dt>
 *   <dd>List of options separated by an &amp;
 *     <dl>
 *       <dt><tt>workers=N[x]</tt></dt>
 *       <dd>Set the number of workers to use.  If <tt>x</tt> is appended, 
 *         then it's maximum number of workers per slave</dd>
 *       <dt><tt>dsname</tt>[=&lt;output dataset&gt;]</dt>
 *       <dd>Register tree output (e.g., AOD) as a new data set on the
 *         PROOF cluster. If &lt;output dataset&gt; is not specified, take
 *         the name of the train.</dd>
 *       <dt><tt>par[=all]</tt></dt>
 *       <dd>Use PAR files.  If the value <tt>all</tt> is given, then also 
 *         PAR files of STEERBase, ESD, AOD, ANALYSIS, OADB, ANALYSISalice 
 *         are used. </dd>
 *       <dt><tt>mode=[default,rec,sim,train,custom]</tt></dt>
 *       <dd>Set the AliROOT mode.  If not specified <tt>default</tt> 
 *         is assumed.  See also CreateAliROOTPar</dd>
 *       <dt><tt>storage=&lt;url&gt;</tt></dt>
 *       <dd>Specify a non-default storage location for special output
 *         (e.g., AOD trees).  &lt;url&gt; should be a valid XRootd 
 *         server URI accessible to the slaves - e.g., 
 *         <tt>root://lxplus.cern.ch:10930//tmp</tt>.</dd>
 *     </dl>
 *   </dd>
 * </dl>  
 *
 * @ingroup pwglf_forward_trains_helper
 */
struct ProofRailway : public Railway
{
  /** 
   * Constructor 
   * 
   * @param url  Url 
   * @param verbose Verbosity level
   */
  ProofRailway(const TUrl& url, Int_t verbose)
    : Railway(url, verbose), 
      fExtraLibs(""),
      fExtraPars(""),
      fExtraSrcs(""),
      fUsePars(false), 
      fBasePars(false),
      fTestBuild(true),
      fAuxFiles()
  {
    fOptions.Add("workers",  "N[x]", "Number of workers to use", 0);
    fOptions.Add("dsname",   "NAME", "Make output dataset", "");
    fOptions.Add("par",      "tasks|all", "Use par files",           "tasks");
    fOptions.Add("mode",     "default|rec|sim", "AliROOT mode",      "default");
    fOptions.Add("storage",  "URL", "Location for external storage", "");    
    fOptions.Add("wrapper",  "CMD", "Wrapper command", "");
    fOptions.Add("clear",    "PKGS", "Clear packages ','-separated", "");
    fOptions.Add("reset",    "soft|hard", "Reset cluster", "hard");
    fOptions.Add("feedback", "Enable feedback mechanism");
    fOptions.Add("env",      "SCRIPT", "Script to set-up environment","-none-");
    fOptions.Add("offset",   "EVENTS", "Skip this number of events", 0);
    fOptions.Add("testpar",  "Test build PARs");
    if (!fUrl.GetUser() || fUrl.GetUser()[0] == '\0') 
      fUrl.SetUser(gSystem->GetUserInfo()->fUser);
    fAuxFiles.SetOwner();
  }
  ProofRailway(const ProofRailway& o) 
    : Railway(o),
      fExtraLibs(""),
      fExtraPars(""),
      fExtraSrcs(""),
      fUsePars(false), 
      fBasePars(false),
      fTestBuild(true),
      fAuxFiles()
  {}
  ProofRailway& operator=(const ProofRailway& o) 
  {
    if (&o == this) return *this;
    Railway::operator=(o);
    fExtraLibs = o.fExtraLibs;
    fExtraPars = o.fExtraPars;
    fExtraSrcs = o.fExtraSrcs;
    fUsePars   = o.fUsePars;    
    fBasePars  = o.fBasePars;
    fTestBuild = o.fTestBuild;
    // fAuxFiles;
    return *this;
  }
  /** 
   * Destructor 
   */
  virtual ~ProofRailway() {}
  /** 
   * Load a library/PAR/script 
   * 
   * @param name   Name 
   * @param slaves If true, also load on slaves
   * 
   * @return true on success 
   */
  virtual Bool_t LoadLibrary(const TString& name, 
			     Bool_t slaves=true)
  {
    Bool_t isBase = false;
    if (!fBasePars) { 
      if (name.EqualTo("STEERBase")      || 
	  name.EqualTo("ESD")            || 
	  name.EqualTo("AOD")            || 
	  name.EqualTo("ANALYSIS")       || 
	  name.EqualTo("OADB")           || 
	  name.EqualTo("ANALYSISalice")) 
	isBase = true;
    }
    if (!fUsePars || isBase) {
      Int_t ret = gSystem->Load(MakeLibraryName(name));
      if (ret < 0) return false;
      if (slaves) fExtraLibs.Append(Form(":%s", name.Data()));
    }
    else { 
      if (!ParUtilities::Find(name)) { 
	Error("ProofRailway::LoadLibrary", "Failed to find PAR file %s", 
	      name.Data());
	return false;
      }
      if (fTestBuild && !ParUtilities::Build(name)) { 
	Error("ProofRailway::LoadLibrary", "Failed to build PAR file %s", 
	      name.Data());
	return false;
      }
      if (gProof->UploadPackage(name.Data(), TProof::kRemoveOld) < 0) {
	Error("ProofRailway::LoadLibrary", "Failed to upload PAR file %s", 
	      name.Data());
	return false;
      }
      fExtraPars.Append(Form(":%s", name.Data()));
    }
    return true;
  }
  /** 
   * Load a source file, and compile it 
   * 
   * @param name Name of the source file 
   * @param copy If true, copy not link 
   * 
   * @return true on success
   */
  virtual Bool_t LoadSource(const TString& name, bool copy=false)
  {
    if (!Railway::LoadSource(name, copy)) return false;
    fExtraSrcs.Append(Form(":%s", gSystem->BaseName(name.Data())));
    return true;
  }
  /** 
   * Set-up to load the AliROOT libraries 
   * 
   * @return true on success
   */
  virtual Bool_t LoadAliROOT()
  {
    if (!gSystem->Getenv("ALICE_ROOT")) { 
      Error("ProofRailway::LoadAliROOT", "Local AliROOT not available");
      return false;
    }

    Bool_t tmp = fUsePars;
    fUsePars   = fBasePars;
    if (!LoadLibrary("STEERBase"))     return false;
    if (!LoadLibrary("ESD"))           return false;
    if (!LoadLibrary("AOD"))           return false;
    if (!LoadLibrary("ANALYSIS"))      return false;
    if (!LoadLibrary("OADB"))          return false;
    if (!LoadLibrary("ANALYSISalice")) return false;
    fUsePars = tmp;

    return CreateAliROOTPar();
  }
  /** 
   * Get the name of the AliROOT par file to use 
   * 
   * @return String 
   */
  virtual const char* AliROOTParName() const
  {
    return "ALIROOT";
  }
  /** 
   * Create an AliROOT par file from the executing AliROOT.  This PAR
   * file basically uses the environment of the client - that is, we
   * assume that the used AliROOT is accessible on the slaves - e.g.,
   * via an NFS export.
   * 
   * Note, the SETUP.C script take one argument - a TList of TNamed
   * parameters.  Parameters processed are	
   *
   * - ALIROOT_MODE=[default,aliroot,rec,sim,train]
   *   - default: Load base analysis libraries 
   *   - aliroot: Load $ALICE_ROOT/macros/loadlibs.C
   *   - rec:     Load $ALICE_ROOT/macros/loadlibsrec.C
   *   - sim:     Load $ALICE_ROOT/macros/loadlibssim.C
   * - ALIROOT_EXTRA_LIBS Colon separated list of additional (Ali)ROOT
   *   libraries to load on the slaves.
   * 
   * The generated PAR file is uploaded but not enabled until we have 
   * populated fExtraLibs.  The enabling takes place at the end of the 
   * set-up. 
   * 
   * @return true on success, false otherwise.     */
  virtual Bool_t CreateAliROOTPar()
  {
    if (fBasePars) return true;

    TString parName(AliROOTParName());
    TString parFile(Form("%s.par", parName.Data()));

    // --- Check if we have the drirectory already -------------------
    if (gSystem->AccessPathName(parName.Data()) == 0) { 
      // Let's remove it to get a clean slate 
      if (gSystem->Exec(Form("rm -rf %s", parName.Data())) != 0) {
	Error("ProofRailway", "Failed to remove %s", parName.Data());
	return false;
      }
    }
    // --- Check if the PAR file is there, and remove it if so -------
    if (gSystem->AccessPathName(parFile.Data()) == 0) { 
      if (gSystem->Unlink(parFile.Data()) != 0) { 
	Error("ProofRailway::CreateAliROOTPar", "Failed to remove %s", 
	      parFile.Data());
	return false;
      }
    }
      

    // Set-up directories 
    if (gSystem->MakeDirectory(parName) < 0) {
      Error("ProofRailway::CreateAliROOTPar", "Could not make directory '%s'", 
	    parName.Data());
      return false;
    }
    
    if (gSystem->MakeDirectory(Form("%s/PROOF-INF", parName.Data()))) {
      Error("ProofRailway::CreateAliROOTPar", 
	    "Could not make directory %s/PROOF-INF", 
	    parName.Data());
      return false;
    }

    std::ofstream b(Form("%s/PROOF-INF/BUILD.sh",parName.Data()));
    if (!b) { 
      Error("ProofRailway::CreateAliROOTPar", 
	    "Failed to make BUILD.sh shell script");
      return false;
    }
    b << "#!/bin/sh\n\n"
      << "# echo Nothing to do\n"
      << "exit 0\n"
      << std::endl;
    b.close();
    gSystem->Exec(Form("chmod a+x %s/PROOF-INF/BUILD.sh",parName.Data()));

    TString envScript = fOptions.Get("env");
    if (envScript.EqualTo("-none-", TString::kIgnoreCase)) 
      envScript = "";
    if (!envScript.IsNull()) { 
      // If an environment script was specified, copy that to the par
      if (gSystem->AccessPathName(envScript.Data()) == 0) { 
	// Copy script 
	if (gSystem->Exec(Form("cp %s %s/PROOF-INF/", envScript.Data(), 
			       parName.Data())) != 0) {
	  Error("ProofRailway", "Failed to copy %s", envScript.Data());
	  return false;
	}
      }
      else {
	Warning("CreateALIROOTPar", "Couldn't read %s", envScript.Data());
	envScript = "";
      }
    }
    std::ofstream s(Form("%s/PROOF-INF/SETUP.C", parName.Data()));
    if (!s) { 
      Error("ProofRailway::CreateAliROOTPar", 
	    "Failed to make SETUP.C ROOT script");
      return false;
    }
    s << "void SETUP(TList* opts) {\n";
    if (envScript.IsNull()) {
      s << "  gSystem->Setenv(\"ALICE\",\"" 
      << gSystem->Getenv("ALICE") << "\");\n"
      << "  gSystem->Setenv(\"ALICE_ROOT\",\"" 
      << gSystem->Getenv("ALICE_ROOT") << "\");\n"
      << "  gSystem->Setenv(\"ALICE_TARGET\",\"" 
	<< gSystem->Getenv("ALICE_TARGET") << "\");\n";
    if (gSystem->Getenv("OADB_PATH")) 
      s << "  gSystem->Setenv(\"OADB_PATH\",\"" 
	<< gSystem->Getenv("OADB_PATH") << "\");\n";
    }
    else { 
      s << "  gROOT->Macro(\"PROOF-INF/" << gSystem->BaseName(envScript.Data())
	<< "\");\n";
    }
    s  	<< "  gSystem->AddDynamicPath("
	<< "\"$(ALICE_ROOT)/lib/tgt_$(ALICE_TARGET)\");\n";
    s << "  \n"
      << "  // Info(\"SETUP\",\"Loading ROOT libraries\");\n"
      << "  gSystem->Load(\"libTree\");\n"
      << "  gSystem->Load(\"libGeom\");\n"
      << "  gSystem->Load(\"libVMC\");\n"
      << "  gSystem->Load(\"libPhysics\");\n"
      << "  gSystem->Load(\"libMinuit\");\n"
      << "  \n";
    s << "  // Info(\"SETUP\",\"Parameter list:\");\n"
      << "  if (!opts) return;\n"
      << "  //opts->ls();\n"
      << "  \n";
    s << "  TObject* par = opts->FindObject(\"ALIROOT_MODE\");\n"
      << "  if (par) {\n"
      << "    // Info(\"SETUP\",\"ALIROOT mode: %s\", par->GetTitle());\n"
      << "    TString mode(par->GetTitle());\n"
      << "    if (mode.EqualTo(\"default\",TString::kIgnoreCase)) {\n"
      << "      gSystem->Load(\"libSTEERBase\");\n"
      << "      gSystem->Load(\"libESD\");\n"
      << "      gSystem->Load(\"libAOD\");\n"
      << "      gSystem->Load(\"libANALYSIS\");\n"
      << "      gSystem->Load(\"libOADB\");\n"
      << "      gSystem->Load(\"libANALYSISalice\");\n"
      << "    }\n"
      << "    else if (mode.EqualTo(\"aliroot\",TString::kIgnoreCase)) \n"
      << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibs.C\");\n"
      << "    else if (mode.EqualTo(\"rec\",TString::kIgnoreCase)) \n"
      << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibsrec.C\");\n"
      << "    else if (mode.EqualTo(\"sim\",TString::kIgnoreCase)) \n"
      << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibssim.C\");\n"
      << "    else if (mode.EqualTo(\"train\",TString::kIgnoreCase)) \n"
      << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibstrain.C\");\n"
      << "    else if (mode.EqualTo(\"custom\",TString::kIgnoreCase)) \n"
      << "      gROOT->Macro(\"$ALICE_ROOT/macros/loadlibstrain.C\");\n"
      << "  }\n"
      << "  \n";
    s << "  par = opts->FindObject(\"ALIROOT_EXTRA_LIBS\");\n"
      << "  if (par) {\n"
      << "    Info(\"SETUP\",\"Libaries to load: %s\\n\",par->GetTitle());\n"
      << "    TString tit(par->GetTitle());\n"
      << "    TObjArray* tokens = tit.Tokenize(\":\");\n"
      << "    TObject*   lib    = 0;\n"
      << "    TIter      next(tokens);\n"
      << "    while ((lib = next())) {\n"
      << "      TString libName(lib->GetName());\n"
      << "      if (!libName.BeginsWith(\"lib\")) libName.Prepend(\"lib\");\n"
      << "      // Info(\"SETUP\",\"Loading %s ...\",libName.Data());\n"
      << "      gSystem->Load(libName.Data());\n"
      << "    }\n"
      << "  }\n"
      << "}\n"
      << std::endl;
    s.close();

    Int_t ret = gSystem->Exec(Form("tar -czf %s %s",
				   parFile.Data(), parName.Data()));
    if (ret != 0) { 
      Error("ProofRailway::CreateAliROOTPar", "Failed to pack up PAR file %s",
	    parFile.Data());
      return false;
    }

    ret = gProof->UploadPackage(parFile.Data(),TProof::kRemoveOld);
    if (ret != 0) { 
      Error("ProofRailway::CreateAliROOTPar", 
	    "Failed to upload the AliROOT PAR file");
      return false;
    }
    // Note, the PAR isn't enabled until much later when we've
    // collected all the needed libraries in fExtraLibs
    return true;
  }
  /** 
   * Get the mode identifier 
   * 
   * @return Always kProof
   */
  virtual UShort_t Mode() const { return kProof; }
  /**
   * Get the mode string used for AliAnalysisManager::StartAnalysis
   */
  virtual const char* ModeString() const { return "proof"; }
  /** 
   * Set-up done before task set-ups 
   * 
   * @return true on success 
   */
  virtual Bool_t PreSetup()
  {
    // --- Set prefered GSI method ---------------------------------
    gEnv->SetValue("XSec.GSI.DelegProxy", "2");

    // --- Add ALICE_ROOT directory to search path for packages ----
    // Info("ProofRailway::PreSetup", "Set location of packages");
    gEnv->SetValue("Proof.GlobalPackageDirs", 
		   Form("%s:%s", 
			gEnv->GetValue("Proof.GlobalPackageDirs", "."), 
			gSystem->Getenv("ALICE_ROOT")));

    // --- Forming the URI we use to connect with --------------------
    TUrl connect(fUrl);
    connect.SetAnchor("");
    connect.SetFile("");
    connect.SetOptions("");

    // --- Check if we need to reset first ---------------------------
    if (fOptions.Has("reset")) { 
      TString reset = fOptions.Get("reset");
      Bool_t  hard  = (reset.IsNull() || 
		       reset.EqualTo("hard", TString::kIgnoreCase));
      Info("ProofRailway::PreSetup", "Doing a %s reset of %s", 
	   hard ? "hard" : "soft", connect.GetUrl());
      TProof::Reset(connect.GetUrl(), hard);
      Int_t secs = 3;
      Info("ProofRailway::PreSetup", 
	   "Waiting for %d second%s for things to settle", secs,
	   secs > 1 ? "s" : "");
      gSystem->Sleep(1000*secs);
    }
      
    // --- Check if we're using a wrapper ----------------------------
    if (fOptions.Has("wrapper")) { 
      TString wrapper = fOptions.Get("wrapper");
      if (wrapper.IsNull()) 
	// In case of no argument, use GDB 
	// Just run and backtrace 
	wrapper = "/usr/bin/gdb --batch -ex run -ex bt --args";
      Info("ProofRailway::PreSetup", "Using wrapper command: %s", 
	   wrapper.Data());
      TProof::AddEnvVar("PROOF_WRAPPERCMD", wrapper);
    }

    // --- PAR parameters --------------------------------------------
    fUsePars   = fOptions.Has("par");
    fBasePars  = (fUsePars && 
		  fOptions.Get("par").EqualTo("all",TString::kIgnoreCase));
    fTestBuild = fOptions.Has("testpar");

    // --- Connect to the cluster ------------------------------------
    TString opts;
    if (fOptions.Has("workers")) 
      opts.Append(Form("workers=%s", fOptions.Get("workers").Data()));
      
    Info("ProofRailway::PreSetup", "Connecting to %s with %soptions %s", 
	 connect.GetUrl(), 
	 opts.IsNull() ? "no " : "", 
	 opts.Data());
    TString proto(connect.GetProtocol());
    if (proto.BeginsWith("lite") && fOptions.Has("workers")) 
      TProof::Open(opts);
    else 
      TProof::Open(connect.GetUrl(), opts);
    // TProof::Open(connect.GetHost(), opts);
    if (!gProof) { 
      Error("ProofRailway::PreSetup", "Failed to open Proof connection %s", 
	    connect.GetUrl());
      return false;
    }
    
    // --- Check if we need to clear packages ------------------------
    if (fOptions.Has("clear")) {
      TString pkgs = fOptions.Get("clear");
      if (pkgs.IsNull() || pkgs.EqualTo("all", TString::kIgnoreCase)) { 
	// No value given, clear all 
	if (gProof->ClearPackages() != 0) 
	  Warning("ProofRailway::PreSetup", "Failed to lear all packages");
      }
      else { 
	// Tokenize on ',' and clear each package 
	TObjArray* pars = pkgs.Tokenize(",");
	TObject*   pkg  = 0;
	TIter      next(pars); 
	while ((pkg = next())) { 
	  if (gProof->ClearPackage(pkg->GetName()) != 0)
	    Warning("ProofRailway::PreSetup", "Failed to clear package %s", 
		    pkg->GetName());
	}
	pars->Delete();
      }
    }
    return true;
  }
  /** 
   * Set-up done after the task set-ups 
   *
   * @return true on success 
   */
  virtual Bool_t PostSetup() 
  {
    AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) { 
      Error("ProofRailway::PostSetup", "No analysis manager defined");
      return false;
    }

    // --- Check for output ------------------------------------------
    if (fOptions.Has("dsname")) 
      OutputUtilities::RegisterDataset(fOptions.Get("dsname"));
    if (fOptions.Has("storage"))
      OutputUtilities::RegisterStorage(fOptions.Get("storage"));

    // --- Check for feedback mechanism ------------------------------
    if (!fOptions.Has("feedback"))
      gProof->ClearFeedback();

    // --- If we are not using PARs for Base, enable special PAR -----
    if (!fBasePars) {
      TString tmp(fExtraLibs.Strip(TString::kBoth,':'));
      TList* params = new TList;
      params->SetOwner(true);
      params->Add(new TNamed("ALIROOT_EXTRA_LIBS", tmp.Data()));
      if (fOptions.Has("mode"))
	params->Add(new TNamed("ALIROOT_MODE", fOptions.Get("mode").Data()));
      else
	params->Add(new TNamed("ALIROOT_MODE", "default"));
      Int_t ret = gProof->EnablePackage(AliROOTParName(), params, true);
      if (ret < 0) {
	Error("ProofRailway::EnableAliROOT", "Failed to enable AliROOT PAR %s", 
	      AliROOTParName());
	return false;
      }
    }

    // --- Make PAR file of Aux Files --------------------------------
    if (fAuxFiles.GetEntries() > 0) { 
      TString name = TString::Format("%s_auxfiles", mgr->GetName());
      ParUtilities::MakeAuxFilePAR(fAuxFiles, name);

      if (gProof->UploadPackage(name.Data(), TProof::kRemoveOld) < 0) 
	Error("ProofRailway::PostSetup", "Failed to upload PAR file %s", 
	      name.Data());
      else 
	fExtraPars.Append(Form(":%s", name.Data()));
    }
    
    // --- Load par files --------------------------------------------
    TString    tmp  = fExtraPars.Strip(TString::kBoth,':');
    TObjArray* pars = tmp.Tokenize(":");
    TObject*   obj  = 0;
    TIter      next(pars);
    while ((obj = next())) { 
      // Enable the package, but do not build on client - already done
      Int_t ret = gProof->EnablePackage(obj->GetName(), true);
      if (ret < 0) { 
	Error("ProofRailway::PostSetup", "Failed to enable PAR %s",
	      obj->GetName());
	return false;
      }
    }
    
    // --- Load extra sources ----------------------------------------
    TString    tmp2 = fExtraSrcs.Strip(TString::kBoth, ':');
    TObjArray* srcs = tmp2.Tokenize(":");
    TIter      next2(srcs);
    while ((obj = next())) { 
      Int_t ret = gProof->Load(Form("%s++g", obj->GetName()), true);
      if (ret < 0) { 
	Error("ProofRailway::PostSetup", "Failed to compile %s", obj->GetName());
	return false;
      }
    }
    return true;
  }
  /** 
   * Start the analysis 
   * 
   * @param nEvents Number of events to analyse 
   * 
   * @return The return value of AliAnalysisManager::StartAnalysis
   */
  virtual Long64_t Run(Long64_t nEvents=-1) 
  {
    AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
    gProof->SetLogLevel(TMath::Max(fVerbose-2,0), 
			/* TProofDebug::kPacketizer| */
			TProofDebug::kLoop|
			/* TProofDebug::kSelector|
			TProofDebug::kOutput|
			TProofDebug::kInput|
			TProofDebug::kGlobal|*/
			TProofDebug::kPackage);
    TString dsName(fUrl.GetFile());
    // if (fUrl.GetAnchor() && fUrl.GetAnchor()[0] != '\0') 
    //   dsName.Append(Form("#%s", fUrl.GetAnchor()));
    // Info("Run", "Output objects registered with PROOF:");
    // gProof->GetOutputList()->ls();
    Long64_t off = fOptions.AsLong("offset", 0);
    if (nEvents > 0 && nEvents < off) {
      Warning("Run", "Number of events %lld < offset (%lld), stopping", 
	      nEvents, off);
      return 0;
    }
    Long64_t ret = mgr->StartAnalysis(fUrl.GetProtocol(), dsName, nEvents, off);
    
    if (fVerbose > 10) 
      TProof::Mgr(fUrl.GetUrl())->GetSessionLogs()->Save("*","proof.log");
    return ret;
  }
#if 0
  Bool_t AddMonitor(const TString& path)
  {
    if (path.IsNull()) return true;

    TObjArray* tokens  = path.Tokenize("/");
    Int_t      nTokens = tokens->GetEntries();
    if (nTokens < 2) { 
      Error("AddMonitor", "Monitors must be of the form:\n"
	    "  <task>[:<slot>]/<name>\n"
	    "  <task>[:<slot>]/<path>/<name>");
      return false;
    }
    // --- Get the manager 
    AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();

    // --- Extract task and possibly slot number 
    TString& sTask  = static_cast<TObjString*>(tokens->At(0))->String();
    Int_t    slotNo = 0;
    Ssiz_t   colon  = sTask.Index(":");
    if (colon != kNPOS) { 
      TString sSlot = sTask(colon+1, sTask.Length()-colon-1);
      if (!sSlot.IsNull()) slotNo = sSlot.Atoi();
      sTask.Remove(colon, sTask.Length()-colon);
    }
    
    AliAnalysisTask* task = mgr->GetTask(sTask);
    if (!task) { 
      Error("AddMonitor", "Task \"%s\" not registered with manager", 
	    sTask.Data());
      return false;
    }
    AliAnalysisDataSlot* slot = task->GetOutputSlot(slotNo);
    if (!slot) { 
      Error("AddMonitor", "Task \"%s\" does not have an output slot at %d",
	    task->GetName(), slotNo);
      return false;
    }
    AliAnalysisDataContainer* cont = slot->GetContainer();
    if (!cont) {
      Error("AddMonitor", "Output slot %d of task \"%s\" has no container",
	    slotNo, task->GetName());
      return false;
    }
    Int_t    idx   = 1;
    TString& first = static_cast<TObjString*>(tokens->At(idx))->String(); 
    if (first.EqualTo(cont->GetName())) {
      idx++;
    }
    TObject* data = cont->GetData();
    TObject* obj  = data; 
    for (; idx < nTokens; idx++) {
    }
    return true;
  }
#endif
  /** 
   * Print information to standard output
   * 
   * @param option 
   */
  virtual void Print(Option_t* option="") const 
  {
    Railway::Print(option);
    std::cout << std::boolalpha 
	      << "  --- Other settings -------\n"
	      << "  Extra libraries  : " << fExtraLibs << "\n"
	      << "  Extra PARs       : " << fExtraPars << "\n"
	      << "  Extra sources    : " << fExtraSrcs << "\n"
	      << "  Use PARs of tasks: " << fUsePars   << "\n"
	      << "  Use PARs of base : " << fBasePars  
	      << std::noboolalpha << std::endl;
  }
  /** 
   * Link an auxilary file to working directory 
   * 
   * @param name Name of the file
   * @param copy Copy rather than link
   *
   * @return true on success
   */
  virtual Bool_t AuxFile(const TString& name, bool copy=false)
  {
    Bool_t ret = Railway::AuxFile(name, copy);
    if (!name.BeginsWith("/")) {
      fAuxFiles.Add(new TObjString(name));
    }
#if 0
    if (ret && name.EndsWith(".root")) { 
      TFile* file = TFile::Open(name, "READ");
      if (file) {
	Info("AuxFile", "Adding input file %s", name.Data());
	gProof->AddInputData(file, true);
      }
    }
#endif
    return ret;
  }
  Int_t SendFile(const TString& fileName) 
  {
    Int_t    bufSize = 32768;
    Char_t   buf[bufSize];
    Long64_t size = 0;
    Long_t   id = 0, flags = 0, modtime = 0;
    if (gSystem->GetPathInfo(fileName.Data(), &id, &size, &flags, &modtime)==1 
	|| size <= 0) {
      Error("SendFile", "Cannot stat %s", fileName.Data());
      return -1;
    }
    TString fn(gSystem->BaseName(fileName.Data()));
    TList*  slaves = 0; // gProof->GetListOfActiveSlaves(); - protected
    TIter   next(slaves);
    TSlave* sl   = 0;
    Int_t   ret  = 0;
    Int_t   fd = open(fileName.Data(), O_RDONLY);
    while ((sl = static_cast<TSlave*>(next()))) {
      if (!sl->IsValid()) continue;
      if (sl->GetSlaveType() != TSlave::kSlave) continue;
      
      // Always binary (first 1), never forward (last 0).
      snprintf(buf,bufSize,"%s %d %lld %d", fn.Data(), 1, size, 0);
      if (sl->GetSocket()->Send(buf, kPROOF_SENDFILE) == -1) {
	Warning("SendFile", "Could not send kPROOF_SENDFILE request");
	continue;
      }

      // Go to the beginning of the file 
      lseek(fd, 0, SEEK_SET);
      Int_t len = 0;
      do { 
	while ((len = read(fd, buf, bufSize)) < 0 && 
	       TSystem::GetErrno() == EINTR)
	  TSystem::ResetErrno();
	if (len < 0) { 
	  Error("SendFile", "error reading input");
	  close(fd);
	  return -1;
	}
	if (len > 0 && sl->GetSocket()->SendRaw(buf, len) == -1) {
	  Error("SendFile", "error writing to slave");
	  sl = 0;
	  break;
	}
      } while (len > 0);
      ret ++;

      // Wait for slave - private
      // if (sl) gProof->Collect(sl,gEnv->GetValue("Proof.CollectTimeout",-1));
    }

    // Close the file 
    close(fd);

    return ret;
  }
  /** 
   * Path of output 
   * 
   * @return Path to output - possibly a data set
   */
  virtual TString OutputPath() const 
  {
    TString ret;
    if (fOptions.Has("dsname")) {
      ret = Form("/%s/%s/", gProof->GetGroup(), gProof->GetUser());
      ret.Append(OutputUtilities::RegisteredDataset());
    }
    return ret;
  }
  /** 
   * @return URL help string
   */
  virtual const Char_t* UrlHelp() const 
  {
    return "proof://<host>[:<port>]/[<dataset>|<path>][?<options>][#<treeName>]";
  }
  /** 
   * @return Short description 
   */
  virtual const char* Desc() const { return "PROOF"; }
  TString fExtraLibs;
  TString fExtraPars;
  TString fExtraSrcs;
  Bool_t  fUsePars;
  Bool_t  fBasePars;
  Bool_t  fTestBuild;
  TList   fAuxFiles;
};
#endif
//
// EOF
//
 ProofRailway.C:1
 ProofRailway.C:2
 ProofRailway.C:3
 ProofRailway.C:4
 ProofRailway.C:5
 ProofRailway.C:6
 ProofRailway.C:7
 ProofRailway.C:8
 ProofRailway.C:9
 ProofRailway.C:10
 ProofRailway.C:11
 ProofRailway.C:12
 ProofRailway.C:13
 ProofRailway.C:14
 ProofRailway.C:15
 ProofRailway.C:16
 ProofRailway.C:17
 ProofRailway.C:18
 ProofRailway.C:19
 ProofRailway.C:20
 ProofRailway.C:21
 ProofRailway.C:22
 ProofRailway.C:23
 ProofRailway.C:24
 ProofRailway.C:25
 ProofRailway.C:26
 ProofRailway.C:27
 ProofRailway.C:28
 ProofRailway.C:29
 ProofRailway.C:30
 ProofRailway.C:31
 ProofRailway.C:32
 ProofRailway.C:33
 ProofRailway.C:34
 ProofRailway.C:35
 ProofRailway.C:36
 ProofRailway.C:37
 ProofRailway.C:38
 ProofRailway.C:39
 ProofRailway.C:40
 ProofRailway.C:41
 ProofRailway.C:42
 ProofRailway.C:43
 ProofRailway.C:44
 ProofRailway.C:45
 ProofRailway.C:46
 ProofRailway.C:47
 ProofRailway.C:48
 ProofRailway.C:49
 ProofRailway.C:50
 ProofRailway.C:51
 ProofRailway.C:52
 ProofRailway.C:53
 ProofRailway.C:54
 ProofRailway.C:55
 ProofRailway.C:56
 ProofRailway.C:57
 ProofRailway.C:58
 ProofRailway.C:59
 ProofRailway.C:60
 ProofRailway.C:61
 ProofRailway.C:62
 ProofRailway.C:63
 ProofRailway.C:64
 ProofRailway.C:65
 ProofRailway.C:66
 ProofRailway.C:67
 ProofRailway.C:68
 ProofRailway.C:69
 ProofRailway.C:70
 ProofRailway.C:71
 ProofRailway.C:72
 ProofRailway.C:73
 ProofRailway.C:74
 ProofRailway.C:75
 ProofRailway.C:76
 ProofRailway.C:77
 ProofRailway.C:78
 ProofRailway.C:79
 ProofRailway.C:80
 ProofRailway.C:81
 ProofRailway.C:82
 ProofRailway.C:83
 ProofRailway.C:84
 ProofRailway.C:85
 ProofRailway.C:86
 ProofRailway.C:87
 ProofRailway.C:88
 ProofRailway.C:89
 ProofRailway.C:90
 ProofRailway.C:91
 ProofRailway.C:92
 ProofRailway.C:93
 ProofRailway.C:94
 ProofRailway.C:95
 ProofRailway.C:96
 ProofRailway.C:97
 ProofRailway.C:98
 ProofRailway.C:99
 ProofRailway.C:100
 ProofRailway.C:101
 ProofRailway.C:102
 ProofRailway.C:103
 ProofRailway.C:104
 ProofRailway.C:105
 ProofRailway.C:106
 ProofRailway.C:107
 ProofRailway.C:108
 ProofRailway.C:109
 ProofRailway.C:110
 ProofRailway.C:111
 ProofRailway.C:112
 ProofRailway.C:113
 ProofRailway.C:114
 ProofRailway.C:115
 ProofRailway.C:116
 ProofRailway.C:117
 ProofRailway.C:118
 ProofRailway.C:119
 ProofRailway.C:120
 ProofRailway.C:121
 ProofRailway.C:122
 ProofRailway.C:123
 ProofRailway.C:124
 ProofRailway.C:125
 ProofRailway.C:126
 ProofRailway.C:127
 ProofRailway.C:128
 ProofRailway.C:129
 ProofRailway.C:130
 ProofRailway.C:131
 ProofRailway.C:132
 ProofRailway.C:133
 ProofRailway.C:134
 ProofRailway.C:135
 ProofRailway.C:136
 ProofRailway.C:137
 ProofRailway.C:138
 ProofRailway.C:139
 ProofRailway.C:140
 ProofRailway.C:141
 ProofRailway.C:142
 ProofRailway.C:143
 ProofRailway.C:144
 ProofRailway.C:145
 ProofRailway.C:146
 ProofRailway.C:147
 ProofRailway.C:148
 ProofRailway.C:149
 ProofRailway.C:150
 ProofRailway.C:151
 ProofRailway.C:152
 ProofRailway.C:153
 ProofRailway.C:154
 ProofRailway.C:155
 ProofRailway.C:156
 ProofRailway.C:157
 ProofRailway.C:158
 ProofRailway.C:159
 ProofRailway.C:160
 ProofRailway.C:161
 ProofRailway.C:162
 ProofRailway.C:163
 ProofRailway.C:164
 ProofRailway.C:165
 ProofRailway.C:166
 ProofRailway.C:167
 ProofRailway.C:168
 ProofRailway.C:169
 ProofRailway.C:170
 ProofRailway.C:171
 ProofRailway.C:172
 ProofRailway.C:173
 ProofRailway.C:174
 ProofRailway.C:175
 ProofRailway.C:176
 ProofRailway.C:177
 ProofRailway.C:178
 ProofRailway.C:179
 ProofRailway.C:180
 ProofRailway.C:181
 ProofRailway.C:182
 ProofRailway.C:183
 ProofRailway.C:184
 ProofRailway.C:185
 ProofRailway.C:186
 ProofRailway.C:187
 ProofRailway.C:188
 ProofRailway.C:189
 ProofRailway.C:190
 ProofRailway.C:191
 ProofRailway.C:192
 ProofRailway.C:193
 ProofRailway.C:194
 ProofRailway.C:195
 ProofRailway.C:196
 ProofRailway.C:197
 ProofRailway.C:198
 ProofRailway.C:199
 ProofRailway.C:200
 ProofRailway.C:201
 ProofRailway.C:202
 ProofRailway.C:203
 ProofRailway.C:204
 ProofRailway.C:205
 ProofRailway.C:206
 ProofRailway.C:207
 ProofRailway.C:208
 ProofRailway.C:209
 ProofRailway.C:210
 ProofRailway.C:211
 ProofRailway.C:212
 ProofRailway.C:213
 ProofRailway.C:214
 ProofRailway.C:215
 ProofRailway.C:216
 ProofRailway.C:217
 ProofRailway.C:218
 ProofRailway.C:219
 ProofRailway.C:220
 ProofRailway.C:221
 ProofRailway.C:222
 ProofRailway.C:223
 ProofRailway.C:224
 ProofRailway.C:225
 ProofRailway.C:226
 ProofRailway.C:227
 ProofRailway.C:228
 ProofRailway.C:229
 ProofRailway.C:230
 ProofRailway.C:231
 ProofRailway.C:232
 ProofRailway.C:233
 ProofRailway.C:234
 ProofRailway.C:235
 ProofRailway.C:236
 ProofRailway.C:237
 ProofRailway.C:238
 ProofRailway.C:239
 ProofRailway.C:240
 ProofRailway.C:241
 ProofRailway.C:242
 ProofRailway.C:243
 ProofRailway.C:244
 ProofRailway.C:245
 ProofRailway.C:246
 ProofRailway.C:247
 ProofRailway.C:248
 ProofRailway.C:249
 ProofRailway.C:250
 ProofRailway.C:251
 ProofRailway.C:252
 ProofRailway.C:253
 ProofRailway.C:254
 ProofRailway.C:255
 ProofRailway.C:256
 ProofRailway.C:257
 ProofRailway.C:258
 ProofRailway.C:259
 ProofRailway.C:260
 ProofRailway.C:261
 ProofRailway.C:262
 ProofRailway.C:263
 ProofRailway.C:264
 ProofRailway.C:265
 ProofRailway.C:266
 ProofRailway.C:267
 ProofRailway.C:268
 ProofRailway.C:269
 ProofRailway.C:270
 ProofRailway.C:271
 ProofRailway.C:272
 ProofRailway.C:273
 ProofRailway.C:274
 ProofRailway.C:275
 ProofRailway.C:276
 ProofRailway.C:277
 ProofRailway.C:278
 ProofRailway.C:279
 ProofRailway.C:280
 ProofRailway.C:281
 ProofRailway.C:282
 ProofRailway.C:283
 ProofRailway.C:284
 ProofRailway.C:285
 ProofRailway.C:286
 ProofRailway.C:287
 ProofRailway.C:288
 ProofRailway.C:289
 ProofRailway.C:290
 ProofRailway.C:291
 ProofRailway.C:292
 ProofRailway.C:293
 ProofRailway.C:294
 ProofRailway.C:295
 ProofRailway.C:296
 ProofRailway.C:297
 ProofRailway.C:298
 ProofRailway.C:299
 ProofRailway.C:300
 ProofRailway.C:301
 ProofRailway.C:302
 ProofRailway.C:303
 ProofRailway.C:304
 ProofRailway.C:305
 ProofRailway.C:306
 ProofRailway.C:307
 ProofRailway.C:308
 ProofRailway.C:309
 ProofRailway.C:310
 ProofRailway.C:311
 ProofRailway.C:312
 ProofRailway.C:313
 ProofRailway.C:314
 ProofRailway.C:315
 ProofRailway.C:316
 ProofRailway.C:317
 ProofRailway.C:318
 ProofRailway.C:319
 ProofRailway.C:320
 ProofRailway.C:321
 ProofRailway.C:322
 ProofRailway.C:323
 ProofRailway.C:324
 ProofRailway.C:325
 ProofRailway.C:326
 ProofRailway.C:327
 ProofRailway.C:328
 ProofRailway.C:329
 ProofRailway.C:330
 ProofRailway.C:331
 ProofRailway.C:332
 ProofRailway.C:333
 ProofRailway.C:334
 ProofRailway.C:335
 ProofRailway.C:336
 ProofRailway.C:337
 ProofRailway.C:338
 ProofRailway.C:339
 ProofRailway.C:340
 ProofRailway.C:341
 ProofRailway.C:342
 ProofRailway.C:343
 ProofRailway.C:344
 ProofRailway.C:345
 ProofRailway.C:346
 ProofRailway.C:347
 ProofRailway.C:348
 ProofRailway.C:349
 ProofRailway.C:350
 ProofRailway.C:351
 ProofRailway.C:352
 ProofRailway.C:353
 ProofRailway.C:354
 ProofRailway.C:355
 ProofRailway.C:356
 ProofRailway.C:357
 ProofRailway.C:358
 ProofRailway.C:359
 ProofRailway.C:360
 ProofRailway.C:361
 ProofRailway.C:362
 ProofRailway.C:363
 ProofRailway.C:364
 ProofRailway.C:365
 ProofRailway.C:366
 ProofRailway.C:367
 ProofRailway.C:368
 ProofRailway.C:369
 ProofRailway.C:370
 ProofRailway.C:371
 ProofRailway.C:372
 ProofRailway.C:373
 ProofRailway.C:374
 ProofRailway.C:375
 ProofRailway.C:376
 ProofRailway.C:377
 ProofRailway.C:378
 ProofRailway.C:379
 ProofRailway.C:380
 ProofRailway.C:381
 ProofRailway.C:382
 ProofRailway.C:383
 ProofRailway.C:384
 ProofRailway.C:385
 ProofRailway.C:386
 ProofRailway.C:387
 ProofRailway.C:388
 ProofRailway.C:389
 ProofRailway.C:390
 ProofRailway.C:391
 ProofRailway.C:392
 ProofRailway.C:393
 ProofRailway.C:394
 ProofRailway.C:395
 ProofRailway.C:396
 ProofRailway.C:397
 ProofRailway.C:398
 ProofRailway.C:399
 ProofRailway.C:400
 ProofRailway.C:401
 ProofRailway.C:402
 ProofRailway.C:403
 ProofRailway.C:404
 ProofRailway.C:405
 ProofRailway.C:406
 ProofRailway.C:407
 ProofRailway.C:408
 ProofRailway.C:409
 ProofRailway.C:410
 ProofRailway.C:411
 ProofRailway.C:412
 ProofRailway.C:413
 ProofRailway.C:414
 ProofRailway.C:415
 ProofRailway.C:416
 ProofRailway.C:417
 ProofRailway.C:418
 ProofRailway.C:419
 ProofRailway.C:420
 ProofRailway.C:421
 ProofRailway.C:422
 ProofRailway.C:423
 ProofRailway.C:424
 ProofRailway.C:425
 ProofRailway.C:426
 ProofRailway.C:427
 ProofRailway.C:428
 ProofRailway.C:429
 ProofRailway.C:430
 ProofRailway.C:431
 ProofRailway.C:432
 ProofRailway.C:433
 ProofRailway.C:434
 ProofRailway.C:435
 ProofRailway.C:436
 ProofRailway.C:437
 ProofRailway.C:438
 ProofRailway.C:439
 ProofRailway.C:440
 ProofRailway.C:441
 ProofRailway.C:442
 ProofRailway.C:443
 ProofRailway.C:444
 ProofRailway.C:445
 ProofRailway.C:446
 ProofRailway.C:447
 ProofRailway.C:448
 ProofRailway.C:449
 ProofRailway.C:450
 ProofRailway.C:451
 ProofRailway.C:452
 ProofRailway.C:453
 ProofRailway.C:454
 ProofRailway.C:455
 ProofRailway.C:456
 ProofRailway.C:457
 ProofRailway.C:458
 ProofRailway.C:459
 ProofRailway.C:460
 ProofRailway.C:461
 ProofRailway.C:462
 ProofRailway.C:463
 ProofRailway.C:464
 ProofRailway.C:465
 ProofRailway.C:466
 ProofRailway.C:467
 ProofRailway.C:468
 ProofRailway.C:469
 ProofRailway.C:470
 ProofRailway.C:471
 ProofRailway.C:472
 ProofRailway.C:473
 ProofRailway.C:474
 ProofRailway.C:475
 ProofRailway.C:476
 ProofRailway.C:477
 ProofRailway.C:478
 ProofRailway.C:479
 ProofRailway.C:480
 ProofRailway.C:481
 ProofRailway.C:482
 ProofRailway.C:483
 ProofRailway.C:484
 ProofRailway.C:485
 ProofRailway.C:486
 ProofRailway.C:487
 ProofRailway.C:488
 ProofRailway.C:489
 ProofRailway.C:490
 ProofRailway.C:491
 ProofRailway.C:492
 ProofRailway.C:493
 ProofRailway.C:494
 ProofRailway.C:495
 ProofRailway.C:496
 ProofRailway.C:497
 ProofRailway.C:498
 ProofRailway.C:499
 ProofRailway.C:500
 ProofRailway.C:501
 ProofRailway.C:502
 ProofRailway.C:503
 ProofRailway.C:504
 ProofRailway.C:505
 ProofRailway.C:506
 ProofRailway.C:507
 ProofRailway.C:508
 ProofRailway.C:509
 ProofRailway.C:510
 ProofRailway.C:511
 ProofRailway.C:512
 ProofRailway.C:513
 ProofRailway.C:514
 ProofRailway.C:515
 ProofRailway.C:516
 ProofRailway.C:517
 ProofRailway.C:518
 ProofRailway.C:519
 ProofRailway.C:520
 ProofRailway.C:521
 ProofRailway.C:522
 ProofRailway.C:523
 ProofRailway.C:524
 ProofRailway.C:525
 ProofRailway.C:526
 ProofRailway.C:527
 ProofRailway.C:528
 ProofRailway.C:529
 ProofRailway.C:530
 ProofRailway.C:531
 ProofRailway.C:532
 ProofRailway.C:533
 ProofRailway.C:534
 ProofRailway.C:535
 ProofRailway.C:536
 ProofRailway.C:537
 ProofRailway.C:538
 ProofRailway.C:539
 ProofRailway.C:540
 ProofRailway.C:541
 ProofRailway.C:542
 ProofRailway.C:543
 ProofRailway.C:544
 ProofRailway.C:545
 ProofRailway.C:546
 ProofRailway.C:547
 ProofRailway.C:548
 ProofRailway.C:549
 ProofRailway.C:550
 ProofRailway.C:551
 ProofRailway.C:552
 ProofRailway.C:553
 ProofRailway.C:554
 ProofRailway.C:555
 ProofRailway.C:556
 ProofRailway.C:557
 ProofRailway.C:558
 ProofRailway.C:559
 ProofRailway.C:560
 ProofRailway.C:561
 ProofRailway.C:562
 ProofRailway.C:563
 ProofRailway.C:564
 ProofRailway.C:565
 ProofRailway.C:566
 ProofRailway.C:567
 ProofRailway.C:568
 ProofRailway.C:569
 ProofRailway.C:570
 ProofRailway.C:571
 ProofRailway.C:572
 ProofRailway.C:573
 ProofRailway.C:574
 ProofRailway.C:575
 ProofRailway.C:576
 ProofRailway.C:577
 ProofRailway.C:578
 ProofRailway.C:579
 ProofRailway.C:580
 ProofRailway.C:581
 ProofRailway.C:582
 ProofRailway.C:583
 ProofRailway.C:584
 ProofRailway.C:585
 ProofRailway.C:586
 ProofRailway.C:587
 ProofRailway.C:588
 ProofRailway.C:589
 ProofRailway.C:590
 ProofRailway.C:591
 ProofRailway.C:592
 ProofRailway.C:593
 ProofRailway.C:594
 ProofRailway.C:595
 ProofRailway.C:596
 ProofRailway.C:597
 ProofRailway.C:598
 ProofRailway.C:599
 ProofRailway.C:600
 ProofRailway.C:601
 ProofRailway.C:602
 ProofRailway.C:603
 ProofRailway.C:604
 ProofRailway.C:605
 ProofRailway.C:606
 ProofRailway.C:607
 ProofRailway.C:608
 ProofRailway.C:609
 ProofRailway.C:610
 ProofRailway.C:611
 ProofRailway.C:612
 ProofRailway.C:613
 ProofRailway.C:614
 ProofRailway.C:615
 ProofRailway.C:616
 ProofRailway.C:617
 ProofRailway.C:618
 ProofRailway.C:619
 ProofRailway.C:620
 ProofRailway.C:621
 ProofRailway.C:622
 ProofRailway.C:623
 ProofRailway.C:624
 ProofRailway.C:625
 ProofRailway.C:626
 ProofRailway.C:627
 ProofRailway.C:628
 ProofRailway.C:629
 ProofRailway.C:630
 ProofRailway.C:631
 ProofRailway.C:632
 ProofRailway.C:633
 ProofRailway.C:634
 ProofRailway.C:635
 ProofRailway.C:636
 ProofRailway.C:637
 ProofRailway.C:638
 ProofRailway.C:639
 ProofRailway.C:640
 ProofRailway.C:641
 ProofRailway.C:642
 ProofRailway.C:643
 ProofRailway.C:644
 ProofRailway.C:645
 ProofRailway.C:646
 ProofRailway.C:647
 ProofRailway.C:648
 ProofRailway.C:649
 ProofRailway.C:650
 ProofRailway.C:651
 ProofRailway.C:652
 ProofRailway.C:653
 ProofRailway.C:654
 ProofRailway.C:655
 ProofRailway.C:656
 ProofRailway.C:657
 ProofRailway.C:658
 ProofRailway.C:659
 ProofRailway.C:660
 ProofRailway.C:661
 ProofRailway.C:662
 ProofRailway.C:663
 ProofRailway.C:664
 ProofRailway.C:665
 ProofRailway.C:666
 ProofRailway.C:667
 ProofRailway.C:668
 ProofRailway.C:669
 ProofRailway.C:670
 ProofRailway.C:671
 ProofRailway.C:672
 ProofRailway.C:673
 ProofRailway.C:674
 ProofRailway.C:675
 ProofRailway.C:676
 ProofRailway.C:677
 ProofRailway.C:678
 ProofRailway.C:679
 ProofRailway.C:680
 ProofRailway.C:681
 ProofRailway.C:682
 ProofRailway.C:683
 ProofRailway.C:684
 ProofRailway.C:685
 ProofRailway.C:686
 ProofRailway.C:687
 ProofRailway.C:688
 ProofRailway.C:689
 ProofRailway.C:690
 ProofRailway.C:691
 ProofRailway.C:692
 ProofRailway.C:693
 ProofRailway.C:694
 ProofRailway.C:695
 ProofRailway.C:696
 ProofRailway.C:697
 ProofRailway.C:698
 ProofRailway.C:699
 ProofRailway.C:700
 ProofRailway.C:701
 ProofRailway.C:702
 ProofRailway.C:703
 ProofRailway.C:704
 ProofRailway.C:705
 ProofRailway.C:706
 ProofRailway.C:707
 ProofRailway.C:708
 ProofRailway.C:709
 ProofRailway.C:710
 ProofRailway.C:711
 ProofRailway.C:712
 ProofRailway.C:713
 ProofRailway.C:714
 ProofRailway.C:715
 ProofRailway.C:716
 ProofRailway.C:717
 ProofRailway.C:718
 ProofRailway.C:719
 ProofRailway.C:720
 ProofRailway.C:721
 ProofRailway.C:722
 ProofRailway.C:723
 ProofRailway.C:724
 ProofRailway.C:725
 ProofRailway.C:726
 ProofRailway.C:727
 ProofRailway.C:728
 ProofRailway.C:729
 ProofRailway.C:730
 ProofRailway.C:731
 ProofRailway.C:732
 ProofRailway.C:733
 ProofRailway.C:734
 ProofRailway.C:735
 ProofRailway.C:736
 ProofRailway.C:737
 ProofRailway.C:738
 ProofRailway.C:739
 ProofRailway.C:740
 ProofRailway.C:741
 ProofRailway.C:742
 ProofRailway.C:743
 ProofRailway.C:744
 ProofRailway.C:745
 ProofRailway.C:746
 ProofRailway.C:747
 ProofRailway.C:748
 ProofRailway.C:749
 ProofRailway.C:750
 ProofRailway.C:751
 ProofRailway.C:752
 ProofRailway.C:753
 ProofRailway.C:754
 ProofRailway.C:755
 ProofRailway.C:756
 ProofRailway.C:757
 ProofRailway.C:758
 ProofRailway.C:759
 ProofRailway.C:760
 ProofRailway.C:761
 ProofRailway.C:762
 ProofRailway.C:763
 ProofRailway.C:764
 ProofRailway.C:765
 ProofRailway.C:766
 ProofRailway.C:767
 ProofRailway.C:768
 ProofRailway.C:769
 ProofRailway.C:770
 ProofRailway.C:771
 ProofRailway.C:772
 ProofRailway.C:773
 ProofRailway.C:774
 ProofRailway.C:775
 ProofRailway.C:776
 ProofRailway.C:777
 ProofRailway.C:778
 ProofRailway.C:779
 ProofRailway.C:780
 ProofRailway.C:781
 ProofRailway.C:782
 ProofRailway.C:783
 ProofRailway.C:784
 ProofRailway.C:785
 ProofRailway.C:786
 ProofRailway.C:787
 ProofRailway.C:788
 ProofRailway.C:789
 ProofRailway.C:790
 ProofRailway.C:791
 ProofRailway.C:792
 ProofRailway.C:793
 ProofRailway.C:794
 ProofRailway.C:795
 ProofRailway.C:796
 ProofRailway.C:797
 ProofRailway.C:798
 ProofRailway.C:799
 ProofRailway.C:800
 ProofRailway.C:801
 ProofRailway.C:802
 ProofRailway.C:803
 ProofRailway.C:804
 ProofRailway.C:805
 ProofRailway.C:806
 ProofRailway.C:807
 ProofRailway.C:808
 ProofRailway.C:809
 ProofRailway.C:810
 ProofRailway.C:811
 ProofRailway.C:812
 ProofRailway.C:813
 ProofRailway.C:814
 ProofRailway.C:815
 ProofRailway.C:816
 ProofRailway.C:817
 ProofRailway.C:818
 ProofRailway.C:819
 ProofRailway.C:820
 ProofRailway.C:821
 ProofRailway.C:822
 ProofRailway.C:823
 ProofRailway.C:824
 ProofRailway.C:825
 ProofRailway.C:826
 ProofRailway.C:827
 ProofRailway.C:828
 ProofRailway.C:829
 ProofRailway.C:830
 ProofRailway.C:831
 ProofRailway.C:832
 ProofRailway.C:833
 ProofRailway.C:834
 ProofRailway.C:835
 ProofRailway.C:836
 ProofRailway.C:837
 ProofRailway.C:838
 ProofRailway.C:839
 ProofRailway.C:840
 ProofRailway.C:841
 ProofRailway.C:842
 ProofRailway.C:843
 ProofRailway.C:844
 ProofRailway.C:845
 ProofRailway.C:846
 ProofRailway.C:847