ROOT logo
//-*- Mode: C++ -*-
// $Id$

/// @file   run-single-task.C
/// @author Matthias.Richter@ift.uib.no
/// @date   2012-04-06
/// @brief  Run a single task
///
/// Helper macro to run a single task either locally or on Grid
/// Usage:
/// aliroot -b -q -l run-single-task.C'("mode", "input", "tasks", "name", "options", events, "path", "pattern", "friendPattern", "outputDir", "user")'
///  arguments
///   mode:    local, full, test, compile, merge, collect
///   input:   In grid mode a list of run numbers. 
///            In local mode:
///             - ESD file AliESDs.root
///             - a list of ESD files in a text file <choose-file-name>.txt
///             - AOD file AliAOD.root
///             - AODs with predefined list/AODs in same folder, specifiy as "AOD"
///
///   tasks:   list of class names/source or header files of tasks, or AddTask-macros
///
///  optional arguments
///   name:    analysis name (default 'myanalysis')
///   options: optional arguments passed onto the task, e.g. 'mc', 'event-mixing'
///            options of run-single-task:
///              'mcData' -> the run numbers indicate MC Data, no '000' prepended
///   events:  number of events to be processed (default -1 -> all)
///   path:    data search path for grid analysis (default from configuration file)
///   pattern: data search pattern (default from configuration file)
///   friend pattern: friend file search pattern (default from configuration file)
///   output dir: output directory in Grid home (default gridwork/yyyy-mm-dd_hh-mm)
///   user:    default NULL, using user of active token
///
/// Examples:
/// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "myanalysis_LHC11a")'
///
/// aliroot -b -q -l run-single-task.C'("local", "$ALICE_ROOT/test/ppbench/AliESDs.root", "AliAnalysisTaskSample")'
///
/// aliroot -b -q -l run-single-task.C'("local", "AOD", "AddTaskSample.C")'
///
/// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "correlation3p_LHC11a", 0, -1, "/alice/data/2011/LHC11a", "*/pass2_without_SDD/AOD*/*/AliAOD.root")'
///
/// aliroot -b -q -l run-single-task.C'("merge", "gridwork/mydir", "AliAnalysisTaskSample", "myanalysis_LHC11a")'
///
/// aliroot -b -q -l run-single-task.C'("collect", "gridwork/mydir", "AliAnalysisTaskSample", "myanalysis_LHC11a")'
///
/// Data input:
/// depending on the format of the search pattern either the ESD or AOD input handler is used.
///
/// Source files:
/// If the task and classes used by the task are not in an AliRoot library available, e.g.
/// for the purpose of development, all header and source files need to be in the local
/// directory. The macro searches automatically for dependencies, compiles those and
/// copies files to the Grid working directory. In order to make the files accessible in
/// the local directory, the files can be just linked.
/// <pre>
/// for f in <search path>; do ln -s $f; done
/// </pre>
/// If there are dependencies (include headers) which are not available in the working
/// directory, the macro searches for the aliroot libraries implementing them, and adds
/// the libraries if found to the setup.
///
/// Local analysis:
/// requires only the path to the input file and the task class name. If the specified file is
/// a text file (.txt) each line can contain an input ESD file path, all files are chained.
/// Analysis on local AOD files needs to be setup prior to this macro. gDirectory must contain
/// a TChain object of name 'aodTree'. This is for example created by macros like
/// $ALICE_ROOT/PWGHF/vertexingHF/MakeAODInputChain.C
/// Set $ALICE_ROOT/PWGHF/correlationHF/macros/setupDxHFE.C for an example.
///
/// Grid analysis:
/// All modes provided by the AliAnalysisAlien plugin can be used, e.g. full, test, offline
/// A couple of settings need to be defined in a configuration file 'grid-config.C' which can be
/// either in the local directory or home directory. The file can look like
/// <pre>
///   const char* alienAPIVersion="V1.1x";
///   const char* alienROOTVersion="v5-34-01";
///   const char* alienAliROOTVersion="v5-03-61-AN";
///   const char* defaultGridDataDir="/alice/data/2011/LHC11a";
///   const char* defaultDataPattern="*/pass2_without_SDD/*/AliESDs.root";
///   const char* defaultFriendDataPattern="";
///   {} // note this empty body
/// </pre>
/// Data path and pattern can also be specified as command line arguments.
/// The working directory in the grid home directory of the user is set to
/// gridwork/<date>_<time> (gridwork/yyyy-mm-dd_hh-mm), can be overridden by command line
/// parameter.
///
/// Options:
/// Options to the macro can be propagated via the parameter 'arguments', the known options
/// are parsed and filtered out from the arguments, which are than further propagated to
/// AdTask macros and task.
/// --mcData        switch indicates that the input data is mc data, the run numbers have
///                 a different format in real data
/// --nTestFiles=   number of test files to be used in test mode (default 10)
/// --merge=        merging mode 'local', 'grid', 'collect' (default Grid)
///
/// Merging of output:
/// The result of Grid analysis is merged remotely by using the ability of AliAnalysisAlien
/// to create stages of merging jobs. Being in the directory where analysis was originally
/// launched, the macro can be run in mode 'merge' with the remote working directory,
/// tasknames and the analysis name as arguments. Final result can be collected in mode
/// 'collect' with the same arguments, see examples.
/// Optionally, within the 'options' argument a list of output directories in the
/// remote grid directory can be specified, e.g. "000 002".
///
/// Merging of output in mode 'terminate':
/// The output files can be merged locally by using the argument '--merge=local'. In that
/// case all files are downloaded to the local machine and merged. The merging on grid
/// requires to launch the analysis with argument '--merge=grid'. After the jobs are done
/// further steps are required, 
/// 1) run in mode "terminate" with argument '--merge=grid' and working directory on grid,
/// 2) run in mode "terminate" with argument '--merge=collect' and working directory on grid.
/// Step 1) can be repeated  multiple times, the AnalysisManager will in each stage merge
/// several files of the previous stage, it will notify you when the final result has
/// already been merged.
/// 
/// Suggestions:
/// Feedback appreciated: Matthias.Richter@cern.ch
/// If you find this macro useful but not applicable without patching it, let me know
/// your changes and use cases.


#if defined(__CINT__) && !defined(__MAKECINT__)
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// environment
//
int macroVerbosity=0;
const char* defaultAnalysisName="myanalysis";
const char* includePath="-I. -I$ROOTSYS/include -I$ALICE_ROOT/include";
const char* libraryDependencies=
  "libSTEERBase.so "
  "libESD.so "
  "libAOD.so "
  "libANALYSIS.so "
  "libANALYSISalice.so "
  ;

TString BuildJDLName(const char* analysisName);
AliAnalysisManager* LoadAnalysisManager(const char* filename);
AliInputEventHandler* LoadCustomInputHandler(const char* name);
TChain* CreateChain(const char* filename);
TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass=true);
TObject* BuildCodeTree(const char* filename, TObject* pTree);
int  ProcessCodeTree(TObject* tree, TString& sources, TString& headers, TString& libs);
void ErrorConfigurationFile(const char* fileName);

void run_single_task(const char* mode,
		     const char* input,
		     const char* tasknames=NULL,
		     const char* analysisName=defaultAnalysisName,
		     const char* arguments="",
		     int nevents=-1,
		     const char* gridDataDir=NULL,
		     const char* dataPattern=NULL,
		     const char* friendDataPattern=NULL,
		     TString odir="",
		     const char* user=NULL
		     )
{
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // defaults
  //
  if (analysisName==defaultAnalysisName && gDirectory!=NULL) {
    // NOTE: the direct pointer comparison is on purpose
    // string comparison not necessary in this special case

    // fetch the analysis name from the setup file
    const char* confObjectName="analysis_name";
    TObject* confObject=gDirectory->FindObject(confObjectName);
    if (confObject) {
      analysisName=confObject->GetTitle();
    }
  }

  bool bRunLocal=strcmp(mode, "local")==0;
  bool bCompileOnly=strcmp(mode, "compile")==0;
  if (bCompileOnly) {
    bRunLocal=true;
    if (tasknames==NULL) {
      // short form with tasknames as the second argument
      tasknames=input;
    }
  }
  int mergeMode=0;
  if ((strcmp(mode, "merge")==0 && (mergeMode=1)>0) ||
      (strcmp(mode, "collect")==0 && (mergeMode=2)>0)) {
    mode="terminate";
    odir=input;
    input="0";
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // argument settings
  //
  bool bRunAnalysis=true;
  bool bDefaultOutput=true;
  bool bMergeOnGrid=mergeMode==2?false:true; // default true in all cases but 'collect'
  bool mcData=false;
  int nTestFiles=10;
  int nMaxInputFiles=100;
  TString strArguments(arguments);
  TString mergeDirs;
  TString strCustomInputHandler;
  TObjArray* tokens=strArguments.Tokenize(" ");
  if (tokens) {
    for (int iToken=0; iToken<tokens->GetEntriesFast(); iToken++) {
      TObject* token=tokens->At(iToken);
      if (!token) continue;
      TString arg=token->GetName();
      const char* key=NULL;

      if (arg.CompareTo("--help")==0 ||
          arg.CompareTo("-h")==0 ||
          arg.CompareTo("help")==0 ||
          arg.CompareTo("options")==0) {
	// printing help when called without arguments
	run_single_task();
	return;
      }
      key="--mcData";
      if (arg.CompareTo(key)==0) {
	// this is an argument to the macro, don't propagate it further to tasks
	// switch indicates that the input data is mc data, the run numbers have
	// a different format in real data
	// NOTE: not to be confused with option 'mc' which is propagated to tasks
	// and switches processing and output modes inside tasks
	mcData=true;
	continue;
      }
      key="--merge=";
      if (arg.BeginsWith(key)) {
	// this is an argument to the macro, don't propagate it further to tasks
	strArguments.ReplaceAll(arg, "");
	arg.ReplaceAll(key, "");
	if (arg.CompareTo("local")==0) {
	  // download all files and merge locally
	  bMergeOnGrid=false;
	} else if (arg.CompareTo("collect")==0) {
	  // download the output of merging on Grid
	  // macro must have been called in mode "terminate" with option
	  // --merge=grid and the correct grid working directory
	  bMergeOnGrid=false;
	} else if (arg.CompareTo("grid")==0) {
	  // merge output on grid,  the correct grid working directory
	  // must be provided
	  bMergeOnGrid=true;
	}
	continue;
      }
      key="--nTestFiles=";
      if (arg.BeginsWith(key)) {
	// this is an argument to the macro, don't propagate it further to tasks
	strArguments.ReplaceAll(arg, "");
	arg.ReplaceAll(key, "");
	nTestFiles=arg.Atoi();
	continue;
      }
      key="--noDefaultOutput";
      if (arg.CompareTo(key)==0) {
	// this is an argument to the macro, don't propagate it further to tasks
	strArguments.ReplaceAll(arg, "");
	bDefaultOutput=false;
	continue;
      }
      key="--stopBeforeRunning";
      if (arg.CompareTo(key)==0) {
	// this is an argument to the macro, don't propagate it further to tasks
	strArguments.ReplaceAll(arg, "");
	bRunAnalysis=false;
	continue;
      }
      key="--maxInputFiles=";
      if (arg.BeginsWith(key)) {
	// this is an argument to the macro, don't propagate it further to tasks
	strArguments.ReplaceAll(arg, "");
	arg.ReplaceAll(key, "");
	nMaxInputFiles=arg.Atoi();
	continue;
      }
      key="--InputHandler=";
      if (arg.BeginsWith(key)) {
	arg.ReplaceAll(key, "");
	strCustomInputHandler=arg;
      }
      if (!arg.BeginsWith("-") && mergeMode>0) {
	// treat as subdirectories in the remote grid dir
	mergeDirs+=" "; mergeDirs+=arg;
	// this is an argument to the macro, don't propagate it further to tasks
	strArguments.ReplaceAll(arg, "");
      }
    }
    delete tokens;
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // load task classes and find and load all dependencies
  //
  gSystem->AddIncludePath(includePath);
  TString libraries=libraryDependencies;
  if (gDirectory!=NULL) {
    // fetch the analysis libraries from the setup file
    const char* confObjectName="analysis_libraries";
    TObject* confObject=gDirectory->FindObject(confObjectName);
    if (confObject) {
      TString analysisLibraries(confObject->GetTitle());
      TObjArray* pTokens=analysisLibraries.Tokenize(" ");
      if (pTokens) {
	for (int i=0; i<pTokens->GetEntriesFast(); i++) {
	  if (libraries.Contains(pTokens->At(i)->GetName())==0) {
	    libraries+=" ";
	    libraries+=pTokens->At(i)->GetName();
	    TString library=pTokens->At(i)->GetName();
	    if (!library.EndsWith(".so")) libraries+=".so";
	  }
	}
	delete pTokens;
      }
    }
  }
  TObjArray* pTokens=libraries.Tokenize(" ");
  if (pTokens) {
    for (int i=0; i<pTokens->GetEntriesFast(); i++) {
      TString library=pTokens->At(i)->GetName();
      if (!library.EndsWith(".so")) {
	cerr << "libraries need to have ending '.so' in order to be correctly processed by alien plugin, please correct library name '" << library << "'" << endl;
      }
      if (gSystem->Load(pTokens->At(i)->GetName())==0) {
	cout << "loading " << pTokens->At(i)->GetName() << endl;
      }
    }
    delete pTokens;
  }

  TString taskNames=tasknames;
  TString taskClasses="";
  TString taskSources="";
  TString taskHeaders="";
  TString addTaskMacros="";
  TString dependencyHeader;
  TString dependencySource;
  TString parPackages="";
  TString delimiter(" ");
  TStringToken taskNameTokens(taskNames, delimiter);
  TObject* pCodeTree=NULL;
  {
    while (taskNameTokens.NextToken()) {
      TString taskSource(taskNameTokens);
      TString taskHeader(taskNameTokens);
      bool bIsAddTask=false;
      if (taskSource.EndsWith(".C")) {
	// suppose that's an 'AddTask' macro
	taskHeader="";
	bIsAddTask=true;
      } else if (taskSource.EndsWith(".par")) {
	// par file
	if (gSystem->AccessPathName(taskSource)!=0) {
	  ::Error("run_single_task", Form("par file '%s' not found in current directory, you might want to set a symbolic link", taskSource.Data()));
	  return;
	}
	parPackages+=" ";
	parPackages+=taskSource;
	continue;
      } else if (taskSource.EndsWith(".h")) {
	taskSource.ReplaceAll(".h", "");
	taskClasses+=" ";
	taskClasses+=taskSource;
	taskSource+=".cxx";
      } else if (taskSource.EndsWith(".cxx")) {
	taskHeader.ReplaceAll(".cxx", "");
	taskClasses+=" ";
	taskClasses+=taskHeader;
	taskHeader+=".h";
      } else {
	taskClasses+=" ";
	taskClasses+=taskSource;
	taskSource+=".cxx";
	taskHeader+=".h";
      }
      if (gSystem->AccessPathName(taskSource)==0) {
	pCodeTree=BuildCodeTree(taskSource, pCodeTree);
	if (!bIsAddTask) {taskSources+=" "; taskSources+=taskSource;}
	else {addTaskMacros+=" "; addTaskMacros+=taskSource;}
      }
      if (gSystem->AccessPathName(taskHeader)==0) {
	pCodeTree=BuildCodeTree(taskHeader, pCodeTree);
	taskHeaders+=" "; taskHeaders+=taskHeader;
      }
    }
  }
  if (!strCustomInputHandler.IsNull()) {
    if (strCustomInputHandler.EndsWith(".h")) strCustomInputHandler.ReplaceAll(".h", ".cxx");
    else if (!strCustomInputHandler.EndsWith(".cxx")) strCustomInputHandler+=".cxx";
    pCodeTree=BuildCodeTree(strCustomInputHandler, pCodeTree);
  }
  ProcessCodeTree(pCodeTree, dependencySource, dependencyHeader, libraries);
  if (bCompileOnly) return;

  cout << "Tasks: " << taskClasses << endl;
  cout << "Task files: " << taskSources << addTaskMacros << taskHeaders << endl;
  cout << "Dependency classes: " << dependencySource << endl;
  cout << "Dependency headers: " << dependencyHeader << endl;
  cout << "Dependency libraries: " << libraries << endl;
  cout << "Packages: " << parPackages << endl;

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // grid defaults
  //
  const char* gridConfigFile="grid-config.C";
  TString strGridConfigFile=gridConfigFile;
  if (gSystem->AccessPathName(strGridConfigFile)!=0) {
    strGridConfigFile.Prepend("/");
    strGridConfigFile.Prepend(gSystem->Getenv("HOME"));
    if (gSystem->AccessPathName(strGridConfigFile)!=0) {
      if (!bRunLocal && mergeMode==0) {
	ErrorConfigurationFile(gridConfigFile);
	return;
      }
      strGridConfigFile="";
    }
  }

  // load the grid configuration file if not merging and not running locally
  if (strGridConfigFile.IsNull()==0 && !bRunLocal) {
    cout << "loading grid configuration from file '" << strGridConfigFile << "':" << endl;
    gROOT->LoadMacro(strGridConfigFile);
    cout << " alienAPIVersion          =" << alienAPIVersion     << endl;
    cout << " alienROOTVersion         =" << alienROOTVersion    << endl;
    cout << " alienAliROOTVersion      =" << alienAliROOTVersion << endl;
    cout << " defaultGridDataDir       =" << defaultGridDataDir  << endl;
    cout << " defaultDataPattern       =" << defaultDataPattern  << endl;
    cout << " defaultFriendDataPattern =" << defaultFriendDataPattern  << endl;

    if (gridDataDir==NULL) gridDataDir=defaultGridDataDir;
    if (dataPattern==NULL) dataPattern=defaultDataPattern;
    if (friendDataPattern==NULL) friendDataPattern=defaultFriendDataPattern;
  } else if (bRunLocal) {
    if (dataPattern==NULL) {
      // thats a very crude logic, I guess it can fail in some special cases
      TString strin=input;
      if (strin.Contains("AOD"))
	dataPattern="AOD";
      else if (strin.Contains("ESD"))
	dataPattern="ESD";
    }
  }

  if(!bRunLocal) {
    // Connect to AliEn
    TGrid::Connect("alien://");
  }
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // make the analysis manager
  //
  AliAnalysisManager *pManager=NULL;
  pManager=new AliAnalysisManager("AnalysisManager");
  if (!pManager) {
    cerr << "failed to create AnalysisManager" << endl;
    return;
  }
  AliInputEventHandler *pInputHandler = NULL;
  TString strDataPattern(dataPattern);
  if (!strCustomInputHandler.IsNull()) {
    pInputHandler=LoadCustomInputHandler(strCustomInputHandler);
  }
  else if (strDataPattern.Contains("AOD")) pInputHandler=new AliAODInputHandler;
  else if (strDataPattern.Contains("ESD")) pInputHandler=new AliESDInputHandler;
  else if (mergeMode>0) pInputHandler=new AliInputEventHandler; // a default handler, not used in the end
  else {
    cerr << "can not determine input type from data pattern '" << strDataPattern << "'" << endl;
    return;
  }
  if (!pInputHandler) {
    cerr << "failed to created input handler" << endl;
    return;
  }
  //pInputHandler->SetReadFriends(kFALSE);
  pManager->SetInputEventHandler(pInputHandler);  
  pManager->SetNSysInfo(1000);

  TString ofile=Form("%s.root", analysisName);

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // init for local or GRID analysis
  //
  AliAnalysisAlien *alienHandler = NULL; // for grid analysis
  TChain *chain=NULL; // for local analysis
  TString strInput=input;
  if (bRunLocal) {
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // local analysis
    //
    if (strInput.BeginsWith("alien://")) {
      // file on Grid -> connect to AliEn
      TGrid::Connect("alien://");
    }
    if (strInput.EndsWith(".root") && gSystem->AccessPathName(strInput)==0) {
      // open a local file
      chain=CreateChain(strInput.Data());
    }
    if (chain) {
      // nothing to do here, just forward to the original
      // functionality if the chain was not created already
    } else 
    if(strInput.EndsWith("AliESDs.root")){
      // suppose it's a single ESD file
      chain = new TChain("esdTree"); 
      chain->Add(strInput);
    } else if(strInput.EndsWith(".txt")) {
      // Constructs chain from filenames in *.txt
      // in the form $DIR/AliESDs.root  
      gROOT->LoadMacro("$ALICE_ROOT/PWG0/CreateESDChain.C");
      // chain can contain up to 200 files, value can be modified to 
      // include a subset of what the *txt file contains
      chain = CreateESDChain(strInput.Data(),200); 

      // check if the files are on grid
      TIter next(chain->GetListOfFiles());
      TChainElement *chEl = 0;
      while(( chEl = (TChainElement*)next() )){
	TString tmp = chEl->GetTitle();	    
	if(tmp.BeginsWith("alien://")) {
	  TGrid::Connect("alien://");
	  break;
	}
      }
    } else if(strInput.EndsWith("ESD")){
      // fetch esd tree from the setup macro
      const char* esdTreeName="esdTree";
      if (gDirectory!=NULL) {
	TObject* chainObject=gDirectory->FindObject(esdTreeName);
	if (chainObject) {
	  chain=dynamic_cast<TChain*>(chainObject);
	}
      }
      if (!chain) {
	::Error("run_single_task", Form("failed to fetch esd tree object from setup; the chain with name '%s' has to be created before calling this macro", esdTreeName));
	return;
      }
    } else if(strInput.EndsWith("AliAOD.root")){
      // single local AOD file
      chain = new TChain("aodTree"); 
      chain->Add(strInput);
    } else if(strInput.EndsWith("AOD")){
      // fetch aod tree from the setup macro
      const char* aodTreeName="aodTree";
      if (gDirectory!=NULL) {
	TObject* chainObject=gDirectory->FindObject(aodTreeName);
	if (chainObject) {
	  chain=dynamic_cast<TChain*>(chainObject);
	}
      }
      if (!chain) {
	::Error("run_single_task", Form("failed to fetch aod tree object from setup; the chain with name '%s' has to be created before calling this macro", aodTreeName));
	return;
      }
    } else {
      ::Error("run_single_task", Form("invalid input"));
      return;
    }
  } else {
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // grid analysis
    //
    bool bSetRun=true;
    if (!strInput.IsDigit()) {
      // support for external macros specifying the the runs to be
      // analyzed
      // the input is expected to be an external plugin with name 'input'
      // and all run numbers being set
      TObject* pObj=gDirectory->FindObject(input);
      if (pObj) alienHandler=dynamic_cast<AliAnalysisAlien*>(pObj);
      if (!alienHandler) {
	::Error("run_single_task", Form("can not find plugin of name '%s', please setup alien handler with name and run numbers before calling this macro", input));
	return;
      }
      bSetRun=false;
    } else {
      alienHandler=new AliAnalysisAlien();
    }
    if (!alienHandler) {
      ::Error("run_single_task", Form("failed to create alien handler"));
      return;
    }

    // do not check for copying to grid (CLOSE_SE)
    alienHandler->SetCheckCopy(kFALSE);

    // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
    alienHandler->SetRunMode(mode);

    // number of files in test mode configurable via argument '--nTestFiles='
    if(mode=="test") alienHandler->SetNtestFiles(nTestFiles);
  
    // check the versions available on alien with the command 'packages'
    if (mergeMode==0) {
    alienHandler->SetAPIVersion(alienAPIVersion);
    alienHandler->SetROOTVersion(alienROOTVersion);
    alienHandler->SetAliROOTVersion(alienAliROOTVersion);
    }

    // using only default output
    // the alien plugin automatically recognizes all output files associated to output
    // containers, all files are treated in the standard output and added to the
    // root-archieve.root, which also seems to be needed for merging on Grid
    // see further down for using non-default output
    alienHandler->SetDefaultOutputs(bDefaultOutput);

    if (user && user[0]!=0) alienHandler->SetUser(user);

    // data alien directory
    alienHandler->SetGridDataDir(gridDataDir);
  
    // Set data search pattern
    alienHandler->SetDataPattern(dataPattern);
    alienHandler->SetFriendChainName(friendDataPattern);

    TObjArray* packageTokens=parPackages.Tokenize(" " );
    if (packageTokens) {
      for (int iPackageToken=0; iPackageToken<packageTokens->GetEntriesFast(); iPackageToken++) {
    	alienHandler->EnablePackage(packageTokens->At(iPackageToken)->GetName());
      }
      delete packageTokens;
    }

    if (bSetRun) {
      // only set if input is a run number
      if (!mcData && !strInput.BeginsWith("000"))
	alienHandler->SetRunPrefix("000");   // real data

      alienHandler->AddRunNumber(input);
    }

    if (mergeMode>0) {
      // the merge and collect modes have been added to simplify merging on grid
      // the treatment of arguments are a bit different in order to reduce list
      // of required arguments
      TString delimiter(" ");
      if (mergeDirs.IsNull()) mergeDirs="000";
      TStringToken dir(mergeDirs, delimiter);
      while (dir.NextToken()) {
	alienHandler->AddDataFile(dir->Data());
      }
      // use the specified directory names rather than a counter
      alienHandler->SetOutputToRunNo();
    }

    // define working and output directories
    TDatime dt;
    if(odir.IsNull())
      odir=(Form("gridwork/%04d-%02d-%02d_%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute()));
    cout << odir << endl;
    alienHandler->SetGridWorkingDir(odir); // relative to $HOME
    alienHandler->SetGridOutputDir("output");   // relative to working dir
    //alienHandler->SetOverwriteMode();                // overwrites the contents of the working and output directory

    // workaround for a Root feature: GetIncludePath() appends always
    // the current Root include path including escaped quotes. Those
    // quotes make it difficult to pass the output directly. Search for the
    // last appended include path and truncate
    TString strIncludePath(gSystem->GetIncludePath());
    Int_t pos=strIncludePath.Index(includePath);
    if (pos>=0) {
      Int_t cut=0;
      do {
	cut=pos+strlen(includePath);
      } while ((pos=strIncludePath.Index(includePath, cut))>cut);
      strIncludePath.Resize(cut);
    }
    alienHandler->AddIncludePath(strIncludePath);

    // Note: there is no extra source or header file to be transferred if 'AddTask' macros are used
    alienHandler->SetAnalysisSource(Form("%s %s %s %s", dependencySource.Data(), dependencyHeader.Data(), taskSources.Data(), taskHeaders.Data()));
    alienHandler->SetAdditionalLibs(Form("%s %s %s %s %s", libraries.Data(), dependencySource.Data(), dependencyHeader.Data(), taskSources.Data(), taskHeaders.Data()));

    // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
    TString macroName; macroName.Form("run_%s.C",analysisName); macroName.ReplaceAll("-","_");
    alienHandler->SetAnalysisMacro(macroName);
  
    //alienHandler->SetExecutable("comparison.sh");
    alienHandler->SetExecutable(Form("run_%s.sh",analysisName));

    alienHandler->SetSplitMaxInputFileNumber(nMaxInputFiles);
  
    // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
    //    alienHandler->SetMaxInitFailed(10);
  
    // Optionally resubmit threshold.
    alienHandler->SetMasterResubmitThreshold(90); // in %

    alienHandler->SetTTL(86400);// in sec
  
    // Optionally set input format (default xml-single)
    alienHandler->SetInputFormat("xml-single");
 
    // Optionally modify the name of the generated JDL (default analysis.jdl)
    alienHandler->SetJDLName(BuildJDLName(analysisName));
 
    // Optionally modify job price (default 1)
    alienHandler->SetPrice(1);
  
    // Optionally modify split mode (default 'se')
    alienHandler->SetSplitMode("se");
  
    // configure merging on grid,
    // argument '--merge=collect' sets 'false' for fetching the merged output
    alienHandler->SetMergeViaJDL(bMergeOnGrid); 

    alienHandler->SetOneStageMerging(kFALSE);
    alienHandler->SetMaxMergeStages(2);
  }

  // Connect plugin to the analysis manager
  if (alienHandler) {
    pManager->SetGridHandler(alienHandler);
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // create task from the name, create output container, connect slots
  //
  TObjArray* taskClassTokens=taskClasses.Tokenize(" ");
  if (taskClassTokens) {
    for (int iTaskClassToken=0; iTaskClassToken<taskClassTokens->GetEntriesFast(); iTaskClassToken++) {
      AliAnalysisTaskSE *pTask=NULL;
      TString taskName=taskClassTokens->At(iTaskClassToken)->GetName();
      taskName.ReplaceAll(".cxx", "");
      TClass* pCl=TClass::GetClass(taskName);
      if (!pCl) {
	cerr << "can not load class " << taskName << endl;
	return;
      }
      void* p=pCl->New();
      if (!p) {
	cerr << "failed to instantiate class " << taskName << endl;
	return;
      }
      pTask=reinterpret_cast<AliAnalysisTaskSE*>(p);
      pManager->AddTask(pTask);
      AliAnalysisDataContainer *pContainer=pManager->CreateContainer(analysisName ,TObject::Class(), AliAnalysisManager::kOutputContainer, ofile);       
      pManager->ConnectInput(pTask,0,pManager->GetCommonInputContainer());
      pManager->ConnectOutput(pTask,1,pContainer);
    }
    delete taskClassTokens;
  }
  TObjArray* taskMacroTokens=addTaskMacros.Tokenize(" ");
  if (taskMacroTokens) {
    for (int iTaskMacroToken=0; iTaskMacroToken<taskMacroTokens->GetEntriesFast(); iTaskMacroToken++) {
      TString taskSource= taskMacroTokens->At(iTaskMacroToken)->GetName();

      taskSource+="+g";
      TString configuration;
      if(!strArguments.Contains("file=")) configuration+=Form(" file=%s",ofile.Data()); 
      if(!strArguments.Contains("name=")) configuration+=Form(" name=%s",analysisName); 
      configuration+=" "; configuration+=strArguments.Data();
      if (gDirectory) gDirectory->Add(new TNamed("run_single_task_configuration", configuration.Data()));
      gROOT->Macro(taskMacroTokens->At(iTaskMacroToken)->GetName());
    }
    delete taskMacroTokens;
  }

  if (!bDefaultOutput) {
    // fetch all output files from the output containers
    TString ofiles;
    TIter nextcontainer(pManager->GetContainers());
    TObject* objContainer=NULL;
    while ((objContainer=nextcontainer())!=NULL) {
      AliAnalysisDataContainer* container=dynamic_cast<AliAnalysisDataContainer*>(objContainer);
      if (!container) continue;
      ofiles+=container->GetFileName();
      ofiles+=" ";
    }

    alienHandler->SetOutputFiles(ofiles);
    // Optionally define the files to be archived.
    alienHandler->SetOutputArchive("log_archive.zip:stdout,stderr");
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  //
  // run
  //

  if (!pManager->InitAnalysis()) {
    cerr << "failed to initialize analysis" << endl;
    return;
  }
  if (nevents<0) nevents=1000000000;
  pManager->PrintStatus();
  if (!bRunAnalysis) return;
  if (bRunLocal) {
    pManager->StartAnalysis("local", chain, nevents);
  } else {
    pManager->StartAnalysis("grid", nevents);
  }
}

void run_single_task()
{
  // Print help
  cout << "\nrun-single-task.C: Helper macro to run a single task either locally or on Grid"
       << "\nUsage:"
       << "\naliroot -b -q -l run-single-task.C'(\"mode\", \"input\", \"tasks\", \"name\", \"options\", events, \"path\", \"pattern\", \"friendPattern\", \"outputDir\", \"user\")' "
       << "\n arguments"
       << "\n  mode:    local, full, test, compile, merge, collect"
       << "\n  input:   In grid mode a list of run numbers. "
       << "\n           In local mode:"
       << "\n            - ESD file AliESDs.root"
       << "\n            - a list of ESD files in a text file <choose-file-name>.txt"
       << "\n            - AOD file AliAOD.root"
       << "\n            - AODs with predefined list/AODs in same folder, specifiy as \"AOD\""
       << "\n"
       << "\n  tasks:   list of class names/source or header files of tasks, or AddTask-macros"
       << "\n"
       << "\n optional arguments"
       << "\n  name:    analysis name (default 'myanalysis')"
       << "\n  options: optional arguments passed onto the task, e.g. 'mc', 'event-mixing'"
       << "\n           options of run-single-task:"
       << "\n             'mcData' -> the run numbers indicate MC Data, no '000' prepended"
       << "\n  events:  number of events to be processed (default -1 -> all)"
       << "\n  path:    data search path for grid analysis (default from configuration file)"
       << "\n  pattern: data search pattern (default from configuration file)"
       << "\n  friend pattern: friend file search pattern (default from configuration file)"
       << "\n  output dir: output directory in Grid home (default gridwork/yyyy-mm-dd_hh-mm)"
       << "\n  user:    default NULL, using user of active token"
       << "\n" << endl;
  cout << "Examples:"
       << "\naliroot -b -q -l run-single-task.C'(\"full\", \"146860\", \"AliAnalysisTaskSample\", \"myanalysis_LHC11a\")'"
       << "\n"
       << "\naliroot -b -q -l run-single-task.C'(\"local\", \"$ALICE_ROOT/test/ppbench/AliESDs.root\", \"AliAnalysisTaskSample\")'"
       << "\n"
       << "\naliroot -b -q -l run-single-task.C'(\"local\", \"AOD\", \"AddTaskSample.C\")'"
       << "\n"
       << "\naliroot -b -q -l run-single-task.C'(\"full\", \"146860\", \"AliAnalysisTaskSample\", \"correlation3p_LHC11a\", 0, -1, \"/alice/data/2011/LHC11a\", \"*/pass2_without_SDD/AOD*/*/AliAOD.root\")'"
       << "\n"
       << "\naliroot -b -q -l run-single-task.C'(\"merge\", \"gridwork/mydir\", \"AliAnalysisTaskSample\", \"myanalysis_LHC11a\")'"
       << "\n"
       << "\naliroot -b -q -l run-single-task.C'(\"collect\", \"gridwork/mydir\", \"AliAnalysisTaskSample\", \"myanalysis_LHC11a\")'"
       << "\n" << endl;

  cout << "Further options: \n" 
       << "--merge=local/grid/collect (merge option when running in mode 'terminate', simplified by runniing modes 'merge' and 'collect')\n"
       << "                           (if you want to merge files on grid, run with --merge=grid and --merge=collect to fetch files)\n"
       << "--mcData                   (needed if running on MC)\n"
       << "--nTestFiles=              (number of test files to use from grid, default=10)\n"
       << "--maxInputFiles=           (number of files in each subjob on grid, default=100)\n"
       << "--noDefaultOutput \n"
       << "--stopBeforeRunning        (Testmode for run-single-task, will stop right before starting the analysis)\n\n"
       << "To get the keywords to send to the AddTask-macros, run them individually with argument help\n\n";
}

// method for backward compatibility
void run_single_task(const char* mode,
		     const char* input,
		     const char* tasknames,
		     const char* analysisName,
		     Bool_t useMC,
		     int nevents=-1,
		     const char* gridDataDir=NULL,
		     const char* dataPattern=NULL,
		     const char* friendDataPattern=NULL,
		     TString odir="",
		     const char* user=NULL
		     )
{
  run_single_task(mode,
		  input,
		  tasknames,
		  analysisName,
		  (useMC?"mc":""),
		  nevents,
		  gridDataDir,
		  dataPattern,
		  friendDataPattern,
		  odir,
		  user
		  );
}

// method for calling with a fixed working directory, e.g. in mode terminate 
void run_single_task(const char* mode,
		     const char* input,
		     const char* tasknames,
		     const char* analysisName,
		     const char* arguments,
		     const char* workdir
		     )
{
  TString odir(workdir);
  run_single_task(mode,
		  input,
		  tasknames,
		  analysisName,
		  arguments,
		  -1,
		  NULL,
		  NULL,
		  NULL,
		  odir,
		  NULL
		  );
}

TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass)
{
  // scan the file and add all include headers found by path
  // to the parameter headers
  ifstream input(filename);
  if (input.bad()) {
    cerr << "failed to open file " << filename << endl;
    return headers;
  }
  TString line; 
  while (!line.ReadLine(input).eof()) {
    if (!line.Contains("#include") || !line.Contains(".h")) continue;
    line=line(0, line.Index(".h"));line+=".h";
    line.Replace(0, line.Index("#include"), "");
    line.ReplaceAll("#include", "");
    line.ReplaceAll(" ", "");
    line.ReplaceAll("\"", "");
    if (!line.BeginsWith("Ali") && !line.BeginsWith("T")) continue;
    if (gSystem->AccessPathName(line)!=0) {
      // not an include file in the current directory, check if class
      // is available or find library
      line.ReplaceAll(".h","");
      //cout << "checking class " << line << endl;
      if (TClass::GetClass(line)==NULL) {
	TString command;
	TString resfilename(gSystem->TempDirectory()); resfilename+="/findlib.txt";
	command.Form("for lib in $ALICE_ROOT/lib/*/lib*.so; do (nm $lib | grep %s | grep ' T ' | grep Class_Name > /dev/null) && echo $lib > %s; done", line.Data(), resfilename.Data());
	gSystem->Exec(command);
	ifstream resfile(resfilename.Data());
	if (resfile.good()) {
	  TString result;
	  if (!result.ReadLine(resfile).eof()) {
	    Ssiz_t haveSlash=-1;
	    while ((haveSlash=result.First('/'))>=0) result.Replace(0, haveSlash+1, "");
	    if (!libs.Contains(result)) {
	      cout << "loading dependency library '" << result << "' for class '" << line << "'" << endl;
	      gSystem->Load(result);
	      if (!libs.IsNull()) libs+=" ";
	      libs+=result;
	    }
	  }
	  command="rm "; command+=resfilename;
	  gSystem->Exec(command);
	}
      }
    } else {
      if (headers.Contains(line)) {
        if (!headers.BeginsWith(line)) {
          headers.ReplaceAll(line, "");
          if (!headers.IsNull()) headers.Insert(0, " ");
	  if (macroVerbosity>0) cout << "moving " << line << endl;
          headers.Insert(0, line);
        }
        continue;
      }
      if (!headers.IsNull()) headers.Insert(0, " ");
      if (macroVerbosity>0) cout << "inserting " << line << endl;
      headers.Insert(0, line);
      TString source=line; source.ReplaceAll(".h", ".cxx");
      if (gSystem->AccessPathName(source)==0) {
	GetIncludeHeaders(source, headers, libs);
      }
      GetIncludeHeaders(line, headers, libs);
      if (loadClass && gSystem->AccessPathName(source)==0) {
	line.ReplaceAll(".h", "");
	if (TClass::GetClass(line)==NULL) {
	  source+="+g";
	  gROOT->LoadMacro(source);
	}
      }
    }
  }

  return headers;
}

TString BuildJDLName(const char* analysisName)
{
  TString jdlname(Form("run_%s.jdl",(analysisName!=NULL?analysisName:"analysis")));
  return jdlname;
}

AliAnalysisManager* LoadAnalysisManager(const char* filename)
{
  // open file and loop through objects to find AnalysisManager
  TFile* file=TFile::Open(infilename);
  if (!file || file->IsZombie()) {
    return;
  }

  TList* keys=file->GetListOfKeys();
  if (!keys || keys->GetEntries()==0) {
    cerr << "can not find any keys in file " << infilename << endl;
    return;
  }

  TObject* pObj=NULL;
  TObject* pKey=NULL;
  TList output;
  TIter nextkey(keys);
  while (pKey=nextkey()) {
    file->GetObject(pKey->GetName(), pObj);
    if (pObj && pObj->IsA()!=AliAnalysisManager::Class())
      return dynamic_cast<AliAnalysisManager*>(pObj);
  }
}

AliInputEventHandler* LoadCustomInputHandler(const char* name)
{
  // load a custom input handler
  TString className(name);
  className.ReplaceAll(".cxx", "");
  TClass* pCl=TClass::GetClass(className);
  if (!pCl) {
    cerr << "can not load class " << className << endl;
    return;
  }
  void* p=pCl->New();
  if (!p) {
    cerr << "failed to instantiate class " << className << endl;
    return;
  }
  return dynamic_cast<AliInputEventHandler*>(p);
}

TChain* CreateChain(const char* filename)
{
  // create input TChain object with tree name derived from input file
  TChain* chain=NULL;
  TFile* file=TFile::Open(filename);
  if (!file || file->IsZombie()) {
    return NULL;
  }

  TList* keys=file->GetListOfKeys();
  if (!keys || keys->GetEntries()==0) {
    cerr << "can not find any keys in file " << filename << endl;
    return NULL;
  }

  TObject* pObj=NULL;
  TObject* pKey=NULL;
  TIter nextkey(keys);
  while (pKey=nextkey()) {
    file->GetObject(pKey->GetName(), pObj);
    if (!pObj || pObj->IsA()!=TTree::Class()) continue;
    TChain* chain = new TChain(pObj->GetName()); 
    chain->Add(filename);
    break;
  }
  file->Close();
  delete file;
  if (chain) {
    cout << "created chain " << chain->GetName() << endl;
  }
  return chain;
}

void ErrorConfigurationFile(const char* fileName) {
  cout << endl;
  cout << "/// -------------------------------------------------------------------" << endl;
  cout << "/// Warning: can not find configuration file '" << fileName << "'" << endl;
  cout << "/// please create a configuration file in either local or HOME directory, or in" << endl;
  cout << "/// specified location. Below is an example, fill in your preferred defaults." << endl;
  cout << "/// -------------------------------------------------------------------" << endl;
  cout << endl;
  cout << "const char* alienAPIVersion=\"V1.1x\";" << endl;
  cout << "const char* alienROOTVersion=\"v5-33-02a\";" << endl;
  cout << "const char* alienAliROOTVersion=\"v5-01-Rev-29\";" << endl;
  cout << "const char* defaultGridDataDir=\"/alice/data/2011/LHC11f\";" << endl;
  cout << "const char* defaultDataPattern=\"*ESDs.root\";" << endl;
  cout << "const char* defaultFriendDataPattern=\"\";" << endl;
  cout << "{} // note this empty body";
  cout << endl;
}

class AliCodeNode : public TNamed
{
public:
  AliCodeNode();
  AliCodeNode(const char* filename);
  ~AliCodeNode();

  enum {
    kTypeInvalid = 0,
    kTypeSource = 1,
    kTypeHeader,
    kTypeMacro,
    kNofTypes
  };
    
  const TList& GetParents() const {return fParents;}
  const TList& GetChilds() const {return fChilds;}
  int AddParent(AliCodeNode* pParent);
  int InsertChild(AliCodeNode* pChild);
  bool HasChilds() const {return (GetChilds().GetEntries()-fProcessedChilds.GetEntries())>0;}
  int MarkProcessed();
  int MarkChildProcessed(AliCodeNode* pChild);
  bool HasSourceParent();
  //int DisconnectParents();

  bool IsHeader() const {return fType==kTypeHeader;}
  bool IsSource() const {return fType==kTypeSource;}
  void HaveFile(bool haveFile) {fHaveFile=haveFile;}
  bool HaveFile() const {return fHaveFile;}
  void Print(Option_t *option="") const;

protected:
  //int DisconnectChild(const AliCodeNode& child);

private:
  TList fParents; // list of parents
  TList fChilds;  // list of childs
  TList fProcessedChilds;  // list of processed childs
  int   fType;    // source of header
  bool  fHaveFile;// file is existing in pwd

  ClassDef(AliCodeNode, 1)
};

class AliCodeTree : public TObject
{
public:
  AliCodeTree(short verbosity=0) : fNodes(), fIndentCount(0), fVerbosity(verbosity) {fNodes.SetOwner(kTRUE);}
  ~AliCodeTree() {}

  AliCodeNode* Build(const char* topfile, AliCodeNode* parent=NULL);
  AliCodeNode* FindNode(const char* name);
  int Sort();
  int LoadClasses(TString& libs);
  int LoadClasses() {TString dummy; return LoadClasses(dummy);}
  int GetHeaders(TString& headers);
  int GetSources(TString& sources);

  void Print(Option_t *option="") const;

private:
  TObjArray fNodes; // list of nodes
  short fIndentCount;
  short fVerbosity;

  ClassDef(AliCodeTree, 1)
};

ClassImp(AliCodeNode)

AliCodeNode::AliCodeNode()
 : TNamed()
 , fParents()
 , fChilds()
 , fProcessedChilds()
 , fType(AliCodeNode::kTypeInvalid)
 , fHaveFile(false)
{
}

AliCodeNode::AliCodeNode(const char* filename)
  : TNamed(filename, filename)
  , fParents()
  , fChilds()
  , fProcessedChilds()
  , fType(AliCodeNode::kTypeInvalid)
 , fHaveFile(false)
{
  TString s(filename);
  if (s.EndsWith(".cxx")) fType=kTypeSource;
  else if (s.EndsWith(".h")) fType=kTypeHeader;
  else if (s.EndsWith(".C")) fType=kTypeMacro;
}

AliCodeNode::~AliCodeNode()
{
}

int AliCodeNode::AddParent(AliCodeNode* pParent)
{
  if (!pParent) return -1;
  if (fParents.FindObject(pParent)) return 0;
  if (GetChilds().FindObject(pParent)) {
    cerr << "error: circular dependency: can not add " << pParent->GetName() << " as parent to " << this->GetName() << endl;
    return -2;
  }
  fParents.Add(pParent);
  return 0;
}

int AliCodeNode::InsertChild(AliCodeNode* pChild)
{
  if (!pChild) return -1;
  if (fChilds.FindObject(pChild)) return 0;
  if (pChild->GetChilds().FindObject(this)) {
    cerr << "error: circular dependency: can not add " << pChild->GetName() << " as child to " << this->GetName() << endl;
    return -2;
  }
  fChilds.Add(pChild);
  return 0;
}

int AliCodeNode::MarkProcessed()
{
  TIter parents(&fParents);
  TObject* obj=NULL;
  while ((obj=parents())) {
    AliCodeNode* parent=dynamic_cast<AliCodeNode*>(obj);
    parent->MarkChildProcessed(this);
  }

  return 0;
}

bool AliCodeNode::HasSourceParent()
{
  if (fType!=kTypeHeader) return false;
  TString name(GetName());
  name.ReplaceAll(".h", ".cxx");
  TIter parents(&fParents);
  TObject* obj=NULL;
  while ((obj=parents())) {
    if (name.CompareTo(obj->GetName())==0)
      return true;
  }
  return false;
}

int AliCodeNode::MarkChildProcessed(AliCodeNode* pChild)
{
  if (!pChild) return -1;
  if (fChilds.FindObject(pChild)==NULL) {
    cerr << "node " << GetName() << ": failed to find child node " << pChild->GetName() << endl;
    return -1;
  }
  if (fProcessedChilds.FindObject(pChild)!=NULL) {
    cerr << "node " << GetName() << ": child node " << pChild->GetName() << " already processed" << endl;
    return 0;
  }
  fProcessedChilds.Add(pChild);
  return 0;
}

void AliCodeNode::Print(Option_t */*option*/) const
{
  cout   << "-- " << GetName() << endl;
  TObject* obj=NULL;
  cout   << "    - parents" << endl;
  TIter parents(&fParents);
  while ((obj=parents())) {
    cout << "    |- " << obj->GetName() << endl;
  }
  cout   << "    - childs" << endl;
  TIter childs(&fChilds);
  while ((obj=childs())) {
    cout << "    |- " << obj->GetName() << endl;
  }
}

ClassImp(AliCodeTree)

AliCodeNode* AliCodeTree::Build(const char* topfile, AliCodeNode* parent)
{
  // scan the file and recursively add all include headers found by path
  int iResult=0;
  AliCodeNode* node=FindNode(topfile);
  if (!node) {
    if (fVerbosity>0) cout << setw(2*fIndentCount) << " " << "new node " << topfile << endl;
    fIndentCount++;
    node=new AliCodeNode(topfile);
    fNodes.Add(node);
    ifstream input(topfile);
    if (input.good()) {
      node->HaveFile(true);
      TString line; 
      while (!line.ReadLine(input).eof()) {
	if (!line.Contains("#include") || !line.Contains(".h")) continue;
	line=line(0, line.Index(".h"));line+=".h";
	line.Replace(0, line.Index("#include"), "");
	line.ReplaceAll("#include", "");
	line.ReplaceAll(" ", "");
	line.ReplaceAll("\"", "");
	if (!line.BeginsWith("Ali") && !line.BeginsWith("T")) continue;
	AliCodeNode* child=NULL;
	TString source=line; source.ReplaceAll(".h", ".cxx");
	if (source.CompareTo(topfile)!=0 && gSystem->AccessPathName(source)==0) {
	  child=Build(source, node);
	  node->InsertChild(child);
	}
	child=Build(line, node);
	node->InsertChild(child);
      }
    }
    fIndentCount--;
  }
  if (parent) {
    if ((iResult=node->AddParent(parent))<0)
      return NULL;
  }
  if (fVerbosity>0) cout << setw(2*fIndentCount) << " " << "finished " << topfile << endl;
  return node;
}

int AliCodeTree::Sort()
{
  TObjArray sortedNodes;
  int nNodes=fNodes.GetEntriesFast();
  int nCount=0;
  while (sortedNodes.GetEntriesFast()<nNodes && nCount<nNodes) {
    for (int i=0; i<nNodes; i++) {
      if (fNodes[i]==NULL) continue;
      AliCodeNode* node=dynamic_cast<AliCodeNode*>(fNodes[i]);
      if (node->HasChilds()) {
	continue;
      }
      fNodes[i]=NULL;
      sortedNodes.Add(node);
      node->MarkProcessed();
    }
    nCount++;
  }

  for (int i=0; i<nNodes; i++) {
    fNodes[i]=sortedNodes[i];
  }

  return 0;
}

int AliCodeTree::LoadClasses(TString& libs)
{
  TIter next(&fNodes);
  TObject* obj=NULL;
  while ((obj=next())!=NULL) {
    AliCodeNode* node=dynamic_cast<AliCodeNode*>(obj);
    TString name(node->GetName());
    if (node->IsHeader()) {
      if (node->HasSourceParent()) {
	// nothing to do, class going to be compiled from source
	continue;
      }
      name.ReplaceAll(".h", "");
      if (TClass::GetClass(name)!=NULL) {
	// class available in the system
	continue;
      }

      TString command;
      TString resfilename(gSystem->TempDirectory()); resfilename+="/findlib.txt";
      command.Form("for lib in $ALICE_ROOT/lib/*/lib*.so; do (nm $lib | grep %s | grep ' T ' | grep Class_Name > /dev/null) && echo $lib > %s; done", name.Data(), resfilename.Data());
      gSystem->Exec(command);
      ifstream resfile(resfilename.Data());
      if (resfile.good()) {
	TString result;
	if (!result.ReadLine(resfile).eof()) {
	  Ssiz_t haveSlash=-1;
	  while ((haveSlash=result.First('/'))>=0) result.Replace(0, haveSlash+1, "");
	  if (!libs.Contains(result)) {
	    cout << "loading dependency library '" << result << "' for class '" << name << "'" << endl;
	    gSystem->Load(result);
	    if (!libs.IsNull()) libs+=" ";
	    libs+=result;
	  }
	}
	command="rm "; command+=resfilename;
	gSystem->Exec(command);
      }
      continue;
    }
    if (node->IsSource()) {
      TString classname(name);
      classname.ReplaceAll(".cxx", "");
      if (TClass::GetClass(classname)!=NULL) {
	// class available in the system
	continue;
      }
      name+="+g";
      gROOT->LoadMacro(name);
    }
  }
  return 0;
}

int AliCodeTree::GetHeaders(TString& headers)
{
  TIter next(&fNodes);
  TObject* obj=NULL;
  while ((obj=next())!=NULL) {
    AliCodeNode* node=dynamic_cast<AliCodeNode*>(obj);
    if (!node->IsHeader() || !node->HaveFile()) continue;
    if (!headers.IsNull()) headers+=" ";
    headers+=node->GetName();
  }
  return 0;
}

int AliCodeTree::GetSources(TString& sources)
{
  TIter next(&fNodes);
  TObject* obj=NULL;
  while ((obj=next())!=NULL) {
    AliCodeNode* node=dynamic_cast<AliCodeNode*>(obj);
    if (!node->IsSource() || !node->HaveFile()) continue;
    if (!sources.IsNull()) sources+=" ";
    sources+=node->GetName();
  }
  return 0;
}

AliCodeNode* AliCodeTree::FindNode(const char* name)
{
  TObject* node=fNodes.FindObject(name);
  if (!node) return NULL;
  return dynamic_cast<AliCodeNode*>(node);
}

void AliCodeTree::Print(Option_t *option) const
{
  const char* key=NULL;
  int indent=0;
  TString childOptions;
  const TString delimiter(" ");
  TStringToken options(option, delimiter);
  while (options.NextToken()) {
    key="indent=";
    if (options.BeginsWith(key)) {
      TString arg(options);
      arg.ReplaceAll(key, "");
      indent=arg.Atoi();
      continue;
    }
    childOptions+=" ";
    childOptions+=options;
  }
  childOptions+=Form("indent=%d", indent+1);
  TIter next(&fNodes);
  TObject* obj=NULL;
  while ((obj=next())!=NULL) {
    obj->Print(childOptions);
  }
}

TObject* BuildCodeTree(const char* filename, TObject* useObject)
{
  AliCodeTree* pTree=NULL;
  if (useObject) pTree=dynamic_cast<AliCodeTree*>(useObject);
  if (!pTree) pTree=new AliCodeTree;
  if (!pTree) return NULL;
  
  pTree->Build(filename);
  return pTree;
}

int ProcessCodeTree(TObject* tree, TString& sources, TString& headers, TString& libs)
{
  if (!tree) return -1;
  AliCodeTree* pTree=dynamic_cast<AliCodeTree*>(tree);
  pTree->Sort();
  pTree->LoadClasses(libs);
  pTree->GetHeaders(headers);
  pTree->GetSources(sources);
  return 0;
}

#else
#include "TObject.h"
#include "TNamed.h"
#include "TList.h"
#include "TObjArray.h"
#include "TString.h"
#include "TPRegexp.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TGrid.h"
#include "TChain.h"
#include "TChainElement.h"
// #include "AliAnalysisManager.h"
// #include "AliAnalysisAlien.h"
// #include "AliAnalysisTaskSE.h"
// #include "AliInputEventHandler.h"
// #include "AliAODInputHandler.h"
// #include "AliESDInputHandler.h"
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

#endif
 run-single-task.C:1
 run-single-task.C:2
 run-single-task.C:3
 run-single-task.C:4
 run-single-task.C:5
 run-single-task.C:6
 run-single-task.C:7
 run-single-task.C:8
 run-single-task.C:9
 run-single-task.C:10
 run-single-task.C:11
 run-single-task.C:12
 run-single-task.C:13
 run-single-task.C:14
 run-single-task.C:15
 run-single-task.C:16
 run-single-task.C:17
 run-single-task.C:18
 run-single-task.C:19
 run-single-task.C:20
 run-single-task.C:21
 run-single-task.C:22
 run-single-task.C:23
 run-single-task.C:24
 run-single-task.C:25
 run-single-task.C:26
 run-single-task.C:27
 run-single-task.C:28
 run-single-task.C:29
 run-single-task.C:30
 run-single-task.C:31
 run-single-task.C:32
 run-single-task.C:33
 run-single-task.C:34
 run-single-task.C:35
 run-single-task.C:36
 run-single-task.C:37
 run-single-task.C:38
 run-single-task.C:39
 run-single-task.C:40
 run-single-task.C:41
 run-single-task.C:42
 run-single-task.C:43
 run-single-task.C:44
 run-single-task.C:45
 run-single-task.C:46
 run-single-task.C:47
 run-single-task.C:48
 run-single-task.C:49
 run-single-task.C:50
 run-single-task.C:51
 run-single-task.C:52
 run-single-task.C:53
 run-single-task.C:54
 run-single-task.C:55
 run-single-task.C:56
 run-single-task.C:57
 run-single-task.C:58
 run-single-task.C:59
 run-single-task.C:60
 run-single-task.C:61
 run-single-task.C:62
 run-single-task.C:63
 run-single-task.C:64
 run-single-task.C:65
 run-single-task.C:66
 run-single-task.C:67
 run-single-task.C:68
 run-single-task.C:69
 run-single-task.C:70
 run-single-task.C:71
 run-single-task.C:72
 run-single-task.C:73
 run-single-task.C:74
 run-single-task.C:75
 run-single-task.C:76
 run-single-task.C:77
 run-single-task.C:78
 run-single-task.C:79
 run-single-task.C:80
 run-single-task.C:81
 run-single-task.C:82
 run-single-task.C:83
 run-single-task.C:84
 run-single-task.C:85
 run-single-task.C:86
 run-single-task.C:87
 run-single-task.C:88
 run-single-task.C:89
 run-single-task.C:90
 run-single-task.C:91
 run-single-task.C:92
 run-single-task.C:93
 run-single-task.C:94
 run-single-task.C:95
 run-single-task.C:96
 run-single-task.C:97
 run-single-task.C:98
 run-single-task.C:99
 run-single-task.C:100
 run-single-task.C:101
 run-single-task.C:102
 run-single-task.C:103
 run-single-task.C:104
 run-single-task.C:105
 run-single-task.C:106
 run-single-task.C:107
 run-single-task.C:108
 run-single-task.C:109
 run-single-task.C:110
 run-single-task.C:111
 run-single-task.C:112
 run-single-task.C:113
 run-single-task.C:114
 run-single-task.C:115
 run-single-task.C:116
 run-single-task.C:117
 run-single-task.C:118
 run-single-task.C:119
 run-single-task.C:120
 run-single-task.C:121
 run-single-task.C:122
 run-single-task.C:123
 run-single-task.C:124
 run-single-task.C:125
 run-single-task.C:126
 run-single-task.C:127
 run-single-task.C:128
 run-single-task.C:129
 run-single-task.C:130
 run-single-task.C:131
 run-single-task.C:132
 run-single-task.C:133
 run-single-task.C:134
 run-single-task.C:135
 run-single-task.C:136
 run-single-task.C:137
 run-single-task.C:138
 run-single-task.C:139
 run-single-task.C:140
 run-single-task.C:141
 run-single-task.C:142
 run-single-task.C:143
 run-single-task.C:144
 run-single-task.C:145
 run-single-task.C:146
 run-single-task.C:147
 run-single-task.C:148
 run-single-task.C:149
 run-single-task.C:150
 run-single-task.C:151
 run-single-task.C:152
 run-single-task.C:153
 run-single-task.C:154
 run-single-task.C:155
 run-single-task.C:156
 run-single-task.C:157
 run-single-task.C:158
 run-single-task.C:159
 run-single-task.C:160
 run-single-task.C:161
 run-single-task.C:162
 run-single-task.C:163
 run-single-task.C:164
 run-single-task.C:165
 run-single-task.C:166
 run-single-task.C:167
 run-single-task.C:168
 run-single-task.C:169
 run-single-task.C:170
 run-single-task.C:171
 run-single-task.C:172
 run-single-task.C:173
 run-single-task.C:174
 run-single-task.C:175
 run-single-task.C:176
 run-single-task.C:177
 run-single-task.C:178
 run-single-task.C:179
 run-single-task.C:180
 run-single-task.C:181
 run-single-task.C:182
 run-single-task.C:183
 run-single-task.C:184
 run-single-task.C:185
 run-single-task.C:186
 run-single-task.C:187
 run-single-task.C:188
 run-single-task.C:189
 run-single-task.C:190
 run-single-task.C:191
 run-single-task.C:192
 run-single-task.C:193
 run-single-task.C:194
 run-single-task.C:195
 run-single-task.C:196
 run-single-task.C:197
 run-single-task.C:198
 run-single-task.C:199
 run-single-task.C:200
 run-single-task.C:201
 run-single-task.C:202
 run-single-task.C:203
 run-single-task.C:204
 run-single-task.C:205
 run-single-task.C:206
 run-single-task.C:207
 run-single-task.C:208
 run-single-task.C:209
 run-single-task.C:210
 run-single-task.C:211
 run-single-task.C:212
 run-single-task.C:213
 run-single-task.C:214
 run-single-task.C:215
 run-single-task.C:216
 run-single-task.C:217
 run-single-task.C:218
 run-single-task.C:219
 run-single-task.C:220
 run-single-task.C:221
 run-single-task.C:222
 run-single-task.C:223
 run-single-task.C:224
 run-single-task.C:225
 run-single-task.C:226
 run-single-task.C:227
 run-single-task.C:228
 run-single-task.C:229
 run-single-task.C:230
 run-single-task.C:231
 run-single-task.C:232
 run-single-task.C:233
 run-single-task.C:234
 run-single-task.C:235
 run-single-task.C:236
 run-single-task.C:237
 run-single-task.C:238
 run-single-task.C:239
 run-single-task.C:240
 run-single-task.C:241
 run-single-task.C:242
 run-single-task.C:243
 run-single-task.C:244
 run-single-task.C:245
 run-single-task.C:246
 run-single-task.C:247
 run-single-task.C:248
 run-single-task.C:249
 run-single-task.C:250
 run-single-task.C:251
 run-single-task.C:252
 run-single-task.C:253
 run-single-task.C:254
 run-single-task.C:255
 run-single-task.C:256
 run-single-task.C:257
 run-single-task.C:258
 run-single-task.C:259
 run-single-task.C:260
 run-single-task.C:261
 run-single-task.C:262
 run-single-task.C:263
 run-single-task.C:264
 run-single-task.C:265
 run-single-task.C:266
 run-single-task.C:267
 run-single-task.C:268
 run-single-task.C:269
 run-single-task.C:270
 run-single-task.C:271
 run-single-task.C:272
 run-single-task.C:273
 run-single-task.C:274
 run-single-task.C:275
 run-single-task.C:276
 run-single-task.C:277
 run-single-task.C:278
 run-single-task.C:279
 run-single-task.C:280
 run-single-task.C:281
 run-single-task.C:282
 run-single-task.C:283
 run-single-task.C:284
 run-single-task.C:285
 run-single-task.C:286
 run-single-task.C:287
 run-single-task.C:288
 run-single-task.C:289
 run-single-task.C:290
 run-single-task.C:291
 run-single-task.C:292
 run-single-task.C:293
 run-single-task.C:294
 run-single-task.C:295
 run-single-task.C:296
 run-single-task.C:297
 run-single-task.C:298
 run-single-task.C:299
 run-single-task.C:300
 run-single-task.C:301
 run-single-task.C:302
 run-single-task.C:303
 run-single-task.C:304
 run-single-task.C:305
 run-single-task.C:306
 run-single-task.C:307
 run-single-task.C:308
 run-single-task.C:309
 run-single-task.C:310
 run-single-task.C:311
 run-single-task.C:312
 run-single-task.C:313
 run-single-task.C:314
 run-single-task.C:315
 run-single-task.C:316
 run-single-task.C:317
 run-single-task.C:318
 run-single-task.C:319
 run-single-task.C:320
 run-single-task.C:321
 run-single-task.C:322
 run-single-task.C:323
 run-single-task.C:324
 run-single-task.C:325
 run-single-task.C:326
 run-single-task.C:327
 run-single-task.C:328
 run-single-task.C:329
 run-single-task.C:330
 run-single-task.C:331
 run-single-task.C:332
 run-single-task.C:333
 run-single-task.C:334
 run-single-task.C:335
 run-single-task.C:336
 run-single-task.C:337
 run-single-task.C:338
 run-single-task.C:339
 run-single-task.C:340
 run-single-task.C:341
 run-single-task.C:342
 run-single-task.C:343
 run-single-task.C:344
 run-single-task.C:345
 run-single-task.C:346
 run-single-task.C:347
 run-single-task.C:348
 run-single-task.C:349
 run-single-task.C:350
 run-single-task.C:351
 run-single-task.C:352
 run-single-task.C:353
 run-single-task.C:354
 run-single-task.C:355
 run-single-task.C:356
 run-single-task.C:357
 run-single-task.C:358
 run-single-task.C:359
 run-single-task.C:360
 run-single-task.C:361
 run-single-task.C:362
 run-single-task.C:363
 run-single-task.C:364
 run-single-task.C:365
 run-single-task.C:366
 run-single-task.C:367
 run-single-task.C:368
 run-single-task.C:369
 run-single-task.C:370
 run-single-task.C:371
 run-single-task.C:372
 run-single-task.C:373
 run-single-task.C:374
 run-single-task.C:375
 run-single-task.C:376
 run-single-task.C:377
 run-single-task.C:378
 run-single-task.C:379
 run-single-task.C:380
 run-single-task.C:381
 run-single-task.C:382
 run-single-task.C:383
 run-single-task.C:384
 run-single-task.C:385
 run-single-task.C:386
 run-single-task.C:387
 run-single-task.C:388
 run-single-task.C:389
 run-single-task.C:390
 run-single-task.C:391
 run-single-task.C:392
 run-single-task.C:393
 run-single-task.C:394
 run-single-task.C:395
 run-single-task.C:396
 run-single-task.C:397
 run-single-task.C:398
 run-single-task.C:399
 run-single-task.C:400
 run-single-task.C:401
 run-single-task.C:402
 run-single-task.C:403
 run-single-task.C:404
 run-single-task.C:405
 run-single-task.C:406
 run-single-task.C:407
 run-single-task.C:408
 run-single-task.C:409
 run-single-task.C:410
 run-single-task.C:411
 run-single-task.C:412
 run-single-task.C:413
 run-single-task.C:414
 run-single-task.C:415
 run-single-task.C:416
 run-single-task.C:417
 run-single-task.C:418
 run-single-task.C:419
 run-single-task.C:420
 run-single-task.C:421
 run-single-task.C:422
 run-single-task.C:423
 run-single-task.C:424
 run-single-task.C:425
 run-single-task.C:426
 run-single-task.C:427
 run-single-task.C:428
 run-single-task.C:429
 run-single-task.C:430
 run-single-task.C:431
 run-single-task.C:432
 run-single-task.C:433
 run-single-task.C:434
 run-single-task.C:435
 run-single-task.C:436
 run-single-task.C:437
 run-single-task.C:438
 run-single-task.C:439
 run-single-task.C:440
 run-single-task.C:441
 run-single-task.C:442
 run-single-task.C:443
 run-single-task.C:444
 run-single-task.C:445
 run-single-task.C:446
 run-single-task.C:447
 run-single-task.C:448
 run-single-task.C:449
 run-single-task.C:450
 run-single-task.C:451
 run-single-task.C:452
 run-single-task.C:453
 run-single-task.C:454
 run-single-task.C:455
 run-single-task.C:456
 run-single-task.C:457
 run-single-task.C:458
 run-single-task.C:459
 run-single-task.C:460
 run-single-task.C:461
 run-single-task.C:462
 run-single-task.C:463
 run-single-task.C:464
 run-single-task.C:465
 run-single-task.C:466
 run-single-task.C:467
 run-single-task.C:468
 run-single-task.C:469
 run-single-task.C:470
 run-single-task.C:471
 run-single-task.C:472
 run-single-task.C:473
 run-single-task.C:474
 run-single-task.C:475
 run-single-task.C:476
 run-single-task.C:477
 run-single-task.C:478
 run-single-task.C:479
 run-single-task.C:480
 run-single-task.C:481
 run-single-task.C:482
 run-single-task.C:483
 run-single-task.C:484
 run-single-task.C:485
 run-single-task.C:486
 run-single-task.C:487
 run-single-task.C:488
 run-single-task.C:489
 run-single-task.C:490
 run-single-task.C:491
 run-single-task.C:492
 run-single-task.C:493
 run-single-task.C:494
 run-single-task.C:495
 run-single-task.C:496
 run-single-task.C:497
 run-single-task.C:498
 run-single-task.C:499
 run-single-task.C:500
 run-single-task.C:501
 run-single-task.C:502
 run-single-task.C:503
 run-single-task.C:504
 run-single-task.C:505
 run-single-task.C:506
 run-single-task.C:507
 run-single-task.C:508
 run-single-task.C:509
 run-single-task.C:510
 run-single-task.C:511
 run-single-task.C:512
 run-single-task.C:513
 run-single-task.C:514
 run-single-task.C:515
 run-single-task.C:516
 run-single-task.C:517
 run-single-task.C:518
 run-single-task.C:519
 run-single-task.C:520
 run-single-task.C:521
 run-single-task.C:522
 run-single-task.C:523
 run-single-task.C:524
 run-single-task.C:525
 run-single-task.C:526
 run-single-task.C:527
 run-single-task.C:528
 run-single-task.C:529
 run-single-task.C:530
 run-single-task.C:531
 run-single-task.C:532
 run-single-task.C:533
 run-single-task.C:534
 run-single-task.C:535
 run-single-task.C:536
 run-single-task.C:537
 run-single-task.C:538
 run-single-task.C:539
 run-single-task.C:540
 run-single-task.C:541
 run-single-task.C:542
 run-single-task.C:543
 run-single-task.C:544
 run-single-task.C:545
 run-single-task.C:546
 run-single-task.C:547
 run-single-task.C:548
 run-single-task.C:549
 run-single-task.C:550
 run-single-task.C:551
 run-single-task.C:552
 run-single-task.C:553
 run-single-task.C:554
 run-single-task.C:555
 run-single-task.C:556
 run-single-task.C:557
 run-single-task.C:558
 run-single-task.C:559
 run-single-task.C:560
 run-single-task.C:561
 run-single-task.C:562
 run-single-task.C:563
 run-single-task.C:564
 run-single-task.C:565
 run-single-task.C:566
 run-single-task.C:567
 run-single-task.C:568
 run-single-task.C:569
 run-single-task.C:570
 run-single-task.C:571
 run-single-task.C:572
 run-single-task.C:573
 run-single-task.C:574
 run-single-task.C:575
 run-single-task.C:576
 run-single-task.C:577
 run-single-task.C:578
 run-single-task.C:579
 run-single-task.C:580
 run-single-task.C:581
 run-single-task.C:582
 run-single-task.C:583
 run-single-task.C:584
 run-single-task.C:585
 run-single-task.C:586
 run-single-task.C:587
 run-single-task.C:588
 run-single-task.C:589
 run-single-task.C:590
 run-single-task.C:591
 run-single-task.C:592
 run-single-task.C:593
 run-single-task.C:594
 run-single-task.C:595
 run-single-task.C:596
 run-single-task.C:597
 run-single-task.C:598
 run-single-task.C:599
 run-single-task.C:600
 run-single-task.C:601
 run-single-task.C:602
 run-single-task.C:603
 run-single-task.C:604
 run-single-task.C:605
 run-single-task.C:606
 run-single-task.C:607
 run-single-task.C:608
 run-single-task.C:609
 run-single-task.C:610
 run-single-task.C:611
 run-single-task.C:612
 run-single-task.C:613
 run-single-task.C:614
 run-single-task.C:615
 run-single-task.C:616
 run-single-task.C:617
 run-single-task.C:618
 run-single-task.C:619
 run-single-task.C:620
 run-single-task.C:621
 run-single-task.C:622
 run-single-task.C:623
 run-single-task.C:624
 run-single-task.C:625
 run-single-task.C:626
 run-single-task.C:627
 run-single-task.C:628
 run-single-task.C:629
 run-single-task.C:630
 run-single-task.C:631
 run-single-task.C:632
 run-single-task.C:633
 run-single-task.C:634
 run-single-task.C:635
 run-single-task.C:636
 run-single-task.C:637
 run-single-task.C:638
 run-single-task.C:639
 run-single-task.C:640
 run-single-task.C:641
 run-single-task.C:642
 run-single-task.C:643
 run-single-task.C:644
 run-single-task.C:645
 run-single-task.C:646
 run-single-task.C:647
 run-single-task.C:648
 run-single-task.C:649
 run-single-task.C:650
 run-single-task.C:651
 run-single-task.C:652
 run-single-task.C:653
 run-single-task.C:654
 run-single-task.C:655
 run-single-task.C:656
 run-single-task.C:657
 run-single-task.C:658
 run-single-task.C:659
 run-single-task.C:660
 run-single-task.C:661
 run-single-task.C:662
 run-single-task.C:663
 run-single-task.C:664
 run-single-task.C:665
 run-single-task.C:666
 run-single-task.C:667
 run-single-task.C:668
 run-single-task.C:669
 run-single-task.C:670
 run-single-task.C:671
 run-single-task.C:672
 run-single-task.C:673
 run-single-task.C:674
 run-single-task.C:675
 run-single-task.C:676
 run-single-task.C:677
 run-single-task.C:678
 run-single-task.C:679
 run-single-task.C:680
 run-single-task.C:681
 run-single-task.C:682
 run-single-task.C:683
 run-single-task.C:684
 run-single-task.C:685
 run-single-task.C:686
 run-single-task.C:687
 run-single-task.C:688
 run-single-task.C:689
 run-single-task.C:690
 run-single-task.C:691
 run-single-task.C:692
 run-single-task.C:693
 run-single-task.C:694
 run-single-task.C:695
 run-single-task.C:696
 run-single-task.C:697
 run-single-task.C:698
 run-single-task.C:699
 run-single-task.C:700
 run-single-task.C:701
 run-single-task.C:702
 run-single-task.C:703
 run-single-task.C:704
 run-single-task.C:705
 run-single-task.C:706
 run-single-task.C:707
 run-single-task.C:708
 run-single-task.C:709
 run-single-task.C:710
 run-single-task.C:711
 run-single-task.C:712
 run-single-task.C:713
 run-single-task.C:714
 run-single-task.C:715
 run-single-task.C:716
 run-single-task.C:717
 run-single-task.C:718
 run-single-task.C:719
 run-single-task.C:720
 run-single-task.C:721
 run-single-task.C:722
 run-single-task.C:723
 run-single-task.C:724
 run-single-task.C:725
 run-single-task.C:726
 run-single-task.C:727
 run-single-task.C:728
 run-single-task.C:729
 run-single-task.C:730
 run-single-task.C:731
 run-single-task.C:732
 run-single-task.C:733
 run-single-task.C:734
 run-single-task.C:735
 run-single-task.C:736
 run-single-task.C:737
 run-single-task.C:738
 run-single-task.C:739
 run-single-task.C:740
 run-single-task.C:741
 run-single-task.C:742
 run-single-task.C:743
 run-single-task.C:744
 run-single-task.C:745
 run-single-task.C:746
 run-single-task.C:747
 run-single-task.C:748
 run-single-task.C:749
 run-single-task.C:750
 run-single-task.C:751
 run-single-task.C:752
 run-single-task.C:753
 run-single-task.C:754
 run-single-task.C:755
 run-single-task.C:756
 run-single-task.C:757
 run-single-task.C:758
 run-single-task.C:759
 run-single-task.C:760
 run-single-task.C:761
 run-single-task.C:762
 run-single-task.C:763
 run-single-task.C:764
 run-single-task.C:765
 run-single-task.C:766
 run-single-task.C:767
 run-single-task.C:768
 run-single-task.C:769
 run-single-task.C:770
 run-single-task.C:771
 run-single-task.C:772
 run-single-task.C:773
 run-single-task.C:774
 run-single-task.C:775
 run-single-task.C:776
 run-single-task.C:777
 run-single-task.C:778
 run-single-task.C:779
 run-single-task.C:780
 run-single-task.C:781
 run-single-task.C:782
 run-single-task.C:783
 run-single-task.C:784
 run-single-task.C:785
 run-single-task.C:786
 run-single-task.C:787
 run-single-task.C:788
 run-single-task.C:789
 run-single-task.C:790
 run-single-task.C:791
 run-single-task.C:792
 run-single-task.C:793
 run-single-task.C:794
 run-single-task.C:795
 run-single-task.C:796
 run-single-task.C:797
 run-single-task.C:798
 run-single-task.C:799
 run-single-task.C:800
 run-single-task.C:801
 run-single-task.C:802
 run-single-task.C:803
 run-single-task.C:804
 run-single-task.C:805
 run-single-task.C:806
 run-single-task.C:807
 run-single-task.C:808
 run-single-task.C:809
 run-single-task.C:810
 run-single-task.C:811
 run-single-task.C:812
 run-single-task.C:813
 run-single-task.C:814
 run-single-task.C:815
 run-single-task.C:816
 run-single-task.C:817
 run-single-task.C:818
 run-single-task.C:819
 run-single-task.C:820
 run-single-task.C:821
 run-single-task.C:822
 run-single-task.C:823
 run-single-task.C:824
 run-single-task.C:825
 run-single-task.C:826
 run-single-task.C:827
 run-single-task.C:828
 run-single-task.C:829
 run-single-task.C:830
 run-single-task.C:831
 run-single-task.C:832
 run-single-task.C:833
 run-single-task.C:834
 run-single-task.C:835
 run-single-task.C:836
 run-single-task.C:837
 run-single-task.C:838
 run-single-task.C:839
 run-single-task.C:840
 run-single-task.C:841
 run-single-task.C:842
 run-single-task.C:843
 run-single-task.C:844
 run-single-task.C:845
 run-single-task.C:846
 run-single-task.C:847
 run-single-task.C:848
 run-single-task.C:849
 run-single-task.C:850
 run-single-task.C:851
 run-single-task.C:852
 run-single-task.C:853
 run-single-task.C:854
 run-single-task.C:855
 run-single-task.C:856
 run-single-task.C:857
 run-single-task.C:858
 run-single-task.C:859
 run-single-task.C:860
 run-single-task.C:861
 run-single-task.C:862
 run-single-task.C:863
 run-single-task.C:864
 run-single-task.C:865
 run-single-task.C:866
 run-single-task.C:867
 run-single-task.C:868
 run-single-task.C:869
 run-single-task.C:870
 run-single-task.C:871
 run-single-task.C:872
 run-single-task.C:873
 run-single-task.C:874
 run-single-task.C:875
 run-single-task.C:876
 run-single-task.C:877
 run-single-task.C:878
 run-single-task.C:879
 run-single-task.C:880
 run-single-task.C:881
 run-single-task.C:882
 run-single-task.C:883
 run-single-task.C:884
 run-single-task.C:885
 run-single-task.C:886
 run-single-task.C:887
 run-single-task.C:888
 run-single-task.C:889
 run-single-task.C:890
 run-single-task.C:891
 run-single-task.C:892
 run-single-task.C:893
 run-single-task.C:894
 run-single-task.C:895
 run-single-task.C:896
 run-single-task.C:897
 run-single-task.C:898
 run-single-task.C:899
 run-single-task.C:900
 run-single-task.C:901
 run-single-task.C:902
 run-single-task.C:903
 run-single-task.C:904
 run-single-task.C:905
 run-single-task.C:906
 run-single-task.C:907
 run-single-task.C:908
 run-single-task.C:909
 run-single-task.C:910
 run-single-task.C:911
 run-single-task.C:912
 run-single-task.C:913
 run-single-task.C:914
 run-single-task.C:915
 run-single-task.C:916
 run-single-task.C:917
 run-single-task.C:918
 run-single-task.C:919
 run-single-task.C:920
 run-single-task.C:921
 run-single-task.C:922
 run-single-task.C:923
 run-single-task.C:924
 run-single-task.C:925
 run-single-task.C:926
 run-single-task.C:927
 run-single-task.C:928
 run-single-task.C:929
 run-single-task.C:930
 run-single-task.C:931
 run-single-task.C:932
 run-single-task.C:933
 run-single-task.C:934
 run-single-task.C:935
 run-single-task.C:936
 run-single-task.C:937
 run-single-task.C:938
 run-single-task.C:939
 run-single-task.C:940
 run-single-task.C:941
 run-single-task.C:942
 run-single-task.C:943
 run-single-task.C:944
 run-single-task.C:945
 run-single-task.C:946
 run-single-task.C:947
 run-single-task.C:948
 run-single-task.C:949
 run-single-task.C:950
 run-single-task.C:951
 run-single-task.C:952
 run-single-task.C:953
 run-single-task.C:954
 run-single-task.C:955
 run-single-task.C:956
 run-single-task.C:957
 run-single-task.C:958
 run-single-task.C:959
 run-single-task.C:960
 run-single-task.C:961
 run-single-task.C:962
 run-single-task.C:963
 run-single-task.C:964
 run-single-task.C:965
 run-single-task.C:966
 run-single-task.C:967
 run-single-task.C:968
 run-single-task.C:969
 run-single-task.C:970
 run-single-task.C:971
 run-single-task.C:972
 run-single-task.C:973
 run-single-task.C:974
 run-single-task.C:975
 run-single-task.C:976
 run-single-task.C:977
 run-single-task.C:978
 run-single-task.C:979
 run-single-task.C:980
 run-single-task.C:981
 run-single-task.C:982
 run-single-task.C:983
 run-single-task.C:984
 run-single-task.C:985
 run-single-task.C:986
 run-single-task.C:987
 run-single-task.C:988
 run-single-task.C:989
 run-single-task.C:990
 run-single-task.C:991
 run-single-task.C:992
 run-single-task.C:993
 run-single-task.C:994
 run-single-task.C:995
 run-single-task.C:996
 run-single-task.C:997
 run-single-task.C:998
 run-single-task.C:999
 run-single-task.C:1000
 run-single-task.C:1001
 run-single-task.C:1002
 run-single-task.C:1003
 run-single-task.C:1004
 run-single-task.C:1005
 run-single-task.C:1006
 run-single-task.C:1007
 run-single-task.C:1008
 run-single-task.C:1009
 run-single-task.C:1010
 run-single-task.C:1011
 run-single-task.C:1012
 run-single-task.C:1013
 run-single-task.C:1014
 run-single-task.C:1015
 run-single-task.C:1016
 run-single-task.C:1017
 run-single-task.C:1018
 run-single-task.C:1019
 run-single-task.C:1020
 run-single-task.C:1021
 run-single-task.C:1022
 run-single-task.C:1023
 run-single-task.C:1024
 run-single-task.C:1025
 run-single-task.C:1026
 run-single-task.C:1027
 run-single-task.C:1028
 run-single-task.C:1029
 run-single-task.C:1030
 run-single-task.C:1031
 run-single-task.C:1032
 run-single-task.C:1033
 run-single-task.C:1034
 run-single-task.C:1035
 run-single-task.C:1036
 run-single-task.C:1037
 run-single-task.C:1038
 run-single-task.C:1039
 run-single-task.C:1040
 run-single-task.C:1041
 run-single-task.C:1042
 run-single-task.C:1043
 run-single-task.C:1044
 run-single-task.C:1045
 run-single-task.C:1046
 run-single-task.C:1047
 run-single-task.C:1048
 run-single-task.C:1049
 run-single-task.C:1050
 run-single-task.C:1051
 run-single-task.C:1052
 run-single-task.C:1053
 run-single-task.C:1054
 run-single-task.C:1055
 run-single-task.C:1056
 run-single-task.C:1057
 run-single-task.C:1058
 run-single-task.C:1059
 run-single-task.C:1060
 run-single-task.C:1061
 run-single-task.C:1062
 run-single-task.C:1063
 run-single-task.C:1064
 run-single-task.C:1065
 run-single-task.C:1066
 run-single-task.C:1067
 run-single-task.C:1068
 run-single-task.C:1069
 run-single-task.C:1070
 run-single-task.C:1071
 run-single-task.C:1072
 run-single-task.C:1073
 run-single-task.C:1074
 run-single-task.C:1075
 run-single-task.C:1076
 run-single-task.C:1077
 run-single-task.C:1078
 run-single-task.C:1079
 run-single-task.C:1080
 run-single-task.C:1081
 run-single-task.C:1082
 run-single-task.C:1083
 run-single-task.C:1084
 run-single-task.C:1085
 run-single-task.C:1086
 run-single-task.C:1087
 run-single-task.C:1088
 run-single-task.C:1089
 run-single-task.C:1090
 run-single-task.C:1091
 run-single-task.C:1092
 run-single-task.C:1093
 run-single-task.C:1094
 run-single-task.C:1095
 run-single-task.C:1096
 run-single-task.C:1097
 run-single-task.C:1098
 run-single-task.C:1099
 run-single-task.C:1100
 run-single-task.C:1101
 run-single-task.C:1102
 run-single-task.C:1103
 run-single-task.C:1104
 run-single-task.C:1105
 run-single-task.C:1106
 run-single-task.C:1107
 run-single-task.C:1108
 run-single-task.C:1109
 run-single-task.C:1110
 run-single-task.C:1111
 run-single-task.C:1112
 run-single-task.C:1113
 run-single-task.C:1114
 run-single-task.C:1115
 run-single-task.C:1116
 run-single-task.C:1117
 run-single-task.C:1118
 run-single-task.C:1119
 run-single-task.C:1120
 run-single-task.C:1121
 run-single-task.C:1122
 run-single-task.C:1123
 run-single-task.C:1124
 run-single-task.C:1125
 run-single-task.C:1126
 run-single-task.C:1127
 run-single-task.C:1128
 run-single-task.C:1129
 run-single-task.C:1130
 run-single-task.C:1131
 run-single-task.C:1132
 run-single-task.C:1133
 run-single-task.C:1134
 run-single-task.C:1135
 run-single-task.C:1136
 run-single-task.C:1137
 run-single-task.C:1138
 run-single-task.C:1139
 run-single-task.C:1140
 run-single-task.C:1141
 run-single-task.C:1142
 run-single-task.C:1143
 run-single-task.C:1144
 run-single-task.C:1145
 run-single-task.C:1146
 run-single-task.C:1147
 run-single-task.C:1148
 run-single-task.C:1149
 run-single-task.C:1150
 run-single-task.C:1151
 run-single-task.C:1152
 run-single-task.C:1153
 run-single-task.C:1154
 run-single-task.C:1155
 run-single-task.C:1156
 run-single-task.C:1157
 run-single-task.C:1158
 run-single-task.C:1159
 run-single-task.C:1160
 run-single-task.C:1161
 run-single-task.C:1162
 run-single-task.C:1163
 run-single-task.C:1164
 run-single-task.C:1165
 run-single-task.C:1166
 run-single-task.C:1167
 run-single-task.C:1168
 run-single-task.C:1169
 run-single-task.C:1170
 run-single-task.C:1171
 run-single-task.C:1172
 run-single-task.C:1173
 run-single-task.C:1174
 run-single-task.C:1175
 run-single-task.C:1176
 run-single-task.C:1177
 run-single-task.C:1178
 run-single-task.C:1179
 run-single-task.C:1180
 run-single-task.C:1181
 run-single-task.C:1182
 run-single-task.C:1183
 run-single-task.C:1184
 run-single-task.C:1185
 run-single-task.C:1186
 run-single-task.C:1187
 run-single-task.C:1188
 run-single-task.C:1189
 run-single-task.C:1190
 run-single-task.C:1191
 run-single-task.C:1192
 run-single-task.C:1193
 run-single-task.C:1194
 run-single-task.C:1195
 run-single-task.C:1196
 run-single-task.C:1197
 run-single-task.C:1198
 run-single-task.C:1199
 run-single-task.C:1200
 run-single-task.C:1201
 run-single-task.C:1202
 run-single-task.C:1203
 run-single-task.C:1204
 run-single-task.C:1205
 run-single-task.C:1206
 run-single-task.C:1207
 run-single-task.C:1208
 run-single-task.C:1209
 run-single-task.C:1210
 run-single-task.C:1211
 run-single-task.C:1212
 run-single-task.C:1213
 run-single-task.C:1214
 run-single-task.C:1215
 run-single-task.C:1216
 run-single-task.C:1217
 run-single-task.C:1218
 run-single-task.C:1219
 run-single-task.C:1220
 run-single-task.C:1221
 run-single-task.C:1222
 run-single-task.C:1223
 run-single-task.C:1224
 run-single-task.C:1225
 run-single-task.C:1226
 run-single-task.C:1227
 run-single-task.C:1228
 run-single-task.C:1229
 run-single-task.C:1230
 run-single-task.C:1231
 run-single-task.C:1232
 run-single-task.C:1233
 run-single-task.C:1234
 run-single-task.C:1235
 run-single-task.C:1236
 run-single-task.C:1237
 run-single-task.C:1238
 run-single-task.C:1239
 run-single-task.C:1240
 run-single-task.C:1241
 run-single-task.C:1242
 run-single-task.C:1243
 run-single-task.C:1244
 run-single-task.C:1245
 run-single-task.C:1246
 run-single-task.C:1247
 run-single-task.C:1248
 run-single-task.C:1249
 run-single-task.C:1250
 run-single-task.C:1251
 run-single-task.C:1252
 run-single-task.C:1253
 run-single-task.C:1254
 run-single-task.C:1255
 run-single-task.C:1256
 run-single-task.C:1257
 run-single-task.C:1258
 run-single-task.C:1259
 run-single-task.C:1260
 run-single-task.C:1261
 run-single-task.C:1262
 run-single-task.C:1263
 run-single-task.C:1264
 run-single-task.C:1265
 run-single-task.C:1266
 run-single-task.C:1267
 run-single-task.C:1268
 run-single-task.C:1269
 run-single-task.C:1270
 run-single-task.C:1271
 run-single-task.C:1272
 run-single-task.C:1273
 run-single-task.C:1274
 run-single-task.C:1275
 run-single-task.C:1276
 run-single-task.C:1277
 run-single-task.C:1278
 run-single-task.C:1279
 run-single-task.C:1280
 run-single-task.C:1281
 run-single-task.C:1282
 run-single-task.C:1283
 run-single-task.C:1284
 run-single-task.C:1285
 run-single-task.C:1286
 run-single-task.C:1287
 run-single-task.C:1288
 run-single-task.C:1289
 run-single-task.C:1290
 run-single-task.C:1291
 run-single-task.C:1292
 run-single-task.C:1293
 run-single-task.C:1294
 run-single-task.C:1295
 run-single-task.C:1296
 run-single-task.C:1297
 run-single-task.C:1298
 run-single-task.C:1299
 run-single-task.C:1300
 run-single-task.C:1301
 run-single-task.C:1302
 run-single-task.C:1303
 run-single-task.C:1304
 run-single-task.C:1305
 run-single-task.C:1306
 run-single-task.C:1307
 run-single-task.C:1308
 run-single-task.C:1309
 run-single-task.C:1310
 run-single-task.C:1311
 run-single-task.C:1312
 run-single-task.C:1313
 run-single-task.C:1314
 run-single-task.C:1315
 run-single-task.C:1316
 run-single-task.C:1317
 run-single-task.C:1318
 run-single-task.C:1319
 run-single-task.C:1320
 run-single-task.C:1321
 run-single-task.C:1322
 run-single-task.C:1323
 run-single-task.C:1324
 run-single-task.C:1325
 run-single-task.C:1326
 run-single-task.C:1327
 run-single-task.C:1328
 run-single-task.C:1329
 run-single-task.C:1330
 run-single-task.C:1331
 run-single-task.C:1332
 run-single-task.C:1333
 run-single-task.C:1334
 run-single-task.C:1335
 run-single-task.C:1336
 run-single-task.C:1337
 run-single-task.C:1338
 run-single-task.C:1339
 run-single-task.C:1340
 run-single-task.C:1341
 run-single-task.C:1342
 run-single-task.C:1343
 run-single-task.C:1344
 run-single-task.C:1345
 run-single-task.C:1346
 run-single-task.C:1347
 run-single-task.C:1348
 run-single-task.C:1349
 run-single-task.C:1350
 run-single-task.C:1351
 run-single-task.C:1352
 run-single-task.C:1353
 run-single-task.C:1354
 run-single-task.C:1355
 run-single-task.C:1356
 run-single-task.C:1357
 run-single-task.C:1358
 run-single-task.C:1359
 run-single-task.C:1360
 run-single-task.C:1361
 run-single-task.C:1362
 run-single-task.C:1363
 run-single-task.C:1364
 run-single-task.C:1365
 run-single-task.C:1366
 run-single-task.C:1367
 run-single-task.C:1368
 run-single-task.C:1369
 run-single-task.C:1370
 run-single-task.C:1371
 run-single-task.C:1372
 run-single-task.C:1373
 run-single-task.C:1374
 run-single-task.C:1375
 run-single-task.C:1376
 run-single-task.C:1377
 run-single-task.C:1378
 run-single-task.C:1379
 run-single-task.C:1380
 run-single-task.C:1381
 run-single-task.C:1382
 run-single-task.C:1383
 run-single-task.C:1384
 run-single-task.C:1385
 run-single-task.C:1386
 run-single-task.C:1387
 run-single-task.C:1388
 run-single-task.C:1389
 run-single-task.C:1390
 run-single-task.C:1391
 run-single-task.C:1392
 run-single-task.C:1393
 run-single-task.C:1394
 run-single-task.C:1395
 run-single-task.C:1396
 run-single-task.C:1397
 run-single-task.C:1398
 run-single-task.C:1399
 run-single-task.C:1400
 run-single-task.C:1401
 run-single-task.C:1402
 run-single-task.C:1403
 run-single-task.C:1404
 run-single-task.C:1405
 run-single-task.C:1406
 run-single-task.C:1407
 run-single-task.C:1408
 run-single-task.C:1409
 run-single-task.C:1410
 run-single-task.C:1411
 run-single-task.C:1412
 run-single-task.C:1413
 run-single-task.C:1414
 run-single-task.C:1415
 run-single-task.C:1416
 run-single-task.C:1417
 run-single-task.C:1418
 run-single-task.C:1419
 run-single-task.C:1420
 run-single-task.C:1421
 run-single-task.C:1422
 run-single-task.C:1423
 run-single-task.C:1424
 run-single-task.C:1425
 run-single-task.C:1426
 run-single-task.C:1427
 run-single-task.C:1428
 run-single-task.C:1429
 run-single-task.C:1430
 run-single-task.C:1431
 run-single-task.C:1432
 run-single-task.C:1433
 run-single-task.C:1434
 run-single-task.C:1435
 run-single-task.C:1436
 run-single-task.C:1437
 run-single-task.C:1438
 run-single-task.C:1439
 run-single-task.C:1440
 run-single-task.C:1441
 run-single-task.C:1442
 run-single-task.C:1443
 run-single-task.C:1444
 run-single-task.C:1445
 run-single-task.C:1446
 run-single-task.C:1447
 run-single-task.C:1448
 run-single-task.C:1449
 run-single-task.C:1450
 run-single-task.C:1451
 run-single-task.C:1452
 run-single-task.C:1453
 run-single-task.C:1454
 run-single-task.C:1455
 run-single-task.C:1456
 run-single-task.C:1457
 run-single-task.C:1458
 run-single-task.C:1459
 run-single-task.C:1460
 run-single-task.C:1461
 run-single-task.C:1462
 run-single-task.C:1463
 run-single-task.C:1464
 run-single-task.C:1465
 run-single-task.C:1466
 run-single-task.C:1467
 run-single-task.C:1468
 run-single-task.C:1469
 run-single-task.C:1470
 run-single-task.C:1471
 run-single-task.C:1472
 run-single-task.C:1473
 run-single-task.C:1474
 run-single-task.C:1475
 run-single-task.C:1476
 run-single-task.C:1477
 run-single-task.C:1478
 run-single-task.C:1479
 run-single-task.C:1480
 run-single-task.C:1481
 run-single-task.C:1482
 run-single-task.C:1483
 run-single-task.C:1484
 run-single-task.C:1485
 run-single-task.C:1486
 run-single-task.C:1487
 run-single-task.C:1488
 run-single-task.C:1489
 run-single-task.C:1490
 run-single-task.C:1491
 run-single-task.C:1492
 run-single-task.C:1493
 run-single-task.C:1494
 run-single-task.C:1495
 run-single-task.C:1496
 run-single-task.C:1497
 run-single-task.C:1498
 run-single-task.C:1499
 run-single-task.C:1500
 run-single-task.C:1501
 run-single-task.C:1502
 run-single-task.C:1503
 run-single-task.C:1504
 run-single-task.C:1505
 run-single-task.C:1506
 run-single-task.C:1507
 run-single-task.C:1508
 run-single-task.C:1509
 run-single-task.C:1510
 run-single-task.C:1511
 run-single-task.C:1512
 run-single-task.C:1513
 run-single-task.C:1514