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