]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisAlien.cxx
Fixed output directory setting in submit mode (Ernesto)
[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"
24#include "TROOT.h"
25#include "TSystem.h"
26#include "TFile.h"
27#include "TObjString.h"
28#include "TObjArray.h"
29#include "TGrid.h"
30#include "TGridResult.h"
31#include "TGridCollection.h"
32#include "TGridJDL.h"
d2a409b2 33#include "TGridJobStatusList.h"
34#include "TGridJobStatus.h"
c57f56b7 35#include "TFileMerger.h"
36#include "AliAnalysisManager.h"
bb885a9e 37#include "AliVEventHandler.h"
38#include "AliAnalysisDataContainer.h"
c57f56b7 39#include "AliAnalysisAlien.h"
40
41ClassImp(AliAnalysisAlien)
42
43//______________________________________________________________________________
44AliAnalysisAlien::AliAnalysisAlien()
45 :AliAnalysisGrid(),
46 fGridJDL(NULL),
47 fPrice(0),
48 fTTL(0),
49 fSplitMaxInputFileNumber(0),
50 fMaxInitFailed(0),
51 fMasterResubmitThreshold(0),
bb885a9e 52 fNtestFiles(0),
319593fb 53 fNrunsPerMaster(0),
16a4353c 54 fMaxMergeFiles(0),
d2a409b2 55 fNsubmitted(0),
a3e84053 56 fProductionMode(0),
c57f56b7 57 fRunNumbers(),
58 fExecutable(),
0a1c1f7f 59 fExecutableCommand(),
c57f56b7 60 fArguments(),
61 fAnalysisMacro(),
62 fAnalysisSource(),
63 fAdditionalLibs(),
64 fSplitMode(),
65 fAPIVersion(),
66 fROOTVersion(),
67 fAliROOTVersion(),
648174cf 68 fExternalPackages(),
c57f56b7 69 fUser(),
70 fGridWorkingDir(),
71 fGridDataDir(),
72 fDataPattern(),
73 fGridOutputDir(),
74 fOutputArchive(),
75 fOutputFiles(),
76 fInputFormat(),
e7c71df0 77 fDatasetName(),
c57f56b7 78 fJDLName(),
bb885a9e 79 fMergeExcludes(),
f965131e 80 fIncludePath(),
bb885a9e 81 fCloseSE(),
0df6ccf2 82 fFriendChainName(),
c6cb3634 83 fJobTag(),
648174cf 84 fOutputSingle(),
5fce53f4 85 fRunPrefix(),
4e5c5506 86 fInputFiles(0),
87 fPackages(0)
c57f56b7 88{
89// Dummy ctor.
90 SetDefaults();
91}
92
93//______________________________________________________________________________
94AliAnalysisAlien::AliAnalysisAlien(const char *name)
95 :AliAnalysisGrid(name),
96 fGridJDL(NULL),
97 fPrice(0),
98 fTTL(0),
99 fSplitMaxInputFileNumber(0),
100 fMaxInitFailed(0),
101 fMasterResubmitThreshold(0),
bb885a9e 102 fNtestFiles(0),
319593fb 103 fNrunsPerMaster(0),
16a4353c 104 fMaxMergeFiles(0),
d2a409b2 105 fNsubmitted(0),
a3e84053 106 fProductionMode(0),
c57f56b7 107 fRunNumbers(),
108 fExecutable(),
0a1c1f7f 109 fExecutableCommand(),
c57f56b7 110 fArguments(),
111 fAnalysisMacro(),
112 fAnalysisSource(),
113 fAdditionalLibs(),
114 fSplitMode(),
115 fAPIVersion(),
116 fROOTVersion(),
117 fAliROOTVersion(),
648174cf 118 fExternalPackages(),
c57f56b7 119 fUser(),
120 fGridWorkingDir(),
121 fGridDataDir(),
122 fDataPattern(),
123 fGridOutputDir(),
124 fOutputArchive(),
125 fOutputFiles(),
126 fInputFormat(),
e7c71df0 127 fDatasetName(),
c57f56b7 128 fJDLName(),
bb885a9e 129 fMergeExcludes(),
f965131e 130 fIncludePath(),
bb885a9e 131 fCloseSE(),
0df6ccf2 132 fFriendChainName(),
c6cb3634 133 fJobTag(),
648174cf 134 fOutputSingle(),
5fce53f4 135 fRunPrefix(),
4e5c5506 136 fInputFiles(0),
137 fPackages(0)
c57f56b7 138{
139// Default ctor.
140 SetDefaults();
141}
142
143//______________________________________________________________________________
144AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
145 :AliAnalysisGrid(other),
146 fGridJDL(NULL),
147 fPrice(other.fPrice),
148 fTTL(other.fTTL),
149 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
150 fMaxInitFailed(other.fMaxInitFailed),
151 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
bb885a9e 152 fNtestFiles(other.fNtestFiles),
319593fb 153 fNrunsPerMaster(other.fNrunsPerMaster),
16a4353c 154 fMaxMergeFiles(other.fMaxMergeFiles),
d2a409b2 155 fNsubmitted(other.fNsubmitted),
a3e84053 156 fProductionMode(other.fProductionMode),
c57f56b7 157 fRunNumbers(other.fRunNumbers),
158 fExecutable(other.fExecutable),
0a1c1f7f 159 fExecutableCommand(other.fExecutableCommand),
c57f56b7 160 fArguments(other.fArguments),
161 fAnalysisMacro(other.fAnalysisMacro),
162 fAnalysisSource(other.fAnalysisSource),
163 fAdditionalLibs(other.fAdditionalLibs),
164 fSplitMode(other.fSplitMode),
165 fAPIVersion(other.fAPIVersion),
166 fROOTVersion(other.fROOTVersion),
167 fAliROOTVersion(other.fAliROOTVersion),
648174cf 168 fExternalPackages(other.fExternalPackages),
c57f56b7 169 fUser(other.fUser),
170 fGridWorkingDir(other.fGridWorkingDir),
171 fGridDataDir(other.fGridDataDir),
172 fDataPattern(other.fDataPattern),
173 fGridOutputDir(other.fGridOutputDir),
174 fOutputArchive(other.fOutputArchive),
175 fOutputFiles(other.fOutputFiles),
176 fInputFormat(other.fInputFormat),
e7c71df0 177 fDatasetName(other.fDatasetName),
c57f56b7 178 fJDLName(other.fJDLName),
bb885a9e 179 fMergeExcludes(other.fMergeExcludes),
f965131e 180 fIncludePath(other.fIncludePath),
bb885a9e 181 fCloseSE(other.fCloseSE),
0df6ccf2 182 fFriendChainName(other.fFriendChainName),
c6cb3634 183 fJobTag(other.fJobTag),
648174cf 184 fOutputSingle(other.fOutputSingle),
5fce53f4 185 fRunPrefix(other.fRunPrefix),
4e5c5506 186 fInputFiles(0),
187 fPackages(0)
c57f56b7 188{
189// Copy ctor.
190 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
a8739e8a 191 fRunRange[0] = other.fRunRange[0];
192 fRunRange[1] = other.fRunRange[1];
c57f56b7 193 if (other.fInputFiles) {
194 fInputFiles = new TObjArray();
195 TIter next(other.fInputFiles);
196 TObject *obj;
197 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
198 fInputFiles->SetOwner();
199 }
4e5c5506 200 if (other.fPackages) {
201 fPackages = new TObjArray();
202 TIter next(other.fPackages);
203 TObject *obj;
204 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
205 fPackages->SetOwner();
206 }
c57f56b7 207}
208
209//______________________________________________________________________________
210AliAnalysisAlien::~AliAnalysisAlien()
211{
212// Destructor.
213 if (fGridJDL) delete fGridJDL;
214 if (fInputFiles) delete fInputFiles;
4e5c5506 215 if (fPackages) delete fPackages;
c57f56b7 216}
217
218//______________________________________________________________________________
219AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
220{
221// Assignment.
222 if (this != &other) {
223 AliAnalysisGrid::operator=(other);
224 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
225 fPrice = other.fPrice;
226 fTTL = other.fTTL;
227 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
228 fMaxInitFailed = other.fMaxInitFailed;
229 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
bb885a9e 230 fNtestFiles = other.fNtestFiles;
a3e84053 231 fNrunsPerMaster = other.fNrunsPerMaster;
232 fMaxMergeFiles = other.fMaxMergeFiles;
233 fNsubmitted = other.fNsubmitted;
234 fProductionMode = other.fProductionMode;
c57f56b7 235 fRunNumbers = other.fRunNumbers;
236 fExecutable = other.fExecutable;
0a1c1f7f 237 fExecutableCommand = other.fExecutableCommand;
c57f56b7 238 fArguments = other.fArguments;
239 fAnalysisMacro = other.fAnalysisMacro;
240 fAnalysisSource = other.fAnalysisSource;
241 fAdditionalLibs = other.fAdditionalLibs;
242 fSplitMode = other.fSplitMode;
243 fAPIVersion = other.fAPIVersion;
244 fROOTVersion = other.fROOTVersion;
245 fAliROOTVersion = other.fAliROOTVersion;
648174cf 246 fExternalPackages = other.fExternalPackages;
c57f56b7 247 fUser = other.fUser;
248 fGridWorkingDir = other.fGridWorkingDir;
249 fGridDataDir = other.fGridDataDir;
250 fDataPattern = other.fDataPattern;
251 fGridOutputDir = other.fGridOutputDir;
252 fOutputArchive = other.fOutputArchive;
253 fOutputFiles = other.fOutputFiles;
254 fInputFormat = other.fInputFormat;
e7c71df0 255 fDatasetName = other.fDatasetName;
c57f56b7 256 fJDLName = other.fJDLName;
bb885a9e 257 fMergeExcludes = other.fMergeExcludes;
f965131e 258 fIncludePath = other.fIncludePath;
bb885a9e 259 fCloseSE = other.fCloseSE;
0df6ccf2 260 fFriendChainName = other.fFriendChainName;
c6cb3634 261 fJobTag = other.fJobTag;
648174cf 262 fOutputSingle = other.fOutputSingle;
5fce53f4 263 fRunPrefix = other.fRunPrefix;
c57f56b7 264 if (other.fInputFiles) {
265 fInputFiles = new TObjArray();
266 TIter next(other.fInputFiles);
267 TObject *obj;
268 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
269 fInputFiles->SetOwner();
270 }
4e5c5506 271 if (other.fPackages) {
272 fPackages = new TObjArray();
273 TIter next(other.fPackages);
274 TObject *obj;
275 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
276 fPackages->SetOwner();
277 }
c57f56b7 278 }
279 return *this;
280}
281
f965131e 282//______________________________________________________________________________
283void AliAnalysisAlien::AddIncludePath(const char *path)
284{
285// Add include path in the remote analysis macro.
286 TString p(path);
287 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
288 else fIncludePath += Form("-I%s ", path);
289}
290
c57f56b7 291//______________________________________________________________________________
292void AliAnalysisAlien::AddRunNumber(Int_t run)
293{
294// Add a run number to the list of runs to be processed.
295 if (fRunNumbers.Length()) fRunNumbers += " ";
5fce53f4 296 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
c57f56b7 297}
298
ee75cfc3 299//______________________________________________________________________________
300void AliAnalysisAlien::AddRunNumber(const char* run)
301{
302// Add a run number to the list of runs to be processed.
303 if (fRunNumbers.Length()) fRunNumbers += " ";
304 fRunNumbers += run;
305}
306
c57f56b7 307//______________________________________________________________________________
308void AliAnalysisAlien::AddDataFile(const char *lfn)
309{
310// Adds a data file to the input to be analysed. The file should be a valid LFN
311// or point to an existing file in the alien workdir.
312 if (!fInputFiles) fInputFiles = new TObjArray();
313 fInputFiles->Add(new TObjString(lfn));
314}
648174cf 315
316//______________________________________________________________________________
317void AliAnalysisAlien::AddExternalPackage(const char *package)
318{
319// Adds external packages w.r.t to the default ones (root,aliroot and gapi)
320 if (fExternalPackages) fExternalPackages += " ";
321 fExternalPackages += package;
322}
323
c57f56b7 324//______________________________________________________________________________
325Bool_t AliAnalysisAlien::Connect()
326{
327// Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
328 if (gGrid && gGrid->IsConnected()) return kTRUE;
329 if (!gSystem->Getenv("alien_API_USER")) {
330 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
331 gSystem->Getenv("UID"));
332 return kFALSE;
333 }
334 if (!gGrid) {
335 Info("Connect", "Trying to connect to AliEn ...");
336 TGrid::Connect("alien://");
337 }
338 if (!gGrid || !gGrid->IsConnected()) {
339 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
340 return kFALSE;
341 }
342 fUser = gGrid->GetUser();
343 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
344 return kTRUE;
345}
346
347//______________________________________________________________________________
348void AliAnalysisAlien::CdWork()
349{
350// Check validity of alien workspace. Create directory if possible.
351 if (!Connect()) {
352 Error("CdWork", "Alien connection required");
353 return;
354 }
355 TString homedir = gGrid->GetHomeDirectory();
356 TString workdir = homedir + fGridWorkingDir;
923e2ca5 357 if (DirectoryExists(workdir)) {
358 gGrid->Cd(workdir);
359 return;
360 }
361 // Work directory not existing - create it
362 gGrid->Cd(homedir);
363 if (gGrid->Mkdir(workdir)) {
364 gGrid->Cd(fGridWorkingDir);
365 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
366 } else {
367 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
368 workdir.Data(), homedir.Data());
369 fGridWorkingDir = "";
370 }
c57f56b7 371}
372
373//______________________________________________________________________________
374Bool_t AliAnalysisAlien::CheckInputData()
375{
376// Check validity of input data. If necessary, create xml files.
a8739e8a 377 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
d2a409b2 378 if (!fGridDataDir.Length()) {
379 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
380 return kFALSE;
381 }
382 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
383 return kTRUE;
c57f56b7 384 }
385 // Process declared files
386 Bool_t is_collection = kFALSE;
387 Bool_t is_xml = kFALSE;
388 Bool_t use_tags = kFALSE;
389 Bool_t checked = kFALSE;
390 CdWork();
391 TString file;
392 TString workdir = gGrid->GetHomeDirectory();
393 workdir += fGridWorkingDir;
394 if (fInputFiles) {
395 TObjString *objstr;
396 TIter next(fInputFiles);
397 while ((objstr=(TObjString*)next())) {
398 file = workdir;
399 file += "/";
400 file += objstr->GetString();
401 // Store full lfn path
402 if (FileExists(file)) objstr->SetString(file);
403 else {
404 file = objstr->GetName();
405 if (!FileExists(objstr->GetName())) {
406 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
407 objstr->GetName(), workdir.Data());
408 return kFALSE;
409 }
410 }
411 Bool_t iscoll, isxml, usetags;
412 CheckDataType(file, iscoll, isxml, usetags);
413 if (!checked) {
414 checked = kTRUE;
415 is_collection = iscoll;
416 is_xml = isxml;
417 use_tags = usetags;
418 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
419 } else {
420 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
421 Error("CheckInputData", "Some conflict was found in the types of inputs");
422 return kFALSE;
423 }
424 }
425 }
426 }
427 // Process requested run numbers
a8739e8a 428 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
c57f56b7 429 // Check validity of alien data directory
430 if (!fGridDataDir.Length()) {
431 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
432 return kFALSE;
433 }
923e2ca5 434 if (!DirectoryExists(fGridDataDir)) {
c57f56b7 435 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
436 return kFALSE;
437 }
438 if (is_collection) {
439 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
440 return kFALSE;
441 }
442
443 if (checked && !is_xml) {
444 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
445 return kFALSE;
446 }
447 // Check validity of run number(s)
448 TObjArray *arr;
449 TObjString *os;
319593fb 450 Int_t nruns = 0;
904f9f5f 451 TString schunk, schunk2;
c57f56b7 452 TString path;
453 if (!checked) {
454 checked = kTRUE;
455 use_tags = fDataPattern.Contains("tag");
456 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
457 }
458 if (use_tags != fDataPattern.Contains("tag")) {
459 Error("CheckInputData", "Cannot mix input files using/not using tags");
460 return kFALSE;
461 }
462 if (fRunNumbers.Length()) {
a8739e8a 463 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
c57f56b7 464 arr = fRunNumbers.Tokenize(" ");
465 TIter next(arr);
466 while ((os=(TObjString*)next())) {
467 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
923e2ca5 468 if (!DirectoryExists(path)) {
469 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
a8739e8a 470 continue;
c57f56b7 471 }
472 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
473 TString msg = "\n##### file: ";
474 msg += path;
475 msg += " type: xml_collection;";
476 if (use_tags) msg += " using_tags: Yes";
477 else msg += " using_tags: No";
478 Info("CheckDataType", msg.Data());
319593fb 479 if (fNrunsPerMaster<2) {
d2a409b2 480 AddDataFile(Form("%s.xml", os->GetString().Data()));
319593fb 481 } else {
482 nruns++;
483 if (((nruns-1)%fNrunsPerMaster) == 0) {
484 schunk = os->GetString();
485 }
486 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
487 schunk += Form("_%s.xml", os->GetString().Data());
d2a409b2 488 AddDataFile(schunk);
319593fb 489 }
c57f56b7 490 }
491 delete arr;
a8739e8a 492 } else {
493 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
494 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
5fce53f4 495 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
923e2ca5 496 if (!DirectoryExists(path)) {
497// Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
a8739e8a 498 continue;
499 }
5fce53f4 500 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
a8739e8a 501 TString msg = "\n##### file: ";
502 msg += path;
503 msg += " type: xml_collection;";
504 if (use_tags) msg += " using_tags: Yes";
505 else msg += " using_tags: No";
506 Info("CheckDataType", msg.Data());
319593fb 507 if (fNrunsPerMaster<2) {
5fce53f4 508 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
319593fb 509 } else {
510 nruns++;
511 if (((nruns-1)%fNrunsPerMaster) == 0) {
5fce53f4 512 schunk = Form("%s%d", fRunPrefix.Data(),irun);
319593fb 513 }
904f9f5f 514 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
319593fb 515 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
904f9f5f 516 schunk += schunk2;
d2a409b2 517 AddDataFile(schunk);
319593fb 518 }
a8739e8a 519 }
904f9f5f 520 if (!fInputFiles) {
521 schunk += schunk2;
522 AddDataFile(schunk);
523 }
c57f56b7 524 }
525 return kTRUE;
526}
527
528//______________________________________________________________________________
529Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
530{
531// Create dataset for the grid data directory + run number.
532 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
533 if (!Connect()) {
534 Error("CreateDataset", "Cannot create dataset with no grid connection");
535 return kFALSE;
536 }
537
538 // Cd workspace
539 CdWork();
540 TString workdir = gGrid->GetHomeDirectory();
541 workdir += fGridWorkingDir;
542
543 // Compose the 'find' command arguments
544 TString command;
545 TString options = "-x collection ";
bb885a9e 546 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
c57f56b7 547 TString conditions = "";
548
549 TString file;
550 TString path;
319593fb 551 Int_t nruns = 0;
904f9f5f 552 TString schunk, schunk2;
ab254fd1 553 TGridCollection *cbase=0, *cadd=0;
d2a409b2 554 if (!fRunNumbers.Length() && !fRunRange[0]) {
555 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
556 // Make a single data collection from data directory.
557 path = fGridDataDir;
923e2ca5 558 if (!DirectoryExists(path)) {
d2a409b2 559 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
560 return kFALSE;
561 }
923e2ca5 562// CdWork();
d2a409b2 563 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
564 else file = Form("%s.xml", gSystem->BaseName(path));
14d25f30 565 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest)) {
d2a409b2 566 command = "find ";
567 command += options;
568 command += path;
569 command += " ";
570 command += pattern;
571 command += conditions;
84fcd93f 572 printf("command: %s\n", command.Data());
d2a409b2 573 TGridResult *res = gGrid->Command(command);
574 if (res) delete res;
575 // Write standard output to file
576 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
577 }
578 if (!TestBit(AliAnalysisGrid::kTest) && !FileExists(file)) {
579 // Copy xml file to alien space
580 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
581 if (!FileExists(file)) {
582 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
583 return kFALSE;
584 }
585 // Update list of files to be processed.
586 }
587 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
588 return kTRUE;
589 }
c57f56b7 590 // Several runs
a8739e8a 591 if (fRunNumbers.Length()) {
592 TObjArray *arr = fRunNumbers.Tokenize(" ");
593 TObjString *os;
594 TIter next(arr);
595 while ((os=(TObjString*)next())) {
596 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
923e2ca5 597 if (!DirectoryExists(path)) continue;
598// CdWork();
a8739e8a 599 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
600 else file = Form("%s.xml", os->GetString().Data());
319593fb 601 // If local collection file does not exist, create it via 'find' command.
602 if (gSystem->AccessPathName(file)) {
603 command = "find ";
604 command += options;
605 command += path;
606 command += pattern;
607 command += conditions;
608 TGridResult *res = gGrid->Command(command);
609 if (res) delete res;
610 // Write standard output to file
611 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
612 }
a8739e8a 613 if (TestBit(AliAnalysisGrid::kTest)) break;
319593fb 614 // Check if there is one run per master job.
615 if (fNrunsPerMaster<2) {
616 if (FileExists(file)) {
617 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
618 continue;
619 }
620 // Copy xml file to alien space
621 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
622 if (!FileExists(file)) {
623 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
624 delete arr;
625 return kFALSE;
626 }
627 } else {
628 nruns++;
629 if (((nruns-1)%fNrunsPerMaster) == 0) {
630 schunk = os->GetString();
631 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
632 } else {
633 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
84fcd93f 634 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
319593fb 635 cbase->Add(cadd);
636 delete cadd;
637 }
638 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
639 continue;
640 }
641 schunk += Form("_%s.xml", os->GetString().Data());
642 if (FileExists(schunk)) {
643 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
644 continue;
645 }
84fcd93f 646 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
319593fb 647 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
e95434bc 648 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
319593fb 649 if (!FileExists(schunk)) {
650 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
651 delete arr;
652 return kFALSE;
653 }
654 }
a8739e8a 655 }
656 delete arr;
657 } else {
658 // Process a full run range.
659 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
5fce53f4 660 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
923e2ca5 661 if (!DirectoryExists(path)) continue;
662// CdWork();
a8739e8a 663 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
5fce53f4 664 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
319593fb 665 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
a8739e8a 666 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
667// gGrid->Rm(file);
668 continue;
669 }
319593fb 670 // If local collection file does not exist, create it via 'find' command.
671 if (gSystem->AccessPathName(file)) {
672 command = "find ";
673 command += options;
674 command += path;
675 command += pattern;
676 command += conditions;
677 TGridResult *res = gGrid->Command(command);
678 if (res) delete res;
679 // Write standard output to file
680 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
681 }
a8739e8a 682 if (TestBit(AliAnalysisGrid::kTest)) break;
319593fb 683 // Check if there is one run per master job.
684 if (fNrunsPerMaster<2) {
685 if (FileExists(file)) {
686 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
687 continue;
688 }
689 // Copy xml file to alien space
690 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
691 if (!FileExists(file)) {
692 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
693 return kFALSE;
694 }
695 } else {
696 nruns++;
95e5b448 697 // Check if the collection for the chunk exist locally.
698 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
699 if (FileExists(fInputFiles->At(nchunk)->GetName())) continue;
84fcd93f 700 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
319593fb 701 if (((nruns-1)%fNrunsPerMaster) == 0) {
904f9f5f 702 schunk = Form("%s%d", fRunPrefix.Data(), irun);
319593fb 703 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
704 } else {
705 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
706 cbase->Add(cadd);
707 delete cadd;
708 }
904f9f5f 709 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
710 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
319593fb 711 continue;
712 }
904f9f5f 713 schunk = schunk2;
319593fb 714 if (FileExists(schunk)) {
715 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
716 continue;
717 }
84fcd93f 718 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
319593fb 719 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
95e5b448 720 if (FileExists(schunk)) {
721 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
722 continue;
723 }
319593fb 724 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
725 if (!FileExists(schunk)) {
726 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
727 return kFALSE;
728 }
729 }
c57f56b7 730 }
a8739e8a 731 }
c57f56b7 732 return kTRUE;
733}
734
735//______________________________________________________________________________
736Bool_t AliAnalysisAlien::CreateJDL()
737{
738// Generate a JDL file according to current settings. The name of the file is
739// specified by fJDLName.
740 Bool_t error = kFALSE;
741 TObjArray *arr = 0;
742 Bool_t copy = kTRUE;
743 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
744 Bool_t generate = kTRUE;
745 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
746 if (!Connect()) {
747 Error("CreateJDL", "Alien connection required");
748 return kFALSE;
749 }
750 // Check validity of alien workspace
751 CdWork();
752 TString workdir = gGrid->GetHomeDirectory();
753 workdir += fGridWorkingDir;
754 if (generate) {
755 TObjString *os;
756 if (!fInputFiles) {
757 Error("CreateJDL()", "Define some input files for your analysis.");
758 error = kTRUE;
759 }
760 // Compose list of input files
761 // Check if output files were defined
762 if (!fOutputFiles.Length()) {
763 Error("CreateJDL", "You must define at least one output file");
764 error = kTRUE;
765 }
766 // Check if an output directory was defined and valid
767 if (!fGridOutputDir.Length()) {
768 Error("CreateJDL", "You must define AliEn output directory");
769 error = kTRUE;
770 } else {
d2a409b2 771 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
923e2ca5 772 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 773 if (gGrid->Mkdir(fGridOutputDir)) {
774 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
775 } else {
776 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
5513444a 777 // error = kTRUE;
c57f56b7 778 }
779 }
780 gGrid->Cd(workdir);
781 }
782 // Exit if any error up to now
783 if (error) return kFALSE;
784 // Set JDL fields
785 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
3c639fc4 786 fGridJDL->SetExecutable(fExecutable);
c57f56b7 787// fGridJDL->SetTTL((UInt_t)fTTL);
788 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
789 if (fMaxInitFailed > 0)
790 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
791 if (fSplitMaxInputFileNumber > 0)
792 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
793 if (fSplitMode.Length())
794 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
795// fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
796 if (fAliROOTVersion.Length())
797 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
798 if (fROOTVersion.Length())
799 fGridJDL->AddToPackages("ROOT", fROOTVersion);
800 if (fAPIVersion.Length())
801 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
648174cf 802 if (!fExternalPackages.IsNull()) {
803 arr = fExternalPackages.Tokenize(" ");
804 TIter next(arr);
805 while ((os=(TObjString*)next())) {
806 TString pkgname = os->GetString();
807 Int_t index = pkgname.Index("::");
808 TString pkgversion = pkgname(index+2, pkgname.Length());
809 pkgname.Remove(index);
810 fGridJDL->AddToPackages(pkgname, pkgversion);
811 }
812 delete arr;
813 }
c57f56b7 814 fGridJDL->SetInputDataListFormat(fInputFormat);
815 fGridJDL->SetInputDataList("wn.xml");
c57f56b7 816 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
f10e8481 817 TString analysisFile = fExecutable;
818 analysisFile.ReplaceAll(".sh", ".root");
819 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 820 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
821 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
822 if (fAdditionalLibs.Length()) {
823 arr = fAdditionalLibs.Tokenize(" ");
824 TIter next(arr);
825 while ((os=(TObjString*)next())) {
826 if (os->GetString().Contains(".so")) continue;
827 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
828 }
829 delete arr;
830 }
4e5c5506 831 if (fPackages) {
832 TIter next(fPackages);
833 TObject *obj;
834 while ((obj=next()))
835 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
836 }
c57f56b7 837 if (fOutputArchive.Length()) {
838 arr = fOutputArchive.Tokenize(" ");
839 TIter next(arr);
840 while ((os=(TObjString*)next()))
43da816a 841 if (!os->GetString().Contains("@") && fCloseSE.Length())
842 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
843 else
844 fGridJDL->AddToOutputArchive(os->GetString());
c57f56b7 845 delete arr;
846 }
c57f56b7 847 arr = fOutputFiles.Tokenize(" ");
848 TIter next(arr);
43da816a 849 while ((os=(TObjString*)next())) {
e1eaf596 850 // Ignore ouputs in jdl that are also in outputarchive
851 TString sout = os->GetString();
852 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
853 if (fOutputArchive.Contains(sout)) continue;
43da816a 854 if (!os->GetString().Contains("@") && fCloseSE.Length())
855 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
856 else
857 fGridJDL->AddToOutputSandbox(os->GetString());
858 }
c57f56b7 859 delete arr;
860// fGridJDL->SetPrice((UInt_t)fPrice);
861 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
0d5d317c 862 TString validationScript = fExecutable;
863 validationScript.ReplaceAll(".sh", "_validation.sh");
864 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 865 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
d2a409b2 866 // Write a jdl with 2 input parameters: collection name and output dir name.
867 WriteJDL(copy);
c57f56b7 868 }
869 // Copy jdl to grid workspace
a8739e8a 870 if (copy) {
b5e4aaa7 871 // Check if an output directory was defined and valid
872 if (!fGridOutputDir.Length()) {
873 Error("CreateJDL", "You must define AliEn output directory");
874 return kFALSE;
875 } else {
876 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
877 if (!DirectoryExists(fGridOutputDir)) {
878 if (gGrid->Mkdir(fGridOutputDir)) {
879 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
880 } else {
881 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
882 return kFALSE;
883 }
884 }
885 gGrid->Cd(workdir);
886 }
648174cf 887 if (TestBit(AliAnalysisGrid::kSubmit)) {
888 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
889 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
890 if (fProductionMode)
891 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
892 if (FileExists(locjdl)) gGrid->Rm(locjdl);
893 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
894 }
c57f56b7 895 if (fAdditionalLibs.Length()) {
e7c71df0 896 arr = fAdditionalLibs.Tokenize(" ");
c57f56b7 897 TObjString *os;
898 TIter next(arr);
899 while ((os=(TObjString*)next())) {
c57f56b7 900 if (os->GetString().Contains(".so")) continue;
4e5c5506 901 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
c57f56b7 902 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
903 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
904 }
905 delete arr;
906 }
4e5c5506 907 if (fPackages) {
908 TIter next(fPackages);
909 TObject *obj;
910 while ((obj=next())) {
911 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
912 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
913 }
914 }
c57f56b7 915 }
916 return kTRUE;
917}
918
a8739e8a 919//______________________________________________________________________________
d2a409b2 920Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
a8739e8a 921{
922// Writes one or more JDL's corresponding to findex. If findex is negative,
923// all run numbers are considered in one go (jdl). For non-negative indices
924// they correspond to the indices in the array fInputFiles.
925 if (!fInputFiles) return kFALSE;
926 TObjString *os;
a8739e8a 927 TString workdir = gGrid->GetHomeDirectory();
928 workdir += fGridWorkingDir;
d2a409b2 929
930 if (!fRunNumbers.Length() && !fRunRange[0]) {
931 // One jdl with no parameters in case input data is specified by name.
a8739e8a 932 TIter next(fInputFiles);
933 while ((os=(TObjString*)next()))
934 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
648174cf 935 if (!fOutputSingle.IsNull())
936 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
937 else
938 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
a8739e8a 939 } else {
d2a409b2 940 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
941 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
648174cf 942 if (!fOutputSingle.IsNull())
943 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
e1eaf596 944 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()));
a8739e8a 945 }
946
947
948 // Generate the JDL as a string
949 TString sjdl = fGridJDL->Generate();
950 Int_t index;
951 index = sjdl.Index("Executable");
952 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
953 index = sjdl.Index("Split ");
648174cf 954 if (index >= 0) sjdl.Insert(index, "\n# We split per SE or file\n");
a8739e8a 955 index = sjdl.Index("SplitMaxInputFileNumber");
956 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
957 index = sjdl.Index("InputDataCollection");
958 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
a8739e8a 959 index = sjdl.Index("InputFile");
960 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
961 index = sjdl.Index("InputDataList ");
962 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
963 index = sjdl.Index("InputDataListFormat");
964 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
965 index = sjdl.Index("Price");
966 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
967 index = sjdl.Index("Requirements");
968 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
969 index = sjdl.Index("Packages");
970 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
971 index = sjdl.Index("User =");
972 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
973 index = sjdl.Index("TTL");
974 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
975 index = sjdl.Index("OutputFile");
976 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
977 index = sjdl.Index("OutputDir");
978 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
979 index = sjdl.Index("OutputArchive");
980 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
981 index = sjdl.Index("MaxInitFailed");
982 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
983 index = sjdl.Index("MasterResubmitThreshold");
984 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
985 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
986 index = sjdl.Index("Validationcommand");
987 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
988 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
989 sjdl.ReplaceAll("(member", "\n (member");
990 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
991 sjdl.ReplaceAll("{", "{\n ");
992 sjdl.ReplaceAll("};", "\n};");
993 sjdl.ReplaceAll("{\n \n", "{\n");
994 sjdl.ReplaceAll("\n\n", "\n");
995 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
996 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
f60ef0ba 997 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
a8739e8a 998 index = sjdl.Index("JDLVariables");
999 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1000 // Write jdl to file
a8739e8a 1001 ofstream out;
d2a409b2 1002 out.open(fJDLName.Data(), ios::out);
a8739e8a 1003 if (out.bad()) {
d2a409b2 1004 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
a8739e8a 1005 return kFALSE;
1006 }
1007 out << sjdl << endl;
1008
1009 // Copy jdl to grid workspace
1010 if (!copy) {
1011 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1012 } else {
d2a409b2 1013 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1014 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
a3e84053 1015 if (fProductionMode)
b5fe9cba 1016 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
d2a409b2 1017 if (FileExists(locjdl)) gGrid->Rm(locjdl);
5513444a 1018 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
a8739e8a 1019 }
1020 return kTRUE;
1021}
1022
c57f56b7 1023//______________________________________________________________________________
5513444a 1024Bool_t AliAnalysisAlien::FileExists(const char *lfn)
c57f56b7 1025{
1026// Returns true if file exists.
5513444a 1027 if (!gGrid) return kFALSE;
c57f56b7 1028 TGridResult *res = gGrid->Ls(lfn);
1029 if (!res) return kFALSE;
1030 TMap *map = dynamic_cast<TMap*>(res->At(0));
1031 if (!map) {
1032 delete res;
1033 return kFALSE;
1034 }
1035 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1036 if (!objs || !objs->GetString().Length()) {
1037 delete res;
1038 return kFALSE;
1039 }
1040 delete res;
1041 return kTRUE;
1042}
1043
923e2ca5 1044//______________________________________________________________________________
1045Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1046{
1047// Returns true if directory exists. Can be also a path.
1048 if (!gGrid) return kFALSE;
1049 // Check if dirname is a path
1050 TString dirstripped = dirname;
1051 dirstripped = dirstripped.Strip();
1052 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1053 TString dir = gSystem->BaseName(dirstripped);
1054 dir += "/";
1055 TString path = gSystem->DirName(dirstripped);
1056 TGridResult *res = gGrid->Ls(path, "-F");
1057 if (!res) return kFALSE;
1058 TIter next(res);
1059 TMap *map;
1060 TObject *obj;
1061 while ((map=dynamic_cast<TMap*>(next()))) {
1062 obj = map->GetValue("name");
1063 if (!obj) break;
1064 if (dir == obj->GetName()) {
1065 delete res;
1066 return kTRUE;
1067 }
1068 }
1069 delete res;
1070 return kFALSE;
1071}
1072
c57f56b7 1073//______________________________________________________________________________
1074void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1075{
1076// Check input data type.
1077 is_collection = kFALSE;
1078 is_xml = kFALSE;
1079 use_tags = kFALSE;
1080 if (!gGrid) {
1081 Error("CheckDataType", "No connection to grid");
1082 return;
1083 }
1084 is_collection = IsCollection(lfn);
1085 TString msg = "\n##### file: ";
1086 msg += lfn;
1087 if (is_collection) {
1088 msg += " type: raw_collection;";
1089 // special treatment for collections
1090 is_xml = kFALSE;
1091 // check for tag files in the collection
1092 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1093 if (!res) {
1094 msg += " using_tags: No (unknown)";
1095 Info("CheckDataType", msg.Data());
1096 return;
1097 }
1098 const char* typeStr = res->GetKey(0, "origLFN");
1099 if (!typeStr || !strlen(typeStr)) {
1100 msg += " using_tags: No (unknown)";
1101 Info("CheckDataType", msg.Data());
1102 return;
1103 }
1104 TString file = typeStr;
1105 use_tags = file.Contains(".tag");
1106 if (use_tags) msg += " using_tags: Yes";
1107 else msg += " using_tags: No";
1108 Info("CheckDataType", msg.Data());
1109 return;
1110 }
1111 TString slfn(lfn);
1112 slfn.ToLower();
1113 is_xml = slfn.Contains(".xml");
1114 if (is_xml) {
1115 // Open xml collection and check if there are tag files inside
1116 msg += " type: xml_collection;";
1117 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1118 if (!coll) {
1119 msg += " using_tags: No (unknown)";
1120 Info("CheckDataType", msg.Data());
1121 return;
1122 }
1123 TMap *map = coll->Next();
1124 if (!map) {
1125 msg += " using_tags: No (unknown)";
1126 Info("CheckDataType", msg.Data());
1127 return;
1128 }
1129 map = (TMap*)map->GetValue("");
1130 TString file;
1131 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1132 use_tags = file.Contains(".tag");
1133 delete coll;
1134 if (use_tags) msg += " using_tags: Yes";
1135 else msg += " using_tags: No";
1136 Info("CheckDataType", msg.Data());
1137 return;
1138 }
1139 use_tags = slfn.Contains(".tag");
1140 if (slfn.Contains(".root")) msg += " type: root file;";
1141 else msg += " type: unhnown file;";
1142 if (use_tags) msg += " using_tags: Yes";
1143 else msg += " using_tags: No";
1144 Info("CheckDataType", msg.Data());
1145}
1146
4e5c5506 1147//______________________________________________________________________________
1148void AliAnalysisAlien::EnablePackage(const char *package)
1149{
1150// Enables a par file supposed to exist in the current directory.
1151 TString pkg(package);
1152 pkg.ReplaceAll(".par", "");
1153 pkg += ".par";
1154 if (gSystem->AccessPathName(pkg)) {
1155 Error("EnablePackage", "Package %s not found", pkg.Data());
1156 return;
1157 }
1158 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1159 Info("EnablePackage", "AliEn plugin will use .par packages");
1160 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1161 if (!fPackages) {
1162 fPackages = new TObjArray();
1163 fPackages->SetOwner();
1164 }
1165 fPackages->Add(new TObjString(pkg));
1166}
1167
d2a409b2 1168//______________________________________________________________________________
1169const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1170{
1171// Get job status for all jobs with jobid>jobidstart.
1172 static char mstatus[20];
1173 mstatus[0] = '\0';
1174 nrunning = 0;
1175 nwaiting = 0;
1176 nerror = 0;
1177 ndone = 0;
1178 TGridJobStatusList *list = gGrid->Ps("");
1179 if (!list) return mstatus;
1180 Int_t nentries = list->GetSize();
1181 TGridJobStatus *status;
1182 Int_t pid;
1183 for (Int_t ijob=0; ijob<nentries; ijob++) {
1184 status = (TGridJobStatus *)list->At(ijob);
1185 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1186 if (pid<jobidstart) continue;
1187 if (pid == lastid) {
1188 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1189 }
1190 switch (status->GetStatus()) {
1191 case TGridJobStatus::kWAITING:
1192 nwaiting++; break;
1193 case TGridJobStatus::kRUNNING:
1194 nrunning++; break;
1195 case TGridJobStatus::kABORTED:
1196 case TGridJobStatus::kFAIL:
1197 case TGridJobStatus::kUNKNOWN:
1198 nerror++; break;
1199 case TGridJobStatus::kDONE:
1200 ndone++;
1201 }
1202 }
1203 list->Delete();
1204 delete list;
1205 return mstatus;
1206}
1207
c57f56b7 1208//______________________________________________________________________________
1209Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1210{
1211// Returns true if file is a collection. Functionality duplicated from
1212// TAlien::Type() because we don't want to directly depend on TAlien.
1213 if (!gGrid) {
1214 Error("IsCollection", "No connection to grid");
1215 return kFALSE;
1216 }
1217 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1218 if (!res) return kFALSE;
1219 const char* typeStr = res->GetKey(0, "type");
1220 if (!typeStr || !strlen(typeStr)) return kFALSE;
1221 if (!strcmp(typeStr, "collection")) return kTRUE;
1222 delete res;
1223 return kFALSE;
1224}
1225
16a4353c 1226//______________________________________________________________________________
1227void AliAnalysisAlien::Print(Option_t *) const
1228{
1229// Print current plugin settings.
84fcd93f 1230 printf("### AliEn analysis plugin current settings ###\n");
1231 printf("= Production mode:______________________________ %d\n", fProductionMode);
1232 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1233 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1234 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
16a4353c 1235 if (fUser.Length())
84fcd93f 1236 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1237 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1238 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1239 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1240 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1241 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
16a4353c 1242 if (fRunNumbers.Length())
84fcd93f 1243 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
16a4353c 1244 if (fRunRange[0])
5fce53f4 1245 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
16a4353c 1246 if (!fRunRange[0] && !fRunNumbers.Length()) {
1247 TIter next(fInputFiles);
1248 TObject *obj;
1249 TString list;
1250 while ((obj=next())) list += obj->GetName();
84fcd93f 1251 printf("= Input files to be processed: _________________ %s\n", list.Data());
16a4353c 1252 }
1253 if (TestBit(AliAnalysisGrid::kTest))
84fcd93f 1254 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1255 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1256 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1257 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1258 printf("=====================================================================\n");
1259 printf("= Job price: ___________________________________ %d\n", fPrice);
1260 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1261 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
16a4353c 1262 if (fMaxInitFailed>0)
84fcd93f 1263 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
16a4353c 1264 if (fMasterResubmitThreshold>0)
84fcd93f 1265 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
319593fb 1266 if (fNrunsPerMaster>0)
84fcd93f 1267 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1268 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1269 printf("= Name of the generated execution script: ______ %s\n",fExecutable.Data());
16a4353c 1270 if (fArguments.Length())
84fcd93f 1271 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1272 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1273 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1274 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1275 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
16a4353c 1276 if (fDatasetName)
84fcd93f 1277 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1278 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
16a4353c 1279 if (fIncludePath.Data())
84fcd93f 1280 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
16a4353c 1281 if (fCloseSE.Length())
84fcd93f 1282 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
16a4353c 1283 if (fFriendChainName.Length())
84fcd93f 1284 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
16a4353c 1285 if (fPackages) {
1286 TIter next(fPackages);
1287 TObject *obj;
1288 TString list;
1289 while ((obj=next())) list += obj->GetName();
84fcd93f 1290 printf("= Par files to be used: ________________________ %s\n", list.Data());
16a4353c 1291 }
1292}
1293
c57f56b7 1294//______________________________________________________________________________
1295void AliAnalysisAlien::SetDefaults()
1296{
1297// Set default values for everything. What cannot be filled will be left empty.
1298 if (fGridJDL) delete fGridJDL;
1299 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1300 fPrice = 1;
1301 fTTL = 30000;
1302 fSplitMaxInputFileNumber = 100;
1303 fMaxInitFailed = 0;
1304 fMasterResubmitThreshold = 0;
bb885a9e 1305 fNtestFiles = 10;
a8739e8a 1306 fRunRange[0] = 0;
1307 fRunRange[1] = 0;
319593fb 1308 fNrunsPerMaster = 1;
16a4353c 1309 fMaxMergeFiles = 100;
c57f56b7 1310 fRunNumbers = "";
1311 fExecutable = "analysis.sh";
0a1c1f7f 1312 fExecutableCommand = "root -b -q";
c57f56b7 1313 fArguments = "";
1314 fAnalysisMacro = "myAnalysis.C";
1315 fAnalysisSource = "";
1316 fAdditionalLibs = "";
1317 fSplitMode = "se";
1318 fAPIVersion = "";
1319 fROOTVersion = "";
1320 fAliROOTVersion = "";
1321 fUser = ""; // Your alien user name
1322 fGridWorkingDir = "";
1323 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1324 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
0df6ccf2 1325 fFriendChainName = "";
c57f56b7 1326 fGridOutputDir = "output";
1327 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1328 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1329 fInputFormat = "xml-single";
1330 fJDLName = "analysis.jdl";
c6cb3634 1331 fJobTag = "Automatically generated analysis JDL";
bb885a9e 1332 fMergeExcludes = "";
c57f56b7 1333}
1334
1335//______________________________________________________________________________
1336Bool_t AliAnalysisAlien::MergeOutputs()
1337{
1338// Merge analysis outputs existing in the AliEn space.
1339 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1340 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1341 if (!Connect()) {
1342 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1343 return kFALSE;
1344 }
1345 // Get the output path
d2a409b2 1346 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
923e2ca5 1347 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 1348 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1349 return kFALSE;
1350 }
1351 if (!fOutputFiles.Length()) {
1352 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1353 return kFALSE;
1354 }
1355 TObjArray *list = fOutputFiles.Tokenize(" ");
1356 TIter next(list);
1357 TObjString *str;
1358 TString command;
1359 TString output_file;
16a4353c 1360 TString output_chunk;
1361 TString previous_chunk;
1362 Int_t count_chunk = 0;
1363 Int_t count_zero = fMaxMergeFiles;
c57f56b7 1364 Bool_t merged = kTRUE;
1365 while((str=(TObjString*)next())) {
1366 output_file = str->GetString();
1367 Int_t index = output_file.Index("@");
1368 if (index > 0) output_file.Remove(index);
319593fb 1369 // Skip already merged outputs
1370 if (!gSystem->AccessPathName(output_file)) {
1371 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1372 continue;
1373 }
bb885a9e 1374 if (fMergeExcludes.Length() &&
1375 fMergeExcludes.Contains(output_file.Data())) continue;
16a4353c 1376 // Perform a 'find' command in the output directory, looking for registered outputs
d2a409b2 1377 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
84fcd93f 1378 printf("command: %s\n", command.Data());
c57f56b7 1379 TGridResult *res = gGrid->Command(command);
1380 if (!res) continue;
1381 TFileMerger *fm = 0;
1382 TIter nextmap(res);
ab254fd1 1383 TMap *map = 0;
16a4353c 1384 previous_chunk = "";
1385 count_chunk = 0;
319593fb 1386 // Check if there is a merge operation to resume
1387 output_chunk = output_file;
1388 output_chunk.ReplaceAll(".root", "_*.root");
1389 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1390 while (1) {
1391 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1392 if (!map) {
1393 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1394 delete res;
1395 return kFALSE;
1396 }
1397 output_chunk = output_file;
1398 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
84fcd93f 1399 printf("%s\n", output_chunk.Data());
319593fb 1400 count_chunk++;
1401 if (gSystem->AccessPathName(output_chunk)) continue;
1402 // Merged file with chunks up to <count_chunk> found
84fcd93f 1403 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
319593fb 1404 previous_chunk = output_chunk;
1405 break;
1406 }
1407 }
16a4353c 1408 count_zero = fMaxMergeFiles;
c57f56b7 1409 while ((map=(TMap*)nextmap())) {
16a4353c 1410 // Loop 'find' results and get next LFN
1411 if (count_zero == fMaxMergeFiles) {
1412 // First file in chunk - create file merger and add previous chunk if any.
1413 fm = new TFileMerger(kFALSE);
1414 fm->SetFastMethod(kTRUE);
1415 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1416 output_chunk = output_file;
1417 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1418 }
1419 // If last file found, put merged results in the output file
1420 if (map == res->Last()) output_chunk = output_file;
c57f56b7 1421 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1422 if (!objs || !objs->GetString().Length()) {
16a4353c 1423 // Nothing found - skip this output
c57f56b7 1424 delete res;
16a4353c 1425 delete fm;
1426 break;
1427 }
1428 // Add file to be merged and decrement chunk counter.
1429 fm->AddFile(objs->GetString());
1430 count_zero--;
1431 if (count_zero==0 || map == res->Last()) {
1432 fm->OutputFile(output_chunk);
1433 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1434 // Nothing found - skip this output
1435 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1436 delete res;
1437 delete fm;
1438 break;
1439 }
1440 // Merge the outputs, then go to next chunk
1441 if (!fm->Merge()) {
1442 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1443 delete res;
1444 delete fm;
1445 merged = kFALSE;
1446 break;
1447 } else {
1448 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
319593fb 1449 gSystem->Unlink(previous_chunk);
16a4353c 1450 }
1451 if (map == res->Last()) {
1452 delete res;
1453 delete fm;
1454 break;
1455 }
1456 count_chunk++;
1457 count_zero = fMaxMergeFiles;
1458 previous_chunk = output_chunk;
c57f56b7 1459 }
c57f56b7 1460 }
c57f56b7 1461 }
1462 if (!merged) {
1463 Error("MergeOutputs", "Terminate() will NOT be executed");
1464 }
1465 return merged;
1466}
1467
bb885a9e 1468//______________________________________________________________________________
1469void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1470{
1471// Use the output files connected to output containers from the analysis manager
1472// rather than the files defined by SetOutputFiles
1473 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1474 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1475 analysis manager");
1476 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1477}
1478
5513444a 1479//______________________________________________________________________________
1480Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
c57f56b7 1481{
1482// Start remote grid analysis.
1483
43da816a 1484 // Check if output files have to be taken from the analysis manager
1485 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1486 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1487 if (!mgr || !mgr->IsInitialized()) {
1488 Error("StartAnalysis", "You need an initialized analysis manager for this");
5513444a 1489 return kFALSE;
43da816a 1490 }
1491 fOutputFiles = "";
1492 TIter next(mgr->GetOutputs());
1493 AliAnalysisDataContainer *output;
1494 while ((output=(AliAnalysisDataContainer*)next())) {
1495 const char *filename = output->GetFileName();
1496 if (!(strcmp(filename, "default"))) {
1497 if (!mgr->GetOutputEventHandler()) continue;
1498 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1499 }
84fcd93f 1500 if (fOutputFiles.Contains(filename)) continue;
43da816a 1501 if (fOutputFiles.Length()) fOutputFiles += " ";
1502 fOutputFiles += filename;
1503 }
c07b9ce2 1504 // Add extra files registered to the analysis manager
1505 if (mgr->GetExtraFiles().Length()) {
1506 if (fOutputFiles.Length()) fOutputFiles += " ";
1507 fOutputFiles += mgr->GetExtraFiles();
84fcd93f 1508 }
43da816a 1509 }
f7b1cbc2 1510// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
c57f56b7 1511 if (TestBit(AliAnalysisGrid::kOffline)) {
1512 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1513 \n there nor any job run. You can revise the JDL and analysis \
1514 \n macro then run the same in \"submit\" mode.");
1515 } else if (TestBit(AliAnalysisGrid::kTest)) {
1516 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1517 \n dataset.");
1518 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1519 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1520 \n space and job submitted.");
1521 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1522 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
5513444a 1523 return kTRUE;
c57f56b7 1524 } else {
1525 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1526 }
1527
1528 if (!Connect()) {
1529 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
5513444a 1530 return kFALSE;
16a4353c 1531 }
1532 Print();
c57f56b7 1533 if (!CheckInputData()) {
1534 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
5513444a 1535 return kFALSE;
c57f56b7 1536 }
1537 CreateDataset(fDataPattern);
1538 WriteAnalysisFile();
1539 WriteAnalysisMacro();
1540 WriteExecutable();
1541 WriteValidationScript();
5513444a 1542 if (!CreateJDL()) return kFALSE;
1543 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
c57f56b7 1544 if (TestBit(AliAnalysisGrid::kTest)) {
1545 // Locally testing the analysis
1546 Info("StartAnalysis", "\n_______________________________________________________________________ \
1547 \n Running analysis script in a daughter shell as on a worker node \
1548 \n_______________________________________________________________________");
1549 TObjArray *list = fOutputFiles.Tokenize(" ");
1550 TIter next(list);
1551 TObjString *str;
1552 TString output_file;
1553 while((str=(TObjString*)next())) {
1554 output_file = str->GetString();
1555 Int_t index = output_file.Index("@");
1556 if (index > 0) output_file.Remove(index);
43da816a 1557 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
c57f56b7 1558 }
1559 delete list;
1560 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
0d5d317c 1561 TString validationScript = fExecutable;
1562 validationScript.ReplaceAll(".sh", "_validation.sh");
1563 gSystem->Exec(Form("bash %s",validationScript.Data()));
c57f56b7 1564// gSystem->Exec("cat stdout");
5513444a 1565 return kFALSE;
c57f56b7 1566 }
5513444a 1567 // Check if submitting is managed by LPM manager
a3e84053 1568 if (fProductionMode) {
5513444a 1569 TString prodfile = fJDLName;
1570 prodfile.ReplaceAll(".jdl", ".prod");
1571 WriteProductionFile(prodfile);
1572 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1573 return kFALSE;
1574 }
a8739e8a 1575 // Submit AliEn job(s)
d2a409b2 1576 gGrid->Cd(fGridOutputDir);
a8739e8a 1577 TGridResult *res;
c57f56b7 1578 TString jobID = "";
d2a409b2 1579 if (!fRunNumbers.Length() && !fRunRange[0]) {
dd74a515 1580 // Submit a given xml or a set of runs
a8739e8a 1581 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
84fcd93f 1582 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
a8739e8a 1583 if (res) {
1584 const char *cjobId = res->GetKey(0,"jobId");
1585 if (!cjobId) {
1586 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
5513444a 1587 return kFALSE;
a8739e8a 1588 } else {
1589 Info("StartAnalysis", "\n_______________________________________________________________________ \
1590 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1591 \n_______________________________________________________________________",
1592 fJDLName.Data(), cjobId);
1593 jobID = cjobId;
1594 }
1595 delete res;
1596 }
1597 } else {
d2a409b2 1598 // Submit for a range of enumeration of runs.
1599 Submit();
c57f56b7 1600 }
a8739e8a 1601
c57f56b7 1602 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1603 \n You may exit at any time and terminate the job later using the option <terminate> \
1604 \n ##################################################################################", jobID.Data());
bb885a9e 1605 gSystem->Exec("aliensh");
5513444a 1606 return kTRUE;
c57f56b7 1607}
1608
d2a409b2 1609//______________________________________________________________________________
1610void AliAnalysisAlien::Submit()
1611{
1612// Submit all master jobs.
1613 Int_t nmasterjobs = fInputFiles->GetEntries();
1614 Long_t tshoot = gSystem->Now();
1615 if (!fNsubmitted) SubmitNext();
1616 while (fNsubmitted < nmasterjobs) {
1617 Long_t now = gSystem->Now();
1618 if ((now-tshoot)>30000) {
1619 tshoot = now;
1620 SubmitNext();
1621 }
1622 }
1623}
1624
1625//______________________________________________________________________________
1626void AliAnalysisAlien::SubmitNext()
1627{
1628// Submit next bunch of master jobs if the queue is free.
1629 static Bool_t iscalled = kFALSE;
1630 static Int_t firstmaster = 0;
1631 static Int_t lastmaster = 0;
1632 static Int_t npermaster = 0;
1633 if (iscalled) return;
1634 iscalled = kTRUE;
1635 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1636 Int_t ntosubmit = 0;
1637 TGridResult *res;
1638 TString jobID = "";
1639 if (!fNsubmitted) ntosubmit = 1;
1640 else {
1641 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
84fcd93f 1642 printf("=== master %d: %s\n", lastmaster, status.Data());
d2a409b2 1643 // If last master not split, just return
1644 if (status != "SPLIT") {iscalled = kFALSE; return;}
1645 // No more than 100 waiting jobs
1646 if (nwaiting>100) {iscalled = kFALSE; return;}
1647 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1648 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
84fcd93f 1649 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
d2a409b2 1650 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1651 }
1652 Int_t nmasterjobs = fInputFiles->GetEntries();
1653 for (Int_t i=0; i<ntosubmit; i++) {
1654 // Submit for a range of enumeration of runs.
1655 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1656 TString query;
1657 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
84fcd93f 1658 printf("********* %s\n",query.Data());
d2a409b2 1659 res = gGrid->Command(query);
1660 if (res) {
98ca124f 1661 TString cjobId1 = res->GetKey(0,"jobId");
1662 if (!cjobId1.Length()) {
d2a409b2 1663 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1664 iscalled = kFALSE;
1665 return;
1666 } else {
1667 Info("StartAnalysis", "\n_______________________________________________________________________ \
1668 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1669 \n_______________________________________________________________________",
98ca124f 1670 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
d2a409b2 1671 jobID += cjobId1;
1672 jobID += " ";
98ca124f 1673 lastmaster = cjobId1.Atoi();
d2a409b2 1674 if (!firstmaster) firstmaster = lastmaster;
1675 fNsubmitted++;
1676 }
1677 delete res;
1678 }
1679 }
1680 iscalled = kFALSE;
1681}
1682
c57f56b7 1683//______________________________________________________________________________
1684void AliAnalysisAlien::WriteAnalysisFile()
1685{
f10e8481 1686// Write current analysis manager into the file <analysisFile>
1687 TString analysisFile = fExecutable;
1688 analysisFile.ReplaceAll(".sh", ".root");
c57f56b7 1689 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1690 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1691 if (!mgr || !mgr->IsInitialized()) {
1692 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1693 return;
1694 }
1695 // Check analysis type
1696 TObject *handler;
1697 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1698 handler = (TObject*)mgr->GetInputEventHandler();
1699 if (handler) {
1700 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1701 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1702 }
1703 TDirectory *cdir = gDirectory;
f10e8481 1704 TFile *file = TFile::Open(analysisFile, "RECREATE");
c57f56b7 1705 if (file) {
1706 mgr->Write();
1707 delete file;
1708 }
1709 if (cdir) cdir->cd();
f10e8481 1710 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
c57f56b7 1711 }
1712 Bool_t copy = kTRUE;
1713 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1714 if (copy) {
1715 CdWork();
1716 TString workdir = gGrid->GetHomeDirectory();
1717 workdir += fGridWorkingDir;
f10e8481 1718 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1719 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1720 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 1721 }
1722}
1723
1724//______________________________________________________________________________
1725void AliAnalysisAlien::WriteAnalysisMacro()
1726{
1727// Write the analysis macro that will steer the analysis in grid mode.
1728 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1729 ofstream out;
1730 out.open(fAnalysisMacro.Data(), ios::out);
1731 if (!out.good()) {
1732 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1733 return;
1734 }
1735 TString func = fAnalysisMacro;
1736 TString type = "ESD";
1737 TString comment = "// Analysis using ";
1738 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1739 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1740 type = "AOD";
1741 comment += "AOD";
1742 }
0df6ccf2 1743 if (type!="AOD" && fFriendChainName!="") {
1744 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1745 return;
1746 }
c57f56b7 1747 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1748 else comment += " data";
1749 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1750 func.ReplaceAll(".C", "");
1751 out << "void " << func.Data() << "()" << endl;
1752 out << "{" << endl;
1753 out << comment.Data() << endl;
1754 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 1755 out << " TStopwatch timer;" << endl;
1756 out << " timer.Start();" << endl << endl;
c57f56b7 1757 out << "// load base root libraries" << endl;
1758 out << " gSystem->Load(\"libTree\");" << endl;
1759 out << " gSystem->Load(\"libGeom\");" << endl;
1760 out << " gSystem->Load(\"libVMC\");" << endl;
1761 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
648174cf 1762 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
57377eb5 1763 out << "// Load analysis framework libraries" << endl;
4e5c5506 1764 if (!fPackages) {
4e5c5506 1765 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1766 out << " gSystem->Load(\"libESD\");" << endl;
1767 out << " gSystem->Load(\"libAOD\");" << endl;
1768 out << " gSystem->Load(\"libANALYSIS\");" << endl;
57377eb5 1769 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1770 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 1771 } else {
4e5c5506 1772 TIter next(fPackages);
1773 TObject *obj;
57377eb5 1774 TString pkgname;
1775 Bool_t hasSTEERBase = kFALSE;
1776 Bool_t hasESD = kFALSE;
1777 Bool_t hasAOD = kFALSE;
1778 Bool_t hasANALYSIS = kFALSE;
1779 Bool_t hasANALYSISalice = kFALSE;
1780 Bool_t hasCORRFW = kFALSE;
1781 while ((obj=next())) {
1782 pkgname = obj->GetName();
4478e6f1 1783 if (pkgname == "STEERBase" ||
1784 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1785 if (pkgname == "ESD" ||
1786 pkgname == "ESD.par") hasESD = kTRUE;
1787 if (pkgname == "AOD" ||
1788 pkgname == "AOD.par") hasAOD = kTRUE;
1789 if (pkgname == "ANALYSIS" ||
1790 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1791 if (pkgname == "ANALYSISalice" ||
1792 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1793 if (pkgname == "CORRFW" ||
1794 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
57377eb5 1795 }
1796 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1797 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1798 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1799 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1800 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1801 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1802 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1803 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1804 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1805 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1806 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1807 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1808 out << "// Compile other par packages" << endl;
1809 next.Reset();
fcc9bb6f 1810 while ((obj=next())) {
1811 pkgname = obj->GetName();
4478e6f1 1812 if (pkgname == "STEERBase" ||
1813 pkgname == "STEERBase.par" ||
1814 pkgname == "ESD" ||
1815 pkgname == "ESD.par" ||
1816 pkgname == "AOD" ||
1817 pkgname == "AOD.par" ||
1818 pkgname == "ANALYSIS" ||
1819 pkgname == "ANALYSIS.par" ||
1820 pkgname == "ANALYSISalice" ||
1821 pkgname == "ANALYSISalice.par" ||
1822 pkgname == "CORRFW" ||
1823 pkgname == "CORRFW.par") continue;
4e5c5506 1824 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 1825 }
4e5c5506 1826 }
43da816a 1827 out << "// include path" << endl;
1828 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1829 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
6da75e0b 1830 if (fAdditionalLibs.Length()) {
1831 out << "// Add aditional AliRoot libraries" << endl;
1832 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1833 TIter next(list);
1834 TObjString *str;
1835 while((str=(TObjString*)next())) {
1836 if (str->GetString().Contains(".so"))
1837 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1838 }
1839 if (list) delete list;
1840 }
1841 out << endl;
c57f56b7 1842 out << "// analysis source to be compiled at runtime (if any)" << endl;
1843 if (fAnalysisSource.Length()) {
1844 TObjArray *list = fAnalysisSource.Tokenize(" ");
1845 TIter next(list);
1846 TObjString *str;
1847 while((str=(TObjString*)next())) {
1848 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1849 }
1850 if (list) delete list;
1851 }
1852 out << endl;
1853 out << "// connect to AliEn and make the chain" << endl;
1854 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1855 if (IsUsingTags()) {
1856 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1857 } else {
76535c98 1858 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1859 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1860 } else {
1861 out << " // Check if the macro to create the chain was provided" << endl;
1862 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1863 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1864 out << " return;" << endl;
1865 out << " }" << endl;
1866 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1867 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1868 }
c57f56b7 1869 }
1870 out << "// read the analysis manager from file" << endl;
f10e8481 1871 TString analysisFile = fExecutable;
1872 analysisFile.ReplaceAll(".sh", ".root");
1873 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
c57f56b7 1874 out << " if (!file) return;" << endl;
1875 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1876 out << " AliAnalysisManager *mgr = 0;" << endl;
1877 out << " TKey *key;" << endl;
1878 out << " while ((key=(TKey*)nextkey())) {" << endl;
1879 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1880 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1881 out << " };" << endl;
1882 out << " if (!mgr) {" << endl;
f10e8481 1883 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
c57f56b7 1884 out << " return;" << endl;
1885 out << " }" << endl << endl;
1886 out << " mgr->PrintStatus();" << endl;
1887 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 1888 out << " timer.Stop();" << endl;
1889 out << " timer.Print();" << endl;
c57f56b7 1890 out << "}" << endl << endl;
1891 if (IsUsingTags()) {
1892 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1893 out << "{" << endl;
1894 out << "// Create a chain using tags from the xml file." << endl;
1895 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1896 out << " if (!coll) {" << endl;
1897 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1898 out << " return NULL;" << endl;
1899 out << " }" << endl;
1900 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1901 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1902 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1903 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1904 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1905 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1906 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1907 out << " // Check if the cuts configuration file was provided" << endl;
1908 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1909 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1910 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1911 out << " }" << endl;
0df6ccf2 1912 if (fFriendChainName=="") {
1913 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1914 } else {
1915 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1916 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1917 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1918 }
c57f56b7 1919 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1920 out << " chain->ls();" << endl;
1921 out << " return chain;" << endl;
fcc9bb6f 1922 out << "}" << endl << endl;
c57f56b7 1923 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1924 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1925 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1926 msg += " AliLHCTagCuts *lhcCuts,\n";
1927 msg += " AliDetectorTagCuts *detCuts,\n";
1928 msg += " AliEventTagCuts *evCuts)";
1929 Info("WriteAnalysisMacro", msg.Data());
1930 }
0df6ccf2 1931 }
1932 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 1933 out <<"//________________________________________________________________________________" << endl;
c57f56b7 1934 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1935 out << "{" << endl;
1936 out << "// Create a chain using url's from xml file" << endl;
1937 out << " TString treename = type;" << endl;
1938 out << " treename.ToLower();" << endl;
1939 out << " treename += \"Tree\";" << endl;
e02fee64 1940 out << " printf(\"***************************************\\n\");" << endl;
1941 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1942 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 1943 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1944 out << " if (!coll) {" << endl;
1945 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1946 out << " return NULL;" << endl;
1947 out << " }" << endl;
1948 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 1949 if(fFriendChainName!="") {
1950 out << " TChain *chainFriend = new TChain(treename);" << endl;
1951 }
c57f56b7 1952 out << " coll->Reset();" << endl;
0df6ccf2 1953 out << " while (coll->Next()) {" << endl;
1954 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1955 if(fFriendChainName!="") {
1956 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1957 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1958 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1959 out << " chainFriend->Add(fileFriend.Data());" << endl;
1960 }
1961 out << " }" << endl;
c57f56b7 1962 out << " if (!chain->GetNtrees()) {" << endl;
1963 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1964 out << " return NULL;" << endl;
1965 out << " }" << endl;
0df6ccf2 1966 if(fFriendChainName!="") {
1967 out << " chain->AddFriend(chainFriend);" << endl;
1968 }
c57f56b7 1969 out << " return chain;" << endl;
fcc9bb6f 1970 out << "}" << endl << endl;
c57f56b7 1971 }
4e5c5506 1972 if (fPackages) {
fcc9bb6f 1973 out <<"//________________________________________________________________________________" << endl;
4e5c5506 1974 out << "Bool_t SetupPar(const char *package) {" << endl;
1975 out << "// Compile the package and set it up." << endl;
1976 out << " TString pkgdir = package;" << endl;
1977 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
fcc9bb6f 1978 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4e5c5506 1979 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1980 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1981 out << " // Check for BUILD.sh and execute" << endl;
1982 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1983 out << " printf(\"*******************************\\n\");" << endl;
1984 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1985 out << " printf(\"*******************************\\n\");" << endl;
1986 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
fcc9bb6f 1987 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4e5c5506 1988 out << " gSystem->ChangeDirectory(cdir);" << endl;
1989 out << " return kFALSE;" << endl;
1990 out << " }" << endl;
1991 out << " } else {" << endl;
fcc9bb6f 1992 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4e5c5506 1993 out << " gSystem->ChangeDirectory(cdir);" << endl;
1994 out << " return kFALSE;" << endl;
1995 out << " }" << endl;
1996 out << " // Check for SETUP.C and execute" << endl;
1997 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1998 out << " printf(\"*******************************\\n\");" << endl;
1999 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2000 out << " printf(\"*******************************\\n\");" << endl;
2001 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2002 out << " } else {" << endl;
fcc9bb6f 2003 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4e5c5506 2004 out << " gSystem->ChangeDirectory(cdir);" << endl;
2005 out << " return kFALSE;" << endl;
2006 out << " }" << endl;
2007 out << " // Restore original workdir" << endl;
2008 out << " gSystem->ChangeDirectory(cdir);" << endl;
2009 out << " return kTRUE;" << endl;
2010 out << "}" << endl;
2011 }
c57f56b7 2012 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2013 }
2014 Bool_t copy = kTRUE;
2015 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2016 if (copy) {
2017 CdWork();
2018 TString workdir = gGrid->GetHomeDirectory();
2019 workdir += fGridWorkingDir;
2020 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2021 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2022 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2023 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2024 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2025 }
2026 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2027 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2028 }
2029}
2030
2031//______________________________________________________________________________
2032void AliAnalysisAlien::WriteExecutable()
2033{
2034// Generate the alien executable script.
2035 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2036 ofstream out;
2037 out.open(fExecutable.Data(), ios::out);
2038 if (out.bad()) {
5513444a 2039 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
c57f56b7 2040 return;
2041 }
2042 out << "#!/bin/bash" << endl;
c57f56b7 2043 out << "echo \"=========================================\"" << endl;
2044 out << "echo \"############## PATH : ##############\"" << endl;
2045 out << "echo $PATH" << endl;
2046 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2047 out << "echo $LD_LIBRARY_PATH" << endl;
2048 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2049 out << "echo $ROOTSYS" << endl;
2050 out << "echo \"############## which root : ##############\"" << endl;
2051 out << "which root" << endl;
2052 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2053 out << "echo $ALICE_ROOT" << endl;
2054 out << "echo \"############## which aliroot : ##############\"" << endl;
2055 out << "which aliroot" << endl;
2056 out << "echo \"=========================================\"" << endl << endl;
74a53467 2057 // Make sure we can properly compile par files
2058 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
0a1c1f7f 2059 out << fExecutableCommand << " ";
c57f56b7 2060 out << fAnalysisMacro.Data() << endl << endl;
2061 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
2062 }
2063 Bool_t copy = kTRUE;
2064 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2065 if (copy) {
2066 CdWork();
2067 TString workdir = gGrid->GetHomeDirectory();
923e2ca5 2068 TString bindir = Form("%s/bin", workdir.Data());
2069 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
c57f56b7 2070 workdir += fGridWorkingDir;
2071 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2072 if (FileExists(executable)) gGrid->Rm(executable);
2073 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2074 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2075 }
2076}
2077
2078//______________________________________________________________________________
5513444a 2079void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2080{
2081// Write the production file to be submitted by LPM manager. The format is:
f5e8c702 2082// First line: full_path_to_jdl estimated_no_subjobs_per_master
5513444a 2083// Next lines: full_path_to_dataset XXX (XXX is a string)
2084// To submit, one has to: submit jdl XXX for all lines
2085 ofstream out;
2086 out.open(filename, ios::out);
2087 if (out.bad()) {
2088 Error("WriteProductionFile", "Bad file name: %s", filename);
2089 return;
2090 }
2091 TString workdir = gGrid->GetHomeDirectory();
2092 workdir += fGridWorkingDir;
f5e8c702 2093 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
5513444a 2094 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
f5e8c702 2095 out << locjdl << " " << njobspermaster << endl;
5513444a 2096 Int_t nmasterjobs = fInputFiles->GetEntries();
2097 for (Int_t i=0; i<nmasterjobs; i++) {
b5fe9cba 2098 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
5513444a 2099 }
2100 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2101 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2102}
2103
2104//______________________________________________________________________________
c57f56b7 2105void AliAnalysisAlien::WriteValidationScript()
2106{
2107// Generate the alien validation script.
2108 // Generate the validation script
2109 TObjString *os;
0d5d317c 2110 TString validationScript = fExecutable;
2111 validationScript.ReplaceAll(".sh", "_validation.sh");
c57f56b7 2112 if (!Connect()) {
2113 Error("WriteValidationScript", "Alien connection required");
2114 return;
2115 }
2116 TString out_stream = "";
2117 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2118 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2119 ofstream out;
0d5d317c 2120 out.open(validationScript, ios::out);
c57f56b7 2121 out << "#!/bin/bash" << endl;
2122 out << "##################################################" << endl;
2123 out << "validateout=`dirname $0`" << endl;
2124 out << "validatetime=`date`" << endl;
2125 out << "validated=\"0\";" << endl;
2126 out << "error=0" << endl;
2127 out << "if [ -z $validateout ]" << endl;
2128 out << "then" << endl;
2129 out << " validateout=\".\"" << endl;
2130 out << "fi" << endl << endl;
2131 out << "cd $validateout;" << endl;
2132 out << "validateworkdir=`pwd`;" << endl << endl;
2133 out << "echo \"*******************************************************\"" << out_stream << endl;
2134 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2135 out << "" << endl;
2136 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2137 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2138 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2139 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2140 out << "ls -la ./" << out_stream << endl;
2141 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2142 out << "##################################################" << endl;
ebec370a 2143
2144 out << "" << endl;
2145 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2146 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2147 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2148 out << "" << endl;
2149
2150 out << "if [ ! -f stderr ] ; then" << endl;
2151 out << " error=1" << endl;
2152 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2153 out << " echo \"Error = $error\" " << out_stream << endl;
2154 out << "fi" << endl;
2155
2156 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2157 out << " error=1" << endl;
2158 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2159 out << " echo \"$parArch\" " << out_stream << endl;
2160 out << " echo \"Error = $error\" " << out_stream << endl;
2161 out << "fi" << endl;
2162
2163 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2164 out << " error=1" << endl;
2165 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2166 out << " echo \"$segViol\" " << out_stream << endl;
2167 out << " echo \"Error = $error\" " << out_stream << endl;
2168 out << "fi" << endl;
2169
2170 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2171 out << " error=1" << endl;
2172 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2173 out << " echo \"$segFault\" " << out_stream << endl;
2174 out << " echo \"Error = $error\" " << out_stream << endl;
2175 out << "fi" << endl;
2176
2177 // Part dedicated to the specific analyses running into the train
2178
c57f56b7 2179 TObjArray *arr = fOutputFiles.Tokenize(" ");
2180 TIter next1(arr);
2181 TString output_file;
2182 while ((os=(TObjString*)next1())) {
2183 output_file = os->GetString();
2184 Int_t index = output_file.Index("@");
2185 if (index > 0) output_file.Remove(index);
2186 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2187 out << " error=1" << endl;
2188 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2189 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2190 out << "fi" << endl;
2191 }
2192 delete arr;
923e2ca5 2193 out << "if ! [ -f outputs_valid ] ; then" << endl;
2194 out << " error=1" << endl;
2195 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2196 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2197 out << "fi" << endl;
2198
c57f56b7 2199 out << "if [ $error = 0 ] ; then" << endl;
2200 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2201 out << "fi" << endl;
2202
2203 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2204 out << "echo \"*******************************************************\"" << out_stream << endl;
2205 out << "cd -" << endl;
2206 out << "exit $error" << endl;
2207 }
2208 Bool_t copy = kTRUE;
2209 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2210 if (copy) {
2211 CdWork();
2212 TString workdir = gGrid->GetHomeDirectory();
2213 workdir += fGridWorkingDir;
0d5d317c 2214 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2215 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2216 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 2217 }
2218}