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