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