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