]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisAlien.cxx
Allow adding par files in the list of additional libs
[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");
1097 outputArchive += Form("root_archive.zip:%s@disk=%d",files.Data(),fNreplicas);
1098 } else {
1099 outputArchive = fOutputArchive;
1100 }
0f389141 1101 arr = outputArchive.Tokenize(" ");
705adb3e 1102 TIter next2(arr);
0f389141 1103 comment = comment1;
1104 first = kTRUE;
705adb3e 1105 while ((os=(TObjString*)next2())) {
0f389141 1106 if (!first) comment = NULL;
0cdf65a8 1107 TString currentfile = os->GetString();
d3b18c4c 1108 if (!IsOneStageMerging()) currentfile.ReplaceAll(".zip", "-Stage$2_$3.zip");
0cdf65a8 1109 if (!currentfile.Contains("@") && fCloseSE.Length())
d3b18c4c 1110 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
0f389141 1111 else
0cdf65a8 1112 fMergingJDL->AddToOutputArchive(currentfile, comment);
0f389141 1113 first = kFALSE;
1114 }
1115 delete arr;
c57f56b7 1116 }
149d288c 1117 arr = fOutputFiles.Tokenize(",");
c57f56b7 1118 TIter next(arr);
0f389141 1119 Bool_t first = kTRUE;
f790bc1b 1120 const char *comment = "Files to be saved";
43da816a 1121 while ((os=(TObjString*)next())) {
e1eaf596 1122 // Ignore ouputs in jdl that are also in outputarchive
1123 TString sout = os->GetString();
f790bc1b 1124 sout.ReplaceAll("*", "");
1125 sout.ReplaceAll(".root", "");
e1eaf596 1126 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1127 if (fOutputArchive.Contains(sout)) continue;
0f389141 1128 if (!first) comment = NULL;
43da816a 1129 if (!os->GetString().Contains("@") && fCloseSE.Length())
0f389141 1130 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
43da816a 1131 else
0f389141 1132 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1133 first = kFALSE;
f790bc1b 1134 if (fMergeExcludes.Contains(sout)) continue;
1135 if (!os->GetString().Contains("@") && fCloseSE.Length())
1136 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1137 else
1138 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
43da816a 1139 }
c57f56b7 1140 delete arr;
0f389141 1141 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1142 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
d3b18c4c 1143 TString validationScript = fValidationScript;
0f389141 1144 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
d3b18c4c 1145 validationScript.ReplaceAll(".sh", "_merge.sh");
0f389141 1146 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1147 if (fMasterResubmitThreshold) {
1148 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1149 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1150 }
d2a409b2 1151 // Write a jdl with 2 input parameters: collection name and output dir name.
1152 WriteJDL(copy);
c57f56b7 1153 }
1154 // Copy jdl to grid workspace
a8739e8a 1155 if (copy) {
b5e4aaa7 1156 // Check if an output directory was defined and valid
1157 if (!fGridOutputDir.Length()) {
1158 Error("CreateJDL", "You must define AliEn output directory");
1159 return kFALSE;
1160 } else {
1161 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
bb2e67a0 1162 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
b93f8109 1163 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
b5e4aaa7 1164 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1165 } else {
1166 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1167 return kFALSE;
1168 }
1169 }
1170 gGrid->Cd(workdir);
1171 }
648174cf 1172 if (TestBit(AliAnalysisGrid::kSubmit)) {
0f389141 1173 TString mergeJDLName = fExecutable;
1174 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
648174cf 1175 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1176 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1177 if (fProductionMode) {
648174cf 1178 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1179 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1180 }
648174cf 1181 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1182 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1183 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
648174cf 1184 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1185 if (fMergeViaJDL) {
1186 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1187 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1188 }
648174cf 1189 }
c57f56b7 1190 if (fAdditionalLibs.Length()) {
e7c71df0 1191 arr = fAdditionalLibs.Tokenize(" ");
c57f56b7 1192 TObjString *os;
1193 TIter next(arr);
1194 while ((os=(TObjString*)next())) {
c57f56b7 1195 if (os->GetString().Contains(".so")) continue;
4e5c5506 1196 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
c57f56b7 1197 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1198 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1199 }
1200 delete arr;
1201 }
4e5c5506 1202 if (fPackages) {
1203 TIter next(fPackages);
1204 TObject *obj;
1205 while ((obj=next())) {
fdbbc7be 1206 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
4e5c5506 1207 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1208 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1209 }
1210 }
c57f56b7 1211 }
1212 return kTRUE;
1213}
1214
a8739e8a 1215//______________________________________________________________________________
d2a409b2 1216Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
a8739e8a 1217{
1218// Writes one or more JDL's corresponding to findex. If findex is negative,
1219// all run numbers are considered in one go (jdl). For non-negative indices
1220// they correspond to the indices in the array fInputFiles.
1221 if (!fInputFiles) return kFALSE;
d3b18c4c 1222 TObject *os;
1223 TString workdir;
1224 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
a8739e8a 1225 workdir += fGridWorkingDir;
d2a409b2 1226
d3b18c4c 1227 if (fProductionMode) {
a8739e8a 1228 TIter next(fInputFiles);
d3b18c4c 1229 while ((os=next()))
1230 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1231 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1232 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1233 } else {
1234 if (!fRunNumbers.Length() && !fRunRange[0]) {
1235 // One jdl with no parameters in case input data is specified by name.
1236 TIter next(fInputFiles);
1237 while ((os=next()))
1238 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1239 if (!fOutputSingle.IsNull())
1240 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1241 else {
1242 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1243 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1244 }
1245 } else {
1246 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1247 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1248 if (!fOutputSingle.IsNull()) {
1249 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1250 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1251 } else {
1252 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1253 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1254 }
1255 }
a8739e8a 1256 }
1257
a8739e8a 1258 // Generate the JDL as a string
1259 TString sjdl = fGridJDL->Generate();
0f389141 1260 TString sjdl1 = fMergingJDL->Generate();
a8739e8a 1261 Int_t index;
a8739e8a 1262 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1263 sjdl.ReplaceAll("(member", "\n (member");
1264 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1265 sjdl.ReplaceAll("{", "{\n ");
1266 sjdl.ReplaceAll("};", "\n};");
1267 sjdl.ReplaceAll("{\n \n", "{\n");
1268 sjdl.ReplaceAll("\n\n", "\n");
1269 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
0f389141 1270 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1271 sjdl1.ReplaceAll("(member", "\n (member");
1272 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1273 sjdl1.ReplaceAll("{", "{\n ");
1274 sjdl1.ReplaceAll("};", "\n};");
1275 sjdl1.ReplaceAll("{\n \n", "{\n");
1276 sjdl1.ReplaceAll("\n\n", "\n");
1277 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
a8739e8a 1278 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
f60ef0ba 1279 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
a8739e8a 1280 index = sjdl.Index("JDLVariables");
1281 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
4739b2aa 1282 sjdl += "Workdirectorysize = {\"5000MB\"};";
0f389141 1283 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
d3b18c4c 1284 index = fJobTag.Index(":");
1285 if (index < 0) index = fJobTag.Length();
1286 TString jobTag = fJobTag;
1287 jobTag.Insert(index, "_Merging");
1288 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
7c2cd90a 1289 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 1290 index = sjdl1.Index("JDLVariables");
1291 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
4739b2aa 1292 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
a8739e8a 1293 // Write jdl to file
a8739e8a 1294 ofstream out;
d2a409b2 1295 out.open(fJDLName.Data(), ios::out);
a8739e8a 1296 if (out.bad()) {
d3b18c4c 1297 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
a8739e8a 1298 return kFALSE;
1299 }
1300 out << sjdl << endl;
0f389141 1301 TString mergeJDLName = fExecutable;
1302 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1303 if (fMergeViaJDL) {
1304 ofstream out1;
1305 out1.open(mergeJDLName.Data(), ios::out);
1306 if (out.bad()) {
d3b18c4c 1307 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
0f389141 1308 return kFALSE;
1309 }
1310 out1 << sjdl1 << endl;
1311 }
a8739e8a 1312
1313 // Copy jdl to grid workspace
1314 if (!copy) {
d3b18c4c 1315 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
a8739e8a 1316 } else {
d2a409b2 1317 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1318 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1319 if (fProductionMode) {
b5fe9cba 1320 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1321 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1322 }
d2a409b2 1323 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1324 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
d3b18c4c 1325 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
5513444a 1326 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1327 if (fMergeViaJDL) {
d3b18c4c 1328 Info("WriteJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
0f389141 1329 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1330 }
a8739e8a 1331 }
1332 return kTRUE;
1333}
1334
c57f56b7 1335//______________________________________________________________________________
5513444a 1336Bool_t AliAnalysisAlien::FileExists(const char *lfn)
c57f56b7 1337{
1338// Returns true if file exists.
5513444a 1339 if (!gGrid) return kFALSE;
c57f56b7 1340 TGridResult *res = gGrid->Ls(lfn);
1341 if (!res) return kFALSE;
1342 TMap *map = dynamic_cast<TMap*>(res->At(0));
1343 if (!map) {
1344 delete res;
1345 return kFALSE;
1346 }
1347 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1348 if (!objs || !objs->GetString().Length()) {
1349 delete res;
1350 return kFALSE;
1351 }
1352 delete res;
1353 return kTRUE;
1354}
1355
923e2ca5 1356//______________________________________________________________________________
1357Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1358{
1359// Returns true if directory exists. Can be also a path.
1360 if (!gGrid) return kFALSE;
1361 // Check if dirname is a path
1362 TString dirstripped = dirname;
1363 dirstripped = dirstripped.Strip();
1364 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1365 TString dir = gSystem->BaseName(dirstripped);
1366 dir += "/";
1367 TString path = gSystem->DirName(dirstripped);
1368 TGridResult *res = gGrid->Ls(path, "-F");
1369 if (!res) return kFALSE;
1370 TIter next(res);
1371 TMap *map;
1372 TObject *obj;
1373 while ((map=dynamic_cast<TMap*>(next()))) {
1374 obj = map->GetValue("name");
1375 if (!obj) break;
1376 if (dir == obj->GetName()) {
1377 delete res;
1378 return kTRUE;
1379 }
1380 }
1381 delete res;
1382 return kFALSE;
1383}
1384
c57f56b7 1385//______________________________________________________________________________
a2f5fc01 1386void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
c57f56b7 1387{
1388// Check input data type.
a2f5fc01 1389 isCollection = kFALSE;
1390 isXml = kFALSE;
1391 useTags = kFALSE;
c57f56b7 1392 if (!gGrid) {
1393 Error("CheckDataType", "No connection to grid");
1394 return;
1395 }
a2f5fc01 1396 isCollection = IsCollection(lfn);
c57f56b7 1397 TString msg = "\n##### file: ";
1398 msg += lfn;
a2f5fc01 1399 if (isCollection) {
c57f56b7 1400 msg += " type: raw_collection;";
1401 // special treatment for collections
a2f5fc01 1402 isXml = kFALSE;
c57f56b7 1403 // check for tag files in the collection
1404 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1405 if (!res) {
1406 msg += " using_tags: No (unknown)";
23329835 1407 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1408 return;
1409 }
1410 const char* typeStr = res->GetKey(0, "origLFN");
1411 if (!typeStr || !strlen(typeStr)) {
1412 msg += " using_tags: No (unknown)";
23329835 1413 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1414 return;
1415 }
1416 TString file = typeStr;
a2f5fc01 1417 useTags = file.Contains(".tag");
1418 if (useTags) msg += " using_tags: Yes";
c57f56b7 1419 else msg += " using_tags: No";
23329835 1420 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1421 return;
1422 }
1423 TString slfn(lfn);
1424 slfn.ToLower();
a2f5fc01 1425 isXml = slfn.Contains(".xml");
1426 if (isXml) {
c57f56b7 1427 // Open xml collection and check if there are tag files inside
1428 msg += " type: xml_collection;";
1429 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1430 if (!coll) {
1431 msg += " using_tags: No (unknown)";
23329835 1432 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1433 return;
1434 }
1435 TMap *map = coll->Next();
1436 if (!map) {
1437 msg += " using_tags: No (unknown)";
23329835 1438 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1439 return;
1440 }
1441 map = (TMap*)map->GetValue("");
1442 TString file;
1443 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
a2f5fc01 1444 useTags = file.Contains(".tag");
c57f56b7 1445 delete coll;
a2f5fc01 1446 if (useTags) msg += " using_tags: Yes";
c57f56b7 1447 else msg += " using_tags: No";
23329835 1448 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1449 return;
1450 }
a2f5fc01 1451 useTags = slfn.Contains(".tag");
c57f56b7 1452 if (slfn.Contains(".root")) msg += " type: root file;";
f866cba5 1453 else msg += " type: unknown file;";
a2f5fc01 1454 if (useTags) msg += " using_tags: Yes";
c57f56b7 1455 else msg += " using_tags: No";
23329835 1456 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1457}
1458
4e5c5506 1459//______________________________________________________________________________
1460void AliAnalysisAlien::EnablePackage(const char *package)
1461{
1462// Enables a par file supposed to exist in the current directory.
1463 TString pkg(package);
1464 pkg.ReplaceAll(".par", "");
1465 pkg += ".par";
1466 if (gSystem->AccessPathName(pkg)) {
ebcdf05e 1467 Fatal("EnablePackage", "Package %s not found", pkg.Data());
4e5c5506 1468 return;
1469 }
1470 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1471 Info("EnablePackage", "AliEn plugin will use .par packages");
1472 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1473 if (!fPackages) {
1474 fPackages = new TObjArray();
1475 fPackages->SetOwner();
1476 }
1477 fPackages->Add(new TObjString(pkg));
1478}
1479
3bdcb562 1480//______________________________________________________________________________
1481TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1482{
1483// Make a tree from files having the location specified in fFileForTestMode.
1484// Inspired from JF's CreateESDChain.
1485 if (fFileForTestMode.IsNull()) {
1486 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1487 return NULL;
1488 }
1489 if (gSystem->AccessPathName(fFileForTestMode)) {
1490 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1491 return NULL;
1492 }
1493 // Open the file
1494 ifstream in;
1495 in.open(fFileForTestMode);
1496 Int_t count = 0;
1497 // Read the input list of files and add them to the chain
1498 TString line;
1499 TChain *chain = new TChain(treeName);
1500 while (in.good())
1501 {
1502 in >> line;
1503 if (line.IsNull()) continue;
1504 if (count++ == fNtestFiles) break;
1505 TString esdFile(line);
1506 TFile *file = TFile::Open(esdFile);
1507 if (file) {
1508 if (!file->IsZombie()) chain->Add(esdFile);
1509 file->Close();
1510 } else {
1511 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1512 }
1513 }
1514 in.close();
1515 if (!chain->GetListOfFiles()->GetEntries()) {
1516 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1517 delete chain;
1518 return NULL;
1519 }
1520// chain->ls();
1521 return chain;
1522}
1523
d2a409b2 1524//______________________________________________________________________________
1525const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1526{
1527// Get job status for all jobs with jobid>jobidstart.
1528 static char mstatus[20];
1529 mstatus[0] = '\0';
1530 nrunning = 0;
1531 nwaiting = 0;
1532 nerror = 0;
1533 ndone = 0;
1534 TGridJobStatusList *list = gGrid->Ps("");
1535 if (!list) return mstatus;
1536 Int_t nentries = list->GetSize();
1537 TGridJobStatus *status;
1538 Int_t pid;
1539 for (Int_t ijob=0; ijob<nentries; ijob++) {
1540 status = (TGridJobStatus *)list->At(ijob);
1541 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1542 if (pid<jobidstart) continue;
1543 if (pid == lastid) {
1544 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1545 }
1546 switch (status->GetStatus()) {
1547 case TGridJobStatus::kWAITING:
1548 nwaiting++; break;
1549 case TGridJobStatus::kRUNNING:
1550 nrunning++; break;
1551 case TGridJobStatus::kABORTED:
1552 case TGridJobStatus::kFAIL:
1553 case TGridJobStatus::kUNKNOWN:
1554 nerror++; break;
1555 case TGridJobStatus::kDONE:
1556 ndone++;
1557 }
1558 }
1559 list->Delete();
1560 delete list;
1561 return mstatus;
1562}
1563
c57f56b7 1564//______________________________________________________________________________
1565Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1566{
1567// Returns true if file is a collection. Functionality duplicated from
1568// TAlien::Type() because we don't want to directly depend on TAlien.
1569 if (!gGrid) {
1570 Error("IsCollection", "No connection to grid");
1571 return kFALSE;
1572 }
1573 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1574 if (!res) return kFALSE;
1575 const char* typeStr = res->GetKey(0, "type");
1576 if (!typeStr || !strlen(typeStr)) return kFALSE;
1577 if (!strcmp(typeStr, "collection")) return kTRUE;
1578 delete res;
1579 return kFALSE;
1580}
1581
fe2d7fc2 1582//______________________________________________________________________________
1583Bool_t AliAnalysisAlien::IsSingleOutput() const
1584{
1585// Check if single-ouput option is on.
1586 return (!fOutputSingle.IsNull());
1587}
1588
16a4353c 1589//______________________________________________________________________________
1590void AliAnalysisAlien::Print(Option_t *) const
1591{
1592// Print current plugin settings.
84fcd93f 1593 printf("### AliEn analysis plugin current settings ###\n");
d3b18c4c 1594 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1595 if (mgr && mgr->IsProofMode()) {
1596 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1597 if (TestBit(AliAnalysisGrid::kTest))
1598 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1599 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1600 if (!fProofDataSet.IsNull())
1601 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1602 if (fProofReset==1)
1603 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1604 if (fProofReset>1)
1605 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1606 if (!fRootVersionForProof.IsNull())
1607 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1608 else
1609 printf("= ROOT version requested________________________ default\n");
1610 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1611 if (!fAliRootMode.IsNull())
1612 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1613 if (fNproofWorkers)
1614 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1615 if (fNproofWorkersPerSlave)
1616 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1617 if (TestSpecialBit(kClearPackages))
1618 printf("= ClearPackages requested...\n");
1619 if (fIncludePath.Data())
1620 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1621 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1622 if (fPackages && fPackages->GetEntries()) {
1623 TIter next(fPackages);
1624 TObject *obj;
1625 TString list;
1626 while ((obj=next())) list += obj->GetName();
1627 printf("= Par files to be used: ________________________ %s\n", list.Data());
1628 }
1629 if (TestSpecialBit(kProofConnectGrid))
1630 printf("= Requested PROOF connection to grid\n");
1631 return;
1632 }
e1c22e21 1633 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1634 if (fOverwriteMode) {
1635 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1636 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1637 }
348be253 1638 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1639 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
84fcd93f 1640 printf("= Production mode:______________________________ %d\n", fProductionMode);
1641 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1642 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1643 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
16a4353c 1644 if (fUser.Length())
84fcd93f 1645 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1646 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1647 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1648 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1649 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1650 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
16a4353c 1651 if (fRunNumbers.Length())
84fcd93f 1652 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
16a4353c 1653 if (fRunRange[0])
5fce53f4 1654 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
16a4353c 1655 if (!fRunRange[0] && !fRunNumbers.Length()) {
1656 TIter next(fInputFiles);
1657 TObject *obj;
1658 TString list;
1659 while ((obj=next())) list += obj->GetName();
84fcd93f 1660 printf("= Input files to be processed: _________________ %s\n", list.Data());
16a4353c 1661 }
1662 if (TestBit(AliAnalysisGrid::kTest))
84fcd93f 1663 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1664 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1665 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1666 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
d3b18c4c 1667 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
84fcd93f 1668 printf("=====================================================================\n");
1669 printf("= Job price: ___________________________________ %d\n", fPrice);
1670 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1671 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
16a4353c 1672 if (fMaxInitFailed>0)
84fcd93f 1673 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
16a4353c 1674 if (fMasterResubmitThreshold>0)
84fcd93f 1675 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
149d288c 1676 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
319593fb 1677 if (fNrunsPerMaster>0)
84fcd93f 1678 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1679 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
b5b9dee8 1680 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1681 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
16a4353c 1682 if (fArguments.Length())
84fcd93f 1683 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
631c0b05 1684 if (fExecutableArgs.Length())
1685 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
84fcd93f 1686 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1687 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1688 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1689 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
16a4353c 1690 if (fDatasetName)
84fcd93f 1691 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1692 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
16a4353c 1693 if (fIncludePath.Data())
84fcd93f 1694 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
16a4353c 1695 if (fCloseSE.Length())
84fcd93f 1696 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
16a4353c 1697 if (fFriendChainName.Length())
84fcd93f 1698 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
d3b18c4c 1699 if (fPackages && fPackages->GetEntries()) {
16a4353c 1700 TIter next(fPackages);
1701 TObject *obj;
1702 TString list;
1703 while ((obj=next())) list += obj->GetName();
84fcd93f 1704 printf("= Par files to be used: ________________________ %s\n", list.Data());
16a4353c 1705 }
1706}
1707
c57f56b7 1708//______________________________________________________________________________
1709void AliAnalysisAlien::SetDefaults()
1710{
1711// Set default values for everything. What cannot be filled will be left empty.
1712 if (fGridJDL) delete fGridJDL;
1713 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 1714 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
c57f56b7 1715 fPrice = 1;
1716 fTTL = 30000;
1717 fSplitMaxInputFileNumber = 100;
1718 fMaxInitFailed = 0;
1719 fMasterResubmitThreshold = 0;
bb885a9e 1720 fNtestFiles = 10;
149d288c 1721 fNreplicas = 2;
a8739e8a 1722 fRunRange[0] = 0;
1723 fRunRange[1] = 0;
319593fb 1724 fNrunsPerMaster = 1;
16a4353c 1725 fMaxMergeFiles = 100;
c57f56b7 1726 fRunNumbers = "";
1727 fExecutable = "analysis.sh";
0a1c1f7f 1728 fExecutableCommand = "root -b -q";
c57f56b7 1729 fArguments = "";
631c0b05 1730 fExecutableArgs = "";
c57f56b7 1731 fAnalysisMacro = "myAnalysis.C";
1732 fAnalysisSource = "";
1733 fAdditionalLibs = "";
1734 fSplitMode = "se";
1735 fAPIVersion = "";
1736 fROOTVersion = "";
1737 fAliROOTVersion = "";
1738 fUser = ""; // Your alien user name
1739 fGridWorkingDir = "";
1740 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1741 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
0df6ccf2 1742 fFriendChainName = "";
c57f56b7 1743 fGridOutputDir = "output";
149d288c 1744 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
c57f56b7 1745 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1746 fInputFormat = "xml-single";
1747 fJDLName = "analysis.jdl";
c6cb3634 1748 fJobTag = "Automatically generated analysis JDL";
bb885a9e 1749 fMergeExcludes = "";
0f389141 1750 fMergeViaJDL = 0;
348be253 1751 SetUseCopy(kTRUE);
1752 SetCheckCopy(kTRUE);
149d288c 1753 SetDefaultOutputs(kTRUE);
e1c22e21 1754 fOverwriteMode = 1;
c57f56b7 1755}
1756
0f389141 1757//______________________________________________________________________________
7c2cd90a 1758Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, Bool_t submit, const char *jdl)
0f389141 1759{
7c2cd90a 1760// Static method that checks the status of merging. This can submit merging jobs that did not produced the expected
1761// output. If <submit> is false (checking) returns true only when the final merged file was found. If submit is true returns
1762// true if the jobs were successfully submitted.
1763 Int_t countOrig = 0;
1764 Int_t countStage = 0;
1765 Int_t stage = 0;
1766 Int_t i;
1767 Bool_t doneFinal = kFALSE;
1768 TBits chunksDone;
1769 TString saliendir(aliendir);
1770 TString sfilename, stmp;
1771 saliendir.ReplaceAll("//","/");
1772 saliendir = saliendir.Strip(TString::kTrailing, '/');
1773 if (!gGrid) {
1774 ::Error("GetNregisteredFiles", "You need to be connected to AliEn.");
1775 return kFALSE;
1776 }
0cdf65a8 1777 sfilename = filename;
1778 sfilename.ReplaceAll(".root", "*.root");
1779 printf("Checking directory <%s> for merged files <%s> ...\n", aliendir, sfilename.Data());
1780 TString command = Form("find %s/ *%s", saliendir.Data(), sfilename.Data());
7c2cd90a 1781 TGridResult *res = gGrid->Command(command);
1782 if (!res) {
1783 ::Error("GetNregisteredFiles","Error: No result for the find command\n");
1784 return kFALSE;
1785 }
1786 TIter nextmap(res);
1787 TMap *map = 0;
1788 while ((map=(TMap*)nextmap())) {
1789 TString turl = map->GetValue("turl")->GetName();
1790 if (!turl.Length()) {
1791 // Nothing found
1792 delete res;
1793 return kFALSE;
1794 }
1795 turl.ReplaceAll("alien://", "");
1796 turl.ReplaceAll(saliendir, "");
1797 sfilename = gSystem->BaseName(turl);
0cdf65a8 1798 turl = turl.Strip(TString::kLeading, '/');
7c2cd90a 1799 // Now check to what the file corresponds to:
1800 // original output - aliendir/%03d/filename
1801 // merged file (which stage) - aliendir/filename-Stage%02d_%04d
1802 // final merged file - aliendir/filename
1803 if (sfilename == turl) {
1804 if (sfilename == filename) {
1805 doneFinal = kTRUE;
1806 } else {
1807 // check stage
1808 Int_t index = sfilename.Index("Stage");
1809 if (index<0) continue;
1810 stmp = sfilename(index+5,2);
1811 Int_t istage = atoi(stmp);
1812 stmp = sfilename(index+8,4);
1813 Int_t ijob = atoi(stmp);
1814 if (istage<stage) continue; // Ignore lower stages
1815 if (istage>stage) {
1816 countStage = 0;
1817 chunksDone.ResetAllBits();
1818 stage = istage;
1819 }
1820 countStage++;
1821 chunksDone.SetBitNumber(ijob);
1822 }
1823 } else {
1824 countOrig++;
1825 }
1826 if (doneFinal) {
1827 delete res;
0cdf65a8 1828 printf("=> Removing files from previous stages...\n");
1829 gGrid->Rm(Form("%s/*Stage*.root", aliendir));
7a62d541 1830 for (i=1; i<stage; i++)
1831 gGrid->Rm(Form("%s/*Stage%d*.zip", aliendir, i));
7c2cd90a 1832 return kTRUE;
1833 }
1834 }
1835 delete res;
1836 // Compute number of jobs that were submitted for the current stage
1837 Int_t ntotstage = countOrig;
7ae54d70 1838 for (i=1; i<=stage; i++) {
1839 if (ntotstage%nperchunk) ntotstage = (ntotstage/nperchunk)+1;
1840 else ntotstage = (ntotstage/nperchunk);
1841 }
7c2cd90a 1842 // Now compare with the number of set bits in the chunksDone array
1843 Int_t nmissing = (stage>0)?(ntotstage - countStage):0;
1844 // Print the info
1845 printf("*** Found %d original files\n", countOrig);
1846 if (stage==0) printf("*** No merging completed so far.\n");
1847 else printf("*** Found %d out of %d files merged for stage %d\n", countStage, ntotstage, stage);
1848 if (nmissing) printf("*** Number of merged files missing for this stage: %d -> check merging job completion\n", nmissing);
7c2cd90a 1849 if (!submit) return doneFinal;
1850 // Sumbit merging jobs for all missing chunks for the current stage.
1851 TString query = Form("submit %s %s", jdl, aliendir);
1852 Int_t ichunk = -1;
1853 if (nmissing) {
1854 for (i=0; i<nmissing; i++) {
1855 ichunk = chunksDone.FirstNullBit(ichunk+1);
1856 Int_t jobId = SubmitSingleJob(Form("%s %d %d", query.Data(), stage, ichunk));
1857 if (!jobId) return kFALSE;
1858 }
1859 return kTRUE;
1860 }
1861 // Submit next stage of merging
1862 if (stage==0) countStage = countOrig;
7ae54d70 1863 Int_t nchunks = (countStage/nperchunk);
1864 if (countStage%nperchunk) nchunks += 1;
7c2cd90a 1865 for (i=0; i<nchunks; i++) {
1866 Int_t jobId = SubmitSingleJob(Form("%s %d %d", query.Data(), stage+1, i));
1867 if (!jobId) return kFALSE;
1868 }
1869 return kTRUE;
1870}
1871
1872//______________________________________________________________________________
1873Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1874{
1875// Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1876 if (!gGrid) return 0;
1877 printf("=> %s ------> ",query);
1878 TGridResult *res = gGrid->Command(query);
1879 if (!res) return 0;
1880 TString jobId = res->GetKey(0,"jobId");
1881 delete res;
1882 if (jobId.IsNull()) {
1883 printf("submission failed. Reason:\n");
1884 gGrid->Stdout();
1885 gGrid->Stderr();
1886 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
1887 return 0;
1888 }
1889 printf(" Job id: %s\n", jobId.Data());
1890 return atoi(jobId);
1891}
1892
1893//______________________________________________________________________________
1894Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage, Int_t ichunk)
1895{
1896// Merge given output files from basedir. The file merger will merge nmaxmerge
1897// files in a group. Merging can be done in stages:
1898// stage=0 : will merge all existing files in a single stage
1899// stage=1 : does a find command for all files that do NOT contain the string "Stage".
1900// If their number is bigger that nmaxmerge, only the files from
1901// ichunk*nmaxmerge to ichunk*(nmaxmerge+1)-1 will get merged as output_stage_<ichunk>
1902// stage=n : does a find command for files named <output>Stage<stage-1>_*. If their number is bigger than
1903// nmaxmerge, merge just the chunk ichunk, otherwise write the merged output to the file
1904// named <output>.
a2f5fc01 1905 TString outputFile = output;
0f389141 1906 TString command;
a2f5fc01 1907 TString outputChunk;
1908 TString previousChunk = "";
1909 Int_t countChunk = 0;
1910 Int_t countZero = nmaxmerge;
0f389141 1911 Bool_t merged = kTRUE;
a2f5fc01 1912 Int_t index = outputFile.Index("@");
1913 if (index > 0) outputFile.Remove(index);
7c2cd90a 1914 TString inputFile = outputFile;
1915 if (stage>1) inputFile.ReplaceAll(".root", Form("-Stage%02d_*.root", stage-1));
1916 command = Form("find %s/ *%s", basedir, inputFile.Data());
0f389141 1917 printf("command: %s\n", command.Data());
1918 TGridResult *res = gGrid->Command(command);
1919 if (!res) {
7c2cd90a 1920 ::Error("MergeOutput","No result for the find command\n");
0f389141 1921 return kFALSE;
1922 }
1923
1924 TFileMerger *fm = 0;
1925 TIter nextmap(res);
1926 TMap *map = 0;
7c2cd90a 1927 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
a2f5fc01 1928 outputChunk = outputFile;
1929 outputChunk.ReplaceAll(".root", "_*.root");
0f389141 1930 // Check for existent temporary merge files
e1c22e21 1931 // Check overwrite mode and remove previous partial results if needed
7c2cd90a 1932 // Preserve old merging functionality for stage 0.
1933 if (stage==0) {
1934 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
1935 while (1) {
1936 // Skip as many input files as in a chunk
1937 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1938 if (!map) {
1939 ::Error("MergeOutput", "Cannot resume merging for <%s>, nentries=%d", outputFile.Data(), res->GetSize());
1940 delete res;
1941 return kFALSE;
1942 }
1943 outputChunk = outputFile;
1944 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
1945 countChunk++;
1946 if (gSystem->AccessPathName(outputChunk)) continue;
1947 // Merged file with chunks up to <countChunk> found
1948 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
1949 previousChunk = outputChunk;
1950 break;
1951 }
1952 }
1953 countZero = nmaxmerge;
1954
1955 while ((map=(TMap*)nextmap())) {
1956 // Loop 'find' results and get next LFN
1957 if (countZero == nmaxmerge) {
1958 // First file in chunk - create file merger and add previous chunk if any.
1959 fm = new TFileMerger(kFALSE);
1960 fm->SetFastMethod(kTRUE);
1961 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
1962 outputChunk = outputFile;
1963 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
1964 }
1965 // If last file found, put merged results in the output file
1966 if (map == res->Last()) outputChunk = outputFile;
1967 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1968 if (!objs || !objs->GetString().Length()) {
1969 // Nothing found - skip this output
0f389141 1970 delete res;
7c2cd90a 1971 delete fm;
0f389141 1972 return kFALSE;
7c2cd90a 1973 }
1974 // Add file to be merged and decrement chunk counter.
1975 fm->AddFile(objs->GetString());
1976 countZero--;
1977 if (countZero==0 || map == res->Last()) {
1978 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1979 // Nothing found - skip this output
1980 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
1981 delete res;
1982 delete fm;
1983 return kFALSE;
1984 }
1985 fm->OutputFile(outputChunk);
1986 // Merge the outputs, then go to next chunk
1987 if (!fm->Merge()) {
1988 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
1989 delete res;
1990 delete fm;
1991 return kFALSE;
1992 } else {
1993 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
1994 gSystem->Unlink(previousChunk);
1995 }
1996 if (map == res->Last()) {
1997 delete res;
1998 delete fm;
1999 break;
2000 }
2001 countChunk++;
2002 countZero = nmaxmerge;
2003 previousChunk = outputChunk;
0f389141 2004 }
0f389141 2005 }
7c2cd90a 2006 return merged;
2007 }
2008 // Merging stage different than 0.
2009 // Move to the begining of the requested chunk.
2010 outputChunk = outputFile;
2011 if (nmaxmerge < res->GetSize()) {
2012 if (ichunk*nmaxmerge >= res->GetSize()) {
2013 ::Error("MergeOutput", "Cannot merge merge chunk %d grouping %d files from %d total.", ichunk, nmaxmerge, res->GetSize());
2014 delete res;
2015 return kFALSE;
2016 }
8a8f17bb 2017 for (Int_t counter=0; counter<ichunk*nmaxmerge; counter++) nextmap();
7c2cd90a 2018 outputChunk.ReplaceAll(".root", Form("-Stage%02d_%04d.root", stage, ichunk));
2019 }
2020 countZero = nmaxmerge;
2021 fm = new TFileMerger(kFALSE);
2022 fm->SetFastMethod(kTRUE);
0f389141 2023 while ((map=(TMap*)nextmap())) {
7c2cd90a 2024 // Loop 'find' results and get next LFN
0f389141 2025 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2026 if (!objs || !objs->GetString().Length()) {
2027 // Nothing found - skip this output
2028 delete res;
2029 delete fm;
2030 return kFALSE;
2031 }
2032 // Add file to be merged and decrement chunk counter.
2033 fm->AddFile(objs->GetString());
a2f5fc01 2034 countZero--;
7c2cd90a 2035 if (countZero==0) break;
2036 }
2037 delete res;
2038 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2039 // Nothing found - skip this output
2040 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2041 delete fm;
2042 return kFALSE;
2043 }
2044 fm->OutputFile(outputChunk);
2045 // Merge the outputs
2046 if (!fm->Merge()) {
2047 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2048 delete fm;
2049 return kFALSE;
2050 } else {
2051 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
0f389141 2052 }
7c2cd90a 2053 delete fm;
2054 return kTRUE;
0f389141 2055}
2056
c57f56b7 2057//______________________________________________________________________________
2058Bool_t AliAnalysisAlien::MergeOutputs()
2059{
2060// Merge analysis outputs existing in the AliEn space.
2061 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2062 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2063 if (!Connect()) {
2064 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2065 return kFALSE;
0f389141 2066 }
c9e8f7fd 2067 if (fMergeViaJDL) {
2068 if (!TestBit(AliAnalysisGrid::kMerge)) {
2069 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2070 return kFALSE;
2071 }
2072 if (fProductionMode) {
2073 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2074 return kFALSE;
2075 }
0f389141 2076 Info("MergeOutputs", "Submitting merging JDL");
a03be957 2077 if (!SubmitMerging()) return kFALSE;
0f389141 2078 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
c9e8f7fd 2079 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
001cb79e 2080 return kFALSE;
c57f56b7 2081 }
2082 // Get the output path
d2a409b2 2083 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
923e2ca5 2084 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 2085 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2086 return kFALSE;
2087 }
2088 if (!fOutputFiles.Length()) {
2089 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2090 return kFALSE;
0f389141 2091 }
2092 // Check if fast read option was requested
e1c22e21 2093 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2094 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
0f389141 2095 if (fFastReadOption) {
d3339be3 2096 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2097 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2098 gEnv->SetValue("XNet.ConnectTimeout",10);
2099 gEnv->SetValue("XNet.RequestTimeout",10);
0f389141 2100 gEnv->SetValue("XNet.MaxRedirectCount",2);
d3339be3 2101 gEnv->SetValue("XNet.ReconnectTimeout",10);
0f389141 2102 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
c57f56b7 2103 }
e8b839ab 2104 // Make sure we change the temporary directory
2105 gSystem->Setenv("TMPDIR", gSystem->pwd());
149d288c 2106 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2107 TIter next(list);
2108 TObjString *str;
a2f5fc01 2109 TString outputFile;
c57f56b7 2110 Bool_t merged = kTRUE;
2111 while((str=(TObjString*)next())) {
a2f5fc01 2112 outputFile = str->GetString();
2113 Int_t index = outputFile.Index("@");
2114 if (index > 0) outputFile.Remove(index);
2115 TString outputChunk = outputFile;
2116 outputChunk.ReplaceAll(".root", "_*.root");
319593fb 2117 // Skip already merged outputs
a2f5fc01 2118 if (!gSystem->AccessPathName(outputFile)) {
e1c22e21 2119 if (fOverwriteMode) {
a2f5fc01 2120 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2121 gSystem->Unlink(outputFile);
2122 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2123 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2124 outputChunk.Data());
2125 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2126 }
2127 } else {
a2f5fc01 2128 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
e1c22e21 2129 continue;
2130 }
2131 } else {
a2f5fc01 2132 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2133 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2134 outputChunk.Data());
2135 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2136 }
2137 }
bb885a9e 2138 if (fMergeExcludes.Length() &&
a2f5fc01 2139 fMergeExcludes.Contains(outputFile.Data())) continue;
16a4353c 2140 // Perform a 'find' command in the output directory, looking for registered outputs
a2f5fc01 2141 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
0f389141 2142 if (!merged) {
2143 Error("MergeOutputs", "Terminate() will NOT be executed");
2144 return kFALSE;
ff07ec61 2145 }
2146 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2147 if (fileOpened) fileOpened->Close();
c57f56b7 2148 }
0f389141 2149 return kTRUE;
c57f56b7 2150}
2151
bb885a9e 2152//______________________________________________________________________________
2153void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2154{
2155// Use the output files connected to output containers from the analysis manager
2156// rather than the files defined by SetOutputFiles
2157 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
205b201f 2158 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
bb885a9e 2159 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2160}
2161
149d288c 2162//______________________________________________________________________________
2163void AliAnalysisAlien::SetOutputFiles(const char *list)
2164{
2165// Manually set the output files list.
2166// Removes duplicates. Not allowed if default outputs are not disabled.
2167 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2168 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2169 return;
2170 }
2171 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2172 fOutputFiles = "";
2173 TString slist = list;
2174 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2175 TObjArray *arr = slist.Tokenize(" ");
2176 TObjString *os;
2177 TIter next(arr);
2178 TString sout;
2179 while ((os=(TObjString*)next())) {
2180 sout = os->GetString();
2181 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2182 if (fOutputFiles.Contains(sout)) continue;
2183 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2184 fOutputFiles += sout;
2185 }
2186 delete arr;
f790bc1b 2187}
149d288c 2188
2189//______________________________________________________________________________
2190void AliAnalysisAlien::SetOutputArchive(const char *list)
2191{
2192// Manually set the output archive list. Free text - you are on your own...
2193// Not allowed if default outputs are not disabled.
2194 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2195 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2196 return;
2197 }
2198 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2199 fOutputArchive = list;
2200}
2201
2202//______________________________________________________________________________
2203void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2204{
2205// Setting a prefered output SE is not allowed anymore.
2206 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2207}
2208
5513444a 2209//______________________________________________________________________________
2210Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
c57f56b7 2211{
2212// Start remote grid analysis.
3bdcb562 2213 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2214 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2215 if (!mgr || !mgr->IsInitialized()) {
2216 Error("StartAnalysis", "You need an initialized analysis manager for this");
2217 return kFALSE;
2218 }
2219 // Are we in PROOF mode ?
2220 if (mgr->IsProofMode()) {
90d50a8c 2221 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3bdcb562 2222 if (fProofCluster.IsNull()) {
2223 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2224 return kFALSE;
2225 }
2226 if (fProofDataSet.IsNull() && !testMode) {
2227 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2228 return kFALSE;
2229 }
2230 // Set the needed environment
2231 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2232 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2233 if (fProofReset && !testMode) {
2234 if (fProofReset==1) {
2235 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2236 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2237 } else {
2238 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2239 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2240 }
2241 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2242 return kFALSE;
2243 }
2244 // Do we need to change the ROOT version ? The success of this cannot be checked.
2245 if (!fRootVersionForProof.IsNull() && !testMode) {
2246 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2247 fProofCluster.Data(), fRootVersionForProof.Data()));
2248 }
2249 // Connect to PROOF and check the status
2250 Long_t proof = 0;
27734f0e 2251 TString sworkers;
2252 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2253 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3bdcb562 2254 if (!testMode) {
27734f0e 2255 if (!sworkers.IsNull())
2256 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3bdcb562 2257 else
2258 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2259 } else {
2260 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2261 if (!proof) {
2262 Error("StartAnalysis", "Could not start PROOF in test mode");
2263 return kFALSE;
2264 }
2265 }
2266 if (!proof) {
2267 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2268 return kFALSE;
2269 }
27734f0e 2270 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2271 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3bdcb562 2272 // Is dataset existing ?
2273 if (!testMode) {
2274 TString dataset = fProofDataSet;
2275 Int_t index = dataset.Index("#");
2276 if (index>=0) dataset.Remove(index);
830acc4c 2277// if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2278// Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2279// return kFALSE;
2280// }
2281// Info("StartAnalysis", "Dataset %s found", dataset.Data());
3bdcb562 2282 }
2283 // Is ClearPackages() needed ?
2284 if (TestSpecialBit(kClearPackages)) {
2285 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2286 gROOT->ProcessLine("gProof->ClearPackages();");
2287 }
2288 // Is a given aliroot mode requested ?
2289 TList optionsList;
1ac846e9 2290 TString parLibs;
830acc4c 2291 if (!fAliRootMode.IsNull()) {
3bdcb562 2292 TString alirootMode = fAliRootMode;
2293 if (alirootMode == "default") alirootMode = "";
2294 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2295 optionsList.SetOwner();
2296 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2297 // Check the additional libs to be loaded
2298 TString extraLibs;
1ac846e9 2299 Bool_t parMode = kFALSE;
3bdcb562 2300 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2301 // Parse the extra libs for .so
2302 if (fAdditionalLibs.Length()) {
2303 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2304 TIter next(list);
2305 TObjString *str;
1ac846e9 2306 while((str=(TObjString*)next())) {
2307 if (str->GetString().Contains(".so")) {
2308 if (parMode) {
2309 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());
2310 break;
2311 }
2312 TString stmp = str->GetName();
2313 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2314 stmp.ReplaceAll(".so","");
2315 if (!extraLibs.IsNull()) extraLibs += ":";
2316 extraLibs += stmp;
2317 continue;
2318 }
2319 if (str->GetString().Contains(".par")) {
2320 // The first par file found in the list will not allow any further .so
2321 parMode = kTRUE;
2322 if (!parLibs.IsNull()) parLibs += ":";
2323 parLibs += str->GetName();
2324 continue;
2325 }
3bdcb562 2326 }
2327 if (list) delete list;
2328 }
2329 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
830acc4c 2330 // Check extra includes
2331 if (!fIncludePath.IsNull()) {
2332 TString includePath = fIncludePath;
2333 includePath.ReplaceAll(" ",":");
2334 includePath.Strip(TString::kTrailing, ':');
2335 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2336 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2337 }
27734f0e 2338 // Check if connection to grid is requested
2339 if (TestSpecialBit(kProofConnectGrid))
2340 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
830acc4c 2341 // Enable AliRoot par
2342 if (testMode) {
2343 // Enable proof lite package
2344 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2345 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2346 TNamed *obj = (TNamed*)optionsList.At(i);
2347 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2348 }
2349 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2350 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)0x%lx);",alirootLite.Data(),(ULong_t)&optionsList))) {
2351 Info("StartAnalysis", "AliRootProofLite enabled");
2352 } else {
2353 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2354 return kFALSE;
2355 }
2356 } else {
2357 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)0x%lx);",
2358 fAliROOTVersion.Data(), (ULong_t)&optionsList))) {
2359 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2360 return kFALSE;
2361 }
27734f0e 2362 }
1ac846e9 2363 // Enable first par files from fAdditionalLibs
2364 if (!parLibs.IsNull()) {
2365 TObjArray *list = parLibs.Tokenize(":");
2366 TIter next(list);
2367 TObjString *package;
2368 while((package=(TObjString*)next())) {
2369 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2370 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2371 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2372 return kFALSE;
2373 }
2374 } else {
2375 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2376 return kFALSE;
2377 }
2378 }
2379 if (list) delete list;
2380 }
3bdcb562 2381 } else {
2382 if (fAdditionalLibs.Contains(".so") && !testMode) {
2383 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2384 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2385 return kFALSE;
2386 }
2387 }
2388 // Enable par files if requested
2389 if (fPackages && fPackages->GetEntries()) {
2390 TIter next(fPackages);
2391 TObject *package;
2392 while ((package=next())) {
1ac846e9 2393 // Skip packages already enabled
2394 if (parLibs.Contains(package->GetName())) continue;
3bdcb562 2395 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
27734f0e 2396 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3bdcb562 2397 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2398 return kFALSE;
2399 }
2400 } else {
2401 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2402 return kFALSE;
2403 }
2404 }
2405 }
2406 // Do we need to load analysis source files ?
2407 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2408 if (fAnalysisSource.Length()) {
2409 TObjArray *list = fAnalysisSource.Tokenize(" ");
2410 TIter next(list);
2411 TObjString *str;
2412 while((str=(TObjString*)next())) {
2413 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2414 }
2415 if (list) delete list;
2416 }
830acc4c 2417 if (testMode) {
2418 // Register dataset to proof lite.
2419 if (fFileForTestMode.IsNull()) {
2420 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2421 return kFALSE;
2422 }
2423 if (gSystem->AccessPathName(fFileForTestMode)) {
2424 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2425 return kFALSE;
2426 }
2427 TFileCollection *coll = new TFileCollection();
2428 coll->AddFromFile(fFileForTestMode);
27734f0e 2429 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)0x%lx, \"OV\");", (ULong_t)coll));
2430 gROOT->ProcessLine("gProof->ShowDataSets()");
830acc4c 2431 }
3bdcb562 2432 return kTRUE;
2433 }
c57f56b7 2434
43da816a 2435 // Check if output files have to be taken from the analysis manager
2436 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
f790bc1b 2437 // Add output files and AOD files
2438 fOutputFiles = GetListOfFiles("outaod");
c07b9ce2 2439 // Add extra files registered to the analysis manager
f790bc1b 2440 TString extra = GetListOfFiles("ext");
2441 if (!extra.IsNull()) {
149d288c 2442 extra.ReplaceAll(".root", "*.root");
f790bc1b 2443 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
149d288c 2444 fOutputFiles += extra;
84fcd93f 2445 }
149d288c 2446 // Compose the output archive.
2447 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2448 fOutputArchive += Form("root_archive.zip:%s@disk=%d",fOutputFiles.Data(),fNreplicas);
43da816a 2449 }
f7b1cbc2 2450// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
c57f56b7 2451 if (TestBit(AliAnalysisGrid::kOffline)) {
2452 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2453 \n there nor any job run. You can revise the JDL and analysis \
2454 \n macro then run the same in \"submit\" mode.");
2455 } else if (TestBit(AliAnalysisGrid::kTest)) {
2456 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2457 \n dataset.");
2458 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2459 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2460 \n space and job submitted.");
2461 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2462 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
0f389141 2463 if (fMergeViaJDL) CheckInputData();
5513444a 2464 return kTRUE;
c57f56b7 2465 } else {
2466 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2467 }
2468
348be253 2469 Print();
c57f56b7 2470 if (!Connect()) {
2471 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
5513444a 2472 return kFALSE;
16a4353c 2473 }
d3b18c4c 2474 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
c57f56b7 2475 if (!CheckInputData()) {
2476 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
5513444a 2477 return kFALSE;
c57f56b7 2478 }
d3339be3 2479 if (!CreateDataset(fDataPattern)) {
2480 TString serror;
2481 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2482 if (fRunNumbers.Length()) serror = "run numbers";
2483 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2484 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2485 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2486 return kFALSE;
2487 }
c57f56b7 2488 WriteAnalysisFile();
2489 WriteAnalysisMacro();
2490 WriteExecutable();
2491 WriteValidationScript();
0f389141 2492 if (fMergeViaJDL) {
2493 WriteMergingMacro();
2494 WriteMergeExecutable();
2495 WriteValidationScript(kTRUE);
2496 }
5513444a 2497 if (!CreateJDL()) return kFALSE;
2498 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3bdcb562 2499 if (testMode) {
c57f56b7 2500 // Locally testing the analysis
2501 Info("StartAnalysis", "\n_______________________________________________________________________ \
2502 \n Running analysis script in a daughter shell as on a worker node \
2503 \n_______________________________________________________________________");
149d288c 2504 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2505 TIter next(list);
2506 TObjString *str;
a2f5fc01 2507 TString outputFile;
c57f56b7 2508 while((str=(TObjString*)next())) {
a2f5fc01 2509 outputFile = str->GetString();
2510 Int_t index = outputFile.Index("@");
2511 if (index > 0) outputFile.Remove(index);
2512 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
c57f56b7 2513 }
2514 delete list;
2515 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
f50e4bc8 2516 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
c57f56b7 2517// gSystem->Exec("cat stdout");
5513444a 2518 return kFALSE;
c57f56b7 2519 }
5513444a 2520 // Check if submitting is managed by LPM manager
a3e84053 2521 if (fProductionMode) {
5513444a 2522 TString prodfile = fJDLName;
2523 prodfile.ReplaceAll(".jdl", ".prod");
2524 WriteProductionFile(prodfile);
2525 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2526 return kFALSE;
2527 }
a8739e8a 2528 // Submit AliEn job(s)
d2a409b2 2529 gGrid->Cd(fGridOutputDir);
a8739e8a 2530 TGridResult *res;
c57f56b7 2531 TString jobID = "";
d2a409b2 2532 if (!fRunNumbers.Length() && !fRunRange[0]) {
dd74a515 2533 // Submit a given xml or a set of runs
a8739e8a 2534 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
84fcd93f 2535 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
a8739e8a 2536 if (res) {
2537 const char *cjobId = res->GetKey(0,"jobId");
2538 if (!cjobId) {
a03be957 2539 gGrid->Stdout();
2540 gGrid->Stderr();
a8739e8a 2541 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
5513444a 2542 return kFALSE;
a8739e8a 2543 } else {
2544 Info("StartAnalysis", "\n_______________________________________________________________________ \
2545 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2546 \n_______________________________________________________________________",
2547 fJDLName.Data(), cjobId);
2548 jobID = cjobId;
2549 }
2550 delete res;
a03be957 2551 } else {
2552 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2553 return kFALSE;
a8739e8a 2554 }
2555 } else {
d2a409b2 2556 // Submit for a range of enumeration of runs.
a03be957 2557 if (!Submit()) return kFALSE;
c57f56b7 2558 }
a8739e8a 2559
c57f56b7 2560 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2561 \n You may exit at any time and terminate the job later using the option <terminate> \
2562 \n ##################################################################################", jobID.Data());
bb885a9e 2563 gSystem->Exec("aliensh");
5513444a 2564 return kTRUE;
c57f56b7 2565}
2566
f790bc1b 2567//______________________________________________________________________________
2568const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2569{
2570// Get a comma-separated list of output files of the requested type.
2571// Type can be (case unsensitive):
2572// aod - list of aod files (std, extensions and filters)
2573// out - list of output files connected to containers (but not aod's or extras)
2574// ext - list of extra files registered to the manager
2575// ter - list of files produced in terminate
2576 static TString files;
2577 files = "";
2578 TString stype = type;
2579 stype.ToLower();
2580 TString aodfiles, extra;
2581 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2582 if (!mgr) {
2583 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2584 return files.Data();
2585 }
2586 if (mgr->GetOutputEventHandler()) {
2587 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2588 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2589 if (!extraaod.IsNull()) {
2590 aodfiles += ",";
2591 aodfiles += extraaod;
2592 }
2593 }
2594 if (stype.Contains("aod")) {
2595 files = aodfiles;
2596 if (stype == "aod") return files.Data();
2597 }
2598 // Add output files that are not in the list of AOD files
2599 TString outputfiles = "";
2600 TIter next(mgr->GetOutputs());
2601 AliAnalysisDataContainer *output;
2602 const char *filename = 0;
2603 while ((output=(AliAnalysisDataContainer*)next())) {
2604 filename = output->GetFileName();
2605 if (!(strcmp(filename, "default"))) continue;
2606 if (outputfiles.Contains(filename)) continue;
2607 if (aodfiles.Contains(filename)) continue;
2608 if (!outputfiles.IsNull()) outputfiles += ",";
2609 outputfiles += filename;
2610 }
2611 if (stype.Contains("out")) {
2612 if (!files.IsNull()) files += ",";
2613 files += outputfiles;
2614 if (stype == "out") return files.Data();
2615 }
2616 // Add extra files registered to the analysis manager
2617 TString sextra;
2618 extra = mgr->GetExtraFiles();
2619 if (!extra.IsNull()) {
2620 extra.Strip();
2621 extra.ReplaceAll(" ", ",");
2622 TObjArray *fextra = extra.Tokenize(",");
2623 TIter nextx(fextra);
2624 TObject *obj;
2625 while ((obj=nextx())) {
2626 if (aodfiles.Contains(obj->GetName())) continue;
2627 if (outputfiles.Contains(obj->GetName())) continue;
2628 if (sextra.Contains(obj->GetName())) continue;
2629 if (!sextra.IsNull()) sextra += ",";
2630 sextra += obj->GetName();
2631 }
2632 delete fextra;
2633 if (stype.Contains("ext")) {
2634 if (!files.IsNull()) files += ",";
2635 files += sextra;
2636 }
2637 }
2638 if (stype == "ext") return files.Data();
2639 TString termfiles;
2640 if (!fTerminateFiles.IsNull()) {
2641 fTerminateFiles.Strip();
2642 fTerminateFiles.ReplaceAll(" ",",");
9c939f2b 2643 TObjArray *fextra = fTerminateFiles.Tokenize(",");
f790bc1b 2644 TIter nextx(fextra);
2645 TObject *obj;
2646 while ((obj=nextx())) {
2647 if (aodfiles.Contains(obj->GetName())) continue;
2648 if (outputfiles.Contains(obj->GetName())) continue;
2649 if (termfiles.Contains(obj->GetName())) continue;
2650 if (sextra.Contains(obj->GetName())) continue;
2651 if (!termfiles.IsNull()) termfiles += ",";
2652 termfiles += obj->GetName();
2653 }
2654 delete fextra;
2655 }
2656 if (stype.Contains("ter")) {
2657 if (!files.IsNull() && !termfiles.IsNull()) {
2658 files += ",";
2659 files += termfiles;
2660 }
2661 }
2662 return files.Data();
2663}
2664
d2a409b2 2665//______________________________________________________________________________
a03be957 2666Bool_t AliAnalysisAlien::Submit()
d2a409b2 2667{
2668// Submit all master jobs.
2669 Int_t nmasterjobs = fInputFiles->GetEntries();
2670 Long_t tshoot = gSystem->Now();
a03be957 2671 if (!fNsubmitted && !SubmitNext()) return kFALSE;
d2a409b2 2672 while (fNsubmitted < nmasterjobs) {
2673 Long_t now = gSystem->Now();
2674 if ((now-tshoot)>30000) {
2675 tshoot = now;
a03be957 2676 if (!SubmitNext()) return kFALSE;
d2a409b2 2677 }
2678 }
a03be957 2679 return kTRUE;
d2a409b2 2680}
2681
0f389141 2682//______________________________________________________________________________
a03be957 2683Bool_t AliAnalysisAlien::SubmitMerging()
0f389141 2684{
2685// Submit all merging jobs.
2686 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2687 gGrid->Cd(fGridOutputDir);
2688 TString mergeJDLName = fExecutable;
2689 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2690 Int_t ntosubmit = fInputFiles->GetEntries();
0f389141 2691 for (Int_t i=0; i<ntosubmit; i++) {
f866cba5 2692 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2693 runOutDir.ReplaceAll(".xml", "");
7c2cd90a 2694 if (fOutputToRunNo) {
2695 // The output directory is the run number
2696 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2697 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2698 } else {
2699 // The output directory is the master number in 3 digits format
2700 printf("### Submitting merging job for master <%03d>\n", i);
2701 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2702 }
2703 // Check now the number of merging stages.
2b222f7c 2704 TObjArray *list = fOutputFiles.Tokenize(",");
2705 TIter next(list);
2706 TObjString *str;
2707 TString outputFile;
2708 while((str=(TObjString*)next())) {
2709 outputFile = str->GetString();
2710 Int_t index = outputFile.Index("@");
2711 if (index > 0) outputFile.Remove(index);
2712 if (!fMergeExcludes.Contains(outputFile)) break;
2713 }
2714 delete list;
7c2cd90a 2715 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, kTRUE, mergeJDLName);
2716 if (!done) return kFALSE;
0f389141 2717 }
a03be957 2718 if (!ntosubmit) return kTRUE;
0f389141 2719 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
2720 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
2721 \n ##################################################################################");
2722 gSystem->Exec("aliensh");
a03be957 2723 return kTRUE;
0f389141 2724}
2725
d2a409b2 2726//______________________________________________________________________________
a03be957 2727Bool_t AliAnalysisAlien::SubmitNext()
d2a409b2 2728{
08d5b699 2729// Submit next bunch of master jobs if the queue is free. The first master job is
2730// submitted right away, while the next will not be unless the previous was split.
2731// The plugin will not submit new master jobs if there are more that 500 jobs in
2732// waiting phase.
d2a409b2 2733 static Bool_t iscalled = kFALSE;
2734 static Int_t firstmaster = 0;
2735 static Int_t lastmaster = 0;
2736 static Int_t npermaster = 0;
a03be957 2737 if (iscalled) return kTRUE;
d2a409b2 2738 iscalled = kTRUE;
2739 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2740 Int_t ntosubmit = 0;
2741 TGridResult *res;
2742 TString jobID = "";
3bdcb562 2743 Int_t nmasterjobs = fInputFiles->GetEntries();
2744 if (!fNsubmitted) {
2745 ntosubmit = 1;
2746 if (!IsUseSubmitPolicy()) {
90d50a8c 2747 if (nmasterjobs>5)
3bdcb562 2748 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2749 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2750 ntosubmit = nmasterjobs;
2751 }
2752 } else {
d2a409b2 2753 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
84fcd93f 2754 printf("=== master %d: %s\n", lastmaster, status.Data());
d2a409b2 2755 // If last master not split, just return
a03be957 2756 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
d2a409b2 2757 // No more than 100 waiting jobs
08d5b699 2758 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
d2a409b2 2759 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
08d5b699 2760 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
7586eedc 2761 if (!ntosubmit) ntosubmit = 1;
84fcd93f 2762 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
d2a409b2 2763 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2764 }
d2a409b2 2765 for (Int_t i=0; i<ntosubmit; i++) {
2766 // Submit for a range of enumeration of runs.
a03be957 2767 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
d2a409b2 2768 TString query;
cd11251e 2769 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2770 runOutDir.ReplaceAll(".xml", "");
2771 if (fOutputToRunNo)
2772 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2773 else
2774 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
84fcd93f 2775 printf("********* %s\n",query.Data());
d2a409b2 2776 res = gGrid->Command(query);
2777 if (res) {
98ca124f 2778 TString cjobId1 = res->GetKey(0,"jobId");
2779 if (!cjobId1.Length()) {
d2a409b2 2780 iscalled = kFALSE;
a03be957 2781 gGrid->Stdout();
2782 gGrid->Stderr();
2783 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2784 return kFALSE;
d2a409b2 2785 } else {
2786 Info("StartAnalysis", "\n_______________________________________________________________________ \
2787 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2788 \n_______________________________________________________________________",
98ca124f 2789 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
d2a409b2 2790 jobID += cjobId1;
2791 jobID += " ";
98ca124f 2792 lastmaster = cjobId1.Atoi();
d2a409b2 2793 if (!firstmaster) firstmaster = lastmaster;
2794 fNsubmitted++;
2795 }
2796 delete res;
a03be957 2797 } else {
2798 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2799 return kFALSE;
d2a409b2 2800 }
2801 }
2802 iscalled = kFALSE;
a03be957 2803 return kTRUE;
d2a409b2 2804}
2805
c57f56b7 2806//______________________________________________________________________________
2807void AliAnalysisAlien::WriteAnalysisFile()
2808{
f10e8481 2809// Write current analysis manager into the file <analysisFile>
2810 TString analysisFile = fExecutable;
2811 analysisFile.ReplaceAll(".sh", ".root");
c57f56b7 2812 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2813 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2814 if (!mgr || !mgr->IsInitialized()) {
2815 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2816 return;
2817 }
2818 // Check analysis type
2819 TObject *handler;
2820 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2821 handler = (TObject*)mgr->GetInputEventHandler();
2822 if (handler) {
2823 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2824 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2825 }
2826 TDirectory *cdir = gDirectory;
f10e8481 2827 TFile *file = TFile::Open(analysisFile, "RECREATE");
c57f56b7 2828 if (file) {
e16a394c 2829 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2830 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
fe2d7fc2 2831 // Unless merging makes no sense
2832 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
c57f56b7 2833 mgr->Write();
2834 delete file;
fe2d7fc2 2835 // Enable termination for local jobs
2836 mgr->SetSkipTerminate(kFALSE);
c57f56b7 2837 }
2838 if (cdir) cdir->cd();
f10e8481 2839 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
c57f56b7 2840 }
2841 Bool_t copy = kTRUE;
d3b18c4c 2842 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 2843 if (copy) {
2844 CdWork();
2845 TString workdir = gGrid->GetHomeDirectory();
2846 workdir += fGridWorkingDir;
d3b18c4c 2847 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
f10e8481 2848 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2849 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 2850 }
2851}
2852
2853//______________________________________________________________________________
2854void AliAnalysisAlien::WriteAnalysisMacro()
2855{
2856// Write the analysis macro that will steer the analysis in grid mode.
2857 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2858 ofstream out;
2859 out.open(fAnalysisMacro.Data(), ios::out);
2860 if (!out.good()) {
2861 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2862 return;
2863 }
5b273635 2864 Bool_t hasSTEERBase = kFALSE;
2865 Bool_t hasESD = kFALSE;
2866 Bool_t hasAOD = kFALSE;
2867 Bool_t hasANALYSIS = kFALSE;
2868 Bool_t hasANALYSISalice = kFALSE;
2869 Bool_t hasCORRFW = kFALSE;
c57f56b7 2870 TString func = fAnalysisMacro;
2871 TString type = "ESD";
2872 TString comment = "// Analysis using ";
2873 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2874 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2875 type = "AOD";
2876 comment += "AOD";
2877 }
0df6ccf2 2878 if (type!="AOD" && fFriendChainName!="") {
2879 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2880 return;
2881 }
c57f56b7 2882 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2883 else comment += " data";
2884 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2885 func.ReplaceAll(".C", "");
2886 out << "void " << func.Data() << "()" << endl;
2887 out << "{" << endl;
2888 out << comment.Data() << endl;
2889 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 2890 out << " TStopwatch timer;" << endl;
2891 out << " timer.Start();" << endl << endl;
13f0c00b 2892 // Change temp directory to current one
2893 out << "// Set temporary merging directory to current one" << endl;
2894 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
f790bc1b 2895 if (!fExecutableCommand.Contains("aliroot")) {
2896 out << "// load base root libraries" << endl;
2897 out << " gSystem->Load(\"libTree\");" << endl;
2898 out << " gSystem->Load(\"libGeom\");" << endl;
2899 out << " gSystem->Load(\"libVMC\");" << endl;
2900 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2901 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2902 }
d5c6455a 2903 if (fAdditionalRootLibs.Length()) {
47a4137d 2904 // in principle libtree /lib geom libvmc etc. can go into this list, too
2905 out << "// Add aditional libraries" << endl;
2906 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2907 TIter next(list);
2908 TObjString *str;
2909 while((str=(TObjString*)next())) {
2910 if (str->GetString().Contains(".so"))
2911 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
d5c6455a 2912 }
47a4137d 2913 if (list) delete list;
d5c6455a 2914 }
47a4137d 2915 out << "// include path" << endl;
2916 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2917 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
57377eb5 2918 out << "// Load analysis framework libraries" << endl;
652561d5 2919 TString setupPar = "AliAnalysisAlien::SetupPar";
4e5c5506 2920 if (!fPackages) {
f790bc1b 2921 if (!fExecutableCommand.Contains("aliroot")) {
2922 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2923 out << " gSystem->Load(\"libESD\");" << endl;
2924 out << " gSystem->Load(\"libAOD\");" << endl;
2925 }
4e5c5506 2926 out << " gSystem->Load(\"libANALYSIS\");" << endl;
57377eb5 2927 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2928 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 2929 } else {
4e5c5506 2930 TIter next(fPackages);
2931 TObject *obj;
57377eb5 2932 TString pkgname;
57377eb5 2933 while ((obj=next())) {
2934 pkgname = obj->GetName();
4478e6f1 2935 if (pkgname == "STEERBase" ||
2936 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2937 if (pkgname == "ESD" ||
2938 pkgname == "ESD.par") hasESD = kTRUE;
2939 if (pkgname == "AOD" ||
2940 pkgname == "AOD.par") hasAOD = kTRUE;
2941 if (pkgname == "ANALYSIS" ||
2942 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2943 if (pkgname == "ANALYSISalice" ||
2944 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2945 if (pkgname == "CORRFW" ||
2946 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
5b273635 2947 }
2948 if (hasANALYSISalice) setupPar = "SetupPar";
57377eb5 2949 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 2950 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
57377eb5 2951 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 2952 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
57377eb5 2953 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 2954 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
57377eb5 2955 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 2956 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
57377eb5 2957 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 2958 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
57377eb5 2959 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 2960 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
57377eb5 2961 out << "// Compile other par packages" << endl;
2962 next.Reset();
fcc9bb6f 2963 while ((obj=next())) {
2964 pkgname = obj->GetName();
4478e6f1 2965 if (pkgname == "STEERBase" ||
2966 pkgname == "STEERBase.par" ||
2967 pkgname == "ESD" ||
2968 pkgname == "ESD.par" ||
2969 pkgname == "AOD" ||
2970 pkgname == "AOD.par" ||
2971 pkgname == "ANALYSIS" ||
2972 pkgname == "ANALYSIS.par" ||
2973 pkgname == "ANALYSISalice" ||
2974 pkgname == "ANALYSISalice.par" ||
2975 pkgname == "CORRFW" ||
2976 pkgname == "CORRFW.par") continue;
5b273635 2977 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 2978 }
4e5c5506 2979 }
6da75e0b 2980 if (fAdditionalLibs.Length()) {
2981 out << "// Add aditional AliRoot libraries" << endl;
2982 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2983 TIter next(list);
2984 TObjString *str;
2985 while((str=(TObjString*)next())) {
2986 if (str->GetString().Contains(".so"))
2987 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
652561d5 2988 if (str->GetString().Contains(".par"))
2989 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
6da75e0b 2990 }
2991 if (list) delete list;
2992 }
2993 out << endl;
c57f56b7 2994 out << "// analysis source to be compiled at runtime (if any)" << endl;
2995 if (fAnalysisSource.Length()) {
2996 TObjArray *list = fAnalysisSource.Tokenize(" ");
2997 TIter next(list);
2998 TObjString *str;
2999 while((str=(TObjString*)next())) {
3000 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3001 }
3002 if (list) delete list;
3003 }
3004 out << endl;
0f389141 3005 if (fFastReadOption) {
d3339be3 3006 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 !!! \
3007 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
0f389141 3008 out << "// fast xrootd reading enabled" << endl;
3009 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 3010 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
f790bc1b 3011 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
0f389141 3012 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
f790bc1b 3013 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
0f389141 3014 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3015 }
c57f56b7 3016 out << "// connect to AliEn and make the chain" << endl;
3017 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
c57f56b7 3018 out << "// read the analysis manager from file" << endl;
f10e8481 3019 TString analysisFile = fExecutable;
3020 analysisFile.ReplaceAll(".sh", ".root");
3021 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
c57f56b7 3022 out << " if (!file) return;" << endl;
3023 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3024 out << " AliAnalysisManager *mgr = 0;" << endl;
3025 out << " TKey *key;" << endl;
3026 out << " while ((key=(TKey*)nextkey())) {" << endl;
3027 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3028 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3029 out << " };" << endl;
3030 out << " if (!mgr) {" << endl;
205b201f 3031 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
c57f56b7 3032 out << " return;" << endl;
3033 out << " }" << endl << endl;
3034 out << " mgr->PrintStatus();" << endl;
52b6a92b 3035 if (AliAnalysisManager::GetAnalysisManager()) {
f866cba5 3036 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
52b6a92b 3037 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
de52b69c 3038 } else {
9a8288ff 3039 if (TestBit(AliAnalysisGrid::kTest))
3040 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3041 else
3042 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
52b6a92b 3043 }
3044 }
242accb2 3045 if (IsUsingTags()) {
3046 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3047 } else {
3048 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3049 }
c57f56b7 3050 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 3051 out << " timer.Stop();" << endl;
3052 out << " timer.Print();" << endl;
c57f56b7 3053 out << "}" << endl << endl;
3054 if (IsUsingTags()) {
3055 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3056 out << "{" << endl;
3057 out << "// Create a chain using tags from the xml file." << endl;
3058 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3059 out << " if (!coll) {" << endl;
3060 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3061 out << " return NULL;" << endl;
3062 out << " }" << endl;
3063 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3064 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3065 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3066 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3067 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3068 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3069 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3070 out << " // Check if the cuts configuration file was provided" << endl;
3071 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3072 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3073 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3074 out << " }" << endl;
0df6ccf2 3075 if (fFriendChainName=="") {
3076 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3077 } else {
3078 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3079 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3080 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3081 }
c57f56b7 3082 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3083 out << " chain->ls();" << endl;
3084 out << " return chain;" << endl;
fcc9bb6f 3085 out << "}" << endl << endl;
c57f56b7 3086 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3087 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3088 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3089 msg += " AliLHCTagCuts *lhcCuts,\n";
3090 msg += " AliDetectorTagCuts *detCuts,\n";
3091 msg += " AliEventTagCuts *evCuts)";
23329835 3092 Info("WriteAnalysisMacro", "%s", msg.Data());
c57f56b7 3093 }
0df6ccf2 3094 }
3095 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 3096 out <<"//________________________________________________________________________________" << endl;
c57f56b7 3097 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3098 out << "{" << endl;
3099 out << "// Create a chain using url's from xml file" << endl;
242accb2 3100 out << " TString filename;" << endl;
3101 out << " Int_t run = 0;" << endl;
c57f56b7 3102 out << " TString treename = type;" << endl;
3103 out << " treename.ToLower();" << endl;
3104 out << " treename += \"Tree\";" << endl;
e02fee64 3105 out << " printf(\"***************************************\\n\");" << endl;
3106 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3107 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 3108 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3109 out << " if (!coll) {" << endl;
3110 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3111 out << " return NULL;" << endl;
3112 out << " }" << endl;
242accb2 3113 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
c57f56b7 3114 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 3115 if(fFriendChainName!="") {
3116 out << " TChain *chainFriend = new TChain(treename);" << endl;
3117 }
c57f56b7 3118 out << " coll->Reset();" << endl;
0df6ccf2 3119 out << " while (coll->Next()) {" << endl;
242accb2 3120 out << " filename = coll->GetTURL("");" << endl;
3121 out << " if (mgr) {" << endl;
3122 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3123 out << " if (nrun && nrun != run) {" << endl;
3124 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3125 out << " mgr->SetRunFromPath(nrun);" << endl;
3126 out << " run = nrun;" << endl;
3127 out << " }" << endl;
3128 out << " }" << endl;
3129 out << " chain->Add(filename);" << endl;
0df6ccf2 3130 if(fFriendChainName!="") {
3131 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3132 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3133 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3134 out << " chainFriend->Add(fileFriend.Data());" << endl;
3135 }
3136 out << " }" << endl;
c57f56b7 3137 out << " if (!chain->GetNtrees()) {" << endl;
3138 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3139 out << " return NULL;" << endl;
3140 out << " }" << endl;
0df6ccf2 3141 if(fFriendChainName!="") {
3142 out << " chain->AddFriend(chainFriend);" << endl;
3143 }
c57f56b7 3144 out << " return chain;" << endl;
fcc9bb6f 3145 out << "}" << endl << endl;
c57f56b7 3146 }
5b273635 3147 if (hasANALYSISalice) {
3148 out <<"//________________________________________________________________________________" << endl;
3149 out << "Bool_t SetupPar(const char *package) {" << endl;
3150 out << "// Compile the package and set it up." << endl;
3151 out << " TString pkgdir = package;" << endl;
3152 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3153 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3154 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3155 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3156 out << " // Check for BUILD.sh and execute" << endl;
3157 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3158 out << " printf(\"*******************************\\n\");" << endl;
3159 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3160 out << " printf(\"*******************************\\n\");" << endl;
3161 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3162 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3163 out << " gSystem->ChangeDirectory(cdir);" << endl;
3164 out << " return kFALSE;" << endl;
3165 out << " }" << endl;
3166 out << " } else {" << endl;
3167 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3168 out << " gSystem->ChangeDirectory(cdir);" << endl;
3169 out << " return kFALSE;" << endl;
3170 out << " }" << endl;
3171 out << " // Check for SETUP.C and execute" << endl;
3172 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3173 out << " printf(\"*******************************\\n\");" << endl;
3174 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3175 out << " printf(\"*******************************\\n\");" << endl;
3176 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3177 out << " } else {" << endl;
3178 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3179 out << " gSystem->ChangeDirectory(cdir);" << endl;
3180 out << " return kFALSE;" << endl;
3181 out << " }" << endl;
3182 out << " // Restore original workdir" << endl;
3183 out << " gSystem->ChangeDirectory(cdir);" << endl;
3184 out << " return kTRUE;" << endl;
3185 out << "}" << endl;
3186 }
c57f56b7 3187 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3188 }
3189 Bool_t copy = kTRUE;
d3b18c4c 3190 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3191 if (copy) {
3192 CdWork();
3193 TString workdir = gGrid->GetHomeDirectory();
3194 workdir += fGridWorkingDir;
3195 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3196 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3197 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3198 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3199 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3200 }
3201 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3202 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3203 }
3204}
3205
0f389141 3206//______________________________________________________________________________
3207void AliAnalysisAlien::WriteMergingMacro()
3208{
3209// Write a macro to merge the outputs per master job.
3210 if (!fMergeViaJDL) return;
3211 if (!fOutputFiles.Length()) {
3212 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3213 return;
3214 }
3215 TString mergingMacro = fExecutable;
3216 mergingMacro.ReplaceAll(".sh","_merge.C");
3217 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3218 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3219 ofstream out;
3220 out.open(mergingMacro.Data(), ios::out);
3221 if (!out.good()) {
3222 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3223 return;
3224 }
5b273635 3225 Bool_t hasSTEERBase = kFALSE;
3226 Bool_t hasESD = kFALSE;
3227 Bool_t hasAOD = kFALSE;
3228 Bool_t hasANALYSIS = kFALSE;
3229 Bool_t hasANALYSISalice = kFALSE;
3230 Bool_t hasCORRFW = kFALSE;
0f389141 3231 TString func = mergingMacro;
3232 TString comment;
3233 func.ReplaceAll(".C", "");
7c2cd90a 3234 out << "void " << func.Data() << "(const char *dir, Int_t stage=0, Int_t ichunk=0)" << endl;
0f389141 3235 out << "{" << endl;
3236 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3237 out << " TStopwatch timer;" << endl;
3238 out << " timer.Start();" << endl << endl;
7c2cd90a 3239 if (!fExecutableCommand.Contains("aliroot")) {
3240 out << "// load base root libraries" << endl;
3241 out << " gSystem->Load(\"libTree\");" << endl;
3242 out << " gSystem->Load(\"libGeom\");" << endl;
3243 out << " gSystem->Load(\"libVMC\");" << endl;
3244 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3245 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3246 }
0f389141 3247 if (fAdditionalRootLibs.Length()) {
3248 // in principle libtree /lib geom libvmc etc. can go into this list, too
3249 out << "// Add aditional libraries" << endl;
3250 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3251 TIter next(list);
3252 TObjString *str;
3253 while((str=(TObjString*)next())) {
3254 if (str->GetString().Contains(".so"))
3255 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3256 }
3257 if (list) delete list;
3258 }
3259 out << "// include path" << endl;
3260 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3261 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
3262 out << "// Load analysis framework libraries" << endl;
3263 if (!fPackages) {
7c2cd90a 3264 if (!fExecutableCommand.Contains("aliroot")) {
3265 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3266 out << " gSystem->Load(\"libESD\");" << endl;
3267 out << " gSystem->Load(\"libAOD\");" << endl;
3268 }
0f389141 3269 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3270 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3271 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3272 } else {
3273 TIter next(fPackages);
3274 TObject *obj;
3275 TString pkgname;
5b273635 3276 TString setupPar = "AliAnalysisAlien::SetupPar";
0f389141 3277 while ((obj=next())) {
3278 pkgname = obj->GetName();
3279 if (pkgname == "STEERBase" ||
3280 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3281 if (pkgname == "ESD" ||
3282 pkgname == "ESD.par") hasESD = kTRUE;
3283 if (pkgname == "AOD" ||
3284 pkgname == "AOD.par") hasAOD = kTRUE;
3285 if (pkgname == "ANALYSIS" ||
3286 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3287 if (pkgname == "ANALYSISalice" ||
3288 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3289 if (pkgname == "CORRFW" ||
3290 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3291 }
5b273635 3292 if (hasANALYSISalice) setupPar = "SetupPar";
0f389141 3293 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3294 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
0f389141 3295 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3296 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
0f389141 3297 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3298 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
0f389141 3299 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3300 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
0f389141 3301 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3302 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
0f389141 3303 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3304 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
0f389141 3305 out << "// Compile other par packages" << endl;
3306 next.Reset();
3307 while ((obj=next())) {
3308 pkgname = obj->GetName();
3309 if (pkgname == "STEERBase" ||
3310 pkgname == "STEERBase.par" ||
3311 pkgname == "ESD" ||
3312 pkgname == "ESD.par" ||
3313 pkgname == "AOD" ||
3314 pkgname == "AOD.par" ||
3315 pkgname == "ANALYSIS" ||
3316 pkgname == "ANALYSIS.par" ||
3317 pkgname == "ANALYSISalice" ||
3318 pkgname == "ANALYSISalice.par" ||
3319 pkgname == "CORRFW" ||
3320 pkgname == "CORRFW.par") continue;
5b273635 3321 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
0f389141 3322 }
3323 }
3324 if (fAdditionalLibs.Length()) {
3325 out << "// Add aditional AliRoot libraries" << endl;
3326 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3327 TIter next(list);
3328 TObjString *str;
3329 while((str=(TObjString*)next())) {
3330 if (str->GetString().Contains(".so"))
3331 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3332 }
3333 if (list) delete list;
3334 }
3335 out << endl;
3336 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3337 if (fAnalysisSource.Length()) {
3338 TObjArray *list = fAnalysisSource.Tokenize(" ");
3339 TIter next(list);
3340 TObjString *str;
3341 while((str=(TObjString*)next())) {
3342 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3343 }
3344 if (list) delete list;
3345 }
149d288c 3346 out << endl;
3347
0f389141 3348 if (fFastReadOption) {
3349 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 !!!");
3350 out << "// fast xrootd reading enabled" << endl;
3351 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 3352 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
f790bc1b 3353 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
0f389141 3354 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
f790bc1b 3355 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
0f389141 3356 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
e8b839ab 3357 }
3358 // Change temp directory to current one
3359 out << "// Set temporary merging directory to current one" << endl;
3360 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
0f389141 3361 out << "// Connect to AliEn" << endl;
3362 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
0cdf65a8 3363 out << " Bool_t laststage = kFALSE;" << endl;
7c2cd90a 3364 out << " TString outputDir = dir;" << endl;
f790bc1b 3365 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
0f389141 3366 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
58268c13 3367 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
0f389141 3368 out << " TIter *iter = new TIter(list);" << endl;
3369 out << " TObjString *str;" << endl;
a2f5fc01 3370 out << " TString outputFile;" << endl;
0f389141 3371 out << " Bool_t merged = kTRUE;" << endl;
3372 out << " while((str=(TObjString*)iter->Next())) {" << endl;
a2f5fc01 3373 out << " outputFile = str->GetString();" << endl;
7c2cd90a 3374 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
a2f5fc01 3375 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3376 out << " if (index > 0) outputFile.Remove(index);" << endl;
0f389141 3377 out << " // Skip already merged outputs" << endl;
a2f5fc01 3378 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3379 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
0f389141 3380 out << " continue;" << endl;
3381 out << " }" << endl;
a2f5fc01 3382 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
7c2cd90a 3383 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage, ichunk);" << endl;
0f389141 3384 out << " if (!merged) {" << endl;
a2f5fc01 3385 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
7c2cd90a 3386 out << " return;" << endl;
0f389141 3387 out << " }" << endl;
7c2cd90a 3388 out << " // Check if this was the last stage. If yes, run terminate for the tasks." << endl;
3389 out << " if (!gSystem->AccessPathName(outputFile)) laststage = kTRUE;" << endl;
0f389141 3390 out << " }" << endl;
7c2cd90a 3391 out << " // all outputs merged, validate" << endl;
3392 out << " ofstream out;" << endl;
3393 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3394 out << " out.close();" << endl;
3395 out << " // read the analysis manager from file" << endl;
f866cba5 3396 TString analysisFile = fExecutable;
3397 analysisFile.ReplaceAll(".sh", ".root");
7c2cd90a 3398 out << " if (!laststage) return;" << endl;
f866cba5 3399 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
7c2cd90a 3400 out << " if (!file) return;" << endl;
f866cba5 3401 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3402 out << " AliAnalysisManager *mgr = 0;" << endl;
3403 out << " TKey *key;" << endl;
3404 out << " while ((key=(TKey*)nextkey())) {" << endl;
3405 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3406 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3407 out << " };" << endl;
3408 out << " if (!mgr) {" << endl;
3409 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3410 out << " return;" << endl;
3411 out << " }" << endl << endl;
5c4250fc 3412 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
b385fec0 3413 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
f866cba5 3414 out << " mgr->PrintStatus();" << endl;
3415 if (AliAnalysisManager::GetAnalysisManager()) {
3416 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3417 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3418 } else {
9a8288ff 3419 if (TestBit(AliAnalysisGrid::kTest))
3420 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3421 else
3422 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
f866cba5 3423 }
3424 }
9a8288ff 3425 out << " TTree *tree = NULL;" << endl;
3426 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
0f389141 3427 out << "}" << endl << endl;
5b273635 3428 if (hasANALYSISalice) {
3429 out <<"//________________________________________________________________________________" << endl;
3430 out << "Bool_t SetupPar(const char *package) {" << endl;
3431 out << "// Compile the package and set it up." << endl;
3432 out << " TString pkgdir = package;" << endl;
3433 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3434 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3435 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3436 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3437 out << " // Check for BUILD.sh and execute" << endl;
3438 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3439 out << " printf(\"*******************************\\n\");" << endl;
3440 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3441 out << " printf(\"*******************************\\n\");" << endl;
3442 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3443 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3444 out << " gSystem->ChangeDirectory(cdir);" << endl;
3445 out << " return kFALSE;" << endl;
3446 out << " }" << endl;
3447 out << " } else {" << endl;
3448 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3449 out << " gSystem->ChangeDirectory(cdir);" << endl;
3450 out << " return kFALSE;" << endl;
3451 out << " }" << endl;
3452 out << " // Check for SETUP.C and execute" << endl;
3453 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3454 out << " printf(\"*******************************\\n\");" << endl;
3455 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3456 out << " printf(\"*******************************\\n\");" << endl;
3457 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3458 out << " } else {" << endl;
3459 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3460 out << " gSystem->ChangeDirectory(cdir);" << endl;
3461 out << " return kFALSE;" << endl;
3462 out << " }" << endl;
3463 out << " // Restore original workdir" << endl;
3464 out << " gSystem->ChangeDirectory(cdir);" << endl;
3465 out << " return kTRUE;" << endl;
3466 out << "}" << endl;
3467 }
0f389141 3468 }
3469 Bool_t copy = kTRUE;
d3b18c4c 3470 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 3471 if (copy) {
3472 CdWork();
3473 TString workdir = gGrid->GetHomeDirectory();
3474 workdir += fGridWorkingDir;
3475 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3476 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3477 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3478 }
3479}
3480
3481//______________________________________________________________________________
3482Bool_t AliAnalysisAlien::SetupPar(const char *package)
3483{
205b201f 3484// Compile the par file archive pointed by <package>. This must be present in the current directory.
0f389141 3485// Note that for loading the compiled library. The current directory should have precedence in
3486// LD_LIBRARY_PATH
3487 TString pkgdir = package;
3488 pkgdir.ReplaceAll(".par","");
3489 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
3490 TString cdir = gSystem->WorkingDirectory();
3491 gSystem->ChangeDirectory(pkgdir);
3492 // Check for BUILD.sh and execute
3493 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3494 printf("**************************************************\n");
3495 printf("*** Building PAR archive %s\n", package);
3496 printf("**************************************************\n");
3497 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3498 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3499 gSystem->ChangeDirectory(cdir);
3500 return kFALSE;
3501 }
3502 } else {
3503 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3504 gSystem->ChangeDirectory(cdir);
3505 return kFALSE;
3506 }
3507 // Check for SETUP.C and execute
3508 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3509 printf("**************************************************\n");
3510 printf("*** Setup PAR archive %s\n", package);
3511 printf("**************************************************\n");
3512 gROOT->Macro("PROOF-INF/SETUP.C");
3513 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3514 } else {
3515 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3516 gSystem->ChangeDirectory(cdir);
3517 return kFALSE;
3518 }
3519 // Restore original workdir
3520 gSystem->ChangeDirectory(cdir);
3521 return kTRUE;
3522}
3523
c57f56b7 3524//______________________________________________________________________________
3525void AliAnalysisAlien::WriteExecutable()
3526{
3527// Generate the alien executable script.
3528 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3529 ofstream out;
3530 out.open(fExecutable.Data(), ios::out);
3531 if (out.bad()) {
5513444a 3532 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
c57f56b7 3533 return;
3534 }
3535 out << "#!/bin/bash" << endl;
c57f56b7 3536 out << "echo \"=========================================\"" << endl;
3537 out << "echo \"############## PATH : ##############\"" << endl;
3538 out << "echo $PATH" << endl;
3539 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3540 out << "echo $LD_LIBRARY_PATH" << endl;
3541 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3542 out << "echo $ROOTSYS" << endl;
3543 out << "echo \"############## which root : ##############\"" << endl;
3544 out << "which root" << endl;
3545 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3546 out << "echo $ALICE_ROOT" << endl;
3547 out << "echo \"############## which aliroot : ##############\"" << endl;
3548 out << "which aliroot" << endl;
9c5ddadc 3549 out << "echo \"############## system limits : ##############\"" << endl;
3550 out << "ulimit -a" << endl;
3551 out << "echo \"############## memory : ##############\"" << endl;
3552 out << "free -m" << endl;
c57f56b7 3553 out << "echo \"=========================================\"" << endl << endl;
74a53467 3554 // Make sure we can properly compile par files
3555 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
0a1c1f7f 3556 out << fExecutableCommand << " ";
631c0b05 3557 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
9c5ddadc 3558 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3559 out << "echo \"############## memory after: ##############\"" << endl;
3560 out << "free -m" << endl;
c57f56b7 3561 }
3562 Bool_t copy = kTRUE;
d3b18c4c 3563 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3564 if (copy) {
3565 CdWork();
3566 TString workdir = gGrid->GetHomeDirectory();
923e2ca5 3567 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 3568 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
c57f56b7 3569 workdir += fGridWorkingDir;
3570 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3571 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 3572 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
c57f56b7 3573 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3574 }
3575}
3576
0f389141 3577//______________________________________________________________________________
3578void AliAnalysisAlien::WriteMergeExecutable()
3579{
3580// Generate the alien executable script for the merging job.
3581 if (!fMergeViaJDL) return;
3582 TString mergeExec = fExecutable;
3583 mergeExec.ReplaceAll(".sh", "_merge.sh");
3584 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3585 ofstream out;
3586 out.open(mergeExec.Data(), ios::out);
3587 if (out.bad()) {
3588 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3589 return;
3590 }
3591 out << "#!/bin/bash" << endl;
3592 out << "echo \"=========================================\"" << endl;
3593 out << "echo \"############## PATH : ##############\"" << endl;
3594 out << "echo $PATH" << endl;
3595 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3596 out << "echo $LD_LIBRARY_PATH" << endl;
3597 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3598 out << "echo $ROOTSYS" << endl;
3599 out << "echo \"############## which root : ##############\"" << endl;
3600 out << "which root" << endl;
3601 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3602 out << "echo $ALICE_ROOT" << endl;
3603 out << "echo \"############## which aliroot : ##############\"" << endl;
3604 out << "which aliroot" << endl;
3605 out << "echo \"############## system limits : ##############\"" << endl;
3606 out << "ulimit -a" << endl;
3607 out << "echo \"############## memory : ##############\"" << endl;
3608 out << "free -m" << endl;
3609 out << "echo \"=========================================\"" << endl << endl;
3610 // Make sure we can properly compile par files
3611 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3612 TString mergeMacro = fExecutable;
3613 mergeMacro.ReplaceAll(".sh", "_merge.C");
f790bc1b 3614 if (IsOneStageMerging())
3615 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3616 else
3617 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2,$3)\"" << endl;
0f389141 3618 out << fExecutableCommand << " " << "$ARG" << endl;
3619 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3620 out << "echo \"############## memory after: ##############\"" << endl;
3621 out << "free -m" << endl;
0f389141 3622 }
3623 Bool_t copy = kTRUE;
d3b18c4c 3624 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 3625 if (copy) {
3626 CdWork();
3627 TString workdir = gGrid->GetHomeDirectory();
3628 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 3629 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
0f389141 3630 workdir += fGridWorkingDir;
3631 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3632 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 3633 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
0f389141 3634 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3635 }
3636}
3637
c57f56b7 3638//______________________________________________________________________________
5513444a 3639void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3640{
3641// Write the production file to be submitted by LPM manager. The format is:
f5e8c702 3642// First line: full_path_to_jdl estimated_no_subjobs_per_master
5513444a 3643// Next lines: full_path_to_dataset XXX (XXX is a string)
3644// To submit, one has to: submit jdl XXX for all lines
3645 ofstream out;
3646 out.open(filename, ios::out);
3647 if (out.bad()) {
3648 Error("WriteProductionFile", "Bad file name: %s", filename);
3649 return;
3650 }
d3b18c4c 3651 TString workdir;
3652 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3653 workdir = gGrid->GetHomeDirectory();
5513444a 3654 workdir += fGridWorkingDir;
f5e8c702 3655 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
5513444a 3656 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
f5e8c702 3657 out << locjdl << " " << njobspermaster << endl;
5513444a 3658 Int_t nmasterjobs = fInputFiles->GetEntries();
3659 for (Int_t i=0; i<nmasterjobs; i++) {
409b4ada 3660 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3661 runOutDir.ReplaceAll(".xml", "");
3662 if (fOutputToRunNo)
3663 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3664 else
3665 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
5513444a 3666 }
d3b18c4c 3667 if (gGrid) {
3668 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3669 if (FileExists(filename)) gGrid->Rm(filename);
3670 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3671 }
5513444a 3672}
3673
3674//______________________________________________________________________________
0f389141 3675void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
c57f56b7 3676{
3677// Generate the alien validation script.
3678 // Generate the validation script
3679 TObjString *os;
d3b18c4c 3680 if (fValidationScript.IsNull()) {
3681 fValidationScript = fExecutable;
3682 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3683 }
3684 TString validationScript = fValidationScript;
3685 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
c57f56b7 3686 if (!Connect()) {
3687 Error("WriteValidationScript", "Alien connection required");
3688 return;
3689 }
d3b18c4c 3690 if (!fTerminateFiles.IsNull()) {
3691 fTerminateFiles.Strip();
3692 fTerminateFiles.ReplaceAll(" ",",");
3693 }
a2f5fc01 3694 TString outStream = "";
3695 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
c57f56b7 3696 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3697 ofstream out;
0d5d317c 3698 out.open(validationScript, ios::out);
c57f56b7 3699 out << "#!/bin/bash" << endl;
3700 out << "##################################################" << endl;
3701 out << "validateout=`dirname $0`" << endl;
3702 out << "validatetime=`date`" << endl;
3703 out << "validated=\"0\";" << endl;
3704 out << "error=0" << endl;
3705 out << "if [ -z $validateout ]" << endl;
3706 out << "then" << endl;
3707 out << " validateout=\".\"" << endl;
3708 out << "fi" << endl << endl;
3709 out << "cd $validateout;" << endl;
3710 out << "validateworkdir=`pwd`;" << endl << endl;
a2f5fc01 3711 out << "echo \"*******************************************************\"" << outStream << endl;
3712 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
c57f56b7 3713 out << "" << endl;
a2f5fc01 3714 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3715 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3716 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3717 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3718 out << "ls -la ./" << outStream << endl;
3719 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
c57f56b7 3720 out << "##################################################" << endl;
ebec370a 3721 out << "" << endl;
3722
3723 out << "if [ ! -f stderr ] ; then" << endl;
3724 out << " error=1" << endl;
a2f5fc01 3725 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3726 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3727 out << "fi" << endl;
3728
b34c9f51 3729 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3730 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3731 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3732 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3733 out << "" << endl;
3734
ebec370a 3735 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3736 out << " error=1" << endl;
a2f5fc01 3737 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3738 out << " echo \"$parArch\" " << outStream << endl;
3739 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3740 out << "fi" << endl;
3741
3742 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3743 out << " error=1" << endl;
a2f5fc01 3744 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3745 out << " echo \"$segViol\" " << outStream << endl;
3746 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3747 out << "fi" << endl;
3748
3749 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3750 out << " error=1" << endl;
a2f5fc01 3751 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3752 out << " echo \"$segFault\" " << outStream << endl;
3753 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3754 out << "fi" << endl;
3755
b34c9f51 3756 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3757 out << " error=1" << endl;
a2f5fc01 3758 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3759 out << " echo \"$glibcErr\" " << outStream << endl;
3760 out << " echo \"Error = $error\" " << outStream << endl;
b34c9f51 3761 out << "fi" << endl;
3762
ebec370a 3763 // Part dedicated to the specific analyses running into the train
3764
d3b18c4c 3765 TString outputFiles = fOutputFiles;
3766 if (merge && !fTerminateFiles.IsNull()) {
3767 outputFiles += ",";
3768 outputFiles += fTerminateFiles;
3769 }
3770 TObjArray *arr = outputFiles.Tokenize(",");
c57f56b7 3771 TIter next1(arr);
a2f5fc01 3772 TString outputFile;
bbd88db8 3773 while (!merge && (os=(TObjString*)next1())) {
3774 // No need to validate outputs produced by merging since the merging macro does this
a2f5fc01 3775 outputFile = os->GetString();
3776 Int_t index = outputFile.Index("@");
3777 if (index > 0) outputFile.Remove(index);
bbd88db8 3778 if (fTerminateFiles.Contains(outputFile)) continue;
a2f5fc01 3779 if (outputFile.Contains("*")) continue;
3780 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
c57f56b7 3781 out << " error=1" << endl;
7c2cd90a 3782 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
3783 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
c57f56b7 3784 out << "fi" << endl;
3785 }
3786 delete arr;
7c2cd90a 3787 out << "if ! [ -f outputs_valid ] ; then" << endl;
3788 out << " error=1" << endl;
3789 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3790 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3791 out << "fi" << endl;
923e2ca5 3792
c57f56b7 3793 out << "if [ $error = 0 ] ; then" << endl;
a2f5fc01 3794 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
149d288c 3795 if (!IsKeepLogs()) {
3796 out << " echo \"* === Logs std* will be deleted === \"" << endl;
a2f5fc01 3797 outStream = "";
149d288c 3798 out << " rm -f std*" << endl;
3799 }
c57f56b7 3800 out << "fi" << endl;
3801
a2f5fc01 3802 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3803 out << "echo \"*******************************************************\"" << outStream << endl;
c57f56b7 3804 out << "cd -" << endl;
3805 out << "exit $error" << endl;
3806 }
3807 Bool_t copy = kTRUE;
d3b18c4c 3808 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3809 if (copy) {
3810 CdWork();
3811 TString workdir = gGrid->GetHomeDirectory();
3812 workdir += fGridWorkingDir;
d3b18c4c 3813 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
0d5d317c 3814 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3815 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 3816 }
3817}