]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - ANALYSIS/AliAnalysisAlien.cxx
correct leak in AliIsolationCut
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisAlien.cxx
... / ...
CommitLineData
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 "TEnv.h"
25#include "TError.h"
26#include "TROOT.h"
27#include "TSystem.h"
28#include "TFile.h"
29#include "TObjString.h"
30#include "TObjArray.h"
31#include "TGrid.h"
32#include "TGridResult.h"
33#include "TGridCollection.h"
34#include "TGridJDL.h"
35#include "TGridJobStatusList.h"
36#include "TGridJobStatus.h"
37#include "TFileMerger.h"
38#include "AliAnalysisManager.h"
39#include "AliVEventHandler.h"
40#include "AliAnalysisDataContainer.h"
41#include "AliAnalysisAlien.h"
42
43ClassImp(AliAnalysisAlien)
44
45//______________________________________________________________________________
46AliAnalysisAlien::AliAnalysisAlien()
47 :AliAnalysisGrid(),
48 fGridJDL(NULL),
49 fMergingJDL(NULL),
50 fPrice(0),
51 fTTL(0),
52 fSplitMaxInputFileNumber(0),
53 fMaxInitFailed(0),
54 fMasterResubmitThreshold(0),
55 fNtestFiles(0),
56 fNrunsPerMaster(0),
57 fMaxMergeFiles(0),
58 fNsubmitted(0),
59 fProductionMode(0),
60 fOutputToRunNo(0),
61 fMergeViaJDL(0),
62 fFastReadOption(0),
63 fOverwriteMode(0),
64 fRunNumbers(),
65 fExecutable(),
66 fExecutableCommand(),
67 fArguments(),
68 fExecutableArgs(),
69 fAnalysisMacro(),
70 fAnalysisSource(),
71 fAdditionalRootLibs(),
72 fAdditionalLibs(),
73 fSplitMode(),
74 fAPIVersion(),
75 fROOTVersion(),
76 fAliROOTVersion(),
77 fExternalPackages(),
78 fUser(),
79 fGridWorkingDir(),
80 fGridDataDir(),
81 fDataPattern(),
82 fGridOutputDir(),
83 fOutputArchive(),
84 fOutputFiles(),
85 fInputFormat(),
86 fDatasetName(),
87 fJDLName(),
88 fMergeExcludes(),
89 fIncludePath(),
90 fCloseSE(),
91 fFriendChainName(),
92 fJobTag(),
93 fOutputSingle(),
94 fRunPrefix(),
95 fInputFiles(0),
96 fPackages(0)
97{
98// Dummy ctor.
99 SetDefaults();
100}
101
102//______________________________________________________________________________
103AliAnalysisAlien::AliAnalysisAlien(const char *name)
104 :AliAnalysisGrid(name),
105 fGridJDL(NULL),
106 fMergingJDL(NULL),
107 fPrice(0),
108 fTTL(0),
109 fSplitMaxInputFileNumber(0),
110 fMaxInitFailed(0),
111 fMasterResubmitThreshold(0),
112 fNtestFiles(0),
113 fNrunsPerMaster(0),
114 fMaxMergeFiles(0),
115 fNsubmitted(0),
116 fProductionMode(0),
117 fOutputToRunNo(0),
118 fMergeViaJDL(0),
119 fFastReadOption(0),
120 fOverwriteMode(0),
121 fRunNumbers(),
122 fExecutable(),
123 fExecutableCommand(),
124 fArguments(),
125 fExecutableArgs(),
126 fAnalysisMacro(),
127 fAnalysisSource(),
128 fAdditionalRootLibs(),
129 fAdditionalLibs(),
130 fSplitMode(),
131 fAPIVersion(),
132 fROOTVersion(),
133 fAliROOTVersion(),
134 fExternalPackages(),
135 fUser(),
136 fGridWorkingDir(),
137 fGridDataDir(),
138 fDataPattern(),
139 fGridOutputDir(),
140 fOutputArchive(),
141 fOutputFiles(),
142 fInputFormat(),
143 fDatasetName(),
144 fJDLName(),
145 fMergeExcludes(),
146 fIncludePath(),
147 fCloseSE(),
148 fFriendChainName(),
149 fJobTag(),
150 fOutputSingle(),
151 fRunPrefix(),
152 fInputFiles(0),
153 fPackages(0)
154{
155// Default ctor.
156 SetDefaults();
157}
158
159//______________________________________________________________________________
160AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
161 :AliAnalysisGrid(other),
162 fGridJDL(NULL),
163 fMergingJDL(NULL),
164 fPrice(other.fPrice),
165 fTTL(other.fTTL),
166 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
167 fMaxInitFailed(other.fMaxInitFailed),
168 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
169 fNtestFiles(other.fNtestFiles),
170 fNrunsPerMaster(other.fNrunsPerMaster),
171 fMaxMergeFiles(other.fMaxMergeFiles),
172 fNsubmitted(other.fNsubmitted),
173 fProductionMode(other.fProductionMode),
174 fOutputToRunNo(other.fOutputToRunNo),
175 fMergeViaJDL(other.fMergeViaJDL),
176 fFastReadOption(other.fFastReadOption),
177 fOverwriteMode(other.fOverwriteMode),
178 fRunNumbers(other.fRunNumbers),
179 fExecutable(other.fExecutable),
180 fExecutableCommand(other.fExecutableCommand),
181 fArguments(other.fArguments),
182 fExecutableArgs(other.fExecutableArgs),
183 fAnalysisMacro(other.fAnalysisMacro),
184 fAnalysisSource(other.fAnalysisSource),
185 fAdditionalRootLibs(other.fAdditionalRootLibs),
186 fAdditionalLibs(other.fAdditionalLibs),
187 fSplitMode(other.fSplitMode),
188 fAPIVersion(other.fAPIVersion),
189 fROOTVersion(other.fROOTVersion),
190 fAliROOTVersion(other.fAliROOTVersion),
191 fExternalPackages(other.fExternalPackages),
192 fUser(other.fUser),
193 fGridWorkingDir(other.fGridWorkingDir),
194 fGridDataDir(other.fGridDataDir),
195 fDataPattern(other.fDataPattern),
196 fGridOutputDir(other.fGridOutputDir),
197 fOutputArchive(other.fOutputArchive),
198 fOutputFiles(other.fOutputFiles),
199 fInputFormat(other.fInputFormat),
200 fDatasetName(other.fDatasetName),
201 fJDLName(other.fJDLName),
202 fMergeExcludes(other.fMergeExcludes),
203 fIncludePath(other.fIncludePath),
204 fCloseSE(other.fCloseSE),
205 fFriendChainName(other.fFriendChainName),
206 fJobTag(other.fJobTag),
207 fOutputSingle(other.fOutputSingle),
208 fRunPrefix(other.fRunPrefix),
209 fInputFiles(0),
210 fPackages(0)
211{
212// Copy ctor.
213 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
214 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
215 fRunRange[0] = other.fRunRange[0];
216 fRunRange[1] = other.fRunRange[1];
217 if (other.fInputFiles) {
218 fInputFiles = new TObjArray();
219 TIter next(other.fInputFiles);
220 TObject *obj;
221 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
222 fInputFiles->SetOwner();
223 }
224 if (other.fPackages) {
225 fPackages = new TObjArray();
226 TIter next(other.fPackages);
227 TObject *obj;
228 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
229 fPackages->SetOwner();
230 }
231}
232
233//______________________________________________________________________________
234AliAnalysisAlien::~AliAnalysisAlien()
235{
236// Destructor.
237 if (fGridJDL) delete fGridJDL;
238 if (fMergingJDL) delete fMergingJDL;
239 if (fInputFiles) delete fInputFiles;
240 if (fPackages) delete fPackages;
241}
242
243//______________________________________________________________________________
244AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
245{
246// Assignment.
247 if (this != &other) {
248 AliAnalysisGrid::operator=(other);
249 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
250 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
251 fPrice = other.fPrice;
252 fTTL = other.fTTL;
253 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
254 fMaxInitFailed = other.fMaxInitFailed;
255 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
256 fNtestFiles = other.fNtestFiles;
257 fNrunsPerMaster = other.fNrunsPerMaster;
258 fMaxMergeFiles = other.fMaxMergeFiles;
259 fNsubmitted = other.fNsubmitted;
260 fProductionMode = other.fProductionMode;
261 fOutputToRunNo = other.fOutputToRunNo;
262 fMergeViaJDL = other.fMergeViaJDL;
263 fFastReadOption = other.fFastReadOption;
264 fOverwriteMode = other.fOverwriteMode;
265 fRunNumbers = other.fRunNumbers;
266 fExecutable = other.fExecutable;
267 fExecutableCommand = other.fExecutableCommand;
268 fArguments = other.fArguments;
269 fExecutableArgs = other.fExecutableArgs;
270 fAnalysisMacro = other.fAnalysisMacro;
271 fAnalysisSource = other.fAnalysisSource;
272 fAdditionalRootLibs = other.fAdditionalRootLibs;
273 fAdditionalLibs = other.fAdditionalLibs;
274 fSplitMode = other.fSplitMode;
275 fAPIVersion = other.fAPIVersion;
276 fROOTVersion = other.fROOTVersion;
277 fAliROOTVersion = other.fAliROOTVersion;
278 fExternalPackages = other.fExternalPackages;
279 fUser = other.fUser;
280 fGridWorkingDir = other.fGridWorkingDir;
281 fGridDataDir = other.fGridDataDir;
282 fDataPattern = other.fDataPattern;
283 fGridOutputDir = other.fGridOutputDir;
284 fOutputArchive = other.fOutputArchive;
285 fOutputFiles = other.fOutputFiles;
286 fInputFormat = other.fInputFormat;
287 fDatasetName = other.fDatasetName;
288 fJDLName = other.fJDLName;
289 fMergeExcludes = other.fMergeExcludes;
290 fIncludePath = other.fIncludePath;
291 fCloseSE = other.fCloseSE;
292 fFriendChainName = other.fFriendChainName;
293 fJobTag = other.fJobTag;
294 fOutputSingle = other.fOutputSingle;
295 fRunPrefix = other.fRunPrefix;
296 if (other.fInputFiles) {
297 fInputFiles = new TObjArray();
298 TIter next(other.fInputFiles);
299 TObject *obj;
300 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
301 fInputFiles->SetOwner();
302 }
303 if (other.fPackages) {
304 fPackages = new TObjArray();
305 TIter next(other.fPackages);
306 TObject *obj;
307 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
308 fPackages->SetOwner();
309 }
310 }
311 return *this;
312}
313
314//______________________________________________________________________________
315void AliAnalysisAlien::AddIncludePath(const char *path)
316{
317// Add include path in the remote analysis macro.
318 TString p(path);
319 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
320 else fIncludePath += Form("-I%s ", path);
321}
322
323//______________________________________________________________________________
324void AliAnalysisAlien::AddRunNumber(Int_t run)
325{
326// Add a run number to the list of runs to be processed.
327 if (fRunNumbers.Length()) fRunNumbers += " ";
328 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
329}
330
331//______________________________________________________________________________
332void AliAnalysisAlien::AddRunNumber(const char* run)
333{
334// Add a run number to the list of runs to be processed.
335 if (fRunNumbers.Length()) fRunNumbers += " ";
336 fRunNumbers += run;
337}
338
339//______________________________________________________________________________
340void AliAnalysisAlien::AddDataFile(const char *lfn)
341{
342// Adds a data file to the input to be analysed. The file should be a valid LFN
343// or point to an existing file in the alien workdir.
344 if (!fInputFiles) fInputFiles = new TObjArray();
345 fInputFiles->Add(new TObjString(lfn));
346}
347
348//______________________________________________________________________________
349void AliAnalysisAlien::AddExternalPackage(const char *package)
350{
351// Adds external packages w.r.t to the default ones (root,aliroot and gapi)
352 if (fExternalPackages) fExternalPackages += " ";
353 fExternalPackages += package;
354}
355
356//______________________________________________________________________________
357Bool_t AliAnalysisAlien::Connect()
358{
359// Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
360 if (gGrid && gGrid->IsConnected()) return kTRUE;
361 if (!gSystem->Getenv("alien_API_USER")) {
362 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
363 gSystem->Getenv("UID"));
364 return kFALSE;
365 }
366 if (!gGrid) {
367 Info("Connect", "Trying to connect to AliEn ...");
368 TGrid::Connect("alien://");
369 }
370 if (!gGrid || !gGrid->IsConnected()) {
371 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
372 return kFALSE;
373 }
374 fUser = gGrid->GetUser();
375 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
376 return kTRUE;
377}
378
379//______________________________________________________________________________
380void AliAnalysisAlien::CdWork()
381{
382// Check validity of alien workspace. Create directory if possible.
383 if (!Connect()) {
384 Error("CdWork", "Alien connection required");
385 return;
386 }
387 TString homedir = gGrid->GetHomeDirectory();
388 TString workdir = homedir + fGridWorkingDir;
389 if (DirectoryExists(workdir)) {
390 gGrid->Cd(workdir);
391 return;
392 }
393 // Work directory not existing - create it
394 gGrid->Cd(homedir);
395 if (gGrid->Mkdir(workdir)) {
396 gGrid->Cd(fGridWorkingDir);
397 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
398 } else {
399 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
400 workdir.Data(), homedir.Data());
401 fGridWorkingDir = "";
402 }
403}
404
405//______________________________________________________________________________
406Bool_t AliAnalysisAlien::CheckInputData()
407{
408// Check validity of input data. If necessary, create xml files.
409 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
410 if (!fGridDataDir.Length()) {
411 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
412 return kFALSE;
413 }
414 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
415 return kTRUE;
416 }
417 // Process declared files
418 Bool_t is_collection = kFALSE;
419 Bool_t is_xml = kFALSE;
420 Bool_t use_tags = kFALSE;
421 Bool_t checked = kFALSE;
422 CdWork();
423 TString file;
424 TString workdir = gGrid->GetHomeDirectory();
425 workdir += fGridWorkingDir;
426 if (fInputFiles) {
427 TObjString *objstr;
428 TIter next(fInputFiles);
429 while ((objstr=(TObjString*)next())) {
430 file = workdir;
431 file += "/";
432 file += objstr->GetString();
433 // Store full lfn path
434 if (FileExists(file)) objstr->SetString(file);
435 else {
436 file = objstr->GetName();
437 if (!FileExists(objstr->GetName())) {
438 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
439 objstr->GetName(), workdir.Data());
440 return kFALSE;
441 }
442 }
443 Bool_t iscoll, isxml, usetags;
444 CheckDataType(file, iscoll, isxml, usetags);
445 if (!checked) {
446 checked = kTRUE;
447 is_collection = iscoll;
448 is_xml = isxml;
449 use_tags = usetags;
450 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
451 } else {
452 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
453 Error("CheckInputData", "Some conflict was found in the types of inputs");
454 return kFALSE;
455 }
456 }
457 }
458 }
459 // Process requested run numbers
460 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
461 // Check validity of alien data directory
462 if (!fGridDataDir.Length()) {
463 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
464 return kFALSE;
465 }
466 if (!DirectoryExists(fGridDataDir)) {
467 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
468 return kFALSE;
469 }
470 if (is_collection) {
471 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
472 return kFALSE;
473 }
474
475 if (checked && !is_xml) {
476 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
477 return kFALSE;
478 }
479 // Check validity of run number(s)
480 TObjArray *arr;
481 TObjString *os;
482 Int_t nruns = 0;
483 TString schunk, schunk2;
484 TString path;
485 if (!checked) {
486 checked = kTRUE;
487 use_tags = fDataPattern.Contains("tag");
488 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
489 }
490 if (use_tags != fDataPattern.Contains("tag")) {
491 Error("CheckInputData", "Cannot mix input files using/not using tags");
492 return kFALSE;
493 }
494 if (fRunNumbers.Length()) {
495 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
496 arr = fRunNumbers.Tokenize(" ");
497 TIter next(arr);
498 while ((os=(TObjString*)next())) {
499 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
500 if (!DirectoryExists(path)) {
501 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
502 continue;
503 }
504 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
505 TString msg = "\n##### file: ";
506 msg += path;
507 msg += " type: xml_collection;";
508 if (use_tags) msg += " using_tags: Yes";
509 else msg += " using_tags: No";
510 Info("CheckDataType", msg.Data());
511 if (fNrunsPerMaster<2) {
512 AddDataFile(Form("%s.xml", os->GetString().Data()));
513 } else {
514 nruns++;
515 if (((nruns-1)%fNrunsPerMaster) == 0) {
516 schunk = os->GetString();
517 }
518 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
519 schunk += Form("_%s.xml", os->GetString().Data());
520 AddDataFile(schunk);
521 }
522 }
523 delete arr;
524 } else {
525 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
526 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
527 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
528 if (!DirectoryExists(path)) {
529// Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
530 continue;
531 }
532 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
533 TString msg = "\n##### file: ";
534 msg += path;
535 msg += " type: xml_collection;";
536 if (use_tags) msg += " using_tags: Yes";
537 else msg += " using_tags: No";
538 Info("CheckDataType", msg.Data());
539 if (fNrunsPerMaster<2) {
540 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
541 } else {
542 nruns++;
543 if (((nruns-1)%fNrunsPerMaster) == 0) {
544 schunk = Form("%s%d", fRunPrefix.Data(),irun);
545 }
546 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
547 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
548 schunk += schunk2;
549 AddDataFile(schunk);
550 }
551 }
552 if (!fInputFiles) {
553 schunk += schunk2;
554 AddDataFile(schunk);
555 }
556 }
557 return kTRUE;
558}
559
560//______________________________________________________________________________
561Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
562{
563// Create dataset for the grid data directory + run number.
564 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
565 if (!Connect()) {
566 Error("CreateDataset", "Cannot create dataset with no grid connection");
567 return kFALSE;
568 }
569
570 // Cd workspace
571 CdWork();
572 TString workdir = gGrid->GetHomeDirectory();
573 workdir += fGridWorkingDir;
574
575 // Compose the 'find' command arguments
576 TString command;
577 TString options = "-x collection ";
578 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
579 TString conditions = "";
580
581 TString file;
582 TString path;
583 Int_t nruns = 0;
584 TString schunk, schunk2;
585 TGridCollection *cbase=0, *cadd=0;
586 if (!fRunNumbers.Length() && !fRunRange[0]) {
587 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
588 // Make a single data collection from data directory.
589 path = fGridDataDir;
590 if (!DirectoryExists(path)) {
591 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
592 return kFALSE;
593 }
594// CdWork();
595 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
596 else file = Form("%s.xml", gSystem->BaseName(path));
597 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
598 command = "find ";
599 command += options;
600 command += path;
601 command += " ";
602 command += pattern;
603 command += conditions;
604 printf("command: %s\n", command.Data());
605 TGridResult *res = gGrid->Command(command);
606 if (res) delete res;
607 // Write standard output to file
608 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
609 }
610 Bool_t fileExists = FileExists(file);
611 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
612 // Copy xml file to alien space
613 if (fileExists) gGrid->Rm(file);
614 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
615 if (!FileExists(file)) {
616 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
617 return kFALSE;
618 }
619 // Update list of files to be processed.
620 }
621 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
622 return kTRUE;
623 }
624 // Several runs
625 if (fRunNumbers.Length()) {
626 TObjArray *arr = fRunNumbers.Tokenize(" ");
627 TObjString *os;
628 TIter next(arr);
629 while ((os=(TObjString*)next())) {
630 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
631 if (!DirectoryExists(path)) continue;
632// CdWork();
633 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
634 else file = Form("%s.xml", os->GetString().Data());
635 // If local collection file does not exist, create it via 'find' command.
636 if (gSystem->AccessPathName(file)) {
637 command = "find ";
638 command += options;
639 command += path;
640 command += pattern;
641 command += conditions;
642 TGridResult *res = gGrid->Command(command);
643 if (res) delete res;
644 // Write standard output to file
645 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
646 }
647 if (TestBit(AliAnalysisGrid::kTest)) break;
648 // Check if there is one run per master job.
649 if (fNrunsPerMaster<2) {
650 if (FileExists(file)) {
651 if (fOverwriteMode) gGrid->Rm(file);
652 else {
653 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
654 continue;
655 }
656 }
657 // Copy xml file to alien space
658 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
659 if (!FileExists(file)) {
660 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
661 delete arr;
662 return kFALSE;
663 }
664 } else {
665 nruns++;
666 if (((nruns-1)%fNrunsPerMaster) == 0) {
667 schunk = os->GetString();
668 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
669 } else {
670 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
671 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
672 cbase->Add(cadd);
673 delete cadd;
674 }
675 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
676 continue;
677 }
678 schunk += Form("_%s.xml", os->GetString().Data());
679 if (FileExists(schunk)) {
680 if (fOverwriteMode) gGrid->Rm(file);
681 else {
682 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
683 continue;
684 }
685 }
686 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
687 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
688 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
689 if (!FileExists(schunk)) {
690 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
691 delete arr;
692 return kFALSE;
693 }
694 }
695 }
696 delete arr;
697 } else {
698 // Process a full run range.
699 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
700 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
701 if (!DirectoryExists(path)) continue;
702// CdWork();
703 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
704 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
705 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
706 if (fOverwriteMode) gGrid->Rm(file);
707 else {
708 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
709 continue;
710 }
711 }
712 // If local collection file does not exist, create it via 'find' command.
713 if (gSystem->AccessPathName(file) || fOverwriteMode) {
714 command = "find ";
715 command += options;
716 command += path;
717 command += pattern;
718 command += conditions;
719 TGridResult *res = gGrid->Command(command);
720 if (res) delete res;
721 // Write standard output to file
722 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
723 }
724 if (TestBit(AliAnalysisGrid::kTest)) break;
725 // Check if there is one run per master job.
726 if (fNrunsPerMaster<2) {
727 if (FileExists(file)) {
728 if (fOverwriteMode) gGrid->Rm(file);
729 else {
730 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
731 continue;
732 }
733 }
734 // Copy xml file to alien space
735 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
736 if (!FileExists(file)) {
737 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
738 return kFALSE;
739 }
740 } else {
741 nruns++;
742 // Check if the collection for the chunk exist locally.
743 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
744 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
745 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
746 else continue;
747 }
748 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
749 if (((nruns-1)%fNrunsPerMaster) == 0) {
750 schunk = Form("%s%d", fRunPrefix.Data(), irun);
751 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
752 } else {
753 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
754 cbase->Add(cadd);
755 delete cadd;
756 }
757 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
758 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
759 continue;
760 }
761 schunk = schunk2;
762 if (FileExists(schunk)) {
763 if (fOverwriteMode) gGrid->Rm(schunk);
764 else {
765 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
766 continue;
767 }
768 }
769 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
770 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
771 if (FileExists(schunk)) {
772 if (fOverwriteMode) gGrid->Rm(schunk);
773 else {
774 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
775 continue;
776 }
777 }
778 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
779 if (!FileExists(schunk)) {
780 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
781 return kFALSE;
782 }
783 }
784 }
785 }
786 return kTRUE;
787}
788
789//______________________________________________________________________________
790Bool_t AliAnalysisAlien::CreateJDL()
791{
792// Generate a JDL file according to current settings. The name of the file is
793// specified by fJDLName.
794 Bool_t error = kFALSE;
795 TObjArray *arr = 0;
796 Bool_t copy = kTRUE;
797 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
798 Bool_t generate = kTRUE;
799 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
800 if (!Connect()) {
801 Error("CreateJDL", "Alien connection required");
802 return kFALSE;
803 }
804 // Check validity of alien workspace
805 CdWork();
806 TString workdir = gGrid->GetHomeDirectory();
807 workdir += fGridWorkingDir;
808 if (generate) {
809 TObjString *os;
810 if (!fInputFiles) {
811 Error("CreateJDL()", "Define some input files for your analysis.");
812 error = kTRUE;
813 }
814 // Compose list of input files
815 // Check if output files were defined
816 if (!fOutputFiles.Length()) {
817 Error("CreateJDL", "You must define at least one output file");
818 error = kTRUE;
819 }
820 // Check if an output directory was defined and valid
821 if (!fGridOutputDir.Length()) {
822 Error("CreateJDL", "You must define AliEn output directory");
823 error = kTRUE;
824 } else {
825 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
826 if (!DirectoryExists(fGridOutputDir)) {
827 if (gGrid->Mkdir(fGridOutputDir)) {
828 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
829 } else {
830 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
831 // error = kTRUE;
832 }
833 }
834 gGrid->Cd(workdir);
835 }
836 // Exit if any error up to now
837 if (error) return kFALSE;
838 // Set JDL fields
839 if (!fUser.IsNull()) {
840 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
841 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
842 }
843 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
844 TString mergeExec = fExecutable;
845 mergeExec.ReplaceAll(".sh", "_merge.sh");
846 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
847 mergeExec.ReplaceAll(".sh", ".C");
848 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
849 if (!fArguments.IsNull())
850 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
851 fMergingJDL->SetArguments("$1");
852 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
853 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
854 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
855 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
856
857 if (fMaxInitFailed > 0) {
858 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
859 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
860 }
861 if (fSplitMaxInputFileNumber > 0) {
862 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
863 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
864 }
865 if (fSplitMode.Length()) {
866 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
867 fGridJDL->SetDescription("Split", "We split per SE or file");
868 }
869 if (!fAliROOTVersion.IsNull()) {
870 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
871 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
872 }
873 if (!fROOTVersion.IsNull()) {
874 fGridJDL->AddToPackages("ROOT", fROOTVersion);
875 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
876 }
877 if (!fAPIVersion.IsNull()) {
878 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
879 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
880 }
881 if (!fExternalPackages.IsNull()) {
882 arr = fExternalPackages.Tokenize(" ");
883 TIter next(arr);
884 while ((os=(TObjString*)next())) {
885 TString pkgname = os->GetString();
886 Int_t index = pkgname.Index("::");
887 TString pkgversion = pkgname(index+2, pkgname.Length());
888 pkgname.Remove(index);
889 fGridJDL->AddToPackages(pkgname, pkgversion);
890 fMergingJDL->AddToPackages(pkgname, pkgversion);
891 }
892 delete arr;
893 }
894 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
895 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
896 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
897 TString analysisFile = fExecutable;
898 analysisFile.ReplaceAll(".sh", ".root");
899 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
900 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
901 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
902 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
903 if (fAdditionalLibs.Length()) {
904 arr = fAdditionalLibs.Tokenize(" ");
905 TIter next(arr);
906 while ((os=(TObjString*)next())) {
907 if (os->GetString().Contains(".so")) continue;
908 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
909 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
910 }
911 delete arr;
912 }
913 if (fPackages) {
914 TIter next(fPackages);
915 TObject *obj;
916 while ((obj=next())) {
917 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
918 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
919 }
920 }
921 if (fOutputArchive.Length()) {
922 arr = fOutputArchive.Tokenize(" ");
923 TIter next(arr);
924 Bool_t first = kTRUE;
925 const char *comment = "Files to be archived";
926 const char *comment1 = comment;
927 while ((os=(TObjString*)next())) {
928 if (!first) comment = NULL;
929 if (!os->GetString().Contains("@") && fCloseSE.Length())
930 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
931 else
932 fGridJDL->AddToOutputArchive(os->GetString(), comment);
933 first = kFALSE;
934 }
935 delete arr;
936 TString outputArchive = fOutputArchive;
937 if (!fMergeExcludes.IsNull()) {
938 arr = fMergeExcludes.Tokenize(" ");
939 TIter next1(arr);
940 while ((os=(TObjString*)next1())) {
941 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
942 outputArchive.ReplaceAll(os->GetString(),"");
943 }
944 delete arr;
945 }
946 arr = outputArchive.Tokenize(" ");
947 TIter next2(arr);
948 comment = comment1;
949 first = kTRUE;
950 while ((os=(TObjString*)next2())) {
951 if (!first) comment = NULL;
952 if (!os->GetString().Contains("@") && fCloseSE.Length())
953 fMergingJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
954 else
955 fMergingJDL->AddToOutputArchive(os->GetString(), comment);
956 first = kFALSE;
957 }
958 delete arr;
959 }
960 arr = fOutputFiles.Tokenize(" ");
961 TIter next(arr);
962 Bool_t first = kTRUE;
963 const char *comment = "Files to be archived";
964 const char *comment1 = comment;
965 while ((os=(TObjString*)next())) {
966 // Ignore ouputs in jdl that are also in outputarchive
967 TString sout = os->GetString();
968 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
969 if (fOutputArchive.Contains(sout)) continue;
970 if (!first) comment = NULL;
971 if (!os->GetString().Contains("@") && fCloseSE.Length())
972 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
973 else
974 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
975 first = kFALSE;
976 }
977 delete arr;
978 if (fOutputFiles.Length()) {
979 TString outputFiles = fOutputFiles;
980 if (!fMergeExcludes.IsNull()) {
981 arr = fMergeExcludes.Tokenize(" ");
982 TIter next1(arr);
983 while ((os=(TObjString*)next1())) {
984 outputFiles.ReplaceAll(Form("%s,",os->GetString().Data()),"");
985 outputFiles.ReplaceAll(os->GetString(),"");
986 }
987 delete arr;
988 }
989 arr = outputFiles.Tokenize(" ");
990 TIter next2(arr);
991 comment = comment1;
992 first = kTRUE;
993 while ((os=(TObjString*)next2())) {
994 // Ignore ouputs in jdl that are also in outputarchive
995 TString sout = os->GetString();
996 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
997 if (fOutputArchive.Contains(sout)) continue;
998 if (!first) comment = NULL;
999 if (!os->GetString().Contains("@") && fCloseSE.Length())
1000 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1001 else
1002 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1003 }
1004 delete arr;
1005 }
1006 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1007 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1008 TString validationScript = fExecutable;
1009 validationScript.ReplaceAll(".sh", "_validation.sh");
1010 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1011 validationScript = fExecutable;
1012 validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
1013 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1014 if (fMasterResubmitThreshold) {
1015 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1016 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1017 }
1018 // Write a jdl with 2 input parameters: collection name and output dir name.
1019 WriteJDL(copy);
1020 }
1021 // Copy jdl to grid workspace
1022 if (copy) {
1023 // Check if an output directory was defined and valid
1024 if (!fGridOutputDir.Length()) {
1025 Error("CreateJDL", "You must define AliEn output directory");
1026 return kFALSE;
1027 } else {
1028 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1029 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1030 if (gGrid->Mkdir(fGridOutputDir)) {
1031 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1032 } else {
1033 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1034 return kFALSE;
1035 }
1036 }
1037 gGrid->Cd(workdir);
1038 }
1039 if (TestBit(AliAnalysisGrid::kSubmit)) {
1040 TString mergeJDLName = fExecutable;
1041 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1042 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1043 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1044 if (fProductionMode) {
1045 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1046 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1047 }
1048 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1049 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1050 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1051 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1052 if (fMergeViaJDL) {
1053 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1054 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1055 }
1056 }
1057 if (fAdditionalLibs.Length()) {
1058 arr = fAdditionalLibs.Tokenize(" ");
1059 TObjString *os;
1060 TIter next(arr);
1061 while ((os=(TObjString*)next())) {
1062 if (os->GetString().Contains(".so")) continue;
1063 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1064 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1065 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1066 }
1067 delete arr;
1068 }
1069 if (fPackages) {
1070 TIter next(fPackages);
1071 TObject *obj;
1072 while ((obj=next())) {
1073 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1074 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1075 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1076 }
1077 }
1078 }
1079 return kTRUE;
1080}
1081
1082//______________________________________________________________________________
1083Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1084{
1085// Writes one or more JDL's corresponding to findex. If findex is negative,
1086// all run numbers are considered in one go (jdl). For non-negative indices
1087// they correspond to the indices in the array fInputFiles.
1088 if (!fInputFiles) return kFALSE;
1089 TObjString *os;
1090 TString workdir = gGrid->GetHomeDirectory();
1091 workdir += fGridWorkingDir;
1092
1093 if (!fRunNumbers.Length() && !fRunRange[0]) {
1094 // One jdl with no parameters in case input data is specified by name.
1095 TIter next(fInputFiles);
1096 while ((os=(TObjString*)next()))
1097 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()), "Input xml collections");
1098 if (!fOutputSingle.IsNull())
1099 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1100 else {
1101 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1102 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1103 }
1104 } else {
1105 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1106 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1107 if (!fOutputSingle.IsNull()) {
1108 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1109 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1110 } else {
1111 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1112 fMergingJDL->SetOutputDirectory(Form("%s/$1", fGridOutputDir.Data()), "Output directory");
1113 }
1114 }
1115
1116
1117 // Generate the JDL as a string
1118 TString sjdl = fGridJDL->Generate();
1119 TString sjdl1 = fMergingJDL->Generate();
1120 Int_t index;
1121 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1122 sjdl.ReplaceAll("(member", "\n (member");
1123 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1124 sjdl.ReplaceAll("{", "{\n ");
1125 sjdl.ReplaceAll("};", "\n};");
1126 sjdl.ReplaceAll("{\n \n", "{\n");
1127 sjdl.ReplaceAll("\n\n", "\n");
1128 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1129 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1130 sjdl1.ReplaceAll("(member", "\n (member");
1131 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1132 sjdl1.ReplaceAll("{", "{\n ");
1133 sjdl1.ReplaceAll("};", "\n};");
1134 sjdl1.ReplaceAll("{\n \n", "{\n");
1135 sjdl1.ReplaceAll("\n\n", "\n");
1136 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1137 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1138 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1139 index = sjdl.Index("JDLVariables");
1140 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1141 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1142 sjdl1.Prepend(Form("Jobtag = {\n \"comment:Merging_%s\"\n};\n", fJobTag.Data()));
1143 index = sjdl1.Index("JDLVariables");
1144 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1145 // Write jdl to file
1146 ofstream out;
1147 out.open(fJDLName.Data(), ios::out);
1148 if (out.bad()) {
1149 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1150 return kFALSE;
1151 }
1152 out << sjdl << endl;
1153 TString mergeJDLName = fExecutable;
1154 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1155 if (fMergeViaJDL) {
1156 ofstream out1;
1157 out1.open(mergeJDLName.Data(), ios::out);
1158 if (out.bad()) {
1159 Error("CreateJDL", "Bad file name: %s", mergeJDLName.Data());
1160 return kFALSE;
1161 }
1162 out1 << sjdl1 << endl;
1163 }
1164
1165 // Copy jdl to grid workspace
1166 if (!copy) {
1167 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1168 } else {
1169 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1170 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1171 if (fProductionMode) {
1172 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1173 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1174 }
1175 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1176 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1177 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1178 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1179 if (fMergeViaJDL) {
1180 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1181 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1182 }
1183 }
1184 return kTRUE;
1185}
1186
1187//______________________________________________________________________________
1188Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1189{
1190// Returns true if file exists.
1191 if (!gGrid) return kFALSE;
1192 TGridResult *res = gGrid->Ls(lfn);
1193 if (!res) return kFALSE;
1194 TMap *map = dynamic_cast<TMap*>(res->At(0));
1195 if (!map) {
1196 delete res;
1197 return kFALSE;
1198 }
1199 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1200 if (!objs || !objs->GetString().Length()) {
1201 delete res;
1202 return kFALSE;
1203 }
1204 delete res;
1205 return kTRUE;
1206}
1207
1208//______________________________________________________________________________
1209Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1210{
1211// Returns true if directory exists. Can be also a path.
1212 if (!gGrid) return kFALSE;
1213 // Check if dirname is a path
1214 TString dirstripped = dirname;
1215 dirstripped = dirstripped.Strip();
1216 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1217 TString dir = gSystem->BaseName(dirstripped);
1218 dir += "/";
1219 TString path = gSystem->DirName(dirstripped);
1220 TGridResult *res = gGrid->Ls(path, "-F");
1221 if (!res) return kFALSE;
1222 TIter next(res);
1223 TMap *map;
1224 TObject *obj;
1225 while ((map=dynamic_cast<TMap*>(next()))) {
1226 obj = map->GetValue("name");
1227 if (!obj) break;
1228 if (dir == obj->GetName()) {
1229 delete res;
1230 return kTRUE;
1231 }
1232 }
1233 delete res;
1234 return kFALSE;
1235}
1236
1237//______________________________________________________________________________
1238void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1239{
1240// Check input data type.
1241 is_collection = kFALSE;
1242 is_xml = kFALSE;
1243 use_tags = kFALSE;
1244 if (!gGrid) {
1245 Error("CheckDataType", "No connection to grid");
1246 return;
1247 }
1248 is_collection = IsCollection(lfn);
1249 TString msg = "\n##### file: ";
1250 msg += lfn;
1251 if (is_collection) {
1252 msg += " type: raw_collection;";
1253 // special treatment for collections
1254 is_xml = kFALSE;
1255 // check for tag files in the collection
1256 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1257 if (!res) {
1258 msg += " using_tags: No (unknown)";
1259 Info("CheckDataType", msg.Data());
1260 return;
1261 }
1262 const char* typeStr = res->GetKey(0, "origLFN");
1263 if (!typeStr || !strlen(typeStr)) {
1264 msg += " using_tags: No (unknown)";
1265 Info("CheckDataType", msg.Data());
1266 return;
1267 }
1268 TString file = typeStr;
1269 use_tags = file.Contains(".tag");
1270 if (use_tags) msg += " using_tags: Yes";
1271 else msg += " using_tags: No";
1272 Info("CheckDataType", msg.Data());
1273 return;
1274 }
1275 TString slfn(lfn);
1276 slfn.ToLower();
1277 is_xml = slfn.Contains(".xml");
1278 if (is_xml) {
1279 // Open xml collection and check if there are tag files inside
1280 msg += " type: xml_collection;";
1281 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1282 if (!coll) {
1283 msg += " using_tags: No (unknown)";
1284 Info("CheckDataType", msg.Data());
1285 return;
1286 }
1287 TMap *map = coll->Next();
1288 if (!map) {
1289 msg += " using_tags: No (unknown)";
1290 Info("CheckDataType", msg.Data());
1291 return;
1292 }
1293 map = (TMap*)map->GetValue("");
1294 TString file;
1295 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1296 use_tags = file.Contains(".tag");
1297 delete coll;
1298 if (use_tags) msg += " using_tags: Yes";
1299 else msg += " using_tags: No";
1300 Info("CheckDataType", msg.Data());
1301 return;
1302 }
1303 use_tags = slfn.Contains(".tag");
1304 if (slfn.Contains(".root")) msg += " type: root file;";
1305 else msg += " type: unknown file;";
1306 if (use_tags) msg += " using_tags: Yes";
1307 else msg += " using_tags: No";
1308 Info("CheckDataType", msg.Data());
1309}
1310
1311//______________________________________________________________________________
1312void AliAnalysisAlien::EnablePackage(const char *package)
1313{
1314// Enables a par file supposed to exist in the current directory.
1315 TString pkg(package);
1316 pkg.ReplaceAll(".par", "");
1317 pkg += ".par";
1318 if (gSystem->AccessPathName(pkg)) {
1319 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1320 return;
1321 }
1322 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1323 Info("EnablePackage", "AliEn plugin will use .par packages");
1324 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1325 if (!fPackages) {
1326 fPackages = new TObjArray();
1327 fPackages->SetOwner();
1328 }
1329 fPackages->Add(new TObjString(pkg));
1330}
1331
1332//______________________________________________________________________________
1333const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1334{
1335// Get job status for all jobs with jobid>jobidstart.
1336 static char mstatus[20];
1337 mstatus[0] = '\0';
1338 nrunning = 0;
1339 nwaiting = 0;
1340 nerror = 0;
1341 ndone = 0;
1342 TGridJobStatusList *list = gGrid->Ps("");
1343 if (!list) return mstatus;
1344 Int_t nentries = list->GetSize();
1345 TGridJobStatus *status;
1346 Int_t pid;
1347 for (Int_t ijob=0; ijob<nentries; ijob++) {
1348 status = (TGridJobStatus *)list->At(ijob);
1349 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1350 if (pid<jobidstart) continue;
1351 if (pid == lastid) {
1352 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1353 }
1354 switch (status->GetStatus()) {
1355 case TGridJobStatus::kWAITING:
1356 nwaiting++; break;
1357 case TGridJobStatus::kRUNNING:
1358 nrunning++; break;
1359 case TGridJobStatus::kABORTED:
1360 case TGridJobStatus::kFAIL:
1361 case TGridJobStatus::kUNKNOWN:
1362 nerror++; break;
1363 case TGridJobStatus::kDONE:
1364 ndone++;
1365 }
1366 }
1367 list->Delete();
1368 delete list;
1369 return mstatus;
1370}
1371
1372//______________________________________________________________________________
1373Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1374{
1375// Returns true if file is a collection. Functionality duplicated from
1376// TAlien::Type() because we don't want to directly depend on TAlien.
1377 if (!gGrid) {
1378 Error("IsCollection", "No connection to grid");
1379 return kFALSE;
1380 }
1381 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1382 if (!res) return kFALSE;
1383 const char* typeStr = res->GetKey(0, "type");
1384 if (!typeStr || !strlen(typeStr)) return kFALSE;
1385 if (!strcmp(typeStr, "collection")) return kTRUE;
1386 delete res;
1387 return kFALSE;
1388}
1389
1390//______________________________________________________________________________
1391Bool_t AliAnalysisAlien::IsSingleOutput() const
1392{
1393// Check if single-ouput option is on.
1394 return (!fOutputSingle.IsNull());
1395}
1396
1397//______________________________________________________________________________
1398void AliAnalysisAlien::Print(Option_t *) const
1399{
1400// Print current plugin settings.
1401 printf("### AliEn analysis plugin current settings ###\n");
1402 printf("= Production mode:______________________________ %d\n", fProductionMode);
1403 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1404 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1405 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1406 if (fUser.Length())
1407 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1408 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1409 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1410 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1411 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1412 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1413 if (fRunNumbers.Length())
1414 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1415 if (fRunRange[0])
1416 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1417 if (!fRunRange[0] && !fRunNumbers.Length()) {
1418 TIter next(fInputFiles);
1419 TObject *obj;
1420 TString list;
1421 while ((obj=next())) list += obj->GetName();
1422 printf("= Input files to be processed: _________________ %s\n", list.Data());
1423 }
1424 if (TestBit(AliAnalysisGrid::kTest))
1425 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1426 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1427 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1428 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1429 printf("=====================================================================\n");
1430 printf("= Job price: ___________________________________ %d\n", fPrice);
1431 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1432 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1433 if (fMaxInitFailed>0)
1434 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1435 if (fMasterResubmitThreshold>0)
1436 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1437 if (fNrunsPerMaster>0)
1438 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1439 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1440 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1441 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1442 if (fArguments.Length())
1443 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1444 if (fExecutableArgs.Length())
1445 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1446 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1447 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1448 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1449 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1450 if (fDatasetName)
1451 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1452 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1453 if (fIncludePath.Data())
1454 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1455 if (fCloseSE.Length())
1456 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1457 if (fFriendChainName.Length())
1458 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1459 if (fPackages) {
1460 TIter next(fPackages);
1461 TObject *obj;
1462 TString list;
1463 while ((obj=next())) list += obj->GetName();
1464 printf("= Par files to be used: ________________________ %s\n", list.Data());
1465 }
1466}
1467
1468//______________________________________________________________________________
1469void AliAnalysisAlien::SetDefaults()
1470{
1471// Set default values for everything. What cannot be filled will be left empty.
1472 if (fGridJDL) delete fGridJDL;
1473 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1474 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1475 fPrice = 1;
1476 fTTL = 30000;
1477 fSplitMaxInputFileNumber = 100;
1478 fMaxInitFailed = 0;
1479 fMasterResubmitThreshold = 0;
1480 fNtestFiles = 10;
1481 fRunRange[0] = 0;
1482 fRunRange[1] = 0;
1483 fNrunsPerMaster = 1;
1484 fMaxMergeFiles = 100;
1485 fRunNumbers = "";
1486 fExecutable = "analysis.sh";
1487 fExecutableCommand = "root -b -q";
1488 fArguments = "";
1489 fExecutableArgs = "";
1490 fAnalysisMacro = "myAnalysis.C";
1491 fAnalysisSource = "";
1492 fAdditionalLibs = "";
1493 fSplitMode = "se";
1494 fAPIVersion = "";
1495 fROOTVersion = "";
1496 fAliROOTVersion = "";
1497 fUser = ""; // Your alien user name
1498 fGridWorkingDir = "";
1499 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1500 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1501 fFriendChainName = "";
1502 fGridOutputDir = "output";
1503 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1504 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1505 fInputFormat = "xml-single";
1506 fJDLName = "analysis.jdl";
1507 fJobTag = "Automatically generated analysis JDL";
1508 fMergeExcludes = "";
1509 fMergeViaJDL = 0;
1510}
1511
1512//______________________________________________________________________________
1513Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge)
1514{
1515// Merge all registered outputs from basedir.
1516 TString output_file = output;
1517 TString command;
1518 TString output_chunk;
1519 TString previous_chunk = "";
1520 Int_t count_chunk = 0;
1521 Int_t count_zero = nmaxmerge;
1522 Bool_t merged = kTRUE;
1523 Int_t index = output_file.Index("@");
1524 if (index > 0) output_file.Remove(index);
1525 command = Form("find %s/ *%s", basedir, output_file.Data());
1526 printf("command: %s\n", command.Data());
1527 TGridResult *res = gGrid->Command(command);
1528 if (!res) {
1529 printf("Error: No result for the find command\n");
1530 return kFALSE;
1531 }
1532
1533 TFileMerger *fm = 0;
1534 TIter nextmap(res);
1535 TMap *map = 0;
1536 // Check if there is a merge operation to resume
1537 output_chunk = output_file;
1538 output_chunk.ReplaceAll(".root", "_*.root");
1539 // Check for existent temporary merge files
1540 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1541 while (1) {
1542 // Skip as many input files as in a chunk
1543 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1544 if (!map) {
1545 ::Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1546 delete res;
1547 return kFALSE;
1548 }
1549 output_chunk = output_file;
1550 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1551 count_chunk++;
1552 if (gSystem->AccessPathName(output_chunk)) continue;
1553 // Merged file with chunks up to <count_chunk> found
1554 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1555 previous_chunk = output_chunk;
1556 break;
1557 }
1558 }
1559 count_zero = nmaxmerge;
1560
1561 while ((map=(TMap*)nextmap())) {
1562 // Loop 'find' results and get next LFN
1563 if (count_zero == nmaxmerge) {
1564 // First file in chunk - create file merger and add previous chunk if any.
1565 fm = new TFileMerger(kFALSE);
1566 fm->SetFastMethod(kTRUE);
1567 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1568 output_chunk = output_file;
1569 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1570 }
1571 // If last file found, put merged results in the output file
1572 if (map == res->Last()) output_chunk = output_file;
1573 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1574 if (!objs || !objs->GetString().Length()) {
1575 // Nothing found - skip this output
1576 delete res;
1577 delete fm;
1578 return kFALSE;
1579 }
1580 // Add file to be merged and decrement chunk counter.
1581 fm->AddFile(objs->GetString());
1582 count_zero--;
1583 if (count_zero==0 || map == res->Last()) {
1584 fm->OutputFile(output_chunk);
1585 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1586 // Nothing found - skip this output
1587 ::Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1588 delete res;
1589 delete fm;
1590 return kFALSE;
1591 }
1592 // Merge the outputs, then go to next chunk
1593 if (!fm->Merge()) {
1594 ::Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1595 delete res;
1596 delete fm;
1597 merged = kFALSE;
1598 return kFALSE;
1599 } else {
1600 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1601 gSystem->Unlink(previous_chunk);
1602 }
1603 if (map == res->Last()) {
1604 delete res;
1605 delete fm;
1606 break;
1607 }
1608 count_chunk++;
1609 count_zero = nmaxmerge;
1610 previous_chunk = output_chunk;
1611 }
1612 }
1613 return merged;
1614}
1615
1616//______________________________________________________________________________
1617Bool_t AliAnalysisAlien::MergeOutputs()
1618{
1619// Merge analysis outputs existing in the AliEn space.
1620 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1621 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1622 if (!Connect()) {
1623 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1624 return kFALSE;
1625 }
1626 if (fMergeViaJDL) {
1627 if (!TestBit(AliAnalysisGrid::kMerge)) {
1628 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
1629 return kFALSE;
1630 }
1631 if (fProductionMode) {
1632 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
1633 return kFALSE;
1634 }
1635 Info("MergeOutputs", "Submitting merging JDL");
1636 SubmitMerging();
1637 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
1638 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
1639 return kFALSE;
1640 }
1641 // Get the output path
1642 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1643 if (!DirectoryExists(fGridOutputDir)) {
1644 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1645 return kFALSE;
1646 }
1647 if (!fOutputFiles.Length()) {
1648 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1649 return kFALSE;
1650 }
1651 // Check if fast read option was requested
1652 if (fFastReadOption) {
1653 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !");
1654 gEnv->SetValue("XNet.ConnectTimeout",5);
1655 gEnv->SetValue("XNet.RequestTimeout",5);
1656 gEnv->SetValue("XNet.MaxRedirectCount",2);
1657 gEnv->SetValue("XNet.ReconnectTimeout",5);
1658 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
1659 }
1660 TObjArray *list = fOutputFiles.Tokenize(" ");
1661 TIter next(list);
1662 TObjString *str;
1663 TString output_file;
1664 Bool_t merged = kTRUE;
1665 while((str=(TObjString*)next())) {
1666 output_file = str->GetString();
1667 Int_t index = output_file.Index("@");
1668 if (index > 0) output_file.Remove(index);
1669 // Skip already merged outputs
1670 if (!gSystem->AccessPathName(output_file)) {
1671 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1672 continue;
1673 }
1674 if (fMergeExcludes.Length() &&
1675 fMergeExcludes.Contains(output_file.Data())) continue;
1676 // Perform a 'find' command in the output directory, looking for registered outputs
1677 merged = MergeOutput(output_file, fGridOutputDir, fMaxMergeFiles);
1678 if (!merged) {
1679 Error("MergeOutputs", "Terminate() will NOT be executed");
1680 return kFALSE;
1681 }
1682 }
1683 return kTRUE;
1684}
1685
1686//______________________________________________________________________________
1687void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1688{
1689// Use the output files connected to output containers from the analysis manager
1690// rather than the files defined by SetOutputFiles
1691 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1692 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1693 analysis manager");
1694 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1695}
1696
1697//______________________________________________________________________________
1698Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1699{
1700// Start remote grid analysis.
1701
1702 // Check if output files have to be taken from the analysis manager
1703 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1704 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1705 if (!mgr || !mgr->IsInitialized()) {
1706 Error("StartAnalysis", "You need an initialized analysis manager for this");
1707 return kFALSE;
1708 }
1709 fOutputFiles = "";
1710 TIter next(mgr->GetOutputs());
1711 AliAnalysisDataContainer *output;
1712 while ((output=(AliAnalysisDataContainer*)next())) {
1713 const char *filename = output->GetFileName();
1714 if (!(strcmp(filename, "default"))) {
1715 if (!mgr->GetOutputEventHandler()) continue;
1716 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1717 }
1718 if (fOutputFiles.Contains(filename)) continue;
1719 if (fOutputFiles.Length()) fOutputFiles += " ";
1720 fOutputFiles += filename;
1721 }
1722 // Add extra files registered to the analysis manager
1723 if (mgr->GetExtraFiles().Length()) {
1724 if (fOutputFiles.Length()) fOutputFiles += " ";
1725 fOutputFiles += mgr->GetExtraFiles();
1726 }
1727 }
1728// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1729 if (TestBit(AliAnalysisGrid::kOffline)) {
1730 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1731 \n there nor any job run. You can revise the JDL and analysis \
1732 \n macro then run the same in \"submit\" mode.");
1733 } else if (TestBit(AliAnalysisGrid::kTest)) {
1734 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1735 \n dataset.");
1736 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1737 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1738 \n space and job submitted.");
1739 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1740 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1741 if (fMergeViaJDL) CheckInputData();
1742 return kTRUE;
1743 } else {
1744 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1745 }
1746
1747 if (!Connect()) {
1748 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1749 return kFALSE;
1750 }
1751 Print();
1752 if (!CheckInputData()) {
1753 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1754 return kFALSE;
1755 }
1756 CreateDataset(fDataPattern);
1757 WriteAnalysisFile();
1758 WriteAnalysisMacro();
1759 WriteExecutable();
1760 WriteValidationScript();
1761 if (fMergeViaJDL) {
1762 WriteMergingMacro();
1763 WriteMergeExecutable();
1764 WriteValidationScript(kTRUE);
1765 }
1766 if (!CreateJDL()) return kFALSE;
1767 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1768 if (TestBit(AliAnalysisGrid::kTest)) {
1769 // Locally testing the analysis
1770 Info("StartAnalysis", "\n_______________________________________________________________________ \
1771 \n Running analysis script in a daughter shell as on a worker node \
1772 \n_______________________________________________________________________");
1773 TObjArray *list = fOutputFiles.Tokenize(" ");
1774 TIter next(list);
1775 TObjString *str;
1776 TString output_file;
1777 while((str=(TObjString*)next())) {
1778 output_file = str->GetString();
1779 Int_t index = output_file.Index("@");
1780 if (index > 0) output_file.Remove(index);
1781 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1782 }
1783 delete list;
1784 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1785 TString validationScript = fExecutable;
1786 validationScript.ReplaceAll(".sh", "_validation.sh");
1787 gSystem->Exec(Form("bash %s",validationScript.Data()));
1788// gSystem->Exec("cat stdout");
1789 return kFALSE;
1790 }
1791 // Check if submitting is managed by LPM manager
1792 if (fProductionMode) {
1793 TString prodfile = fJDLName;
1794 prodfile.ReplaceAll(".jdl", ".prod");
1795 WriteProductionFile(prodfile);
1796 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1797 return kFALSE;
1798 }
1799 // Submit AliEn job(s)
1800 gGrid->Cd(fGridOutputDir);
1801 TGridResult *res;
1802 TString jobID = "";
1803 if (!fRunNumbers.Length() && !fRunRange[0]) {
1804 // Submit a given xml or a set of runs
1805 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1806 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1807 if (res) {
1808 const char *cjobId = res->GetKey(0,"jobId");
1809 if (!cjobId) {
1810 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1811 return kFALSE;
1812 } else {
1813 Info("StartAnalysis", "\n_______________________________________________________________________ \
1814 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1815 \n_______________________________________________________________________",
1816 fJDLName.Data(), cjobId);
1817 jobID = cjobId;
1818 }
1819 delete res;
1820 }
1821 } else {
1822 // Submit for a range of enumeration of runs.
1823 Submit();
1824 }
1825
1826 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1827 \n You may exit at any time and terminate the job later using the option <terminate> \
1828 \n ##################################################################################", jobID.Data());
1829 gSystem->Exec("aliensh");
1830 return kTRUE;
1831}
1832
1833//______________________________________________________________________________
1834void AliAnalysisAlien::Submit()
1835{
1836// Submit all master jobs.
1837 Int_t nmasterjobs = fInputFiles->GetEntries();
1838 Long_t tshoot = gSystem->Now();
1839 if (!fNsubmitted) SubmitNext();
1840 while (fNsubmitted < nmasterjobs) {
1841 Long_t now = gSystem->Now();
1842 if ((now-tshoot)>30000) {
1843 tshoot = now;
1844 SubmitNext();
1845 }
1846 }
1847}
1848
1849//______________________________________________________________________________
1850void AliAnalysisAlien::SubmitMerging()
1851{
1852// Submit all merging jobs.
1853 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1854 gGrid->Cd(fGridOutputDir);
1855 TString mergeJDLName = fExecutable;
1856 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1857 Int_t ntosubmit = fInputFiles->GetEntries();
1858 printf("### Submitting %d merging jobs...\n", ntosubmit);
1859 for (Int_t i=0; i<ntosubmit; i++) {
1860 TString query;
1861 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
1862 runOutDir.ReplaceAll(".xml", "");
1863 if (fOutputToRunNo)
1864 query = Form("submit %s %s", mergeJDLName.Data(), runOutDir.Data());
1865 else
1866 query = Form("submit %s %03d", mergeJDLName.Data(), i);
1867 printf("********* %s\n",query.Data());
1868 TGridResult *res = gGrid->Command(query);
1869 if (res) {
1870 const char *cjobId = res->GetKey(0,"jobId");
1871 if (!cjobId) {
1872 Error("StartAnalysis", "Your JDL %s could not be submitted", mergeJDLName.Data());
1873 return;
1874 } else {
1875 Info("StartAnalysis", "\n_______________________________________________________________________ \
1876 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1877 \n_______________________________________________________________________",
1878 mergeJDLName.Data(), cjobId);
1879 }
1880 delete res;
1881 }
1882 }
1883 if (!ntosubmit) return;
1884 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
1885 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
1886 \n ##################################################################################");
1887 gSystem->Exec("aliensh");
1888}
1889
1890//______________________________________________________________________________
1891void AliAnalysisAlien::SubmitNext()
1892{
1893// Submit next bunch of master jobs if the queue is free.
1894 static Bool_t iscalled = kFALSE;
1895 static Int_t firstmaster = 0;
1896 static Int_t lastmaster = 0;
1897 static Int_t npermaster = 0;
1898 if (iscalled) return;
1899 iscalled = kTRUE;
1900 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1901 Int_t ntosubmit = 0;
1902 TGridResult *res;
1903 TString jobID = "";
1904 if (!fNsubmitted) ntosubmit = 1;
1905 else {
1906 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1907 printf("=== master %d: %s\n", lastmaster, status.Data());
1908 // If last master not split, just return
1909 if (status != "SPLIT") {iscalled = kFALSE; return;}
1910 // No more than 100 waiting jobs
1911 if (nwaiting>100) {iscalled = kFALSE; return;}
1912 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1913 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1914 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1915 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1916 }
1917 Int_t nmasterjobs = fInputFiles->GetEntries();
1918 for (Int_t i=0; i<ntosubmit; i++) {
1919 // Submit for a range of enumeration of runs.
1920 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1921 TString query;
1922 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
1923 runOutDir.ReplaceAll(".xml", "");
1924 if (fOutputToRunNo)
1925 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
1926 else
1927 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1928 printf("********* %s\n",query.Data());
1929 res = gGrid->Command(query);
1930 if (res) {
1931 TString cjobId1 = res->GetKey(0,"jobId");
1932 if (!cjobId1.Length()) {
1933 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1934 iscalled = kFALSE;
1935 return;
1936 } else {
1937 Info("StartAnalysis", "\n_______________________________________________________________________ \
1938 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1939 \n_______________________________________________________________________",
1940 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1941 jobID += cjobId1;
1942 jobID += " ";
1943 lastmaster = cjobId1.Atoi();
1944 if (!firstmaster) firstmaster = lastmaster;
1945 fNsubmitted++;
1946 }
1947 delete res;
1948 }
1949 }
1950 iscalled = kFALSE;
1951}
1952
1953//______________________________________________________________________________
1954void AliAnalysisAlien::WriteAnalysisFile()
1955{
1956// Write current analysis manager into the file <analysisFile>
1957 TString analysisFile = fExecutable;
1958 analysisFile.ReplaceAll(".sh", ".root");
1959 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1960 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1961 if (!mgr || !mgr->IsInitialized()) {
1962 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1963 return;
1964 }
1965 // Check analysis type
1966 TObject *handler;
1967 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1968 handler = (TObject*)mgr->GetInputEventHandler();
1969 if (handler) {
1970 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1971 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1972 }
1973 TDirectory *cdir = gDirectory;
1974 TFile *file = TFile::Open(analysisFile, "RECREATE");
1975 if (file) {
1976 // Skip task Terminate calls for the grid job
1977 mgr->SetSkipTerminate(kTRUE);
1978 // Unless merging makes no sense
1979 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
1980 mgr->Write();
1981 delete file;
1982 // Enable termination for local jobs
1983 mgr->SetSkipTerminate(kFALSE);
1984 }
1985 if (cdir) cdir->cd();
1986 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
1987 }
1988 Bool_t copy = kTRUE;
1989 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1990 if (copy) {
1991 CdWork();
1992 TString workdir = gGrid->GetHomeDirectory();
1993 workdir += fGridWorkingDir;
1994 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1995 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1996 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
1997 }
1998}
1999
2000//______________________________________________________________________________
2001void AliAnalysisAlien::WriteAnalysisMacro()
2002{
2003// Write the analysis macro that will steer the analysis in grid mode.
2004 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2005 ofstream out;
2006 out.open(fAnalysisMacro.Data(), ios::out);
2007 if (!out.good()) {
2008 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2009 return;
2010 }
2011 Bool_t hasSTEERBase = kFALSE;
2012 Bool_t hasESD = kFALSE;
2013 Bool_t hasAOD = kFALSE;
2014 Bool_t hasANALYSIS = kFALSE;
2015 Bool_t hasANALYSISalice = kFALSE;
2016 Bool_t hasCORRFW = kFALSE;
2017 TString func = fAnalysisMacro;
2018 TString type = "ESD";
2019 TString comment = "// Analysis using ";
2020 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2021 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2022 type = "AOD";
2023 comment += "AOD";
2024 }
2025 if (type!="AOD" && fFriendChainName!="") {
2026 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2027 return;
2028 }
2029 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2030 else comment += " data";
2031 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2032 func.ReplaceAll(".C", "");
2033 out << "void " << func.Data() << "()" << endl;
2034 out << "{" << endl;
2035 out << comment.Data() << endl;
2036 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
2037 out << " TStopwatch timer;" << endl;
2038 out << " timer.Start();" << endl << endl;
2039 out << "// load base root libraries" << endl;
2040 out << " gSystem->Load(\"libTree\");" << endl;
2041 out << " gSystem->Load(\"libGeom\");" << endl;
2042 out << " gSystem->Load(\"libVMC\");" << endl;
2043 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2044 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2045 if (fAdditionalRootLibs.Length()) {
2046 // in principle libtree /lib geom libvmc etc. can go into this list, too
2047 out << "// Add aditional libraries" << endl;
2048 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2049 TIter next(list);
2050 TObjString *str;
2051 while((str=(TObjString*)next())) {
2052 if (str->GetString().Contains(".so"))
2053 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2054 }
2055 if (list) delete list;
2056 }
2057 out << "// include path" << endl;
2058 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2059 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2060 out << "// Load analysis framework libraries" << endl;
2061 if (!fPackages) {
2062 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2063 out << " gSystem->Load(\"libESD\");" << endl;
2064 out << " gSystem->Load(\"libAOD\");" << endl;
2065 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2066 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2067 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2068 } else {
2069 TIter next(fPackages);
2070 TObject *obj;
2071 TString pkgname;
2072 TString setupPar = "AliAnalysisAlien::SetupPar";
2073 while ((obj=next())) {
2074 pkgname = obj->GetName();
2075 if (pkgname == "STEERBase" ||
2076 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2077 if (pkgname == "ESD" ||
2078 pkgname == "ESD.par") hasESD = kTRUE;
2079 if (pkgname == "AOD" ||
2080 pkgname == "AOD.par") hasAOD = kTRUE;
2081 if (pkgname == "ANALYSIS" ||
2082 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2083 if (pkgname == "ANALYSISalice" ||
2084 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2085 if (pkgname == "CORRFW" ||
2086 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2087 }
2088 if (hasANALYSISalice) setupPar = "SetupPar";
2089 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2090 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2091 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2092 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2093 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2094 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2095 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2096 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2097 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2098 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2099 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2100 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2101 out << "// Compile other par packages" << endl;
2102 next.Reset();
2103 while ((obj=next())) {
2104 pkgname = obj->GetName();
2105 if (pkgname == "STEERBase" ||
2106 pkgname == "STEERBase.par" ||
2107 pkgname == "ESD" ||
2108 pkgname == "ESD.par" ||
2109 pkgname == "AOD" ||
2110 pkgname == "AOD.par" ||
2111 pkgname == "ANALYSIS" ||
2112 pkgname == "ANALYSIS.par" ||
2113 pkgname == "ANALYSISalice" ||
2114 pkgname == "ANALYSISalice.par" ||
2115 pkgname == "CORRFW" ||
2116 pkgname == "CORRFW.par") continue;
2117 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2118 }
2119 }
2120 if (fAdditionalLibs.Length()) {
2121 out << "// Add aditional AliRoot libraries" << endl;
2122 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2123 TIter next(list);
2124 TObjString *str;
2125 while((str=(TObjString*)next())) {
2126 if (str->GetString().Contains(".so"))
2127 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2128 }
2129 if (list) delete list;
2130 }
2131 out << endl;
2132 out << "// analysis source to be compiled at runtime (if any)" << endl;
2133 if (fAnalysisSource.Length()) {
2134 TObjArray *list = fAnalysisSource.Tokenize(" ");
2135 TIter next(list);
2136 TObjString *str;
2137 while((str=(TObjString*)next())) {
2138 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2139 }
2140 if (list) delete list;
2141 }
2142 out << endl;
2143 if (fFastReadOption) {
2144 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. Note that this may skip some files that could be accessed !!!");
2145 out << "// fast xrootd reading enabled" << endl;
2146 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2147 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",5);" << endl;
2148 out << " gEnv->SetValue(\"XNet.RequestTimeout\",5);" << endl;
2149 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2150 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",5);" << endl;
2151 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2152 }
2153 out << "// connect to AliEn and make the chain" << endl;
2154 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2155 if (IsUsingTags()) {
2156 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
2157 } else {
2158 if(fFriendChainName!="AliAOD.VertexingHF.root") {
2159 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
2160 } else {
2161 out << " // Check if the macro to create the chain was provided" << endl;
2162 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
2163 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
2164 out << " return;" << endl;
2165 out << " }" << endl;
2166 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
2167 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
2168 }
2169 }
2170 out << "// read the analysis manager from file" << endl;
2171 TString analysisFile = fExecutable;
2172 analysisFile.ReplaceAll(".sh", ".root");
2173 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2174 out << " if (!file) return;" << endl;
2175 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2176 out << " AliAnalysisManager *mgr = 0;" << endl;
2177 out << " TKey *key;" << endl;
2178 out << " while ((key=(TKey*)nextkey())) {" << endl;
2179 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2180 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2181 out << " };" << endl;
2182 out << " if (!mgr) {" << endl;
2183 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2184 out << " return;" << endl;
2185 out << " }" << endl << endl;
2186 out << " mgr->PrintStatus();" << endl;
2187 if (AliAnalysisManager::GetAnalysisManager()) {
2188 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2189 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2190 } else {
2191 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2192 }
2193 }
2194 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
2195 out << " timer.Stop();" << endl;
2196 out << " timer.Print();" << endl;
2197 out << "}" << endl << endl;
2198 if (IsUsingTags()) {
2199 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
2200 out << "{" << endl;
2201 out << "// Create a chain using tags from the xml file." << endl;
2202 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
2203 out << " if (!coll) {" << endl;
2204 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2205 out << " return NULL;" << endl;
2206 out << " }" << endl;
2207 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
2208 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
2209 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
2210 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
2211 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
2212 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
2213 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
2214 out << " // Check if the cuts configuration file was provided" << endl;
2215 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
2216 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
2217 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2218 out << " }" << endl;
2219 if (fFriendChainName=="") {
2220 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2221 } else {
2222 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
2223 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
2224 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
2225 }
2226 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
2227 out << " chain->ls();" << endl;
2228 out << " return chain;" << endl;
2229 out << "}" << endl << endl;
2230 if (gSystem->AccessPathName("ConfigureCuts.C")) {
2231 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
2232 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
2233 msg += " AliLHCTagCuts *lhcCuts,\n";
2234 msg += " AliDetectorTagCuts *detCuts,\n";
2235 msg += " AliEventTagCuts *evCuts)";
2236 Info("WriteAnalysisMacro", msg.Data());
2237 }
2238 }
2239 if (!IsUsingTags() || fFriendChainName!="") {
2240 out <<"//________________________________________________________________________________" << endl;
2241 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
2242 out << "{" << endl;
2243 out << "// Create a chain using url's from xml file" << endl;
2244 out << " TString treename = type;" << endl;
2245 out << " treename.ToLower();" << endl;
2246 out << " treename += \"Tree\";" << endl;
2247 out << " printf(\"***************************************\\n\");" << endl;
2248 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
2249 out << " printf(\"***************************************\\n\");" << endl;
2250 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
2251 out << " if (!coll) {" << endl;
2252 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2253 out << " return NULL;" << endl;
2254 out << " }" << endl;
2255 out << " TChain *chain = new TChain(treename);" << endl;
2256 if(fFriendChainName!="") {
2257 out << " TChain *chainFriend = new TChain(treename);" << endl;
2258 }
2259 out << " coll->Reset();" << endl;
2260 out << " while (coll->Next()) {" << endl;
2261 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2262 if(fFriendChainName!="") {
2263 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2264 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2265 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2266 out << " chainFriend->Add(fileFriend.Data());" << endl;
2267 }
2268 out << " }" << endl;
2269 out << " if (!chain->GetNtrees()) {" << endl;
2270 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2271 out << " return NULL;" << endl;
2272 out << " }" << endl;
2273 if(fFriendChainName!="") {
2274 out << " chain->AddFriend(chainFriend);" << endl;
2275 }
2276 out << " return chain;" << endl;
2277 out << "}" << endl << endl;
2278 }
2279 if (hasANALYSISalice) {
2280 out <<"//________________________________________________________________________________" << endl;
2281 out << "Bool_t SetupPar(const char *package) {" << endl;
2282 out << "// Compile the package and set it up." << endl;
2283 out << " TString pkgdir = package;" << endl;
2284 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2285 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2286 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2287 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2288 out << " // Check for BUILD.sh and execute" << endl;
2289 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2290 out << " printf(\"*******************************\\n\");" << endl;
2291 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2292 out << " printf(\"*******************************\\n\");" << endl;
2293 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2294 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2295 out << " gSystem->ChangeDirectory(cdir);" << endl;
2296 out << " return kFALSE;" << endl;
2297 out << " }" << endl;
2298 out << " } else {" << endl;
2299 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2300 out << " gSystem->ChangeDirectory(cdir);" << endl;
2301 out << " return kFALSE;" << endl;
2302 out << " }" << endl;
2303 out << " // Check for SETUP.C and execute" << endl;
2304 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2305 out << " printf(\"*******************************\\n\");" << endl;
2306 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2307 out << " printf(\"*******************************\\n\");" << endl;
2308 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2309 out << " } else {" << endl;
2310 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2311 out << " gSystem->ChangeDirectory(cdir);" << endl;
2312 out << " return kFALSE;" << endl;
2313 out << " }" << endl;
2314 out << " // Restore original workdir" << endl;
2315 out << " gSystem->ChangeDirectory(cdir);" << endl;
2316 out << " return kTRUE;" << endl;
2317 out << "}" << endl;
2318 }
2319 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2320 }
2321 Bool_t copy = kTRUE;
2322 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2323 if (copy) {
2324 CdWork();
2325 TString workdir = gGrid->GetHomeDirectory();
2326 workdir += fGridWorkingDir;
2327 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2328 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2329 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2330 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2331 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2332 }
2333 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2334 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2335 }
2336}
2337
2338//______________________________________________________________________________
2339void AliAnalysisAlien::WriteMergingMacro()
2340{
2341// Write a macro to merge the outputs per master job.
2342 if (!fMergeViaJDL) return;
2343 if (!fOutputFiles.Length()) {
2344 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2345 return;
2346 }
2347 TString mergingMacro = fExecutable;
2348 mergingMacro.ReplaceAll(".sh","_merge.C");
2349 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2350 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2351 ofstream out;
2352 out.open(mergingMacro.Data(), ios::out);
2353 if (!out.good()) {
2354 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2355 return;
2356 }
2357 Bool_t hasSTEERBase = kFALSE;
2358 Bool_t hasESD = kFALSE;
2359 Bool_t hasAOD = kFALSE;
2360 Bool_t hasANALYSIS = kFALSE;
2361 Bool_t hasANALYSISalice = kFALSE;
2362 Bool_t hasCORRFW = kFALSE;
2363 TString func = mergingMacro;
2364 TString comment;
2365 func.ReplaceAll(".C", "");
2366 out << "void " << func.Data() << "(const char *dir)" << endl;
2367 out << "{" << endl;
2368 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
2369 out << " TStopwatch timer;" << endl;
2370 out << " timer.Start();" << endl << endl;
2371 out << "// load base root libraries" << endl;
2372 out << " gSystem->Load(\"libTree\");" << endl;
2373 out << " gSystem->Load(\"libGeom\");" << endl;
2374 out << " gSystem->Load(\"libVMC\");" << endl;
2375 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2376 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2377 if (fAdditionalRootLibs.Length()) {
2378 // in principle libtree /lib geom libvmc etc. can go into this list, too
2379 out << "// Add aditional libraries" << endl;
2380 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2381 TIter next(list);
2382 TObjString *str;
2383 while((str=(TObjString*)next())) {
2384 if (str->GetString().Contains(".so"))
2385 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2386 }
2387 if (list) delete list;
2388 }
2389 out << "// include path" << endl;
2390 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2391 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2392 out << "// Load analysis framework libraries" << endl;
2393 if (!fPackages) {
2394 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2395 out << " gSystem->Load(\"libESD\");" << endl;
2396 out << " gSystem->Load(\"libAOD\");" << endl;
2397 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2398 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2399 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2400 } else {
2401 TIter next(fPackages);
2402 TObject *obj;
2403 TString pkgname;
2404 TString setupPar = "AliAnalysisAlien::SetupPar";
2405 while ((obj=next())) {
2406 pkgname = obj->GetName();
2407 if (pkgname == "STEERBase" ||
2408 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2409 if (pkgname == "ESD" ||
2410 pkgname == "ESD.par") hasESD = kTRUE;
2411 if (pkgname == "AOD" ||
2412 pkgname == "AOD.par") hasAOD = kTRUE;
2413 if (pkgname == "ANALYSIS" ||
2414 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2415 if (pkgname == "ANALYSISalice" ||
2416 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2417 if (pkgname == "CORRFW" ||
2418 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2419 }
2420 if (hasANALYSISalice) setupPar = "SetupPar";
2421 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2422 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2423 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2424 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2425 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2426 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2427 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2428 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2429 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2430 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2431 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2432 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2433 out << "// Compile other par packages" << endl;
2434 next.Reset();
2435 while ((obj=next())) {
2436 pkgname = obj->GetName();
2437 if (pkgname == "STEERBase" ||
2438 pkgname == "STEERBase.par" ||
2439 pkgname == "ESD" ||
2440 pkgname == "ESD.par" ||
2441 pkgname == "AOD" ||
2442 pkgname == "AOD.par" ||
2443 pkgname == "ANALYSIS" ||
2444 pkgname == "ANALYSIS.par" ||
2445 pkgname == "ANALYSISalice" ||
2446 pkgname == "ANALYSISalice.par" ||
2447 pkgname == "CORRFW" ||
2448 pkgname == "CORRFW.par") continue;
2449 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2450 }
2451 }
2452 if (fAdditionalLibs.Length()) {
2453 out << "// Add aditional AliRoot libraries" << endl;
2454 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2455 TIter next(list);
2456 TObjString *str;
2457 while((str=(TObjString*)next())) {
2458 if (str->GetString().Contains(".so"))
2459 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2460 }
2461 if (list) delete list;
2462 }
2463 out << endl;
2464 out << "// Analysis source to be compiled at runtime (if any)" << endl;
2465 if (fAnalysisSource.Length()) {
2466 TObjArray *list = fAnalysisSource.Tokenize(" ");
2467 TIter next(list);
2468 TObjString *str;
2469 while((str=(TObjString*)next())) {
2470 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2471 }
2472 if (list) delete list;
2473 }
2474 out << endl;
2475 if (fFastReadOption) {
2476 Warning("WriteMergingMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid merging jobs. Note that this may skip some files that could be accessed !!!");
2477 out << "// fast xrootd reading enabled" << endl;
2478 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2479 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",5);" << endl;
2480 out << " gEnv->SetValue(\"XNet.RequestTimeout\",5);" << endl;
2481 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2482 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",5);" << endl;
2483 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2484 }
2485 out << "// Connect to AliEn" << endl;
2486 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2487 out << " TString outputDir = \"" << fGridOutputDir << "/\";" << endl;
2488 out << " outputDir += dir;" << endl;
2489 out << " TString outputFiles = \"" << fOutputFiles << "\";" << endl;
2490 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
2491 out << " mergeExcludes += \"" << AliAnalysisManager::GetAnalysisManager()->GetExtraFiles() << "\";" << endl;
2492 out << " TObjArray *list = outputFiles.Tokenize(\" \");" << endl;
2493 out << " TIter *iter = new TIter(list);" << endl;
2494 out << " TObjString *str;" << endl;
2495 out << " TString output_file;" << endl;
2496 out << " Bool_t merged = kTRUE;" << endl;
2497 out << " while((str=(TObjString*)iter->Next())) {" << endl;
2498 out << " output_file = str->GetString();" << endl;
2499 out << " Int_t index = output_file.Index(\"@\");" << endl;
2500 out << " if (index > 0) output_file.Remove(index);" << endl;
2501 out << " // Skip already merged outputs" << endl;
2502 out << " if (!gSystem->AccessPathName(output_file)) {" << endl;
2503 out << " printf(\"Output file <%s> found. Not merging again.\",output_file.Data());" << endl;
2504 out << " continue;" << endl;
2505 out << " }" << endl;
2506 out << " if (mergeExcludes.Contains(output_file.Data())) continue;" << endl;
2507 out << " merged = AliAnalysisAlien::MergeOutput(output_file, outputDir, " << fMaxMergeFiles << ");" << endl;
2508 out << " if (!merged) {" << endl;
2509 out << " printf(\"ERROR: Cannot merge %s\\n\", output_file.Data());" << endl;
2510 out << " }" << endl;
2511 out << " }" << endl;
2512 out << "// read the analysis manager from file" << endl;
2513 TString analysisFile = fExecutable;
2514 analysisFile.ReplaceAll(".sh", ".root");
2515 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2516 out << " if (!file) return;" << endl;
2517 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2518 out << " AliAnalysisManager *mgr = 0;" << endl;
2519 out << " TKey *key;" << endl;
2520 out << " while ((key=(TKey*)nextkey())) {" << endl;
2521 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2522 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2523 out << " };" << endl;
2524 out << " if (!mgr) {" << endl;
2525 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2526 out << " return;" << endl;
2527 out << " }" << endl << endl;
2528 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
2529 out << " mgr->PrintStatus();" << endl;
2530 if (AliAnalysisManager::GetAnalysisManager()) {
2531 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2532 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2533 } else {
2534 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2535 }
2536 }
2537 out << " mgr->StartAnalysis(\"gridterminate\");" << endl;
2538 out << "}" << endl << endl;
2539 if (hasANALYSISalice) {
2540 out <<"//________________________________________________________________________________" << endl;
2541 out << "Bool_t SetupPar(const char *package) {" << endl;
2542 out << "// Compile the package and set it up." << endl;
2543 out << " TString pkgdir = package;" << endl;
2544 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2545 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2546 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2547 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2548 out << " // Check for BUILD.sh and execute" << endl;
2549 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2550 out << " printf(\"*******************************\\n\");" << endl;
2551 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2552 out << " printf(\"*******************************\\n\");" << endl;
2553 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2554 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2555 out << " gSystem->ChangeDirectory(cdir);" << endl;
2556 out << " return kFALSE;" << endl;
2557 out << " }" << endl;
2558 out << " } else {" << endl;
2559 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2560 out << " gSystem->ChangeDirectory(cdir);" << endl;
2561 out << " return kFALSE;" << endl;
2562 out << " }" << endl;
2563 out << " // Check for SETUP.C and execute" << endl;
2564 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2565 out << " printf(\"*******************************\\n\");" << endl;
2566 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2567 out << " printf(\"*******************************\\n\");" << endl;
2568 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2569 out << " } else {" << endl;
2570 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2571 out << " gSystem->ChangeDirectory(cdir);" << endl;
2572 out << " return kFALSE;" << endl;
2573 out << " }" << endl;
2574 out << " // Restore original workdir" << endl;
2575 out << " gSystem->ChangeDirectory(cdir);" << endl;
2576 out << " return kTRUE;" << endl;
2577 out << "}" << endl;
2578 }
2579 }
2580 Bool_t copy = kTRUE;
2581 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2582 if (copy) {
2583 CdWork();
2584 TString workdir = gGrid->GetHomeDirectory();
2585 workdir += fGridWorkingDir;
2586 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
2587 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
2588 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
2589 }
2590}
2591
2592//______________________________________________________________________________
2593Bool_t AliAnalysisAlien::SetupPar(const char *package)
2594{
2595// Compile the par file archive pointed by <package>. This must be present in the current durectory.
2596// Note that for loading the compiled library. The current directory should have precedence in
2597// LD_LIBRARY_PATH
2598 TString pkgdir = package;
2599 pkgdir.ReplaceAll(".par","");
2600 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
2601 TString cdir = gSystem->WorkingDirectory();
2602 gSystem->ChangeDirectory(pkgdir);
2603 // Check for BUILD.sh and execute
2604 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
2605 printf("**************************************************\n");
2606 printf("*** Building PAR archive %s\n", package);
2607 printf("**************************************************\n");
2608 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
2609 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
2610 gSystem->ChangeDirectory(cdir);
2611 return kFALSE;
2612 }
2613 } else {
2614 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
2615 gSystem->ChangeDirectory(cdir);
2616 return kFALSE;
2617 }
2618 // Check for SETUP.C and execute
2619 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
2620 printf("**************************************************\n");
2621 printf("*** Setup PAR archive %s\n", package);
2622 printf("**************************************************\n");
2623 gROOT->Macro("PROOF-INF/SETUP.C");
2624 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
2625 } else {
2626 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
2627 gSystem->ChangeDirectory(cdir);
2628 return kFALSE;
2629 }
2630 // Restore original workdir
2631 gSystem->ChangeDirectory(cdir);
2632 return kTRUE;
2633}
2634
2635//______________________________________________________________________________
2636void AliAnalysisAlien::WriteExecutable()
2637{
2638// Generate the alien executable script.
2639 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2640 ofstream out;
2641 out.open(fExecutable.Data(), ios::out);
2642 if (out.bad()) {
2643 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2644 return;
2645 }
2646 out << "#!/bin/bash" << endl;
2647 out << "echo \"=========================================\"" << endl;
2648 out << "echo \"############## PATH : ##############\"" << endl;
2649 out << "echo $PATH" << endl;
2650 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2651 out << "echo $LD_LIBRARY_PATH" << endl;
2652 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2653 out << "echo $ROOTSYS" << endl;
2654 out << "echo \"############## which root : ##############\"" << endl;
2655 out << "which root" << endl;
2656 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2657 out << "echo $ALICE_ROOT" << endl;
2658 out << "echo \"############## which aliroot : ##############\"" << endl;
2659 out << "which aliroot" << endl;
2660 out << "echo \"############## system limits : ##############\"" << endl;
2661 out << "ulimit -a" << endl;
2662 out << "echo \"############## memory : ##############\"" << endl;
2663 out << "free -m" << endl;
2664 out << "echo \"=========================================\"" << endl << endl;
2665 // Make sure we can properly compile par files
2666 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2667 out << fExecutableCommand << " ";
2668 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2669 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2670 out << "echo \"############## memory after: ##############\"" << endl;
2671 out << "free -m" << endl;
2672 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2673 out << "dmesg | tail -n 10" << endl;
2674 }
2675 Bool_t copy = kTRUE;
2676 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2677 if (copy) {
2678 CdWork();
2679 TString workdir = gGrid->GetHomeDirectory();
2680 TString bindir = Form("%s/bin", workdir.Data());
2681 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2682 workdir += fGridWorkingDir;
2683 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2684 if (FileExists(executable)) gGrid->Rm(executable);
2685 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2686 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2687 }
2688}
2689
2690//______________________________________________________________________________
2691void AliAnalysisAlien::WriteMergeExecutable()
2692{
2693// Generate the alien executable script for the merging job.
2694 if (!fMergeViaJDL) return;
2695 TString mergeExec = fExecutable;
2696 mergeExec.ReplaceAll(".sh", "_merge.sh");
2697 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2698 ofstream out;
2699 out.open(mergeExec.Data(), ios::out);
2700 if (out.bad()) {
2701 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
2702 return;
2703 }
2704 out << "#!/bin/bash" << endl;
2705 out << "echo \"=========================================\"" << endl;
2706 out << "echo \"############## PATH : ##############\"" << endl;
2707 out << "echo $PATH" << endl;
2708 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2709 out << "echo $LD_LIBRARY_PATH" << endl;
2710 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2711 out << "echo $ROOTSYS" << endl;
2712 out << "echo \"############## which root : ##############\"" << endl;
2713 out << "which root" << endl;
2714 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2715 out << "echo $ALICE_ROOT" << endl;
2716 out << "echo \"############## which aliroot : ##############\"" << endl;
2717 out << "which aliroot" << endl;
2718 out << "echo \"############## system limits : ##############\"" << endl;
2719 out << "ulimit -a" << endl;
2720 out << "echo \"############## memory : ##############\"" << endl;
2721 out << "free -m" << endl;
2722 out << "echo \"=========================================\"" << endl << endl;
2723 // Make sure we can properly compile par files
2724 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2725 TString mergeMacro = fExecutable;
2726 mergeMacro.ReplaceAll(".sh", "_merge.C");
2727 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
2728 out << fExecutableCommand << " " << "$ARG" << endl;
2729 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
2730 out << "echo \"############## memory after: ##############\"" << endl;
2731 out << "free -m" << endl;
2732 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2733 out << "dmesg | tail -n 10" << endl;
2734 }
2735 Bool_t copy = kTRUE;
2736 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2737 if (copy) {
2738 CdWork();
2739 TString workdir = gGrid->GetHomeDirectory();
2740 TString bindir = Form("%s/bin", workdir.Data());
2741 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2742 workdir += fGridWorkingDir;
2743 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
2744 if (FileExists(executable)) gGrid->Rm(executable);
2745 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
2746 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
2747 }
2748}
2749
2750//______________________________________________________________________________
2751void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2752{
2753// Write the production file to be submitted by LPM manager. The format is:
2754// First line: full_path_to_jdl estimated_no_subjobs_per_master
2755// Next lines: full_path_to_dataset XXX (XXX is a string)
2756// To submit, one has to: submit jdl XXX for all lines
2757 ofstream out;
2758 out.open(filename, ios::out);
2759 if (out.bad()) {
2760 Error("WriteProductionFile", "Bad file name: %s", filename);
2761 return;
2762 }
2763 TString workdir = gGrid->GetHomeDirectory();
2764 workdir += fGridWorkingDir;
2765 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2766 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2767 out << locjdl << " " << njobspermaster << endl;
2768 Int_t nmasterjobs = fInputFiles->GetEntries();
2769 for (Int_t i=0; i<nmasterjobs; i++) {
2770 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2771 runOutDir.ReplaceAll(".xml", "");
2772 if (fOutputToRunNo)
2773 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
2774 else
2775 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2776 }
2777 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2778 if (FileExists(filename)) gGrid->Rm(filename);
2779 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2780}
2781
2782//______________________________________________________________________________
2783void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
2784{
2785// Generate the alien validation script.
2786 // Generate the validation script
2787 TObjString *os;
2788 TString validationScript = fExecutable;
2789 if (merge) validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
2790 else validationScript.ReplaceAll(".sh", "_validation.sh");
2791 if (!Connect()) {
2792 Error("WriteValidationScript", "Alien connection required");
2793 return;
2794 }
2795 TString out_stream = "";
2796 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2797 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2798 ofstream out;
2799 out.open(validationScript, ios::out);
2800 out << "#!/bin/bash" << endl;
2801 out << "##################################################" << endl;
2802 out << "validateout=`dirname $0`" << endl;
2803 out << "validatetime=`date`" << endl;
2804 out << "validated=\"0\";" << endl;
2805 out << "error=0" << endl;
2806 out << "if [ -z $validateout ]" << endl;
2807 out << "then" << endl;
2808 out << " validateout=\".\"" << endl;
2809 out << "fi" << endl << endl;
2810 out << "cd $validateout;" << endl;
2811 out << "validateworkdir=`pwd`;" << endl << endl;
2812 out << "echo \"*******************************************************\"" << out_stream << endl;
2813 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2814 out << "" << endl;
2815 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2816 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2817 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2818 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2819 out << "ls -la ./" << out_stream << endl;
2820 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2821 out << "##################################################" << endl;
2822
2823 out << "" << endl;
2824 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2825 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2826 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2827 out << "" << endl;
2828
2829 out << "if [ ! -f stderr ] ; then" << endl;
2830 out << " error=1" << endl;
2831 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2832 out << " echo \"Error = $error\" " << out_stream << endl;
2833 out << "fi" << endl;
2834
2835 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2836 out << " error=1" << endl;
2837 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2838 out << " echo \"$parArch\" " << out_stream << endl;
2839 out << " echo \"Error = $error\" " << out_stream << endl;
2840 out << "fi" << endl;
2841
2842 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2843 out << " error=1" << endl;
2844 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2845 out << " echo \"$segViol\" " << out_stream << endl;
2846 out << " echo \"Error = $error\" " << out_stream << endl;
2847 out << "fi" << endl;
2848
2849 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2850 out << " error=1" << endl;
2851 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2852 out << " echo \"$segFault\" " << out_stream << endl;
2853 out << " echo \"Error = $error\" " << out_stream << endl;
2854 out << "fi" << endl;
2855
2856 // Part dedicated to the specific analyses running into the train
2857
2858 TObjArray *arr = fOutputFiles.Tokenize(" ");
2859 TIter next1(arr);
2860 TString output_file;
2861 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2862 TString extra = mgr->GetExtraFiles();
2863 while ((os=(TObjString*)next1())) {
2864 output_file = os->GetString();
2865 Int_t index = output_file.Index("@");
2866 if (index > 0) output_file.Remove(index);
2867 if (merge && fMergeExcludes.Contains(output_file)) continue;
2868 if (extra.Contains(output_file)) continue;
2869 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2870 out << " error=1" << endl;
2871 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2872 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2873 out << "fi" << endl;
2874 }
2875 delete arr;
2876 if (!merge) {
2877 out << "if ! [ -f outputs_valid ] ; then" << endl;
2878 out << " error=1" << endl;
2879 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2880 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2881 out << "fi" << endl;
2882 }
2883
2884 out << "if [ $error = 0 ] ; then" << endl;
2885 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2886 out << "fi" << endl;
2887
2888 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2889 out << "echo \"*******************************************************\"" << out_stream << endl;
2890 out << "cd -" << endl;
2891 out << "exit $error" << endl;
2892 }
2893 Bool_t copy = kTRUE;
2894 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2895 if (copy) {
2896 CdWork();
2897 TString workdir = gGrid->GetHomeDirectory();
2898 workdir += fGridWorkingDir;
2899 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2900 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2901 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
2902 }
2903}