]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisAlien.cxx
PWG2 resonances wagon included. Still problems so disabled for the moment.
[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
f965131e 247//______________________________________________________________________________
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
c57f56b7 256//______________________________________________________________________________
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++)
648 WriteJDL(irun-fRunRange[0],copy);
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
a8739e8a 677//______________________________________________________________________________
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;
688 CdWork();
689 if (findex < 0) {
690 TIter next(fInputFiles);
691 while ((os=(TObjString*)next()))
692 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
693 fGridJDL->SetOutputDirectory(Form("%s/%s/#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data()));
694 } else {
695 os = (TObjString*)fInputFiles->At(findex);
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
c57f56b7 782//______________________________________________________________________________
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
4e5c5506 880//______________________________________________________________________________
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
c57f56b7 901//______________________________________________________________________________
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
bb885a9e 1031//______________________________________________________________________________
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
c57f56b7 1042//______________________________________________________________________________
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 = "";
a8739e8a 1130 if (fRunNumbers.Length()) {
1131 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1132 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1133 if (res) {
1134 const char *cjobId = res->GetKey(0,"jobId");
1135 if (!cjobId) {
1136 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1137 return;
1138 } else {
1139 Info("StartAnalysis", "\n_______________________________________________________________________ \
1140 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1141 \n_______________________________________________________________________",
1142 fJDLName.Data(), cjobId);
1143 jobID = cjobId;
1144 }
1145 delete res;
1146 }
1147 } else {
1148 if (!fRunRange[0]) {
1149 Error("StartAnalysis", "No runs defined. Exiting.");
c57f56b7 1150 return;
a8739e8a 1151 }
1152 TString sjdl;
1153 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1154 sjdl = fJDLName;
1155 sjdl.ReplaceAll(".jdl", Form("_%03d.jdl", irun-fRunRange[0]));
1156 res = gGrid->Command(Form("submit %s", sjdl.Data()));
1157 printf("*************************** %s\n",Form("submit %s", sjdl.Data()));
1158 if (res) {
1159 const char *cjobId1 = res->GetKey(0,"jobId");
1160 if (!cjobId1) {
1161 Error("StartAnalysis", "Your JDL %s could not be submitted", sjdl.Data());
1162 return;
1163 } else {
1164 Info("StartAnalysis", "\n_______________________________________________________________________ \
1165 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1166 \n_______________________________________________________________________",
1167 sjdl.Data(), cjobId1);
1168 jobID += cjobId1;
1169 jobID += " ";
1170 }
1171 delete res;
1172 }
1173 }
c57f56b7 1174 }
a8739e8a 1175
c57f56b7 1176 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1177 \n You may exit at any time and terminate the job later using the option <terminate> \
1178 \n ##################################################################################", jobID.Data());
bb885a9e 1179 //gGrid->Shell();
1180 gSystem->Exec("aliensh");
c57f56b7 1181}
1182
1183//______________________________________________________________________________
1184void AliAnalysisAlien::WriteAnalysisFile()
1185{
1186// Write current analysis manager into the file analysis.root
1187 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1188 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1189 if (!mgr || !mgr->IsInitialized()) {
1190 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1191 return;
1192 }
1193 // Check analysis type
1194 TObject *handler;
1195 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1196 handler = (TObject*)mgr->GetInputEventHandler();
1197 if (handler) {
1198 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1199 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1200 }
1201 TDirectory *cdir = gDirectory;
1202 TFile *file = TFile::Open("analysis.root", "RECREATE");
1203 if (file) {
1204 mgr->Write();
1205 delete file;
1206 }
1207 if (cdir) cdir->cd();
1208 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1209 }
1210 Bool_t copy = kTRUE;
1211 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1212 if (copy) {
1213 CdWork();
1214 TString workdir = gGrid->GetHomeDirectory();
1215 workdir += fGridWorkingDir;
1216 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1217 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1218 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1219 }
1220}
1221
1222//______________________________________________________________________________
1223void AliAnalysisAlien::WriteAnalysisMacro()
1224{
1225// Write the analysis macro that will steer the analysis in grid mode.
1226 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1227 ofstream out;
1228 out.open(fAnalysisMacro.Data(), ios::out);
1229 if (!out.good()) {
1230 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1231 return;
1232 }
1233 TString func = fAnalysisMacro;
1234 TString type = "ESD";
1235 TString comment = "// Analysis using ";
1236 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1237 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1238 type = "AOD";
1239 comment += "AOD";
1240 }
0df6ccf2 1241 if (type!="AOD" && fFriendChainName!="") {
1242 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1243 return;
1244 }
c57f56b7 1245 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1246 else comment += " data";
1247 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1248 func.ReplaceAll(".C", "");
1249 out << "void " << func.Data() << "()" << endl;
1250 out << "{" << endl;
1251 out << comment.Data() << endl;
1252 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 1253 out << " TStopwatch timer;" << endl;
1254 out << " timer.Start();" << endl << endl;
c57f56b7 1255 out << "// load base root libraries" << endl;
1256 out << " gSystem->Load(\"libTree\");" << endl;
1257 out << " gSystem->Load(\"libGeom\");" << endl;
1258 out << " gSystem->Load(\"libVMC\");" << endl;
1259 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
57377eb5 1260 out << "// Load analysis framework libraries" << endl;
4e5c5506 1261 if (!fPackages) {
4e5c5506 1262 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1263 out << " gSystem->Load(\"libESD\");" << endl;
1264 out << " gSystem->Load(\"libAOD\");" << endl;
1265 out << " gSystem->Load(\"libANALYSIS\");" << endl;
57377eb5 1266 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1267 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 1268 } else {
4e5c5506 1269 TIter next(fPackages);
1270 TObject *obj;
57377eb5 1271 TString pkgname;
1272 Bool_t hasSTEERBase = kFALSE;
1273 Bool_t hasESD = kFALSE;
1274 Bool_t hasAOD = kFALSE;
1275 Bool_t hasANALYSIS = kFALSE;
1276 Bool_t hasANALYSISalice = kFALSE;
1277 Bool_t hasCORRFW = kFALSE;
1278 while ((obj=next())) {
1279 pkgname = obj->GetName();
4478e6f1 1280 if (pkgname == "STEERBase" ||
1281 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1282 if (pkgname == "ESD" ||
1283 pkgname == "ESD.par") hasESD = kTRUE;
1284 if (pkgname == "AOD" ||
1285 pkgname == "AOD.par") hasAOD = kTRUE;
1286 if (pkgname == "ANALYSIS" ||
1287 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1288 if (pkgname == "ANALYSISalice" ||
1289 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1290 if (pkgname == "CORRFW" ||
1291 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
57377eb5 1292 }
1293 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1294 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1295 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1296 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1297 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1298 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1299 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1300 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1301 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1302 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1303 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1304 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1305 out << "// Compile other par packages" << endl;
1306 next.Reset();
fcc9bb6f 1307 while ((obj=next())) {
1308 pkgname = obj->GetName();
4478e6f1 1309 if (pkgname == "STEERBase" ||
1310 pkgname == "STEERBase.par" ||
1311 pkgname == "ESD" ||
1312 pkgname == "ESD.par" ||
1313 pkgname == "AOD" ||
1314 pkgname == "AOD.par" ||
1315 pkgname == "ANALYSIS" ||
1316 pkgname == "ANALYSIS.par" ||
1317 pkgname == "ANALYSISalice" ||
1318 pkgname == "ANALYSISalice.par" ||
1319 pkgname == "CORRFW" ||
1320 pkgname == "CORRFW.par") continue;
4e5c5506 1321 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 1322 }
4e5c5506 1323 }
43da816a 1324 out << "// include path" << endl;
1325 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1326 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
6da75e0b 1327 if (fAdditionalLibs.Length()) {
1328 out << "// Add aditional AliRoot libraries" << endl;
1329 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1330 TIter next(list);
1331 TObjString *str;
1332 while((str=(TObjString*)next())) {
1333 if (str->GetString().Contains(".so"))
1334 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1335 }
1336 if (list) delete list;
1337 }
1338 out << endl;
c57f56b7 1339 out << "// analysis source to be compiled at runtime (if any)" << endl;
1340 if (fAnalysisSource.Length()) {
1341 TObjArray *list = fAnalysisSource.Tokenize(" ");
1342 TIter next(list);
1343 TObjString *str;
1344 while((str=(TObjString*)next())) {
1345 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1346 }
1347 if (list) delete list;
1348 }
1349 out << endl;
1350 out << "// connect to AliEn and make the chain" << endl;
1351 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1352 if (IsUsingTags()) {
1353 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1354 } else {
1355 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1356 }
1357 out << "// read the analysis manager from file" << endl;
1358 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1359 out << " if (!file) return;" << endl;
1360 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1361 out << " AliAnalysisManager *mgr = 0;" << endl;
1362 out << " TKey *key;" << endl;
1363 out << " while ((key=(TKey*)nextkey())) {" << endl;
1364 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1365 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1366 out << " };" << endl;
1367 out << " if (!mgr) {" << endl;
1368 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1369 out << " return;" << endl;
1370 out << " }" << endl << endl;
1371 out << " mgr->PrintStatus();" << endl;
1372 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 1373 out << " timer.Stop();" << endl;
1374 out << " timer.Print();" << endl;
c57f56b7 1375 out << "}" << endl << endl;
1376 if (IsUsingTags()) {
1377 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1378 out << "{" << endl;
1379 out << "// Create a chain using tags from the xml file." << endl;
1380 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1381 out << " if (!coll) {" << endl;
1382 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1383 out << " return NULL;" << endl;
1384 out << " }" << endl;
1385 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1386 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1387 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1388 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1389 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1390 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1391 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1392 out << " // Check if the cuts configuration file was provided" << endl;
1393 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1394 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1395 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1396 out << " }" << endl;
0df6ccf2 1397 if (fFriendChainName=="") {
1398 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1399 } else {
1400 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1401 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1402 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1403 }
c57f56b7 1404 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1405 out << " chain->ls();" << endl;
1406 out << " return chain;" << endl;
fcc9bb6f 1407 out << "}" << endl << endl;
c57f56b7 1408 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1409 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1410 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1411 msg += " AliLHCTagCuts *lhcCuts,\n";
1412 msg += " AliDetectorTagCuts *detCuts,\n";
1413 msg += " AliEventTagCuts *evCuts)";
1414 Info("WriteAnalysisMacro", msg.Data());
1415 }
0df6ccf2 1416 }
1417 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 1418 out <<"//________________________________________________________________________________" << endl;
c57f56b7 1419 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1420 out << "{" << endl;
1421 out << "// Create a chain using url's from xml file" << endl;
1422 out << " TString treename = type;" << endl;
1423 out << " treename.ToLower();" << endl;
1424 out << " treename += \"Tree\";" << endl;
e02fee64 1425 out << " printf(\"***************************************\\n\");" << endl;
1426 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1427 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 1428 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1429 out << " if (!coll) {" << endl;
1430 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1431 out << " return NULL;" << endl;
1432 out << " }" << endl;
1433 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 1434 if(fFriendChainName!="") {
1435 out << " TChain *chainFriend = new TChain(treename);" << endl;
1436 }
c57f56b7 1437 out << " coll->Reset();" << endl;
0df6ccf2 1438 out << " while (coll->Next()) {" << endl;
1439 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1440 if(fFriendChainName!="") {
1441 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1442 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1443 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1444 out << " chainFriend->Add(fileFriend.Data());" << endl;
1445 }
1446 out << " }" << endl;
c57f56b7 1447 out << " if (!chain->GetNtrees()) {" << endl;
1448 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1449 out << " return NULL;" << endl;
1450 out << " }" << endl;
0df6ccf2 1451 if(fFriendChainName!="") {
1452 out << " chain->AddFriend(chainFriend);" << endl;
1453 }
c57f56b7 1454 out << " return chain;" << endl;
fcc9bb6f 1455 out << "}" << endl << endl;
c57f56b7 1456 }
4e5c5506 1457 if (fPackages) {
fcc9bb6f 1458 out <<"//________________________________________________________________________________" << endl;
4e5c5506 1459 out << "Bool_t SetupPar(const char *package) {" << endl;
1460 out << "// Compile the package and set it up." << endl;
1461 out << " TString pkgdir = package;" << endl;
1462 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
fcc9bb6f 1463 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
4e5c5506 1464 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1465 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1466 out << " // Check for BUILD.sh and execute" << endl;
1467 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1468 out << " printf(\"*******************************\\n\");" << endl;
1469 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1470 out << " printf(\"*******************************\\n\");" << endl;
1471 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
fcc9bb6f 1472 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
4e5c5506 1473 out << " gSystem->ChangeDirectory(cdir);" << endl;
1474 out << " return kFALSE;" << endl;
1475 out << " }" << endl;
1476 out << " } else {" << endl;
fcc9bb6f 1477 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
4e5c5506 1478 out << " gSystem->ChangeDirectory(cdir);" << endl;
1479 out << " return kFALSE;" << endl;
1480 out << " }" << endl;
1481 out << " // Check for SETUP.C and execute" << endl;
1482 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1483 out << " printf(\"*******************************\\n\");" << endl;
1484 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1485 out << " printf(\"*******************************\\n\");" << endl;
1486 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1487 out << " } else {" << endl;
fcc9bb6f 1488 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
4e5c5506 1489 out << " gSystem->ChangeDirectory(cdir);" << endl;
1490 out << " return kFALSE;" << endl;
1491 out << " }" << endl;
1492 out << " // Restore original workdir" << endl;
1493 out << " gSystem->ChangeDirectory(cdir);" << endl;
1494 out << " return kTRUE;" << endl;
1495 out << "}" << endl;
1496 }
c57f56b7 1497 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1498 }
1499 Bool_t copy = kTRUE;
1500 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1501 if (copy) {
1502 CdWork();
1503 TString workdir = gGrid->GetHomeDirectory();
1504 workdir += fGridWorkingDir;
1505 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1506 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1507 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1508 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1509 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1510 }
1511 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1512 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1513 }
1514}
1515
1516//______________________________________________________________________________
1517void AliAnalysisAlien::WriteExecutable()
1518{
1519// Generate the alien executable script.
1520 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1521 ofstream out;
1522 out.open(fExecutable.Data(), ios::out);
1523 if (out.bad()) {
1524 Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1525 return;
1526 }
1527 out << "#!/bin/bash" << endl;
1528 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1529 out << "echo \"=========================================\"" << endl;
1530 out << "echo \"############## PATH : ##############\"" << endl;
1531 out << "echo $PATH" << endl;
1532 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1533 out << "echo $LD_LIBRARY_PATH" << endl;
1534 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1535 out << "echo $ROOTSYS" << endl;
1536 out << "echo \"############## which root : ##############\"" << endl;
1537 out << "which root" << endl;
1538 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1539 out << "echo $ALICE_ROOT" << endl;
1540 out << "echo \"############## which aliroot : ##############\"" << endl;
1541 out << "which aliroot" << endl;
1542 out << "echo \"=========================================\"" << endl << endl;
1543// if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1544 out << "root -b -q ";
1545 out << fAnalysisMacro.Data() << endl << endl;
1546 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1547 }
1548 Bool_t copy = kTRUE;
1549 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1550 if (copy) {
1551 CdWork();
1552 TString workdir = gGrid->GetHomeDirectory();
1553 workdir += fGridWorkingDir;
1554 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1555 if (FileExists(executable)) gGrid->Rm(executable);
1556 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1557 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1558 }
1559}
1560
1561//______________________________________________________________________________
1562void AliAnalysisAlien::WriteValidationScript()
1563{
1564// Generate the alien validation script.
1565 // Generate the validation script
1566 TObjString *os;
1567 if (!Connect()) {
1568 Error("WriteValidationScript", "Alien connection required");
1569 return;
1570 }
1571 TString out_stream = "";
1572 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1573 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1574 ofstream out;
1575 out.open("validate.sh", ios::out);
1576 out << "#!/bin/bash" << endl;
1577 out << "##################################################" << endl;
1578 out << "validateout=`dirname $0`" << endl;
1579 out << "validatetime=`date`" << endl;
1580 out << "validated=\"0\";" << endl;
1581 out << "error=0" << endl;
1582 out << "if [ -z $validateout ]" << endl;
1583 out << "then" << endl;
1584 out << " validateout=\".\"" << endl;
1585 out << "fi" << endl << endl;
1586 out << "cd $validateout;" << endl;
1587 out << "validateworkdir=`pwd`;" << endl << endl;
1588 out << "echo \"*******************************************************\"" << out_stream << endl;
1589 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1590 out << "" << endl;
1591 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1592 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1593 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1594 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1595 out << "ls -la ./" << out_stream << endl;
1596 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1597 out << "##################################################" << endl;
ebec370a 1598
1599 out << "" << endl;
1600 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
1601 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
1602 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
1603 out << "" << endl;
1604
1605 out << "if [ ! -f stderr ] ; then" << endl;
1606 out << " error=1" << endl;
1607 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
1608 out << " echo \"Error = $error\" " << out_stream << endl;
1609 out << "fi" << endl;
1610
1611 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
1612 out << " error=1" << endl;
1613 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
1614 out << " echo \"$parArch\" " << out_stream << endl;
1615 out << " echo \"Error = $error\" " << out_stream << endl;
1616 out << "fi" << endl;
1617
1618 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
1619 out << " error=1" << endl;
1620 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
1621 out << " echo \"$segViol\" " << out_stream << endl;
1622 out << " echo \"Error = $error\" " << out_stream << endl;
1623 out << "fi" << endl;
1624
1625 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
1626 out << " error=1" << endl;
1627 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
1628 out << " echo \"$segFault\" " << out_stream << endl;
1629 out << " echo \"Error = $error\" " << out_stream << endl;
1630 out << "fi" << endl;
1631
1632 // Part dedicated to the specific analyses running into the train
1633
c57f56b7 1634 TObjArray *arr = fOutputFiles.Tokenize(" ");
1635 TIter next1(arr);
1636 TString output_file;
1637 while ((os=(TObjString*)next1())) {
1638 output_file = os->GetString();
1639 Int_t index = output_file.Index("@");
1640 if (index > 0) output_file.Remove(index);
1641 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1642 out << " error=1" << endl;
1643 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
1644 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
1645 out << "fi" << endl;
1646 }
1647 delete arr;
1648 out << "if [ $error = 0 ] ; then" << endl;
1649 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
1650 out << "fi" << endl;
1651
1652 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1653 out << "echo \"*******************************************************\"" << out_stream << endl;
1654 out << "cd -" << endl;
1655 out << "exit $error" << endl;
1656 }
1657 Bool_t copy = kTRUE;
1658 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1659 if (copy) {
1660 CdWork();
1661 TString workdir = gGrid->GetHomeDirectory();
1662 workdir += fGridWorkingDir;
1663 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
1664 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
1665 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));
1666 }
1667}