Take into account plugin->SetArguments(const char *arguments) command
[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
282//______________________________________________________________________________
f965131e 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
291//______________________________________________________________________________
c57f56b7 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
299//______________________________________________________________________________
ee75cfc3 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
307//______________________________________________________________________________
c57f56b7 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);
b5b9dee8 787 if (!fArguments.IsNull())
788 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
c57f56b7 789// fGridJDL->SetTTL((UInt_t)fTTL);
790 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
791 if (fMaxInitFailed > 0)
792 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
793 if (fSplitMaxInputFileNumber > 0)
794 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
795 if (fSplitMode.Length())
796 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
797// fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
798 if (fAliROOTVersion.Length())
799 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
800 if (fROOTVersion.Length())
801 fGridJDL->AddToPackages("ROOT", fROOTVersion);
802 if (fAPIVersion.Length())
803 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
648174cf 804 if (!fExternalPackages.IsNull()) {
805 arr = fExternalPackages.Tokenize(" ");
806 TIter next(arr);
807 while ((os=(TObjString*)next())) {
808 TString pkgname = os->GetString();
809 Int_t index = pkgname.Index("::");
810 TString pkgversion = pkgname(index+2, pkgname.Length());
811 pkgname.Remove(index);
812 fGridJDL->AddToPackages(pkgname, pkgversion);
813 }
814 delete arr;
815 }
c57f56b7 816 fGridJDL->SetInputDataListFormat(fInputFormat);
817 fGridJDL->SetInputDataList("wn.xml");
c57f56b7 818 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
f10e8481 819 TString analysisFile = fExecutable;
820 analysisFile.ReplaceAll(".sh", ".root");
821 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 822 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
823 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
824 if (fAdditionalLibs.Length()) {
825 arr = fAdditionalLibs.Tokenize(" ");
826 TIter next(arr);
827 while ((os=(TObjString*)next())) {
828 if (os->GetString().Contains(".so")) continue;
829 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
830 }
831 delete arr;
832 }
4e5c5506 833 if (fPackages) {
834 TIter next(fPackages);
835 TObject *obj;
836 while ((obj=next()))
837 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
838 }
c57f56b7 839 if (fOutputArchive.Length()) {
840 arr = fOutputArchive.Tokenize(" ");
841 TIter next(arr);
842 while ((os=(TObjString*)next()))
43da816a 843 if (!os->GetString().Contains("@") && fCloseSE.Length())
844 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
845 else
846 fGridJDL->AddToOutputArchive(os->GetString());
c57f56b7 847 delete arr;
848 }
c57f56b7 849 arr = fOutputFiles.Tokenize(" ");
850 TIter next(arr);
43da816a 851 while ((os=(TObjString*)next())) {
e1eaf596 852 // Ignore ouputs in jdl that are also in outputarchive
853 TString sout = os->GetString();
854 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
855 if (fOutputArchive.Contains(sout)) continue;
43da816a 856 if (!os->GetString().Contains("@") && fCloseSE.Length())
857 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
858 else
859 fGridJDL->AddToOutputSandbox(os->GetString());
860 }
c57f56b7 861 delete arr;
862// fGridJDL->SetPrice((UInt_t)fPrice);
863 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
0d5d317c 864 TString validationScript = fExecutable;
865 validationScript.ReplaceAll(".sh", "_validation.sh");
866 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 867 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
d2a409b2 868 // Write a jdl with 2 input parameters: collection name and output dir name.
869 WriteJDL(copy);
c57f56b7 870 }
871 // Copy jdl to grid workspace
a8739e8a 872 if (copy) {
b5e4aaa7 873 // Check if an output directory was defined and valid
874 if (!fGridOutputDir.Length()) {
875 Error("CreateJDL", "You must define AliEn output directory");
876 return kFALSE;
877 } else {
878 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
879 if (!DirectoryExists(fGridOutputDir)) {
880 if (gGrid->Mkdir(fGridOutputDir)) {
881 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
882 } else {
883 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
884 return kFALSE;
885 }
886 }
887 gGrid->Cd(workdir);
888 }
648174cf 889 if (TestBit(AliAnalysisGrid::kSubmit)) {
890 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
891 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
892 if (fProductionMode)
893 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
894 if (FileExists(locjdl)) gGrid->Rm(locjdl);
895 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
896 }
c57f56b7 897 if (fAdditionalLibs.Length()) {
e7c71df0 898 arr = fAdditionalLibs.Tokenize(" ");
c57f56b7 899 TObjString *os;
900 TIter next(arr);
901 while ((os=(TObjString*)next())) {
c57f56b7 902 if (os->GetString().Contains(".so")) continue;
4e5c5506 903 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
c57f56b7 904 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
905 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
906 }
907 delete arr;
908 }
4e5c5506 909 if (fPackages) {
910 TIter next(fPackages);
911 TObject *obj;
912 while ((obj=next())) {
913 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
914 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
915 }
916 }
c57f56b7 917 }
918 return kTRUE;
919}
920
921//______________________________________________________________________________
d2a409b2 922Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
a8739e8a 923{
924// Writes one or more JDL's corresponding to findex. If findex is negative,
925// all run numbers are considered in one go (jdl). For non-negative indices
926// they correspond to the indices in the array fInputFiles.
927 if (!fInputFiles) return kFALSE;
928 TObjString *os;
a8739e8a 929 TString workdir = gGrid->GetHomeDirectory();
930 workdir += fGridWorkingDir;
d2a409b2 931
932 if (!fRunNumbers.Length() && !fRunRange[0]) {
933 // One jdl with no parameters in case input data is specified by name.
a8739e8a 934 TIter next(fInputFiles);
935 while ((os=(TObjString*)next()))
936 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
648174cf 937 if (!fOutputSingle.IsNull())
938 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
939 else
940 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
a8739e8a 941 } else {
d2a409b2 942 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
943 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
648174cf 944 if (!fOutputSingle.IsNull())
945 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
e1eaf596 946 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()));
a8739e8a 947 }
948
949
950 // Generate the JDL as a string
951 TString sjdl = fGridJDL->Generate();
952 Int_t index;
953 index = sjdl.Index("Executable");
954 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
955 index = sjdl.Index("Split ");
648174cf 956 if (index >= 0) sjdl.Insert(index, "\n# We split per SE or file\n");
a8739e8a 957 index = sjdl.Index("SplitMaxInputFileNumber");
958 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
959 index = sjdl.Index("InputDataCollection");
960 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
a8739e8a 961 index = sjdl.Index("InputFile");
962 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
963 index = sjdl.Index("InputDataList ");
964 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
965 index = sjdl.Index("InputDataListFormat");
966 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
967 index = sjdl.Index("Price");
968 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
969 index = sjdl.Index("Requirements");
970 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
971 index = sjdl.Index("Packages");
972 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
973 index = sjdl.Index("User =");
974 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
975 index = sjdl.Index("TTL");
976 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
977 index = sjdl.Index("OutputFile");
978 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
979 index = sjdl.Index("OutputDir");
980 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
981 index = sjdl.Index("OutputArchive");
982 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
983 index = sjdl.Index("MaxInitFailed");
984 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
985 index = sjdl.Index("MasterResubmitThreshold");
986 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
987 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
988 index = sjdl.Index("Validationcommand");
989 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
990 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
991 sjdl.ReplaceAll("(member", "\n (member");
992 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
993 sjdl.ReplaceAll("{", "{\n ");
994 sjdl.ReplaceAll("};", "\n};");
995 sjdl.ReplaceAll("{\n \n", "{\n");
996 sjdl.ReplaceAll("\n\n", "\n");
997 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
998 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
f60ef0ba 999 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
a8739e8a 1000 index = sjdl.Index("JDLVariables");
1001 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1002 // Write jdl to file
a8739e8a 1003 ofstream out;
d2a409b2 1004 out.open(fJDLName.Data(), ios::out);
a8739e8a 1005 if (out.bad()) {
d2a409b2 1006 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
a8739e8a 1007 return kFALSE;
1008 }
1009 out << sjdl << endl;
1010
1011 // Copy jdl to grid workspace
1012 if (!copy) {
1013 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1014 } else {
d2a409b2 1015 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1016 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
a3e84053 1017 if (fProductionMode)
b5fe9cba 1018 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
d2a409b2 1019 if (FileExists(locjdl)) gGrid->Rm(locjdl);
5513444a 1020 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
a8739e8a 1021 }
1022 return kTRUE;
1023}
1024
1025//______________________________________________________________________________
5513444a 1026Bool_t AliAnalysisAlien::FileExists(const char *lfn)
c57f56b7 1027{
1028// Returns true if file exists.
5513444a 1029 if (!gGrid) return kFALSE;
c57f56b7 1030 TGridResult *res = gGrid->Ls(lfn);
1031 if (!res) return kFALSE;
1032 TMap *map = dynamic_cast<TMap*>(res->At(0));
1033 if (!map) {
1034 delete res;
1035 return kFALSE;
1036 }
1037 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1038 if (!objs || !objs->GetString().Length()) {
1039 delete res;
1040 return kFALSE;
1041 }
1042 delete res;
1043 return kTRUE;
1044}
1045
1046//______________________________________________________________________________
923e2ca5 1047Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1048{
1049// Returns true if directory exists. Can be also a path.
1050 if (!gGrid) return kFALSE;
1051 // Check if dirname is a path
1052 TString dirstripped = dirname;
1053 dirstripped = dirstripped.Strip();
1054 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1055 TString dir = gSystem->BaseName(dirstripped);
1056 dir += "/";
1057 TString path = gSystem->DirName(dirstripped);
1058 TGridResult *res = gGrid->Ls(path, "-F");
1059 if (!res) return kFALSE;
1060 TIter next(res);
1061 TMap *map;
1062 TObject *obj;
1063 while ((map=dynamic_cast<TMap*>(next()))) {
1064 obj = map->GetValue("name");
1065 if (!obj) break;
1066 if (dir == obj->GetName()) {
1067 delete res;
1068 return kTRUE;
1069 }
1070 }
1071 delete res;
1072 return kFALSE;
1073}
1074
1075//______________________________________________________________________________
c57f56b7 1076void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1077{
1078// Check input data type.
1079 is_collection = kFALSE;
1080 is_xml = kFALSE;
1081 use_tags = kFALSE;
1082 if (!gGrid) {
1083 Error("CheckDataType", "No connection to grid");
1084 return;
1085 }
1086 is_collection = IsCollection(lfn);
1087 TString msg = "\n##### file: ";
1088 msg += lfn;
1089 if (is_collection) {
1090 msg += " type: raw_collection;";
1091 // special treatment for collections
1092 is_xml = kFALSE;
1093 // check for tag files in the collection
1094 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1095 if (!res) {
1096 msg += " using_tags: No (unknown)";
1097 Info("CheckDataType", msg.Data());
1098 return;
1099 }
1100 const char* typeStr = res->GetKey(0, "origLFN");
1101 if (!typeStr || !strlen(typeStr)) {
1102 msg += " using_tags: No (unknown)";
1103 Info("CheckDataType", msg.Data());
1104 return;
1105 }
1106 TString file = typeStr;
1107 use_tags = file.Contains(".tag");
1108 if (use_tags) msg += " using_tags: Yes";
1109 else msg += " using_tags: No";
1110 Info("CheckDataType", msg.Data());
1111 return;
1112 }
1113 TString slfn(lfn);
1114 slfn.ToLower();
1115 is_xml = slfn.Contains(".xml");
1116 if (is_xml) {
1117 // Open xml collection and check if there are tag files inside
1118 msg += " type: xml_collection;";
1119 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1120 if (!coll) {
1121 msg += " using_tags: No (unknown)";
1122 Info("CheckDataType", msg.Data());
1123 return;
1124 }
1125 TMap *map = coll->Next();
1126 if (!map) {
1127 msg += " using_tags: No (unknown)";
1128 Info("CheckDataType", msg.Data());
1129 return;
1130 }
1131 map = (TMap*)map->GetValue("");
1132 TString file;
1133 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1134 use_tags = file.Contains(".tag");
1135 delete coll;
1136 if (use_tags) msg += " using_tags: Yes";
1137 else msg += " using_tags: No";
1138 Info("CheckDataType", msg.Data());
1139 return;
1140 }
1141 use_tags = slfn.Contains(".tag");
1142 if (slfn.Contains(".root")) msg += " type: root file;";
1143 else msg += " type: unhnown file;";
1144 if (use_tags) msg += " using_tags: Yes";
1145 else msg += " using_tags: No";
1146 Info("CheckDataType", msg.Data());
1147}
1148
1149//______________________________________________________________________________
4e5c5506 1150void AliAnalysisAlien::EnablePackage(const char *package)
1151{
1152// Enables a par file supposed to exist in the current directory.
1153 TString pkg(package);
1154 pkg.ReplaceAll(".par", "");
1155 pkg += ".par";
1156 if (gSystem->AccessPathName(pkg)) {
1157 Error("EnablePackage", "Package %s not found", pkg.Data());
1158 return;
1159 }
1160 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1161 Info("EnablePackage", "AliEn plugin will use .par packages");
1162 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1163 if (!fPackages) {
1164 fPackages = new TObjArray();
1165 fPackages->SetOwner();
1166 }
1167 fPackages->Add(new TObjString(pkg));
1168}
1169
1170//______________________________________________________________________________
d2a409b2 1171const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1172{
1173// Get job status for all jobs with jobid>jobidstart.
1174 static char mstatus[20];
1175 mstatus[0] = '\0';
1176 nrunning = 0;
1177 nwaiting = 0;
1178 nerror = 0;
1179 ndone = 0;
1180 TGridJobStatusList *list = gGrid->Ps("");
1181 if (!list) return mstatus;
1182 Int_t nentries = list->GetSize();
1183 TGridJobStatus *status;
1184 Int_t pid;
1185 for (Int_t ijob=0; ijob<nentries; ijob++) {
1186 status = (TGridJobStatus *)list->At(ijob);
1187 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1188 if (pid<jobidstart) continue;
1189 if (pid == lastid) {
1190 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1191 }
1192 switch (status->GetStatus()) {
1193 case TGridJobStatus::kWAITING:
1194 nwaiting++; break;
1195 case TGridJobStatus::kRUNNING:
1196 nrunning++; break;
1197 case TGridJobStatus::kABORTED:
1198 case TGridJobStatus::kFAIL:
1199 case TGridJobStatus::kUNKNOWN:
1200 nerror++; break;
1201 case TGridJobStatus::kDONE:
1202 ndone++;
1203 }
1204 }
1205 list->Delete();
1206 delete list;
1207 return mstatus;
1208}
1209
1210//______________________________________________________________________________
c57f56b7 1211Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1212{
1213// Returns true if file is a collection. Functionality duplicated from
1214// TAlien::Type() because we don't want to directly depend on TAlien.
1215 if (!gGrid) {
1216 Error("IsCollection", "No connection to grid");
1217 return kFALSE;
1218 }
1219 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1220 if (!res) return kFALSE;
1221 const char* typeStr = res->GetKey(0, "type");
1222 if (!typeStr || !strlen(typeStr)) return kFALSE;
1223 if (!strcmp(typeStr, "collection")) return kTRUE;
1224 delete res;
1225 return kFALSE;
1226}
1227
1228//______________________________________________________________________________
16a4353c 1229void AliAnalysisAlien::Print(Option_t *) const
1230{
1231// Print current plugin settings.
84fcd93f 1232 printf("### AliEn analysis plugin current settings ###\n");
1233 printf("= Production mode:______________________________ %d\n", fProductionMode);
1234 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1235 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1236 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
16a4353c 1237 if (fUser.Length())
84fcd93f 1238 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1239 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1240 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1241 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1242 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1243 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
16a4353c 1244 if (fRunNumbers.Length())
84fcd93f 1245 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
16a4353c 1246 if (fRunRange[0])
5fce53f4 1247 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
16a4353c 1248 if (!fRunRange[0] && !fRunNumbers.Length()) {
1249 TIter next(fInputFiles);
1250 TObject *obj;
1251 TString list;
1252 while ((obj=next())) list += obj->GetName();
84fcd93f 1253 printf("= Input files to be processed: _________________ %s\n", list.Data());
16a4353c 1254 }
1255 if (TestBit(AliAnalysisGrid::kTest))
84fcd93f 1256 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1257 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1258 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1259 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1260 printf("=====================================================================\n");
1261 printf("= Job price: ___________________________________ %d\n", fPrice);
1262 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1263 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
16a4353c 1264 if (fMaxInitFailed>0)
84fcd93f 1265 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
16a4353c 1266 if (fMasterResubmitThreshold>0)
84fcd93f 1267 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
319593fb 1268 if (fNrunsPerMaster>0)
84fcd93f 1269 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1270 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
b5b9dee8 1271 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1272 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
16a4353c 1273 if (fArguments.Length())
84fcd93f 1274 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1275 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1276 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1277 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1278 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
16a4353c 1279 if (fDatasetName)
84fcd93f 1280 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1281 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
16a4353c 1282 if (fIncludePath.Data())
84fcd93f 1283 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
16a4353c 1284 if (fCloseSE.Length())
84fcd93f 1285 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
16a4353c 1286 if (fFriendChainName.Length())
84fcd93f 1287 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
16a4353c 1288 if (fPackages) {
1289 TIter next(fPackages);
1290 TObject *obj;
1291 TString list;
1292 while ((obj=next())) list += obj->GetName();
84fcd93f 1293 printf("= Par files to be used: ________________________ %s\n", list.Data());
16a4353c 1294 }
1295}
1296
1297//______________________________________________________________________________
c57f56b7 1298void AliAnalysisAlien::SetDefaults()
1299{
1300// Set default values for everything. What cannot be filled will be left empty.
1301 if (fGridJDL) delete fGridJDL;
1302 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1303 fPrice = 1;
1304 fTTL = 30000;
1305 fSplitMaxInputFileNumber = 100;
1306 fMaxInitFailed = 0;
1307 fMasterResubmitThreshold = 0;
bb885a9e 1308 fNtestFiles = 10;
a8739e8a 1309 fRunRange[0] = 0;
1310 fRunRange[1] = 0;
319593fb 1311 fNrunsPerMaster = 1;
16a4353c 1312 fMaxMergeFiles = 100;
c57f56b7 1313 fRunNumbers = "";
1314 fExecutable = "analysis.sh";
0a1c1f7f 1315 fExecutableCommand = "root -b -q";
c57f56b7 1316 fArguments = "";
1317 fAnalysisMacro = "myAnalysis.C";
1318 fAnalysisSource = "";
1319 fAdditionalLibs = "";
1320 fSplitMode = "se";
1321 fAPIVersion = "";
1322 fROOTVersion = "";
1323 fAliROOTVersion = "";
1324 fUser = ""; // Your alien user name
1325 fGridWorkingDir = "";
1326 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1327 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
0df6ccf2 1328 fFriendChainName = "";
c57f56b7 1329 fGridOutputDir = "output";
1330 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1331 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1332 fInputFormat = "xml-single";
1333 fJDLName = "analysis.jdl";
c6cb3634 1334 fJobTag = "Automatically generated analysis JDL";
bb885a9e 1335 fMergeExcludes = "";
c57f56b7 1336}
1337
1338//______________________________________________________________________________
1339Bool_t AliAnalysisAlien::MergeOutputs()
1340{
1341// Merge analysis outputs existing in the AliEn space.
1342 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1343 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1344 if (!Connect()) {
1345 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1346 return kFALSE;
1347 }
1348 // Get the output path
d2a409b2 1349 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
923e2ca5 1350 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 1351 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1352 return kFALSE;
1353 }
1354 if (!fOutputFiles.Length()) {
1355 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1356 return kFALSE;
1357 }
1358 TObjArray *list = fOutputFiles.Tokenize(" ");
1359 TIter next(list);
1360 TObjString *str;
1361 TString command;
1362 TString output_file;
16a4353c 1363 TString output_chunk;
1364 TString previous_chunk;
1365 Int_t count_chunk = 0;
1366 Int_t count_zero = fMaxMergeFiles;
c57f56b7 1367 Bool_t merged = kTRUE;
1368 while((str=(TObjString*)next())) {
1369 output_file = str->GetString();
1370 Int_t index = output_file.Index("@");
1371 if (index > 0) output_file.Remove(index);
319593fb 1372 // Skip already merged outputs
1373 if (!gSystem->AccessPathName(output_file)) {
1374 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1375 continue;
1376 }
bb885a9e 1377 if (fMergeExcludes.Length() &&
1378 fMergeExcludes.Contains(output_file.Data())) continue;
16a4353c 1379 // Perform a 'find' command in the output directory, looking for registered outputs
d2a409b2 1380 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
84fcd93f 1381 printf("command: %s\n", command.Data());
c57f56b7 1382 TGridResult *res = gGrid->Command(command);
1383 if (!res) continue;
1384 TFileMerger *fm = 0;
1385 TIter nextmap(res);
ab254fd1 1386 TMap *map = 0;
16a4353c 1387 previous_chunk = "";
1388 count_chunk = 0;
319593fb 1389 // Check if there is a merge operation to resume
1390 output_chunk = output_file;
1391 output_chunk.ReplaceAll(".root", "_*.root");
1392 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1393 while (1) {
1394 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1395 if (!map) {
1396 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1397 delete res;
1398 return kFALSE;
1399 }
1400 output_chunk = output_file;
1401 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
84fcd93f 1402 printf("%s\n", output_chunk.Data());
319593fb 1403 count_chunk++;
1404 if (gSystem->AccessPathName(output_chunk)) continue;
1405 // Merged file with chunks up to <count_chunk> found
84fcd93f 1406 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
319593fb 1407 previous_chunk = output_chunk;
1408 break;
1409 }
1410 }
16a4353c 1411 count_zero = fMaxMergeFiles;
c57f56b7 1412 while ((map=(TMap*)nextmap())) {
16a4353c 1413 // Loop 'find' results and get next LFN
1414 if (count_zero == fMaxMergeFiles) {
1415 // First file in chunk - create file merger and add previous chunk if any.
1416 fm = new TFileMerger(kFALSE);
1417 fm->SetFastMethod(kTRUE);
1418 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1419 output_chunk = output_file;
1420 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1421 }
1422 // If last file found, put merged results in the output file
1423 if (map == res->Last()) output_chunk = output_file;
c57f56b7 1424 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1425 if (!objs || !objs->GetString().Length()) {
16a4353c 1426 // Nothing found - skip this output
c57f56b7 1427 delete res;
16a4353c 1428 delete fm;
1429 break;
1430 }
1431 // Add file to be merged and decrement chunk counter.
1432 fm->AddFile(objs->GetString());
1433 count_zero--;
1434 if (count_zero==0 || map == res->Last()) {
1435 fm->OutputFile(output_chunk);
1436 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1437 // Nothing found - skip this output
1438 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1439 delete res;
1440 delete fm;
1441 break;
1442 }
1443 // Merge the outputs, then go to next chunk
1444 if (!fm->Merge()) {
1445 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1446 delete res;
1447 delete fm;
1448 merged = kFALSE;
1449 break;
1450 } else {
1451 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
319593fb 1452 gSystem->Unlink(previous_chunk);
16a4353c 1453 }
1454 if (map == res->Last()) {
1455 delete res;
1456 delete fm;
1457 break;
1458 }
1459 count_chunk++;
1460 count_zero = fMaxMergeFiles;
1461 previous_chunk = output_chunk;
c57f56b7 1462 }
c57f56b7 1463 }
c57f56b7 1464 }
1465 if (!merged) {
1466 Error("MergeOutputs", "Terminate() will NOT be executed");
1467 }
1468 return merged;
1469}
1470
1471//______________________________________________________________________________
bb885a9e 1472void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1473{
1474// Use the output files connected to output containers from the analysis manager
1475// rather than the files defined by SetOutputFiles
1476 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1477 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1478 analysis manager");
1479 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1480}
1481
1482//______________________________________________________________________________
5513444a 1483Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
c57f56b7 1484{
1485// Start remote grid analysis.
1486
43da816a 1487 // Check if output files have to be taken from the analysis manager
1488 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1489 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1490 if (!mgr || !mgr->IsInitialized()) {
1491 Error("StartAnalysis", "You need an initialized analysis manager for this");
5513444a 1492 return kFALSE;
43da816a 1493 }
1494 fOutputFiles = "";
1495 TIter next(mgr->GetOutputs());
1496 AliAnalysisDataContainer *output;
1497 while ((output=(AliAnalysisDataContainer*)next())) {
1498 const char *filename = output->GetFileName();
1499 if (!(strcmp(filename, "default"))) {
1500 if (!mgr->GetOutputEventHandler()) continue;
1501 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1502 }
84fcd93f 1503 if (fOutputFiles.Contains(filename)) continue;
43da816a 1504 if (fOutputFiles.Length()) fOutputFiles += " ";
1505 fOutputFiles += filename;
1506 }
c07b9ce2 1507 // Add extra files registered to the analysis manager
1508 if (mgr->GetExtraFiles().Length()) {
1509 if (fOutputFiles.Length()) fOutputFiles += " ";
1510 fOutputFiles += mgr->GetExtraFiles();
84fcd93f 1511 }
43da816a 1512 }
f7b1cbc2 1513// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
c57f56b7 1514 if (TestBit(AliAnalysisGrid::kOffline)) {
1515 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1516 \n there nor any job run. You can revise the JDL and analysis \
1517 \n macro then run the same in \"submit\" mode.");
1518 } else if (TestBit(AliAnalysisGrid::kTest)) {
1519 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1520 \n dataset.");
1521 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1522 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1523 \n space and job submitted.");
1524 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1525 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
5513444a 1526 return kTRUE;
c57f56b7 1527 } else {
1528 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1529 }
1530
1531 if (!Connect()) {
1532 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
5513444a 1533 return kFALSE;
16a4353c 1534 }
1535 Print();
c57f56b7 1536 if (!CheckInputData()) {
1537 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
5513444a 1538 return kFALSE;
c57f56b7 1539 }
1540 CreateDataset(fDataPattern);
1541 WriteAnalysisFile();
1542 WriteAnalysisMacro();
1543 WriteExecutable();
1544 WriteValidationScript();
5513444a 1545 if (!CreateJDL()) return kFALSE;
1546 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
c57f56b7 1547 if (TestBit(AliAnalysisGrid::kTest)) {
1548 // Locally testing the analysis
1549 Info("StartAnalysis", "\n_______________________________________________________________________ \
1550 \n Running analysis script in a daughter shell as on a worker node \
1551 \n_______________________________________________________________________");
1552 TObjArray *list = fOutputFiles.Tokenize(" ");
1553 TIter next(list);
1554 TObjString *str;
1555 TString output_file;
1556 while((str=(TObjString*)next())) {
1557 output_file = str->GetString();
1558 Int_t index = output_file.Index("@");
1559 if (index > 0) output_file.Remove(index);
43da816a 1560 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
c57f56b7 1561 }
1562 delete list;
1563 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
0d5d317c 1564 TString validationScript = fExecutable;
1565 validationScript.ReplaceAll(".sh", "_validation.sh");
1566 gSystem->Exec(Form("bash %s",validationScript.Data()));
c57f56b7 1567// gSystem->Exec("cat stdout");
5513444a 1568 return kFALSE;
c57f56b7 1569 }
5513444a 1570 // Check if submitting is managed by LPM manager
a3e84053 1571 if (fProductionMode) {
5513444a 1572 TString prodfile = fJDLName;
1573 prodfile.ReplaceAll(".jdl", ".prod");
1574 WriteProductionFile(prodfile);
1575 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1576 return kFALSE;
1577 }
a8739e8a 1578 // Submit AliEn job(s)
d2a409b2 1579 gGrid->Cd(fGridOutputDir);
a8739e8a 1580 TGridResult *res;
c57f56b7 1581 TString jobID = "";
d2a409b2 1582 if (!fRunNumbers.Length() && !fRunRange[0]) {
dd74a515 1583 // Submit a given xml or a set of runs
a8739e8a 1584 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
84fcd93f 1585 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
a8739e8a 1586 if (res) {
1587 const char *cjobId = res->GetKey(0,"jobId");
1588 if (!cjobId) {
1589 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
5513444a 1590 return kFALSE;
a8739e8a 1591 } else {
1592 Info("StartAnalysis", "\n_______________________________________________________________________ \
1593 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1594 \n_______________________________________________________________________",
1595 fJDLName.Data(), cjobId);
1596 jobID = cjobId;
1597 }
1598 delete res;
1599 }
1600 } else {
d2a409b2 1601 // Submit for a range of enumeration of runs.
1602 Submit();
c57f56b7 1603 }
a8739e8a 1604
c57f56b7 1605 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1606 \n You may exit at any time and terminate the job later using the option <terminate> \
1607 \n ##################################################################################", jobID.Data());
bb885a9e 1608 gSystem->Exec("aliensh");
5513444a 1609 return kTRUE;
c57f56b7 1610}
1611
1612//______________________________________________________________________________
d2a409b2 1613void AliAnalysisAlien::Submit()
1614{
1615// Submit all master jobs.
1616 Int_t nmasterjobs = fInputFiles->GetEntries();
1617 Long_t tshoot = gSystem->Now();
1618 if (!fNsubmitted) SubmitNext();
1619 while (fNsubmitted < nmasterjobs) {
1620 Long_t now = gSystem->Now();
1621 if ((now-tshoot)>30000) {
1622 tshoot = now;
1623 SubmitNext();
1624 }
1625 }
1626}
1627
1628//______________________________________________________________________________
1629void AliAnalysisAlien::SubmitNext()
1630{
1631// Submit next bunch of master jobs if the queue is free.
1632 static Bool_t iscalled = kFALSE;
1633 static Int_t firstmaster = 0;
1634 static Int_t lastmaster = 0;
1635 static Int_t npermaster = 0;
1636 if (iscalled) return;
1637 iscalled = kTRUE;
1638 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1639 Int_t ntosubmit = 0;
1640 TGridResult *res;
1641 TString jobID = "";
1642 if (!fNsubmitted) ntosubmit = 1;
1643 else {
1644 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
84fcd93f 1645 printf("=== master %d: %s\n", lastmaster, status.Data());
d2a409b2 1646 // If last master not split, just return
1647 if (status != "SPLIT") {iscalled = kFALSE; return;}
1648 // No more than 100 waiting jobs
1649 if (nwaiting>100) {iscalled = kFALSE; return;}
1650 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1651 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
84fcd93f 1652 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
d2a409b2 1653 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1654 }
1655 Int_t nmasterjobs = fInputFiles->GetEntries();
1656 for (Int_t i=0; i<ntosubmit; i++) {
1657 // Submit for a range of enumeration of runs.
1658 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1659 TString query;
1660 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
84fcd93f 1661 printf("********* %s\n",query.Data());
d2a409b2 1662 res = gGrid->Command(query);
1663 if (res) {
98ca124f 1664 TString cjobId1 = res->GetKey(0,"jobId");
1665 if (!cjobId1.Length()) {
d2a409b2 1666 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1667 iscalled = kFALSE;
1668 return;
1669 } else {
1670 Info("StartAnalysis", "\n_______________________________________________________________________ \
1671 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1672 \n_______________________________________________________________________",
98ca124f 1673 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
d2a409b2 1674 jobID += cjobId1;
1675 jobID += " ";
98ca124f 1676 lastmaster = cjobId1.Atoi();
d2a409b2 1677 if (!firstmaster) firstmaster = lastmaster;
1678 fNsubmitted++;
1679 }
1680 delete res;
1681 }
1682 }
1683 iscalled = kFALSE;
1684}
1685
1686//______________________________________________________________________________
c57f56b7 1687void AliAnalysisAlien::WriteAnalysisFile()
1688{
f10e8481 1689// Write current analysis manager into the file <analysisFile>
1690 TString analysisFile = fExecutable;
1691 analysisFile.ReplaceAll(".sh", ".root");
c57f56b7 1692 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1693 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1694 if (!mgr || !mgr->IsInitialized()) {
1695 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1696 return;
1697 }
1698 // Check analysis type
1699 TObject *handler;
1700 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1701 handler = (TObject*)mgr->GetInputEventHandler();
1702 if (handler) {
1703 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1704 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1705 }
1706 TDirectory *cdir = gDirectory;
f10e8481 1707 TFile *file = TFile::Open(analysisFile, "RECREATE");
c57f56b7 1708 if (file) {
1709 mgr->Write();
1710 delete file;
1711 }
1712 if (cdir) cdir->cd();
f10e8481 1713 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
c57f56b7 1714 }
1715 Bool_t copy = kTRUE;
1716 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1717 if (copy) {
1718 CdWork();
1719 TString workdir = gGrid->GetHomeDirectory();
1720 workdir += fGridWorkingDir;
f10e8481 1721 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1722 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1723 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 1724 }
1725}
1726
1727//______________________________________________________________________________
1728void AliAnalysisAlien::WriteAnalysisMacro()
1729{
1730// Write the analysis macro that will steer the analysis in grid mode.
1731 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1732 ofstream out;
1733 out.open(fAnalysisMacro.Data(), ios::out);
1734 if (!out.good()) {
1735 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1736 return;
1737 }
1738 TString func = fAnalysisMacro;
1739 TString type = "ESD";
1740 TString comment = "// Analysis using ";
1741 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1742 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1743 type = "AOD";
1744 comment += "AOD";
1745 }
0df6ccf2 1746 if (type!="AOD" && fFriendChainName!="") {
1747 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1748 return;
1749 }
c57f56b7 1750 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1751 else comment += " data";
1752 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1753 func.ReplaceAll(".C", "");
1754 out << "void " << func.Data() << "()" << endl;
1755 out << "{" << endl;
1756 out << comment.Data() << endl;
1757 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 1758 out << " TStopwatch timer;" << endl;
1759 out << " timer.Start();" << endl << endl;
c57f56b7 1760 out << "// load base root libraries" << endl;
1761 out << " gSystem->Load(\"libTree\");" << endl;
1762 out << " gSystem->Load(\"libGeom\");" << endl;
1763 out << " gSystem->Load(\"libVMC\");" << endl;
1764 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
648174cf 1765 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
57377eb5 1766 out << "// Load analysis framework libraries" << endl;
4e5c5506 1767 if (!fPackages) {
4e5c5506 1768 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1769 out << " gSystem->Load(\"libESD\");" << endl;
1770 out << " gSystem->Load(\"libAOD\");" << endl;
1771 out << " gSystem->Load(\"libANALYSIS\");" << endl;
57377eb5 1772 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1773 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 1774 } else {
4e5c5506 1775 TIter next(fPackages);
1776 TObject *obj;
57377eb5 1777 TString pkgname;
1778 Bool_t hasSTEERBase = kFALSE;
1779 Bool_t hasESD = kFALSE;
1780 Bool_t hasAOD = kFALSE;
1781 Bool_t hasANALYSIS = kFALSE;
1782 Bool_t hasANALYSISalice = kFALSE;
1783 Bool_t hasCORRFW = kFALSE;
1784 while ((obj=next())) {
1785 pkgname = obj->GetName();
4478e6f1 1786 if (pkgname == "STEERBase" ||
1787 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1788 if (pkgname == "ESD" ||
1789 pkgname == "ESD.par") hasESD = kTRUE;
1790 if (pkgname == "AOD" ||
1791 pkgname == "AOD.par") hasAOD = kTRUE;
1792 if (pkgname == "ANALYSIS" ||
1793 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1794 if (pkgname == "ANALYSISalice" ||
1795 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1796 if (pkgname == "CORRFW" ||
1797 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
57377eb5 1798 }
1799 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1800 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1801 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1802 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1803 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1804 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1805 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1806 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1807 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1808 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1809 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1810 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1811 out << "// Compile other par packages" << endl;
1812 next.Reset();
fcc9bb6f 1813 while ((obj=next())) {
1814 pkgname = obj->GetName();
4478e6f1 1815 if (pkgname == "STEERBase" ||
1816 pkgname == "STEERBase.par" ||
1817 pkgname == "ESD" ||
1818 pkgname == "ESD.par" ||
1819 pkgname == "AOD" ||
1820 pkgname == "AOD.par" ||
1821 pkgname == "ANALYSIS" ||
1822 pkgname == "ANALYSIS.par" ||
1823 pkgname == "ANALYSISalice" ||
1824 pkgname == "ANALYSISalice.par" ||
1825 pkgname == "CORRFW" ||
1826 pkgname == "CORRFW.par") continue;
4e5c5506 1827 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 1828 }
4e5c5506 1829 }
43da816a 1830 out << "// include path" << endl;
1831 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1832 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
6da75e0b 1833 if (fAdditionalLibs.Length()) {
1834 out << "// Add aditional AliRoot libraries" << endl;
1835 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1836 TIter next(list);
1837 TObjString *str;
1838 while((str=(TObjString*)next())) {
1839 if (str->GetString().Contains(".so"))
1840 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1841 }
1842 if (list) delete list;
1843 }
1844 out << endl;
c57f56b7 1845 out << "// analysis source to be compiled at runtime (if any)" << endl;
1846 if (fAnalysisSource.Length()) {
1847 TObjArray *list = fAnalysisSource.Tokenize(" ");
1848 TIter next(list);
1849 TObjString *str;
1850 while((str=(TObjString*)next())) {
1851 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1852 }
1853 if (list) delete list;
1854 }
1855 out << endl;
1856 out << "// connect to AliEn and make the chain" << endl;
1857 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1858 if (IsUsingTags()) {
1859 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1860 } else {
76535c98 1861 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1862 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1863 } else {
1864 out << " // Check if the macro to create the chain was provided" << endl;
1865 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1866 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1867 out << " return;" << endl;
1868 out << " }" << endl;
1869 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1870 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1871 }
c57f56b7 1872 }
1873 out << "// read the analysis manager from file" << endl;
f10e8481 1874 TString analysisFile = fExecutable;
1875 analysisFile.ReplaceAll(".sh", ".root");
1876 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
c57f56b7 1877 out << " if (!file) return;" << endl;
1878 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1879 out << " AliAnalysisManager *mgr = 0;" << endl;
1880 out << " TKey *key;" << endl;
1881 out << " while ((key=(TKey*)nextkey())) {" << endl;
1882 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1883 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1884 out << " };" << endl;
1885 out << " if (!mgr) {" << endl;
f10e8481 1886 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
c57f56b7 1887 out << " return;" << endl;
1888 out << " }" << endl << endl;
1889 out << " mgr->PrintStatus();" << endl;
1890 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 1891 out << " timer.Stop();" << endl;
1892 out << " timer.Print();" << endl;
c57f56b7 1893 out << "}" << endl << endl;
1894 if (IsUsingTags()) {
1895 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1896 out << "{" << endl;
1897 out << "// Create a chain using tags from the xml file." << endl;
1898 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1899 out << " if (!coll) {" << endl;
1900 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1901 out << " return NULL;" << endl;
1902 out << " }" << endl;
1903 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1904 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1905 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1906 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1907 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1908 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1909 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1910 out << " // Check if the cuts configuration file was provided" << endl;
1911 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1912 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1913 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1914 out << " }" << endl;
0df6ccf2 1915 if (fFriendChainName=="") {
1916 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1917 } else {
1918 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1919 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1920 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1921 }
c57f56b7 1922 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1923 out << " chain->ls();" << endl;
1924 out << " return chain;" << endl;
fcc9bb6f 1925 out << "}" << endl << endl;
c57f56b7 1926 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1927 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1928 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1929 msg += " AliLHCTagCuts *lhcCuts,\n";
1930 msg += " AliDetectorTagCuts *detCuts,\n";
1931 msg += " AliEventTagCuts *evCuts)";
1932 Info("WriteAnalysisMacro", msg.Data());
1933 }
0df6ccf2 1934 }
1935 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 1936 out <<"//________________________________________________________________________________" << endl;
c57f56b7 1937 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1938 out << "{" << endl;
1939 out << "// Create a chain using url's from xml file" << endl;
1940 out << " TString treename = type;" << endl;
1941 out << " treename.ToLower();" << endl;
1942 out << " treename += \"Tree\";" << endl;
e02fee64 1943 out << " printf(\"***************************************\\n\");" << endl;
1944 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1945 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 1946 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1947 out << " if (!coll) {" << endl;
1948 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1949 out << " return NULL;" << endl;
1950 out << " }" << endl;
1951 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 1952 if(fFriendChainName!="") {
1953 out << " TChain *chainFriend = new TChain(treename);" << endl;
1954 }
c57f56b7 1955 out << " coll->Reset();" << endl;
0df6ccf2 1956 out << " while (coll->Next()) {" << endl;
1957 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1958 if(fFriendChainName!="") {
1959 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1960 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1961 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1962 out << " chainFriend->Add(fileFriend.Data());" << endl;
1963 }
1964 out << " }" << endl;
c57f56b7 1965 out << " if (!chain->GetNtrees()) {" << endl;
1966 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1967 out << " return NULL;" << endl;
1968 out << " }" << endl;
0df6ccf2 1969 if(fFriendChainName!="") {
1970 out << " chain->AddFriend(chainFriend);" << endl;
1971 }
c57f56b7 1972 out << " return chain;" << endl;
fcc9bb6f 1973 out << "}" << endl << endl;
c57f56b7 1974 }
4e5c5506 1975 if (fPackages) {
fcc9bb6f 1976 out <<"//________________________________________________________________________________" << endl;
4e5c5506 1977 out << "Bool_t SetupPar(const char *package) {" << endl;
1978 out << "// Compile the package and set it up." << endl;
1979 out << " TString pkgdir = package;" << endl;
1980 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
fcc9bb6f 1981 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4e5c5506 1982 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1983 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1984 out << " // Check for BUILD.sh and execute" << endl;
1985 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1986 out << " printf(\"*******************************\\n\");" << endl;
1987 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1988 out << " printf(\"*******************************\\n\");" << endl;
1989 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
fcc9bb6f 1990 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4e5c5506 1991 out << " gSystem->ChangeDirectory(cdir);" << endl;
1992 out << " return kFALSE;" << endl;
1993 out << " }" << endl;
1994 out << " } else {" << endl;
fcc9bb6f 1995 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4e5c5506 1996 out << " gSystem->ChangeDirectory(cdir);" << endl;
1997 out << " return kFALSE;" << endl;
1998 out << " }" << endl;
1999 out << " // Check for SETUP.C and execute" << endl;
2000 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2001 out << " printf(\"*******************************\\n\");" << endl;
2002 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2003 out << " printf(\"*******************************\\n\");" << endl;
2004 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2005 out << " } else {" << endl;
fcc9bb6f 2006 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4e5c5506 2007 out << " gSystem->ChangeDirectory(cdir);" << endl;
2008 out << " return kFALSE;" << endl;
2009 out << " }" << endl;
2010 out << " // Restore original workdir" << endl;
2011 out << " gSystem->ChangeDirectory(cdir);" << endl;
2012 out << " return kTRUE;" << endl;
2013 out << "}" << endl;
2014 }
c57f56b7 2015 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2016 }
2017 Bool_t copy = kTRUE;
2018 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2019 if (copy) {
2020 CdWork();
2021 TString workdir = gGrid->GetHomeDirectory();
2022 workdir += fGridWorkingDir;
2023 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2024 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2025 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2026 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2027 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2028 }
2029 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2030 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2031 }
2032}
2033
2034//______________________________________________________________________________
2035void AliAnalysisAlien::WriteExecutable()
2036{
2037// Generate the alien executable script.
2038 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2039 ofstream out;
2040 out.open(fExecutable.Data(), ios::out);
2041 if (out.bad()) {
5513444a 2042 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
c57f56b7 2043 return;
2044 }
2045 out << "#!/bin/bash" << endl;
c57f56b7 2046 out << "echo \"=========================================\"" << endl;
2047 out << "echo \"############## PATH : ##############\"" << endl;
2048 out << "echo $PATH" << endl;
2049 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2050 out << "echo $LD_LIBRARY_PATH" << endl;
2051 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2052 out << "echo $ROOTSYS" << endl;
2053 out << "echo \"############## which root : ##############\"" << endl;
2054 out << "which root" << endl;
2055 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2056 out << "echo $ALICE_ROOT" << endl;
2057 out << "echo \"############## which aliroot : ##############\"" << endl;
2058 out << "which aliroot" << endl;
2059 out << "echo \"=========================================\"" << endl << endl;
74a53467 2060 // Make sure we can properly compile par files
2061 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
0a1c1f7f 2062 out << fExecutableCommand << " ";
c57f56b7 2063 out << fAnalysisMacro.Data() << endl << endl;
2064 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
2065 }
2066 Bool_t copy = kTRUE;
2067 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2068 if (copy) {
2069 CdWork();
2070 TString workdir = gGrid->GetHomeDirectory();
923e2ca5 2071 TString bindir = Form("%s/bin", workdir.Data());
2072 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
c57f56b7 2073 workdir += fGridWorkingDir;
2074 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2075 if (FileExists(executable)) gGrid->Rm(executable);
2076 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2077 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2078 }
2079}
2080
2081//______________________________________________________________________________
5513444a 2082void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2083{
2084// Write the production file to be submitted by LPM manager. The format is:
f5e8c702 2085// First line: full_path_to_jdl estimated_no_subjobs_per_master
5513444a 2086// Next lines: full_path_to_dataset XXX (XXX is a string)
2087// To submit, one has to: submit jdl XXX for all lines
2088 ofstream out;
2089 out.open(filename, ios::out);
2090 if (out.bad()) {
2091 Error("WriteProductionFile", "Bad file name: %s", filename);
2092 return;
2093 }
2094 TString workdir = gGrid->GetHomeDirectory();
2095 workdir += fGridWorkingDir;
f5e8c702 2096 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
5513444a 2097 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
f5e8c702 2098 out << locjdl << " " << njobspermaster << endl;
5513444a 2099 Int_t nmasterjobs = fInputFiles->GetEntries();
2100 for (Int_t i=0; i<nmasterjobs; i++) {
b5fe9cba 2101 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
5513444a 2102 }
2103 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2104 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2105}
2106
2107//______________________________________________________________________________
c57f56b7 2108void AliAnalysisAlien::WriteValidationScript()
2109{
2110// Generate the alien validation script.
2111 // Generate the validation script
2112 TObjString *os;
0d5d317c 2113 TString validationScript = fExecutable;
2114 validationScript.ReplaceAll(".sh", "_validation.sh");
c57f56b7 2115 if (!Connect()) {
2116 Error("WriteValidationScript", "Alien connection required");
2117 return;
2118 }
2119 TString out_stream = "";
2120 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2121 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2122 ofstream out;
0d5d317c 2123 out.open(validationScript, ios::out);
c57f56b7 2124 out << "#!/bin/bash" << endl;
2125 out << "##################################################" << endl;
2126 out << "validateout=`dirname $0`" << endl;
2127 out << "validatetime=`date`" << endl;
2128 out << "validated=\"0\";" << endl;
2129 out << "error=0" << endl;
2130 out << "if [ -z $validateout ]" << endl;
2131 out << "then" << endl;
2132 out << " validateout=\".\"" << endl;
2133 out << "fi" << endl << endl;
2134 out << "cd $validateout;" << endl;
2135 out << "validateworkdir=`pwd`;" << endl << endl;
2136 out << "echo \"*******************************************************\"" << out_stream << endl;
2137 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2138 out << "" << endl;
2139 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2140 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2141 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2142 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2143 out << "ls -la ./" << out_stream << endl;
2144 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2145 out << "##################################################" << endl;
ebec370a 2146
2147 out << "" << endl;
2148 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2149 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2150 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2151 out << "" << endl;
2152
2153 out << "if [ ! -f stderr ] ; then" << endl;
2154 out << " error=1" << endl;
2155 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2156 out << " echo \"Error = $error\" " << out_stream << endl;
2157 out << "fi" << endl;
2158
2159 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2160 out << " error=1" << endl;
2161 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2162 out << " echo \"$parArch\" " << out_stream << endl;
2163 out << " echo \"Error = $error\" " << out_stream << endl;
2164 out << "fi" << endl;
2165
2166 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2167 out << " error=1" << endl;
2168 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2169 out << " echo \"$segViol\" " << out_stream << endl;
2170 out << " echo \"Error = $error\" " << out_stream << endl;
2171 out << "fi" << endl;
2172
2173 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2174 out << " error=1" << endl;
2175 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2176 out << " echo \"$segFault\" " << out_stream << endl;
2177 out << " echo \"Error = $error\" " << out_stream << endl;
2178 out << "fi" << endl;
2179
2180 // Part dedicated to the specific analyses running into the train
2181
c57f56b7 2182 TObjArray *arr = fOutputFiles.Tokenize(" ");
2183 TIter next1(arr);
2184 TString output_file;
2185 while ((os=(TObjString*)next1())) {
2186 output_file = os->GetString();
2187 Int_t index = output_file.Index("@");
2188 if (index > 0) output_file.Remove(index);
2189 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2190 out << " error=1" << endl;
2191 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2192 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2193 out << "fi" << endl;
2194 }
2195 delete arr;
923e2ca5 2196 out << "if ! [ -f outputs_valid ] ; then" << endl;
2197 out << " error=1" << endl;
2198 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2199 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2200 out << "fi" << endl;
2201
c57f56b7 2202 out << "if [ $error = 0 ] ; then" << endl;
2203 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2204 out << "fi" << endl;
2205
2206 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2207 out << "echo \"*******************************************************\"" << out_stream << endl;
2208 out << "cd -" << endl;
2209 out << "exit $error" << endl;
2210 }
2211 Bool_t copy = kTRUE;
2212 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2213 if (copy) {
2214 CdWork();
2215 TString workdir = gGrid->GetHomeDirectory();
2216 workdir += fGridWorkingDir;
0d5d317c 2217 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2218 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2219 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 2220 }
2221}