Renamed
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisAlien.cxx
index 82f6d97..3e78fb7 100644 (file)
@@ -20,6 +20,8 @@
 // a personalized JDL, finding and creating a dataset.
 //==============================================================================
 
+#include "AliAnalysisAlien.h"
+
 #include "Riostream.h"
 #include "TEnv.h"
 #include "TBits.h"
@@ -41,7 +43,7 @@
 #include "AliAnalysisManager.h"
 #include "AliVEventHandler.h"
 #include "AliAnalysisDataContainer.h"
-#include "AliAnalysisAlien.h"
+#include "AliMultiInputEventHandler.h"
 
 ClassImp(AliAnalysisAlien)
 
@@ -107,6 +109,7 @@ AliAnalysisAlien::AliAnalysisAlien()
                   fFileForTestMode(),
                   fRootVersionForProof(),
                   fAliRootMode(),
+                  fMergeDirName(),
                   fInputFiles(0),
                   fPackages(0)
 {
@@ -176,6 +179,7 @@ AliAnalysisAlien::AliAnalysisAlien(const char *name)
                   fFileForTestMode(),
                   fRootVersionForProof(),
                   fAliRootMode(),
+                  fMergeDirName(),
                   fInputFiles(0),
                   fPackages(0)
 {
@@ -245,6 +249,7 @@ AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
                   fFileForTestMode(other.fFileForTestMode),
                   fRootVersionForProof(other.fRootVersionForProof),
                   fAliRootMode(other.fAliRootMode),
+                  fMergeDirName(other.fMergeDirName),
                   fInputFiles(0),
                   fPackages(0)
 {
@@ -344,6 +349,7 @@ AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
       fFileForTestMode         = other.fFileForTestMode;
       fRootVersionForProof     = other.fRootVersionForProof;
       fAliRootMode             = other.fAliRootMode;
+      fMergeDirName            = other.fMergeDirName;
       if (other.fInputFiles) {
          fInputFiles = new TObjArray();
          TIter next(other.fInputFiles);
@@ -363,6 +369,14 @@ AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
 }
 
 //______________________________________________________________________________
+void AliAnalysisAlien::SetRunPrefix(const char *prefix)
+{
+// Set the run number format. Can be a prefix or a format like "%09d"
+   fRunPrefix = prefix;
+   if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
+}   
+
+//______________________________________________________________________________
 void AliAnalysisAlien::AddIncludePath(const char *path)
 {
 // Add include path in the remote analysis macro.
@@ -376,10 +390,24 @@ void AliAnalysisAlien::AddRunNumber(Int_t run)
 {
 // Add a run number to the list of runs to be processed.
    if (fRunNumbers.Length()) fRunNumbers += " ";
-   fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
+   fRunNumbers += Form(fRunPrefix.Data(), run);
 }   
 
 //______________________________________________________________________________
+void AliAnalysisAlien::AddRunList(const char* runList)
+{
+// Add several runs into the list of runs; they are expected to be separated by a blank character.  
+  TString    sList = runList;
+  TObjArray *list  = sList.Tokenize(" ");
+  Int_t n = list->GetEntries();
+  for (Int_t i = 0; i < n; i++) {
+    TObjString *os = (TObjString*)list->At(i);
+    AddRunNumber(os->GetString().Atoi());
+  }
+  delete list;
+}
+
+//______________________________________________________________________________
 void AliAnalysisAlien::AddRunNumber(const char* run)
 {
 // Add a run number to the list of runs to be processed.
@@ -508,6 +536,10 @@ Bool_t AliAnalysisAlien::CheckInputData()
          Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
          return kFALSE;
       }
+      if (fMergeViaJDL) {
+         Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
+         return kFALSE;
+      }   
       Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
       if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
          TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode) 
@@ -578,6 +610,7 @@ Bool_t AliAnalysisAlien::CheckInputData()
    // Check validity of run number(s)
    TObjArray *arr;
    TObjString *os;
+   TString format;
    Int_t nruns = 0;
    TString schunk, schunk2;
    TString path;
@@ -623,12 +656,13 @@ Bool_t AliAnalysisAlien::CheckInputData()
    } else {
       Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
       for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
-         path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
+         format = Form("%%s/%s ", fRunPrefix.Data());
+         path = Form(format.Data(), fGridDataDir.Data(), irun);
          if (!DirectoryExists(path)) {
-//            Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
             continue;
          }
-         path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
+         format = Form("%%s/%s.xml", fRunPrefix.Data());
+         path = Form(format.Data(), workdir.Data(),irun);
          TString msg = "\n#####   file: ";
          msg += path;
          msg += " type: xml_collection;";
@@ -636,13 +670,15 @@ Bool_t AliAnalysisAlien::CheckInputData()
          else          msg += " using_tags: No";
          Info("CheckDataType", "%s", msg.Data());
          if (fNrunsPerMaster<2) {
-            AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
+            format = Form("%s.xml", fRunPrefix.Data());
+            AddDataFile(Form(format.Data(),irun));
          } else {
             nruns++;
             if (((nruns-1)%fNrunsPerMaster) == 0) {
-               schunk = Form("%s%d", fRunPrefix.Data(),irun);
+               schunk = Form(fRunPrefix.Data(),irun);
             }
-            schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
+            format = Form("_%s.xml", fRunPrefix.Data());
+            schunk2 = Form(format.Data(), irun);
             if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
             schunk += schunk2;
             AddDataFile(schunk);
@@ -672,6 +708,7 @@ Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
    workdir += fGridWorkingDir;
 
    // Compose the 'find' command arguments
+   TString format;
    TString command;
    TString options = "-x collection ";
    if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
@@ -825,11 +862,13 @@ Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
    } else {
       // Process a full run range.
       for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
-         path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
+         format = Form("%%s/%s ", fRunPrefix.Data());
+         path = Form(format.Data(), fGridDataDir.Data(), irun);
          if (!DirectoryExists(path)) continue;
 //         CdWork();
+         format = Form("%s.xml", fRunPrefix.Data());
          if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
-         else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
+         else file = Form(format.Data(), irun);
          if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {         
             if (fOverwriteMode) gGrid->Rm(file);
             else {
@@ -887,14 +926,15 @@ Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
             }   
             printf("   Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
             if (((nruns-1)%fNrunsPerMaster) == 0) {
-               schunk = Form("%s%d", fRunPrefix.Data(), irun);
+               schunk = Form(fRunPrefix.Data(), irun);
                cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
             } else {
                cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
                cbase->Add(cadd);
                delete cadd;
             }
-            schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
+            format = Form("%%s_%s.xml", fRunPrefix.Data());
+            schunk2 = Form(format.Data(), schunk.Data(), irun);
             if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
                continue;
             }   
@@ -976,6 +1016,8 @@ Bool_t AliAnalysisAlien::CreateJDL()
                   Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
                   // error = kTRUE;
                }
+            } else {
+               Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
             }   
             gGrid->Cd(workdir);
          }   
@@ -996,7 +1038,10 @@ Bool_t AliAnalysisAlien::CreateJDL()
       if (!fArguments.IsNull())
          fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
       if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
-      else                     fMergingJDL->SetArguments("wn.xml $2 $3");    // xml, stage, laststage(0 or 1)
+      else {
+         if (fProductionMode)  fMergingJDL->SetArguments("wn.xml $4");    // xml, stage
+         else                  fMergingJDL->SetArguments("wn.xml $2");    // xml, stage
+     }               
 
       fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
       fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
@@ -1012,7 +1057,7 @@ Bool_t AliAnalysisAlien::CreateJDL()
          fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
       }
       if (!IsOneStageMerging()) {
-         fMergingJDL->SetValue("SplitMaxInputFileNumber", "\"$3\"");
+         fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
          fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
       }   
       if (fSplitMode.Length()) {
@@ -1093,7 +1138,7 @@ Bool_t AliAnalysisAlien::CreateJDL()
          // Output archive for the merging jdl
          TString outputArchive;
          if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
-            outputArchive = "log_archive.zip:std*,*.stat@disk=1 ";
+            outputArchive = "log_archive.zip:std*@disk=1 ";
             // Add normal output files, extra files + terminate files
             TString files = GetListOfFiles("outextter");
             // Do not register merge excludes
@@ -1107,7 +1152,7 @@ Bool_t AliAnalysisAlien::CreateJDL()
                delete arr;
             }
             files.ReplaceAll(".root", "*.root");
-            outputArchive += Form("root_archive.zip:%s@disk=%d",files.Data(),fNreplicas);
+            outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
          } else {
             TString files = fOutputArchive;
             files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
@@ -1237,9 +1282,15 @@ Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
    TString workdir;
    if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
    workdir += fGridWorkingDir;
-   fMergingJDL->AddToInputDataCollection("LF:$1/Stage_$2.xml,nodownload", "Collection of files to be merged for stage $2");
-   fMergingJDL->SetOutputDirectory("$1/Stage_$2/#alien_counter_03i#", "Output directory");
-   
+   TString stageName = "$2";
+   if (fProductionMode) stageName = "$4";
+   if (!fMergeDirName.IsNull()) {
+     fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
+     fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
+   } else {
+     fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
+     fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
+   }
    if (fProductionMode) {
       TIter next(fInputFiles);
       while ((os=next())) {
@@ -1273,8 +1324,14 @@ Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
    // Generate the JDL as a string
    TString sjdl = fGridJDL->Generate();
    TString sjdl1 = fMergingJDL->Generate();
-   fMergingJDL->SetOutputDirectory("$1", "Output directory");
-   fMergingJDL->AddToInputSandbox("LF:$1/$4");
+   // Final merge jdl
+   if (!fMergeDirName.IsNull()) {
+     fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
+     fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
+   } else {  
+     fMergingJDL->SetOutputDirectory("$1", "Output directory");
+     fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
+   }  
    TString sjdl2 = fMergingJDL->Generate();
    Int_t index, index1;
    sjdl.ReplaceAll("\"LF:", "\n   \"LF:");
@@ -1311,18 +1368,33 @@ Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
    index = fJobTag.Index(":");
    if (index < 0) index = fJobTag.Length();
    TString jobTag = fJobTag;
+   if (fProductionMode) jobTag.Insert(index,"_Stage$4");
    sjdl1.Prepend(Form("Jobtag = {\n   \"comment:%s_Merging\"\n};\n", jobTag.Data()));
-   sjdl1.Prepend("# Generated merging jdl \
-                  \n# $1 = full alien path to output directory to be merged \
-                  \n# $2 = merging stage \
-                  \n# $3 = maximum number of files to merge (must be >= 10000 for the last stage) \
-                  \n# $4 = xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
-   sjdl2.Prepend(Form("Jobtag = {\n   \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
-   sjdl2.Prepend("# Generated merging jdl \
-                  \n# $1 = full alien path to output directory to be merged \
-                  \n# $2 = merging stage \
-                  \n# $3 = maximum number of files to merge (must be >= 10000 for the last stage) \
-                  \n# $4 = xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
+   if (fProductionMode) {   
+     sjdl1.Prepend("# Generated merging jdl (production mode) \
+                    \n# $1 = full alien path to output directory to be merged \
+                    \n# $2 = train number \
+                    \n# $3 = production (like LHC10b) \
+                    \n# $4 = merging stage \
+                    \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
+     sjdl2.Prepend(Form("Jobtag = {\n   \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
+     sjdl2.Prepend("# Generated merging jdl \
+                    \n# $1 = full alien path to output directory to be merged \
+                    \n# $2 = train number \
+                    \n# $3 = production (like LHC10b) \
+                    \n# $4 = merging stage \
+                    \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
+   } else {
+     sjdl1.Prepend("# Generated merging jdl \
+                    \n# $1 = full alien path to output directory to be merged \
+                    \n# $2 = merging stage \
+                    \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
+     sjdl2.Prepend(Form("Jobtag = {\n   \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
+     sjdl2.Prepend("# Generated merging jdl \
+                    \n# $1 = full alien path to output directory to be merged \
+                    \n# $2 = merging stage \
+                    \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
+   }
    index = sjdl1.Index("JDLVariables");
    if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
    index = sjdl2.Index("JDLVariables");
@@ -1354,7 +1426,7 @@ Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
       index1 = sjdl2.Index("\n", index);
       sjdl2.Remove(index, index1-index+1);
    }
-   sjdl2.ReplaceAll("wn.xml", "$4");
+   sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
    // Write jdl to file
    ofstream out;
    out.open(fJDLName.Data(), ios::out);
@@ -1623,10 +1695,10 @@ const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t
    Int_t pid;
    for (Int_t ijob=0; ijob<nentries; ijob++) {
       status = (TGridJobStatus *)list->At(ijob);
-      pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
+      pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
       if (pid<jobidstart) continue;
       if (pid == lastid) {
-         gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
+         gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
       }   
       switch (status->GetStatus()) {
          case TGridJobStatus::kWAITING:
@@ -1736,7 +1808,7 @@ void AliAnalysisAlien::Print(Option_t *) const
    if (fRunNumbers.Length()) 
    printf("=   Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
    if (fRunRange[0])
-   printf("=   Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
+   printf("=   Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
    if (!fRunRange[0] && !fRunNumbers.Length()) {
       TIter next(fInputFiles);
       TObject *obj;
@@ -1806,6 +1878,7 @@ void AliAnalysisAlien::SetDefaults()
    fNreplicas                  = 2;
    fRunRange[0]                = 0;
    fRunRange[1]                = 0;
+   fRunPrefix                  = "%d";
    fNrunsPerMaster             = 1;
    fMaxMergeFiles              = 100;
    fRunNumbers                 = "";
@@ -1826,7 +1899,7 @@ void AliAnalysisAlien::SetDefaults()
    fDataPattern                = "*AliESDs.root";  // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
    fFriendChainName            = "";
    fGridOutputDir              = "output";
-   fOutputArchive              = "log_archive.zip:std*,*.stat@disk=1 root_archive.zip:*.root@disk=2";
+   fOutputArchive              = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
    fOutputFiles                = "";  // Like "AliAODs.root histos.root"
    fInputFormat                = "xml-single";
    fJDLName                    = "analysis.jdl";
@@ -1892,12 +1965,12 @@ Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *alie
       printf("### Submiting final merging stage %d\n", stage);
       TString finalJDL = jdl;
       finalJDL.ReplaceAll(".jdl", "_final.jdl");
-      TString query = Form("submit %s %s %d 10000 Stage_%d.xml", finalJDL.Data(), aliendir, stage, stage);
+      TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
       Int_t jobId = SubmitSingleJob(query);
       if (!jobId) return kFALSE;      
    } else {
       printf("### Submiting merging stage %d\n", stage);
-      TString query = Form("submit %s %s %d %d wn.xml", jdl, aliendir, stage, nperchunk);
+      TString query = Form("submit %s %s %d", jdl, aliendir, stage);
       Int_t jobId = SubmitSingleJob(query);
       if (!jobId) return kFALSE;           
    }
@@ -2167,6 +2240,8 @@ Bool_t AliAnalysisAlien::MergeOutputs()
    }   
    // Make sure we change the temporary directory
    gSystem->Setenv("TMPDIR", gSystem->pwd());
+   // Set temporary compilation directory to current one
+   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);   
    TObjArray *list = fOutputFiles.Tokenize(",");
    TIter next(list);
    TObjString *str;
@@ -2395,6 +2470,9 @@ Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEn
          if (!fIncludePath.IsNull()) {
             TString includePath = fIncludePath;
             includePath.ReplaceAll(" ",":");
+            includePath.ReplaceAll("$ALICE_ROOT","");
+            includePath.ReplaceAll("${ALICE_ROOT}","");
+            includePath.ReplaceAll("-I","");
             includePath.Strip(TString::kTrailing, ':');
             Info("StartAnalysis", "Adding extra includes: %s",includePath.Data()); 
             optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
@@ -2411,15 +2489,15 @@ Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEn
                printf("%s  %s\n", obj->GetName(), obj->GetTitle());
             }   
             if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
-              && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)0x%lx);",alirootLite.Data(),(ULong_t)&optionsList))) {
+              && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
                   Info("StartAnalysis", "AliRootProofLite enabled");
             } else {                      
                Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
                return kFALSE;
             }   
          } else {
-            if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)0x%lx);", 
-                                   fAliROOTVersion.Data(), (ULong_t)&optionsList))) {
+            if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);", 
+                                   fAliROOTVersion.Data(), &optionsList))) {
                Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
                return kFALSE;
             }         
@@ -2497,7 +2575,7 @@ Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEn
          }   
          TFileCollection *coll = new TFileCollection();
          coll->AddFromFile(fFileForTestMode);
-         gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)0x%lx, \"OV\");", (ULong_t)coll));
+         gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
          gROOT->ProcessLine("gProof->ShowDataSets()");
       }
       return kTRUE;
@@ -2515,8 +2593,8 @@ Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEn
          fOutputFiles += extra;
       }
       // Compose the output archive.
-      fOutputArchive = "log_archive.zip:std*,*.stat@disk=1 ";
-      fOutputArchive += Form("root_archive.zip:%s@disk=%d",fOutputFiles.Data(),fNreplicas);
+      fOutputArchive = "log_archive.zip:std*@disk=1 ";
+      fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
    }
 //   if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
    if (TestBit(AliAnalysisGrid::kOffline)) {
@@ -2758,6 +2836,10 @@ Bool_t AliAnalysisAlien::SubmitMerging()
    gGrid->Cd(fGridOutputDir);
    TString mergeJDLName = fExecutable;
    mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
+   if (!fInputFiles) {
+      Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
+      return kFALSE;
+   }   
    Int_t ntosubmit = fInputFiles->GetEntries();
    for (Int_t i=0; i<ntosubmit; i++) {
       TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
@@ -2767,9 +2849,15 @@ Bool_t AliAnalysisAlien::SubmitMerging()
          printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
          runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
       } else {
-         // The output directory is the master number in 3 digits format
-         printf("### Submitting merging job for master <%03d>\n", i);
-         runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
+         if (!fRunNumbers.Length() && !fRunRange[0]) {
+            // The output directory is the grid outdir
+            printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
+            runOutDir = fGridOutputDir;
+         } else {
+            // The output directory is the master number in 3 digits format
+            printf("### Submitting merging job for master <%03d>\n", i);
+            runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
+         }   
       }
       // Check now the number of merging stages.
       TObjArray *list = fOutputFiles.Tokenize(",");
@@ -2784,12 +2872,15 @@ Bool_t AliAnalysisAlien::SubmitMerging()
       }
       delete list;
       Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
-      if (!done) return kFALSE;
+      if (!done && (i==ntosubmit-1)) return kFALSE;
+      if (!fRunNumbers.Length() && !fRunRange[0]) break;
    }
    if (!ntosubmit) return kTRUE;
-   Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
-   \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
-   \n ##################################################################################");
+   Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
+                          \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
+                          \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
+                          \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
+                          \n ################################################################################################################");
    gSystem->Exec("aliensh");
    return kTRUE;
 }
@@ -2891,8 +2982,14 @@ void AliAnalysisAlien::WriteAnalysisFile()
       if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
       handler = (TObject*)mgr->GetInputEventHandler();
       if (handler) {
-         if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
-         if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
+         if (handler->InheritsFrom("AliMultiInputEventHandler")) {
+            AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
+            if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
+            if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
+         } else {
+            if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
+            if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
+         }
       }
       TDirectory *cdir = gDirectory;
       TFile *file = TFile::Open(analysisFile, "RECREATE");
@@ -2941,11 +3038,16 @@ void AliAnalysisAlien::WriteAnalysisMacro()
       TString func = fAnalysisMacro;
       TString type = "ESD";
       TString comment = "// Analysis using ";
-      if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
-      if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
-         type = "AOD";
-         comment += "AOD";
-      }   
+      if (IsUseMCchain()) {
+         type = "MC";
+         comment += "MC";
+      } else {   
+         if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
+         if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
+            type = "AOD";
+            comment += "AOD";
+         }   
+      }
       if (type!="AOD" && fFriendChainName!="") {
          Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
          return;
@@ -2963,6 +3065,8 @@ void AliAnalysisAlien::WriteAnalysisMacro()
       // Change temp directory to current one
       out << "// Set temporary merging directory to current one" << endl;
       out << "   gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;   
+      out << "// Set temporary compilation directory to current one" << endl;
+      out << "   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;   
       // Reset existing include path
       out << "// Reset existing include path and add current directory first in the search" << endl;
       out << "   gSystem->SetIncludePath(\"-I.\");" << endl;
@@ -3187,9 +3291,13 @@ void AliAnalysisAlien::WriteAnalysisMacro()
          out << "// Create a chain using url's from xml file" << endl;
          out << "   TString filename;" << endl;
          out << "   Int_t run = 0;" << endl;
-         out << "   TString treename = type;" << endl;
-         out << "   treename.ToLower();" << endl;
-         out << "   treename += \"Tree\";" << endl;
+         if (IsUseMCchain()) {
+            out << "   TString treename = \"TE\";" << endl;
+         } else {   
+            out << "   TString treename = type;" << endl;
+            out << "   treename.ToLower();" << endl;
+            out << "   treename += \"Tree\";" << endl;
+         }   
          out << "   printf(\"***************************************\\n\");" << endl;
          out << "   printf(\"    Getting chain of trees %s\\n\", treename.Data());" << endl;
          out << "   printf(\"***************************************\\n\");" << endl;
@@ -3319,7 +3427,7 @@ void AliAnalysisAlien::WriteMergingMacro()
       TString func = mergingMacro;
       TString comment;
       func.ReplaceAll(".C", "");
-      out << "void " << func.Data() << "(const char *dir, Int_t stage=0, Int_t laststage=0)" << endl;
+      out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
       out << "{" << endl;
       out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
       out << "   TStopwatch timer;" << endl;
@@ -3461,6 +3569,8 @@ void AliAnalysisAlien::WriteMergingMacro()
       // Change temp directory to current one
       out << "// Set temporary merging directory to current one" << endl;
       out << "   gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;   
+      out << "// Set temporary compilation directory to current one" << endl;
+      out << "   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;   
       out << "// Connect to AliEn" << endl;
       out << "   if (!TGrid::Connect(\"alien://\")) return;" << endl;
       out << "   TString outputDir = dir;" << endl;  
@@ -3495,7 +3605,7 @@ void AliAnalysisAlien::WriteMergingMacro()
       out << "   // read the analysis manager from file" << endl;
       TString analysisFile = fExecutable;
       analysisFile.ReplaceAll(".sh", ".root");
-      out << "   if (laststage<10000) return;" << endl;
+      out << "   if (!outputDir.Contains(\"Stage\")) return;" << endl;
       out << "   TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
       out << "   if (!file) return;" << endl;
       out << "   TIter nextkey(file->GetListOfKeys());" << endl;
@@ -3714,7 +3824,7 @@ void AliAnalysisAlien::WriteMergeExecutable()
       if (IsOneStageMerging())
          out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
       else
-         out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2,$3)\"" << endl;
+         out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
       out << fExecutableCommand << " " << "$ARG" << endl; 
       out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
       out << "echo \"############## memory after: ##############\"" << endl;