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