]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisAlien.cxx
Set status flag for TPC only tracks
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisAlien.cxx
CommitLineData
c57f56b7 1/**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16// Author: Mihaela Gheata, 01/09/2008
17
18//==============================================================================
19// AliAnalysisAlien - AliEn utility class. Provides interface for creating
20// a personalized JDL, finding and creating a dataset.
21//==============================================================================
22
23#include "Riostream.h"
0f389141 24#include "TEnv.h"
7c2cd90a 25#include "TBits.h"
0f389141 26#include "TError.h"
c57f56b7 27#include "TROOT.h"
28#include "TSystem.h"
29#include "TFile.h"
830acc4c 30#include "TFileCollection.h"
3bdcb562 31#include "TChain.h"
c57f56b7 32#include "TObjString.h"
33#include "TObjArray.h"
34#include "TGrid.h"
35#include "TGridResult.h"
36#include "TGridCollection.h"
37#include "TGridJDL.h"
d2a409b2 38#include "TGridJobStatusList.h"
39#include "TGridJobStatus.h"
c57f56b7 40#include "TFileMerger.h"
41#include "AliAnalysisManager.h"
bb885a9e 42#include "AliVEventHandler.h"
43#include "AliAnalysisDataContainer.h"
c57f56b7 44#include "AliAnalysisAlien.h"
45
46ClassImp(AliAnalysisAlien)
47
48//______________________________________________________________________________
49AliAnalysisAlien::AliAnalysisAlien()
50 :AliAnalysisGrid(),
51 fGridJDL(NULL),
0f389141 52 fMergingJDL(NULL),
c57f56b7 53 fPrice(0),
54 fTTL(0),
55 fSplitMaxInputFileNumber(0),
56 fMaxInitFailed(0),
57 fMasterResubmitThreshold(0),
bb885a9e 58 fNtestFiles(0),
319593fb 59 fNrunsPerMaster(0),
16a4353c 60 fMaxMergeFiles(0),
b3e07543 61 fMaxMergeStages(0),
d2a409b2 62 fNsubmitted(0),
a3e84053 63 fProductionMode(0),
cd11251e 64 fOutputToRunNo(0),
0f389141 65 fMergeViaJDL(0),
66 fFastReadOption(0),
e1c22e21 67 fOverwriteMode(1),
149d288c 68 fNreplicas(2),
3bdcb562 69 fNproofWorkers(0),
27734f0e 70 fNproofWorkersPerSlave(0),
3bdcb562 71 fProofReset(0),
c57f56b7 72 fRunNumbers(),
73 fExecutable(),
0a1c1f7f 74 fExecutableCommand(),
c57f56b7 75 fArguments(),
631c0b05 76 fExecutableArgs(),
c57f56b7 77 fAnalysisMacro(),
78 fAnalysisSource(),
d3b18c4c 79 fValidationScript(),
d5c6455a 80 fAdditionalRootLibs(),
c57f56b7 81 fAdditionalLibs(),
82 fSplitMode(),
83 fAPIVersion(),
84 fROOTVersion(),
85 fAliROOTVersion(),
648174cf 86 fExternalPackages(),
c57f56b7 87 fUser(),
88 fGridWorkingDir(),
89 fGridDataDir(),
90 fDataPattern(),
91 fGridOutputDir(),
92 fOutputArchive(),
93 fOutputFiles(),
94 fInputFormat(),
e7c71df0 95 fDatasetName(),
c57f56b7 96 fJDLName(),
d3b18c4c 97 fTerminateFiles(),
bb885a9e 98 fMergeExcludes(),
f965131e 99 fIncludePath(),
bb885a9e 100 fCloseSE(),
0df6ccf2 101 fFriendChainName(),
c6cb3634 102 fJobTag(),
648174cf 103 fOutputSingle(),
5fce53f4 104 fRunPrefix(),
3bdcb562 105 fProofCluster(),
106 fProofDataSet(),
107 fFileForTestMode(),
108 fRootVersionForProof(),
109 fAliRootMode(),
f47d5cb4 110 fMergeDirName(),
4e5c5506 111 fInputFiles(0),
112 fPackages(0)
c57f56b7 113{
114// Dummy ctor.
115 SetDefaults();
116}
117
118//______________________________________________________________________________
119AliAnalysisAlien::AliAnalysisAlien(const char *name)
120 :AliAnalysisGrid(name),
121 fGridJDL(NULL),
0f389141 122 fMergingJDL(NULL),
c57f56b7 123 fPrice(0),
124 fTTL(0),
125 fSplitMaxInputFileNumber(0),
126 fMaxInitFailed(0),
127 fMasterResubmitThreshold(0),
bb885a9e 128 fNtestFiles(0),
319593fb 129 fNrunsPerMaster(0),
16a4353c 130 fMaxMergeFiles(0),
b3e07543 131 fMaxMergeStages(0),
d2a409b2 132 fNsubmitted(0),
a3e84053 133 fProductionMode(0),
cd11251e 134 fOutputToRunNo(0),
0f389141 135 fMergeViaJDL(0),
136 fFastReadOption(0),
e1c22e21 137 fOverwriteMode(1),
149d288c 138 fNreplicas(2),
3bdcb562 139 fNproofWorkers(0),
27734f0e 140 fNproofWorkersPerSlave(0),
3bdcb562 141 fProofReset(0),
c57f56b7 142 fRunNumbers(),
143 fExecutable(),
0a1c1f7f 144 fExecutableCommand(),
c57f56b7 145 fArguments(),
631c0b05 146 fExecutableArgs(),
c57f56b7 147 fAnalysisMacro(),
148 fAnalysisSource(),
d3b18c4c 149 fValidationScript(),
d5c6455a 150 fAdditionalRootLibs(),
c57f56b7 151 fAdditionalLibs(),
152 fSplitMode(),
153 fAPIVersion(),
154 fROOTVersion(),
155 fAliROOTVersion(),
648174cf 156 fExternalPackages(),
c57f56b7 157 fUser(),
158 fGridWorkingDir(),
159 fGridDataDir(),
160 fDataPattern(),
161 fGridOutputDir(),
162 fOutputArchive(),
163 fOutputFiles(),
164 fInputFormat(),
e7c71df0 165 fDatasetName(),
c57f56b7 166 fJDLName(),
d3b18c4c 167 fTerminateFiles(),
bb885a9e 168 fMergeExcludes(),
f965131e 169 fIncludePath(),
bb885a9e 170 fCloseSE(),
0df6ccf2 171 fFriendChainName(),
c6cb3634 172 fJobTag(),
648174cf 173 fOutputSingle(),
5fce53f4 174 fRunPrefix(),
3bdcb562 175 fProofCluster(),
176 fProofDataSet(),
177 fFileForTestMode(),
178 fRootVersionForProof(),
179 fAliRootMode(),
f47d5cb4 180 fMergeDirName(),
4e5c5506 181 fInputFiles(0),
182 fPackages(0)
c57f56b7 183{
184// Default ctor.
185 SetDefaults();
186}
187
188//______________________________________________________________________________
189AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
190 :AliAnalysisGrid(other),
191 fGridJDL(NULL),
0f389141 192 fMergingJDL(NULL),
c57f56b7 193 fPrice(other.fPrice),
194 fTTL(other.fTTL),
195 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
196 fMaxInitFailed(other.fMaxInitFailed),
197 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
bb885a9e 198 fNtestFiles(other.fNtestFiles),
319593fb 199 fNrunsPerMaster(other.fNrunsPerMaster),
16a4353c 200 fMaxMergeFiles(other.fMaxMergeFiles),
b3e07543 201 fMaxMergeStages(other.fMaxMergeStages),
d2a409b2 202 fNsubmitted(other.fNsubmitted),
a3e84053 203 fProductionMode(other.fProductionMode),
cd11251e 204 fOutputToRunNo(other.fOutputToRunNo),
0f389141 205 fMergeViaJDL(other.fMergeViaJDL),
206 fFastReadOption(other.fFastReadOption),
207 fOverwriteMode(other.fOverwriteMode),
149d288c 208 fNreplicas(other.fNreplicas),
3bdcb562 209 fNproofWorkers(other.fNproofWorkers),
27734f0e 210 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
3bdcb562 211 fProofReset(other.fProofReset),
c57f56b7 212 fRunNumbers(other.fRunNumbers),
213 fExecutable(other.fExecutable),
0a1c1f7f 214 fExecutableCommand(other.fExecutableCommand),
c57f56b7 215 fArguments(other.fArguments),
631c0b05 216 fExecutableArgs(other.fExecutableArgs),
c57f56b7 217 fAnalysisMacro(other.fAnalysisMacro),
218 fAnalysisSource(other.fAnalysisSource),
d3b18c4c 219 fValidationScript(other.fValidationScript),
d5c6455a 220 fAdditionalRootLibs(other.fAdditionalRootLibs),
c57f56b7 221 fAdditionalLibs(other.fAdditionalLibs),
222 fSplitMode(other.fSplitMode),
223 fAPIVersion(other.fAPIVersion),
224 fROOTVersion(other.fROOTVersion),
225 fAliROOTVersion(other.fAliROOTVersion),
648174cf 226 fExternalPackages(other.fExternalPackages),
c57f56b7 227 fUser(other.fUser),
228 fGridWorkingDir(other.fGridWorkingDir),
229 fGridDataDir(other.fGridDataDir),
230 fDataPattern(other.fDataPattern),
231 fGridOutputDir(other.fGridOutputDir),
232 fOutputArchive(other.fOutputArchive),
233 fOutputFiles(other.fOutputFiles),
234 fInputFormat(other.fInputFormat),
e7c71df0 235 fDatasetName(other.fDatasetName),
c57f56b7 236 fJDLName(other.fJDLName),
d3b18c4c 237 fTerminateFiles(other.fTerminateFiles),
bb885a9e 238 fMergeExcludes(other.fMergeExcludes),
f965131e 239 fIncludePath(other.fIncludePath),
bb885a9e 240 fCloseSE(other.fCloseSE),
0df6ccf2 241 fFriendChainName(other.fFriendChainName),
c6cb3634 242 fJobTag(other.fJobTag),
648174cf 243 fOutputSingle(other.fOutputSingle),
5fce53f4 244 fRunPrefix(other.fRunPrefix),
3bdcb562 245 fProofCluster(other.fProofCluster),
246 fProofDataSet(other.fProofDataSet),
247 fFileForTestMode(other.fFileForTestMode),
248 fRootVersionForProof(other.fRootVersionForProof),
249 fAliRootMode(other.fAliRootMode),
f47d5cb4 250 fMergeDirName(other.fMergeDirName),
4e5c5506 251 fInputFiles(0),
252 fPackages(0)
c57f56b7 253{
254// Copy ctor.
255 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 256 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
a8739e8a 257 fRunRange[0] = other.fRunRange[0];
258 fRunRange[1] = other.fRunRange[1];
c57f56b7 259 if (other.fInputFiles) {
260 fInputFiles = new TObjArray();
261 TIter next(other.fInputFiles);
262 TObject *obj;
263 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
264 fInputFiles->SetOwner();
265 }
4e5c5506 266 if (other.fPackages) {
267 fPackages = new TObjArray();
268 TIter next(other.fPackages);
269 TObject *obj;
270 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
271 fPackages->SetOwner();
272 }
c57f56b7 273}
274
275//______________________________________________________________________________
276AliAnalysisAlien::~AliAnalysisAlien()
277{
278// Destructor.
279 if (fGridJDL) delete fGridJDL;
0f389141 280 if (fMergingJDL) delete fMergingJDL;
c57f56b7 281 if (fInputFiles) delete fInputFiles;
4e5c5506 282 if (fPackages) delete fPackages;
c57f56b7 283}
284
285//______________________________________________________________________________
286AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
287{
288// Assignment.
289 if (this != &other) {
290 AliAnalysisGrid::operator=(other);
291 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 292 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
c57f56b7 293 fPrice = other.fPrice;
294 fTTL = other.fTTL;
295 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
296 fMaxInitFailed = other.fMaxInitFailed;
297 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
bb885a9e 298 fNtestFiles = other.fNtestFiles;
a3e84053 299 fNrunsPerMaster = other.fNrunsPerMaster;
300 fMaxMergeFiles = other.fMaxMergeFiles;
b3e07543 301 fMaxMergeStages = other.fMaxMergeStages;
a3e84053 302 fNsubmitted = other.fNsubmitted;
303 fProductionMode = other.fProductionMode;
cd11251e 304 fOutputToRunNo = other.fOutputToRunNo;
0f389141 305 fMergeViaJDL = other.fMergeViaJDL;
306 fFastReadOption = other.fFastReadOption;
307 fOverwriteMode = other.fOverwriteMode;
149d288c 308 fNreplicas = other.fNreplicas;
3bdcb562 309 fNproofWorkers = other.fNproofWorkers;
27734f0e 310 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
3bdcb562 311 fProofReset = other.fProofReset;
c57f56b7 312 fRunNumbers = other.fRunNumbers;
313 fExecutable = other.fExecutable;
0a1c1f7f 314 fExecutableCommand = other.fExecutableCommand;
c57f56b7 315 fArguments = other.fArguments;
631c0b05 316 fExecutableArgs = other.fExecutableArgs;
c57f56b7 317 fAnalysisMacro = other.fAnalysisMacro;
318 fAnalysisSource = other.fAnalysisSource;
d3b18c4c 319 fValidationScript = other.fValidationScript;
d5c6455a 320 fAdditionalRootLibs = other.fAdditionalRootLibs;
c57f56b7 321 fAdditionalLibs = other.fAdditionalLibs;
322 fSplitMode = other.fSplitMode;
323 fAPIVersion = other.fAPIVersion;
324 fROOTVersion = other.fROOTVersion;
325 fAliROOTVersion = other.fAliROOTVersion;
648174cf 326 fExternalPackages = other.fExternalPackages;
c57f56b7 327 fUser = other.fUser;
328 fGridWorkingDir = other.fGridWorkingDir;
329 fGridDataDir = other.fGridDataDir;
330 fDataPattern = other.fDataPattern;
331 fGridOutputDir = other.fGridOutputDir;
332 fOutputArchive = other.fOutputArchive;
333 fOutputFiles = other.fOutputFiles;
334 fInputFormat = other.fInputFormat;
e7c71df0 335 fDatasetName = other.fDatasetName;
c57f56b7 336 fJDLName = other.fJDLName;
d3b18c4c 337 fTerminateFiles = other.fTerminateFiles;
bb885a9e 338 fMergeExcludes = other.fMergeExcludes;
f965131e 339 fIncludePath = other.fIncludePath;
bb885a9e 340 fCloseSE = other.fCloseSE;
0df6ccf2 341 fFriendChainName = other.fFriendChainName;
c6cb3634 342 fJobTag = other.fJobTag;
648174cf 343 fOutputSingle = other.fOutputSingle;
5fce53f4 344 fRunPrefix = other.fRunPrefix;
3bdcb562 345 fProofCluster = other.fProofCluster;
346 fProofDataSet = other.fProofDataSet;
347 fFileForTestMode = other.fFileForTestMode;
348 fRootVersionForProof = other.fRootVersionForProof;
349 fAliRootMode = other.fAliRootMode;
f47d5cb4 350 fMergeDirName = other.fMergeDirName;
c57f56b7 351 if (other.fInputFiles) {
352 fInputFiles = new TObjArray();
353 TIter next(other.fInputFiles);
354 TObject *obj;
355 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
356 fInputFiles->SetOwner();
357 }
4e5c5506 358 if (other.fPackages) {
359 fPackages = new TObjArray();
360 TIter next(other.fPackages);
361 TObject *obj;
362 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
363 fPackages->SetOwner();
364 }
c57f56b7 365 }
366 return *this;
367}
368
74013535 369//______________________________________________________________________________
370void AliAnalysisAlien::SetRunPrefix(const char *prefix)
371{
372// Set the run number format. Can be a prefix or a format like "%09d"
373 fRunPrefix = prefix;
374 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
375}
376
f965131e 377//______________________________________________________________________________
378void AliAnalysisAlien::AddIncludePath(const char *path)
379{
380// Add include path in the remote analysis macro.
381 TString p(path);
382 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
383 else fIncludePath += Form("-I%s ", path);
384}
385
c57f56b7 386//______________________________________________________________________________
387void AliAnalysisAlien::AddRunNumber(Int_t run)
388{
389// Add a run number to the list of runs to be processed.
390 if (fRunNumbers.Length()) fRunNumbers += " ";
74013535 391 fRunNumbers += Form(fRunPrefix.Data(), run);
c57f56b7 392}
393
ee75cfc3 394//______________________________________________________________________________
395void AliAnalysisAlien::AddRunNumber(const char* run)
396{
397// Add a run number to the list of runs to be processed.
398 if (fRunNumbers.Length()) fRunNumbers += " ";
399 fRunNumbers += run;
400}
401
c57f56b7 402//______________________________________________________________________________
403void AliAnalysisAlien::AddDataFile(const char *lfn)
404{
405// Adds a data file to the input to be analysed. The file should be a valid LFN
406// or point to an existing file in the alien workdir.
407 if (!fInputFiles) fInputFiles = new TObjArray();
408 fInputFiles->Add(new TObjString(lfn));
409}
648174cf 410
411//______________________________________________________________________________
412void AliAnalysisAlien::AddExternalPackage(const char *package)
413{
414// Adds external packages w.r.t to the default ones (root,aliroot and gapi)
415 if (fExternalPackages) fExternalPackages += " ";
416 fExternalPackages += package;
417}
418
c57f56b7 419//______________________________________________________________________________
420Bool_t AliAnalysisAlien::Connect()
421{
422// Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
423 if (gGrid && gGrid->IsConnected()) return kTRUE;
d3b18c4c 424 if (fProductionMode) return kTRUE;
c57f56b7 425 if (!gGrid) {
426 Info("Connect", "Trying to connect to AliEn ...");
427 TGrid::Connect("alien://");
428 }
429 if (!gGrid || !gGrid->IsConnected()) {
430 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
431 return kFALSE;
432 }
433 fUser = gGrid->GetUser();
434 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
435 return kTRUE;
436}
437
438//______________________________________________________________________________
439void AliAnalysisAlien::CdWork()
440{
441// Check validity of alien workspace. Create directory if possible.
442 if (!Connect()) {
443 Error("CdWork", "Alien connection required");
444 return;
445 }
446 TString homedir = gGrid->GetHomeDirectory();
447 TString workdir = homedir + fGridWorkingDir;
923e2ca5 448 if (DirectoryExists(workdir)) {
449 gGrid->Cd(workdir);
450 return;
451 }
452 // Work directory not existing - create it
453 gGrid->Cd(homedir);
b93f8109 454 if (gGrid->Mkdir(workdir, "-p")) {
923e2ca5 455 gGrid->Cd(fGridWorkingDir);
d3b18c4c 456 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
923e2ca5 457 } else {
d3b18c4c 458 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
923e2ca5 459 workdir.Data(), homedir.Data());
460 fGridWorkingDir = "";
461 }
c57f56b7 462}
463
348be253 464//______________________________________________________________________________
465Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
466{
467// Check if file copying is possible.
d3b18c4c 468 if (fProductionMode) return kTRUE;
348be253 469 if (!Connect()) {
470 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
471 return kFALSE;
472 }
d3339be3 473 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
474 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
348be253 475 // Check if alien_CLOSE_SE is defined
476 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
477 if (!closeSE.IsNull()) {
478 Info("CheckFileCopy", "Your current close storage is pointing to: \
479 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
480 } else {
481 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
482 }
483 // Check if grid directory exists.
484 if (!DirectoryExists(alienpath)) {
485 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
486 return kFALSE;
487 }
d3339be3 488 TFile f("plugin_test_copy", "RECREATE");
348be253 489 // User may not have write permissions to current directory
490 if (f.IsZombie()) {
491 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
492 gSystem->WorkingDirectory());
493 return kFALSE;
494 }
495 f.Close();
d3339be3 496 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
497 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
498 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
348be253 499 \n# 1. Make sure you have write permissions there. If this is the case: \
500 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
501 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
502 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
503 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
504 gSystem->Unlink(f.GetName());
505 return kFALSE;
506 }
507 gSystem->Unlink(f.GetName());
d3339be3 508 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
509 Info("CheckFileCopy", "### ...SUCCESS ###");
348be253 510 return kTRUE;
511}
512
c57f56b7 513//______________________________________________________________________________
514Bool_t AliAnalysisAlien::CheckInputData()
515{
516// Check validity of input data. If necessary, create xml files.
d3b18c4c 517 if (fProductionMode) return kTRUE;
a8739e8a 518 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
d2a409b2 519 if (!fGridDataDir.Length()) {
520 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
521 return kFALSE;
522 }
523 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
23329835 524 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
525 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
d2a409b2 526 return kTRUE;
c57f56b7 527 }
528 // Process declared files
a2f5fc01 529 Bool_t isCollection = kFALSE;
530 Bool_t isXml = kFALSE;
531 Bool_t useTags = kFALSE;
c57f56b7 532 Bool_t checked = kFALSE;
d3b18c4c 533 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
c57f56b7 534 TString file;
535 TString workdir = gGrid->GetHomeDirectory();
536 workdir += fGridWorkingDir;
537 if (fInputFiles) {
538 TObjString *objstr;
539 TIter next(fInputFiles);
540 while ((objstr=(TObjString*)next())) {
541 file = workdir;
542 file += "/";
543 file += objstr->GetString();
544 // Store full lfn path
545 if (FileExists(file)) objstr->SetString(file);
546 else {
547 file = objstr->GetName();
548 if (!FileExists(objstr->GetName())) {
549 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
550 objstr->GetName(), workdir.Data());
551 return kFALSE;
552 }
553 }
554 Bool_t iscoll, isxml, usetags;
555 CheckDataType(file, iscoll, isxml, usetags);
556 if (!checked) {
557 checked = kTRUE;
a2f5fc01 558 isCollection = iscoll;
559 isXml = isxml;
560 useTags = usetags;
561 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
c57f56b7 562 } else {
a2f5fc01 563 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
c57f56b7 564 Error("CheckInputData", "Some conflict was found in the types of inputs");
565 return kFALSE;
566 }
567 }
568 }
569 }
570 // Process requested run numbers
a8739e8a 571 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
c57f56b7 572 // Check validity of alien data directory
573 if (!fGridDataDir.Length()) {
574 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
575 return kFALSE;
576 }
923e2ca5 577 if (!DirectoryExists(fGridDataDir)) {
c57f56b7 578 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
579 return kFALSE;
580 }
a2f5fc01 581 if (isCollection) {
c57f56b7 582 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
583 return kFALSE;
584 }
585
a2f5fc01 586 if (checked && !isXml) {
c57f56b7 587 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
588 return kFALSE;
589 }
590 // Check validity of run number(s)
591 TObjArray *arr;
592 TObjString *os;
74013535 593 TString format;
319593fb 594 Int_t nruns = 0;
904f9f5f 595 TString schunk, schunk2;
c57f56b7 596 TString path;
597 if (!checked) {
598 checked = kTRUE;
a2f5fc01 599 useTags = fDataPattern.Contains("tag");
600 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
c57f56b7 601 }
a2f5fc01 602 if (useTags != fDataPattern.Contains("tag")) {
c57f56b7 603 Error("CheckInputData", "Cannot mix input files using/not using tags");
604 return kFALSE;
605 }
606 if (fRunNumbers.Length()) {
a8739e8a 607 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
c57f56b7 608 arr = fRunNumbers.Tokenize(" ");
609 TIter next(arr);
610 while ((os=(TObjString*)next())) {
611 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
923e2ca5 612 if (!DirectoryExists(path)) {
613 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
a8739e8a 614 continue;
c57f56b7 615 }
616 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
617 TString msg = "\n##### file: ";
618 msg += path;
619 msg += " type: xml_collection;";
a2f5fc01 620 if (useTags) msg += " using_tags: Yes";
c57f56b7 621 else msg += " using_tags: No";
23329835 622 Info("CheckDataType", "%s", msg.Data());
319593fb 623 if (fNrunsPerMaster<2) {
d2a409b2 624 AddDataFile(Form("%s.xml", os->GetString().Data()));
319593fb 625 } else {
626 nruns++;
627 if (((nruns-1)%fNrunsPerMaster) == 0) {
628 schunk = os->GetString();
629 }
630 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
631 schunk += Form("_%s.xml", os->GetString().Data());
d2a409b2 632 AddDataFile(schunk);
319593fb 633 }
c57f56b7 634 }
635 delete arr;
a8739e8a 636 } else {
637 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
638 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
74013535 639 format = Form("%%s/%s ", fRunPrefix.Data());
640 path = Form(format.Data(), fGridDataDir.Data(), irun);
923e2ca5 641 if (!DirectoryExists(path)) {
a8739e8a 642 continue;
643 }
74013535 644 format = Form("%%s/%s.xml", fRunPrefix.Data());
645 path = Form(format.Data(), workdir.Data(),irun);
a8739e8a 646 TString msg = "\n##### file: ";
647 msg += path;
648 msg += " type: xml_collection;";
a2f5fc01 649 if (useTags) msg += " using_tags: Yes";
a8739e8a 650 else msg += " using_tags: No";
23329835 651 Info("CheckDataType", "%s", msg.Data());
319593fb 652 if (fNrunsPerMaster<2) {
74013535 653 format = Form("%s.xml", fRunPrefix.Data());
654 AddDataFile(Form(format.Data(),irun));
319593fb 655 } else {
656 nruns++;
657 if (((nruns-1)%fNrunsPerMaster) == 0) {
74013535 658 schunk = Form(fRunPrefix.Data(),irun);
319593fb 659 }
74013535 660 format = Form("_%s.xml", fRunPrefix.Data());
661 schunk2 = Form(format.Data(), irun);
319593fb 662 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
904f9f5f 663 schunk += schunk2;
d2a409b2 664 AddDataFile(schunk);
319593fb 665 }
a8739e8a 666 }
904f9f5f 667 if (!fInputFiles) {
668 schunk += schunk2;
669 AddDataFile(schunk);
670 }
c57f56b7 671 }
672 return kTRUE;
673}
674
675//______________________________________________________________________________
676Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
677{
678// Create dataset for the grid data directory + run number.
d3b18c4c 679 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
c57f56b7 680 if (!Connect()) {
681 Error("CreateDataset", "Cannot create dataset with no grid connection");
682 return kFALSE;
683 }
684
685 // Cd workspace
d3b18c4c 686 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
c57f56b7 687 TString workdir = gGrid->GetHomeDirectory();
688 workdir += fGridWorkingDir;
689
690 // Compose the 'find' command arguments
74013535 691 TString format;
c57f56b7 692 TString command;
693 TString options = "-x collection ";
bb885a9e 694 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
c57f56b7 695 TString conditions = "";
696
697 TString file;
698 TString path;
319593fb 699 Int_t nruns = 0;
904f9f5f 700 TString schunk, schunk2;
ab254fd1 701 TGridCollection *cbase=0, *cadd=0;
d2a409b2 702 if (!fRunNumbers.Length() && !fRunRange[0]) {
703 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
704 // Make a single data collection from data directory.
705 path = fGridDataDir;
923e2ca5 706 if (!DirectoryExists(path)) {
d2a409b2 707 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
708 return kFALSE;
709 }
923e2ca5 710// CdWork();
d2a409b2 711 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
712 else file = Form("%s.xml", gSystem->BaseName(path));
0f389141 713 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
d2a409b2 714 command = "find ";
715 command += options;
716 command += path;
717 command += " ";
718 command += pattern;
719 command += conditions;
84fcd93f 720 printf("command: %s\n", command.Data());
d2a409b2 721 TGridResult *res = gGrid->Command(command);
722 if (res) delete res;
723 // Write standard output to file
724 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
a2f5fc01 725 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
726 Bool_t nullFile = kFALSE;
727 if (!hasGrep) {
d3339be3 728 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
729 } else {
a2f5fc01 730 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
731 if (nullFile) {
defd7a3a 732 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
733 return kFALSE;
734 }
d3339be3 735 }
0f389141 736 }
737 Bool_t fileExists = FileExists(file);
738 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
d2a409b2 739 // Copy xml file to alien space
0f389141 740 if (fileExists) gGrid->Rm(file);
d2a409b2 741 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
742 if (!FileExists(file)) {
743 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
744 return kFALSE;
745 }
746 // Update list of files to be processed.
747 }
748 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
749 return kTRUE;
750 }
c57f56b7 751 // Several runs
a2f5fc01 752 Bool_t nullResult = kTRUE;
a8739e8a 753 if (fRunNumbers.Length()) {
754 TObjArray *arr = fRunNumbers.Tokenize(" ");
755 TObjString *os;
756 TIter next(arr);
757 while ((os=(TObjString*)next())) {
758 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
923e2ca5 759 if (!DirectoryExists(path)) continue;
760// CdWork();
a8739e8a 761 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
762 else file = Form("%s.xml", os->GetString().Data());
319593fb 763 // If local collection file does not exist, create it via 'find' command.
d3339be3 764 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
319593fb 765 command = "find ";
766 command += options;
767 command += path;
768 command += pattern;
769 command += conditions;
770 TGridResult *res = gGrid->Command(command);
771 if (res) delete res;
772 // Write standard output to file
773 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
a2f5fc01 774 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
775 Bool_t nullFile = kFALSE;
776 if (!hasGrep) {
d3339be3 777 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
778 } else {
a2f5fc01 779 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
780 if (nullFile) {
defd7a3a 781 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
782 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
783 continue;
784 }
d3339be3 785 }
a2f5fc01 786 nullResult = kFALSE;
d3339be3 787 }
a8739e8a 788 if (TestBit(AliAnalysisGrid::kTest)) break;
319593fb 789 // Check if there is one run per master job.
790 if (fNrunsPerMaster<2) {
791 if (FileExists(file)) {
0f389141 792 if (fOverwriteMode) gGrid->Rm(file);
793 else {
794 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
795 continue;
796 }
319593fb 797 }
798 // Copy xml file to alien space
799 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
800 if (!FileExists(file)) {
801 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
802 delete arr;
803 return kFALSE;
804 }
805 } else {
806 nruns++;
807 if (((nruns-1)%fNrunsPerMaster) == 0) {
808 schunk = os->GetString();
809 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
810 } else {
811 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
84fcd93f 812 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
319593fb 813 cbase->Add(cadd);
814 delete cadd;
815 }
816 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
817 continue;
818 }
819 schunk += Form("_%s.xml", os->GetString().Data());
0f389141 820 if (FileExists(schunk)) {
821 if (fOverwriteMode) gGrid->Rm(file);
822 else {
823 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
824 continue;
825 }
319593fb 826 }
84fcd93f 827 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
319593fb 828 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
e95434bc 829 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
319593fb 830 if (!FileExists(schunk)) {
831 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
832 delete arr;
833 return kFALSE;
834 }
d3339be3 835 }
a8739e8a 836 }
837 delete arr;
a2f5fc01 838 if (nullResult) {
d3339be3 839 Error("CreateDataset", "No valid dataset corresponding to the query!");
840 return kFALSE;
841 }
a8739e8a 842 } else {
843 // Process a full run range.
844 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
74013535 845 format = Form("%%s/%s ", fRunPrefix.Data());
846 path = Form(format.Data(), fGridDataDir.Data(), irun);
923e2ca5 847 if (!DirectoryExists(path)) continue;
848// CdWork();
74013535 849 format = Form("%s.xml", fRunPrefix.Data());
a8739e8a 850 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
74013535 851 else file = Form(format.Data(), irun);
0f389141 852 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
853 if (fOverwriteMode) gGrid->Rm(file);
854 else {
855 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
856 continue;
857 }
a8739e8a 858 }
319593fb 859 // If local collection file does not exist, create it via 'find' command.
d3339be3 860 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
319593fb 861 command = "find ";
862 command += options;
863 command += path;
864 command += pattern;
865 command += conditions;
866 TGridResult *res = gGrid->Command(command);
867 if (res) delete res;
868 // Write standard output to file
869 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
a2f5fc01 870 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
871 Bool_t nullFile = kFALSE;
872 if (!hasGrep) {
d3339be3 873 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
874 } else {
a2f5fc01 875 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
876 if (nullFile) {
defd7a3a 877 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
878 continue;
879 }
d3339be3 880 }
a2f5fc01 881 nullResult = kFALSE;
319593fb 882 }
a8739e8a 883 if (TestBit(AliAnalysisGrid::kTest)) break;
319593fb 884 // Check if there is one run per master job.
885 if (fNrunsPerMaster<2) {
886 if (FileExists(file)) {
0f389141 887 if (fOverwriteMode) gGrid->Rm(file);
888 else {
889 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
890 continue;
891 }
319593fb 892 }
893 // Copy xml file to alien space
894 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
895 if (!FileExists(file)) {
896 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
897 return kFALSE;
898 }
899 } else {
900 nruns++;
95e5b448 901 // Check if the collection for the chunk exist locally.
902 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
0f389141 903 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
904 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
905 else continue;
906 }
84fcd93f 907 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
319593fb 908 if (((nruns-1)%fNrunsPerMaster) == 0) {
74013535 909 schunk = Form(fRunPrefix.Data(), irun);
319593fb 910 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
911 } else {
912 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
913 cbase->Add(cadd);
914 delete cadd;
915 }
74013535 916 format = Form("%%s_%s.xml", fRunPrefix.Data());
917 schunk2 = Form(format.Data(), schunk.Data(), irun);
904f9f5f 918 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
319593fb 919 continue;
920 }
904f9f5f 921 schunk = schunk2;
319593fb 922 if (FileExists(schunk)) {
0f389141 923 if (fOverwriteMode) gGrid->Rm(schunk);
924 else {
925 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
926 continue;
927 }
319593fb 928 }
84fcd93f 929 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
319593fb 930 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
95e5b448 931 if (FileExists(schunk)) {
0f389141 932 if (fOverwriteMode) gGrid->Rm(schunk);
933 else {
934 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
935 continue;
936 }
95e5b448 937 }
319593fb 938 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
939 if (!FileExists(schunk)) {
940 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
941 return kFALSE;
942 }
943 }
c57f56b7 944 }
a2f5fc01 945 if (nullResult) {
d3339be3 946 Error("CreateDataset", "No valid dataset corresponding to the query!");
947 return kFALSE;
948 }
a8739e8a 949 }
c57f56b7 950 return kTRUE;
951}
952
953//______________________________________________________________________________
954Bool_t AliAnalysisAlien::CreateJDL()
955{
956// Generate a JDL file according to current settings. The name of the file is
957// specified by fJDLName.
958 Bool_t error = kFALSE;
959 TObjArray *arr = 0;
960 Bool_t copy = kTRUE;
d3b18c4c 961 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 962 Bool_t generate = kTRUE;
963 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
964 if (!Connect()) {
965 Error("CreateJDL", "Alien connection required");
966 return kFALSE;
967 }
968 // Check validity of alien workspace
d3b18c4c 969 TString workdir;
970 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
971 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
c57f56b7 972 workdir += fGridWorkingDir;
973 if (generate) {
974 TObjString *os;
975 if (!fInputFiles) {
976 Error("CreateJDL()", "Define some input files for your analysis.");
977 error = kTRUE;
978 }
979 // Compose list of input files
980 // Check if output files were defined
981 if (!fOutputFiles.Length()) {
982 Error("CreateJDL", "You must define at least one output file");
983 error = kTRUE;
984 }
985 // Check if an output directory was defined and valid
986 if (!fGridOutputDir.Length()) {
987 Error("CreateJDL", "You must define AliEn output directory");
988 error = kTRUE;
989 } else {
d3b18c4c 990 if (!fProductionMode) {
991 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
992 if (!DirectoryExists(fGridOutputDir)) {
993 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
994 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
995 } else {
996 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
997 // error = kTRUE;
998 }
67a3b254 999 } else {
1000 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
d3b18c4c 1001 }
1002 gGrid->Cd(workdir);
1003 }
c57f56b7 1004 }
1005 // Exit if any error up to now
1006 if (error) return kFALSE;
1007 // Set JDL fields
0f389141 1008 if (!fUser.IsNull()) {
1009 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1010 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1011 }
1012 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1013 TString mergeExec = fExecutable;
1014 mergeExec.ReplaceAll(".sh", "_merge.sh");
1015 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1016 mergeExec.ReplaceAll(".sh", ".C");
1017 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
b5b9dee8 1018 if (!fArguments.IsNull())
1019 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
d3b18c4c 1020 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
f47d5cb4 1021 else {
1022 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1023 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1024 }
b3e07543 1025
1f0d1ca2 1026 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1027 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1028 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1029 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1030
0f389141 1031 if (fMaxInitFailed > 0) {
c57f56b7 1032 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
0f389141 1033 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1034 }
1035 if (fSplitMaxInputFileNumber > 0) {
c57f56b7 1036 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
0f389141 1037 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
b3e07543 1038 }
1039 if (!IsOneStageMerging()) {
f47d5cb4 1040 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
b3e07543 1041 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
0f389141 1042 }
1043 if (fSplitMode.Length()) {
c57f56b7 1044 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
0f389141 1045 fGridJDL->SetDescription("Split", "We split per SE or file");
b3e07543 1046 }
1047 fMergingJDL->SetValue("Split", "\"se\"");
1048 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
0f389141 1049 if (!fAliROOTVersion.IsNull()) {
1050 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1051 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1052 }
1053 if (!fROOTVersion.IsNull()) {
c57f56b7 1054 fGridJDL->AddToPackages("ROOT", fROOTVersion);
0f389141 1055 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1056 }
1057 if (!fAPIVersion.IsNull()) {
c57f56b7 1058 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
0f389141 1059 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1060 }
648174cf 1061 if (!fExternalPackages.IsNull()) {
1062 arr = fExternalPackages.Tokenize(" ");
1063 TIter next(arr);
1064 while ((os=(TObjString*)next())) {
1065 TString pkgname = os->GetString();
1066 Int_t index = pkgname.Index("::");
1067 TString pkgversion = pkgname(index+2, pkgname.Length());
1068 pkgname.Remove(index);
1069 fGridJDL->AddToPackages(pkgname, pkgversion);
0f389141 1070 fMergingJDL->AddToPackages(pkgname, pkgversion);
648174cf 1071 }
1072 delete arr;
1073 }
0f389141 1074 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1075 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
b3e07543 1076 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1077 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
0f389141 1078 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
f10e8481 1079 TString analysisFile = fExecutable;
1080 analysisFile.ReplaceAll(".sh", ".root");
1081 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
f866cba5 1082 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 1083 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1084 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1085 if (fAdditionalLibs.Length()) {
1086 arr = fAdditionalLibs.Tokenize(" ");
1087 TIter next(arr);
1088 while ((os=(TObjString*)next())) {
1089 if (os->GetString().Contains(".so")) continue;
1090 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
0f389141 1091 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
c57f56b7 1092 }
1093 delete arr;
1094 }
4e5c5506 1095 if (fPackages) {
1096 TIter next(fPackages);
1097 TObject *obj;
0f389141 1098 while ((obj=next())) {
4e5c5506 1099 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
0f389141 1100 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1101 }
4e5c5506 1102 }
c57f56b7 1103 if (fOutputArchive.Length()) {
1104 arr = fOutputArchive.Tokenize(" ");
1105 TIter next(arr);
0f389141 1106 Bool_t first = kTRUE;
1107 const char *comment = "Files to be archived";
1108 const char *comment1 = comment;
1109 while ((os=(TObjString*)next())) {
1110 if (!first) comment = NULL;
1111 if (!os->GetString().Contains("@") && fCloseSE.Length())
1112 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1113 else
1114 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1115 first = kFALSE;
1116 }
c57f56b7 1117 delete arr;
f790bc1b 1118 // Output archive for the merging jdl
1119 TString outputArchive;
1120 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
b83f84f0 1121 outputArchive = "log_archive.zip:std*@disk=1 ";
f790bc1b 1122 // Add normal output files, extra files + terminate files
1123 TString files = GetListOfFiles("outextter");
1124 // Do not register merge excludes
1125 if (!fMergeExcludes.IsNull()) {
1126 arr = fMergeExcludes.Tokenize(" ");
1127 TIter next1(arr);
1128 while ((os=(TObjString*)next1())) {
1129 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1130 files.ReplaceAll(os->GetString(),"");
1131 }
66d71516 1132 delete arr;
0f389141 1133 }
f790bc1b 1134 files.ReplaceAll(".root", "*.root");
b83f84f0 1135 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
f790bc1b 1136 } else {
95f84779 1137 TString files = fOutputArchive;
1138 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1139 outputArchive = files;
f790bc1b 1140 }
0f389141 1141 arr = outputArchive.Tokenize(" ");
705adb3e 1142 TIter next2(arr);
0f389141 1143 comment = comment1;
1144 first = kTRUE;
705adb3e 1145 while ((os=(TObjString*)next2())) {
0f389141 1146 if (!first) comment = NULL;
0cdf65a8 1147 TString currentfile = os->GetString();
0cdf65a8 1148 if (!currentfile.Contains("@") && fCloseSE.Length())
d3b18c4c 1149 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
0f389141 1150 else
0cdf65a8 1151 fMergingJDL->AddToOutputArchive(currentfile, comment);
0f389141 1152 first = kFALSE;
1153 }
1154 delete arr;
c57f56b7 1155 }
149d288c 1156 arr = fOutputFiles.Tokenize(",");
c57f56b7 1157 TIter next(arr);
0f389141 1158 Bool_t first = kTRUE;
f790bc1b 1159 const char *comment = "Files to be saved";
43da816a 1160 while ((os=(TObjString*)next())) {
e1eaf596 1161 // Ignore ouputs in jdl that are also in outputarchive
1162 TString sout = os->GetString();
f790bc1b 1163 sout.ReplaceAll("*", "");
1164 sout.ReplaceAll(".root", "");
e1eaf596 1165 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1166 if (fOutputArchive.Contains(sout)) continue;
0f389141 1167 if (!first) comment = NULL;
43da816a 1168 if (!os->GetString().Contains("@") && fCloseSE.Length())
0f389141 1169 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
43da816a 1170 else
0f389141 1171 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
b3e07543 1172 first = kFALSE;
f790bc1b 1173 if (fMergeExcludes.Contains(sout)) continue;
1174 if (!os->GetString().Contains("@") && fCloseSE.Length())
1175 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1176 else
1177 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
43da816a 1178 }
c57f56b7 1179 delete arr;
0f389141 1180 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1181 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
d3b18c4c 1182 TString validationScript = fValidationScript;
0f389141 1183 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
d3b18c4c 1184 validationScript.ReplaceAll(".sh", "_merge.sh");
0f389141 1185 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1186 if (fMasterResubmitThreshold) {
1187 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1188 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1189 }
d2a409b2 1190 // Write a jdl with 2 input parameters: collection name and output dir name.
1191 WriteJDL(copy);
c57f56b7 1192 }
1193 // Copy jdl to grid workspace
a8739e8a 1194 if (copy) {
b5e4aaa7 1195 // Check if an output directory was defined and valid
1196 if (!fGridOutputDir.Length()) {
1197 Error("CreateJDL", "You must define AliEn output directory");
1198 return kFALSE;
1199 } else {
1200 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
bb2e67a0 1201 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
b93f8109 1202 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
b5e4aaa7 1203 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1204 } else {
1205 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1206 return kFALSE;
1207 }
1208 }
1209 gGrid->Cd(workdir);
1210 }
648174cf 1211 if (TestBit(AliAnalysisGrid::kSubmit)) {
0f389141 1212 TString mergeJDLName = fExecutable;
1213 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
648174cf 1214 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1215 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1216 if (fProductionMode) {
648174cf 1217 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1218 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1219 }
648174cf 1220 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1221 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1222 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
648174cf 1223 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1224 if (fMergeViaJDL) {
1225 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1226 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1227 }
648174cf 1228 }
c57f56b7 1229 if (fAdditionalLibs.Length()) {
e7c71df0 1230 arr = fAdditionalLibs.Tokenize(" ");
c57f56b7 1231 TObjString *os;
1232 TIter next(arr);
1233 while ((os=(TObjString*)next())) {
c57f56b7 1234 if (os->GetString().Contains(".so")) continue;
4e5c5506 1235 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
c57f56b7 1236 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1237 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1238 }
1239 delete arr;
1240 }
4e5c5506 1241 if (fPackages) {
1242 TIter next(fPackages);
1243 TObject *obj;
1244 while ((obj=next())) {
fdbbc7be 1245 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
4e5c5506 1246 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1247 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1248 }
1249 }
c57f56b7 1250 }
1251 return kTRUE;
1252}
1253
a8739e8a 1254//______________________________________________________________________________
d2a409b2 1255Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
a8739e8a 1256{
1257// Writes one or more JDL's corresponding to findex. If findex is negative,
1258// all run numbers are considered in one go (jdl). For non-negative indices
1259// they correspond to the indices in the array fInputFiles.
1260 if (!fInputFiles) return kFALSE;
d3b18c4c 1261 TObject *os;
1262 TString workdir;
1263 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
a8739e8a 1264 workdir += fGridWorkingDir;
f47d5cb4 1265 TString stageName = "$2";
1266 if (fProductionMode) stageName = "$4";
1267 if (!fMergeDirName.IsNull()) {
1268 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1269 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1270 } else {
1271 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1272 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1273 }
d3b18c4c 1274 if (fProductionMode) {
a8739e8a 1275 TIter next(fInputFiles);
b3e07543 1276 while ((os=next())) {
d3b18c4c 1277 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
b3e07543 1278 }
d3b18c4c 1279 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
d3b18c4c 1280 } else {
1281 if (!fRunNumbers.Length() && !fRunRange[0]) {
1282 // One jdl with no parameters in case input data is specified by name.
1283 TIter next(fInputFiles);
1284 while ((os=next()))
1285 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1286 if (!fOutputSingle.IsNull())
1287 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1288 else {
1289 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1290 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1291 }
1292 } else {
1293 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1294 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1295 if (!fOutputSingle.IsNull()) {
1296 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1297 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1298 } else {
1299 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
d3b18c4c 1300 }
1301 }
a8739e8a 1302 }
1303
a8739e8a 1304 // Generate the JDL as a string
1305 TString sjdl = fGridJDL->Generate();
0f389141 1306 TString sjdl1 = fMergingJDL->Generate();
f47d5cb4 1307 // Final merge jdl
1308 if (!fMergeDirName.IsNull()) {
1309 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1310 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1311 } else {
1312 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1313 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1314 }
b3e07543 1315 TString sjdl2 = fMergingJDL->Generate();
1316 Int_t index, index1;
a8739e8a 1317 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1318 sjdl.ReplaceAll("(member", "\n (member");
1319 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1320 sjdl.ReplaceAll("{", "{\n ");
1321 sjdl.ReplaceAll("};", "\n};");
1322 sjdl.ReplaceAll("{\n \n", "{\n");
1323 sjdl.ReplaceAll("\n\n", "\n");
1324 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
0f389141 1325 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1326 sjdl1.ReplaceAll("(member", "\n (member");
1327 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1328 sjdl1.ReplaceAll("{", "{\n ");
1329 sjdl1.ReplaceAll("};", "\n};");
1330 sjdl1.ReplaceAll("{\n \n", "{\n");
1331 sjdl1.ReplaceAll("\n\n", "\n");
1332 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
b3e07543 1333 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1334 sjdl2.ReplaceAll("(member", "\n (member");
1335 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1336 sjdl2.ReplaceAll("{", "{\n ");
1337 sjdl2.ReplaceAll("};", "\n};");
1338 sjdl2.ReplaceAll("{\n \n", "{\n");
1339 sjdl2.ReplaceAll("\n\n", "\n");
1340 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
a8739e8a 1341 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
f60ef0ba 1342 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
a8739e8a 1343 index = sjdl.Index("JDLVariables");
1344 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
4739b2aa 1345 sjdl += "Workdirectorysize = {\"5000MB\"};";
b3e07543 1346 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
0f389141 1347 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
d3b18c4c 1348 index = fJobTag.Index(":");
1349 if (index < 0) index = fJobTag.Length();
1350 TString jobTag = fJobTag;
f47d5cb4 1351 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
d3b18c4c 1352 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
f47d5cb4 1353 if (fProductionMode) {
1354 sjdl1.Prepend("# Generated merging jdl (production mode) \
1355 \n# $1 = full alien path to output directory to be merged \
1356 \n# $2 = train number \
1357 \n# $3 = production (like LHC10b) \
1358 \n# $4 = merging stage \
1359 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1360 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1361 sjdl2.Prepend("# Generated merging jdl \
1362 \n# $1 = full alien path to output directory to be merged \
1363 \n# $2 = train number \
1364 \n# $3 = production (like LHC10b) \
1365 \n# $4 = merging stage \
1366 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1367 } else {
1368 sjdl1.Prepend("# Generated merging jdl \
1369 \n# $1 = full alien path to output directory to be merged \
1370 \n# $2 = merging stage \
03335324 1371 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
f47d5cb4 1372 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1373 sjdl2.Prepend("# Generated merging jdl \
1374 \n# $1 = full alien path to output directory to be merged \
1375 \n# $2 = merging stage \
03335324 1376 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
f47d5cb4 1377 }
0f389141 1378 index = sjdl1.Index("JDLVariables");
1379 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
b3e07543 1380 index = sjdl2.Index("JDLVariables");
1381 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
4739b2aa 1382 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
b3e07543 1383 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1384 index = sjdl2.Index("Split =");
1385 if (index>=0) {
1386 index1 = sjdl2.Index("\n", index);
1387 sjdl2.Remove(index, index1-index+1);
1388 }
1389 index = sjdl2.Index("SplitMaxInputFileNumber");
1390 if (index>=0) {
1391 index1 = sjdl2.Index("\n", index);
1392 sjdl2.Remove(index, index1-index+1);
1393 }
1394 index = sjdl2.Index("InputDataCollection");
1395 if (index>=0) {
1396 index1 = sjdl2.Index(";", index);
1397 sjdl2.Remove(index, index1-index+1);
1398 }
1399 index = sjdl2.Index("InputDataListFormat");
1400 if (index>=0) {
1401 index1 = sjdl2.Index("\n", index);
1402 sjdl2.Remove(index, index1-index+1);
1403 }
1404 index = sjdl2.Index("InputDataList");
1405 if (index>=0) {
1406 index1 = sjdl2.Index("\n", index);
1407 sjdl2.Remove(index, index1-index+1);
1408 }
f47d5cb4 1409 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
a8739e8a 1410 // Write jdl to file
a8739e8a 1411 ofstream out;
d2a409b2 1412 out.open(fJDLName.Data(), ios::out);
a8739e8a 1413 if (out.bad()) {
d3b18c4c 1414 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
a8739e8a 1415 return kFALSE;
1416 }
1417 out << sjdl << endl;
b3e07543 1418 out.close();
0f389141 1419 TString mergeJDLName = fExecutable;
1420 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1421 if (fMergeViaJDL) {
1422 ofstream out1;
1423 out1.open(mergeJDLName.Data(), ios::out);
b3e07543 1424 if (out1.bad()) {
d3b18c4c 1425 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
0f389141 1426 return kFALSE;
1427 }
1428 out1 << sjdl1 << endl;
b3e07543 1429 out1.close();
1430 ofstream out2;
1431 TString finalJDL = mergeJDLName;
1432 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1433 out2.open(finalJDL.Data(), ios::out);
1434 if (out2.bad()) {
1435 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1436 return kFALSE;
1437 }
1438 out2 << sjdl2 << endl;
1439 out2.close();
0f389141 1440 }
a8739e8a 1441
1442 // Copy jdl to grid workspace
1443 if (!copy) {
d3b18c4c 1444 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
a8739e8a 1445 } else {
d2a409b2 1446 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1447 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
b3e07543 1448 TString finalJDL = mergeJDLName;
1449 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1450 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
0f389141 1451 if (fProductionMode) {
b5fe9cba 1452 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1453 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
b3e07543 1454 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
0f389141 1455 }
d2a409b2 1456 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1457 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
b3e07543 1458 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
d3b18c4c 1459 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
5513444a 1460 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1461 if (fMergeViaJDL) {
b3e07543 1462 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
0f389141 1463 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
b3e07543 1464 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
0f389141 1465 }
a8739e8a 1466 }
1467 return kTRUE;
1468}
1469
c57f56b7 1470//______________________________________________________________________________
5513444a 1471Bool_t AliAnalysisAlien::FileExists(const char *lfn)
c57f56b7 1472{
1473// Returns true if file exists.
5513444a 1474 if (!gGrid) return kFALSE;
2ea55496 1475 TString slfn = lfn;
1476 slfn.ReplaceAll("alien://","");
1477 TGridResult *res = gGrid->Ls(slfn);
c57f56b7 1478 if (!res) return kFALSE;
1479 TMap *map = dynamic_cast<TMap*>(res->At(0));
1480 if (!map) {
1481 delete res;
1482 return kFALSE;
1483 }
1484 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1485 if (!objs || !objs->GetString().Length()) {
1486 delete res;
1487 return kFALSE;
1488 }
1489 delete res;
1490 return kTRUE;
1491}
1492
923e2ca5 1493//______________________________________________________________________________
1494Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1495{
1496// Returns true if directory exists. Can be also a path.
1497 if (!gGrid) return kFALSE;
1498 // Check if dirname is a path
1499 TString dirstripped = dirname;
1500 dirstripped = dirstripped.Strip();
1501 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1502 TString dir = gSystem->BaseName(dirstripped);
1503 dir += "/";
1504 TString path = gSystem->DirName(dirstripped);
1505 TGridResult *res = gGrid->Ls(path, "-F");
1506 if (!res) return kFALSE;
1507 TIter next(res);
1508 TMap *map;
1509 TObject *obj;
1510 while ((map=dynamic_cast<TMap*>(next()))) {
1511 obj = map->GetValue("name");
1512 if (!obj) break;
1513 if (dir == obj->GetName()) {
1514 delete res;
1515 return kTRUE;
1516 }
1517 }
1518 delete res;
1519 return kFALSE;
1520}
1521
c57f56b7 1522//______________________________________________________________________________
a2f5fc01 1523void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
c57f56b7 1524{
1525// Check input data type.
a2f5fc01 1526 isCollection = kFALSE;
1527 isXml = kFALSE;
1528 useTags = kFALSE;
c57f56b7 1529 if (!gGrid) {
1530 Error("CheckDataType", "No connection to grid");
1531 return;
1532 }
a2f5fc01 1533 isCollection = IsCollection(lfn);
c57f56b7 1534 TString msg = "\n##### file: ";
1535 msg += lfn;
a2f5fc01 1536 if (isCollection) {
c57f56b7 1537 msg += " type: raw_collection;";
1538 // special treatment for collections
a2f5fc01 1539 isXml = kFALSE;
c57f56b7 1540 // check for tag files in the collection
1541 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1542 if (!res) {
1543 msg += " using_tags: No (unknown)";
23329835 1544 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1545 return;
1546 }
1547 const char* typeStr = res->GetKey(0, "origLFN");
1548 if (!typeStr || !strlen(typeStr)) {
1549 msg += " using_tags: No (unknown)";
23329835 1550 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1551 return;
1552 }
1553 TString file = typeStr;
a2f5fc01 1554 useTags = file.Contains(".tag");
1555 if (useTags) msg += " using_tags: Yes";
c57f56b7 1556 else msg += " using_tags: No";
23329835 1557 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1558 return;
1559 }
1560 TString slfn(lfn);
1561 slfn.ToLower();
a2f5fc01 1562 isXml = slfn.Contains(".xml");
1563 if (isXml) {
c57f56b7 1564 // Open xml collection and check if there are tag files inside
1565 msg += " type: xml_collection;";
1566 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1567 if (!coll) {
1568 msg += " using_tags: No (unknown)";
23329835 1569 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1570 return;
1571 }
1572 TMap *map = coll->Next();
1573 if (!map) {
1574 msg += " using_tags: No (unknown)";
23329835 1575 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1576 return;
1577 }
1578 map = (TMap*)map->GetValue("");
1579 TString file;
1580 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
a2f5fc01 1581 useTags = file.Contains(".tag");
c57f56b7 1582 delete coll;
a2f5fc01 1583 if (useTags) msg += " using_tags: Yes";
c57f56b7 1584 else msg += " using_tags: No";
23329835 1585 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1586 return;
1587 }
a2f5fc01 1588 useTags = slfn.Contains(".tag");
c57f56b7 1589 if (slfn.Contains(".root")) msg += " type: root file;";
f866cba5 1590 else msg += " type: unknown file;";
a2f5fc01 1591 if (useTags) msg += " using_tags: Yes";
c57f56b7 1592 else msg += " using_tags: No";
23329835 1593 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1594}
1595
4e5c5506 1596//______________________________________________________________________________
1597void AliAnalysisAlien::EnablePackage(const char *package)
1598{
1599// Enables a par file supposed to exist in the current directory.
1600 TString pkg(package);
1601 pkg.ReplaceAll(".par", "");
1602 pkg += ".par";
1603 if (gSystem->AccessPathName(pkg)) {
ebcdf05e 1604 Fatal("EnablePackage", "Package %s not found", pkg.Data());
4e5c5506 1605 return;
1606 }
1607 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1608 Info("EnablePackage", "AliEn plugin will use .par packages");
1609 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1610 if (!fPackages) {
1611 fPackages = new TObjArray();
1612 fPackages->SetOwner();
1613 }
1614 fPackages->Add(new TObjString(pkg));
1615}
1616
3bdcb562 1617//______________________________________________________________________________
1618TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1619{
1620// Make a tree from files having the location specified in fFileForTestMode.
1621// Inspired from JF's CreateESDChain.
1622 if (fFileForTestMode.IsNull()) {
1623 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1624 return NULL;
1625 }
1626 if (gSystem->AccessPathName(fFileForTestMode)) {
1627 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1628 return NULL;
1629 }
1630 // Open the file
1631 ifstream in;
1632 in.open(fFileForTestMode);
1633 Int_t count = 0;
1634 // Read the input list of files and add them to the chain
1635 TString line;
1636 TChain *chain = new TChain(treeName);
1637 while (in.good())
1638 {
1639 in >> line;
1640 if (line.IsNull()) continue;
1641 if (count++ == fNtestFiles) break;
1642 TString esdFile(line);
1643 TFile *file = TFile::Open(esdFile);
1644 if (file) {
1645 if (!file->IsZombie()) chain->Add(esdFile);
1646 file->Close();
1647 } else {
1648 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1649 }
1650 }
1651 in.close();
1652 if (!chain->GetListOfFiles()->GetEntries()) {
1653 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1654 delete chain;
1655 return NULL;
1656 }
1657// chain->ls();
1658 return chain;
1659}
1660
d2a409b2 1661//______________________________________________________________________________
1662const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1663{
1664// Get job status for all jobs with jobid>jobidstart.
1665 static char mstatus[20];
1666 mstatus[0] = '\0';
1667 nrunning = 0;
1668 nwaiting = 0;
1669 nerror = 0;
1670 ndone = 0;
1671 TGridJobStatusList *list = gGrid->Ps("");
1672 if (!list) return mstatus;
1673 Int_t nentries = list->GetSize();
1674 TGridJobStatus *status;
1675 Int_t pid;
1676 for (Int_t ijob=0; ijob<nentries; ijob++) {
1677 status = (TGridJobStatus *)list->At(ijob);
8ddad121 1678 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
d2a409b2 1679 if (pid<jobidstart) continue;
1680 if (pid == lastid) {
8ddad121 1681 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
d2a409b2 1682 }
1683 switch (status->GetStatus()) {
1684 case TGridJobStatus::kWAITING:
1685 nwaiting++; break;
1686 case TGridJobStatus::kRUNNING:
1687 nrunning++; break;
1688 case TGridJobStatus::kABORTED:
1689 case TGridJobStatus::kFAIL:
1690 case TGridJobStatus::kUNKNOWN:
1691 nerror++; break;
1692 case TGridJobStatus::kDONE:
1693 ndone++;
1694 }
1695 }
1696 list->Delete();
1697 delete list;
1698 return mstatus;
1699}
1700
c57f56b7 1701//______________________________________________________________________________
1702Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1703{
1704// Returns true if file is a collection. Functionality duplicated from
1705// TAlien::Type() because we don't want to directly depend on TAlien.
1706 if (!gGrid) {
1707 Error("IsCollection", "No connection to grid");
1708 return kFALSE;
1709 }
1710 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1711 if (!res) return kFALSE;
1712 const char* typeStr = res->GetKey(0, "type");
1713 if (!typeStr || !strlen(typeStr)) return kFALSE;
1714 if (!strcmp(typeStr, "collection")) return kTRUE;
1715 delete res;
1716 return kFALSE;
1717}
1718
fe2d7fc2 1719//______________________________________________________________________________
1720Bool_t AliAnalysisAlien::IsSingleOutput() const
1721{
1722// Check if single-ouput option is on.
1723 return (!fOutputSingle.IsNull());
1724}
1725
16a4353c 1726//______________________________________________________________________________
1727void AliAnalysisAlien::Print(Option_t *) const
1728{
1729// Print current plugin settings.
84fcd93f 1730 printf("### AliEn analysis plugin current settings ###\n");
d3b18c4c 1731 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1732 if (mgr && mgr->IsProofMode()) {
1733 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1734 if (TestBit(AliAnalysisGrid::kTest))
1735 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1736 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1737 if (!fProofDataSet.IsNull())
1738 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1739 if (fProofReset==1)
1740 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1741 if (fProofReset>1)
1742 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1743 if (!fRootVersionForProof.IsNull())
1744 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1745 else
1746 printf("= ROOT version requested________________________ default\n");
1747 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1748 if (!fAliRootMode.IsNull())
1749 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1750 if (fNproofWorkers)
1751 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1752 if (fNproofWorkersPerSlave)
1753 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1754 if (TestSpecialBit(kClearPackages))
1755 printf("= ClearPackages requested...\n");
1756 if (fIncludePath.Data())
1757 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1758 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1759 if (fPackages && fPackages->GetEntries()) {
1760 TIter next(fPackages);
1761 TObject *obj;
1762 TString list;
1763 while ((obj=next())) list += obj->GetName();
1764 printf("= Par files to be used: ________________________ %s\n", list.Data());
1765 }
1766 if (TestSpecialBit(kProofConnectGrid))
1767 printf("= Requested PROOF connection to grid\n");
1768 return;
1769 }
e1c22e21 1770 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1771 if (fOverwriteMode) {
1772 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1773 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1774 }
348be253 1775 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1776 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
84fcd93f 1777 printf("= Production mode:______________________________ %d\n", fProductionMode);
1778 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1779 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1780 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
16a4353c 1781 if (fUser.Length())
84fcd93f 1782 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1783 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1784 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1785 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1786 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1787 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
16a4353c 1788 if (fRunNumbers.Length())
84fcd93f 1789 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
16a4353c 1790 if (fRunRange[0])
74013535 1791 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
16a4353c 1792 if (!fRunRange[0] && !fRunNumbers.Length()) {
1793 TIter next(fInputFiles);
1794 TObject *obj;
1795 TString list;
1796 while ((obj=next())) list += obj->GetName();
84fcd93f 1797 printf("= Input files to be processed: _________________ %s\n", list.Data());
16a4353c 1798 }
1799 if (TestBit(AliAnalysisGrid::kTest))
84fcd93f 1800 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1801 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1802 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1803 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
d3b18c4c 1804 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
84fcd93f 1805 printf("=====================================================================\n");
1806 printf("= Job price: ___________________________________ %d\n", fPrice);
1807 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1808 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
16a4353c 1809 if (fMaxInitFailed>0)
84fcd93f 1810 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
16a4353c 1811 if (fMasterResubmitThreshold>0)
84fcd93f 1812 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
149d288c 1813 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
319593fb 1814 if (fNrunsPerMaster>0)
84fcd93f 1815 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1816 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
b5b9dee8 1817 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1818 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
16a4353c 1819 if (fArguments.Length())
84fcd93f 1820 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
631c0b05 1821 if (fExecutableArgs.Length())
1822 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
84fcd93f 1823 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1824 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1825 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1826 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
16a4353c 1827 if (fDatasetName)
84fcd93f 1828 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1829 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
16a4353c 1830 if (fIncludePath.Data())
84fcd93f 1831 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
16a4353c 1832 if (fCloseSE.Length())
84fcd93f 1833 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
16a4353c 1834 if (fFriendChainName.Length())
84fcd93f 1835 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
d3b18c4c 1836 if (fPackages && fPackages->GetEntries()) {
16a4353c 1837 TIter next(fPackages);
1838 TObject *obj;
1839 TString list;
1840 while ((obj=next())) list += obj->GetName();
84fcd93f 1841 printf("= Par files to be used: ________________________ %s\n", list.Data());
16a4353c 1842 }
1843}
1844
c57f56b7 1845//______________________________________________________________________________
1846void AliAnalysisAlien::SetDefaults()
1847{
1848// Set default values for everything. What cannot be filled will be left empty.
1849 if (fGridJDL) delete fGridJDL;
1850 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 1851 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
c57f56b7 1852 fPrice = 1;
1853 fTTL = 30000;
1854 fSplitMaxInputFileNumber = 100;
1855 fMaxInitFailed = 0;
1856 fMasterResubmitThreshold = 0;
bb885a9e 1857 fNtestFiles = 10;
149d288c 1858 fNreplicas = 2;
a8739e8a 1859 fRunRange[0] = 0;
1860 fRunRange[1] = 0;
8e3bd06a 1861 fRunPrefix = "%d";
319593fb 1862 fNrunsPerMaster = 1;
16a4353c 1863 fMaxMergeFiles = 100;
c57f56b7 1864 fRunNumbers = "";
1865 fExecutable = "analysis.sh";
0a1c1f7f 1866 fExecutableCommand = "root -b -q";
c57f56b7 1867 fArguments = "";
631c0b05 1868 fExecutableArgs = "";
c57f56b7 1869 fAnalysisMacro = "myAnalysis.C";
1870 fAnalysisSource = "";
1871 fAdditionalLibs = "";
1872 fSplitMode = "se";
1873 fAPIVersion = "";
1874 fROOTVersion = "";
1875 fAliROOTVersion = "";
1876 fUser = ""; // Your alien user name
1877 fGridWorkingDir = "";
1878 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1879 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
0df6ccf2 1880 fFriendChainName = "";
c57f56b7 1881 fGridOutputDir = "output";
b83f84f0 1882 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
c57f56b7 1883 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1884 fInputFormat = "xml-single";
1885 fJDLName = "analysis.jdl";
c6cb3634 1886 fJobTag = "Automatically generated analysis JDL";
bb885a9e 1887 fMergeExcludes = "";
0f389141 1888 fMergeViaJDL = 0;
348be253 1889 SetUseCopy(kTRUE);
1890 SetCheckCopy(kTRUE);
149d288c 1891 SetDefaultOutputs(kTRUE);
e1c22e21 1892 fOverwriteMode = 1;
c57f56b7 1893}
1894
0f389141 1895//______________________________________________________________________________
b3e07543 1896Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
0f389141 1897{
b3e07543 1898// Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1899 // First check if the result is already in the output directory.
1900 if (FileExists(Form("%s/%s",aliendir,filename))) {
1901 printf("Final merged results found. Not merging again.\n");
7c2cd90a 1902 return kFALSE;
1903 }
b3e07543 1904 // Now check the last stage done.
1905 Int_t stage = 0;
1906 while (1) {
1907 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1908 stage++;
1909 }
1910 // Next stage of merging
1911 stage++;
1912 TString pattern = "*root_archive.zip";
1913 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1914 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1915 if (res) delete res;
1916 // Write standard output to file
1917 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1918 // Count the number of files inside
1919 ifstream ifile;
1920 ifile.open(Form("Stage_%d.xml",stage));
1921 if (!ifile.good()) {
1922 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
7c2cd90a 1923 return kFALSE;
b3e07543 1924 }
1925 TString line;
1926 Int_t nfiles = 0;
1927 while (!ifile.eof()) {
1928 ifile >> line;
1929 if (line.Contains("/event")) nfiles++;
7c2cd90a 1930 }
b3e07543 1931 ifile.close();
1932 if (!nfiles) {
1933 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1934 return kFALSE;
1935 } else {
1936 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
7ae54d70 1937 }
b3e07543 1938 // Copy the file in the output directory
1939 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1940 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1941 // Check if this is the last stage to be done.
1942 Bool_t laststage = (nfiles<nperchunk);
1943 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1944 if (laststage) {
1945 printf("### Submiting final merging stage %d\n", stage);
1946 TString finalJDL = jdl;
1947 finalJDL.ReplaceAll(".jdl", "_final.jdl");
03335324 1948 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
b3e07543 1949 Int_t jobId = SubmitSingleJob(query);
1950 if (!jobId) return kFALSE;
1951 } else {
1952 printf("### Submiting merging stage %d\n", stage);
03335324 1953 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
b3e07543 1954 Int_t jobId = SubmitSingleJob(query);
1955 if (!jobId) return kFALSE;
7c2cd90a 1956 }
b3e07543 1957 return kTRUE;
1958}
7c2cd90a 1959
1960//______________________________________________________________________________
1961Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1962{
1963// Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1964 if (!gGrid) return 0;
1965 printf("=> %s ------> ",query);
1966 TGridResult *res = gGrid->Command(query);
1967 if (!res) return 0;
1968 TString jobId = res->GetKey(0,"jobId");
1969 delete res;
1970 if (jobId.IsNull()) {
1971 printf("submission failed. Reason:\n");
1972 gGrid->Stdout();
1973 gGrid->Stderr();
1974 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
1975 return 0;
1976 }
1977 printf(" Job id: %s\n", jobId.Data());
1978 return atoi(jobId);
1979}
1980
1981//______________________________________________________________________________
b3e07543 1982Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
7c2cd90a 1983{
b3e07543 1984// Merge given output files from basedir. Basedir can be an alien output directory
1985// but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
1986// files in a group (ignored for xml input). Merging can be done in stages:
1987// stage=0 : will merge all existing files in a single stage, supporting resume if run locally
1988// stage=1 : works with an xml of all root_archive.zip in the output directory
1989// stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
a2f5fc01 1990 TString outputFile = output;
0f389141 1991 TString command;
a2f5fc01 1992 TString outputChunk;
1993 TString previousChunk = "";
b3e07543 1994 TObjArray *listoffiles = new TObjArray();
1995// listoffiles->SetOwner();
a2f5fc01 1996 Int_t countChunk = 0;
1997 Int_t countZero = nmaxmerge;
0f389141 1998 Bool_t merged = kTRUE;
a2f5fc01 1999 Int_t index = outputFile.Index("@");
2000 if (index > 0) outputFile.Remove(index);
7c2cd90a 2001 TString inputFile = outputFile;
b3e07543 2002 TString sbasedir = basedir;
2003 if (sbasedir.Contains(".xml")) {
2004 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2005 nmaxmerge = 9999999;
2006 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2007 if (!coll) {
2008 ::Error("MergeOutput", "Input XML collection empty.");
2009 return kFALSE;
2010 }
2011 // Iterate grid collection
2012 while (coll->Next()) {
2013 TString fname = gSystem->DirName(coll->GetTURL());
2014 fname += "/";
2015 fname += inputFile;
2016 listoffiles->Add(new TNamed(fname.Data(),""));
2017 }
2018 } else {
2019 command = Form("find %s/ *%s", basedir, inputFile.Data());
2020 printf("command: %s\n", command.Data());
2021 TGridResult *res = gGrid->Command(command);
2022 if (!res) {
2023 ::Error("MergeOutput","No result for the find command\n");
2024 delete listoffiles;
2025 return kFALSE;
2026 }
2027 TIter nextmap(res);
2028 TMap *map = 0;
2029 while ((map=(TMap*)nextmap())) {
2030 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2031 if (!objs || !objs->GetString().Length()) {
2032 // Nothing found - skip this output
2033 delete res;
2034 delete listoffiles;
2035 return kFALSE;
2036 }
2037 listoffiles->Add(new TNamed(objs->GetName(),""));
2038 }
2039 delete res;
2040 }
2041 if (!listoffiles->GetEntries()) {
7c2cd90a 2042 ::Error("MergeOutput","No result for the find command\n");
b3e07543 2043 delete listoffiles;
0f389141 2044 return kFALSE;
2045 }
2046
2047 TFileMerger *fm = 0;
b3e07543 2048 TIter next0(listoffiles);
2049 TObjArray *listoffilestmp = new TObjArray();
2050 listoffilestmp->SetOwner();
2051 TObject *nextfile;
2052 TString snextfile;
2053 // Keep only the files at upper level
2054 Int_t countChar = 0;
2055 while ((nextfile=next0())) {
2056 snextfile = nextfile->GetName();
2057 Int_t crtCount = snextfile.CountChar('/');
2058 if (nextfile == listoffiles->First()) countChar = crtCount;
2059 if (crtCount < countChar) countChar = crtCount;
2060 }
2061 next0.Reset();
2062 while ((nextfile=next0())) {
2063 snextfile = nextfile->GetName();
2064 Int_t crtCount = snextfile.CountChar('/');
2065 if (crtCount > countChar) {
2066 delete nextfile;
2067 continue;
2068 }
2069 listoffilestmp->Add(nextfile);
2070 }
2071 delete listoffiles;
2072 listoffiles = listoffilestmp; // Now contains 'good' files
2073 listoffiles->Print();
2074 TIter next(listoffiles);
7c2cd90a 2075 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
a2f5fc01 2076 outputChunk = outputFile;
2077 outputChunk.ReplaceAll(".root", "_*.root");
0f389141 2078 // Check for existent temporary merge files
e1c22e21 2079 // Check overwrite mode and remove previous partial results if needed
7c2cd90a 2080 // Preserve old merging functionality for stage 0.
2081 if (stage==0) {
2082 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2083 while (1) {
2084 // Skip as many input files as in a chunk
2ea55496 2085 for (Int_t counter=0; counter<nmaxmerge; counter++) {
b3e07543 2086 nextfile = next();
2087 if (!nextfile) {
2ea55496 2088 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
b3e07543 2089 delete listoffiles;
2ea55496 2090 return kFALSE;
2091 }
b3e07543 2092 snextfile = nextfile->GetName();
7c2cd90a 2093 }
2094 outputChunk = outputFile;
2095 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2096 countChunk++;
2097 if (gSystem->AccessPathName(outputChunk)) continue;
2098 // Merged file with chunks up to <countChunk> found
2099 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2100 previousChunk = outputChunk;
2101 break;
2102 }
2103 }
2104 countZero = nmaxmerge;
2105
b3e07543 2106 while ((nextfile=next())) {
2107 snextfile = nextfile->GetName();
2ea55496 2108 // Loop 'find' results and get next LFN
7c2cd90a 2109 if (countZero == nmaxmerge) {
2110 // First file in chunk - create file merger and add previous chunk if any.
2111 fm = new TFileMerger(kFALSE);
2112 fm->SetFastMethod(kTRUE);
2113 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2114 outputChunk = outputFile;
2115 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2116 }
2117 // If last file found, put merged results in the output file
b3e07543 2118 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
7c2cd90a 2119 // Add file to be merged and decrement chunk counter.
b3e07543 2120 fm->AddFile(snextfile);
7c2cd90a 2121 countZero--;
b3e07543 2122 if (countZero==0 || nextfile == listoffiles->Last()) {
7c2cd90a 2123 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2124 // Nothing found - skip this output
2125 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
b3e07543 2126 merged = kFALSE;
2127 break;
7c2cd90a 2128 }
2129 fm->OutputFile(outputChunk);
2130 // Merge the outputs, then go to next chunk
2131 if (!fm->Merge()) {
2132 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
b3e07543 2133 merged = kFALSE;
2134 break;
7c2cd90a 2135 } else {
2136 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2137 gSystem->Unlink(previousChunk);
2138 }
b3e07543 2139 if (nextfile == listoffiles->Last()) break;
7c2cd90a 2140 countChunk++;
2141 countZero = nmaxmerge;
2142 previousChunk = outputChunk;
0f389141 2143 }
0f389141 2144 }
b3e07543 2145 delete listoffiles;
2146 delete fm;
7c2cd90a 2147 return merged;
2148 }
2149 // Merging stage different than 0.
2150 // Move to the begining of the requested chunk.
7c2cd90a 2151 fm = new TFileMerger(kFALSE);
2152 fm->SetFastMethod(kTRUE);
b3e07543 2153 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2154 delete listoffiles;
7c2cd90a 2155 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2156 // Nothing found - skip this output
2157 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2158 delete fm;
2159 return kFALSE;
2160 }
b3e07543 2161 fm->OutputFile(outputFile);
7c2cd90a 2162 // Merge the outputs
2163 if (!fm->Merge()) {
2164 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2165 delete fm;
2166 return kFALSE;
2167 } else {
b3e07543 2168 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
0f389141 2169 }
7c2cd90a 2170 delete fm;
2171 return kTRUE;
0f389141 2172}
2173
c57f56b7 2174//______________________________________________________________________________
2175Bool_t AliAnalysisAlien::MergeOutputs()
2176{
2177// Merge analysis outputs existing in the AliEn space.
2178 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2179 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2180 if (!Connect()) {
2181 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2182 return kFALSE;
0f389141 2183 }
c9e8f7fd 2184 if (fMergeViaJDL) {
2185 if (!TestBit(AliAnalysisGrid::kMerge)) {
2186 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2187 return kFALSE;
2188 }
2189 if (fProductionMode) {
2190 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2191 return kFALSE;
2192 }
0f389141 2193 Info("MergeOutputs", "Submitting merging JDL");
a03be957 2194 if (!SubmitMerging()) return kFALSE;
0f389141 2195 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
c9e8f7fd 2196 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
001cb79e 2197 return kFALSE;
c57f56b7 2198 }
2199 // Get the output path
d2a409b2 2200 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
923e2ca5 2201 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 2202 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2203 return kFALSE;
2204 }
2205 if (!fOutputFiles.Length()) {
2206 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2207 return kFALSE;
0f389141 2208 }
2209 // Check if fast read option was requested
e1c22e21 2210 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2211 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
0f389141 2212 if (fFastReadOption) {
d3339be3 2213 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2214 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
b3e07543 2215 gEnv->SetValue("XNet.ConnectTimeout",50);
2216 gEnv->SetValue("XNet.RequestTimeout",50);
0f389141 2217 gEnv->SetValue("XNet.MaxRedirectCount",2);
b3e07543 2218 gEnv->SetValue("XNet.ReconnectTimeout",50);
0f389141 2219 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
c57f56b7 2220 }
e8b839ab 2221 // Make sure we change the temporary directory
2222 gSystem->Setenv("TMPDIR", gSystem->pwd());
149d288c 2223 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2224 TIter next(list);
2225 TObjString *str;
a2f5fc01 2226 TString outputFile;
c57f56b7 2227 Bool_t merged = kTRUE;
2228 while((str=(TObjString*)next())) {
a2f5fc01 2229 outputFile = str->GetString();
2230 Int_t index = outputFile.Index("@");
2231 if (index > 0) outputFile.Remove(index);
2232 TString outputChunk = outputFile;
2233 outputChunk.ReplaceAll(".root", "_*.root");
319593fb 2234 // Skip already merged outputs
a2f5fc01 2235 if (!gSystem->AccessPathName(outputFile)) {
e1c22e21 2236 if (fOverwriteMode) {
a2f5fc01 2237 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2238 gSystem->Unlink(outputFile);
2239 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2240 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2241 outputChunk.Data());
2242 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2243 }
2244 } else {
a2f5fc01 2245 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
e1c22e21 2246 continue;
2247 }
2248 } else {
a2f5fc01 2249 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2250 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2251 outputChunk.Data());
2252 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2253 }
2254 }
bb885a9e 2255 if (fMergeExcludes.Length() &&
a2f5fc01 2256 fMergeExcludes.Contains(outputFile.Data())) continue;
16a4353c 2257 // Perform a 'find' command in the output directory, looking for registered outputs
a2f5fc01 2258 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
0f389141 2259 if (!merged) {
2260 Error("MergeOutputs", "Terminate() will NOT be executed");
2261 return kFALSE;
ff07ec61 2262 }
2263 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2264 if (fileOpened) fileOpened->Close();
c57f56b7 2265 }
0f389141 2266 return kTRUE;
c57f56b7 2267}
2268
bb885a9e 2269//______________________________________________________________________________
2270void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2271{
2272// Use the output files connected to output containers from the analysis manager
2273// rather than the files defined by SetOutputFiles
2274 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
205b201f 2275 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
bb885a9e 2276 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2277}
2278
149d288c 2279//______________________________________________________________________________
2280void AliAnalysisAlien::SetOutputFiles(const char *list)
2281{
2282// Manually set the output files list.
2283// Removes duplicates. Not allowed if default outputs are not disabled.
2284 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2285 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2286 return;
2287 }
2288 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2289 fOutputFiles = "";
2290 TString slist = list;
2291 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2292 TObjArray *arr = slist.Tokenize(" ");
2293 TObjString *os;
2294 TIter next(arr);
2295 TString sout;
2296 while ((os=(TObjString*)next())) {
2297 sout = os->GetString();
2298 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2299 if (fOutputFiles.Contains(sout)) continue;
2300 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2301 fOutputFiles += sout;
2302 }
2303 delete arr;
f790bc1b 2304}
149d288c 2305
2306//______________________________________________________________________________
2307void AliAnalysisAlien::SetOutputArchive(const char *list)
2308{
2309// Manually set the output archive list. Free text - you are on your own...
2310// Not allowed if default outputs are not disabled.
2311 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2312 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2313 return;
2314 }
2315 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2316 fOutputArchive = list;
2317}
2318
2319//______________________________________________________________________________
2320void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2321{
2322// Setting a prefered output SE is not allowed anymore.
2323 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2324}
2325
5513444a 2326//______________________________________________________________________________
2327Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
c57f56b7 2328{
2329// Start remote grid analysis.
3bdcb562 2330 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2331 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2332 if (!mgr || !mgr->IsInitialized()) {
2333 Error("StartAnalysis", "You need an initialized analysis manager for this");
2334 return kFALSE;
2335 }
2336 // Are we in PROOF mode ?
2337 if (mgr->IsProofMode()) {
90d50a8c 2338 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3bdcb562 2339 if (fProofCluster.IsNull()) {
2340 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2341 return kFALSE;
2342 }
2343 if (fProofDataSet.IsNull() && !testMode) {
2344 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2345 return kFALSE;
2346 }
2347 // Set the needed environment
2348 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2349 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2350 if (fProofReset && !testMode) {
2351 if (fProofReset==1) {
2352 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2353 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2354 } else {
2355 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2356 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2357 }
2358 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2359 return kFALSE;
2360 }
2361 // Do we need to change the ROOT version ? The success of this cannot be checked.
2362 if (!fRootVersionForProof.IsNull() && !testMode) {
2363 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2364 fProofCluster.Data(), fRootVersionForProof.Data()));
2365 }
2366 // Connect to PROOF and check the status
2367 Long_t proof = 0;
27734f0e 2368 TString sworkers;
2369 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2370 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3bdcb562 2371 if (!testMode) {
27734f0e 2372 if (!sworkers.IsNull())
2373 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3bdcb562 2374 else
2375 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2376 } else {
2377 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2378 if (!proof) {
2379 Error("StartAnalysis", "Could not start PROOF in test mode");
2380 return kFALSE;
2381 }
2382 }
2383 if (!proof) {
2384 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2385 return kFALSE;
2386 }
27734f0e 2387 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2388 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
3bdcb562 2389 // Is dataset existing ?
2390 if (!testMode) {
2391 TString dataset = fProofDataSet;
2392 Int_t index = dataset.Index("#");
2393 if (index>=0) dataset.Remove(index);
830acc4c 2394// if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2395// Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2396// return kFALSE;
2397// }
2398// Info("StartAnalysis", "Dataset %s found", dataset.Data());
3bdcb562 2399 }
2400 // Is ClearPackages() needed ?
2401 if (TestSpecialBit(kClearPackages)) {
2402 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2403 gROOT->ProcessLine("gProof->ClearPackages();");
2404 }
2405 // Is a given aliroot mode requested ?
2406 TList optionsList;
1ac846e9 2407 TString parLibs;
830acc4c 2408 if (!fAliRootMode.IsNull()) {
3bdcb562 2409 TString alirootMode = fAliRootMode;
2410 if (alirootMode == "default") alirootMode = "";
2411 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2412 optionsList.SetOwner();
2413 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2414 // Check the additional libs to be loaded
2415 TString extraLibs;
1ac846e9 2416 Bool_t parMode = kFALSE;
3bdcb562 2417 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2418 // Parse the extra libs for .so
2419 if (fAdditionalLibs.Length()) {
2420 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2421 TIter next(list);
2422 TObjString *str;
1ac846e9 2423 while((str=(TObjString*)next())) {
2424 if (str->GetString().Contains(".so")) {
2425 if (parMode) {
2426 Warning("StartAnalysis", "Plugin does not support loading libs after par files in PROOF mode. Library %s and following will not load on workers", str->GetName());
2427 break;
2428 }
2429 TString stmp = str->GetName();
2430 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2431 stmp.ReplaceAll(".so","");
2432 if (!extraLibs.IsNull()) extraLibs += ":";
2433 extraLibs += stmp;
2434 continue;
2435 }
2436 if (str->GetString().Contains(".par")) {
2437 // The first par file found in the list will not allow any further .so
2438 parMode = kTRUE;
2439 if (!parLibs.IsNull()) parLibs += ":";
2440 parLibs += str->GetName();
2441 continue;
2442 }
3bdcb562 2443 }
2444 if (list) delete list;
2445 }
2446 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
830acc4c 2447 // Check extra includes
2448 if (!fIncludePath.IsNull()) {
2449 TString includePath = fIncludePath;
2450 includePath.ReplaceAll(" ",":");
8ddad121 2451 includePath.ReplaceAll("$ALICE_ROOT","");
2452 includePath.ReplaceAll("${ALICE_ROOT}","");
2453 includePath.ReplaceAll("-I","");
830acc4c 2454 includePath.Strip(TString::kTrailing, ':');
2455 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2456 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2457 }
27734f0e 2458 // Check if connection to grid is requested
2459 if (TestSpecialBit(kProofConnectGrid))
2460 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
830acc4c 2461 // Enable AliRoot par
2462 if (testMode) {
2463 // Enable proof lite package
2464 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2465 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2466 TNamed *obj = (TNamed*)optionsList.At(i);
2467 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2468 }
2469 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
8ddad121 2470 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
830acc4c 2471 Info("StartAnalysis", "AliRootProofLite enabled");
2472 } else {
2473 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2474 return kFALSE;
2475 }
2476 } else {
8ddad121 2477 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2478 fAliROOTVersion.Data(), &optionsList))) {
830acc4c 2479 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2480 return kFALSE;
2481 }
27734f0e 2482 }
1ac846e9 2483 // Enable first par files from fAdditionalLibs
2484 if (!parLibs.IsNull()) {
2485 TObjArray *list = parLibs.Tokenize(":");
2486 TIter next(list);
2487 TObjString *package;
2488 while((package=(TObjString*)next())) {
40501bb7 2489 TString spkg = package->GetName();
2490 spkg.ReplaceAll(".par", "");
2491 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
b50a41c3 2492 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
4f136f18 2493 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2494 if (gROOT->ProcessLine(enablePackage)) {
1ac846e9 2495 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2496 return kFALSE;
2497 }
2498 } else {
2499 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2500 return kFALSE;
2501 }
2502 }
2503 if (list) delete list;
2504 }
3bdcb562 2505 } else {
2506 if (fAdditionalLibs.Contains(".so") && !testMode) {
2507 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2508 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2509 return kFALSE;
2510 }
2511 }
2512 // Enable par files if requested
2513 if (fPackages && fPackages->GetEntries()) {
2514 TIter next(fPackages);
2515 TObject *package;
2516 while ((package=next())) {
1ac846e9 2517 // Skip packages already enabled
2518 if (parLibs.Contains(package->GetName())) continue;
40501bb7 2519 TString spkg = package->GetName();
2520 spkg.ReplaceAll(".par", "");
2521 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
3bdcb562 2522 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
27734f0e 2523 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3bdcb562 2524 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2525 return kFALSE;
2526 }
2527 } else {
2528 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2529 return kFALSE;
2530 }
2531 }
2532 }
2533 // Do we need to load analysis source files ?
2534 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2535 if (fAnalysisSource.Length()) {
2536 TObjArray *list = fAnalysisSource.Tokenize(" ");
2537 TIter next(list);
2538 TObjString *str;
2539 while((str=(TObjString*)next())) {
2540 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2541 }
2542 if (list) delete list;
2543 }
830acc4c 2544 if (testMode) {
2545 // Register dataset to proof lite.
2546 if (fFileForTestMode.IsNull()) {
2547 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2548 return kFALSE;
2549 }
2550 if (gSystem->AccessPathName(fFileForTestMode)) {
2551 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2552 return kFALSE;
2553 }
2554 TFileCollection *coll = new TFileCollection();
2555 coll->AddFromFile(fFileForTestMode);
8ddad121 2556 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
27734f0e 2557 gROOT->ProcessLine("gProof->ShowDataSets()");
830acc4c 2558 }
3bdcb562 2559 return kTRUE;
2560 }
c57f56b7 2561
43da816a 2562 // Check if output files have to be taken from the analysis manager
2563 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
f790bc1b 2564 // Add output files and AOD files
2565 fOutputFiles = GetListOfFiles("outaod");
c07b9ce2 2566 // Add extra files registered to the analysis manager
f790bc1b 2567 TString extra = GetListOfFiles("ext");
2568 if (!extra.IsNull()) {
149d288c 2569 extra.ReplaceAll(".root", "*.root");
f790bc1b 2570 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
149d288c 2571 fOutputFiles += extra;
84fcd93f 2572 }
149d288c 2573 // Compose the output archive.
b83f84f0 2574 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2575 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
43da816a 2576 }
f7b1cbc2 2577// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
c57f56b7 2578 if (TestBit(AliAnalysisGrid::kOffline)) {
2579 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2580 \n there nor any job run. You can revise the JDL and analysis \
2581 \n macro then run the same in \"submit\" mode.");
2582 } else if (TestBit(AliAnalysisGrid::kTest)) {
2583 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2584 \n dataset.");
2585 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2586 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2587 \n space and job submitted.");
2588 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2589 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
0f389141 2590 if (fMergeViaJDL) CheckInputData();
5513444a 2591 return kTRUE;
c57f56b7 2592 } else {
2593 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2594 }
2595
348be253 2596 Print();
c57f56b7 2597 if (!Connect()) {
2598 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
5513444a 2599 return kFALSE;
16a4353c 2600 }
d3b18c4c 2601 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
c57f56b7 2602 if (!CheckInputData()) {
2603 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
5513444a 2604 return kFALSE;
c57f56b7 2605 }
d3339be3 2606 if (!CreateDataset(fDataPattern)) {
2607 TString serror;
2608 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2609 if (fRunNumbers.Length()) serror = "run numbers";
2610 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2611 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2612 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2613 return kFALSE;
2614 }
c57f56b7 2615 WriteAnalysisFile();
2616 WriteAnalysisMacro();
2617 WriteExecutable();
2618 WriteValidationScript();
0f389141 2619 if (fMergeViaJDL) {
2620 WriteMergingMacro();
2621 WriteMergeExecutable();
2622 WriteValidationScript(kTRUE);
2623 }
5513444a 2624 if (!CreateJDL()) return kFALSE;
2625 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3bdcb562 2626 if (testMode) {
c57f56b7 2627 // Locally testing the analysis
2628 Info("StartAnalysis", "\n_______________________________________________________________________ \
2629 \n Running analysis script in a daughter shell as on a worker node \
2630 \n_______________________________________________________________________");
149d288c 2631 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2632 TIter next(list);
2633 TObjString *str;
a2f5fc01 2634 TString outputFile;
c57f56b7 2635 while((str=(TObjString*)next())) {
a2f5fc01 2636 outputFile = str->GetString();
2637 Int_t index = outputFile.Index("@");
2638 if (index > 0) outputFile.Remove(index);
2639 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
c57f56b7 2640 }
2641 delete list;
2642 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
f50e4bc8 2643 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
c57f56b7 2644// gSystem->Exec("cat stdout");
5513444a 2645 return kFALSE;
c57f56b7 2646 }
5513444a 2647 // Check if submitting is managed by LPM manager
a3e84053 2648 if (fProductionMode) {
5513444a 2649 TString prodfile = fJDLName;
2650 prodfile.ReplaceAll(".jdl", ".prod");
2651 WriteProductionFile(prodfile);
2652 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2653 return kFALSE;
2654 }
a8739e8a 2655 // Submit AliEn job(s)
d2a409b2 2656 gGrid->Cd(fGridOutputDir);
a8739e8a 2657 TGridResult *res;
c57f56b7 2658 TString jobID = "";
d2a409b2 2659 if (!fRunNumbers.Length() && !fRunRange[0]) {
dd74a515 2660 // Submit a given xml or a set of runs
a8739e8a 2661 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
84fcd93f 2662 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
a8739e8a 2663 if (res) {
2664 const char *cjobId = res->GetKey(0,"jobId");
2665 if (!cjobId) {
a03be957 2666 gGrid->Stdout();
2667 gGrid->Stderr();
a8739e8a 2668 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
5513444a 2669 return kFALSE;
a8739e8a 2670 } else {
2671 Info("StartAnalysis", "\n_______________________________________________________________________ \
2672 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2673 \n_______________________________________________________________________",
2674 fJDLName.Data(), cjobId);
2675 jobID = cjobId;
2676 }
2677 delete res;
a03be957 2678 } else {
2679 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2680 return kFALSE;
a8739e8a 2681 }
2682 } else {
d2a409b2 2683 // Submit for a range of enumeration of runs.
a03be957 2684 if (!Submit()) return kFALSE;
c57f56b7 2685 }
a8739e8a 2686
c57f56b7 2687 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2688 \n You may exit at any time and terminate the job later using the option <terminate> \
2689 \n ##################################################################################", jobID.Data());
bb885a9e 2690 gSystem->Exec("aliensh");
5513444a 2691 return kTRUE;
c57f56b7 2692}
2693
f790bc1b 2694//______________________________________________________________________________
2695const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2696{
2697// Get a comma-separated list of output files of the requested type.
2698// Type can be (case unsensitive):
2699// aod - list of aod files (std, extensions and filters)
2700// out - list of output files connected to containers (but not aod's or extras)
2701// ext - list of extra files registered to the manager
2702// ter - list of files produced in terminate
2703 static TString files;
2704 files = "";
2705 TString stype = type;
2706 stype.ToLower();
2707 TString aodfiles, extra;
2708 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2709 if (!mgr) {
2710 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2711 return files.Data();
2712 }
2713 if (mgr->GetOutputEventHandler()) {
2714 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2715 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2716 if (!extraaod.IsNull()) {
2717 aodfiles += ",";
2718 aodfiles += extraaod;
2719 }
2720 }
2721 if (stype.Contains("aod")) {
2722 files = aodfiles;
2723 if (stype == "aod") return files.Data();
2724 }
2725 // Add output files that are not in the list of AOD files
2726 TString outputfiles = "";
2727 TIter next(mgr->GetOutputs());
2728 AliAnalysisDataContainer *output;
2729 const char *filename = 0;
2730 while ((output=(AliAnalysisDataContainer*)next())) {
2731 filename = output->GetFileName();
2732 if (!(strcmp(filename, "default"))) continue;
2733 if (outputfiles.Contains(filename)) continue;
2734 if (aodfiles.Contains(filename)) continue;
2735 if (!outputfiles.IsNull()) outputfiles += ",";
2736 outputfiles += filename;
2737 }
2738 if (stype.Contains("out")) {
2739 if (!files.IsNull()) files += ",";
2740 files += outputfiles;
2741 if (stype == "out") return files.Data();
2742 }
2743 // Add extra files registered to the analysis manager
2744 TString sextra;
2745 extra = mgr->GetExtraFiles();
2746 if (!extra.IsNull()) {
2747 extra.Strip();
2748 extra.ReplaceAll(" ", ",");
2749 TObjArray *fextra = extra.Tokenize(",");
2750 TIter nextx(fextra);
2751 TObject *obj;
2752 while ((obj=nextx())) {
2753 if (aodfiles.Contains(obj->GetName())) continue;
2754 if (outputfiles.Contains(obj->GetName())) continue;
2755 if (sextra.Contains(obj->GetName())) continue;
2756 if (!sextra.IsNull()) sextra += ",";
2757 sextra += obj->GetName();
2758 }
2759 delete fextra;
2760 if (stype.Contains("ext")) {
2761 if (!files.IsNull()) files += ",";
2762 files += sextra;
2763 }
2764 }
2765 if (stype == "ext") return files.Data();
2766 TString termfiles;
2767 if (!fTerminateFiles.IsNull()) {
2768 fTerminateFiles.Strip();
2769 fTerminateFiles.ReplaceAll(" ",",");
9c939f2b 2770 TObjArray *fextra = fTerminateFiles.Tokenize(",");
f790bc1b 2771 TIter nextx(fextra);
2772 TObject *obj;
2773 while ((obj=nextx())) {
2774 if (aodfiles.Contains(obj->GetName())) continue;
2775 if (outputfiles.Contains(obj->GetName())) continue;
2776 if (termfiles.Contains(obj->GetName())) continue;
2777 if (sextra.Contains(obj->GetName())) continue;
2778 if (!termfiles.IsNull()) termfiles += ",";
2779 termfiles += obj->GetName();
2780 }
2781 delete fextra;
2782 }
2783 if (stype.Contains("ter")) {
2784 if (!files.IsNull() && !termfiles.IsNull()) {
2785 files += ",";
2786 files += termfiles;
2787 }
2788 }
2789 return files.Data();
2790}
2791
d2a409b2 2792//______________________________________________________________________________
a03be957 2793Bool_t AliAnalysisAlien::Submit()
d2a409b2 2794{
2795// Submit all master jobs.
2796 Int_t nmasterjobs = fInputFiles->GetEntries();
2797 Long_t tshoot = gSystem->Now();
a03be957 2798 if (!fNsubmitted && !SubmitNext()) return kFALSE;
d2a409b2 2799 while (fNsubmitted < nmasterjobs) {
2800 Long_t now = gSystem->Now();
2801 if ((now-tshoot)>30000) {
2802 tshoot = now;
a03be957 2803 if (!SubmitNext()) return kFALSE;
d2a409b2 2804 }
2805 }
a03be957 2806 return kTRUE;
d2a409b2 2807}
2808
0f389141 2809//______________________________________________________________________________
a03be957 2810Bool_t AliAnalysisAlien::SubmitMerging()
0f389141 2811{
2812// Submit all merging jobs.
2813 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2814 gGrid->Cd(fGridOutputDir);
2815 TString mergeJDLName = fExecutable;
2816 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2817 Int_t ntosubmit = fInputFiles->GetEntries();
0f389141 2818 for (Int_t i=0; i<ntosubmit; i++) {
f866cba5 2819 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2820 runOutDir.ReplaceAll(".xml", "");
7c2cd90a 2821 if (fOutputToRunNo) {
2822 // The output directory is the run number
2823 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2824 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2825 } else {
2826 // The output directory is the master number in 3 digits format
2827 printf("### Submitting merging job for master <%03d>\n", i);
2828 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2829 }
2830 // Check now the number of merging stages.
2b222f7c 2831 TObjArray *list = fOutputFiles.Tokenize(",");
2832 TIter next(list);
2833 TObjString *str;
2834 TString outputFile;
2835 while((str=(TObjString*)next())) {
2836 outputFile = str->GetString();
2837 Int_t index = outputFile.Index("@");
2838 if (index > 0) outputFile.Remove(index);
2839 if (!fMergeExcludes.Contains(outputFile)) break;
2840 }
2841 delete list;
b3e07543 2842 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
7c2cd90a 2843 if (!done) return kFALSE;
0f389141 2844 }
a03be957 2845 if (!ntosubmit) return kTRUE;
0f389141 2846 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
2847 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
2848 \n ##################################################################################");
2849 gSystem->Exec("aliensh");
a03be957 2850 return kTRUE;
0f389141 2851}
2852
d2a409b2 2853//______________________________________________________________________________
a03be957 2854Bool_t AliAnalysisAlien::SubmitNext()
d2a409b2 2855{
08d5b699 2856// Submit next bunch of master jobs if the queue is free. The first master job is
2857// submitted right away, while the next will not be unless the previous was split.
2858// The plugin will not submit new master jobs if there are more that 500 jobs in
2859// waiting phase.
d2a409b2 2860 static Bool_t iscalled = kFALSE;
2861 static Int_t firstmaster = 0;
2862 static Int_t lastmaster = 0;
2863 static Int_t npermaster = 0;
a03be957 2864 if (iscalled) return kTRUE;
d2a409b2 2865 iscalled = kTRUE;
2866 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2867 Int_t ntosubmit = 0;
2868 TGridResult *res;
2869 TString jobID = "";
3bdcb562 2870 Int_t nmasterjobs = fInputFiles->GetEntries();
2871 if (!fNsubmitted) {
2872 ntosubmit = 1;
2873 if (!IsUseSubmitPolicy()) {
90d50a8c 2874 if (nmasterjobs>5)
3bdcb562 2875 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2876 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2877 ntosubmit = nmasterjobs;
2878 }
2879 } else {
d2a409b2 2880 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
84fcd93f 2881 printf("=== master %d: %s\n", lastmaster, status.Data());
d2a409b2 2882 // If last master not split, just return
a03be957 2883 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
d2a409b2 2884 // No more than 100 waiting jobs
08d5b699 2885 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
d2a409b2 2886 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
08d5b699 2887 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
7586eedc 2888 if (!ntosubmit) ntosubmit = 1;
84fcd93f 2889 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
d2a409b2 2890 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2891 }
d2a409b2 2892 for (Int_t i=0; i<ntosubmit; i++) {
2893 // Submit for a range of enumeration of runs.
a03be957 2894 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
d2a409b2 2895 TString query;
cd11251e 2896 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2897 runOutDir.ReplaceAll(".xml", "");
2898 if (fOutputToRunNo)
2899 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2900 else
2901 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
84fcd93f 2902 printf("********* %s\n",query.Data());
d2a409b2 2903 res = gGrid->Command(query);
2904 if (res) {
98ca124f 2905 TString cjobId1 = res->GetKey(0,"jobId");
2906 if (!cjobId1.Length()) {
d2a409b2 2907 iscalled = kFALSE;
a03be957 2908 gGrid->Stdout();
2909 gGrid->Stderr();
2910 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2911 return kFALSE;
d2a409b2 2912 } else {
2913 Info("StartAnalysis", "\n_______________________________________________________________________ \
2914 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2915 \n_______________________________________________________________________",
98ca124f 2916 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
d2a409b2 2917 jobID += cjobId1;
2918 jobID += " ";
98ca124f 2919 lastmaster = cjobId1.Atoi();
d2a409b2 2920 if (!firstmaster) firstmaster = lastmaster;
2921 fNsubmitted++;
2922 }
2923 delete res;
a03be957 2924 } else {
2925 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2926 return kFALSE;
d2a409b2 2927 }
2928 }
2929 iscalled = kFALSE;
a03be957 2930 return kTRUE;
d2a409b2 2931}
2932
c57f56b7 2933//______________________________________________________________________________
2934void AliAnalysisAlien::WriteAnalysisFile()
2935{
f10e8481 2936// Write current analysis manager into the file <analysisFile>
2937 TString analysisFile = fExecutable;
2938 analysisFile.ReplaceAll(".sh", ".root");
c57f56b7 2939 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2940 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2941 if (!mgr || !mgr->IsInitialized()) {
2942 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2943 return;
2944 }
2945 // Check analysis type
2946 TObject *handler;
2947 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2948 handler = (TObject*)mgr->GetInputEventHandler();
2949 if (handler) {
2950 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2951 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2952 }
2953 TDirectory *cdir = gDirectory;
f10e8481 2954 TFile *file = TFile::Open(analysisFile, "RECREATE");
c57f56b7 2955 if (file) {
e16a394c 2956 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2957 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
fe2d7fc2 2958 // Unless merging makes no sense
2959 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
c57f56b7 2960 mgr->Write();
2961 delete file;
fe2d7fc2 2962 // Enable termination for local jobs
2963 mgr->SetSkipTerminate(kFALSE);
c57f56b7 2964 }
2965 if (cdir) cdir->cd();
f10e8481 2966 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
c57f56b7 2967 }
2968 Bool_t copy = kTRUE;
d3b18c4c 2969 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 2970 if (copy) {
2971 CdWork();
2972 TString workdir = gGrid->GetHomeDirectory();
2973 workdir += fGridWorkingDir;
d3b18c4c 2974 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
f10e8481 2975 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2976 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 2977 }
2978}
2979
2980//______________________________________________________________________________
2981void AliAnalysisAlien::WriteAnalysisMacro()
2982{
2983// Write the analysis macro that will steer the analysis in grid mode.
2984 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2985 ofstream out;
2986 out.open(fAnalysisMacro.Data(), ios::out);
2987 if (!out.good()) {
2988 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2989 return;
2990 }
5b273635 2991 Bool_t hasSTEERBase = kFALSE;
2992 Bool_t hasESD = kFALSE;
2993 Bool_t hasAOD = kFALSE;
2994 Bool_t hasANALYSIS = kFALSE;
2995 Bool_t hasANALYSISalice = kFALSE;
2996 Bool_t hasCORRFW = kFALSE;
c57f56b7 2997 TString func = fAnalysisMacro;
2998 TString type = "ESD";
2999 TString comment = "// Analysis using ";
3000 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3001 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3002 type = "AOD";
3003 comment += "AOD";
3004 }
0df6ccf2 3005 if (type!="AOD" && fFriendChainName!="") {
3006 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3007 return;
3008 }
c57f56b7 3009 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3010 else comment += " data";
3011 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3012 func.ReplaceAll(".C", "");
3013 out << "void " << func.Data() << "()" << endl;
3014 out << "{" << endl;
3015 out << comment.Data() << endl;
3016 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 3017 out << " TStopwatch timer;" << endl;
3018 out << " timer.Start();" << endl << endl;
13f0c00b 3019 // Change temp directory to current one
3020 out << "// Set temporary merging directory to current one" << endl;
3021 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
b3e07543 3022 // Reset existing include path
3023 out << "// Reset existing include path and add current directory first in the search" << endl;
3024 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
f790bc1b 3025 if (!fExecutableCommand.Contains("aliroot")) {
3026 out << "// load base root libraries" << endl;
3027 out << " gSystem->Load(\"libTree\");" << endl;
3028 out << " gSystem->Load(\"libGeom\");" << endl;
3029 out << " gSystem->Load(\"libVMC\");" << endl;
3030 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3031 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3032 }
d5c6455a 3033 if (fAdditionalRootLibs.Length()) {
47a4137d 3034 // in principle libtree /lib geom libvmc etc. can go into this list, too
3035 out << "// Add aditional libraries" << endl;
3036 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3037 TIter next(list);
3038 TObjString *str;
3039 while((str=(TObjString*)next())) {
3040 if (str->GetString().Contains(".so"))
3041 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
d5c6455a 3042 }
47a4137d 3043 if (list) delete list;
d5c6455a 3044 }
57377eb5 3045 out << "// Load analysis framework libraries" << endl;
652561d5 3046 TString setupPar = "AliAnalysisAlien::SetupPar";
4e5c5506 3047 if (!fPackages) {
f790bc1b 3048 if (!fExecutableCommand.Contains("aliroot")) {
3049 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3050 out << " gSystem->Load(\"libESD\");" << endl;
3051 out << " gSystem->Load(\"libAOD\");" << endl;
3052 }
4e5c5506 3053 out << " gSystem->Load(\"libANALYSIS\");" << endl;
57377eb5 3054 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3055 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 3056 } else {
4e5c5506 3057 TIter next(fPackages);
3058 TObject *obj;
57377eb5 3059 TString pkgname;
57377eb5 3060 while ((obj=next())) {
3061 pkgname = obj->GetName();
4478e6f1 3062 if (pkgname == "STEERBase" ||
3063 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3064 if (pkgname == "ESD" ||
3065 pkgname == "ESD.par") hasESD = kTRUE;
3066 if (pkgname == "AOD" ||
3067 pkgname == "AOD.par") hasAOD = kTRUE;
3068 if (pkgname == "ANALYSIS" ||
3069 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3070 if (pkgname == "ANALYSISalice" ||
3071 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3072 if (pkgname == "CORRFW" ||
3073 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
5b273635 3074 }
3075 if (hasANALYSISalice) setupPar = "SetupPar";
57377eb5 3076 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3077 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
57377eb5 3078 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3079 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
57377eb5 3080 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3081 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
57377eb5 3082 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3083 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
57377eb5 3084 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3085 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
57377eb5 3086 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3087 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
57377eb5 3088 out << "// Compile other par packages" << endl;
3089 next.Reset();
fcc9bb6f 3090 while ((obj=next())) {
3091 pkgname = obj->GetName();
4478e6f1 3092 if (pkgname == "STEERBase" ||
3093 pkgname == "STEERBase.par" ||
3094 pkgname == "ESD" ||
3095 pkgname == "ESD.par" ||
3096 pkgname == "AOD" ||
3097 pkgname == "AOD.par" ||
3098 pkgname == "ANALYSIS" ||
3099 pkgname == "ANALYSIS.par" ||
3100 pkgname == "ANALYSISalice" ||
3101 pkgname == "ANALYSISalice.par" ||
3102 pkgname == "CORRFW" ||
3103 pkgname == "CORRFW.par") continue;
5b273635 3104 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 3105 }
4e5c5506 3106 }
b3e07543 3107 out << "// include path" << endl;
3108 // Get the include path from the interpreter and remove entries pointing to AliRoot
3109 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3110 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3111 out << " TIter nextpath(listpaths);" << endl;
3112 out << " TObjString *pname;" << endl;
3113 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3114 out << " TString current = pname->GetName();" << endl;
3115 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3116 out << " gSystem->AddIncludePath(current);" << endl;
3117 out << " }" << endl;
3118 out << " if (listpaths) delete listpaths;" << endl;
3119 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3120 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3121 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
6da75e0b 3122 if (fAdditionalLibs.Length()) {
3123 out << "// Add aditional AliRoot libraries" << endl;
3124 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3125 TIter next(list);
3126 TObjString *str;
3127 while((str=(TObjString*)next())) {
3128 if (str->GetString().Contains(".so"))
3129 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
652561d5 3130 if (str->GetString().Contains(".par"))
3131 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
6da75e0b 3132 }
3133 if (list) delete list;
3134 }
3135 out << endl;
c57f56b7 3136 out << "// analysis source to be compiled at runtime (if any)" << endl;
3137 if (fAnalysisSource.Length()) {
3138 TObjArray *list = fAnalysisSource.Tokenize(" ");
3139 TIter next(list);
3140 TObjString *str;
3141 while((str=(TObjString*)next())) {
3142 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3143 }
3144 if (list) delete list;
3145 }
3146 out << endl;
b3e07543 3147// out << " printf(\"Currently load libraries:\\n\");" << endl;
3148// out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
0f389141 3149 if (fFastReadOption) {
d3339be3 3150 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. This may skip some files that could be accessed !!! \
3151 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
0f389141 3152 out << "// fast xrootd reading enabled" << endl;
3153 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
b3e07543 3154 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3155 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
0f389141 3156 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
b3e07543 3157 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
0f389141 3158 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3159 }
c57f56b7 3160 out << "// connect to AliEn and make the chain" << endl;
3161 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
c57f56b7 3162 out << "// read the analysis manager from file" << endl;
f10e8481 3163 TString analysisFile = fExecutable;
3164 analysisFile.ReplaceAll(".sh", ".root");
3165 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
c57f56b7 3166 out << " if (!file) return;" << endl;
3167 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3168 out << " AliAnalysisManager *mgr = 0;" << endl;
3169 out << " TKey *key;" << endl;
3170 out << " while ((key=(TKey*)nextkey())) {" << endl;
3171 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3172 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3173 out << " };" << endl;
3174 out << " if (!mgr) {" << endl;
205b201f 3175 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
c57f56b7 3176 out << " return;" << endl;
3177 out << " }" << endl << endl;
3178 out << " mgr->PrintStatus();" << endl;
52b6a92b 3179 if (AliAnalysisManager::GetAnalysisManager()) {
f866cba5 3180 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
52b6a92b 3181 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
de52b69c 3182 } else {
9a8288ff 3183 if (TestBit(AliAnalysisGrid::kTest))
3184 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3185 else
3186 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
52b6a92b 3187 }
3188 }
242accb2 3189 if (IsUsingTags()) {
3190 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3191 } else {
3192 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3193 }
c57f56b7 3194 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 3195 out << " timer.Stop();" << endl;
3196 out << " timer.Print();" << endl;
c57f56b7 3197 out << "}" << endl << endl;
3198 if (IsUsingTags()) {
3199 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3200 out << "{" << endl;
3201 out << "// Create a chain using tags from the xml file." << endl;
3202 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3203 out << " if (!coll) {" << endl;
3204 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3205 out << " return NULL;" << endl;
3206 out << " }" << endl;
3207 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3208 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3209 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3210 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3211 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3212 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3213 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3214 out << " // Check if the cuts configuration file was provided" << endl;
3215 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3216 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3217 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3218 out << " }" << endl;
0df6ccf2 3219 if (fFriendChainName=="") {
3220 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3221 } else {
3222 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3223 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3224 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3225 }
c57f56b7 3226 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3227 out << " chain->ls();" << endl;
3228 out << " return chain;" << endl;
fcc9bb6f 3229 out << "}" << endl << endl;
c57f56b7 3230 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3231 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3232 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3233 msg += " AliLHCTagCuts *lhcCuts,\n";
3234 msg += " AliDetectorTagCuts *detCuts,\n";
3235 msg += " AliEventTagCuts *evCuts)";
23329835 3236 Info("WriteAnalysisMacro", "%s", msg.Data());
c57f56b7 3237 }
0df6ccf2 3238 }
3239 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 3240 out <<"//________________________________________________________________________________" << endl;
c57f56b7 3241 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3242 out << "{" << endl;
3243 out << "// Create a chain using url's from xml file" << endl;
242accb2 3244 out << " TString filename;" << endl;
3245 out << " Int_t run = 0;" << endl;
c57f56b7 3246 out << " TString treename = type;" << endl;
3247 out << " treename.ToLower();" << endl;
3248 out << " treename += \"Tree\";" << endl;
e02fee64 3249 out << " printf(\"***************************************\\n\");" << endl;
3250 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3251 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 3252 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3253 out << " if (!coll) {" << endl;
3254 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3255 out << " return NULL;" << endl;
3256 out << " }" << endl;
242accb2 3257 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
c57f56b7 3258 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 3259 if(fFriendChainName!="") {
3260 out << " TChain *chainFriend = new TChain(treename);" << endl;
3261 }
c57f56b7 3262 out << " coll->Reset();" << endl;
0df6ccf2 3263 out << " while (coll->Next()) {" << endl;
242accb2 3264 out << " filename = coll->GetTURL("");" << endl;
3265 out << " if (mgr) {" << endl;
3266 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3267 out << " if (nrun && nrun != run) {" << endl;
3268 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3269 out << " mgr->SetRunFromPath(nrun);" << endl;
3270 out << " run = nrun;" << endl;
3271 out << " }" << endl;
3272 out << " }" << endl;
3273 out << " chain->Add(filename);" << endl;
0df6ccf2 3274 if(fFriendChainName!="") {
3275 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3276 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3277 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3278 out << " chainFriend->Add(fileFriend.Data());" << endl;
3279 }
3280 out << " }" << endl;
c57f56b7 3281 out << " if (!chain->GetNtrees()) {" << endl;
3282 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3283 out << " return NULL;" << endl;
3284 out << " }" << endl;
0df6ccf2 3285 if(fFriendChainName!="") {
3286 out << " chain->AddFriend(chainFriend);" << endl;
3287 }
c57f56b7 3288 out << " return chain;" << endl;
fcc9bb6f 3289 out << "}" << endl << endl;
c57f56b7 3290 }
5b273635 3291 if (hasANALYSISalice) {
3292 out <<"//________________________________________________________________________________" << endl;
3293 out << "Bool_t SetupPar(const char *package) {" << endl;
3294 out << "// Compile the package and set it up." << endl;
3295 out << " TString pkgdir = package;" << endl;
3296 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
b50a41c3 3297 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
5b273635 3298 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3299 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3300 out << " // Check for BUILD.sh and execute" << endl;
3301 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3302 out << " printf(\"*******************************\\n\");" << endl;
3303 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3304 out << " printf(\"*******************************\\n\");" << endl;
3305 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3306 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3307 out << " gSystem->ChangeDirectory(cdir);" << endl;
3308 out << " return kFALSE;" << endl;
3309 out << " }" << endl;
3310 out << " } else {" << endl;
3311 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3312 out << " gSystem->ChangeDirectory(cdir);" << endl;
3313 out << " return kFALSE;" << endl;
3314 out << " }" << endl;
3315 out << " // Check for SETUP.C and execute" << endl;
3316 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3317 out << " printf(\"*******************************\\n\");" << endl;
3318 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3319 out << " printf(\"*******************************\\n\");" << endl;
3320 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3321 out << " } else {" << endl;
3322 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3323 out << " gSystem->ChangeDirectory(cdir);" << endl;
3324 out << " return kFALSE;" << endl;
3325 out << " }" << endl;
3326 out << " // Restore original workdir" << endl;
3327 out << " gSystem->ChangeDirectory(cdir);" << endl;
3328 out << " return kTRUE;" << endl;
3329 out << "}" << endl;
3330 }
c57f56b7 3331 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3332 }
3333 Bool_t copy = kTRUE;
d3b18c4c 3334 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3335 if (copy) {
3336 CdWork();
3337 TString workdir = gGrid->GetHomeDirectory();
3338 workdir += fGridWorkingDir;
3339 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3340 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3341 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3342 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3343 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3344 }
3345 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3346 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3347 }
3348}
3349
0f389141 3350//______________________________________________________________________________
3351void AliAnalysisAlien::WriteMergingMacro()
3352{
3353// Write a macro to merge the outputs per master job.
3354 if (!fMergeViaJDL) return;
3355 if (!fOutputFiles.Length()) {
3356 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3357 return;
3358 }
3359 TString mergingMacro = fExecutable;
3360 mergingMacro.ReplaceAll(".sh","_merge.C");
3361 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3362 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3363 ofstream out;
3364 out.open(mergingMacro.Data(), ios::out);
3365 if (!out.good()) {
3366 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3367 return;
3368 }
5b273635 3369 Bool_t hasSTEERBase = kFALSE;
3370 Bool_t hasESD = kFALSE;
3371 Bool_t hasAOD = kFALSE;
3372 Bool_t hasANALYSIS = kFALSE;
3373 Bool_t hasANALYSISalice = kFALSE;
3374 Bool_t hasCORRFW = kFALSE;
0f389141 3375 TString func = mergingMacro;
3376 TString comment;
3377 func.ReplaceAll(".C", "");
f47d5cb4 3378 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
0f389141 3379 out << "{" << endl;
3380 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3381 out << " TStopwatch timer;" << endl;
3382 out << " timer.Start();" << endl << endl;
b3e07543 3383 // Reset existing include path
3384 out << "// Reset existing include path and add current directory first in the search" << endl;
3385 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
7c2cd90a 3386 if (!fExecutableCommand.Contains("aliroot")) {
3387 out << "// load base root libraries" << endl;
3388 out << " gSystem->Load(\"libTree\");" << endl;
3389 out << " gSystem->Load(\"libGeom\");" << endl;
3390 out << " gSystem->Load(\"libVMC\");" << endl;
3391 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3392 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3393 }
0f389141 3394 if (fAdditionalRootLibs.Length()) {
3395 // in principle libtree /lib geom libvmc etc. can go into this list, too
3396 out << "// Add aditional libraries" << endl;
3397 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3398 TIter next(list);
3399 TObjString *str;
3400 while((str=(TObjString*)next())) {
3401 if (str->GetString().Contains(".so"))
3402 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3403 }
3404 if (list) delete list;
3405 }
0f389141 3406 out << "// Load analysis framework libraries" << endl;
3407 if (!fPackages) {
7c2cd90a 3408 if (!fExecutableCommand.Contains("aliroot")) {
3409 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3410 out << " gSystem->Load(\"libESD\");" << endl;
3411 out << " gSystem->Load(\"libAOD\");" << endl;
3412 }
0f389141 3413 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3414 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3415 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3416 } else {
3417 TIter next(fPackages);
3418 TObject *obj;
3419 TString pkgname;
5b273635 3420 TString setupPar = "AliAnalysisAlien::SetupPar";
0f389141 3421 while ((obj=next())) {
3422 pkgname = obj->GetName();
3423 if (pkgname == "STEERBase" ||
3424 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3425 if (pkgname == "ESD" ||
3426 pkgname == "ESD.par") hasESD = kTRUE;
3427 if (pkgname == "AOD" ||
3428 pkgname == "AOD.par") hasAOD = kTRUE;
3429 if (pkgname == "ANALYSIS" ||
3430 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3431 if (pkgname == "ANALYSISalice" ||
3432 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3433 if (pkgname == "CORRFW" ||
3434 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3435 }
5b273635 3436 if (hasANALYSISalice) setupPar = "SetupPar";
0f389141 3437 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3438 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
0f389141 3439 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3440 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
0f389141 3441 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3442 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
0f389141 3443 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3444 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
0f389141 3445 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3446 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
0f389141 3447 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3448 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
0f389141 3449 out << "// Compile other par packages" << endl;
3450 next.Reset();
3451 while ((obj=next())) {
3452 pkgname = obj->GetName();
3453 if (pkgname == "STEERBase" ||
3454 pkgname == "STEERBase.par" ||
3455 pkgname == "ESD" ||
3456 pkgname == "ESD.par" ||
3457 pkgname == "AOD" ||
3458 pkgname == "AOD.par" ||
3459 pkgname == "ANALYSIS" ||
3460 pkgname == "ANALYSIS.par" ||
3461 pkgname == "ANALYSISalice" ||
3462 pkgname == "ANALYSISalice.par" ||
3463 pkgname == "CORRFW" ||
3464 pkgname == "CORRFW.par") continue;
5b273635 3465 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
0f389141 3466 }
3467 }
b3e07543 3468 out << "// include path" << endl;
3469 // Get the include path from the interpreter and remove entries pointing to AliRoot
3470 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3471 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3472 out << " TIter nextpath(listpaths);" << endl;
3473 out << " TObjString *pname;" << endl;
3474 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3475 out << " TString current = pname->GetName();" << endl;
3476 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3477 out << " gSystem->AddIncludePath(current);" << endl;
3478 out << " }" << endl;
3479 out << " if (listpaths) delete listpaths;" << endl;
3480 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3481 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3482 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
0f389141 3483 if (fAdditionalLibs.Length()) {
3484 out << "// Add aditional AliRoot libraries" << endl;
3485 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3486 TIter next(list);
3487 TObjString *str;
3488 while((str=(TObjString*)next())) {
3489 if (str->GetString().Contains(".so"))
3490 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3491 }
3492 if (list) delete list;
3493 }
3494 out << endl;
3495 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3496 if (fAnalysisSource.Length()) {
3497 TObjArray *list = fAnalysisSource.Tokenize(" ");
3498 TIter next(list);
3499 TObjString *str;
3500 while((str=(TObjString*)next())) {
3501 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3502 }
3503 if (list) delete list;
3504 }
149d288c 3505 out << endl;
3506
0f389141 3507 if (fFastReadOption) {
3508 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 !!!");
3509 out << "// fast xrootd reading enabled" << endl;
3510 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
b3e07543 3511 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3512 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
0f389141 3513 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
b3e07543 3514 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
0f389141 3515 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
e8b839ab 3516 }
3517 // Change temp directory to current one
3518 out << "// Set temporary merging directory to current one" << endl;
3519 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
0f389141 3520 out << "// Connect to AliEn" << endl;
3521 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
7c2cd90a 3522 out << " TString outputDir = dir;" << endl;
f790bc1b 3523 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
0f389141 3524 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
58268c13 3525 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
0f389141 3526 out << " TIter *iter = new TIter(list);" << endl;
3527 out << " TObjString *str;" << endl;
a2f5fc01 3528 out << " TString outputFile;" << endl;
0f389141 3529 out << " Bool_t merged = kTRUE;" << endl;
3530 out << " while((str=(TObjString*)iter->Next())) {" << endl;
a2f5fc01 3531 out << " outputFile = str->GetString();" << endl;
7c2cd90a 3532 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
a2f5fc01 3533 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3534 out << " if (index > 0) outputFile.Remove(index);" << endl;
0f389141 3535 out << " // Skip already merged outputs" << endl;
a2f5fc01 3536 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3537 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
0f389141 3538 out << " continue;" << endl;
3539 out << " }" << endl;
a2f5fc01 3540 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
b3e07543 3541 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
0f389141 3542 out << " if (!merged) {" << endl;
a2f5fc01 3543 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
7c2cd90a 3544 out << " return;" << endl;
0f389141 3545 out << " }" << endl;
3546 out << " }" << endl;
7c2cd90a 3547 out << " // all outputs merged, validate" << endl;
3548 out << " ofstream out;" << endl;
3549 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3550 out << " out.close();" << endl;
3551 out << " // read the analysis manager from file" << endl;
f866cba5 3552 TString analysisFile = fExecutable;
3553 analysisFile.ReplaceAll(".sh", ".root");
f47d5cb4 3554 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
f866cba5 3555 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
7c2cd90a 3556 out << " if (!file) return;" << endl;
f866cba5 3557 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3558 out << " AliAnalysisManager *mgr = 0;" << endl;
3559 out << " TKey *key;" << endl;
3560 out << " while ((key=(TKey*)nextkey())) {" << endl;
3561 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3562 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3563 out << " };" << endl;
3564 out << " if (!mgr) {" << endl;
3565 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3566 out << " return;" << endl;
3567 out << " }" << endl << endl;
5c4250fc 3568 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
b385fec0 3569 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
f866cba5 3570 out << " mgr->PrintStatus();" << endl;
3571 if (AliAnalysisManager::GetAnalysisManager()) {
3572 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3573 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3574 } else {
9a8288ff 3575 if (TestBit(AliAnalysisGrid::kTest))
3576 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3577 else
3578 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
f866cba5 3579 }
3580 }
9a8288ff 3581 out << " TTree *tree = NULL;" << endl;
3582 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
0f389141 3583 out << "}" << endl << endl;
5b273635 3584 if (hasANALYSISalice) {
3585 out <<"//________________________________________________________________________________" << endl;
3586 out << "Bool_t SetupPar(const char *package) {" << endl;
3587 out << "// Compile the package and set it up." << endl;
3588 out << " TString pkgdir = package;" << endl;
3589 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
b50a41c3 3590 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
5b273635 3591 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3592 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3593 out << " // Check for BUILD.sh and execute" << endl;
3594 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3595 out << " printf(\"*******************************\\n\");" << endl;
3596 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3597 out << " printf(\"*******************************\\n\");" << endl;
3598 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3599 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3600 out << " gSystem->ChangeDirectory(cdir);" << endl;
3601 out << " return kFALSE;" << endl;
3602 out << " }" << endl;
3603 out << " } else {" << endl;
3604 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3605 out << " gSystem->ChangeDirectory(cdir);" << endl;
3606 out << " return kFALSE;" << endl;
3607 out << " }" << endl;
3608 out << " // Check for SETUP.C and execute" << endl;
3609 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3610 out << " printf(\"*******************************\\n\");" << endl;
3611 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3612 out << " printf(\"*******************************\\n\");" << endl;
3613 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3614 out << " } else {" << endl;
3615 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3616 out << " gSystem->ChangeDirectory(cdir);" << endl;
3617 out << " return kFALSE;" << endl;
3618 out << " }" << endl;
3619 out << " // Restore original workdir" << endl;
3620 out << " gSystem->ChangeDirectory(cdir);" << endl;
3621 out << " return kTRUE;" << endl;
3622 out << "}" << endl;
3623 }
0f389141 3624 }
3625 Bool_t copy = kTRUE;
d3b18c4c 3626 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 3627 if (copy) {
3628 CdWork();
3629 TString workdir = gGrid->GetHomeDirectory();
3630 workdir += fGridWorkingDir;
3631 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3632 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3633 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3634 }
3635}
3636
3637//______________________________________________________________________________
3638Bool_t AliAnalysisAlien::SetupPar(const char *package)
3639{
205b201f 3640// Compile the par file archive pointed by <package>. This must be present in the current directory.
0f389141 3641// Note that for loading the compiled library. The current directory should have precedence in
3642// LD_LIBRARY_PATH
3643 TString pkgdir = package;
3644 pkgdir.ReplaceAll(".par","");
b50a41c3 3645 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
0f389141 3646 TString cdir = gSystem->WorkingDirectory();
3647 gSystem->ChangeDirectory(pkgdir);
3648 // Check for BUILD.sh and execute
3649 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3650 printf("**************************************************\n");
3651 printf("*** Building PAR archive %s\n", package);
3652 printf("**************************************************\n");
3653 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3654 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3655 gSystem->ChangeDirectory(cdir);
3656 return kFALSE;
3657 }
3658 } else {
3659 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3660 gSystem->ChangeDirectory(cdir);
3661 return kFALSE;
3662 }
3663 // Check for SETUP.C and execute
3664 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3665 printf("**************************************************\n");
3666 printf("*** Setup PAR archive %s\n", package);
3667 printf("**************************************************\n");
3668 gROOT->Macro("PROOF-INF/SETUP.C");
3669 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3670 } else {
3671 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3672 gSystem->ChangeDirectory(cdir);
3673 return kFALSE;
3674 }
3675 // Restore original workdir
3676 gSystem->ChangeDirectory(cdir);
3677 return kTRUE;
3678}
3679
c57f56b7 3680//______________________________________________________________________________
3681void AliAnalysisAlien::WriteExecutable()
3682{
3683// Generate the alien executable script.
3684 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3685 ofstream out;
3686 out.open(fExecutable.Data(), ios::out);
3687 if (out.bad()) {
5513444a 3688 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
c57f56b7 3689 return;
3690 }
3691 out << "#!/bin/bash" << endl;
2a4d5166 3692 // Make sure we can properly compile par files
3693 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
c57f56b7 3694 out << "echo \"=========================================\"" << endl;
3695 out << "echo \"############## PATH : ##############\"" << endl;
3696 out << "echo $PATH" << endl;
3697 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3698 out << "echo $LD_LIBRARY_PATH" << endl;
3699 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3700 out << "echo $ROOTSYS" << endl;
3701 out << "echo \"############## which root : ##############\"" << endl;
3702 out << "which root" << endl;
3703 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3704 out << "echo $ALICE_ROOT" << endl;
3705 out << "echo \"############## which aliroot : ##############\"" << endl;
3706 out << "which aliroot" << endl;
9c5ddadc 3707 out << "echo \"############## system limits : ##############\"" << endl;
3708 out << "ulimit -a" << endl;
3709 out << "echo \"############## memory : ##############\"" << endl;
3710 out << "free -m" << endl;
c57f56b7 3711 out << "echo \"=========================================\"" << endl << endl;
0a1c1f7f 3712 out << fExecutableCommand << " ";
631c0b05 3713 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
9c5ddadc 3714 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3715 out << "echo \"############## memory after: ##############\"" << endl;
3716 out << "free -m" << endl;
c57f56b7 3717 }
3718 Bool_t copy = kTRUE;
d3b18c4c 3719 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3720 if (copy) {
3721 CdWork();
3722 TString workdir = gGrid->GetHomeDirectory();
923e2ca5 3723 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 3724 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
c57f56b7 3725 workdir += fGridWorkingDir;
3726 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3727 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 3728 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
c57f56b7 3729 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3730 }
3731}
3732
0f389141 3733//______________________________________________________________________________
3734void AliAnalysisAlien::WriteMergeExecutable()
3735{
3736// Generate the alien executable script for the merging job.
3737 if (!fMergeViaJDL) return;
3738 TString mergeExec = fExecutable;
3739 mergeExec.ReplaceAll(".sh", "_merge.sh");
3740 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3741 ofstream out;
3742 out.open(mergeExec.Data(), ios::out);
3743 if (out.bad()) {
3744 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3745 return;
3746 }
3747 out << "#!/bin/bash" << endl;
2a4d5166 3748 // Make sure we can properly compile par files
3749 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
0f389141 3750 out << "echo \"=========================================\"" << endl;
3751 out << "echo \"############## PATH : ##############\"" << endl;
3752 out << "echo $PATH" << endl;
3753 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3754 out << "echo $LD_LIBRARY_PATH" << endl;
3755 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3756 out << "echo $ROOTSYS" << endl;
3757 out << "echo \"############## which root : ##############\"" << endl;
3758 out << "which root" << endl;
3759 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3760 out << "echo $ALICE_ROOT" << endl;
3761 out << "echo \"############## which aliroot : ##############\"" << endl;
3762 out << "which aliroot" << endl;
3763 out << "echo \"############## system limits : ##############\"" << endl;
3764 out << "ulimit -a" << endl;
3765 out << "echo \"############## memory : ##############\"" << endl;
3766 out << "free -m" << endl;
3767 out << "echo \"=========================================\"" << endl << endl;
0f389141 3768 TString mergeMacro = fExecutable;
3769 mergeMacro.ReplaceAll(".sh", "_merge.C");
f790bc1b 3770 if (IsOneStageMerging())
3771 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3772 else
f47d5cb4 3773 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
0f389141 3774 out << fExecutableCommand << " " << "$ARG" << endl;
3775 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3776 out << "echo \"############## memory after: ##############\"" << endl;
3777 out << "free -m" << endl;
0f389141 3778 }
3779 Bool_t copy = kTRUE;
d3b18c4c 3780 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 3781 if (copy) {
3782 CdWork();
3783 TString workdir = gGrid->GetHomeDirectory();
3784 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 3785 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
0f389141 3786 workdir += fGridWorkingDir;
3787 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3788 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 3789 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
0f389141 3790 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3791 }
3792}
3793
c57f56b7 3794//______________________________________________________________________________
5513444a 3795void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3796{
3797// Write the production file to be submitted by LPM manager. The format is:
f5e8c702 3798// First line: full_path_to_jdl estimated_no_subjobs_per_master
5513444a 3799// Next lines: full_path_to_dataset XXX (XXX is a string)
3800// To submit, one has to: submit jdl XXX for all lines
3801 ofstream out;
3802 out.open(filename, ios::out);
3803 if (out.bad()) {
3804 Error("WriteProductionFile", "Bad file name: %s", filename);
3805 return;
3806 }
d3b18c4c 3807 TString workdir;
3808 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3809 workdir = gGrid->GetHomeDirectory();
5513444a 3810 workdir += fGridWorkingDir;
f5e8c702 3811 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
5513444a 3812 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
f5e8c702 3813 out << locjdl << " " << njobspermaster << endl;
5513444a 3814 Int_t nmasterjobs = fInputFiles->GetEntries();
3815 for (Int_t i=0; i<nmasterjobs; i++) {
409b4ada 3816 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3817 runOutDir.ReplaceAll(".xml", "");
3818 if (fOutputToRunNo)
3819 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3820 else
3821 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
5513444a 3822 }
d3b18c4c 3823 if (gGrid) {
3824 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3825 if (FileExists(filename)) gGrid->Rm(filename);
3826 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3827 }
5513444a 3828}
3829
3830//______________________________________________________________________________
0f389141 3831void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
c57f56b7 3832{
3833// Generate the alien validation script.
3834 // Generate the validation script
3835 TObjString *os;
d3b18c4c 3836 if (fValidationScript.IsNull()) {
3837 fValidationScript = fExecutable;
3838 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3839 }
3840 TString validationScript = fValidationScript;
3841 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
c57f56b7 3842 if (!Connect()) {
3843 Error("WriteValidationScript", "Alien connection required");
3844 return;
3845 }
d3b18c4c 3846 if (!fTerminateFiles.IsNull()) {
3847 fTerminateFiles.Strip();
3848 fTerminateFiles.ReplaceAll(" ",",");
3849 }
a2f5fc01 3850 TString outStream = "";
3851 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
c57f56b7 3852 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3853 ofstream out;
0d5d317c 3854 out.open(validationScript, ios::out);
c57f56b7 3855 out << "#!/bin/bash" << endl;
3856 out << "##################################################" << endl;
3857 out << "validateout=`dirname $0`" << endl;
3858 out << "validatetime=`date`" << endl;
3859 out << "validated=\"0\";" << endl;
3860 out << "error=0" << endl;
3861 out << "if [ -z $validateout ]" << endl;
3862 out << "then" << endl;
3863 out << " validateout=\".\"" << endl;
3864 out << "fi" << endl << endl;
3865 out << "cd $validateout;" << endl;
3866 out << "validateworkdir=`pwd`;" << endl << endl;
a2f5fc01 3867 out << "echo \"*******************************************************\"" << outStream << endl;
3868 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
c57f56b7 3869 out << "" << endl;
a2f5fc01 3870 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3871 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3872 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3873 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3874 out << "ls -la ./" << outStream << endl;
3875 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
c57f56b7 3876 out << "##################################################" << endl;
ebec370a 3877 out << "" << endl;
3878
3879 out << "if [ ! -f stderr ] ; then" << endl;
3880 out << " error=1" << endl;
a2f5fc01 3881 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3882 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3883 out << "fi" << endl;
3884
b34c9f51 3885 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3886 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3887 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3888 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3889 out << "" << endl;
3890
ebec370a 3891 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3892 out << " error=1" << endl;
a2f5fc01 3893 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3894 out << " echo \"$parArch\" " << outStream << endl;
3895 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3896 out << "fi" << endl;
3897
3898 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3899 out << " error=1" << endl;
a2f5fc01 3900 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3901 out << " echo \"$segViol\" " << outStream << endl;
3902 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3903 out << "fi" << endl;
3904
3905 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3906 out << " error=1" << endl;
a2f5fc01 3907 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3908 out << " echo \"$segFault\" " << outStream << endl;
3909 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 3910 out << "fi" << endl;
3911
b34c9f51 3912 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3913 out << " error=1" << endl;
a2f5fc01 3914 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3915 out << " echo \"$glibcErr\" " << outStream << endl;
3916 out << " echo \"Error = $error\" " << outStream << endl;
b34c9f51 3917 out << "fi" << endl;
3918
ebec370a 3919 // Part dedicated to the specific analyses running into the train
3920
d3b18c4c 3921 TString outputFiles = fOutputFiles;
3922 if (merge && !fTerminateFiles.IsNull()) {
3923 outputFiles += ",";
3924 outputFiles += fTerminateFiles;
3925 }
3926 TObjArray *arr = outputFiles.Tokenize(",");
c57f56b7 3927 TIter next1(arr);
a2f5fc01 3928 TString outputFile;
bbd88db8 3929 while (!merge && (os=(TObjString*)next1())) {
3930 // No need to validate outputs produced by merging since the merging macro does this
a2f5fc01 3931 outputFile = os->GetString();
3932 Int_t index = outputFile.Index("@");
3933 if (index > 0) outputFile.Remove(index);
bbd88db8 3934 if (fTerminateFiles.Contains(outputFile)) continue;
a2f5fc01 3935 if (outputFile.Contains("*")) continue;
3936 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
c57f56b7 3937 out << " error=1" << endl;
7c2cd90a 3938 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
3939 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
c57f56b7 3940 out << "fi" << endl;
3941 }
3942 delete arr;
7c2cd90a 3943 out << "if ! [ -f outputs_valid ] ; then" << endl;
3944 out << " error=1" << endl;
3945 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3946 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3947 out << "fi" << endl;
923e2ca5 3948
c57f56b7 3949 out << "if [ $error = 0 ] ; then" << endl;
a2f5fc01 3950 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
149d288c 3951 if (!IsKeepLogs()) {
3952 out << " echo \"* === Logs std* will be deleted === \"" << endl;
a2f5fc01 3953 outStream = "";
149d288c 3954 out << " rm -f std*" << endl;
3955 }
c57f56b7 3956 out << "fi" << endl;
3957
a2f5fc01 3958 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3959 out << "echo \"*******************************************************\"" << outStream << endl;
c57f56b7 3960 out << "cd -" << endl;
3961 out << "exit $error" << endl;
3962 }
3963 Bool_t copy = kTRUE;
d3b18c4c 3964 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3965 if (copy) {
3966 CdWork();
3967 TString workdir = gGrid->GetHomeDirectory();
3968 workdir += fGridWorkingDir;
d3b18c4c 3969 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
0d5d317c 3970 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3971 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 3972 }
3973}