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