]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisAlien.cxx
update of GTU simulation
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisAlien.cxx
CommitLineData
c57f56b7 1/**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16// Author: Mihaela Gheata, 01/09/2008
17
18//==============================================================================
19// AliAnalysisAlien - AliEn utility class. Provides interface for creating
20// a personalized JDL, finding and creating a dataset.
21//==============================================================================
22
65eb22f8 23#include "AliAnalysisAlien.h"
24
c57f56b7 25#include "Riostream.h"
0f389141 26#include "TEnv.h"
7c2cd90a 27#include "TBits.h"
0f389141 28#include "TError.h"
c57f56b7 29#include "TROOT.h"
30#include "TSystem.h"
31#include "TFile.h"
830acc4c 32#include "TFileCollection.h"
3bdcb562 33#include "TChain.h"
c57f56b7 34#include "TObjString.h"
35#include "TObjArray.h"
36#include "TGrid.h"
37#include "TGridResult.h"
38#include "TGridCollection.h"
39#include "TGridJDL.h"
d2a409b2 40#include "TGridJobStatusList.h"
41#include "TGridJobStatus.h"
c57f56b7 42#include "TFileMerger.h"
43#include "AliAnalysisManager.h"
bb885a9e 44#include "AliVEventHandler.h"
45#include "AliAnalysisDataContainer.h"
65eb22f8 46#include "AliMultiInputEventHandler.h"
c57f56b7 47
48ClassImp(AliAnalysisAlien)
49
50//______________________________________________________________________________
51AliAnalysisAlien::AliAnalysisAlien()
52 :AliAnalysisGrid(),
53 fGridJDL(NULL),
0f389141 54 fMergingJDL(NULL),
c57f56b7 55 fPrice(0),
56 fTTL(0),
57 fSplitMaxInputFileNumber(0),
58 fMaxInitFailed(0),
59 fMasterResubmitThreshold(0),
bb885a9e 60 fNtestFiles(0),
319593fb 61 fNrunsPerMaster(0),
16a4353c 62 fMaxMergeFiles(0),
b3e07543 63 fMaxMergeStages(0),
d2a409b2 64 fNsubmitted(0),
a3e84053 65 fProductionMode(0),
cd11251e 66 fOutputToRunNo(0),
0f389141 67 fMergeViaJDL(0),
68 fFastReadOption(0),
e1c22e21 69 fOverwriteMode(1),
149d288c 70 fNreplicas(2),
3bdcb562 71 fNproofWorkers(0),
27734f0e 72 fNproofWorkersPerSlave(0),
3bdcb562 73 fProofReset(0),
c57f56b7 74 fRunNumbers(),
75 fExecutable(),
0a1c1f7f 76 fExecutableCommand(),
c57f56b7 77 fArguments(),
631c0b05 78 fExecutableArgs(),
c57f56b7 79 fAnalysisMacro(),
80 fAnalysisSource(),
d3b18c4c 81 fValidationScript(),
d5c6455a 82 fAdditionalRootLibs(),
c57f56b7 83 fAdditionalLibs(),
84 fSplitMode(),
85 fAPIVersion(),
86 fROOTVersion(),
87 fAliROOTVersion(),
648174cf 88 fExternalPackages(),
c57f56b7 89 fUser(),
90 fGridWorkingDir(),
91 fGridDataDir(),
92 fDataPattern(),
93 fGridOutputDir(),
94 fOutputArchive(),
95 fOutputFiles(),
96 fInputFormat(),
e7c71df0 97 fDatasetName(),
c57f56b7 98 fJDLName(),
d3b18c4c 99 fTerminateFiles(),
bb885a9e 100 fMergeExcludes(),
f965131e 101 fIncludePath(),
bb885a9e 102 fCloseSE(),
0df6ccf2 103 fFriendChainName(),
c6cb3634 104 fJobTag(),
648174cf 105 fOutputSingle(),
5fce53f4 106 fRunPrefix(),
3bdcb562 107 fProofCluster(),
108 fProofDataSet(),
109 fFileForTestMode(),
110 fRootVersionForProof(),
111 fAliRootMode(),
f47d5cb4 112 fMergeDirName(),
4e5c5506 113 fInputFiles(0),
28ce6c9c 114 fPackages(0),
115 fProofParam()
c57f56b7 116{
117// Dummy ctor.
118 SetDefaults();
119}
120
121//______________________________________________________________________________
122AliAnalysisAlien::AliAnalysisAlien(const char *name)
123 :AliAnalysisGrid(name),
124 fGridJDL(NULL),
0f389141 125 fMergingJDL(NULL),
c57f56b7 126 fPrice(0),
127 fTTL(0),
128 fSplitMaxInputFileNumber(0),
129 fMaxInitFailed(0),
130 fMasterResubmitThreshold(0),
bb885a9e 131 fNtestFiles(0),
319593fb 132 fNrunsPerMaster(0),
16a4353c 133 fMaxMergeFiles(0),
b3e07543 134 fMaxMergeStages(0),
d2a409b2 135 fNsubmitted(0),
a3e84053 136 fProductionMode(0),
cd11251e 137 fOutputToRunNo(0),
0f389141 138 fMergeViaJDL(0),
139 fFastReadOption(0),
e1c22e21 140 fOverwriteMode(1),
149d288c 141 fNreplicas(2),
3bdcb562 142 fNproofWorkers(0),
27734f0e 143 fNproofWorkersPerSlave(0),
3bdcb562 144 fProofReset(0),
c57f56b7 145 fRunNumbers(),
146 fExecutable(),
0a1c1f7f 147 fExecutableCommand(),
c57f56b7 148 fArguments(),
631c0b05 149 fExecutableArgs(),
c57f56b7 150 fAnalysisMacro(),
151 fAnalysisSource(),
d3b18c4c 152 fValidationScript(),
d5c6455a 153 fAdditionalRootLibs(),
c57f56b7 154 fAdditionalLibs(),
155 fSplitMode(),
156 fAPIVersion(),
157 fROOTVersion(),
158 fAliROOTVersion(),
648174cf 159 fExternalPackages(),
c57f56b7 160 fUser(),
161 fGridWorkingDir(),
162 fGridDataDir(),
163 fDataPattern(),
164 fGridOutputDir(),
165 fOutputArchive(),
166 fOutputFiles(),
167 fInputFormat(),
e7c71df0 168 fDatasetName(),
c57f56b7 169 fJDLName(),
d3b18c4c 170 fTerminateFiles(),
bb885a9e 171 fMergeExcludes(),
f965131e 172 fIncludePath(),
bb885a9e 173 fCloseSE(),
0df6ccf2 174 fFriendChainName(),
c6cb3634 175 fJobTag(),
648174cf 176 fOutputSingle(),
5fce53f4 177 fRunPrefix(),
3bdcb562 178 fProofCluster(),
179 fProofDataSet(),
180 fFileForTestMode(),
181 fRootVersionForProof(),
182 fAliRootMode(),
f47d5cb4 183 fMergeDirName(),
4e5c5506 184 fInputFiles(0),
28ce6c9c 185 fPackages(0),
186 fProofParam()
c57f56b7 187{
188// Default ctor.
189 SetDefaults();
190}
191
192//______________________________________________________________________________
193AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
194 :AliAnalysisGrid(other),
195 fGridJDL(NULL),
0f389141 196 fMergingJDL(NULL),
c57f56b7 197 fPrice(other.fPrice),
198 fTTL(other.fTTL),
199 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
200 fMaxInitFailed(other.fMaxInitFailed),
201 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
bb885a9e 202 fNtestFiles(other.fNtestFiles),
319593fb 203 fNrunsPerMaster(other.fNrunsPerMaster),
16a4353c 204 fMaxMergeFiles(other.fMaxMergeFiles),
b3e07543 205 fMaxMergeStages(other.fMaxMergeStages),
d2a409b2 206 fNsubmitted(other.fNsubmitted),
a3e84053 207 fProductionMode(other.fProductionMode),
cd11251e 208 fOutputToRunNo(other.fOutputToRunNo),
0f389141 209 fMergeViaJDL(other.fMergeViaJDL),
210 fFastReadOption(other.fFastReadOption),
211 fOverwriteMode(other.fOverwriteMode),
149d288c 212 fNreplicas(other.fNreplicas),
3bdcb562 213 fNproofWorkers(other.fNproofWorkers),
27734f0e 214 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
3bdcb562 215 fProofReset(other.fProofReset),
c57f56b7 216 fRunNumbers(other.fRunNumbers),
217 fExecutable(other.fExecutable),
0a1c1f7f 218 fExecutableCommand(other.fExecutableCommand),
c57f56b7 219 fArguments(other.fArguments),
631c0b05 220 fExecutableArgs(other.fExecutableArgs),
c57f56b7 221 fAnalysisMacro(other.fAnalysisMacro),
222 fAnalysisSource(other.fAnalysisSource),
d3b18c4c 223 fValidationScript(other.fValidationScript),
d5c6455a 224 fAdditionalRootLibs(other.fAdditionalRootLibs),
c57f56b7 225 fAdditionalLibs(other.fAdditionalLibs),
226 fSplitMode(other.fSplitMode),
227 fAPIVersion(other.fAPIVersion),
228 fROOTVersion(other.fROOTVersion),
229 fAliROOTVersion(other.fAliROOTVersion),
648174cf 230 fExternalPackages(other.fExternalPackages),
c57f56b7 231 fUser(other.fUser),
232 fGridWorkingDir(other.fGridWorkingDir),
233 fGridDataDir(other.fGridDataDir),
234 fDataPattern(other.fDataPattern),
235 fGridOutputDir(other.fGridOutputDir),
236 fOutputArchive(other.fOutputArchive),
237 fOutputFiles(other.fOutputFiles),
238 fInputFormat(other.fInputFormat),
e7c71df0 239 fDatasetName(other.fDatasetName),
c57f56b7 240 fJDLName(other.fJDLName),
d3b18c4c 241 fTerminateFiles(other.fTerminateFiles),
bb885a9e 242 fMergeExcludes(other.fMergeExcludes),
f965131e 243 fIncludePath(other.fIncludePath),
bb885a9e 244 fCloseSE(other.fCloseSE),
0df6ccf2 245 fFriendChainName(other.fFriendChainName),
c6cb3634 246 fJobTag(other.fJobTag),
648174cf 247 fOutputSingle(other.fOutputSingle),
5fce53f4 248 fRunPrefix(other.fRunPrefix),
3bdcb562 249 fProofCluster(other.fProofCluster),
250 fProofDataSet(other.fProofDataSet),
251 fFileForTestMode(other.fFileForTestMode),
252 fRootVersionForProof(other.fRootVersionForProof),
253 fAliRootMode(other.fAliRootMode),
f47d5cb4 254 fMergeDirName(other.fMergeDirName),
4e5c5506 255 fInputFiles(0),
28ce6c9c 256 fPackages(0),
257 fProofParam()
c57f56b7 258{
259// Copy ctor.
260 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 261 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
a8739e8a 262 fRunRange[0] = other.fRunRange[0];
263 fRunRange[1] = other.fRunRange[1];
c57f56b7 264 if (other.fInputFiles) {
265 fInputFiles = new TObjArray();
266 TIter next(other.fInputFiles);
267 TObject *obj;
268 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
269 fInputFiles->SetOwner();
270 }
4e5c5506 271 if (other.fPackages) {
272 fPackages = new TObjArray();
273 TIter next(other.fPackages);
274 TObject *obj;
275 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
276 fPackages->SetOwner();
277 }
c57f56b7 278}
279
280//______________________________________________________________________________
281AliAnalysisAlien::~AliAnalysisAlien()
282{
283// Destructor.
284 if (fGridJDL) delete fGridJDL;
0f389141 285 if (fMergingJDL) delete fMergingJDL;
c57f56b7 286 if (fInputFiles) delete fInputFiles;
4e5c5506 287 if (fPackages) delete fPackages;
28ce6c9c 288 fProofParam.DeleteAll();
c57f56b7 289}
290
291//______________________________________________________________________________
292AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
293{
294// Assignment.
295 if (this != &other) {
296 AliAnalysisGrid::operator=(other);
297 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 298 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
c57f56b7 299 fPrice = other.fPrice;
300 fTTL = other.fTTL;
301 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
302 fMaxInitFailed = other.fMaxInitFailed;
303 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
bb885a9e 304 fNtestFiles = other.fNtestFiles;
a3e84053 305 fNrunsPerMaster = other.fNrunsPerMaster;
306 fMaxMergeFiles = other.fMaxMergeFiles;
b3e07543 307 fMaxMergeStages = other.fMaxMergeStages;
a3e84053 308 fNsubmitted = other.fNsubmitted;
309 fProductionMode = other.fProductionMode;
cd11251e 310 fOutputToRunNo = other.fOutputToRunNo;
0f389141 311 fMergeViaJDL = other.fMergeViaJDL;
312 fFastReadOption = other.fFastReadOption;
313 fOverwriteMode = other.fOverwriteMode;
149d288c 314 fNreplicas = other.fNreplicas;
3bdcb562 315 fNproofWorkers = other.fNproofWorkers;
27734f0e 316 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
3bdcb562 317 fProofReset = other.fProofReset;
c57f56b7 318 fRunNumbers = other.fRunNumbers;
319 fExecutable = other.fExecutable;
0a1c1f7f 320 fExecutableCommand = other.fExecutableCommand;
c57f56b7 321 fArguments = other.fArguments;
631c0b05 322 fExecutableArgs = other.fExecutableArgs;
c57f56b7 323 fAnalysisMacro = other.fAnalysisMacro;
324 fAnalysisSource = other.fAnalysisSource;
d3b18c4c 325 fValidationScript = other.fValidationScript;
d5c6455a 326 fAdditionalRootLibs = other.fAdditionalRootLibs;
c57f56b7 327 fAdditionalLibs = other.fAdditionalLibs;
328 fSplitMode = other.fSplitMode;
329 fAPIVersion = other.fAPIVersion;
330 fROOTVersion = other.fROOTVersion;
331 fAliROOTVersion = other.fAliROOTVersion;
648174cf 332 fExternalPackages = other.fExternalPackages;
c57f56b7 333 fUser = other.fUser;
334 fGridWorkingDir = other.fGridWorkingDir;
335 fGridDataDir = other.fGridDataDir;
336 fDataPattern = other.fDataPattern;
337 fGridOutputDir = other.fGridOutputDir;
338 fOutputArchive = other.fOutputArchive;
339 fOutputFiles = other.fOutputFiles;
340 fInputFormat = other.fInputFormat;
e7c71df0 341 fDatasetName = other.fDatasetName;
c57f56b7 342 fJDLName = other.fJDLName;
d3b18c4c 343 fTerminateFiles = other.fTerminateFiles;
bb885a9e 344 fMergeExcludes = other.fMergeExcludes;
f965131e 345 fIncludePath = other.fIncludePath;
bb885a9e 346 fCloseSE = other.fCloseSE;
0df6ccf2 347 fFriendChainName = other.fFriendChainName;
c6cb3634 348 fJobTag = other.fJobTag;
648174cf 349 fOutputSingle = other.fOutputSingle;
5fce53f4 350 fRunPrefix = other.fRunPrefix;
3bdcb562 351 fProofCluster = other.fProofCluster;
352 fProofDataSet = other.fProofDataSet;
353 fFileForTestMode = other.fFileForTestMode;
354 fRootVersionForProof = other.fRootVersionForProof;
355 fAliRootMode = other.fAliRootMode;
f47d5cb4 356 fMergeDirName = other.fMergeDirName;
c57f56b7 357 if (other.fInputFiles) {
358 fInputFiles = new TObjArray();
359 TIter next(other.fInputFiles);
360 TObject *obj;
361 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
362 fInputFiles->SetOwner();
363 }
4e5c5506 364 if (other.fPackages) {
365 fPackages = new TObjArray();
366 TIter next(other.fPackages);
367 TObject *obj;
368 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
369 fPackages->SetOwner();
370 }
c57f56b7 371 }
372 return *this;
373}
374
74013535 375//______________________________________________________________________________
376void AliAnalysisAlien::SetRunPrefix(const char *prefix)
377{
378// Set the run number format. Can be a prefix or a format like "%09d"
379 fRunPrefix = prefix;
380 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
381}
382
f965131e 383//______________________________________________________________________________
384void AliAnalysisAlien::AddIncludePath(const char *path)
385{
386// Add include path in the remote analysis macro.
387 TString p(path);
388 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
389 else fIncludePath += Form("-I%s ", path);
390}
391
c57f56b7 392//______________________________________________________________________________
393void AliAnalysisAlien::AddRunNumber(Int_t run)
394{
395// Add a run number to the list of runs to be processed.
396 if (fRunNumbers.Length()) fRunNumbers += " ";
74013535 397 fRunNumbers += Form(fRunPrefix.Data(), run);
c57f56b7 398}
399
98690895 400//______________________________________________________________________________
401void AliAnalysisAlien::AddRunList(const char* runList)
402{
403// Add several runs into the list of runs; they are expected to be separated by a blank character.
404 TString sList = runList;
405 TObjArray *list = sList.Tokenize(" ");
406 Int_t n = list->GetEntries();
407 for (Int_t i = 0; i < n; i++) {
408 TObjString *os = (TObjString*)list->At(i);
409 AddRunNumber(os->GetString().Atoi());
410 }
411 delete list;
412}
413
ee75cfc3 414//______________________________________________________________________________
415void AliAnalysisAlien::AddRunNumber(const char* run)
416{
417// Add a run number to the list of runs to be processed.
7aa5d539 418 TString runs = run;
419 TObjString *os;
420 TObjArray *arr = runs.Tokenize(" ");
421 TIter next(arr);
422 TString prefix;
423 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
424 while ((os=(TObjString*)next())){
425 if (fRunNumbers.Length()) fRunNumbers += " ";
426 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
427 }
428 delete arr;
ee75cfc3 429}
430
c57f56b7 431//______________________________________________________________________________
432void AliAnalysisAlien::AddDataFile(const char *lfn)
433{
434// Adds a data file to the input to be analysed. The file should be a valid LFN
435// or point to an existing file in the alien workdir.
436 if (!fInputFiles) fInputFiles = new TObjArray();
437 fInputFiles->Add(new TObjString(lfn));
438}
648174cf 439
440//______________________________________________________________________________
441void AliAnalysisAlien::AddExternalPackage(const char *package)
442{
443// Adds external packages w.r.t to the default ones (root,aliroot and gapi)
444 if (fExternalPackages) fExternalPackages += " ";
445 fExternalPackages += package;
446}
447
c57f56b7 448//______________________________________________________________________________
449Bool_t AliAnalysisAlien::Connect()
450{
451// Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
452 if (gGrid && gGrid->IsConnected()) return kTRUE;
d3b18c4c 453 if (fProductionMode) return kTRUE;
c57f56b7 454 if (!gGrid) {
455 Info("Connect", "Trying to connect to AliEn ...");
456 TGrid::Connect("alien://");
457 }
458 if (!gGrid || !gGrid->IsConnected()) {
459 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
460 return kFALSE;
461 }
462 fUser = gGrid->GetUser();
463 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
464 return kTRUE;
465}
466
467//______________________________________________________________________________
468void AliAnalysisAlien::CdWork()
469{
470// Check validity of alien workspace. Create directory if possible.
471 if (!Connect()) {
472 Error("CdWork", "Alien connection required");
473 return;
474 }
475 TString homedir = gGrid->GetHomeDirectory();
476 TString workdir = homedir + fGridWorkingDir;
923e2ca5 477 if (DirectoryExists(workdir)) {
478 gGrid->Cd(workdir);
479 return;
480 }
481 // Work directory not existing - create it
482 gGrid->Cd(homedir);
b93f8109 483 if (gGrid->Mkdir(workdir, "-p")) {
923e2ca5 484 gGrid->Cd(fGridWorkingDir);
d3b18c4c 485 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
923e2ca5 486 } else {
d3b18c4c 487 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
923e2ca5 488 workdir.Data(), homedir.Data());
489 fGridWorkingDir = "";
490 }
c57f56b7 491}
492
348be253 493//______________________________________________________________________________
494Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
495{
496// Check if file copying is possible.
d3b18c4c 497 if (fProductionMode) return kTRUE;
348be253 498 if (!Connect()) {
499 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
500 return kFALSE;
501 }
d3339be3 502 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
503 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
348be253 504 // Check if alien_CLOSE_SE is defined
505 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
506 if (!closeSE.IsNull()) {
507 Info("CheckFileCopy", "Your current close storage is pointing to: \
508 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
509 } else {
510 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
511 }
512 // Check if grid directory exists.
513 if (!DirectoryExists(alienpath)) {
514 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
515 return kFALSE;
516 }
d3339be3 517 TFile f("plugin_test_copy", "RECREATE");
348be253 518 // User may not have write permissions to current directory
519 if (f.IsZombie()) {
520 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
521 gSystem->WorkingDirectory());
522 return kFALSE;
523 }
524 f.Close();
d3339be3 525 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
526 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
527 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
348be253 528 \n# 1. Make sure you have write permissions there. If this is the case: \
529 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
530 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
531 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
532 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
533 gSystem->Unlink(f.GetName());
534 return kFALSE;
535 }
536 gSystem->Unlink(f.GetName());
d3339be3 537 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
538 Info("CheckFileCopy", "### ...SUCCESS ###");
348be253 539 return kTRUE;
540}
541
c57f56b7 542//______________________________________________________________________________
543Bool_t AliAnalysisAlien::CheckInputData()
544{
545// Check validity of input data. If necessary, create xml files.
d3b18c4c 546 if (fProductionMode) return kTRUE;
a8739e8a 547 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
d2a409b2 548 if (!fGridDataDir.Length()) {
549 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
550 return kFALSE;
551 }
9f020952 552 if (fMergeViaJDL) {
553 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
554 return kFALSE;
555 }
d2a409b2 556 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
23329835 557 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
558 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
d2a409b2 559 return kTRUE;
c57f56b7 560 }
561 // Process declared files
a2f5fc01 562 Bool_t isCollection = kFALSE;
563 Bool_t isXml = kFALSE;
564 Bool_t useTags = kFALSE;
c57f56b7 565 Bool_t checked = kFALSE;
d3b18c4c 566 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
c57f56b7 567 TString file;
568 TString workdir = gGrid->GetHomeDirectory();
569 workdir += fGridWorkingDir;
570 if (fInputFiles) {
571 TObjString *objstr;
572 TIter next(fInputFiles);
573 while ((objstr=(TObjString*)next())) {
574 file = workdir;
575 file += "/";
576 file += objstr->GetString();
577 // Store full lfn path
578 if (FileExists(file)) objstr->SetString(file);
579 else {
580 file = objstr->GetName();
581 if (!FileExists(objstr->GetName())) {
582 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
583 objstr->GetName(), workdir.Data());
584 return kFALSE;
585 }
586 }
587 Bool_t iscoll, isxml, usetags;
588 CheckDataType(file, iscoll, isxml, usetags);
589 if (!checked) {
590 checked = kTRUE;
a2f5fc01 591 isCollection = iscoll;
592 isXml = isxml;
593 useTags = usetags;
594 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
c57f56b7 595 } else {
a2f5fc01 596 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
c57f56b7 597 Error("CheckInputData", "Some conflict was found in the types of inputs");
598 return kFALSE;
599 }
600 }
601 }
602 }
603 // Process requested run numbers
a8739e8a 604 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
c57f56b7 605 // Check validity of alien data directory
606 if (!fGridDataDir.Length()) {
607 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
608 return kFALSE;
609 }
923e2ca5 610 if (!DirectoryExists(fGridDataDir)) {
c57f56b7 611 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
612 return kFALSE;
613 }
a2f5fc01 614 if (isCollection) {
c57f56b7 615 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
616 return kFALSE;
617 }
618
a2f5fc01 619 if (checked && !isXml) {
c57f56b7 620 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
621 return kFALSE;
622 }
623 // Check validity of run number(s)
624 TObjArray *arr;
625 TObjString *os;
74013535 626 TString format;
319593fb 627 Int_t nruns = 0;
904f9f5f 628 TString schunk, schunk2;
c57f56b7 629 TString path;
630 if (!checked) {
631 checked = kTRUE;
a2f5fc01 632 useTags = fDataPattern.Contains("tag");
633 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
c57f56b7 634 }
a2f5fc01 635 if (useTags != fDataPattern.Contains("tag")) {
c57f56b7 636 Error("CheckInputData", "Cannot mix input files using/not using tags");
637 return kFALSE;
638 }
639 if (fRunNumbers.Length()) {
a8739e8a 640 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
c57f56b7 641 arr = fRunNumbers.Tokenize(" ");
642 TIter next(arr);
643 while ((os=(TObjString*)next())) {
644 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
923e2ca5 645 if (!DirectoryExists(path)) {
646 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
a8739e8a 647 continue;
c57f56b7 648 }
649 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
650 TString msg = "\n##### file: ";
651 msg += path;
652 msg += " type: xml_collection;";
a2f5fc01 653 if (useTags) msg += " using_tags: Yes";
c57f56b7 654 else msg += " using_tags: No";
23329835 655 Info("CheckDataType", "%s", msg.Data());
319593fb 656 if (fNrunsPerMaster<2) {
d2a409b2 657 AddDataFile(Form("%s.xml", os->GetString().Data()));
319593fb 658 } else {
659 nruns++;
660 if (((nruns-1)%fNrunsPerMaster) == 0) {
661 schunk = os->GetString();
662 }
663 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
664 schunk += Form("_%s.xml", os->GetString().Data());
d2a409b2 665 AddDataFile(schunk);
319593fb 666 }
c57f56b7 667 }
668 delete arr;
a8739e8a 669 } else {
670 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
671 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
74013535 672 format = Form("%%s/%s ", fRunPrefix.Data());
673 path = Form(format.Data(), fGridDataDir.Data(), irun);
923e2ca5 674 if (!DirectoryExists(path)) {
a8739e8a 675 continue;
676 }
74013535 677 format = Form("%%s/%s.xml", fRunPrefix.Data());
678 path = Form(format.Data(), workdir.Data(),irun);
a8739e8a 679 TString msg = "\n##### file: ";
680 msg += path;
681 msg += " type: xml_collection;";
a2f5fc01 682 if (useTags) msg += " using_tags: Yes";
a8739e8a 683 else msg += " using_tags: No";
23329835 684 Info("CheckDataType", "%s", msg.Data());
319593fb 685 if (fNrunsPerMaster<2) {
74013535 686 format = Form("%s.xml", fRunPrefix.Data());
687 AddDataFile(Form(format.Data(),irun));
319593fb 688 } else {
689 nruns++;
690 if (((nruns-1)%fNrunsPerMaster) == 0) {
74013535 691 schunk = Form(fRunPrefix.Data(),irun);
319593fb 692 }
74013535 693 format = Form("_%s.xml", fRunPrefix.Data());
694 schunk2 = Form(format.Data(), irun);
319593fb 695 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
904f9f5f 696 schunk += schunk2;
d2a409b2 697 AddDataFile(schunk);
319593fb 698 }
a8739e8a 699 }
904f9f5f 700 if (!fInputFiles) {
701 schunk += schunk2;
702 AddDataFile(schunk);
703 }
c57f56b7 704 }
705 return kTRUE;
706}
707
708//______________________________________________________________________________
709Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
710{
711// Create dataset for the grid data directory + run number.
3af861ff 712 const Int_t gMaxEntries = 15000;
d3b18c4c 713 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
c57f56b7 714 if (!Connect()) {
715 Error("CreateDataset", "Cannot create dataset with no grid connection");
716 return kFALSE;
717 }
718
719 // Cd workspace
d3b18c4c 720 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
c57f56b7 721 TString workdir = gGrid->GetHomeDirectory();
722 workdir += fGridWorkingDir;
723
724 // Compose the 'find' command arguments
74013535 725 TString format;
c57f56b7 726 TString command;
727 TString options = "-x collection ";
bb885a9e 728 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
3af861ff 729 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
c57f56b7 730 TString conditions = "";
3af861ff 731 Int_t nstart = 0;
732 Int_t ncount = 0;
733 Int_t stage = 0;
c57f56b7 734 TString file;
735 TString path;
319593fb 736 Int_t nruns = 0;
904f9f5f 737 TString schunk, schunk2;
ab254fd1 738 TGridCollection *cbase=0, *cadd=0;
d2a409b2 739 if (!fRunNumbers.Length() && !fRunRange[0]) {
740 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
741 // Make a single data collection from data directory.
742 path = fGridDataDir;
923e2ca5 743 if (!DirectoryExists(path)) {
d2a409b2 744 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
745 return kFALSE;
746 }
923e2ca5 747// CdWork();
d2a409b2 748 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
749 else file = Form("%s.xml", gSystem->BaseName(path));
3af861ff 750 while (1) {
751 ncount = 0;
752 stage++;
753 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
754 command = "find ";
755 command += Form("%s -o %d ",options.Data(), nstart);
756 command += path;
757 command += " ";
758 command += pattern;
759 command += conditions;
760 printf("command: %s\n", command.Data());
761 TGridResult *res = gGrid->Command(command);
762 if (res) delete res;
763 // Write standard output to file
764 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
765 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
766 Bool_t nullFile = kFALSE;
767 if (!hasGrep) {
768 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
769 } else {
770 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
771 if (nullFile) {
772 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
773 gSystem->Exec("rm -f __tmp*");
774 return kFALSE;
775 }
776 TString line;
777 ifstream in;
778 in.open("__tmp__");
779 in >> line;
780 in.close();
781 gSystem->Exec("rm -f __tmp__");
782 ncount = line.Atoi();
783 }
784 }
785 if (ncount == gMaxEntries) {
786 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
787 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
788 if (!cbase) cbase = cadd;
789 else {
790 cbase->Add(cadd);
791 delete cadd;
defd7a3a 792 }
3af861ff 793 nstart += ncount;
794 } else {
795 if (cbase) {
796 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
797 printf("... please wait - TAlienCollection::Add() scales badly...\n");
798 cbase->Add(cadd);
799 delete cadd;
800 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
801 delete cbase; cbase = 0;
802 } else {
803 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
804 }
805 gSystem->Exec("rm -f __tmp*");
806 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
807 break;
808 }
0f389141 809 }
810 Bool_t fileExists = FileExists(file);
811 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
d2a409b2 812 // Copy xml file to alien space
0f389141 813 if (fileExists) gGrid->Rm(file);
d2a409b2 814 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
815 if (!FileExists(file)) {
816 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
817 return kFALSE;
818 }
819 // Update list of files to be processed.
820 }
821 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
822 return kTRUE;
823 }
c57f56b7 824 // Several runs
a2f5fc01 825 Bool_t nullResult = kTRUE;
a8739e8a 826 if (fRunNumbers.Length()) {
827 TObjArray *arr = fRunNumbers.Tokenize(" ");
828 TObjString *os;
829 TIter next(arr);
830 while ((os=(TObjString*)next())) {
3af861ff 831 nstart = 0;
832 stage = 0;
dc030a24 833 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
923e2ca5 834 if (!DirectoryExists(path)) continue;
835// CdWork();
a8739e8a 836 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
837 else file = Form("%s.xml", os->GetString().Data());
319593fb 838 // If local collection file does not exist, create it via 'find' command.
3af861ff 839 while (1) {
840 ncount = 0;
841 stage++;
842 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
843 command = "find ";
844 command += Form("%s -o %d ",options.Data(), nstart);
845 command += path;
846 command += pattern;
847 command += conditions;
848 TGridResult *res = gGrid->Command(command);
849 if (res) delete res;
850 // Write standard output to file
851 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
852 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
853 Bool_t nullFile = kFALSE;
854 if (!hasGrep) {
855 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
856 } else {
857 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
858 if (nullFile) {
859 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
860 gSystem->Exec("rm -f __tmp*");
861 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
862 continue;
863 }
864 TString line;
865 ifstream in;
866 in.open("__tmp__");
867 in >> line;
868 in.close();
869 gSystem->Exec("rm -f __tmp__");
870 ncount = line.Atoi();
871 }
872 nullResult = kFALSE;
873 }
874 if (ncount == gMaxEntries) {
875 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
876 if (fNrunsPerMaster > 1) {
877 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
878 file.Data(),gMaxEntries);
879 return kFALSE;
880 }
881 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
882 if (!cbase) cbase = cadd;
883 else {
884 cbase->Add(cadd);
885 delete cadd;
defd7a3a 886 }
3af861ff 887 nstart += ncount;
888 } else {
c89a84bc 889 if (cbase && fNrunsPerMaster<2) {
3af861ff 890 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
891 printf("... please wait - TAlienCollection::Add() scales badly...\n");
892 cbase->Add(cadd);
893 delete cadd;
894 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
895 delete cbase; cbase = 0;
896 } else {
897 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
898 }
899 gSystem->Exec("rm -f __tmp*");
900 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
901 break;
d3339be3 902 }
3af861ff 903 }
a8739e8a 904 if (TestBit(AliAnalysisGrid::kTest)) break;
319593fb 905 // Check if there is one run per master job.
906 if (fNrunsPerMaster<2) {
907 if (FileExists(file)) {
0f389141 908 if (fOverwriteMode) gGrid->Rm(file);
909 else {
910 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
911 continue;
912 }
319593fb 913 }
914 // Copy xml file to alien space
915 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
916 if (!FileExists(file)) {
917 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
918 delete arr;
919 return kFALSE;
920 }
921 } else {
922 nruns++;
923 if (((nruns-1)%fNrunsPerMaster) == 0) {
924 schunk = os->GetString();
925 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
926 } else {
927 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
84fcd93f 928 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
319593fb 929 cbase->Add(cadd);
930 delete cadd;
931 }
932 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
933 continue;
934 }
935 schunk += Form("_%s.xml", os->GetString().Data());
0f389141 936 if (FileExists(schunk)) {
937 if (fOverwriteMode) gGrid->Rm(file);
938 else {
939 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
940 continue;
941 }
319593fb 942 }
84fcd93f 943 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
319593fb 944 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
e95434bc 945 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
319593fb 946 if (!FileExists(schunk)) {
947 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
948 delete arr;
949 return kFALSE;
950 }
d3339be3 951 }
a8739e8a 952 }
953 delete arr;
a2f5fc01 954 if (nullResult) {
d3339be3 955 Error("CreateDataset", "No valid dataset corresponding to the query!");
956 return kFALSE;
957 }
a8739e8a 958 } else {
959 // Process a full run range.
960 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
74013535 961 format = Form("%%s/%s ", fRunPrefix.Data());
3af861ff 962 nstart = 0;
963 stage = 0;
74013535 964 path = Form(format.Data(), fGridDataDir.Data(), irun);
923e2ca5 965 if (!DirectoryExists(path)) continue;
966// CdWork();
74013535 967 format = Form("%s.xml", fRunPrefix.Data());
a8739e8a 968 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
74013535 969 else file = Form(format.Data(), irun);
0f389141 970 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
971 if (fOverwriteMode) gGrid->Rm(file);
972 else {
973 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
974 continue;
975 }
a8739e8a 976 }
319593fb 977 // If local collection file does not exist, create it via 'find' command.
3af861ff 978 while (1) {
979 ncount = 0;
980 stage++;
981 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
982 command = "find ";
983 command += Form("%s -o %d ",options.Data(), nstart);
984 command += path;
985 command += pattern;
986 command += conditions;
987 TGridResult *res = gGrid->Command(command);
988 if (res) delete res;
989 // Write standard output to file
990 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
991 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
992 Bool_t nullFile = kFALSE;
993 if (!hasGrep) {
994 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
995 } else {
996 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
997 if (nullFile) {
998 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
999 gSystem->Exec("rm -f __tmp*");
1000 continue;
1001 }
1002 TString line;
1003 ifstream in;
1004 in.open("__tmp__");
1005 in >> line;
1006 in.close();
1007 gSystem->Exec("rm -f __tmp__");
1008 ncount = line.Atoi();
1009 }
1010 nullResult = kFALSE;
1011 }
1012 if (ncount == gMaxEntries) {
1013 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1014 if (fNrunsPerMaster > 1) {
1015 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1016 file.Data(),gMaxEntries);
1017 return kFALSE;
1018 }
1019 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1020 if (!cbase) cbase = cadd;
1021 else {
1022 cbase->Add(cadd);
1023 delete cadd;
defd7a3a 1024 }
3af861ff 1025 nstart += ncount;
1026 } else {
c89a84bc 1027 if (cbase && fNrunsPerMaster<2) {
3af861ff 1028 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1029 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1030 cbase->Add(cadd);
1031 delete cadd;
1032 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1033 delete cbase; cbase = 0;
1034 } else {
1035 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1036 }
1037 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1038 break;
d3339be3 1039 }
319593fb 1040 }
a8739e8a 1041 if (TestBit(AliAnalysisGrid::kTest)) break;
319593fb 1042 // Check if there is one run per master job.
1043 if (fNrunsPerMaster<2) {
1044 if (FileExists(file)) {
0f389141 1045 if (fOverwriteMode) gGrid->Rm(file);
1046 else {
1047 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1048 continue;
1049 }
319593fb 1050 }
1051 // Copy xml file to alien space
1052 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1053 if (!FileExists(file)) {
1054 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1055 return kFALSE;
1056 }
1057 } else {
1058 nruns++;
95e5b448 1059 // Check if the collection for the chunk exist locally.
1060 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
0f389141 1061 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1062 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1063 else continue;
1064 }
84fcd93f 1065 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
319593fb 1066 if (((nruns-1)%fNrunsPerMaster) == 0) {
74013535 1067 schunk = Form(fRunPrefix.Data(), irun);
319593fb 1068 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1069 } else {
1070 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1071 cbase->Add(cadd);
1072 delete cadd;
1073 }
74013535 1074 format = Form("%%s_%s.xml", fRunPrefix.Data());
1075 schunk2 = Form(format.Data(), schunk.Data(), irun);
904f9f5f 1076 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
319593fb 1077 continue;
1078 }
904f9f5f 1079 schunk = schunk2;
319593fb 1080 if (FileExists(schunk)) {
0f389141 1081 if (fOverwriteMode) gGrid->Rm(schunk);
1082 else {
1083 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1084 continue;
1085 }
319593fb 1086 }
84fcd93f 1087 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
319593fb 1088 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
95e5b448 1089 if (FileExists(schunk)) {
0f389141 1090 if (fOverwriteMode) gGrid->Rm(schunk);
1091 else {
1092 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1093 continue;
1094 }
95e5b448 1095 }
319593fb 1096 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1097 if (!FileExists(schunk)) {
1098 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1099 return kFALSE;
1100 }
1101 }
c57f56b7 1102 }
a2f5fc01 1103 if (nullResult) {
d3339be3 1104 Error("CreateDataset", "No valid dataset corresponding to the query!");
1105 return kFALSE;
1106 }
a8739e8a 1107 }
c57f56b7 1108 return kTRUE;
1109}
1110
1111//______________________________________________________________________________
1112Bool_t AliAnalysisAlien::CreateJDL()
1113{
1114// Generate a JDL file according to current settings. The name of the file is
1115// specified by fJDLName.
1116 Bool_t error = kFALSE;
1117 TObjArray *arr = 0;
1118 Bool_t copy = kTRUE;
d3b18c4c 1119 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 1120 Bool_t generate = kTRUE;
1121 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1122 if (!Connect()) {
1123 Error("CreateJDL", "Alien connection required");
1124 return kFALSE;
1125 }
1126 // Check validity of alien workspace
d3b18c4c 1127 TString workdir;
1128 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1129 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
c57f56b7 1130 workdir += fGridWorkingDir;
1131 if (generate) {
1132 TObjString *os;
1133 if (!fInputFiles) {
1134 Error("CreateJDL()", "Define some input files for your analysis.");
1135 error = kTRUE;
1136 }
1137 // Compose list of input files
1138 // Check if output files were defined
1139 if (!fOutputFiles.Length()) {
1140 Error("CreateJDL", "You must define at least one output file");
1141 error = kTRUE;
1142 }
1143 // Check if an output directory was defined and valid
1144 if (!fGridOutputDir.Length()) {
1145 Error("CreateJDL", "You must define AliEn output directory");
1146 error = kTRUE;
1147 } else {
d3b18c4c 1148 if (!fProductionMode) {
1149 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1150 if (!DirectoryExists(fGridOutputDir)) {
1151 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1152 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1153 } else {
1154 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1155 // error = kTRUE;
1156 }
67a3b254 1157 } else {
1158 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
d3b18c4c 1159 }
1160 gGrid->Cd(workdir);
1161 }
c57f56b7 1162 }
1163 // Exit if any error up to now
1164 if (error) return kFALSE;
1165 // Set JDL fields
0f389141 1166 if (!fUser.IsNull()) {
1167 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1168 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1169 }
1170 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1171 TString mergeExec = fExecutable;
1172 mergeExec.ReplaceAll(".sh", "_merge.sh");
1173 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1174 mergeExec.ReplaceAll(".sh", ".C");
1175 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
b5b9dee8 1176 if (!fArguments.IsNull())
1177 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
d3b18c4c 1178 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
f47d5cb4 1179 else {
1180 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1181 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1182 }
b3e07543 1183
1f0d1ca2 1184 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1185 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1186 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1187 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1188
0f389141 1189 if (fMaxInitFailed > 0) {
c57f56b7 1190 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
0f389141 1191 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1192 }
1193 if (fSplitMaxInputFileNumber > 0) {
c57f56b7 1194 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
0f389141 1195 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
b3e07543 1196 }
1197 if (!IsOneStageMerging()) {
f47d5cb4 1198 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
b3e07543 1199 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
0f389141 1200 }
1201 if (fSplitMode.Length()) {
c57f56b7 1202 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
0f389141 1203 fGridJDL->SetDescription("Split", "We split per SE or file");
b3e07543 1204 }
1205 fMergingJDL->SetValue("Split", "\"se\"");
1206 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
0f389141 1207 if (!fAliROOTVersion.IsNull()) {
1208 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1209 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1210 }
1211 if (!fROOTVersion.IsNull()) {
c57f56b7 1212 fGridJDL->AddToPackages("ROOT", fROOTVersion);
0f389141 1213 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1214 }
1215 if (!fAPIVersion.IsNull()) {
c57f56b7 1216 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
0f389141 1217 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1218 }
648174cf 1219 if (!fExternalPackages.IsNull()) {
1220 arr = fExternalPackages.Tokenize(" ");
1221 TIter next(arr);
1222 while ((os=(TObjString*)next())) {
1223 TString pkgname = os->GetString();
1224 Int_t index = pkgname.Index("::");
1225 TString pkgversion = pkgname(index+2, pkgname.Length());
1226 pkgname.Remove(index);
1227 fGridJDL->AddToPackages(pkgname, pkgversion);
0f389141 1228 fMergingJDL->AddToPackages(pkgname, pkgversion);
648174cf 1229 }
1230 delete arr;
1231 }
0f389141 1232 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1233 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
b3e07543 1234 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1235 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
0f389141 1236 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
f10e8481 1237 TString analysisFile = fExecutable;
1238 analysisFile.ReplaceAll(".sh", ".root");
1239 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
f866cba5 1240 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 1241 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1242 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1243 if (fAdditionalLibs.Length()) {
1244 arr = fAdditionalLibs.Tokenize(" ");
1245 TIter next(arr);
1246 while ((os=(TObjString*)next())) {
1247 if (os->GetString().Contains(".so")) continue;
1248 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
0f389141 1249 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
c57f56b7 1250 }
1251 delete arr;
1252 }
4e5c5506 1253 if (fPackages) {
1254 TIter next(fPackages);
1255 TObject *obj;
0f389141 1256 while ((obj=next())) {
4e5c5506 1257 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
0f389141 1258 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1259 }
4e5c5506 1260 }
c57f56b7 1261 if (fOutputArchive.Length()) {
1262 arr = fOutputArchive.Tokenize(" ");
1263 TIter next(arr);
0f389141 1264 Bool_t first = kTRUE;
1265 const char *comment = "Files to be archived";
1266 const char *comment1 = comment;
1267 while ((os=(TObjString*)next())) {
1268 if (!first) comment = NULL;
1269 if (!os->GetString().Contains("@") && fCloseSE.Length())
1270 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1271 else
1272 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1273 first = kFALSE;
1274 }
c57f56b7 1275 delete arr;
f790bc1b 1276 // Output archive for the merging jdl
1277 TString outputArchive;
1278 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
b83f84f0 1279 outputArchive = "log_archive.zip:std*@disk=1 ";
f790bc1b 1280 // Add normal output files, extra files + terminate files
1281 TString files = GetListOfFiles("outextter");
1282 // Do not register merge excludes
1283 if (!fMergeExcludes.IsNull()) {
1284 arr = fMergeExcludes.Tokenize(" ");
1285 TIter next1(arr);
1286 while ((os=(TObjString*)next1())) {
1287 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1288 files.ReplaceAll(os->GetString(),"");
1289 }
66d71516 1290 delete arr;
0f389141 1291 }
f790bc1b 1292 files.ReplaceAll(".root", "*.root");
b83f84f0 1293 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
f790bc1b 1294 } else {
95f84779 1295 TString files = fOutputArchive;
1296 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1297 outputArchive = files;
f790bc1b 1298 }
0f389141 1299 arr = outputArchive.Tokenize(" ");
705adb3e 1300 TIter next2(arr);
0f389141 1301 comment = comment1;
1302 first = kTRUE;
705adb3e 1303 while ((os=(TObjString*)next2())) {
0f389141 1304 if (!first) comment = NULL;
0cdf65a8 1305 TString currentfile = os->GetString();
0cdf65a8 1306 if (!currentfile.Contains("@") && fCloseSE.Length())
d3b18c4c 1307 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
0f389141 1308 else
0cdf65a8 1309 fMergingJDL->AddToOutputArchive(currentfile, comment);
0f389141 1310 first = kFALSE;
1311 }
1312 delete arr;
c57f56b7 1313 }
149d288c 1314 arr = fOutputFiles.Tokenize(",");
c57f56b7 1315 TIter next(arr);
0f389141 1316 Bool_t first = kTRUE;
f790bc1b 1317 const char *comment = "Files to be saved";
43da816a 1318 while ((os=(TObjString*)next())) {
e1eaf596 1319 // Ignore ouputs in jdl that are also in outputarchive
1320 TString sout = os->GetString();
f790bc1b 1321 sout.ReplaceAll("*", "");
1322 sout.ReplaceAll(".root", "");
e1eaf596 1323 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1324 if (fOutputArchive.Contains(sout)) continue;
0f389141 1325 if (!first) comment = NULL;
43da816a 1326 if (!os->GetString().Contains("@") && fCloseSE.Length())
0f389141 1327 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
43da816a 1328 else
0f389141 1329 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
b3e07543 1330 first = kFALSE;
f790bc1b 1331 if (fMergeExcludes.Contains(sout)) continue;
1332 if (!os->GetString().Contains("@") && fCloseSE.Length())
1333 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1334 else
1335 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
43da816a 1336 }
c57f56b7 1337 delete arr;
0f389141 1338 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1339 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
d3b18c4c 1340 TString validationScript = fValidationScript;
0f389141 1341 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
d3b18c4c 1342 validationScript.ReplaceAll(".sh", "_merge.sh");
0f389141 1343 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1344 if (fMasterResubmitThreshold) {
1345 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1346 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1347 }
d2a409b2 1348 // Write a jdl with 2 input parameters: collection name and output dir name.
1349 WriteJDL(copy);
c57f56b7 1350 }
1351 // Copy jdl to grid workspace
a8739e8a 1352 if (copy) {
b5e4aaa7 1353 // Check if an output directory was defined and valid
1354 if (!fGridOutputDir.Length()) {
1355 Error("CreateJDL", "You must define AliEn output directory");
1356 return kFALSE;
1357 } else {
1358 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
bb2e67a0 1359 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
b93f8109 1360 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
b5e4aaa7 1361 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1362 } else {
1363 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1364 return kFALSE;
1365 }
1366 }
1367 gGrid->Cd(workdir);
1368 }
648174cf 1369 if (TestBit(AliAnalysisGrid::kSubmit)) {
0f389141 1370 TString mergeJDLName = fExecutable;
1371 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
648174cf 1372 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1373 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1374 if (fProductionMode) {
648174cf 1375 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1376 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1377 }
648174cf 1378 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1379 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1380 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
648174cf 1381 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1382 if (fMergeViaJDL) {
1383 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1384 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1385 }
648174cf 1386 }
c57f56b7 1387 if (fAdditionalLibs.Length()) {
e7c71df0 1388 arr = fAdditionalLibs.Tokenize(" ");
c57f56b7 1389 TObjString *os;
1390 TIter next(arr);
1391 while ((os=(TObjString*)next())) {
c57f56b7 1392 if (os->GetString().Contains(".so")) continue;
4e5c5506 1393 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
c57f56b7 1394 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1395 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1396 }
1397 delete arr;
1398 }
4e5c5506 1399 if (fPackages) {
1400 TIter next(fPackages);
1401 TObject *obj;
1402 while ((obj=next())) {
fdbbc7be 1403 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
4e5c5506 1404 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1405 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1406 }
1407 }
c57f56b7 1408 }
1409 return kTRUE;
1410}
1411
a8739e8a 1412//______________________________________________________________________________
d2a409b2 1413Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
a8739e8a 1414{
1415// Writes one or more JDL's corresponding to findex. If findex is negative,
1416// all run numbers are considered in one go (jdl). For non-negative indices
1417// they correspond to the indices in the array fInputFiles.
1418 if (!fInputFiles) return kFALSE;
d3b18c4c 1419 TObject *os;
1420 TString workdir;
1421 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
a8739e8a 1422 workdir += fGridWorkingDir;
f47d5cb4 1423 TString stageName = "$2";
1424 if (fProductionMode) stageName = "$4";
1425 if (!fMergeDirName.IsNull()) {
1426 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1427 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1428 } else {
1429 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1430 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1431 }
d3b18c4c 1432 if (fProductionMode) {
a8739e8a 1433 TIter next(fInputFiles);
b3e07543 1434 while ((os=next())) {
d3b18c4c 1435 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
b3e07543 1436 }
d3b18c4c 1437 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
d3b18c4c 1438 } else {
1439 if (!fRunNumbers.Length() && !fRunRange[0]) {
1440 // One jdl with no parameters in case input data is specified by name.
1441 TIter next(fInputFiles);
1442 while ((os=next()))
1443 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1444 if (!fOutputSingle.IsNull())
1445 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1446 else {
1447 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1448 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1449 }
1450 } else {
1451 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1452 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1453 if (!fOutputSingle.IsNull()) {
1454 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1455 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1456 } else {
1457 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
d3b18c4c 1458 }
1459 }
a8739e8a 1460 }
1461
a8739e8a 1462 // Generate the JDL as a string
1463 TString sjdl = fGridJDL->Generate();
0f389141 1464 TString sjdl1 = fMergingJDL->Generate();
f47d5cb4 1465 // Final merge jdl
1466 if (!fMergeDirName.IsNull()) {
1467 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1468 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1469 } else {
1470 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1471 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1472 }
b3e07543 1473 TString sjdl2 = fMergingJDL->Generate();
1474 Int_t index, index1;
a8739e8a 1475 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1476 sjdl.ReplaceAll("(member", "\n (member");
1477 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1478 sjdl.ReplaceAll("{", "{\n ");
1479 sjdl.ReplaceAll("};", "\n};");
1480 sjdl.ReplaceAll("{\n \n", "{\n");
1481 sjdl.ReplaceAll("\n\n", "\n");
1482 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
0f389141 1483 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1484 sjdl1.ReplaceAll("(member", "\n (member");
1485 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1486 sjdl1.ReplaceAll("{", "{\n ");
1487 sjdl1.ReplaceAll("};", "\n};");
1488 sjdl1.ReplaceAll("{\n \n", "{\n");
1489 sjdl1.ReplaceAll("\n\n", "\n");
1490 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
b3e07543 1491 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1492 sjdl2.ReplaceAll("(member", "\n (member");
1493 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1494 sjdl2.ReplaceAll("{", "{\n ");
1495 sjdl2.ReplaceAll("};", "\n};");
1496 sjdl2.ReplaceAll("{\n \n", "{\n");
1497 sjdl2.ReplaceAll("\n\n", "\n");
1498 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
a8739e8a 1499 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
f60ef0ba 1500 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
a8739e8a 1501 index = sjdl.Index("JDLVariables");
1502 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
4739b2aa 1503 sjdl += "Workdirectorysize = {\"5000MB\"};";
b3e07543 1504 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
0f389141 1505 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
d3b18c4c 1506 index = fJobTag.Index(":");
1507 if (index < 0) index = fJobTag.Length();
1508 TString jobTag = fJobTag;
f47d5cb4 1509 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
d3b18c4c 1510 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
f47d5cb4 1511 if (fProductionMode) {
1512 sjdl1.Prepend("# Generated merging jdl (production mode) \
1513 \n# $1 = full alien path to output directory to be merged \
1514 \n# $2 = train number \
1515 \n# $3 = production (like LHC10b) \
1516 \n# $4 = merging stage \
1517 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1518 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1519 sjdl2.Prepend("# Generated merging jdl \
1520 \n# $1 = full alien path to output directory to be merged \
1521 \n# $2 = train number \
1522 \n# $3 = production (like LHC10b) \
1523 \n# $4 = merging stage \
1524 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1525 } else {
1526 sjdl1.Prepend("# Generated merging jdl \
1527 \n# $1 = full alien path to output directory to be merged \
1528 \n# $2 = merging stage \
03335324 1529 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
f47d5cb4 1530 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1531 sjdl2.Prepend("# Generated merging jdl \
1532 \n# $1 = full alien path to output directory to be merged \
1533 \n# $2 = merging stage \
03335324 1534 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
f47d5cb4 1535 }
0f389141 1536 index = sjdl1.Index("JDLVariables");
1537 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
b3e07543 1538 index = sjdl2.Index("JDLVariables");
1539 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
4739b2aa 1540 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
b3e07543 1541 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1542 index = sjdl2.Index("Split =");
1543 if (index>=0) {
1544 index1 = sjdl2.Index("\n", index);
1545 sjdl2.Remove(index, index1-index+1);
1546 }
1547 index = sjdl2.Index("SplitMaxInputFileNumber");
1548 if (index>=0) {
1549 index1 = sjdl2.Index("\n", index);
1550 sjdl2.Remove(index, index1-index+1);
1551 }
1552 index = sjdl2.Index("InputDataCollection");
1553 if (index>=0) {
1554 index1 = sjdl2.Index(";", index);
1555 sjdl2.Remove(index, index1-index+1);
1556 }
1557 index = sjdl2.Index("InputDataListFormat");
1558 if (index>=0) {
1559 index1 = sjdl2.Index("\n", index);
1560 sjdl2.Remove(index, index1-index+1);
1561 }
1562 index = sjdl2.Index("InputDataList");
1563 if (index>=0) {
1564 index1 = sjdl2.Index("\n", index);
1565 sjdl2.Remove(index, index1-index+1);
1566 }
f47d5cb4 1567 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
a8739e8a 1568 // Write jdl to file
a8739e8a 1569 ofstream out;
d2a409b2 1570 out.open(fJDLName.Data(), ios::out);
a8739e8a 1571 if (out.bad()) {
d3b18c4c 1572 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
a8739e8a 1573 return kFALSE;
1574 }
1575 out << sjdl << endl;
b3e07543 1576 out.close();
0f389141 1577 TString mergeJDLName = fExecutable;
1578 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1579 if (fMergeViaJDL) {
1580 ofstream out1;
1581 out1.open(mergeJDLName.Data(), ios::out);
b3e07543 1582 if (out1.bad()) {
d3b18c4c 1583 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
0f389141 1584 return kFALSE;
1585 }
1586 out1 << sjdl1 << endl;
b3e07543 1587 out1.close();
1588 ofstream out2;
1589 TString finalJDL = mergeJDLName;
1590 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1591 out2.open(finalJDL.Data(), ios::out);
1592 if (out2.bad()) {
1593 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1594 return kFALSE;
1595 }
1596 out2 << sjdl2 << endl;
1597 out2.close();
0f389141 1598 }
a8739e8a 1599
1600 // Copy jdl to grid workspace
1601 if (!copy) {
d3b18c4c 1602 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
a8739e8a 1603 } else {
d2a409b2 1604 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1605 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
b3e07543 1606 TString finalJDL = mergeJDLName;
1607 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1608 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
0f389141 1609 if (fProductionMode) {
b5fe9cba 1610 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1611 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
b3e07543 1612 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
0f389141 1613 }
d2a409b2 1614 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1615 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
b3e07543 1616 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
d3b18c4c 1617 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
5513444a 1618 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1619 if (fMergeViaJDL) {
b3e07543 1620 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
0f389141 1621 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
b3e07543 1622 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
0f389141 1623 }
a8739e8a 1624 }
1625 return kTRUE;
1626}
1627
c57f56b7 1628//______________________________________________________________________________
5513444a 1629Bool_t AliAnalysisAlien::FileExists(const char *lfn)
c57f56b7 1630{
1631// Returns true if file exists.
5513444a 1632 if (!gGrid) return kFALSE;
2ea55496 1633 TString slfn = lfn;
1634 slfn.ReplaceAll("alien://","");
1635 TGridResult *res = gGrid->Ls(slfn);
c57f56b7 1636 if (!res) return kFALSE;
1637 TMap *map = dynamic_cast<TMap*>(res->At(0));
1638 if (!map) {
1639 delete res;
1640 return kFALSE;
1641 }
1642 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1643 if (!objs || !objs->GetString().Length()) {
1644 delete res;
1645 return kFALSE;
1646 }
1647 delete res;
1648 return kTRUE;
1649}
1650
923e2ca5 1651//______________________________________________________________________________
1652Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1653{
1654// Returns true if directory exists. Can be also a path.
1655 if (!gGrid) return kFALSE;
1656 // Check if dirname is a path
1657 TString dirstripped = dirname;
1658 dirstripped = dirstripped.Strip();
1659 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1660 TString dir = gSystem->BaseName(dirstripped);
1661 dir += "/";
1662 TString path = gSystem->DirName(dirstripped);
1663 TGridResult *res = gGrid->Ls(path, "-F");
1664 if (!res) return kFALSE;
1665 TIter next(res);
1666 TMap *map;
1667 TObject *obj;
1668 while ((map=dynamic_cast<TMap*>(next()))) {
1669 obj = map->GetValue("name");
1670 if (!obj) break;
1671 if (dir == obj->GetName()) {
1672 delete res;
1673 return kTRUE;
1674 }
1675 }
1676 delete res;
1677 return kFALSE;
1678}
1679
c57f56b7 1680//______________________________________________________________________________
a2f5fc01 1681void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
c57f56b7 1682{
1683// Check input data type.
a2f5fc01 1684 isCollection = kFALSE;
1685 isXml = kFALSE;
1686 useTags = kFALSE;
c57f56b7 1687 if (!gGrid) {
1688 Error("CheckDataType", "No connection to grid");
1689 return;
1690 }
a2f5fc01 1691 isCollection = IsCollection(lfn);
c57f56b7 1692 TString msg = "\n##### file: ";
1693 msg += lfn;
a2f5fc01 1694 if (isCollection) {
c57f56b7 1695 msg += " type: raw_collection;";
1696 // special treatment for collections
a2f5fc01 1697 isXml = kFALSE;
c57f56b7 1698 // check for tag files in the collection
1699 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1700 if (!res) {
1701 msg += " using_tags: No (unknown)";
23329835 1702 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1703 return;
1704 }
1705 const char* typeStr = res->GetKey(0, "origLFN");
1706 if (!typeStr || !strlen(typeStr)) {
1707 msg += " using_tags: No (unknown)";
23329835 1708 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1709 return;
1710 }
1711 TString file = typeStr;
a2f5fc01 1712 useTags = file.Contains(".tag");
1713 if (useTags) msg += " using_tags: Yes";
c57f56b7 1714 else msg += " using_tags: No";
23329835 1715 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1716 return;
1717 }
1718 TString slfn(lfn);
1719 slfn.ToLower();
a2f5fc01 1720 isXml = slfn.Contains(".xml");
1721 if (isXml) {
c57f56b7 1722 // Open xml collection and check if there are tag files inside
1723 msg += " type: xml_collection;";
1724 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1725 if (!coll) {
1726 msg += " using_tags: No (unknown)";
23329835 1727 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1728 return;
1729 }
1730 TMap *map = coll->Next();
1731 if (!map) {
1732 msg += " using_tags: No (unknown)";
23329835 1733 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1734 return;
1735 }
1736 map = (TMap*)map->GetValue("");
1737 TString file;
1738 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
a2f5fc01 1739 useTags = file.Contains(".tag");
c57f56b7 1740 delete coll;
a2f5fc01 1741 if (useTags) msg += " using_tags: Yes";
c57f56b7 1742 else msg += " using_tags: No";
23329835 1743 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1744 return;
1745 }
a2f5fc01 1746 useTags = slfn.Contains(".tag");
c57f56b7 1747 if (slfn.Contains(".root")) msg += " type: root file;";
f866cba5 1748 else msg += " type: unknown file;";
a2f5fc01 1749 if (useTags) msg += " using_tags: Yes";
c57f56b7 1750 else msg += " using_tags: No";
23329835 1751 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1752}
1753
4e5c5506 1754//______________________________________________________________________________
1755void AliAnalysisAlien::EnablePackage(const char *package)
1756{
1757// Enables a par file supposed to exist in the current directory.
1758 TString pkg(package);
1759 pkg.ReplaceAll(".par", "");
1760 pkg += ".par";
1761 if (gSystem->AccessPathName(pkg)) {
ebcdf05e 1762 Fatal("EnablePackage", "Package %s not found", pkg.Data());
4e5c5506 1763 return;
1764 }
1765 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1766 Info("EnablePackage", "AliEn plugin will use .par packages");
1767 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1768 if (!fPackages) {
1769 fPackages = new TObjArray();
1770 fPackages->SetOwner();
1771 }
1772 fPackages->Add(new TObjString(pkg));
1773}
1774
3bdcb562 1775//______________________________________________________________________________
1776TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1777{
1778// Make a tree from files having the location specified in fFileForTestMode.
1779// Inspired from JF's CreateESDChain.
1780 if (fFileForTestMode.IsNull()) {
1781 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1782 return NULL;
1783 }
1784 if (gSystem->AccessPathName(fFileForTestMode)) {
1785 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1786 return NULL;
1787 }
1788 // Open the file
1789 ifstream in;
1790 in.open(fFileForTestMode);
1791 Int_t count = 0;
1792 // Read the input list of files and add them to the chain
1793 TString line;
1794 TChain *chain = new TChain(treeName);
1795 while (in.good())
1796 {
1797 in >> line;
1798 if (line.IsNull()) continue;
1799 if (count++ == fNtestFiles) break;
1800 TString esdFile(line);
1801 TFile *file = TFile::Open(esdFile);
1802 if (file) {
1803 if (!file->IsZombie()) chain->Add(esdFile);
1804 file->Close();
1805 } else {
1806 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1807 }
1808 }
1809 in.close();
1810 if (!chain->GetListOfFiles()->GetEntries()) {
1811 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1812 delete chain;
1813 return NULL;
1814 }
1815// chain->ls();
1816 return chain;
1817}
1818
d2a409b2 1819//______________________________________________________________________________
1820const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1821{
1822// Get job status for all jobs with jobid>jobidstart.
1823 static char mstatus[20];
1824 mstatus[0] = '\0';
1825 nrunning = 0;
1826 nwaiting = 0;
1827 nerror = 0;
1828 ndone = 0;
1829 TGridJobStatusList *list = gGrid->Ps("");
1830 if (!list) return mstatus;
1831 Int_t nentries = list->GetSize();
1832 TGridJobStatus *status;
1833 Int_t pid;
1834 for (Int_t ijob=0; ijob<nentries; ijob++) {
1835 status = (TGridJobStatus *)list->At(ijob);
8ddad121 1836 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
d2a409b2 1837 if (pid<jobidstart) continue;
1838 if (pid == lastid) {
8ddad121 1839 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
d2a409b2 1840 }
1841 switch (status->GetStatus()) {
1842 case TGridJobStatus::kWAITING:
1843 nwaiting++; break;
1844 case TGridJobStatus::kRUNNING:
1845 nrunning++; break;
1846 case TGridJobStatus::kABORTED:
1847 case TGridJobStatus::kFAIL:
1848 case TGridJobStatus::kUNKNOWN:
1849 nerror++; break;
1850 case TGridJobStatus::kDONE:
1851 ndone++;
1852 }
1853 }
1854 list->Delete();
1855 delete list;
1856 return mstatus;
1857}
1858
c57f56b7 1859//______________________________________________________________________________
1860Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1861{
1862// Returns true if file is a collection. Functionality duplicated from
1863// TAlien::Type() because we don't want to directly depend on TAlien.
1864 if (!gGrid) {
1865 Error("IsCollection", "No connection to grid");
1866 return kFALSE;
1867 }
1868 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1869 if (!res) return kFALSE;
1870 const char* typeStr = res->GetKey(0, "type");
1871 if (!typeStr || !strlen(typeStr)) return kFALSE;
1872 if (!strcmp(typeStr, "collection")) return kTRUE;
1873 delete res;
1874 return kFALSE;
1875}
1876
fe2d7fc2 1877//______________________________________________________________________________
1878Bool_t AliAnalysisAlien::IsSingleOutput() const
1879{
1880// Check if single-ouput option is on.
1881 return (!fOutputSingle.IsNull());
1882}
1883
16a4353c 1884//______________________________________________________________________________
1885void AliAnalysisAlien::Print(Option_t *) const
1886{
1887// Print current plugin settings.
84fcd93f 1888 printf("### AliEn analysis plugin current settings ###\n");
d3b18c4c 1889 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1890 if (mgr && mgr->IsProofMode()) {
1891 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1892 if (TestBit(AliAnalysisGrid::kTest))
1893 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1894 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1895 if (!fProofDataSet.IsNull())
1896 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1897 if (fProofReset==1)
1898 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1899 if (fProofReset>1)
1900 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1901 if (!fRootVersionForProof.IsNull())
1902 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1903 else
1904 printf("= ROOT version requested________________________ default\n");
1905 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1906 if (!fAliRootMode.IsNull())
1907 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1908 if (fNproofWorkers)
1909 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1910 if (fNproofWorkersPerSlave)
1911 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1912 if (TestSpecialBit(kClearPackages))
1913 printf("= ClearPackages requested...\n");
1914 if (fIncludePath.Data())
1915 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1916 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1917 if (fPackages && fPackages->GetEntries()) {
1918 TIter next(fPackages);
1919 TObject *obj;
1920 TString list;
1921 while ((obj=next())) list += obj->GetName();
1922 printf("= Par files to be used: ________________________ %s\n", list.Data());
1923 }
1924 if (TestSpecialBit(kProofConnectGrid))
1925 printf("= Requested PROOF connection to grid\n");
1926 return;
1927 }
e1c22e21 1928 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1929 if (fOverwriteMode) {
1930 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1931 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1932 }
348be253 1933 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1934 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
84fcd93f 1935 printf("= Production mode:______________________________ %d\n", fProductionMode);
1936 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1937 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1938 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
16a4353c 1939 if (fUser.Length())
84fcd93f 1940 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1941 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1942 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1943 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1944 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1945 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
16a4353c 1946 if (fRunNumbers.Length())
84fcd93f 1947 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
16a4353c 1948 if (fRunRange[0])
74013535 1949 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
16a4353c 1950 if (!fRunRange[0] && !fRunNumbers.Length()) {
1951 TIter next(fInputFiles);
1952 TObject *obj;
1953 TString list;
1954 while ((obj=next())) list += obj->GetName();
84fcd93f 1955 printf("= Input files to be processed: _________________ %s\n", list.Data());
16a4353c 1956 }
1957 if (TestBit(AliAnalysisGrid::kTest))
84fcd93f 1958 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1959 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1960 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1961 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
d3b18c4c 1962 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
84fcd93f 1963 printf("=====================================================================\n");
1964 printf("= Job price: ___________________________________ %d\n", fPrice);
1965 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1966 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
16a4353c 1967 if (fMaxInitFailed>0)
84fcd93f 1968 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
16a4353c 1969 if (fMasterResubmitThreshold>0)
84fcd93f 1970 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
149d288c 1971 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
319593fb 1972 if (fNrunsPerMaster>0)
84fcd93f 1973 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1974 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
b5b9dee8 1975 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1976 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
16a4353c 1977 if (fArguments.Length())
84fcd93f 1978 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
631c0b05 1979 if (fExecutableArgs.Length())
1980 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
84fcd93f 1981 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1982 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1983 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1984 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
16a4353c 1985 if (fDatasetName)
84fcd93f 1986 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1987 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
16a4353c 1988 if (fIncludePath.Data())
84fcd93f 1989 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
16a4353c 1990 if (fCloseSE.Length())
84fcd93f 1991 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
16a4353c 1992 if (fFriendChainName.Length())
84fcd93f 1993 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
d3b18c4c 1994 if (fPackages && fPackages->GetEntries()) {
16a4353c 1995 TIter next(fPackages);
1996 TObject *obj;
1997 TString list;
1998 while ((obj=next())) list += obj->GetName();
84fcd93f 1999 printf("= Par files to be used: ________________________ %s\n", list.Data());
16a4353c 2000 }
2001}
2002
c57f56b7 2003//______________________________________________________________________________
2004void AliAnalysisAlien::SetDefaults()
2005{
2006// Set default values for everything. What cannot be filled will be left empty.
2007 if (fGridJDL) delete fGridJDL;
2008 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 2009 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
c57f56b7 2010 fPrice = 1;
2011 fTTL = 30000;
2012 fSplitMaxInputFileNumber = 100;
2013 fMaxInitFailed = 0;
2014 fMasterResubmitThreshold = 0;
bb885a9e 2015 fNtestFiles = 10;
149d288c 2016 fNreplicas = 2;
a8739e8a 2017 fRunRange[0] = 0;
2018 fRunRange[1] = 0;
8e3bd06a 2019 fRunPrefix = "%d";
319593fb 2020 fNrunsPerMaster = 1;
16a4353c 2021 fMaxMergeFiles = 100;
c57f56b7 2022 fRunNumbers = "";
2023 fExecutable = "analysis.sh";
0a1c1f7f 2024 fExecutableCommand = "root -b -q";
c57f56b7 2025 fArguments = "";
631c0b05 2026 fExecutableArgs = "";
c57f56b7 2027 fAnalysisMacro = "myAnalysis.C";
2028 fAnalysisSource = "";
2029 fAdditionalLibs = "";
2030 fSplitMode = "se";
2031 fAPIVersion = "";
2032 fROOTVersion = "";
2033 fAliROOTVersion = "";
2034 fUser = ""; // Your alien user name
2035 fGridWorkingDir = "";
2036 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2037 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
0df6ccf2 2038 fFriendChainName = "";
c57f56b7 2039 fGridOutputDir = "output";
b83f84f0 2040 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
c57f56b7 2041 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2042 fInputFormat = "xml-single";
2043 fJDLName = "analysis.jdl";
c6cb3634 2044 fJobTag = "Automatically generated analysis JDL";
bb885a9e 2045 fMergeExcludes = "";
0f389141 2046 fMergeViaJDL = 0;
348be253 2047 SetUseCopy(kTRUE);
2048 SetCheckCopy(kTRUE);
149d288c 2049 SetDefaultOutputs(kTRUE);
e1c22e21 2050 fOverwriteMode = 1;
c57f56b7 2051}
2052
0f389141 2053//______________________________________________________________________________
b3e07543 2054Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
0f389141 2055{
b3e07543 2056// Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2057 // First check if the result is already in the output directory.
2058 if (FileExists(Form("%s/%s",aliendir,filename))) {
2059 printf("Final merged results found. Not merging again.\n");
7c2cd90a 2060 return kFALSE;
2061 }
b3e07543 2062 // Now check the last stage done.
2063 Int_t stage = 0;
2064 while (1) {
2065 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2066 stage++;
2067 }
2068 // Next stage of merging
2069 stage++;
2070 TString pattern = "*root_archive.zip";
2071 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2072 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2073 if (res) delete res;
2074 // Write standard output to file
2075 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2076 // Count the number of files inside
2077 ifstream ifile;
2078 ifile.open(Form("Stage_%d.xml",stage));
2079 if (!ifile.good()) {
2080 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
7c2cd90a 2081 return kFALSE;
b3e07543 2082 }
2083 TString line;
2084 Int_t nfiles = 0;
2085 while (!ifile.eof()) {
2086 ifile >> line;
2087 if (line.Contains("/event")) nfiles++;
7c2cd90a 2088 }
b3e07543 2089 ifile.close();
2090 if (!nfiles) {
2091 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2092 return kFALSE;
2093 } else {
2094 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
7ae54d70 2095 }
b3e07543 2096 // Copy the file in the output directory
2097 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2098 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2099 // Check if this is the last stage to be done.
2100 Bool_t laststage = (nfiles<nperchunk);
2101 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2102 if (laststage) {
2103 printf("### Submiting final merging stage %d\n", stage);
2104 TString finalJDL = jdl;
2105 finalJDL.ReplaceAll(".jdl", "_final.jdl");
03335324 2106 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
b3e07543 2107 Int_t jobId = SubmitSingleJob(query);
2108 if (!jobId) return kFALSE;
2109 } else {
2110 printf("### Submiting merging stage %d\n", stage);
03335324 2111 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
b3e07543 2112 Int_t jobId = SubmitSingleJob(query);
2113 if (!jobId) return kFALSE;
7c2cd90a 2114 }
b3e07543 2115 return kTRUE;
2116}
7c2cd90a 2117
2118//______________________________________________________________________________
2119Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2120{
2121// Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2122 if (!gGrid) return 0;
2123 printf("=> %s ------> ",query);
2124 TGridResult *res = gGrid->Command(query);
2125 if (!res) return 0;
2126 TString jobId = res->GetKey(0,"jobId");
2127 delete res;
2128 if (jobId.IsNull()) {
2129 printf("submission failed. Reason:\n");
2130 gGrid->Stdout();
2131 gGrid->Stderr();
2132 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2133 return 0;
2134 }
2135 printf(" Job id: %s\n", jobId.Data());
2136 return atoi(jobId);
2137}
2138
2139//______________________________________________________________________________
b3e07543 2140Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
7c2cd90a 2141{
b3e07543 2142// Merge given output files from basedir. Basedir can be an alien output directory
2143// but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2144// files in a group (ignored for xml input). Merging can be done in stages:
2145// stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2146// stage=1 : works with an xml of all root_archive.zip in the output directory
2147// stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
a2f5fc01 2148 TString outputFile = output;
0f389141 2149 TString command;
a2f5fc01 2150 TString outputChunk;
2151 TString previousChunk = "";
b3e07543 2152 TObjArray *listoffiles = new TObjArray();
2153// listoffiles->SetOwner();
a2f5fc01 2154 Int_t countChunk = 0;
2155 Int_t countZero = nmaxmerge;
0f389141 2156 Bool_t merged = kTRUE;
a2f5fc01 2157 Int_t index = outputFile.Index("@");
2158 if (index > 0) outputFile.Remove(index);
7c2cd90a 2159 TString inputFile = outputFile;
b3e07543 2160 TString sbasedir = basedir;
2161 if (sbasedir.Contains(".xml")) {
2162 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2163 nmaxmerge = 9999999;
2164 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2165 if (!coll) {
2166 ::Error("MergeOutput", "Input XML collection empty.");
2167 return kFALSE;
2168 }
2169 // Iterate grid collection
2170 while (coll->Next()) {
2171 TString fname = gSystem->DirName(coll->GetTURL());
2172 fname += "/";
2173 fname += inputFile;
2174 listoffiles->Add(new TNamed(fname.Data(),""));
2175 }
2176 } else {
2177 command = Form("find %s/ *%s", basedir, inputFile.Data());
2178 printf("command: %s\n", command.Data());
2179 TGridResult *res = gGrid->Command(command);
2180 if (!res) {
2181 ::Error("MergeOutput","No result for the find command\n");
2182 delete listoffiles;
2183 return kFALSE;
2184 }
2185 TIter nextmap(res);
2186 TMap *map = 0;
2187 while ((map=(TMap*)nextmap())) {
2188 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2189 if (!objs || !objs->GetString().Length()) {
2190 // Nothing found - skip this output
2191 delete res;
2192 delete listoffiles;
2193 return kFALSE;
2194 }
2195 listoffiles->Add(new TNamed(objs->GetName(),""));
2196 }
2197 delete res;
2198 }
2199 if (!listoffiles->GetEntries()) {
7c2cd90a 2200 ::Error("MergeOutput","No result for the find command\n");
b3e07543 2201 delete listoffiles;
0f389141 2202 return kFALSE;
2203 }
2204
2205 TFileMerger *fm = 0;
b3e07543 2206 TIter next0(listoffiles);
2207 TObjArray *listoffilestmp = new TObjArray();
2208 listoffilestmp->SetOwner();
2209 TObject *nextfile;
2210 TString snextfile;
2211 // Keep only the files at upper level
2212 Int_t countChar = 0;
2213 while ((nextfile=next0())) {
2214 snextfile = nextfile->GetName();
2215 Int_t crtCount = snextfile.CountChar('/');
2216 if (nextfile == listoffiles->First()) countChar = crtCount;
2217 if (crtCount < countChar) countChar = crtCount;
2218 }
2219 next0.Reset();
2220 while ((nextfile=next0())) {
2221 snextfile = nextfile->GetName();
2222 Int_t crtCount = snextfile.CountChar('/');
2223 if (crtCount > countChar) {
2224 delete nextfile;
2225 continue;
2226 }
2227 listoffilestmp->Add(nextfile);
2228 }
2229 delete listoffiles;
2230 listoffiles = listoffilestmp; // Now contains 'good' files
2231 listoffiles->Print();
2232 TIter next(listoffiles);
7c2cd90a 2233 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
a2f5fc01 2234 outputChunk = outputFile;
2235 outputChunk.ReplaceAll(".root", "_*.root");
0f389141 2236 // Check for existent temporary merge files
e1c22e21 2237 // Check overwrite mode and remove previous partial results if needed
7c2cd90a 2238 // Preserve old merging functionality for stage 0.
2239 if (stage==0) {
2240 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2241 while (1) {
2242 // Skip as many input files as in a chunk
2ea55496 2243 for (Int_t counter=0; counter<nmaxmerge; counter++) {
b3e07543 2244 nextfile = next();
2245 if (!nextfile) {
2ea55496 2246 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
b3e07543 2247 delete listoffiles;
2ea55496 2248 return kFALSE;
2249 }
b3e07543 2250 snextfile = nextfile->GetName();
7c2cd90a 2251 }
2252 outputChunk = outputFile;
2253 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2254 countChunk++;
2255 if (gSystem->AccessPathName(outputChunk)) continue;
2256 // Merged file with chunks up to <countChunk> found
2257 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2258 previousChunk = outputChunk;
2259 break;
2260 }
2261 }
2262 countZero = nmaxmerge;
2263
b3e07543 2264 while ((nextfile=next())) {
2265 snextfile = nextfile->GetName();
2ea55496 2266 // Loop 'find' results and get next LFN
7c2cd90a 2267 if (countZero == nmaxmerge) {
2268 // First file in chunk - create file merger and add previous chunk if any.
2269 fm = new TFileMerger(kFALSE);
2270 fm->SetFastMethod(kTRUE);
2271 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2272 outputChunk = outputFile;
2273 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2274 }
2275 // If last file found, put merged results in the output file
b3e07543 2276 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
7c2cd90a 2277 // Add file to be merged and decrement chunk counter.
b3e07543 2278 fm->AddFile(snextfile);
7c2cd90a 2279 countZero--;
b3e07543 2280 if (countZero==0 || nextfile == listoffiles->Last()) {
7c2cd90a 2281 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2282 // Nothing found - skip this output
2283 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
b3e07543 2284 merged = kFALSE;
2285 break;
7c2cd90a 2286 }
2287 fm->OutputFile(outputChunk);
2288 // Merge the outputs, then go to next chunk
2289 if (!fm->Merge()) {
2290 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
b3e07543 2291 merged = kFALSE;
2292 break;
7c2cd90a 2293 } else {
2294 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2295 gSystem->Unlink(previousChunk);
2296 }
b3e07543 2297 if (nextfile == listoffiles->Last()) break;
7c2cd90a 2298 countChunk++;
2299 countZero = nmaxmerge;
2300 previousChunk = outputChunk;
0f389141 2301 }
0f389141 2302 }
b3e07543 2303 delete listoffiles;
2304 delete fm;
7c2cd90a 2305 return merged;
2306 }
2307 // Merging stage different than 0.
2308 // Move to the begining of the requested chunk.
7c2cd90a 2309 fm = new TFileMerger(kFALSE);
2310 fm->SetFastMethod(kTRUE);
b3e07543 2311 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2312 delete listoffiles;
7c2cd90a 2313 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2314 // Nothing found - skip this output
2315 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2316 delete fm;
2317 return kFALSE;
2318 }
b3e07543 2319 fm->OutputFile(outputFile);
7c2cd90a 2320 // Merge the outputs
2321 if (!fm->Merge()) {
2322 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2323 delete fm;
2324 return kFALSE;
2325 } else {
b3e07543 2326 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
0f389141 2327 }
7c2cd90a 2328 delete fm;
2329 return kTRUE;
0f389141 2330}
2331
c57f56b7 2332//______________________________________________________________________________
2333Bool_t AliAnalysisAlien::MergeOutputs()
2334{
2335// Merge analysis outputs existing in the AliEn space.
2336 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2337 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2338 if (!Connect()) {
2339 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2340 return kFALSE;
0f389141 2341 }
c9e8f7fd 2342 if (fMergeViaJDL) {
2343 if (!TestBit(AliAnalysisGrid::kMerge)) {
2344 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2345 return kFALSE;
2346 }
2347 if (fProductionMode) {
2348 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2349 return kFALSE;
2350 }
0f389141 2351 Info("MergeOutputs", "Submitting merging JDL");
a03be957 2352 if (!SubmitMerging()) return kFALSE;
0f389141 2353 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
c9e8f7fd 2354 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
001cb79e 2355 return kFALSE;
c57f56b7 2356 }
2357 // Get the output path
dc030a24 2358 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
923e2ca5 2359 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 2360 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2361 return kFALSE;
2362 }
2363 if (!fOutputFiles.Length()) {
2364 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2365 return kFALSE;
0f389141 2366 }
2367 // Check if fast read option was requested
e1c22e21 2368 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2369 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
0f389141 2370 if (fFastReadOption) {
d3339be3 2371 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2372 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
b3e07543 2373 gEnv->SetValue("XNet.ConnectTimeout",50);
2374 gEnv->SetValue("XNet.RequestTimeout",50);
0f389141 2375 gEnv->SetValue("XNet.MaxRedirectCount",2);
b3e07543 2376 gEnv->SetValue("XNet.ReconnectTimeout",50);
0f389141 2377 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
c57f56b7 2378 }
e8b839ab 2379 // Make sure we change the temporary directory
2380 gSystem->Setenv("TMPDIR", gSystem->pwd());
70c52cf3 2381 // Set temporary compilation directory to current one
2382 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
149d288c 2383 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2384 TIter next(list);
2385 TObjString *str;
a2f5fc01 2386 TString outputFile;
c57f56b7 2387 Bool_t merged = kTRUE;
2388 while((str=(TObjString*)next())) {
a2f5fc01 2389 outputFile = str->GetString();
2390 Int_t index = outputFile.Index("@");
2391 if (index > 0) outputFile.Remove(index);
2392 TString outputChunk = outputFile;
2393 outputChunk.ReplaceAll(".root", "_*.root");
319593fb 2394 // Skip already merged outputs
a2f5fc01 2395 if (!gSystem->AccessPathName(outputFile)) {
e1c22e21 2396 if (fOverwriteMode) {
a2f5fc01 2397 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2398 gSystem->Unlink(outputFile);
2399 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2400 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2401 outputChunk.Data());
2402 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2403 }
2404 } else {
a2f5fc01 2405 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
e1c22e21 2406 continue;
2407 }
2408 } else {
a2f5fc01 2409 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2410 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2411 outputChunk.Data());
2412 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2413 }
2414 }
bb885a9e 2415 if (fMergeExcludes.Length() &&
a2f5fc01 2416 fMergeExcludes.Contains(outputFile.Data())) continue;
16a4353c 2417 // Perform a 'find' command in the output directory, looking for registered outputs
a2f5fc01 2418 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
0f389141 2419 if (!merged) {
2420 Error("MergeOutputs", "Terminate() will NOT be executed");
2421 return kFALSE;
ff07ec61 2422 }
2423 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2424 if (fileOpened) fileOpened->Close();
c57f56b7 2425 }
0f389141 2426 return kTRUE;
c57f56b7 2427}
2428
bb885a9e 2429//______________________________________________________________________________
2430void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2431{
2432// Use the output files connected to output containers from the analysis manager
2433// rather than the files defined by SetOutputFiles
2434 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
205b201f 2435 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
bb885a9e 2436 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2437}
2438
149d288c 2439//______________________________________________________________________________
2440void AliAnalysisAlien::SetOutputFiles(const char *list)
2441{
2442// Manually set the output files list.
2443// Removes duplicates. Not allowed if default outputs are not disabled.
2444 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2445 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2446 return;
2447 }
2448 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2449 fOutputFiles = "";
2450 TString slist = list;
2451 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2452 TObjArray *arr = slist.Tokenize(" ");
2453 TObjString *os;
2454 TIter next(arr);
2455 TString sout;
2456 while ((os=(TObjString*)next())) {
2457 sout = os->GetString();
2458 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2459 if (fOutputFiles.Contains(sout)) continue;
2460 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2461 fOutputFiles += sout;
2462 }
2463 delete arr;
f790bc1b 2464}
149d288c 2465
2466//______________________________________________________________________________
2467void AliAnalysisAlien::SetOutputArchive(const char *list)
2468{
2469// Manually set the output archive list. Free text - you are on your own...
2470// Not allowed if default outputs are not disabled.
2471 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2472 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2473 return;
2474 }
2475 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2476 fOutputArchive = list;
2477}
2478
2479//______________________________________________________________________________
2480void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2481{
2482// Setting a prefered output SE is not allowed anymore.
2483 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2484}
2485
28ce6c9c 2486//______________________________________________________________________________
2487void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2488{
2489// Set some PROOF special parameter.
2490 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2491 if (pair) {
2492 TObject *old = pair->Key();
2493 TObject *val = pair->Value();
2494 fProofParam.Remove(old);
2495 delete old;
2496 delete val;
2497 }
2498 fProofParam.Add(new TObjString(pname), new TObjString(value));
2499}
2500
2501//______________________________________________________________________________
2502const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2503{
2504// Returns a special PROOF parameter.
2505 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2506 if (!pair) return 0;
2507 return pair->Value()->GetName();
2508}
2509
5513444a 2510//______________________________________________________________________________
2511Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
c57f56b7 2512{
2513// Start remote grid analysis.
3bdcb562 2514 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2515 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2516 if (!mgr || !mgr->IsInitialized()) {
2517 Error("StartAnalysis", "You need an initialized analysis manager for this");
2518 return kFALSE;
2519 }
2520 // Are we in PROOF mode ?
2521 if (mgr->IsProofMode()) {
baa34407 2522 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2523 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3bdcb562 2524 if (fProofCluster.IsNull()) {
2525 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2526 return kFALSE;
2527 }
2528 if (fProofDataSet.IsNull() && !testMode) {
2529 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2530 return kFALSE;
2531 }
2532 // Set the needed environment
2533 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2534 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2535 if (fProofReset && !testMode) {
2536 if (fProofReset==1) {
2537 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2538 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2539 } else {
2540 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2541 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2542 }
2543 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2544 return kFALSE;
2545 }
baa34407 2546
2547 if (!testMode) {
2548 // Check if there is an old active session
2549 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2550 if (nsessions) {
2551 Error("StartAnalysis","You have to reset your old session first\n");
2552 return kFALSE;
2553 }
53911ca6 2554 }
3bdcb562 2555 // Do we need to change the ROOT version ? The success of this cannot be checked.
2556 if (!fRootVersionForProof.IsNull() && !testMode) {
2557 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2558 fProofCluster.Data(), fRootVersionForProof.Data()));
2559 }
2560 // Connect to PROOF and check the status
2561 Long_t proof = 0;
27734f0e 2562 TString sworkers;
2563 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2564 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3bdcb562 2565 if (!testMode) {
27734f0e 2566 if (!sworkers.IsNull())
2567 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3bdcb562 2568 else
2569 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2570 } else {
2571 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2572 if (!proof) {
2573 Error("StartAnalysis", "Could not start PROOF in test mode");
2574 return kFALSE;
2575 }
2576 }
2577 if (!proof) {
2578 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2579 return kFALSE;
2580 }
27734f0e 2581 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2582 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
28ce6c9c 2583 // Set proof special parameters if any
2584 TIter nextpp(&fProofParam);
2585 TObject *proofparam;
2586 while ((proofparam=nextpp())) {
2587 TString svalue = GetProofParameter(proofparam->GetName());
2588 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
2589 }
3bdcb562 2590 // Is dataset existing ?
2591 if (!testMode) {
2592 TString dataset = fProofDataSet;
2593 Int_t index = dataset.Index("#");
2594 if (index>=0) dataset.Remove(index);
830acc4c 2595// if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2596// Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2597// return kFALSE;
2598// }
2599// Info("StartAnalysis", "Dataset %s found", dataset.Data());
3bdcb562 2600 }
2601 // Is ClearPackages() needed ?
2602 if (TestSpecialBit(kClearPackages)) {
2603 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2604 gROOT->ProcessLine("gProof->ClearPackages();");
2605 }
2606 // Is a given aliroot mode requested ?
2607 TList optionsList;
1ac846e9 2608 TString parLibs;
830acc4c 2609 if (!fAliRootMode.IsNull()) {
3bdcb562 2610 TString alirootMode = fAliRootMode;
2611 if (alirootMode == "default") alirootMode = "";
2612 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2613 optionsList.SetOwner();
2614 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2615 // Check the additional libs to be loaded
2616 TString extraLibs;
1ac846e9 2617 Bool_t parMode = kFALSE;
3bdcb562 2618 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2619 // Parse the extra libs for .so
2620 if (fAdditionalLibs.Length()) {
2621 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2622 TIter next(list);
2623 TObjString *str;
1ac846e9 2624 while((str=(TObjString*)next())) {
2625 if (str->GetString().Contains(".so")) {
2626 if (parMode) {
2627 Warning("StartAnalysis", "Plugin does not support loading libs after par files in PROOF mode. Library %s and following will not load on workers", str->GetName());
2628 break;
2629 }
2630 TString stmp = str->GetName();
2631 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2632 stmp.ReplaceAll(".so","");
2633 if (!extraLibs.IsNull()) extraLibs += ":";
2634 extraLibs += stmp;
2635 continue;
2636 }
2637 if (str->GetString().Contains(".par")) {
2638 // The first par file found in the list will not allow any further .so
2639 parMode = kTRUE;
2640 if (!parLibs.IsNull()) parLibs += ":";
2641 parLibs += str->GetName();
2642 continue;
2643 }
3bdcb562 2644 }
2645 if (list) delete list;
2646 }
dc030a24 2647 if (!extraLibs.IsNull()) {
2648 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
2649 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2650 }
830acc4c 2651 // Check extra includes
2652 if (!fIncludePath.IsNull()) {
2653 TString includePath = fIncludePath;
2654 includePath.ReplaceAll(" ",":");
dc030a24 2655 includePath.ReplaceAll("$ALICE_ROOT/","");
2656 includePath.ReplaceAll("${ALICE_ROOT}/","");
8ddad121 2657 includePath.ReplaceAll("-I","");
dc030a24 2658 includePath.Remove(TString::kTrailing, ':');
830acc4c 2659 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2660 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2661 }
27734f0e 2662 // Check if connection to grid is requested
2663 if (TestSpecialBit(kProofConnectGrid))
2664 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
830acc4c 2665 // Enable AliRoot par
2666 if (testMode) {
2667 // Enable proof lite package
2668 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2669 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2670 TNamed *obj = (TNamed*)optionsList.At(i);
2671 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2672 }
2673 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
8ddad121 2674 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
830acc4c 2675 Info("StartAnalysis", "AliRootProofLite enabled");
2676 } else {
2677 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2678 return kFALSE;
2679 }
2680 } else {
dc030a24 2681 if ( ! fAliROOTVersion.IsNull() ) {
2682 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2683 fAliROOTVersion.Data(), &optionsList))) {
2684 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2685 return kFALSE;
2686 }
2687 }
27734f0e 2688 }
1ac846e9 2689 // Enable first par files from fAdditionalLibs
2690 if (!parLibs.IsNull()) {
2691 TObjArray *list = parLibs.Tokenize(":");
2692 TIter next(list);
2693 TObjString *package;
2694 while((package=(TObjString*)next())) {
40501bb7 2695 TString spkg = package->GetName();
2696 spkg.ReplaceAll(".par", "");
2697 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
b50a41c3 2698 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
4f136f18 2699 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2700 if (gROOT->ProcessLine(enablePackage)) {
1ac846e9 2701 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2702 return kFALSE;
2703 }
2704 } else {
2705 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2706 return kFALSE;
2707 }
2708 }
2709 if (list) delete list;
2710 }
3bdcb562 2711 } else {
2712 if (fAdditionalLibs.Contains(".so") && !testMode) {
2713 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2714 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2715 return kFALSE;
2716 }
2717 }
2718 // Enable par files if requested
2719 if (fPackages && fPackages->GetEntries()) {
2720 TIter next(fPackages);
2721 TObject *package;
2722 while ((package=next())) {
1ac846e9 2723 // Skip packages already enabled
2724 if (parLibs.Contains(package->GetName())) continue;
40501bb7 2725 TString spkg = package->GetName();
2726 spkg.ReplaceAll(".par", "");
2727 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
dc030a24 2728 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
27734f0e 2729 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3bdcb562 2730 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2731 return kFALSE;
2732 }
2733 } else {
2734 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2735 return kFALSE;
2736 }
2737 }
2738 }
2739 // Do we need to load analysis source files ?
2740 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2741 if (fAnalysisSource.Length()) {
2742 TObjArray *list = fAnalysisSource.Tokenize(" ");
2743 TIter next(list);
2744 TObjString *str;
2745 while((str=(TObjString*)next())) {
2746 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
dc030a24 2747 }
3bdcb562 2748 if (list) delete list;
2749 }
830acc4c 2750 if (testMode) {
2751 // Register dataset to proof lite.
2752 if (fFileForTestMode.IsNull()) {
2753 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2754 return kFALSE;
2755 }
2756 if (gSystem->AccessPathName(fFileForTestMode)) {
2757 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2758 return kFALSE;
2759 }
2760 TFileCollection *coll = new TFileCollection();
2761 coll->AddFromFile(fFileForTestMode);
8ddad121 2762 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
27734f0e 2763 gROOT->ProcessLine("gProof->ShowDataSets()");
830acc4c 2764 }
3bdcb562 2765 return kTRUE;
2766 }
c57f56b7 2767
43da816a 2768 // Check if output files have to be taken from the analysis manager
2769 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
f790bc1b 2770 // Add output files and AOD files
2771 fOutputFiles = GetListOfFiles("outaod");
c07b9ce2 2772 // Add extra files registered to the analysis manager
f790bc1b 2773 TString extra = GetListOfFiles("ext");
2774 if (!extra.IsNull()) {
149d288c 2775 extra.ReplaceAll(".root", "*.root");
f790bc1b 2776 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
149d288c 2777 fOutputFiles += extra;
84fcd93f 2778 }
149d288c 2779 // Compose the output archive.
b83f84f0 2780 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2781 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
43da816a 2782 }
f7b1cbc2 2783// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
c57f56b7 2784 if (TestBit(AliAnalysisGrid::kOffline)) {
2785 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2786 \n there nor any job run. You can revise the JDL and analysis \
2787 \n macro then run the same in \"submit\" mode.");
2788 } else if (TestBit(AliAnalysisGrid::kTest)) {
2789 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2790 \n dataset.");
2791 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2792 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2793 \n space and job submitted.");
2794 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2795 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
0f389141 2796 if (fMergeViaJDL) CheckInputData();
5513444a 2797 return kTRUE;
c57f56b7 2798 } else {
2799 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2800 }
2801
348be253 2802 Print();
c57f56b7 2803 if (!Connect()) {
2804 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
5513444a 2805 return kFALSE;
16a4353c 2806 }
d3b18c4c 2807 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
c57f56b7 2808 if (!CheckInputData()) {
2809 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
5513444a 2810 return kFALSE;
c57f56b7 2811 }
d3339be3 2812 if (!CreateDataset(fDataPattern)) {
2813 TString serror;
2814 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2815 if (fRunNumbers.Length()) serror = "run numbers";
2816 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2817 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2818 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2819 return kFALSE;
2820 }
c57f56b7 2821 WriteAnalysisFile();
2822 WriteAnalysisMacro();
2823 WriteExecutable();
2824 WriteValidationScript();
0f389141 2825 if (fMergeViaJDL) {
2826 WriteMergingMacro();
2827 WriteMergeExecutable();
2828 WriteValidationScript(kTRUE);
2829 }
5513444a 2830 if (!CreateJDL()) return kFALSE;
2831 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3bdcb562 2832 if (testMode) {
c57f56b7 2833 // Locally testing the analysis
2834 Info("StartAnalysis", "\n_______________________________________________________________________ \
2835 \n Running analysis script in a daughter shell as on a worker node \
2836 \n_______________________________________________________________________");
149d288c 2837 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2838 TIter next(list);
2839 TObjString *str;
a2f5fc01 2840 TString outputFile;
c57f56b7 2841 while((str=(TObjString*)next())) {
a2f5fc01 2842 outputFile = str->GetString();
2843 Int_t index = outputFile.Index("@");
2844 if (index > 0) outputFile.Remove(index);
2845 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
c57f56b7 2846 }
2847 delete list;
2848 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
f50e4bc8 2849 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
c57f56b7 2850// gSystem->Exec("cat stdout");
5513444a 2851 return kFALSE;
c57f56b7 2852 }
5513444a 2853 // Check if submitting is managed by LPM manager
a3e84053 2854 if (fProductionMode) {
5513444a 2855 TString prodfile = fJDLName;
2856 prodfile.ReplaceAll(".jdl", ".prod");
2857 WriteProductionFile(prodfile);
2858 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2859 return kFALSE;
2860 }
a8739e8a 2861 // Submit AliEn job(s)
d2a409b2 2862 gGrid->Cd(fGridOutputDir);
a8739e8a 2863 TGridResult *res;
c57f56b7 2864 TString jobID = "";
d2a409b2 2865 if (!fRunNumbers.Length() && !fRunRange[0]) {
dd74a515 2866 // Submit a given xml or a set of runs
a8739e8a 2867 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
84fcd93f 2868 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
a8739e8a 2869 if (res) {
2870 const char *cjobId = res->GetKey(0,"jobId");
2871 if (!cjobId) {
a03be957 2872 gGrid->Stdout();
2873 gGrid->Stderr();
a8739e8a 2874 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
5513444a 2875 return kFALSE;
a8739e8a 2876 } else {
2877 Info("StartAnalysis", "\n_______________________________________________________________________ \
2878 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2879 \n_______________________________________________________________________",
2880 fJDLName.Data(), cjobId);
2881 jobID = cjobId;
2882 }
2883 delete res;
a03be957 2884 } else {
2885 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2886 return kFALSE;
a8739e8a 2887 }
2888 } else {
d2a409b2 2889 // Submit for a range of enumeration of runs.
a03be957 2890 if (!Submit()) return kFALSE;
c57f56b7 2891 }
a8739e8a 2892
c57f56b7 2893 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2894 \n You may exit at any time and terminate the job later using the option <terminate> \
2895 \n ##################################################################################", jobID.Data());
bb885a9e 2896 gSystem->Exec("aliensh");
5513444a 2897 return kTRUE;
c57f56b7 2898}
2899
f790bc1b 2900//______________________________________________________________________________
2901const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2902{
2903// Get a comma-separated list of output files of the requested type.
2904// Type can be (case unsensitive):
2905// aod - list of aod files (std, extensions and filters)
2906// out - list of output files connected to containers (but not aod's or extras)
2907// ext - list of extra files registered to the manager
2908// ter - list of files produced in terminate
2909 static TString files;
2910 files = "";
2911 TString stype = type;
2912 stype.ToLower();
2913 TString aodfiles, extra;
2914 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2915 if (!mgr) {
2916 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2917 return files.Data();
2918 }
2919 if (mgr->GetOutputEventHandler()) {
2920 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2921 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2922 if (!extraaod.IsNull()) {
2923 aodfiles += ",";
2924 aodfiles += extraaod;
2925 }
2926 }
2927 if (stype.Contains("aod")) {
2928 files = aodfiles;
2929 if (stype == "aod") return files.Data();
2930 }
2931 // Add output files that are not in the list of AOD files
2932 TString outputfiles = "";
2933 TIter next(mgr->GetOutputs());
2934 AliAnalysisDataContainer *output;
2935 const char *filename = 0;
2936 while ((output=(AliAnalysisDataContainer*)next())) {
2937 filename = output->GetFileName();
2938 if (!(strcmp(filename, "default"))) continue;
2939 if (outputfiles.Contains(filename)) continue;
2940 if (aodfiles.Contains(filename)) continue;
2941 if (!outputfiles.IsNull()) outputfiles += ",";
2942 outputfiles += filename;
2943 }
2944 if (stype.Contains("out")) {
2945 if (!files.IsNull()) files += ",";
2946 files += outputfiles;
2947 if (stype == "out") return files.Data();
2948 }
2949 // Add extra files registered to the analysis manager
2950 TString sextra;
2951 extra = mgr->GetExtraFiles();
2952 if (!extra.IsNull()) {
2953 extra.Strip();
2954 extra.ReplaceAll(" ", ",");
2955 TObjArray *fextra = extra.Tokenize(",");
2956 TIter nextx(fextra);
2957 TObject *obj;
2958 while ((obj=nextx())) {
2959 if (aodfiles.Contains(obj->GetName())) continue;
2960 if (outputfiles.Contains(obj->GetName())) continue;
2961 if (sextra.Contains(obj->GetName())) continue;
2962 if (!sextra.IsNull()) sextra += ",";
2963 sextra += obj->GetName();
2964 }
2965 delete fextra;
2966 if (stype.Contains("ext")) {
2967 if (!files.IsNull()) files += ",";
2968 files += sextra;
2969 }
2970 }
2971 if (stype == "ext") return files.Data();
2972 TString termfiles;
2973 if (!fTerminateFiles.IsNull()) {
2974 fTerminateFiles.Strip();
2975 fTerminateFiles.ReplaceAll(" ",",");
9c939f2b 2976 TObjArray *fextra = fTerminateFiles.Tokenize(",");
f790bc1b 2977 TIter nextx(fextra);
2978 TObject *obj;
2979 while ((obj=nextx())) {
2980 if (aodfiles.Contains(obj->GetName())) continue;
2981 if (outputfiles.Contains(obj->GetName())) continue;
2982 if (termfiles.Contains(obj->GetName())) continue;
2983 if (sextra.Contains(obj->GetName())) continue;
2984 if (!termfiles.IsNull()) termfiles += ",";
2985 termfiles += obj->GetName();
2986 }
2987 delete fextra;
2988 }
2989 if (stype.Contains("ter")) {
2990 if (!files.IsNull() && !termfiles.IsNull()) {
2991 files += ",";
2992 files += termfiles;
2993 }
2994 }
2995 return files.Data();
2996}
2997
d2a409b2 2998//______________________________________________________________________________
a03be957 2999Bool_t AliAnalysisAlien::Submit()
d2a409b2 3000{
3001// Submit all master jobs.
3002 Int_t nmasterjobs = fInputFiles->GetEntries();
3003 Long_t tshoot = gSystem->Now();
a03be957 3004 if (!fNsubmitted && !SubmitNext()) return kFALSE;
d2a409b2 3005 while (fNsubmitted < nmasterjobs) {
3006 Long_t now = gSystem->Now();
3007 if ((now-tshoot)>30000) {
3008 tshoot = now;
a03be957 3009 if (!SubmitNext()) return kFALSE;
d2a409b2 3010 }
3011 }
a03be957 3012 return kTRUE;
d2a409b2 3013}
3014
0f389141 3015//______________________________________________________________________________
a03be957 3016Bool_t AliAnalysisAlien::SubmitMerging()
0f389141 3017{
3018// Submit all merging jobs.
dc030a24 3019 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
0f389141 3020 gGrid->Cd(fGridOutputDir);
3021 TString mergeJDLName = fExecutable;
3022 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
9f020952 3023 if (!fInputFiles) {
3024 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3025 return kFALSE;
3026 }
0f389141 3027 Int_t ntosubmit = fInputFiles->GetEntries();
0f389141 3028 for (Int_t i=0; i<ntosubmit; i++) {
f866cba5 3029 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3030 runOutDir.ReplaceAll(".xml", "");
7c2cd90a 3031 if (fOutputToRunNo) {
3032 // The output directory is the run number
3033 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3034 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3035 } else {
17b4e9a4 3036 if (!fRunNumbers.Length() && !fRunRange[0]) {
3037 // The output directory is the grid outdir
3038 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3039 runOutDir = fGridOutputDir;
3040 } else {
3041 // The output directory is the master number in 3 digits format
3042 printf("### Submitting merging job for master <%03d>\n", i);
3043 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3044 }
7c2cd90a 3045 }
3046 // Check now the number of merging stages.
2b222f7c 3047 TObjArray *list = fOutputFiles.Tokenize(",");
3048 TIter next(list);
3049 TObjString *str;
3050 TString outputFile;
3051 while((str=(TObjString*)next())) {
3052 outputFile = str->GetString();
3053 Int_t index = outputFile.Index("@");
3054 if (index > 0) outputFile.Remove(index);
3055 if (!fMergeExcludes.Contains(outputFile)) break;
3056 }
3057 delete list;
b3e07543 3058 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
1d0b4d65 3059 if (!done && (i==ntosubmit-1)) return kFALSE;
17b4e9a4 3060 if (!fRunNumbers.Length() && !fRunRange[0]) break;
0f389141 3061 }
a03be957 3062 if (!ntosubmit) return kTRUE;
9f020952 3063 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3064 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3065 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3066 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3067 \n ################################################################################################################");
0f389141 3068 gSystem->Exec("aliensh");
a03be957 3069 return kTRUE;
0f389141 3070}
3071
d2a409b2 3072//______________________________________________________________________________
a03be957 3073Bool_t AliAnalysisAlien::SubmitNext()
d2a409b2 3074{
08d5b699 3075// Submit next bunch of master jobs if the queue is free. The first master job is
3076// submitted right away, while the next will not be unless the previous was split.
3077// The plugin will not submit new master jobs if there are more that 500 jobs in
3078// waiting phase.
d2a409b2 3079 static Bool_t iscalled = kFALSE;
3080 static Int_t firstmaster = 0;
3081 static Int_t lastmaster = 0;
3082 static Int_t npermaster = 0;
a03be957 3083 if (iscalled) return kTRUE;
d2a409b2 3084 iscalled = kTRUE;
3085 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3086 Int_t ntosubmit = 0;
3087 TGridResult *res;
3088 TString jobID = "";
3bdcb562 3089 Int_t nmasterjobs = fInputFiles->GetEntries();
3090 if (!fNsubmitted) {
3091 ntosubmit = 1;
3092 if (!IsUseSubmitPolicy()) {
90d50a8c 3093 if (nmasterjobs>5)
3bdcb562 3094 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3095 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3096 ntosubmit = nmasterjobs;
3097 }
3098 } else {
d2a409b2 3099 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
84fcd93f 3100 printf("=== master %d: %s\n", lastmaster, status.Data());
d2a409b2 3101 // If last master not split, just return
a03be957 3102 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
d2a409b2 3103 // No more than 100 waiting jobs
08d5b699 3104 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
d2a409b2 3105 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
08d5b699 3106 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
7586eedc 3107 if (!ntosubmit) ntosubmit = 1;
84fcd93f 3108 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
d2a409b2 3109 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3110 }
d2a409b2 3111 for (Int_t i=0; i<ntosubmit; i++) {
3112 // Submit for a range of enumeration of runs.
a03be957 3113 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
d2a409b2 3114 TString query;
cd11251e 3115 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3116 runOutDir.ReplaceAll(".xml", "");
3117 if (fOutputToRunNo)
3118 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3119 else
3120 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
84fcd93f 3121 printf("********* %s\n",query.Data());
d2a409b2 3122 res = gGrid->Command(query);
3123 if (res) {
98ca124f 3124 TString cjobId1 = res->GetKey(0,"jobId");
3125 if (!cjobId1.Length()) {
d2a409b2 3126 iscalled = kFALSE;
a03be957 3127 gGrid->Stdout();
3128 gGrid->Stderr();
3129 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3130 return kFALSE;
d2a409b2 3131 } else {
3132 Info("StartAnalysis", "\n_______________________________________________________________________ \
3133 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3134 \n_______________________________________________________________________",
98ca124f 3135 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
d2a409b2 3136 jobID += cjobId1;
3137 jobID += " ";
98ca124f 3138 lastmaster = cjobId1.Atoi();
d2a409b2 3139 if (!firstmaster) firstmaster = lastmaster;
3140 fNsubmitted++;
3141 }
3142 delete res;
a03be957 3143 } else {
3144 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3145 return kFALSE;
d2a409b2 3146 }
3147 }
3148 iscalled = kFALSE;
a03be957 3149 return kTRUE;
d2a409b2 3150}
3151
c57f56b7 3152//______________________________________________________________________________
3153void AliAnalysisAlien::WriteAnalysisFile()
3154{
f10e8481 3155// Write current analysis manager into the file <analysisFile>
3156 TString analysisFile = fExecutable;
3157 analysisFile.ReplaceAll(".sh", ".root");
c57f56b7 3158 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3159 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3160 if (!mgr || !mgr->IsInitialized()) {
3161 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3162 return;
3163 }
3164 // Check analysis type
3165 TObject *handler;
3166 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3167 handler = (TObject*)mgr->GetInputEventHandler();
3168 if (handler) {
65eb22f8 3169 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3170 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3171 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3172 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3173 } else {
3174 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3175 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3176 }
c57f56b7 3177 }
3178 TDirectory *cdir = gDirectory;
f10e8481 3179 TFile *file = TFile::Open(analysisFile, "RECREATE");
c57f56b7 3180 if (file) {
e16a394c 3181 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3182 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
fe2d7fc2 3183 // Unless merging makes no sense
3184 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
c57f56b7 3185 mgr->Write();
3186 delete file;
fe2d7fc2 3187 // Enable termination for local jobs
3188 mgr->SetSkipTerminate(kFALSE);
c57f56b7 3189 }
3190 if (cdir) cdir->cd();
f10e8481 3191 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
c57f56b7 3192 }
3193 Bool_t copy = kTRUE;
d3b18c4c 3194 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3195 if (copy) {
3196 CdWork();
3197 TString workdir = gGrid->GetHomeDirectory();
3198 workdir += fGridWorkingDir;
d3b18c4c 3199 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
f10e8481 3200 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3201 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 3202 }
3203}
3204
3205//______________________________________________________________________________
3206void AliAnalysisAlien::WriteAnalysisMacro()
3207{
3208// Write the analysis macro that will steer the analysis in grid mode.
3209 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3210 ofstream out;
3211 out.open(fAnalysisMacro.Data(), ios::out);
3212 if (!out.good()) {
3213 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3214 return;
3215 }
5b273635 3216 Bool_t hasSTEERBase = kFALSE;
3217 Bool_t hasESD = kFALSE;
3218 Bool_t hasAOD = kFALSE;
3219 Bool_t hasANALYSIS = kFALSE;
7ea40ac8 3220 Bool_t hasOADB = kFALSE;
5b273635 3221 Bool_t hasANALYSISalice = kFALSE;
3222 Bool_t hasCORRFW = kFALSE;
c57f56b7 3223 TString func = fAnalysisMacro;
3224 TString type = "ESD";
3225 TString comment = "// Analysis using ";
c85cfc0f 3226 if (IsUseMCchain()) {
3227 type = "MC";
3228 comment += "MC";
3229 } else {
3230 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3231 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3232 type = "AOD";
3233 comment += "AOD";
3234 }
3235 }
0df6ccf2 3236 if (type!="AOD" && fFriendChainName!="") {
3237 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3238 return;
3239 }
c57f56b7 3240 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3241 else comment += " data";
3242 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3243 func.ReplaceAll(".C", "");
3244 out << "void " << func.Data() << "()" << endl;
3245 out << "{" << endl;
3246 out << comment.Data() << endl;
3247 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 3248 out << " TStopwatch timer;" << endl;
3249 out << " timer.Start();" << endl << endl;
13f0c00b 3250 // Change temp directory to current one
3251 out << "// Set temporary merging directory to current one" << endl;
3252 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
70c52cf3 3253 out << "// Set temporary compilation directory to current one" << endl;
3254 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
b3e07543 3255 // Reset existing include path
3256 out << "// Reset existing include path and add current directory first in the search" << endl;
3257 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
f790bc1b 3258 if (!fExecutableCommand.Contains("aliroot")) {
3259 out << "// load base root libraries" << endl;
3260 out << " gSystem->Load(\"libTree\");" << endl;
3261 out << " gSystem->Load(\"libGeom\");" << endl;
3262 out << " gSystem->Load(\"libVMC\");" << endl;
3263 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3264 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3265 }
d5c6455a 3266 if (fAdditionalRootLibs.Length()) {
47a4137d 3267 // in principle libtree /lib geom libvmc etc. can go into this list, too
3268 out << "// Add aditional libraries" << endl;
3269 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3270 TIter next(list);
3271 TObjString *str;
3272 while((str=(TObjString*)next())) {
3273 if (str->GetString().Contains(".so"))
3274 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
d5c6455a 3275 }
47a4137d 3276 if (list) delete list;
d5c6455a 3277 }
57377eb5 3278 out << "// Load analysis framework libraries" << endl;
652561d5 3279 TString setupPar = "AliAnalysisAlien::SetupPar";
4e5c5506 3280 if (!fPackages) {
f790bc1b 3281 if (!fExecutableCommand.Contains("aliroot")) {
3282 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3283 out << " gSystem->Load(\"libESD\");" << endl;
3284 out << " gSystem->Load(\"libAOD\");" << endl;
3285 }
4e5c5506 3286 out << " gSystem->Load(\"libANALYSIS\");" << endl;
7ea40ac8 3287 out << " gSystem->Load(\"libOADB\");" << endl;
57377eb5 3288 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3289 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 3290 } else {
4e5c5506 3291 TIter next(fPackages);
3292 TObject *obj;
57377eb5 3293 TString pkgname;
57377eb5 3294 while ((obj=next())) {
3295 pkgname = obj->GetName();
4478e6f1 3296 if (pkgname == "STEERBase" ||
3297 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3298 if (pkgname == "ESD" ||
3299 pkgname == "ESD.par") hasESD = kTRUE;
3300 if (pkgname == "AOD" ||
3301 pkgname == "AOD.par") hasAOD = kTRUE;
3302 if (pkgname == "ANALYSIS" ||
3303 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
7ea40ac8 3304 if (pkgname == "OADB" ||
3305 pkgname == "OADB.par") hasOADB = kTRUE;
4478e6f1 3306 if (pkgname == "ANALYSISalice" ||
3307 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3308 if (pkgname == "CORRFW" ||
3309 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
5b273635 3310 }
3311 if (hasANALYSISalice) setupPar = "SetupPar";
57377eb5 3312 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3313 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
57377eb5 3314 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3315 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
57377eb5 3316 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3317 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
57377eb5 3318 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3319 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
7ea40ac8 3320 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3321 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
57377eb5 3322 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3323 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
57377eb5 3324 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3325 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
57377eb5 3326 out << "// Compile other par packages" << endl;
3327 next.Reset();
fcc9bb6f 3328 while ((obj=next())) {
3329 pkgname = obj->GetName();
4478e6f1 3330 if (pkgname == "STEERBase" ||
3331 pkgname == "STEERBase.par" ||
3332 pkgname == "ESD" ||
3333 pkgname == "ESD.par" ||
3334 pkgname == "AOD" ||
3335 pkgname == "AOD.par" ||
3336 pkgname == "ANALYSIS" ||
3337 pkgname == "ANALYSIS.par" ||
7ea40ac8 3338 pkgname == "OADB" ||
3339 pkgname == "OADB.par" ||
4478e6f1 3340 pkgname == "ANALYSISalice" ||
3341 pkgname == "ANALYSISalice.par" ||
3342 pkgname == "CORRFW" ||
3343 pkgname == "CORRFW.par") continue;
5b273635 3344 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 3345 }
4e5c5506 3346 }
b3e07543 3347 out << "// include path" << endl;
3348 // Get the include path from the interpreter and remove entries pointing to AliRoot
3349 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3350 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3351 out << " TIter nextpath(listpaths);" << endl;
3352 out << " TObjString *pname;" << endl;
3353 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3354 out << " TString current = pname->GetName();" << endl;
3355 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3356 out << " gSystem->AddIncludePath(current);" << endl;
3357 out << " }" << endl;
3358 out << " if (listpaths) delete listpaths;" << endl;
3359 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3360 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3361 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
6da75e0b 3362 if (fAdditionalLibs.Length()) {
3363 out << "// Add aditional AliRoot libraries" << endl;
3364 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3365 TIter next(list);
3366 TObjString *str;
3367 while((str=(TObjString*)next())) {
3368 if (str->GetString().Contains(".so"))
3369 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
652561d5 3370 if (str->GetString().Contains(".par"))
3371 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
6da75e0b 3372 }
3373 if (list) delete list;
3374 }
3375 out << endl;
c57f56b7 3376 out << "// analysis source to be compiled at runtime (if any)" << endl;
3377 if (fAnalysisSource.Length()) {
3378 TObjArray *list = fAnalysisSource.Tokenize(" ");
3379 TIter next(list);
3380 TObjString *str;
3381 while((str=(TObjString*)next())) {
3382 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3383 }
3384 if (list) delete list;
3385 }
3386 out << endl;
b3e07543 3387// out << " printf(\"Currently load libraries:\\n\");" << endl;
3388// out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
0f389141 3389 if (fFastReadOption) {
d3339be3 3390 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. This may skip some files that could be accessed !!! \
3391 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
0f389141 3392 out << "// fast xrootd reading enabled" << endl;
3393 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
b3e07543 3394 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3395 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
0f389141 3396 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
b3e07543 3397 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
0f389141 3398 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3399 }
c57f56b7 3400 out << "// connect to AliEn and make the chain" << endl;
3401 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
c57f56b7 3402 out << "// read the analysis manager from file" << endl;
f10e8481 3403 TString analysisFile = fExecutable;
3404 analysisFile.ReplaceAll(".sh", ".root");
3405 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
c57f56b7 3406 out << " if (!file) return;" << endl;
3407 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3408 out << " AliAnalysisManager *mgr = 0;" << endl;
3409 out << " TKey *key;" << endl;
3410 out << " while ((key=(TKey*)nextkey())) {" << endl;
3411 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3412 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3413 out << " };" << endl;
3414 out << " if (!mgr) {" << endl;
205b201f 3415 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
c57f56b7 3416 out << " return;" << endl;
3417 out << " }" << endl << endl;
3418 out << " mgr->PrintStatus();" << endl;
52b6a92b 3419 if (AliAnalysisManager::GetAnalysisManager()) {
f866cba5 3420 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
52b6a92b 3421 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
de52b69c 3422 } else {
9a8288ff 3423 if (TestBit(AliAnalysisGrid::kTest))
3424 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3425 else
3426 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
52b6a92b 3427 }
3428 }
242accb2 3429 if (IsUsingTags()) {
3430 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3431 } else {
3432 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3433 }
c57f56b7 3434 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 3435 out << " timer.Stop();" << endl;
3436 out << " timer.Print();" << endl;
c57f56b7 3437 out << "}" << endl << endl;
3438 if (IsUsingTags()) {
3439 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3440 out << "{" << endl;
3441 out << "// Create a chain using tags from the xml file." << endl;
3442 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3443 out << " if (!coll) {" << endl;
3444 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3445 out << " return NULL;" << endl;
3446 out << " }" << endl;
3447 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3448 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3449 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3450 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3451 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3452 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3453 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3454 out << " // Check if the cuts configuration file was provided" << endl;
3455 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3456 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3457 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3458 out << " }" << endl;
0df6ccf2 3459 if (fFriendChainName=="") {
3460 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3461 } else {
3462 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3463 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3464 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3465 }
c57f56b7 3466 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3467 out << " chain->ls();" << endl;
3468 out << " return chain;" << endl;
fcc9bb6f 3469 out << "}" << endl << endl;
c57f56b7 3470 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3471 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3472 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3473 msg += " AliLHCTagCuts *lhcCuts,\n";
3474 msg += " AliDetectorTagCuts *detCuts,\n";
3475 msg += " AliEventTagCuts *evCuts)";
23329835 3476 Info("WriteAnalysisMacro", "%s", msg.Data());
c57f56b7 3477 }
0df6ccf2 3478 }
3479 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 3480 out <<"//________________________________________________________________________________" << endl;
c57f56b7 3481 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3482 out << "{" << endl;
3483 out << "// Create a chain using url's from xml file" << endl;
242accb2 3484 out << " TString filename;" << endl;
3485 out << " Int_t run = 0;" << endl;
c85cfc0f 3486 if (IsUseMCchain()) {
3487 out << " TString treename = \"TE\";" << endl;
3488 } else {
3489 out << " TString treename = type;" << endl;
3490 out << " treename.ToLower();" << endl;
3491 out << " treename += \"Tree\";" << endl;
3492 }
e02fee64 3493 out << " printf(\"***************************************\\n\");" << endl;
3494 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3495 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 3496 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3497 out << " if (!coll) {" << endl;
3498 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3499 out << " return NULL;" << endl;
3500 out << " }" << endl;
242accb2 3501 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
c57f56b7 3502 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 3503 if(fFriendChainName!="") {
3504 out << " TChain *chainFriend = new TChain(treename);" << endl;
3505 }
c57f56b7 3506 out << " coll->Reset();" << endl;
0df6ccf2 3507 out << " while (coll->Next()) {" << endl;
242accb2 3508 out << " filename = coll->GetTURL("");" << endl;
3509 out << " if (mgr) {" << endl;
3510 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3511 out << " if (nrun && nrun != run) {" << endl;
3512 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3513 out << " mgr->SetRunFromPath(nrun);" << endl;
3514 out << " run = nrun;" << endl;
3515 out << " }" << endl;
3516 out << " }" << endl;
3517 out << " chain->Add(filename);" << endl;
0df6ccf2 3518 if(fFriendChainName!="") {
3519 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3520 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3521 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3522 out << " chainFriend->Add(fileFriend.Data());" << endl;
3523 }
3524 out << " }" << endl;
c57f56b7 3525 out << " if (!chain->GetNtrees()) {" << endl;
3526 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3527 out << " return NULL;" << endl;
3528 out << " }" << endl;
0df6ccf2 3529 if(fFriendChainName!="") {
3530 out << " chain->AddFriend(chainFriend);" << endl;
3531 }
c57f56b7 3532 out << " return chain;" << endl;
fcc9bb6f 3533 out << "}" << endl << endl;
c57f56b7 3534 }
5b273635 3535 if (hasANALYSISalice) {
3536 out <<"//________________________________________________________________________________" << endl;
3537 out << "Bool_t SetupPar(const char *package) {" << endl;
3538 out << "// Compile the package and set it up." << endl;
3539 out << " TString pkgdir = package;" << endl;
3540 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
b50a41c3 3541 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
5b273635 3542 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3543 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3544 out << " // Check for BUILD.sh and execute" << endl;
3545 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3546 out << " printf(\"*******************************\\n\");" << endl;
3547 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3548 out << " printf(\"*******************************\\n\");" << endl;
3549 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3550 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3551 out << " gSystem->ChangeDirectory(cdir);" << endl;
3552 out << " return kFALSE;" << endl;
3553 out << " }" << endl;
3554 out << " } else {" << endl;
3555 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3556 out << " gSystem->ChangeDirectory(cdir);" << endl;
3557 out << " return kFALSE;" << endl;
3558 out << " }" << endl;
3559 out << " // Check for SETUP.C and execute" << endl;
3560 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3561 out << " printf(\"*******************************\\n\");" << endl;
3562 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3563 out << " printf(\"*******************************\\n\");" << endl;
3564 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3565 out << " } else {" << endl;
3566 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3567 out << " gSystem->ChangeDirectory(cdir);" << endl;
3568 out << " return kFALSE;" << endl;
3569 out << " }" << endl;
3570 out << " // Restore original workdir" << endl;
3571 out << " gSystem->ChangeDirectory(cdir);" << endl;
3572 out << " return kTRUE;" << endl;
3573 out << "}" << endl;
3574 }
c57f56b7 3575 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3576 }
3577 Bool_t copy = kTRUE;
d3b18c4c 3578 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3579 if (copy) {
3580 CdWork();
3581 TString workdir = gGrid->GetHomeDirectory();
3582 workdir += fGridWorkingDir;
3583 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3584 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3585 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3586 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3587 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3588 }
3589 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3590 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3591 }
3592}
3593
0f389141 3594//______________________________________________________________________________
3595void AliAnalysisAlien::WriteMergingMacro()
3596{
3597// Write a macro to merge the outputs per master job.
3598 if (!fMergeViaJDL) return;
3599 if (!fOutputFiles.Length()) {
3600 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3601 return;
3602 }
3603 TString mergingMacro = fExecutable;
3604 mergingMacro.ReplaceAll(".sh","_merge.C");
dc030a24 3605 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
0f389141 3606 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3607 ofstream out;
3608 out.open(mergingMacro.Data(), ios::out);
3609 if (!out.good()) {
3610 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3611 return;
3612 }
5b273635 3613 Bool_t hasSTEERBase = kFALSE;
3614 Bool_t hasESD = kFALSE;
3615 Bool_t hasAOD = kFALSE;
3616 Bool_t hasANALYSIS = kFALSE;
7ea40ac8 3617 Bool_t hasOADB = kFALSE;
5b273635 3618 Bool_t hasANALYSISalice = kFALSE;
3619 Bool_t hasCORRFW = kFALSE;
0f389141 3620 TString func = mergingMacro;
3621 TString comment;
3622 func.ReplaceAll(".C", "");
f47d5cb4 3623 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
0f389141 3624 out << "{" << endl;
3625 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3626 out << " TStopwatch timer;" << endl;
3627 out << " timer.Start();" << endl << endl;
b3e07543 3628 // Reset existing include path
3629 out << "// Reset existing include path and add current directory first in the search" << endl;
3630 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
7c2cd90a 3631 if (!fExecutableCommand.Contains("aliroot")) {
3632 out << "// load base root libraries" << endl;
3633 out << " gSystem->Load(\"libTree\");" << endl;
3634 out << " gSystem->Load(\"libGeom\");" << endl;
3635 out << " gSystem->Load(\"libVMC\");" << endl;
3636 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3637 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3638 }
0f389141 3639 if (fAdditionalRootLibs.Length()) {
3640 // in principle libtree /lib geom libvmc etc. can go into this list, too
3641 out << "// Add aditional libraries" << endl;
3642 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3643 TIter next(list);
3644 TObjString *str;
3645 while((str=(TObjString*)next())) {
3646 if (str->GetString().Contains(".so"))
3647 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3648 }
3649 if (list) delete list;
3650 }
0f389141 3651 out << "// Load analysis framework libraries" << endl;
3652 if (!fPackages) {
7c2cd90a 3653 if (!fExecutableCommand.Contains("aliroot")) {
3654 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3655 out << " gSystem->Load(\"libESD\");" << endl;
3656 out << " gSystem->Load(\"libAOD\");" << endl;
3657 }
0f389141 3658 out << " gSystem->Load(\"libANALYSIS\");" << endl;
7ea40ac8 3659 out << " gSystem->Load(\"libOADB\");" << endl;
0f389141 3660 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3661 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3662 } else {
3663 TIter next(fPackages);
3664 TObject *obj;
3665 TString pkgname;
5b273635 3666 TString setupPar = "AliAnalysisAlien::SetupPar";
0f389141 3667 while ((obj=next())) {
3668 pkgname = obj->GetName();
3669 if (pkgname == "STEERBase" ||
3670 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3671 if (pkgname == "ESD" ||
3672 pkgname == "ESD.par") hasESD = kTRUE;
3673 if (pkgname == "AOD" ||
3674 pkgname == "AOD.par") hasAOD = kTRUE;
3675 if (pkgname == "ANALYSIS" ||
3676 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
7ea40ac8 3677 if (pkgname == "OADB" ||
3678 pkgname == "OADB.par") hasOADB = kTRUE;
0f389141 3679 if (pkgname == "ANALYSISalice" ||
3680 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3681 if (pkgname == "CORRFW" ||
3682 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3683 }
5b273635 3684 if (hasANALYSISalice) setupPar = "SetupPar";
0f389141 3685 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3686 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
0f389141 3687 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3688 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
0f389141 3689 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3690 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
0bc15bcd 3691 out << " gSystem->Load(\"libOADB\");" << endl;
0f389141 3692 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3693 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
7ea40ac8 3694 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3695 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
0f389141 3696 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3697 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
0f389141 3698 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3699 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
0f389141 3700 out << "// Compile other par packages" << endl;
3701 next.Reset();
3702 while ((obj=next())) {
3703 pkgname = obj->GetName();
3704 if (pkgname == "STEERBase" ||
3705 pkgname == "STEERBase.par" ||
3706 pkgname == "ESD" ||
3707 pkgname == "ESD.par" ||
3708 pkgname == "AOD" ||
3709 pkgname == "AOD.par" ||
3710 pkgname == "ANALYSIS" ||
3711 pkgname == "ANALYSIS.par" ||
7ea40ac8 3712 pkgname == "OADB" ||
3713 pkgname == "OADB.par" ||
0f389141 3714 pkgname == "ANALYSISalice" ||
3715 pkgname == "ANALYSISalice.par" ||
3716 pkgname == "CORRFW" ||
3717 pkgname == "CORRFW.par") continue;
5b273635 3718 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
0f389141 3719 }
3720 }
b3e07543 3721 out << "// include path" << endl;
3722 // Get the include path from the interpreter and remove entries pointing to AliRoot
3723 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3724 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3725 out << " TIter nextpath(listpaths);" << endl;
3726 out << " TObjString *pname;" << endl;
3727 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3728 out << " TString current = pname->GetName();" << endl;
3729 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3730 out << " gSystem->AddIncludePath(current);" << endl;
3731 out << " }" << endl;
3732 out << " if (listpaths) delete listpaths;" << endl;
3733 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3734 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3735 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
0f389141 3736 if (fAdditionalLibs.Length()) {
3737 out << "// Add aditional AliRoot libraries" << endl;
3738 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3739 TIter next(list);
3740 TObjString *str;
3741 while((str=(TObjString*)next())) {
3742 if (str->GetString().Contains(".so"))
3743 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3744 }
3745 if (list) delete list;
3746 }
3747 out << endl;
3748 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3749 if (fAnalysisSource.Length()) {
3750 TObjArray *list = fAnalysisSource.Tokenize(" ");
3751 TIter next(list);
3752 TObjString *str;
3753 while((str=(TObjString*)next())) {
3754 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3755 }
3756 if (list) delete list;
3757 }
149d288c 3758 out << endl;
3759
0f389141 3760 if (fFastReadOption) {
3761 Warning("WriteMergingMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid merging jobs. Note that this may skip some files that could be accessed !!!");
3762 out << "// fast xrootd reading enabled" << endl;
3763 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
b3e07543 3764 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3765 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
0f389141 3766 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
b3e07543 3767 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
0f389141 3768 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
e8b839ab 3769 }
3770 // Change temp directory to current one
3771 out << "// Set temporary merging directory to current one" << endl;
3772 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
70c52cf3 3773 out << "// Set temporary compilation directory to current one" << endl;
3774 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
0f389141 3775 out << "// Connect to AliEn" << endl;
3776 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
7c2cd90a 3777 out << " TString outputDir = dir;" << endl;
f790bc1b 3778 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
0f389141 3779 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
58268c13 3780 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
0f389141 3781 out << " TIter *iter = new TIter(list);" << endl;
3782 out << " TObjString *str;" << endl;
a2f5fc01 3783 out << " TString outputFile;" << endl;
0f389141 3784 out << " Bool_t merged = kTRUE;" << endl;
3785 out << " while((str=(TObjString*)iter->Next())) {" << endl;
a2f5fc01 3786 out << " outputFile = str->GetString();" << endl;
7c2cd90a 3787 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
a2f5fc01 3788 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3789 out << " if (index > 0) outputFile.Remove(index);" << endl;
0f389141 3790 out << " // Skip already merged outputs" << endl;
a2f5fc01 3791 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3792 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
0f389141 3793 out << " continue;" << endl;
3794 out << " }" << endl;
a2f5fc01 3795 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
b3e07543 3796 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
0f389141 3797 out << " if (!merged) {" << endl;
a2f5fc01 3798 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
7c2cd90a 3799 out << " return;" << endl;
0f389141 3800 out << " }" << endl;
3801 out << " }" << endl;
7c2cd90a 3802 out << " // all outputs merged, validate" << endl;
3803 out << " ofstream out;" << endl;
3804 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3805 out << " out.close();" << endl;
3806 out << " // read the analysis manager from file" << endl;
f866cba5 3807 TString analysisFile = fExecutable;
3808 analysisFile.ReplaceAll(".sh", ".root");
f47d5cb4 3809 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
f866cba5 3810 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
7c2cd90a 3811 out << " if (!file) return;" << endl;
f866cba5 3812 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3813 out << " AliAnalysisManager *mgr = 0;" << endl;
3814 out << " TKey *key;" << endl;
3815 out << " while ((key=(TKey*)nextkey())) {" << endl;
3816 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3817 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3818 out << " };" << endl;
3819 out << " if (!mgr) {" << endl;
3820 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3821 out << " return;" << endl;
3822 out << " }" << endl << endl;
5c4250fc 3823 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
b385fec0 3824 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
f866cba5 3825 out << " mgr->PrintStatus();" << endl;
3826 if (AliAnalysisManager::GetAnalysisManager()) {
3827 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3828 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3829 } else {
9a8288ff 3830 if (TestBit(AliAnalysisGrid::kTest))
3831 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3832 else
3833 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
f866cba5 3834 }
3835 }
9a8288ff 3836 out << " TTree *tree = NULL;" << endl;
3837 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
0f389141 3838 out << "}" << endl << endl;
5b273635 3839 if (hasANALYSISalice) {
3840 out <<"//________________________________________________________________________________" << endl;
3841 out << "Bool_t SetupPar(const char *package) {" << endl;
3842 out << "// Compile the package and set it up." << endl;
3843 out << " TString pkgdir = package;" << endl;
3844 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
b50a41c3 3845 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
5b273635 3846 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3847 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3848 out << " // Check for BUILD.sh and execute" << endl;
3849 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3850 out << " printf(\"*******************************\\n\");" << endl;
3851 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3852 out << " printf(\"*******************************\\n\");" << endl;
3853 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3854 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3855 out << " gSystem->ChangeDirectory(cdir);" << endl;
3856 out << " return kFALSE;" << endl;
3857 out << " }" << endl;
3858 out << " } else {" << endl;
3859 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3860 out << " gSystem->ChangeDirectory(cdir);" << endl;
3861 out << " return kFALSE;" << endl;
3862 out << " }" << endl;
3863 out << " // Check for SETUP.C and execute" << endl;
3864 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3865 out << " printf(\"*******************************\\n\");" << endl;
3866 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3867 out << " printf(\"*******************************\\n\");" << endl;
3868 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3869 out << " } else {" << endl;
3870 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3871 out << " gSystem->ChangeDirectory(cdir);" << endl;
3872 out << " return kFALSE;" << endl;
3873 out << " }" << endl;
3874 out << " // Restore original workdir" << endl;
3875 out << " gSystem->ChangeDirectory(cdir);" << endl;
3876 out << " return kTRUE;" << endl;
3877 out << "}" << endl;
3878 }
0f389141 3879 }
3880 Bool_t copy = kTRUE;
d3b18c4c 3881 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 3882 if (copy) {
3883 CdWork();
3884 TString workdir = gGrid->GetHomeDirectory();
3885 workdir += fGridWorkingDir;
3886 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3887 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3888 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3889 }
3890}
3891
3892//______________________________________________________________________________
3893Bool_t AliAnalysisAlien::SetupPar(const char *package)
3894{
205b201f 3895// Compile the par file archive pointed by <package>. This must be present in the current directory.
0f389141 3896// Note that for loading the compiled library. The current directory should have precedence in
3897// LD_LIBRARY_PATH
3898 TString pkgdir = package;
3899 pkgdir.ReplaceAll(".par","");
b50a41c3 3900 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
0f389141 3901 TString cdir = gSystem->WorkingDirectory();
3902 gSystem->ChangeDirectory(pkgdir);
3903 // Check for BUILD.sh and execute
3904 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3905 printf("**************************************************\n");
3906 printf("*** Building PAR archive %s\n", package);
3907 printf("**************************************************\n");
3908 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3909 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3910 gSystem->ChangeDirectory(cdir);
3911 return kFALSE;
3912 }
3913 } else {
3914 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3915 gSystem->ChangeDirectory(cdir);
3916 return kFALSE;
3917 }
3918 // Check for SETUP.C and execute
3919 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3920 printf("**************************************************\n");
3921 printf("*** Setup PAR archive %s\n", package);
3922 printf("**************************************************\n");
3923 gROOT->Macro("PROOF-INF/SETUP.C");
3924 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3925 } else {
3926 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3927 gSystem->ChangeDirectory(cdir);
3928 return kFALSE;
3929 }
3930 // Restore original workdir
3931 gSystem->ChangeDirectory(cdir);
3932 return kTRUE;
3933}
3934
c57f56b7 3935//______________________________________________________________________________
3936void AliAnalysisAlien::WriteExecutable()
3937{
3938// Generate the alien executable script.
3939 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3940 ofstream out;
3941 out.open(fExecutable.Data(), ios::out);
3942 if (out.bad()) {
5513444a 3943 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
c57f56b7 3944 return;
3945 }
3946 out << "#!/bin/bash" << endl;
2a4d5166 3947 // Make sure we can properly compile par files
3948 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
c57f56b7 3949 out << "echo \"=========================================\"" << endl;
3950 out << "echo \"############## PATH : ##############\"" << endl;
3951 out << "echo $PATH" << endl;
3952 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3953 out << "echo $LD_LIBRARY_PATH" << endl;
3954 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3955 out << "echo $ROOTSYS" << endl;
3956 out << "echo \"############## which root : ##############\"" << endl;
3957 out << "which root" << endl;
3958 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3959 out << "echo $ALICE_ROOT" << endl;
3960 out << "echo \"############## which aliroot : ##############\"" << endl;
3961 out << "which aliroot" << endl;
9c5ddadc 3962 out << "echo \"############## system limits : ##############\"" << endl;
3963 out << "ulimit -a" << endl;
3964 out << "echo \"############## memory : ##############\"" << endl;
3965 out << "free -m" << endl;
c57f56b7 3966 out << "echo \"=========================================\"" << endl << endl;
0a1c1f7f 3967 out << fExecutableCommand << " ";
631c0b05 3968 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
9c5ddadc 3969 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3970 out << "echo \"############## memory after: ##############\"" << endl;
3971 out << "free -m" << endl;
c57f56b7 3972 }
3973 Bool_t copy = kTRUE;
d3b18c4c 3974 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3975 if (copy) {
3976 CdWork();
3977 TString workdir = gGrid->GetHomeDirectory();
923e2ca5 3978 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 3979 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
c57f56b7 3980 workdir += fGridWorkingDir;
3981 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3982 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 3983 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
c57f56b7 3984 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3985 }
3986}
3987
0f389141 3988//______________________________________________________________________________
3989void AliAnalysisAlien::WriteMergeExecutable()
3990{
3991// Generate the alien executable script for the merging job.
3992 if (!fMergeViaJDL) return;
3993 TString mergeExec = fExecutable;
3994 mergeExec.ReplaceAll(".sh", "_merge.sh");
3995 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3996 ofstream out;
3997 out.open(mergeExec.Data(), ios::out);
3998 if (out.bad()) {
3999 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4000 return;
4001 }
4002 out << "#!/bin/bash" << endl;
2a4d5166 4003 // Make sure we can properly compile par files
4004 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
0f389141 4005 out << "echo \"=========================================\"" << endl;
4006 out << "echo \"############## PATH : ##############\"" << endl;
4007 out << "echo $PATH" << endl;
4008 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4009 out << "echo $LD_LIBRARY_PATH" << endl;
4010 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4011 out << "echo $ROOTSYS" << endl;
4012 out << "echo \"############## which root : ##############\"" << endl;
4013 out << "which root" << endl;
4014 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4015 out << "echo $ALICE_ROOT" << endl;
4016 out << "echo \"############## which aliroot : ##############\"" << endl;
4017 out << "which aliroot" << endl;
4018 out << "echo \"############## system limits : ##############\"" << endl;
4019 out << "ulimit -a" << endl;
4020 out << "echo \"############## memory : ##############\"" << endl;
4021 out << "free -m" << endl;
4022 out << "echo \"=========================================\"" << endl << endl;
0f389141 4023 TString mergeMacro = fExecutable;
4024 mergeMacro.ReplaceAll(".sh", "_merge.C");
f790bc1b 4025 if (IsOneStageMerging())
4026 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4027 else
f47d5cb4 4028 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
0f389141 4029 out << fExecutableCommand << " " << "$ARG" << endl;
4030 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4031 out << "echo \"############## memory after: ##############\"" << endl;
4032 out << "free -m" << endl;
0f389141 4033 }
4034 Bool_t copy = kTRUE;
d3b18c4c 4035 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 4036 if (copy) {
4037 CdWork();
4038 TString workdir = gGrid->GetHomeDirectory();
4039 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 4040 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
0f389141 4041 workdir += fGridWorkingDir;
4042 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4043 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 4044 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
0f389141 4045 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4046 }
4047}
4048
c57f56b7 4049//______________________________________________________________________________
5513444a 4050void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4051{
4052// Write the production file to be submitted by LPM manager. The format is:
f5e8c702 4053// First line: full_path_to_jdl estimated_no_subjobs_per_master
5513444a 4054// Next lines: full_path_to_dataset XXX (XXX is a string)
4055// To submit, one has to: submit jdl XXX for all lines
4056 ofstream out;
4057 out.open(filename, ios::out);
4058 if (out.bad()) {
4059 Error("WriteProductionFile", "Bad file name: %s", filename);
4060 return;
4061 }
d3b18c4c 4062 TString workdir;
4063 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4064 workdir = gGrid->GetHomeDirectory();
5513444a 4065 workdir += fGridWorkingDir;
f5e8c702 4066 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
5513444a 4067 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
f5e8c702 4068 out << locjdl << " " << njobspermaster << endl;
5513444a 4069 Int_t nmasterjobs = fInputFiles->GetEntries();
4070 for (Int_t i=0; i<nmasterjobs; i++) {
409b4ada 4071 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4072 runOutDir.ReplaceAll(".xml", "");
4073 if (fOutputToRunNo)
4074 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4075 else
4076 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
5513444a 4077 }
d3b18c4c 4078 if (gGrid) {
4079 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4080 if (FileExists(filename)) gGrid->Rm(filename);
4081 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4082 }
5513444a 4083}
4084
4085//______________________________________________________________________________
0f389141 4086void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
c57f56b7 4087{
4088// Generate the alien validation script.
4089 // Generate the validation script
4090 TObjString *os;
d3b18c4c 4091 if (fValidationScript.IsNull()) {
4092 fValidationScript = fExecutable;
4093 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4094 }
4095 TString validationScript = fValidationScript;
4096 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
c57f56b7 4097 if (!Connect()) {
4098 Error("WriteValidationScript", "Alien connection required");
4099 return;
4100 }
d3b18c4c 4101 if (!fTerminateFiles.IsNull()) {
4102 fTerminateFiles.Strip();
4103 fTerminateFiles.ReplaceAll(" ",",");
4104 }
a2f5fc01 4105 TString outStream = "";
4106 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
c57f56b7 4107 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4108 ofstream out;
0d5d317c 4109 out.open(validationScript, ios::out);
c57f56b7 4110 out << "#!/bin/bash" << endl;
4111 out << "##################################################" << endl;
4112 out << "validateout=`dirname $0`" << endl;
4113 out << "validatetime=`date`" << endl;
4114 out << "validated=\"0\";" << endl;
4115 out << "error=0" << endl;
4116 out << "if [ -z $validateout ]" << endl;
4117 out << "then" << endl;
4118 out << " validateout=\".\"" << endl;
4119 out << "fi" << endl << endl;
4120 out << "cd $validateout;" << endl;
4121 out << "validateworkdir=`pwd`;" << endl << endl;
a2f5fc01 4122 out << "echo \"*******************************************************\"" << outStream << endl;
4123 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
c57f56b7 4124 out << "" << endl;
a2f5fc01 4125 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4126 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4127 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4128 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4129 out << "ls -la ./" << outStream << endl;
4130 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
c57f56b7 4131 out << "##################################################" << endl;
ebec370a 4132 out << "" << endl;
4133
4134 out << "if [ ! -f stderr ] ; then" << endl;
4135 out << " error=1" << endl;
a2f5fc01 4136 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4137 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4138 out << "fi" << endl;
4139
b34c9f51 4140 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4141 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4142 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4143 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4144 out << "" << endl;
4145
ebec370a 4146 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4147 out << " error=1" << endl;
a2f5fc01 4148 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4149 out << " echo \"$parArch\" " << outStream << endl;
4150 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4151 out << "fi" << endl;
4152
4153 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4154 out << " error=1" << endl;
a2f5fc01 4155 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4156 out << " echo \"$segViol\" " << outStream << endl;
4157 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4158 out << "fi" << endl;
4159
4160 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4161 out << " error=1" << endl;
a2f5fc01 4162 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4163 out << " echo \"$segFault\" " << outStream << endl;
4164 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4165 out << "fi" << endl;
4166
b34c9f51 4167 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4168 out << " error=1" << endl;
a2f5fc01 4169 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4170 out << " echo \"$glibcErr\" " << outStream << endl;
4171 out << " echo \"Error = $error\" " << outStream << endl;
b34c9f51 4172 out << "fi" << endl;
4173
ebec370a 4174 // Part dedicated to the specific analyses running into the train
4175
d3b18c4c 4176 TString outputFiles = fOutputFiles;
4177 if (merge && !fTerminateFiles.IsNull()) {
4178 outputFiles += ",";
4179 outputFiles += fTerminateFiles;
4180 }
4181 TObjArray *arr = outputFiles.Tokenize(",");
c57f56b7 4182 TIter next1(arr);
a2f5fc01 4183 TString outputFile;
bbd88db8 4184 while (!merge && (os=(TObjString*)next1())) {
4185 // No need to validate outputs produced by merging since the merging macro does this
a2f5fc01 4186 outputFile = os->GetString();
4187 Int_t index = outputFile.Index("@");
4188 if (index > 0) outputFile.Remove(index);
bbd88db8 4189 if (fTerminateFiles.Contains(outputFile)) continue;
a2f5fc01 4190 if (outputFile.Contains("*")) continue;
4191 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
c57f56b7 4192 out << " error=1" << endl;
7c2cd90a 4193 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4194 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
c57f56b7 4195 out << "fi" << endl;
4196 }
4197 delete arr;
7c2cd90a 4198 out << "if ! [ -f outputs_valid ] ; then" << endl;
4199 out << " error=1" << endl;
4200 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4201 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4202 out << "fi" << endl;
923e2ca5 4203
c57f56b7 4204 out << "if [ $error = 0 ] ; then" << endl;
a2f5fc01 4205 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
149d288c 4206 if (!IsKeepLogs()) {
4207 out << " echo \"* === Logs std* will be deleted === \"" << endl;
a2f5fc01 4208 outStream = "";
149d288c 4209 out << " rm -f std*" << endl;
4210 }
c57f56b7 4211 out << "fi" << endl;
4212
a2f5fc01 4213 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4214 out << "echo \"*******************************************************\"" << outStream << endl;
c57f56b7 4215 out << "cd -" << endl;
4216 out << "exit $error" << endl;
4217 }
4218 Bool_t copy = kTRUE;
d3b18c4c 4219 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 4220 if (copy) {
4221 CdWork();
4222 TString workdir = gGrid->GetHomeDirectory();
4223 workdir += fGridWorkingDir;
d3b18c4c 4224 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
0d5d317c 4225 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4226 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 4227 }
4228}