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