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