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