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