]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisAlien.cxx
patch
[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 }
d3b18c4c 1438 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
d3b18c4c 1439 } else {
1440 if (!fRunNumbers.Length() && !fRunRange[0]) {
1441 // One jdl with no parameters in case input data is specified by name.
1442 TIter next(fInputFiles);
1443 while ((os=next()))
1444 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1445 if (!fOutputSingle.IsNull())
1446 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1447 else {
1448 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1449 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1450 }
1451 } else {
1452 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1453 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1454 if (!fOutputSingle.IsNull()) {
1455 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1456 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1457 } else {
1458 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
d3b18c4c 1459 }
1460 }
a8739e8a 1461 }
1462
a8739e8a 1463 // Generate the JDL as a string
1464 TString sjdl = fGridJDL->Generate();
0f389141 1465 TString sjdl1 = fMergingJDL->Generate();
f47d5cb4 1466 // Final merge jdl
1467 if (!fMergeDirName.IsNull()) {
1468 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1469 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1470 } else {
1471 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1472 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1473 }
b3e07543 1474 TString sjdl2 = fMergingJDL->Generate();
1475 Int_t index, index1;
a8739e8a 1476 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1477 sjdl.ReplaceAll("(member", "\n (member");
1478 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1479 sjdl.ReplaceAll("{", "{\n ");
1480 sjdl.ReplaceAll("};", "\n};");
1481 sjdl.ReplaceAll("{\n \n", "{\n");
1482 sjdl.ReplaceAll("\n\n", "\n");
1483 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
0f389141 1484 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1485 sjdl1.ReplaceAll("(member", "\n (member");
1486 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1487 sjdl1.ReplaceAll("{", "{\n ");
1488 sjdl1.ReplaceAll("};", "\n};");
1489 sjdl1.ReplaceAll("{\n \n", "{\n");
1490 sjdl1.ReplaceAll("\n\n", "\n");
1491 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
b3e07543 1492 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1493 sjdl2.ReplaceAll("(member", "\n (member");
1494 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1495 sjdl2.ReplaceAll("{", "{\n ");
1496 sjdl2.ReplaceAll("};", "\n};");
1497 sjdl2.ReplaceAll("{\n \n", "{\n");
1498 sjdl2.ReplaceAll("\n\n", "\n");
1499 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
a8739e8a 1500 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
f60ef0ba 1501 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
a8739e8a 1502 index = sjdl.Index("JDLVariables");
1503 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
4739b2aa 1504 sjdl += "Workdirectorysize = {\"5000MB\"};";
b3e07543 1505 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
0f389141 1506 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
d3b18c4c 1507 index = fJobTag.Index(":");
1508 if (index < 0) index = fJobTag.Length();
1509 TString jobTag = fJobTag;
f47d5cb4 1510 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
d3b18c4c 1511 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
f47d5cb4 1512 if (fProductionMode) {
1513 sjdl1.Prepend("# Generated merging jdl (production mode) \
1514 \n# $1 = full alien path to output directory to be merged \
1515 \n# $2 = train number \
1516 \n# $3 = production (like LHC10b) \
1517 \n# $4 = merging stage \
1518 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1519 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1520 sjdl2.Prepend("# Generated merging jdl \
1521 \n# $1 = full alien path to output directory to be merged \
1522 \n# $2 = train number \
1523 \n# $3 = production (like LHC10b) \
1524 \n# $4 = merging stage \
1525 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1526 } else {
1527 sjdl1.Prepend("# Generated merging jdl \
1528 \n# $1 = full alien path to output directory to be merged \
1529 \n# $2 = merging stage \
03335324 1530 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
f47d5cb4 1531 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1532 sjdl2.Prepend("# Generated merging jdl \
1533 \n# $1 = full alien path to output directory to be merged \
1534 \n# $2 = merging stage \
03335324 1535 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
f47d5cb4 1536 }
0f389141 1537 index = sjdl1.Index("JDLVariables");
1538 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
b3e07543 1539 index = sjdl2.Index("JDLVariables");
1540 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
4739b2aa 1541 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
b3e07543 1542 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1543 index = sjdl2.Index("Split =");
1544 if (index>=0) {
1545 index1 = sjdl2.Index("\n", index);
1546 sjdl2.Remove(index, index1-index+1);
1547 }
1548 index = sjdl2.Index("SplitMaxInputFileNumber");
1549 if (index>=0) {
1550 index1 = sjdl2.Index("\n", index);
1551 sjdl2.Remove(index, index1-index+1);
1552 }
1553 index = sjdl2.Index("InputDataCollection");
1554 if (index>=0) {
1555 index1 = sjdl2.Index(";", index);
1556 sjdl2.Remove(index, index1-index+1);
1557 }
1558 index = sjdl2.Index("InputDataListFormat");
1559 if (index>=0) {
1560 index1 = sjdl2.Index("\n", index);
1561 sjdl2.Remove(index, index1-index+1);
1562 }
1563 index = sjdl2.Index("InputDataList");
1564 if (index>=0) {
1565 index1 = sjdl2.Index("\n", index);
1566 sjdl2.Remove(index, index1-index+1);
1567 }
f47d5cb4 1568 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
a8739e8a 1569 // Write jdl to file
a8739e8a 1570 ofstream out;
d2a409b2 1571 out.open(fJDLName.Data(), ios::out);
a8739e8a 1572 if (out.bad()) {
d3b18c4c 1573 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
a8739e8a 1574 return kFALSE;
1575 }
1576 out << sjdl << endl;
b3e07543 1577 out.close();
0f389141 1578 TString mergeJDLName = fExecutable;
1579 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1580 if (fMergeViaJDL) {
1581 ofstream out1;
1582 out1.open(mergeJDLName.Data(), ios::out);
b3e07543 1583 if (out1.bad()) {
d3b18c4c 1584 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
0f389141 1585 return kFALSE;
1586 }
1587 out1 << sjdl1 << endl;
b3e07543 1588 out1.close();
1589 ofstream out2;
1590 TString finalJDL = mergeJDLName;
1591 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1592 out2.open(finalJDL.Data(), ios::out);
1593 if (out2.bad()) {
1594 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1595 return kFALSE;
1596 }
1597 out2 << sjdl2 << endl;
1598 out2.close();
0f389141 1599 }
a8739e8a 1600
1601 // Copy jdl to grid workspace
1602 if (!copy) {
d3b18c4c 1603 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
a8739e8a 1604 } else {
d2a409b2 1605 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
0f389141 1606 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
b3e07543 1607 TString finalJDL = mergeJDLName;
1608 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1609 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
0f389141 1610 if (fProductionMode) {
b5fe9cba 1611 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
0f389141 1612 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
b3e07543 1613 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
0f389141 1614 }
d2a409b2 1615 if (FileExists(locjdl)) gGrid->Rm(locjdl);
0f389141 1616 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
b3e07543 1617 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
d3b18c4c 1618 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
5513444a 1619 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
0f389141 1620 if (fMergeViaJDL) {
b3e07543 1621 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
0f389141 1622 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
b3e07543 1623 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
0f389141 1624 }
a8739e8a 1625 }
1626 return kTRUE;
1627}
1628
c57f56b7 1629//______________________________________________________________________________
5513444a 1630Bool_t AliAnalysisAlien::FileExists(const char *lfn)
c57f56b7 1631{
1632// Returns true if file exists.
5513444a 1633 if (!gGrid) return kFALSE;
2ea55496 1634 TString slfn = lfn;
1635 slfn.ReplaceAll("alien://","");
1636 TGridResult *res = gGrid->Ls(slfn);
c57f56b7 1637 if (!res) return kFALSE;
1638 TMap *map = dynamic_cast<TMap*>(res->At(0));
1639 if (!map) {
1640 delete res;
1641 return kFALSE;
1642 }
1643 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1644 if (!objs || !objs->GetString().Length()) {
1645 delete res;
1646 return kFALSE;
1647 }
1648 delete res;
1649 return kTRUE;
1650}
1651
923e2ca5 1652//______________________________________________________________________________
1653Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1654{
1655// Returns true if directory exists. Can be also a path.
1656 if (!gGrid) return kFALSE;
1657 // Check if dirname is a path
1658 TString dirstripped = dirname;
1659 dirstripped = dirstripped.Strip();
1660 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1661 TString dir = gSystem->BaseName(dirstripped);
1662 dir += "/";
1663 TString path = gSystem->DirName(dirstripped);
1664 TGridResult *res = gGrid->Ls(path, "-F");
1665 if (!res) return kFALSE;
1666 TIter next(res);
1667 TMap *map;
1668 TObject *obj;
1669 while ((map=dynamic_cast<TMap*>(next()))) {
1670 obj = map->GetValue("name");
1671 if (!obj) break;
1672 if (dir == obj->GetName()) {
1673 delete res;
1674 return kTRUE;
1675 }
1676 }
1677 delete res;
1678 return kFALSE;
1679}
1680
c57f56b7 1681//______________________________________________________________________________
a2f5fc01 1682void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
c57f56b7 1683{
1684// Check input data type.
a2f5fc01 1685 isCollection = kFALSE;
1686 isXml = kFALSE;
1687 useTags = kFALSE;
c57f56b7 1688 if (!gGrid) {
1689 Error("CheckDataType", "No connection to grid");
1690 return;
1691 }
a2f5fc01 1692 isCollection = IsCollection(lfn);
c57f56b7 1693 TString msg = "\n##### file: ";
1694 msg += lfn;
a2f5fc01 1695 if (isCollection) {
c57f56b7 1696 msg += " type: raw_collection;";
1697 // special treatment for collections
a2f5fc01 1698 isXml = kFALSE;
c57f56b7 1699 // check for tag files in the collection
1700 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1701 if (!res) {
1702 msg += " using_tags: No (unknown)";
23329835 1703 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1704 return;
1705 }
1706 const char* typeStr = res->GetKey(0, "origLFN");
1707 if (!typeStr || !strlen(typeStr)) {
1708 msg += " using_tags: No (unknown)";
23329835 1709 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1710 return;
1711 }
1712 TString file = typeStr;
a2f5fc01 1713 useTags = file.Contains(".tag");
1714 if (useTags) msg += " using_tags: Yes";
c57f56b7 1715 else msg += " using_tags: No";
23329835 1716 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1717 return;
1718 }
1719 TString slfn(lfn);
1720 slfn.ToLower();
a2f5fc01 1721 isXml = slfn.Contains(".xml");
1722 if (isXml) {
c57f56b7 1723 // Open xml collection and check if there are tag files inside
1724 msg += " type: xml_collection;";
1725 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1726 if (!coll) {
1727 msg += " using_tags: No (unknown)";
23329835 1728 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1729 return;
1730 }
1731 TMap *map = coll->Next();
1732 if (!map) {
1733 msg += " using_tags: No (unknown)";
23329835 1734 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1735 return;
1736 }
1737 map = (TMap*)map->GetValue("");
1738 TString file;
1739 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
a2f5fc01 1740 useTags = file.Contains(".tag");
c57f56b7 1741 delete coll;
a2f5fc01 1742 if (useTags) msg += " using_tags: Yes";
c57f56b7 1743 else msg += " using_tags: No";
23329835 1744 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1745 return;
1746 }
a2f5fc01 1747 useTags = slfn.Contains(".tag");
c57f56b7 1748 if (slfn.Contains(".root")) msg += " type: root file;";
f866cba5 1749 else msg += " type: unknown file;";
a2f5fc01 1750 if (useTags) msg += " using_tags: Yes";
c57f56b7 1751 else msg += " using_tags: No";
23329835 1752 Info("CheckDataType", "%s", msg.Data());
c57f56b7 1753}
1754
4e5c5506 1755//______________________________________________________________________________
1756void AliAnalysisAlien::EnablePackage(const char *package)
1757{
1758// Enables a par file supposed to exist in the current directory.
1759 TString pkg(package);
1760 pkg.ReplaceAll(".par", "");
1761 pkg += ".par";
1762 if (gSystem->AccessPathName(pkg)) {
ebcdf05e 1763 Fatal("EnablePackage", "Package %s not found", pkg.Data());
4e5c5506 1764 return;
1765 }
1766 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1767 Info("EnablePackage", "AliEn plugin will use .par packages");
1768 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1769 if (!fPackages) {
1770 fPackages = new TObjArray();
1771 fPackages->SetOwner();
1772 }
1773 fPackages->Add(new TObjString(pkg));
1774}
1775
3bdcb562 1776//______________________________________________________________________________
1777TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1778{
1779// Make a tree from files having the location specified in fFileForTestMode.
1780// Inspired from JF's CreateESDChain.
1781 if (fFileForTestMode.IsNull()) {
1782 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1783 return NULL;
1784 }
1785 if (gSystem->AccessPathName(fFileForTestMode)) {
1786 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1787 return NULL;
1788 }
1789 // Open the file
1790 ifstream in;
1791 in.open(fFileForTestMode);
1792 Int_t count = 0;
1793 // Read the input list of files and add them to the chain
1794 TString line;
1795 TChain *chain = new TChain(treeName);
1796 while (in.good())
1797 {
1798 in >> line;
1799 if (line.IsNull()) continue;
1800 if (count++ == fNtestFiles) break;
1801 TString esdFile(line);
1802 TFile *file = TFile::Open(esdFile);
1803 if (file) {
1804 if (!file->IsZombie()) chain->Add(esdFile);
1805 file->Close();
1806 } else {
1807 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1808 }
1809 }
1810 in.close();
1811 if (!chain->GetListOfFiles()->GetEntries()) {
1812 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1813 delete chain;
1814 return NULL;
1815 }
1816// chain->ls();
1817 return chain;
1818}
1819
d2a409b2 1820//______________________________________________________________________________
1821const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1822{
1823// Get job status for all jobs with jobid>jobidstart.
1824 static char mstatus[20];
1825 mstatus[0] = '\0';
1826 nrunning = 0;
1827 nwaiting = 0;
1828 nerror = 0;
1829 ndone = 0;
1830 TGridJobStatusList *list = gGrid->Ps("");
1831 if (!list) return mstatus;
1832 Int_t nentries = list->GetSize();
1833 TGridJobStatus *status;
1834 Int_t pid;
1835 for (Int_t ijob=0; ijob<nentries; ijob++) {
1836 status = (TGridJobStatus *)list->At(ijob);
8ddad121 1837 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
d2a409b2 1838 if (pid<jobidstart) continue;
1839 if (pid == lastid) {
8ddad121 1840 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
d2a409b2 1841 }
1842 switch (status->GetStatus()) {
1843 case TGridJobStatus::kWAITING:
1844 nwaiting++; break;
1845 case TGridJobStatus::kRUNNING:
1846 nrunning++; break;
1847 case TGridJobStatus::kABORTED:
1848 case TGridJobStatus::kFAIL:
1849 case TGridJobStatus::kUNKNOWN:
1850 nerror++; break;
1851 case TGridJobStatus::kDONE:
1852 ndone++;
1853 }
1854 }
1855 list->Delete();
1856 delete list;
1857 return mstatus;
1858}
1859
c57f56b7 1860//______________________________________________________________________________
1861Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1862{
1863// Returns true if file is a collection. Functionality duplicated from
1864// TAlien::Type() because we don't want to directly depend on TAlien.
1865 if (!gGrid) {
1866 Error("IsCollection", "No connection to grid");
1867 return kFALSE;
1868 }
1869 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1870 if (!res) return kFALSE;
1871 const char* typeStr = res->GetKey(0, "type");
1872 if (!typeStr || !strlen(typeStr)) return kFALSE;
1873 if (!strcmp(typeStr, "collection")) return kTRUE;
1874 delete res;
1875 return kFALSE;
1876}
1877
fe2d7fc2 1878//______________________________________________________________________________
1879Bool_t AliAnalysisAlien::IsSingleOutput() const
1880{
1881// Check if single-ouput option is on.
1882 return (!fOutputSingle.IsNull());
1883}
1884
16a4353c 1885//______________________________________________________________________________
1886void AliAnalysisAlien::Print(Option_t *) const
1887{
1888// Print current plugin settings.
84fcd93f 1889 printf("### AliEn analysis plugin current settings ###\n");
d3b18c4c 1890 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1891 if (mgr && mgr->IsProofMode()) {
1892 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1893 if (TestBit(AliAnalysisGrid::kTest))
1894 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1895 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1896 if (!fProofDataSet.IsNull())
1897 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1898 if (fProofReset==1)
1899 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1900 if (fProofReset>1)
1901 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1902 if (!fRootVersionForProof.IsNull())
1903 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1904 else
1905 printf("= ROOT version requested________________________ default\n");
1906 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1907 if (!fAliRootMode.IsNull())
1908 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1909 if (fNproofWorkers)
1910 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1911 if (fNproofWorkersPerSlave)
1912 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1913 if (TestSpecialBit(kClearPackages))
1914 printf("= ClearPackages requested...\n");
1915 if (fIncludePath.Data())
1916 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1917 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1918 if (fPackages && fPackages->GetEntries()) {
1919 TIter next(fPackages);
1920 TObject *obj;
1921 TString list;
1922 while ((obj=next())) list += obj->GetName();
1923 printf("= Par files to be used: ________________________ %s\n", list.Data());
1924 }
1925 if (TestSpecialBit(kProofConnectGrid))
1926 printf("= Requested PROOF connection to grid\n");
1927 return;
1928 }
e1c22e21 1929 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1930 if (fOverwriteMode) {
1931 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1932 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1933 }
348be253 1934 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1935 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
84fcd93f 1936 printf("= Production mode:______________________________ %d\n", fProductionMode);
1937 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1938 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1939 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
16a4353c 1940 if (fUser.Length())
84fcd93f 1941 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1942 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1943 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1944 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1945 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1946 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
16a4353c 1947 if (fRunNumbers.Length())
84fcd93f 1948 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
16a4353c 1949 if (fRunRange[0])
74013535 1950 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
16a4353c 1951 if (!fRunRange[0] && !fRunNumbers.Length()) {
1952 TIter next(fInputFiles);
1953 TObject *obj;
1954 TString list;
1955 while ((obj=next())) list += obj->GetName();
84fcd93f 1956 printf("= Input files to be processed: _________________ %s\n", list.Data());
16a4353c 1957 }
1958 if (TestBit(AliAnalysisGrid::kTest))
84fcd93f 1959 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1960 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1961 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1962 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
d3b18c4c 1963 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
84fcd93f 1964 printf("=====================================================================\n");
1965 printf("= Job price: ___________________________________ %d\n", fPrice);
1966 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1967 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
16a4353c 1968 if (fMaxInitFailed>0)
84fcd93f 1969 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
16a4353c 1970 if (fMasterResubmitThreshold>0)
84fcd93f 1971 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
149d288c 1972 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
319593fb 1973 if (fNrunsPerMaster>0)
84fcd93f 1974 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1975 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
b5b9dee8 1976 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1977 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
16a4353c 1978 if (fArguments.Length())
84fcd93f 1979 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
631c0b05 1980 if (fExecutableArgs.Length())
1981 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
84fcd93f 1982 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1983 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1984 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1985 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
16a4353c 1986 if (fDatasetName)
84fcd93f 1987 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1988 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
16a4353c 1989 if (fIncludePath.Data())
84fcd93f 1990 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
16a4353c 1991 if (fCloseSE.Length())
84fcd93f 1992 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
16a4353c 1993 if (fFriendChainName.Length())
84fcd93f 1994 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
d3b18c4c 1995 if (fPackages && fPackages->GetEntries()) {
16a4353c 1996 TIter next(fPackages);
1997 TObject *obj;
1998 TString list;
1999 while ((obj=next())) list += obj->GetName();
84fcd93f 2000 printf("= Par files to be used: ________________________ %s\n", list.Data());
16a4353c 2001 }
2002}
2003
c57f56b7 2004//______________________________________________________________________________
2005void AliAnalysisAlien::SetDefaults()
2006{
2007// Set default values for everything. What cannot be filled will be left empty.
2008 if (fGridJDL) delete fGridJDL;
2009 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
0f389141 2010 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
c57f56b7 2011 fPrice = 1;
2012 fTTL = 30000;
2013 fSplitMaxInputFileNumber = 100;
2014 fMaxInitFailed = 0;
2015 fMasterResubmitThreshold = 0;
bb885a9e 2016 fNtestFiles = 10;
149d288c 2017 fNreplicas = 2;
a8739e8a 2018 fRunRange[0] = 0;
2019 fRunRange[1] = 0;
8e3bd06a 2020 fRunPrefix = "%d";
319593fb 2021 fNrunsPerMaster = 1;
16a4353c 2022 fMaxMergeFiles = 100;
c57f56b7 2023 fRunNumbers = "";
2024 fExecutable = "analysis.sh";
0a1c1f7f 2025 fExecutableCommand = "root -b -q";
c57f56b7 2026 fArguments = "";
631c0b05 2027 fExecutableArgs = "";
c57f56b7 2028 fAnalysisMacro = "myAnalysis.C";
2029 fAnalysisSource = "";
2030 fAdditionalLibs = "";
2031 fSplitMode = "se";
2032 fAPIVersion = "";
2033 fROOTVersion = "";
2034 fAliROOTVersion = "";
2035 fUser = ""; // Your alien user name
2036 fGridWorkingDir = "";
2037 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2038 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
0df6ccf2 2039 fFriendChainName = "";
c57f56b7 2040 fGridOutputDir = "output";
b83f84f0 2041 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
c57f56b7 2042 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2043 fInputFormat = "xml-single";
2044 fJDLName = "analysis.jdl";
c6cb3634 2045 fJobTag = "Automatically generated analysis JDL";
bb885a9e 2046 fMergeExcludes = "";
0f389141 2047 fMergeViaJDL = 0;
348be253 2048 SetUseCopy(kTRUE);
2049 SetCheckCopy(kTRUE);
149d288c 2050 SetDefaultOutputs(kTRUE);
e1c22e21 2051 fOverwriteMode = 1;
c57f56b7 2052}
2053
0f389141 2054//______________________________________________________________________________
b3e07543 2055Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
0f389141 2056{
b3e07543 2057// Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2058 // First check if the result is already in the output directory.
2059 if (FileExists(Form("%s/%s",aliendir,filename))) {
2060 printf("Final merged results found. Not merging again.\n");
7c2cd90a 2061 return kFALSE;
2062 }
b3e07543 2063 // Now check the last stage done.
2064 Int_t stage = 0;
2065 while (1) {
2066 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2067 stage++;
2068 }
2069 // Next stage of merging
2070 stage++;
2071 TString pattern = "*root_archive.zip";
2072 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2073 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2074 if (res) delete res;
2075 // Write standard output to file
2076 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2077 // Count the number of files inside
2078 ifstream ifile;
2079 ifile.open(Form("Stage_%d.xml",stage));
2080 if (!ifile.good()) {
2081 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
7c2cd90a 2082 return kFALSE;
b3e07543 2083 }
2084 TString line;
2085 Int_t nfiles = 0;
2086 while (!ifile.eof()) {
2087 ifile >> line;
2088 if (line.Contains("/event")) nfiles++;
7c2cd90a 2089 }
b3e07543 2090 ifile.close();
2091 if (!nfiles) {
2092 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2093 return kFALSE;
2094 } else {
2095 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
7ae54d70 2096 }
b3e07543 2097 // Copy the file in the output directory
2098 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2099 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2100 // Check if this is the last stage to be done.
2101 Bool_t laststage = (nfiles<nperchunk);
2102 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2103 if (laststage) {
2104 printf("### Submiting final merging stage %d\n", stage);
2105 TString finalJDL = jdl;
2106 finalJDL.ReplaceAll(".jdl", "_final.jdl");
03335324 2107 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
b3e07543 2108 Int_t jobId = SubmitSingleJob(query);
2109 if (!jobId) return kFALSE;
2110 } else {
2111 printf("### Submiting merging stage %d\n", stage);
03335324 2112 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
b3e07543 2113 Int_t jobId = SubmitSingleJob(query);
2114 if (!jobId) return kFALSE;
7c2cd90a 2115 }
b3e07543 2116 return kTRUE;
2117}
7c2cd90a 2118
105631b5 2119//______________________________________________________________________________
2120AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2121{
2122// Loat the analysis manager from a file.
2123 TFile *file = TFile::Open(fname);
2124 if (!file) {
2125 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2126 return 0;
2127 }
2128 TIter nextkey(file->GetListOfKeys());
2129 AliAnalysisManager *mgr = 0;
2130 TKey *key;
2131 while ((key=(TKey*)nextkey())) {
2132 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2133 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2134 }
2135 if (!mgr)
2136 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2137 return mgr;
2138}
2139
7c2cd90a 2140//______________________________________________________________________________
2141Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2142{
2143// Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2144 if (!gGrid) return 0;
2145 printf("=> %s ------> ",query);
2146 TGridResult *res = gGrid->Command(query);
2147 if (!res) return 0;
2148 TString jobId = res->GetKey(0,"jobId");
2149 delete res;
2150 if (jobId.IsNull()) {
2151 printf("submission failed. Reason:\n");
2152 gGrid->Stdout();
2153 gGrid->Stderr();
2154 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2155 return 0;
2156 }
2157 printf(" Job id: %s\n", jobId.Data());
2158 return atoi(jobId);
2159}
2160
2161//______________________________________________________________________________
b3e07543 2162Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
7c2cd90a 2163{
b3e07543 2164// Merge given output files from basedir. Basedir can be an alien output directory
2165// but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2166// files in a group (ignored for xml input). Merging can be done in stages:
2167// stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2168// stage=1 : works with an xml of all root_archive.zip in the output directory
2169// stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
a2f5fc01 2170 TString outputFile = output;
0f389141 2171 TString command;
a2f5fc01 2172 TString outputChunk;
2173 TString previousChunk = "";
b3e07543 2174 TObjArray *listoffiles = new TObjArray();
2175// listoffiles->SetOwner();
a2f5fc01 2176 Int_t countChunk = 0;
2177 Int_t countZero = nmaxmerge;
0f389141 2178 Bool_t merged = kTRUE;
a2f5fc01 2179 Int_t index = outputFile.Index("@");
2180 if (index > 0) outputFile.Remove(index);
7c2cd90a 2181 TString inputFile = outputFile;
b3e07543 2182 TString sbasedir = basedir;
2183 if (sbasedir.Contains(".xml")) {
2184 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2185 nmaxmerge = 9999999;
2186 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2187 if (!coll) {
2188 ::Error("MergeOutput", "Input XML collection empty.");
2189 return kFALSE;
2190 }
2191 // Iterate grid collection
2192 while (coll->Next()) {
2193 TString fname = gSystem->DirName(coll->GetTURL());
2194 fname += "/";
2195 fname += inputFile;
2196 listoffiles->Add(new TNamed(fname.Data(),""));
2197 }
2198 } else {
2199 command = Form("find %s/ *%s", basedir, inputFile.Data());
2200 printf("command: %s\n", command.Data());
2201 TGridResult *res = gGrid->Command(command);
2202 if (!res) {
2203 ::Error("MergeOutput","No result for the find command\n");
2204 delete listoffiles;
2205 return kFALSE;
2206 }
2207 TIter nextmap(res);
2208 TMap *map = 0;
2209 while ((map=(TMap*)nextmap())) {
2210 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2211 if (!objs || !objs->GetString().Length()) {
2212 // Nothing found - skip this output
2213 delete res;
2214 delete listoffiles;
2215 return kFALSE;
2216 }
2217 listoffiles->Add(new TNamed(objs->GetName(),""));
2218 }
2219 delete res;
2220 }
2221 if (!listoffiles->GetEntries()) {
7c2cd90a 2222 ::Error("MergeOutput","No result for the find command\n");
b3e07543 2223 delete listoffiles;
0f389141 2224 return kFALSE;
2225 }
2226
2227 TFileMerger *fm = 0;
b3e07543 2228 TIter next0(listoffiles);
2229 TObjArray *listoffilestmp = new TObjArray();
2230 listoffilestmp->SetOwner();
2231 TObject *nextfile;
2232 TString snextfile;
2233 // Keep only the files at upper level
2234 Int_t countChar = 0;
2235 while ((nextfile=next0())) {
2236 snextfile = nextfile->GetName();
2237 Int_t crtCount = snextfile.CountChar('/');
2238 if (nextfile == listoffiles->First()) countChar = crtCount;
2239 if (crtCount < countChar) countChar = crtCount;
2240 }
2241 next0.Reset();
2242 while ((nextfile=next0())) {
2243 snextfile = nextfile->GetName();
2244 Int_t crtCount = snextfile.CountChar('/');
2245 if (crtCount > countChar) {
2246 delete nextfile;
2247 continue;
2248 }
2249 listoffilestmp->Add(nextfile);
2250 }
2251 delete listoffiles;
2252 listoffiles = listoffilestmp; // Now contains 'good' files
2253 listoffiles->Print();
2254 TIter next(listoffiles);
7c2cd90a 2255 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
a2f5fc01 2256 outputChunk = outputFile;
2257 outputChunk.ReplaceAll(".root", "_*.root");
0f389141 2258 // Check for existent temporary merge files
e1c22e21 2259 // Check overwrite mode and remove previous partial results if needed
7c2cd90a 2260 // Preserve old merging functionality for stage 0.
2261 if (stage==0) {
2262 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2263 while (1) {
2264 // Skip as many input files as in a chunk
2ea55496 2265 for (Int_t counter=0; counter<nmaxmerge; counter++) {
b3e07543 2266 nextfile = next();
2267 if (!nextfile) {
2ea55496 2268 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
b3e07543 2269 delete listoffiles;
2ea55496 2270 return kFALSE;
2271 }
b3e07543 2272 snextfile = nextfile->GetName();
7c2cd90a 2273 }
2274 outputChunk = outputFile;
2275 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2276 countChunk++;
2277 if (gSystem->AccessPathName(outputChunk)) continue;
2278 // Merged file with chunks up to <countChunk> found
2279 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2280 previousChunk = outputChunk;
2281 break;
2282 }
2283 }
2284 countZero = nmaxmerge;
2285
b3e07543 2286 while ((nextfile=next())) {
2287 snextfile = nextfile->GetName();
2ea55496 2288 // Loop 'find' results and get next LFN
7c2cd90a 2289 if (countZero == nmaxmerge) {
2290 // First file in chunk - create file merger and add previous chunk if any.
2291 fm = new TFileMerger(kFALSE);
2292 fm->SetFastMethod(kTRUE);
2293 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2294 outputChunk = outputFile;
2295 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2296 }
2297 // If last file found, put merged results in the output file
b3e07543 2298 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
7c2cd90a 2299 // Add file to be merged and decrement chunk counter.
b3e07543 2300 fm->AddFile(snextfile);
7c2cd90a 2301 countZero--;
b3e07543 2302 if (countZero==0 || nextfile == listoffiles->Last()) {
7c2cd90a 2303 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2304 // Nothing found - skip this output
2305 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
b3e07543 2306 merged = kFALSE;
2307 break;
7c2cd90a 2308 }
2309 fm->OutputFile(outputChunk);
2310 // Merge the outputs, then go to next chunk
2311 if (!fm->Merge()) {
2312 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
b3e07543 2313 merged = kFALSE;
2314 break;
7c2cd90a 2315 } else {
2316 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2317 gSystem->Unlink(previousChunk);
2318 }
b3e07543 2319 if (nextfile == listoffiles->Last()) break;
7c2cd90a 2320 countChunk++;
2321 countZero = nmaxmerge;
2322 previousChunk = outputChunk;
0f389141 2323 }
0f389141 2324 }
b3e07543 2325 delete listoffiles;
2326 delete fm;
7c2cd90a 2327 return merged;
2328 }
2329 // Merging stage different than 0.
2330 // Move to the begining of the requested chunk.
7c2cd90a 2331 fm = new TFileMerger(kFALSE);
2332 fm->SetFastMethod(kTRUE);
b3e07543 2333 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2334 delete listoffiles;
7c2cd90a 2335 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2336 // Nothing found - skip this output
2337 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2338 delete fm;
2339 return kFALSE;
2340 }
b3e07543 2341 fm->OutputFile(outputFile);
7c2cd90a 2342 // Merge the outputs
2343 if (!fm->Merge()) {
2344 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2345 delete fm;
2346 return kFALSE;
2347 } else {
b3e07543 2348 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
0f389141 2349 }
7c2cd90a 2350 delete fm;
2351 return kTRUE;
0f389141 2352}
2353
c57f56b7 2354//______________________________________________________________________________
2355Bool_t AliAnalysisAlien::MergeOutputs()
2356{
2357// Merge analysis outputs existing in the AliEn space.
2358 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2359 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2360 if (!Connect()) {
2361 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2362 return kFALSE;
0f389141 2363 }
c9e8f7fd 2364 if (fMergeViaJDL) {
2365 if (!TestBit(AliAnalysisGrid::kMerge)) {
2366 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2367 return kFALSE;
2368 }
2369 if (fProductionMode) {
2370 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2371 return kFALSE;
2372 }
0f389141 2373 Info("MergeOutputs", "Submitting merging JDL");
a03be957 2374 if (!SubmitMerging()) return kFALSE;
0f389141 2375 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
c9e8f7fd 2376 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
001cb79e 2377 return kFALSE;
c57f56b7 2378 }
2379 // Get the output path
dc030a24 2380 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
923e2ca5 2381 if (!DirectoryExists(fGridOutputDir)) {
c57f56b7 2382 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2383 return kFALSE;
2384 }
2385 if (!fOutputFiles.Length()) {
2386 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2387 return kFALSE;
0f389141 2388 }
2389 // Check if fast read option was requested
e1c22e21 2390 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2391 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
0f389141 2392 if (fFastReadOption) {
d3339be3 2393 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2394 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
b3e07543 2395 gEnv->SetValue("XNet.ConnectTimeout",50);
2396 gEnv->SetValue("XNet.RequestTimeout",50);
0f389141 2397 gEnv->SetValue("XNet.MaxRedirectCount",2);
b3e07543 2398 gEnv->SetValue("XNet.ReconnectTimeout",50);
0f389141 2399 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
c57f56b7 2400 }
e8b839ab 2401 // Make sure we change the temporary directory
2402 gSystem->Setenv("TMPDIR", gSystem->pwd());
70c52cf3 2403 // Set temporary compilation directory to current one
2404 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
149d288c 2405 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2406 TIter next(list);
2407 TObjString *str;
a2f5fc01 2408 TString outputFile;
c57f56b7 2409 Bool_t merged = kTRUE;
2410 while((str=(TObjString*)next())) {
a2f5fc01 2411 outputFile = str->GetString();
2412 Int_t index = outputFile.Index("@");
2413 if (index > 0) outputFile.Remove(index);
2414 TString outputChunk = outputFile;
2415 outputChunk.ReplaceAll(".root", "_*.root");
319593fb 2416 // Skip already merged outputs
a2f5fc01 2417 if (!gSystem->AccessPathName(outputFile)) {
e1c22e21 2418 if (fOverwriteMode) {
a2f5fc01 2419 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2420 gSystem->Unlink(outputFile);
2421 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2422 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2423 outputChunk.Data());
2424 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2425 }
2426 } else {
a2f5fc01 2427 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
e1c22e21 2428 continue;
2429 }
2430 } else {
a2f5fc01 2431 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
e1c22e21 2432 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
a2f5fc01 2433 outputChunk.Data());
2434 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
e1c22e21 2435 }
2436 }
bb885a9e 2437 if (fMergeExcludes.Length() &&
a2f5fc01 2438 fMergeExcludes.Contains(outputFile.Data())) continue;
16a4353c 2439 // Perform a 'find' command in the output directory, looking for registered outputs
a2f5fc01 2440 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
0f389141 2441 if (!merged) {
2442 Error("MergeOutputs", "Terminate() will NOT be executed");
2443 return kFALSE;
ff07ec61 2444 }
2445 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2446 if (fileOpened) fileOpened->Close();
c57f56b7 2447 }
0f389141 2448 return kTRUE;
c57f56b7 2449}
2450
bb885a9e 2451//______________________________________________________________________________
2452void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2453{
2454// Use the output files connected to output containers from the analysis manager
2455// rather than the files defined by SetOutputFiles
2456 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
205b201f 2457 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
bb885a9e 2458 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2459}
2460
149d288c 2461//______________________________________________________________________________
2462void AliAnalysisAlien::SetOutputFiles(const char *list)
2463{
2464// Manually set the output files list.
2465// Removes duplicates. Not allowed if default outputs are not disabled.
2466 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2467 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2468 return;
2469 }
2470 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2471 fOutputFiles = "";
2472 TString slist = list;
2473 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2474 TObjArray *arr = slist.Tokenize(" ");
2475 TObjString *os;
2476 TIter next(arr);
2477 TString sout;
2478 while ((os=(TObjString*)next())) {
2479 sout = os->GetString();
2480 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2481 if (fOutputFiles.Contains(sout)) continue;
2482 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2483 fOutputFiles += sout;
2484 }
2485 delete arr;
f790bc1b 2486}
149d288c 2487
2488//______________________________________________________________________________
2489void AliAnalysisAlien::SetOutputArchive(const char *list)
2490{
2491// Manually set the output archive list. Free text - you are on your own...
2492// Not allowed if default outputs are not disabled.
2493 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2494 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2495 return;
2496 }
2497 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2498 fOutputArchive = list;
2499}
2500
2501//______________________________________________________________________________
2502void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2503{
2504// Setting a prefered output SE is not allowed anymore.
2505 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2506}
2507
28ce6c9c 2508//______________________________________________________________________________
2509void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2510{
2511// Set some PROOF special parameter.
2512 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2513 if (pair) {
2514 TObject *old = pair->Key();
2515 TObject *val = pair->Value();
2516 fProofParam.Remove(old);
2517 delete old;
2518 delete val;
2519 }
2520 fProofParam.Add(new TObjString(pname), new TObjString(value));
2521}
2522
2523//______________________________________________________________________________
2524const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2525{
2526// Returns a special PROOF parameter.
2527 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2528 if (!pair) return 0;
2529 return pair->Value()->GetName();
2530}
2531
5513444a 2532//______________________________________________________________________________
2533Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
c57f56b7 2534{
2535// Start remote grid analysis.
3bdcb562 2536 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2537 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2538 if (!mgr || !mgr->IsInitialized()) {
2539 Error("StartAnalysis", "You need an initialized analysis manager for this");
2540 return kFALSE;
2541 }
2542 // Are we in PROOF mode ?
2543 if (mgr->IsProofMode()) {
baa34407 2544 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2545 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
3bdcb562 2546 if (fProofCluster.IsNull()) {
2547 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2548 return kFALSE;
2549 }
2550 if (fProofDataSet.IsNull() && !testMode) {
2551 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2552 return kFALSE;
2553 }
2554 // Set the needed environment
2555 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2556 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2557 if (fProofReset && !testMode) {
2558 if (fProofReset==1) {
2559 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2560 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2561 } else {
2562 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2563 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2564 }
2565 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2566 return kFALSE;
2567 }
baa34407 2568
2569 if (!testMode) {
2570 // Check if there is an old active session
2571 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2572 if (nsessions) {
2573 Error("StartAnalysis","You have to reset your old session first\n");
2574 return kFALSE;
2575 }
53911ca6 2576 }
3bdcb562 2577 // Do we need to change the ROOT version ? The success of this cannot be checked.
2578 if (!fRootVersionForProof.IsNull() && !testMode) {
2579 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2580 fProofCluster.Data(), fRootVersionForProof.Data()));
2581 }
2582 // Connect to PROOF and check the status
2583 Long_t proof = 0;
27734f0e 2584 TString sworkers;
2585 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2586 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
3bdcb562 2587 if (!testMode) {
27734f0e 2588 if (!sworkers.IsNull())
2589 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
3bdcb562 2590 else
2591 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2592 } else {
2593 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2594 if (!proof) {
2595 Error("StartAnalysis", "Could not start PROOF in test mode");
2596 return kFALSE;
2597 }
2598 }
2599 if (!proof) {
2600 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2601 return kFALSE;
2602 }
27734f0e 2603 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2604 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
28ce6c9c 2605 // Set proof special parameters if any
2606 TIter nextpp(&fProofParam);
2607 TObject *proofparam;
2608 while ((proofparam=nextpp())) {
2609 TString svalue = GetProofParameter(proofparam->GetName());
2610 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
2611 }
3bdcb562 2612 // Is dataset existing ?
2613 if (!testMode) {
2614 TString dataset = fProofDataSet;
2615 Int_t index = dataset.Index("#");
2616 if (index>=0) dataset.Remove(index);
830acc4c 2617// if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2618// Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2619// return kFALSE;
2620// }
2621// Info("StartAnalysis", "Dataset %s found", dataset.Data());
3bdcb562 2622 }
2623 // Is ClearPackages() needed ?
2624 if (TestSpecialBit(kClearPackages)) {
2625 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2626 gROOT->ProcessLine("gProof->ClearPackages();");
2627 }
2628 // Is a given aliroot mode requested ?
2629 TList optionsList;
1ac846e9 2630 TString parLibs;
830acc4c 2631 if (!fAliRootMode.IsNull()) {
3bdcb562 2632 TString alirootMode = fAliRootMode;
2633 if (alirootMode == "default") alirootMode = "";
2634 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2635 optionsList.SetOwner();
2636 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2637 // Check the additional libs to be loaded
2638 TString extraLibs;
1ac846e9 2639 Bool_t parMode = kFALSE;
3bdcb562 2640 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2641 // Parse the extra libs for .so
2642 if (fAdditionalLibs.Length()) {
2643 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2644 TIter next(list);
2645 TObjString *str;
1ac846e9 2646 while((str=(TObjString*)next())) {
2647 if (str->GetString().Contains(".so")) {
2648 if (parMode) {
2649 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());
2650 break;
2651 }
2652 TString stmp = str->GetName();
2653 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2654 stmp.ReplaceAll(".so","");
2655 if (!extraLibs.IsNull()) extraLibs += ":";
2656 extraLibs += stmp;
2657 continue;
2658 }
2659 if (str->GetString().Contains(".par")) {
2660 // The first par file found in the list will not allow any further .so
2661 parMode = kTRUE;
2662 if (!parLibs.IsNull()) parLibs += ":";
2663 parLibs += str->GetName();
2664 continue;
2665 }
3bdcb562 2666 }
2667 if (list) delete list;
2668 }
dc030a24 2669 if (!extraLibs.IsNull()) {
2670 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
2671 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2672 }
830acc4c 2673 // Check extra includes
2674 if (!fIncludePath.IsNull()) {
2675 TString includePath = fIncludePath;
2676 includePath.ReplaceAll(" ",":");
dc030a24 2677 includePath.ReplaceAll("$ALICE_ROOT/","");
2678 includePath.ReplaceAll("${ALICE_ROOT}/","");
8ddad121 2679 includePath.ReplaceAll("-I","");
dc030a24 2680 includePath.Remove(TString::kTrailing, ':');
830acc4c 2681 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2682 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2683 }
27734f0e 2684 // Check if connection to grid is requested
2685 if (TestSpecialBit(kProofConnectGrid))
2686 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
830acc4c 2687 // Enable AliRoot par
2688 if (testMode) {
2689 // Enable proof lite package
2690 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2691 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2692 TNamed *obj = (TNamed*)optionsList.At(i);
2693 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2694 }
2695 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
8ddad121 2696 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
830acc4c 2697 Info("StartAnalysis", "AliRootProofLite enabled");
2698 } else {
2699 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2700 return kFALSE;
2701 }
2702 } else {
dc030a24 2703 if ( ! fAliROOTVersion.IsNull() ) {
2704 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2705 fAliROOTVersion.Data(), &optionsList))) {
2706 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2707 return kFALSE;
2708 }
2709 }
27734f0e 2710 }
1ac846e9 2711 // Enable first par files from fAdditionalLibs
2712 if (!parLibs.IsNull()) {
2713 TObjArray *list = parLibs.Tokenize(":");
2714 TIter next(list);
2715 TObjString *package;
2716 while((package=(TObjString*)next())) {
40501bb7 2717 TString spkg = package->GetName();
2718 spkg.ReplaceAll(".par", "");
2719 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
b50a41c3 2720 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
4f136f18 2721 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2722 if (gROOT->ProcessLine(enablePackage)) {
1ac846e9 2723 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2724 return kFALSE;
2725 }
2726 } else {
2727 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2728 return kFALSE;
2729 }
2730 }
2731 if (list) delete list;
2732 }
3bdcb562 2733 } else {
2734 if (fAdditionalLibs.Contains(".so") && !testMode) {
2735 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2736 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2737 return kFALSE;
2738 }
2739 }
2740 // Enable par files if requested
2741 if (fPackages && fPackages->GetEntries()) {
2742 TIter next(fPackages);
2743 TObject *package;
2744 while ((package=next())) {
1ac846e9 2745 // Skip packages already enabled
2746 if (parLibs.Contains(package->GetName())) continue;
40501bb7 2747 TString spkg = package->GetName();
2748 spkg.ReplaceAll(".par", "");
2749 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
dc030a24 2750 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
27734f0e 2751 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
3bdcb562 2752 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2753 return kFALSE;
2754 }
2755 } else {
2756 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2757 return kFALSE;
2758 }
2759 }
2760 }
2761 // Do we need to load analysis source files ?
2762 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2763 if (fAnalysisSource.Length()) {
2764 TObjArray *list = fAnalysisSource.Tokenize(" ");
2765 TIter next(list);
2766 TObjString *str;
2767 while((str=(TObjString*)next())) {
2768 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
dc030a24 2769 }
3bdcb562 2770 if (list) delete list;
2771 }
830acc4c 2772 if (testMode) {
2773 // Register dataset to proof lite.
2774 if (fFileForTestMode.IsNull()) {
2775 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2776 return kFALSE;
2777 }
2778 if (gSystem->AccessPathName(fFileForTestMode)) {
2779 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2780 return kFALSE;
2781 }
2782 TFileCollection *coll = new TFileCollection();
2783 coll->AddFromFile(fFileForTestMode);
8ddad121 2784 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
27734f0e 2785 gROOT->ProcessLine("gProof->ShowDataSets()");
830acc4c 2786 }
3bdcb562 2787 return kTRUE;
2788 }
c57f56b7 2789
43da816a 2790 // Check if output files have to be taken from the analysis manager
2791 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
f790bc1b 2792 // Add output files and AOD files
2793 fOutputFiles = GetListOfFiles("outaod");
c07b9ce2 2794 // Add extra files registered to the analysis manager
f790bc1b 2795 TString extra = GetListOfFiles("ext");
2796 if (!extra.IsNull()) {
149d288c 2797 extra.ReplaceAll(".root", "*.root");
f790bc1b 2798 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
149d288c 2799 fOutputFiles += extra;
84fcd93f 2800 }
149d288c 2801 // Compose the output archive.
b83f84f0 2802 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2803 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
43da816a 2804 }
f7b1cbc2 2805// if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
c57f56b7 2806 if (TestBit(AliAnalysisGrid::kOffline)) {
2807 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2808 \n there nor any job run. You can revise the JDL and analysis \
2809 \n macro then run the same in \"submit\" mode.");
2810 } else if (TestBit(AliAnalysisGrid::kTest)) {
2811 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2812 \n dataset.");
2813 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2814 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2815 \n space and job submitted.");
2816 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2817 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
0f389141 2818 if (fMergeViaJDL) CheckInputData();
5513444a 2819 return kTRUE;
c57f56b7 2820 } else {
2821 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2822 }
2823
348be253 2824 Print();
c57f56b7 2825 if (!Connect()) {
2826 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
5513444a 2827 return kFALSE;
16a4353c 2828 }
d3b18c4c 2829 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
c57f56b7 2830 if (!CheckInputData()) {
2831 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
5513444a 2832 return kFALSE;
c57f56b7 2833 }
d3339be3 2834 if (!CreateDataset(fDataPattern)) {
2835 TString serror;
2836 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2837 if (fRunNumbers.Length()) serror = "run numbers";
2838 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2839 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2840 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2841 return kFALSE;
2842 }
c57f56b7 2843 WriteAnalysisFile();
2844 WriteAnalysisMacro();
2845 WriteExecutable();
2846 WriteValidationScript();
0f389141 2847 if (fMergeViaJDL) {
2848 WriteMergingMacro();
2849 WriteMergeExecutable();
2850 WriteValidationScript(kTRUE);
2851 }
5513444a 2852 if (!CreateJDL()) return kFALSE;
2853 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
3bdcb562 2854 if (testMode) {
c57f56b7 2855 // Locally testing the analysis
2856 Info("StartAnalysis", "\n_______________________________________________________________________ \
2857 \n Running analysis script in a daughter shell as on a worker node \
2858 \n_______________________________________________________________________");
149d288c 2859 TObjArray *list = fOutputFiles.Tokenize(",");
c57f56b7 2860 TIter next(list);
2861 TObjString *str;
a2f5fc01 2862 TString outputFile;
c57f56b7 2863 while((str=(TObjString*)next())) {
a2f5fc01 2864 outputFile = str->GetString();
2865 Int_t index = outputFile.Index("@");
2866 if (index > 0) outputFile.Remove(index);
2867 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
c57f56b7 2868 }
2869 delete list;
2870 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
f50e4bc8 2871 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
c57f56b7 2872// gSystem->Exec("cat stdout");
5513444a 2873 return kFALSE;
c57f56b7 2874 }
5513444a 2875 // Check if submitting is managed by LPM manager
a3e84053 2876 if (fProductionMode) {
5513444a 2877 TString prodfile = fJDLName;
2878 prodfile.ReplaceAll(".jdl", ".prod");
2879 WriteProductionFile(prodfile);
2880 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2881 return kFALSE;
2882 }
a8739e8a 2883 // Submit AliEn job(s)
d2a409b2 2884 gGrid->Cd(fGridOutputDir);
a8739e8a 2885 TGridResult *res;
c57f56b7 2886 TString jobID = "";
d2a409b2 2887 if (!fRunNumbers.Length() && !fRunRange[0]) {
dd74a515 2888 // Submit a given xml or a set of runs
a8739e8a 2889 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
84fcd93f 2890 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
a8739e8a 2891 if (res) {
2892 const char *cjobId = res->GetKey(0,"jobId");
2893 if (!cjobId) {
a03be957 2894 gGrid->Stdout();
2895 gGrid->Stderr();
a8739e8a 2896 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
5513444a 2897 return kFALSE;
a8739e8a 2898 } else {
2899 Info("StartAnalysis", "\n_______________________________________________________________________ \
2900 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2901 \n_______________________________________________________________________",
2902 fJDLName.Data(), cjobId);
2903 jobID = cjobId;
2904 }
2905 delete res;
a03be957 2906 } else {
2907 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2908 return kFALSE;
a8739e8a 2909 }
2910 } else {
d2a409b2 2911 // Submit for a range of enumeration of runs.
a03be957 2912 if (!Submit()) return kFALSE;
c57f56b7 2913 }
a8739e8a 2914
c57f56b7 2915 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2916 \n You may exit at any time and terminate the job later using the option <terminate> \
2917 \n ##################################################################################", jobID.Data());
bb885a9e 2918 gSystem->Exec("aliensh");
5513444a 2919 return kTRUE;
c57f56b7 2920}
2921
f790bc1b 2922//______________________________________________________________________________
2923const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2924{
2925// Get a comma-separated list of output files of the requested type.
2926// Type can be (case unsensitive):
2927// aod - list of aod files (std, extensions and filters)
2928// out - list of output files connected to containers (but not aod's or extras)
2929// ext - list of extra files registered to the manager
2930// ter - list of files produced in terminate
2931 static TString files;
2932 files = "";
2933 TString stype = type;
2934 stype.ToLower();
2935 TString aodfiles, extra;
2936 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2937 if (!mgr) {
2938 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2939 return files.Data();
2940 }
2941 if (mgr->GetOutputEventHandler()) {
2942 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2943 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2944 if (!extraaod.IsNull()) {
2945 aodfiles += ",";
2946 aodfiles += extraaod;
2947 }
2948 }
2949 if (stype.Contains("aod")) {
2950 files = aodfiles;
2951 if (stype == "aod") return files.Data();
2952 }
2953 // Add output files that are not in the list of AOD files
2954 TString outputfiles = "";
2955 TIter next(mgr->GetOutputs());
2956 AliAnalysisDataContainer *output;
2957 const char *filename = 0;
2958 while ((output=(AliAnalysisDataContainer*)next())) {
2959 filename = output->GetFileName();
2960 if (!(strcmp(filename, "default"))) continue;
2961 if (outputfiles.Contains(filename)) continue;
2962 if (aodfiles.Contains(filename)) continue;
2963 if (!outputfiles.IsNull()) outputfiles += ",";
2964 outputfiles += filename;
2965 }
2966 if (stype.Contains("out")) {
2967 if (!files.IsNull()) files += ",";
2968 files += outputfiles;
2969 if (stype == "out") return files.Data();
2970 }
2971 // Add extra files registered to the analysis manager
2972 TString sextra;
2973 extra = mgr->GetExtraFiles();
2974 if (!extra.IsNull()) {
2975 extra.Strip();
2976 extra.ReplaceAll(" ", ",");
2977 TObjArray *fextra = extra.Tokenize(",");
2978 TIter nextx(fextra);
2979 TObject *obj;
2980 while ((obj=nextx())) {
2981 if (aodfiles.Contains(obj->GetName())) continue;
2982 if (outputfiles.Contains(obj->GetName())) continue;
2983 if (sextra.Contains(obj->GetName())) continue;
2984 if (!sextra.IsNull()) sextra += ",";
2985 sextra += obj->GetName();
2986 }
2987 delete fextra;
2988 if (stype.Contains("ext")) {
2989 if (!files.IsNull()) files += ",";
2990 files += sextra;
2991 }
2992 }
2993 if (stype == "ext") return files.Data();
2994 TString termfiles;
2995 if (!fTerminateFiles.IsNull()) {
2996 fTerminateFiles.Strip();
2997 fTerminateFiles.ReplaceAll(" ",",");
9c939f2b 2998 TObjArray *fextra = fTerminateFiles.Tokenize(",");
f790bc1b 2999 TIter nextx(fextra);
3000 TObject *obj;
3001 while ((obj=nextx())) {
3002 if (aodfiles.Contains(obj->GetName())) continue;
3003 if (outputfiles.Contains(obj->GetName())) continue;
3004 if (termfiles.Contains(obj->GetName())) continue;
3005 if (sextra.Contains(obj->GetName())) continue;
3006 if (!termfiles.IsNull()) termfiles += ",";
3007 termfiles += obj->GetName();
3008 }
3009 delete fextra;
3010 }
3011 if (stype.Contains("ter")) {
3012 if (!files.IsNull() && !termfiles.IsNull()) {
3013 files += ",";
3014 files += termfiles;
3015 }
3016 }
3017 return files.Data();
3018}
3019
d2a409b2 3020//______________________________________________________________________________
a03be957 3021Bool_t AliAnalysisAlien::Submit()
d2a409b2 3022{
3023// Submit all master jobs.
3024 Int_t nmasterjobs = fInputFiles->GetEntries();
3025 Long_t tshoot = gSystem->Now();
a03be957 3026 if (!fNsubmitted && !SubmitNext()) return kFALSE;
d2a409b2 3027 while (fNsubmitted < nmasterjobs) {
3028 Long_t now = gSystem->Now();
3029 if ((now-tshoot)>30000) {
3030 tshoot = now;
a03be957 3031 if (!SubmitNext()) return kFALSE;
d2a409b2 3032 }
3033 }
a03be957 3034 return kTRUE;
d2a409b2 3035}
3036
0f389141 3037//______________________________________________________________________________
a03be957 3038Bool_t AliAnalysisAlien::SubmitMerging()
0f389141 3039{
3040// Submit all merging jobs.
dc030a24 3041 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
0f389141 3042 gGrid->Cd(fGridOutputDir);
3043 TString mergeJDLName = fExecutable;
3044 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
9f020952 3045 if (!fInputFiles) {
3046 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3047 return kFALSE;
3048 }
0f389141 3049 Int_t ntosubmit = fInputFiles->GetEntries();
0f389141 3050 for (Int_t i=0; i<ntosubmit; i++) {
f866cba5 3051 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3052 runOutDir.ReplaceAll(".xml", "");
7c2cd90a 3053 if (fOutputToRunNo) {
3054 // The output directory is the run number
3055 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3056 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3057 } else {
17b4e9a4 3058 if (!fRunNumbers.Length() && !fRunRange[0]) {
3059 // The output directory is the grid outdir
3060 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3061 runOutDir = fGridOutputDir;
3062 } else {
3063 // The output directory is the master number in 3 digits format
3064 printf("### Submitting merging job for master <%03d>\n", i);
3065 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3066 }
7c2cd90a 3067 }
3068 // Check now the number of merging stages.
2b222f7c 3069 TObjArray *list = fOutputFiles.Tokenize(",");
3070 TIter next(list);
3071 TObjString *str;
3072 TString outputFile;
3073 while((str=(TObjString*)next())) {
3074 outputFile = str->GetString();
3075 Int_t index = outputFile.Index("@");
3076 if (index > 0) outputFile.Remove(index);
3077 if (!fMergeExcludes.Contains(outputFile)) break;
3078 }
3079 delete list;
b3e07543 3080 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
1d0b4d65 3081 if (!done && (i==ntosubmit-1)) return kFALSE;
17b4e9a4 3082 if (!fRunNumbers.Length() && !fRunRange[0]) break;
0f389141 3083 }
a03be957 3084 if (!ntosubmit) return kTRUE;
9f020952 3085 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3086 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3087 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3088 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3089 \n ################################################################################################################");
0f389141 3090 gSystem->Exec("aliensh");
a03be957 3091 return kTRUE;
0f389141 3092}
3093
d2a409b2 3094//______________________________________________________________________________
a03be957 3095Bool_t AliAnalysisAlien::SubmitNext()
d2a409b2 3096{
08d5b699 3097// Submit next bunch of master jobs if the queue is free. The first master job is
3098// submitted right away, while the next will not be unless the previous was split.
3099// The plugin will not submit new master jobs if there are more that 500 jobs in
3100// waiting phase.
d2a409b2 3101 static Bool_t iscalled = kFALSE;
3102 static Int_t firstmaster = 0;
3103 static Int_t lastmaster = 0;
3104 static Int_t npermaster = 0;
a03be957 3105 if (iscalled) return kTRUE;
d2a409b2 3106 iscalled = kTRUE;
3107 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3108 Int_t ntosubmit = 0;
3109 TGridResult *res;
3110 TString jobID = "";
3bdcb562 3111 Int_t nmasterjobs = fInputFiles->GetEntries();
3112 if (!fNsubmitted) {
3113 ntosubmit = 1;
3114 if (!IsUseSubmitPolicy()) {
90d50a8c 3115 if (nmasterjobs>5)
3bdcb562 3116 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3117 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3118 ntosubmit = nmasterjobs;
3119 }
3120 } else {
d2a409b2 3121 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
84fcd93f 3122 printf("=== master %d: %s\n", lastmaster, status.Data());
d2a409b2 3123 // If last master not split, just return
a03be957 3124 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
d2a409b2 3125 // No more than 100 waiting jobs
08d5b699 3126 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
d2a409b2 3127 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
08d5b699 3128 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
7586eedc 3129 if (!ntosubmit) ntosubmit = 1;
84fcd93f 3130 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
d2a409b2 3131 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3132 }
d2a409b2 3133 for (Int_t i=0; i<ntosubmit; i++) {
3134 // Submit for a range of enumeration of runs.
a03be957 3135 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
d2a409b2 3136 TString query;
cd11251e 3137 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3138 runOutDir.ReplaceAll(".xml", "");
3139 if (fOutputToRunNo)
3140 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3141 else
3142 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
84fcd93f 3143 printf("********* %s\n",query.Data());
d2a409b2 3144 res = gGrid->Command(query);
3145 if (res) {
98ca124f 3146 TString cjobId1 = res->GetKey(0,"jobId");
3147 if (!cjobId1.Length()) {
d2a409b2 3148 iscalled = kFALSE;
a03be957 3149 gGrid->Stdout();
3150 gGrid->Stderr();
3151 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3152 return kFALSE;
d2a409b2 3153 } else {
3154 Info("StartAnalysis", "\n_______________________________________________________________________ \
3155 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3156 \n_______________________________________________________________________",
98ca124f 3157 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
d2a409b2 3158 jobID += cjobId1;
3159 jobID += " ";
98ca124f 3160 lastmaster = cjobId1.Atoi();
d2a409b2 3161 if (!firstmaster) firstmaster = lastmaster;
3162 fNsubmitted++;
3163 }
3164 delete res;
a03be957 3165 } else {
3166 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3167 return kFALSE;
d2a409b2 3168 }
3169 }
3170 iscalled = kFALSE;
a03be957 3171 return kTRUE;
d2a409b2 3172}
3173
c57f56b7 3174//______________________________________________________________________________
3175void AliAnalysisAlien::WriteAnalysisFile()
3176{
f10e8481 3177// Write current analysis manager into the file <analysisFile>
3178 TString analysisFile = fExecutable;
3179 analysisFile.ReplaceAll(".sh", ".root");
c57f56b7 3180 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3181 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3182 if (!mgr || !mgr->IsInitialized()) {
3183 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3184 return;
3185 }
3186 // Check analysis type
3187 TObject *handler;
3188 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3189 handler = (TObject*)mgr->GetInputEventHandler();
3190 if (handler) {
65eb22f8 3191 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3192 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3193 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3194 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3195 } else {
3196 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3197 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3198 }
c57f56b7 3199 }
3200 TDirectory *cdir = gDirectory;
f10e8481 3201 TFile *file = TFile::Open(analysisFile, "RECREATE");
c57f56b7 3202 if (file) {
e16a394c 3203 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3204 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
fe2d7fc2 3205 // Unless merging makes no sense
3206 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
c57f56b7 3207 mgr->Write();
3208 delete file;
fe2d7fc2 3209 // Enable termination for local jobs
3210 mgr->SetSkipTerminate(kFALSE);
c57f56b7 3211 }
3212 if (cdir) cdir->cd();
f10e8481 3213 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
c57f56b7 3214 }
3215 Bool_t copy = kTRUE;
d3b18c4c 3216 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3217 if (copy) {
3218 CdWork();
3219 TString workdir = gGrid->GetHomeDirectory();
3220 workdir += fGridWorkingDir;
d3b18c4c 3221 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
f10e8481 3222 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3223 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
c57f56b7 3224 }
3225}
3226
3227//______________________________________________________________________________
3228void AliAnalysisAlien::WriteAnalysisMacro()
3229{
3230// Write the analysis macro that will steer the analysis in grid mode.
3231 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3232 ofstream out;
3233 out.open(fAnalysisMacro.Data(), ios::out);
3234 if (!out.good()) {
3235 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3236 return;
3237 }
5b273635 3238 Bool_t hasSTEERBase = kFALSE;
3239 Bool_t hasESD = kFALSE;
3240 Bool_t hasAOD = kFALSE;
3241 Bool_t hasANALYSIS = kFALSE;
7ea40ac8 3242 Bool_t hasOADB = kFALSE;
5b273635 3243 Bool_t hasANALYSISalice = kFALSE;
3244 Bool_t hasCORRFW = kFALSE;
c57f56b7 3245 TString func = fAnalysisMacro;
3246 TString type = "ESD";
3247 TString comment = "// Analysis using ";
c85cfc0f 3248 if (IsUseMCchain()) {
3249 type = "MC";
3250 comment += "MC";
3251 } else {
3252 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3253 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3254 type = "AOD";
3255 comment += "AOD";
3256 }
3257 }
0df6ccf2 3258 if (type!="AOD" && fFriendChainName!="") {
3259 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3260 return;
3261 }
c57f56b7 3262 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3263 else comment += " data";
3264 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3265 func.ReplaceAll(".C", "");
3266 out << "void " << func.Data() << "()" << endl;
3267 out << "{" << endl;
3268 out << comment.Data() << endl;
3269 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
f7498086 3270 out << " TStopwatch timer;" << endl;
3271 out << " timer.Start();" << endl << endl;
13f0c00b 3272 // Change temp directory to current one
3273 out << "// Set temporary merging directory to current one" << endl;
3274 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
70c52cf3 3275 out << "// Set temporary compilation directory to current one" << endl;
3276 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
b3e07543 3277 // Reset existing include path
3278 out << "// Reset existing include path and add current directory first in the search" << endl;
3279 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
f790bc1b 3280 if (!fExecutableCommand.Contains("aliroot")) {
3281 out << "// load base root libraries" << endl;
3282 out << " gSystem->Load(\"libTree\");" << endl;
3283 out << " gSystem->Load(\"libGeom\");" << endl;
3284 out << " gSystem->Load(\"libVMC\");" << endl;
3285 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3286 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3287 }
d5c6455a 3288 if (fAdditionalRootLibs.Length()) {
47a4137d 3289 // in principle libtree /lib geom libvmc etc. can go into this list, too
3290 out << "// Add aditional libraries" << endl;
3291 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3292 TIter next(list);
3293 TObjString *str;
3294 while((str=(TObjString*)next())) {
3295 if (str->GetString().Contains(".so"))
3296 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
d5c6455a 3297 }
47a4137d 3298 if (list) delete list;
d5c6455a 3299 }
57377eb5 3300 out << "// Load analysis framework libraries" << endl;
652561d5 3301 TString setupPar = "AliAnalysisAlien::SetupPar";
4e5c5506 3302 if (!fPackages) {
f790bc1b 3303 if (!fExecutableCommand.Contains("aliroot")) {
3304 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3305 out << " gSystem->Load(\"libESD\");" << endl;
3306 out << " gSystem->Load(\"libAOD\");" << endl;
3307 }
4e5c5506 3308 out << " gSystem->Load(\"libANALYSIS\");" << endl;
7ea40ac8 3309 out << " gSystem->Load(\"libOADB\");" << endl;
57377eb5 3310 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3311 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
4e5c5506 3312 } else {
4e5c5506 3313 TIter next(fPackages);
3314 TObject *obj;
57377eb5 3315 TString pkgname;
57377eb5 3316 while ((obj=next())) {
3317 pkgname = obj->GetName();
4478e6f1 3318 if (pkgname == "STEERBase" ||
3319 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3320 if (pkgname == "ESD" ||
3321 pkgname == "ESD.par") hasESD = kTRUE;
3322 if (pkgname == "AOD" ||
3323 pkgname == "AOD.par") hasAOD = kTRUE;
3324 if (pkgname == "ANALYSIS" ||
3325 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
7ea40ac8 3326 if (pkgname == "OADB" ||
3327 pkgname == "OADB.par") hasOADB = kTRUE;
4478e6f1 3328 if (pkgname == "ANALYSISalice" ||
3329 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3330 if (pkgname == "CORRFW" ||
3331 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
5b273635 3332 }
3333 if (hasANALYSISalice) setupPar = "SetupPar";
57377eb5 3334 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3335 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
57377eb5 3336 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3337 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
57377eb5 3338 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3339 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
57377eb5 3340 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3341 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
7ea40ac8 3342 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3343 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
57377eb5 3344 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3345 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
57377eb5 3346 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3347 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
57377eb5 3348 out << "// Compile other par packages" << endl;
3349 next.Reset();
fcc9bb6f 3350 while ((obj=next())) {
3351 pkgname = obj->GetName();
4478e6f1 3352 if (pkgname == "STEERBase" ||
3353 pkgname == "STEERBase.par" ||
3354 pkgname == "ESD" ||
3355 pkgname == "ESD.par" ||
3356 pkgname == "AOD" ||
3357 pkgname == "AOD.par" ||
3358 pkgname == "ANALYSIS" ||
3359 pkgname == "ANALYSIS.par" ||
7ea40ac8 3360 pkgname == "OADB" ||
3361 pkgname == "OADB.par" ||
4478e6f1 3362 pkgname == "ANALYSISalice" ||
3363 pkgname == "ANALYSISalice.par" ||
3364 pkgname == "CORRFW" ||
3365 pkgname == "CORRFW.par") continue;
5b273635 3366 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
fcc9bb6f 3367 }
4e5c5506 3368 }
b3e07543 3369 out << "// include path" << endl;
3370 // Get the include path from the interpreter and remove entries pointing to AliRoot
3371 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3372 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3373 out << " TIter nextpath(listpaths);" << endl;
3374 out << " TObjString *pname;" << endl;
3375 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3376 out << " TString current = pname->GetName();" << endl;
3377 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3378 out << " gSystem->AddIncludePath(current);" << endl;
3379 out << " }" << endl;
3380 out << " if (listpaths) delete listpaths;" << endl;
3381 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3382 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3383 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
6da75e0b 3384 if (fAdditionalLibs.Length()) {
3385 out << "// Add aditional AliRoot libraries" << endl;
3386 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3387 TIter next(list);
3388 TObjString *str;
3389 while((str=(TObjString*)next())) {
3390 if (str->GetString().Contains(".so"))
3391 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
652561d5 3392 if (str->GetString().Contains(".par"))
3393 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
6da75e0b 3394 }
3395 if (list) delete list;
3396 }
3397 out << endl;
c57f56b7 3398 out << "// analysis source to be compiled at runtime (if any)" << endl;
3399 if (fAnalysisSource.Length()) {
3400 TObjArray *list = fAnalysisSource.Tokenize(" ");
3401 TIter next(list);
3402 TObjString *str;
3403 while((str=(TObjString*)next())) {
3404 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3405 }
3406 if (list) delete list;
3407 }
3408 out << endl;
b3e07543 3409// out << " printf(\"Currently load libraries:\\n\");" << endl;
3410// out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
0f389141 3411 if (fFastReadOption) {
d3339be3 3412 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 !!! \
3413 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
0f389141 3414 out << "// fast xrootd reading enabled" << endl;
3415 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 3416 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3417 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
0f389141 3418 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
b3e07543 3419 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
0f389141 3420 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3421 }
c57f56b7 3422 out << "// connect to AliEn and make the chain" << endl;
3423 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
c57f56b7 3424 out << "// read the analysis manager from file" << endl;
f10e8481 3425 TString analysisFile = fExecutable;
3426 analysisFile.ReplaceAll(".sh", ".root");
105631b5 3427 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3428 << analysisFile << "\");" << endl;
3429 out << " if (!mgr) return;" << endl;
c57f56b7 3430 out << " mgr->PrintStatus();" << endl;
52b6a92b 3431 if (AliAnalysisManager::GetAnalysisManager()) {
f866cba5 3432 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
52b6a92b 3433 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
de52b69c 3434 } else {
9a8288ff 3435 if (TestBit(AliAnalysisGrid::kTest))
3436 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3437 else
3438 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
52b6a92b 3439 }
3440 }
242accb2 3441 if (IsUsingTags()) {
3442 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3443 } else {
3444 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3445 }
c57f56b7 3446 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
f7498086 3447 out << " timer.Stop();" << endl;
3448 out << " timer.Print();" << endl;
c57f56b7 3449 out << "}" << endl << endl;
3450 if (IsUsingTags()) {
3451 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3452 out << "{" << endl;
3453 out << "// Create a chain using tags from the xml file." << endl;
3454 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3455 out << " if (!coll) {" << endl;
3456 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3457 out << " return NULL;" << endl;
3458 out << " }" << endl;
3459 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3460 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3461 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3462 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3463 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3464 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3465 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3466 out << " // Check if the cuts configuration file was provided" << endl;
3467 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3468 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3469 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3470 out << " }" << endl;
0df6ccf2 3471 if (fFriendChainName=="") {
3472 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3473 } else {
3474 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3475 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3476 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3477 }
c57f56b7 3478 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3479 out << " chain->ls();" << endl;
3480 out << " return chain;" << endl;
fcc9bb6f 3481 out << "}" << endl << endl;
c57f56b7 3482 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3483 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3484 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3485 msg += " AliLHCTagCuts *lhcCuts,\n";
3486 msg += " AliDetectorTagCuts *detCuts,\n";
3487 msg += " AliEventTagCuts *evCuts)";
23329835 3488 Info("WriteAnalysisMacro", "%s", msg.Data());
c57f56b7 3489 }
0df6ccf2 3490 }
3491 if (!IsUsingTags() || fFriendChainName!="") {
fcc9bb6f 3492 out <<"//________________________________________________________________________________" << endl;
c57f56b7 3493 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3494 out << "{" << endl;
3495 out << "// Create a chain using url's from xml file" << endl;
242accb2 3496 out << " TString filename;" << endl;
3497 out << " Int_t run = 0;" << endl;
c85cfc0f 3498 if (IsUseMCchain()) {
3499 out << " TString treename = \"TE\";" << endl;
3500 } else {
3501 out << " TString treename = type;" << endl;
3502 out << " treename.ToLower();" << endl;
3503 out << " treename += \"Tree\";" << endl;
3504 }
e02fee64 3505 out << " printf(\"***************************************\\n\");" << endl;
3506 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3507 out << " printf(\"***************************************\\n\");" << endl;
c57f56b7 3508 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3509 out << " if (!coll) {" << endl;
3510 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3511 out << " return NULL;" << endl;
3512 out << " }" << endl;
242accb2 3513 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
c57f56b7 3514 out << " TChain *chain = new TChain(treename);" << endl;
0df6ccf2 3515 if(fFriendChainName!="") {
3516 out << " TChain *chainFriend = new TChain(treename);" << endl;
3517 }
c57f56b7 3518 out << " coll->Reset();" << endl;
0df6ccf2 3519 out << " while (coll->Next()) {" << endl;
242accb2 3520 out << " filename = coll->GetTURL("");" << endl;
3521 out << " if (mgr) {" << endl;
3522 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3523 out << " if (nrun && nrun != run) {" << endl;
3524 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3525 out << " mgr->SetRunFromPath(nrun);" << endl;
3526 out << " run = nrun;" << endl;
3527 out << " }" << endl;
3528 out << " }" << endl;
3529 out << " chain->Add(filename);" << endl;
0df6ccf2 3530 if(fFriendChainName!="") {
3531 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3532 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3533 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3534 out << " chainFriend->Add(fileFriend.Data());" << endl;
3535 }
3536 out << " }" << endl;
c57f56b7 3537 out << " if (!chain->GetNtrees()) {" << endl;
3538 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3539 out << " return NULL;" << endl;
3540 out << " }" << endl;
0df6ccf2 3541 if(fFriendChainName!="") {
3542 out << " chain->AddFriend(chainFriend);" << endl;
3543 }
c57f56b7 3544 out << " return chain;" << endl;
fcc9bb6f 3545 out << "}" << endl << endl;
c57f56b7 3546 }
5b273635 3547 if (hasANALYSISalice) {
3548 out <<"//________________________________________________________________________________" << endl;
3549 out << "Bool_t SetupPar(const char *package) {" << endl;
3550 out << "// Compile the package and set it up." << endl;
3551 out << " TString pkgdir = package;" << endl;
3552 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
b50a41c3 3553 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
5b273635 3554 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3555 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3556 out << " // Check for BUILD.sh and execute" << endl;
3557 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3558 out << " printf(\"*******************************\\n\");" << endl;
3559 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3560 out << " printf(\"*******************************\\n\");" << endl;
3561 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3562 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3563 out << " gSystem->ChangeDirectory(cdir);" << endl;
3564 out << " return kFALSE;" << endl;
3565 out << " }" << endl;
3566 out << " } else {" << endl;
3567 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3568 out << " gSystem->ChangeDirectory(cdir);" << endl;
3569 out << " return kFALSE;" << endl;
3570 out << " }" << endl;
3571 out << " // Check for SETUP.C and execute" << endl;
3572 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3573 out << " printf(\"*******************************\\n\");" << endl;
3574 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3575 out << " printf(\"*******************************\\n\");" << endl;
3576 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3577 out << " } else {" << endl;
3578 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3579 out << " gSystem->ChangeDirectory(cdir);" << endl;
3580 out << " return kFALSE;" << endl;
3581 out << " }" << endl;
3582 out << " // Restore original workdir" << endl;
3583 out << " gSystem->ChangeDirectory(cdir);" << endl;
3584 out << " return kTRUE;" << endl;
3585 out << "}" << endl;
3586 }
c57f56b7 3587 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3588 }
3589 Bool_t copy = kTRUE;
d3b18c4c 3590 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3591 if (copy) {
3592 CdWork();
3593 TString workdir = gGrid->GetHomeDirectory();
3594 workdir += fGridWorkingDir;
3595 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3596 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3597 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3598 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3599 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3600 }
3601 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3602 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3603 }
3604}
3605
0f389141 3606//______________________________________________________________________________
3607void AliAnalysisAlien::WriteMergingMacro()
3608{
3609// Write a macro to merge the outputs per master job.
3610 if (!fMergeViaJDL) return;
3611 if (!fOutputFiles.Length()) {
3612 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3613 return;
3614 }
3615 TString mergingMacro = fExecutable;
3616 mergingMacro.ReplaceAll(".sh","_merge.C");
dc030a24 3617 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
0f389141 3618 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3619 ofstream out;
3620 out.open(mergingMacro.Data(), ios::out);
3621 if (!out.good()) {
3622 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3623 return;
3624 }
5b273635 3625 Bool_t hasSTEERBase = kFALSE;
3626 Bool_t hasESD = kFALSE;
3627 Bool_t hasAOD = kFALSE;
3628 Bool_t hasANALYSIS = kFALSE;
7ea40ac8 3629 Bool_t hasOADB = kFALSE;
5b273635 3630 Bool_t hasANALYSISalice = kFALSE;
3631 Bool_t hasCORRFW = kFALSE;
0f389141 3632 TString func = mergingMacro;
3633 TString comment;
3634 func.ReplaceAll(".C", "");
f47d5cb4 3635 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
0f389141 3636 out << "{" << endl;
3637 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3638 out << " TStopwatch timer;" << endl;
3639 out << " timer.Start();" << endl << endl;
b3e07543 3640 // Reset existing include path
3641 out << "// Reset existing include path and add current directory first in the search" << endl;
3642 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
7c2cd90a 3643 if (!fExecutableCommand.Contains("aliroot")) {
3644 out << "// load base root libraries" << endl;
3645 out << " gSystem->Load(\"libTree\");" << endl;
3646 out << " gSystem->Load(\"libGeom\");" << endl;
3647 out << " gSystem->Load(\"libVMC\");" << endl;
3648 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3649 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3650 }
0f389141 3651 if (fAdditionalRootLibs.Length()) {
3652 // in principle libtree /lib geom libvmc etc. can go into this list, too
3653 out << "// Add aditional libraries" << endl;
3654 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3655 TIter next(list);
3656 TObjString *str;
3657 while((str=(TObjString*)next())) {
3658 if (str->GetString().Contains(".so"))
3659 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3660 }
3661 if (list) delete list;
3662 }
0f389141 3663 out << "// Load analysis framework libraries" << endl;
3664 if (!fPackages) {
7c2cd90a 3665 if (!fExecutableCommand.Contains("aliroot")) {
3666 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3667 out << " gSystem->Load(\"libESD\");" << endl;
3668 out << " gSystem->Load(\"libAOD\");" << endl;
3669 }
0f389141 3670 out << " gSystem->Load(\"libANALYSIS\");" << endl;
7ea40ac8 3671 out << " gSystem->Load(\"libOADB\");" << endl;
0f389141 3672 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3673 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3674 } else {
3675 TIter next(fPackages);
3676 TObject *obj;
3677 TString pkgname;
5b273635 3678 TString setupPar = "AliAnalysisAlien::SetupPar";
0f389141 3679 while ((obj=next())) {
3680 pkgname = obj->GetName();
3681 if (pkgname == "STEERBase" ||
3682 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3683 if (pkgname == "ESD" ||
3684 pkgname == "ESD.par") hasESD = kTRUE;
3685 if (pkgname == "AOD" ||
3686 pkgname == "AOD.par") hasAOD = kTRUE;
3687 if (pkgname == "ANALYSIS" ||
3688 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
7ea40ac8 3689 if (pkgname == "OADB" ||
3690 pkgname == "OADB.par") hasOADB = kTRUE;
0f389141 3691 if (pkgname == "ANALYSISalice" ||
3692 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3693 if (pkgname == "CORRFW" ||
3694 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3695 }
5b273635 3696 if (hasANALYSISalice) setupPar = "SetupPar";
0f389141 3697 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
5b273635 3698 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
0f389141 3699 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
5b273635 3700 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
0f389141 3701 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
5b273635 3702 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
0bc15bcd 3703 out << " gSystem->Load(\"libOADB\");" << endl;
0f389141 3704 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
5b273635 3705 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
7ea40ac8 3706 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3707 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
0f389141 3708 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
5b273635 3709 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
0f389141 3710 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
5b273635 3711 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
0f389141 3712 out << "// Compile other par packages" << endl;
3713 next.Reset();
3714 while ((obj=next())) {
3715 pkgname = obj->GetName();
3716 if (pkgname == "STEERBase" ||
3717 pkgname == "STEERBase.par" ||
3718 pkgname == "ESD" ||
3719 pkgname == "ESD.par" ||
3720 pkgname == "AOD" ||
3721 pkgname == "AOD.par" ||
3722 pkgname == "ANALYSIS" ||
3723 pkgname == "ANALYSIS.par" ||
7ea40ac8 3724 pkgname == "OADB" ||
3725 pkgname == "OADB.par" ||
0f389141 3726 pkgname == "ANALYSISalice" ||
3727 pkgname == "ANALYSISalice.par" ||
3728 pkgname == "CORRFW" ||
3729 pkgname == "CORRFW.par") continue;
5b273635 3730 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
0f389141 3731 }
3732 }
b3e07543 3733 out << "// include path" << endl;
3734 // Get the include path from the interpreter and remove entries pointing to AliRoot
3735 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3736 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3737 out << " TIter nextpath(listpaths);" << endl;
3738 out << " TObjString *pname;" << endl;
3739 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3740 out << " TString current = pname->GetName();" << endl;
3741 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3742 out << " gSystem->AddIncludePath(current);" << endl;
3743 out << " }" << endl;
3744 out << " if (listpaths) delete listpaths;" << endl;
3745 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3746 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3747 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
0f389141 3748 if (fAdditionalLibs.Length()) {
3749 out << "// Add aditional AliRoot libraries" << endl;
3750 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3751 TIter next(list);
3752 TObjString *str;
3753 while((str=(TObjString*)next())) {
3754 if (str->GetString().Contains(".so"))
3755 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3756 }
3757 if (list) delete list;
3758 }
3759 out << endl;
3760 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3761 if (fAnalysisSource.Length()) {
3762 TObjArray *list = fAnalysisSource.Tokenize(" ");
3763 TIter next(list);
3764 TObjString *str;
3765 while((str=(TObjString*)next())) {
3766 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3767 }
3768 if (list) delete list;
3769 }
149d288c 3770 out << endl;
3771
0f389141 3772 if (fFastReadOption) {
3773 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 !!!");
3774 out << "// fast xrootd reading enabled" << endl;
3775 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 3776 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3777 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
0f389141 3778 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
b3e07543 3779 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
0f389141 3780 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
e8b839ab 3781 }
3782 // Change temp directory to current one
3783 out << "// Set temporary merging directory to current one" << endl;
3784 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
70c52cf3 3785 out << "// Set temporary compilation directory to current one" << endl;
3786 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
0f389141 3787 out << "// Connect to AliEn" << endl;
3788 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
7c2cd90a 3789 out << " TString outputDir = dir;" << endl;
f790bc1b 3790 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
0f389141 3791 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
58268c13 3792 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
0f389141 3793 out << " TIter *iter = new TIter(list);" << endl;
3794 out << " TObjString *str;" << endl;
a2f5fc01 3795 out << " TString outputFile;" << endl;
0f389141 3796 out << " Bool_t merged = kTRUE;" << endl;
3797 out << " while((str=(TObjString*)iter->Next())) {" << endl;
a2f5fc01 3798 out << " outputFile = str->GetString();" << endl;
7c2cd90a 3799 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
a2f5fc01 3800 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3801 out << " if (index > 0) outputFile.Remove(index);" << endl;
0f389141 3802 out << " // Skip already merged outputs" << endl;
a2f5fc01 3803 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3804 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
0f389141 3805 out << " continue;" << endl;
3806 out << " }" << endl;
a2f5fc01 3807 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
b3e07543 3808 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
0f389141 3809 out << " if (!merged) {" << endl;
a2f5fc01 3810 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
7c2cd90a 3811 out << " return;" << endl;
0f389141 3812 out << " }" << endl;
3813 out << " }" << endl;
7c2cd90a 3814 out << " // all outputs merged, validate" << endl;
3815 out << " ofstream out;" << endl;
3816 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3817 out << " out.close();" << endl;
3818 out << " // read the analysis manager from file" << endl;
f866cba5 3819 TString analysisFile = fExecutable;
3820 analysisFile.ReplaceAll(".sh", ".root");
f47d5cb4 3821 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
105631b5 3822 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3823 << analysisFile << "\");" << endl;
3824 out << " if (!mgr) return;" << endl;
5c4250fc 3825 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
b385fec0 3826 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
f866cba5 3827 out << " mgr->PrintStatus();" << endl;
3828 if (AliAnalysisManager::GetAnalysisManager()) {
3829 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3830 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3831 } else {
9a8288ff 3832 if (TestBit(AliAnalysisGrid::kTest))
3833 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3834 else
3835 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
f866cba5 3836 }
3837 }
9a8288ff 3838 out << " TTree *tree = NULL;" << endl;
3839 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
0f389141 3840 out << "}" << endl << endl;
5b273635 3841 if (hasANALYSISalice) {
3842 out <<"//________________________________________________________________________________" << endl;
3843 out << "Bool_t SetupPar(const char *package) {" << endl;
3844 out << "// Compile the package and set it up." << endl;
3845 out << " TString pkgdir = package;" << endl;
3846 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
b50a41c3 3847 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
5b273635 3848 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3849 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3850 out << " // Check for BUILD.sh and execute" << endl;
3851 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3852 out << " printf(\"*******************************\\n\");" << endl;
3853 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3854 out << " printf(\"*******************************\\n\");" << endl;
3855 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3856 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3857 out << " gSystem->ChangeDirectory(cdir);" << endl;
3858 out << " return kFALSE;" << endl;
3859 out << " }" << endl;
3860 out << " } else {" << endl;
3861 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3862 out << " gSystem->ChangeDirectory(cdir);" << endl;
3863 out << " return kFALSE;" << endl;
3864 out << " }" << endl;
3865 out << " // Check for SETUP.C and execute" << endl;
3866 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3867 out << " printf(\"*******************************\\n\");" << endl;
3868 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3869 out << " printf(\"*******************************\\n\");" << endl;
3870 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3871 out << " } else {" << endl;
3872 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3873 out << " gSystem->ChangeDirectory(cdir);" << endl;
3874 out << " return kFALSE;" << endl;
3875 out << " }" << endl;
3876 out << " // Restore original workdir" << endl;
3877 out << " gSystem->ChangeDirectory(cdir);" << endl;
3878 out << " return kTRUE;" << endl;
3879 out << "}" << endl;
3880 }
0f389141 3881 }
3882 Bool_t copy = kTRUE;
d3b18c4c 3883 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 3884 if (copy) {
3885 CdWork();
3886 TString workdir = gGrid->GetHomeDirectory();
3887 workdir += fGridWorkingDir;
3888 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3889 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3890 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3891 }
3892}
3893
3894//______________________________________________________________________________
3895Bool_t AliAnalysisAlien::SetupPar(const char *package)
3896{
205b201f 3897// Compile the par file archive pointed by <package>. This must be present in the current directory.
0f389141 3898// Note that for loading the compiled library. The current directory should have precedence in
3899// LD_LIBRARY_PATH
3900 TString pkgdir = package;
3901 pkgdir.ReplaceAll(".par","");
b50a41c3 3902 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
0f389141 3903 TString cdir = gSystem->WorkingDirectory();
3904 gSystem->ChangeDirectory(pkgdir);
3905 // Check for BUILD.sh and execute
3906 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3907 printf("**************************************************\n");
3908 printf("*** Building PAR archive %s\n", package);
3909 printf("**************************************************\n");
3910 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3911 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3912 gSystem->ChangeDirectory(cdir);
3913 return kFALSE;
3914 }
3915 } else {
3916 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3917 gSystem->ChangeDirectory(cdir);
3918 return kFALSE;
3919 }
3920 // Check for SETUP.C and execute
3921 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3922 printf("**************************************************\n");
3923 printf("*** Setup PAR archive %s\n", package);
3924 printf("**************************************************\n");
3925 gROOT->Macro("PROOF-INF/SETUP.C");
3926 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3927 } else {
3928 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3929 gSystem->ChangeDirectory(cdir);
3930 return kFALSE;
3931 }
3932 // Restore original workdir
3933 gSystem->ChangeDirectory(cdir);
3934 return kTRUE;
3935}
3936
c57f56b7 3937//______________________________________________________________________________
3938void AliAnalysisAlien::WriteExecutable()
3939{
3940// Generate the alien executable script.
3941 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3942 ofstream out;
3943 out.open(fExecutable.Data(), ios::out);
3944 if (out.bad()) {
5513444a 3945 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
c57f56b7 3946 return;
3947 }
3948 out << "#!/bin/bash" << endl;
2a4d5166 3949 // Make sure we can properly compile par files
3950 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
c57f56b7 3951 out << "echo \"=========================================\"" << endl;
3952 out << "echo \"############## PATH : ##############\"" << endl;
3953 out << "echo $PATH" << endl;
3954 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3955 out << "echo $LD_LIBRARY_PATH" << endl;
3956 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3957 out << "echo $ROOTSYS" << endl;
3958 out << "echo \"############## which root : ##############\"" << endl;
3959 out << "which root" << endl;
3960 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3961 out << "echo $ALICE_ROOT" << endl;
3962 out << "echo \"############## which aliroot : ##############\"" << endl;
3963 out << "which aliroot" << endl;
9c5ddadc 3964 out << "echo \"############## system limits : ##############\"" << endl;
3965 out << "ulimit -a" << endl;
3966 out << "echo \"############## memory : ##############\"" << endl;
3967 out << "free -m" << endl;
c57f56b7 3968 out << "echo \"=========================================\"" << endl << endl;
0a1c1f7f 3969 out << fExecutableCommand << " ";
631c0b05 3970 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
9c5ddadc 3971 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3972 out << "echo \"############## memory after: ##############\"" << endl;
3973 out << "free -m" << endl;
c57f56b7 3974 }
3975 Bool_t copy = kTRUE;
d3b18c4c 3976 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 3977 if (copy) {
3978 CdWork();
3979 TString workdir = gGrid->GetHomeDirectory();
923e2ca5 3980 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 3981 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
c57f56b7 3982 workdir += fGridWorkingDir;
3983 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3984 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 3985 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
c57f56b7 3986 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3987 }
3988}
3989
0f389141 3990//______________________________________________________________________________
3991void AliAnalysisAlien::WriteMergeExecutable()
3992{
3993// Generate the alien executable script for the merging job.
3994 if (!fMergeViaJDL) return;
3995 TString mergeExec = fExecutable;
3996 mergeExec.ReplaceAll(".sh", "_merge.sh");
3997 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3998 ofstream out;
3999 out.open(mergeExec.Data(), ios::out);
4000 if (out.bad()) {
4001 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4002 return;
4003 }
4004 out << "#!/bin/bash" << endl;
2a4d5166 4005 // Make sure we can properly compile par files
4006 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
0f389141 4007 out << "echo \"=========================================\"" << endl;
4008 out << "echo \"############## PATH : ##############\"" << endl;
4009 out << "echo $PATH" << endl;
4010 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4011 out << "echo $LD_LIBRARY_PATH" << endl;
4012 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4013 out << "echo $ROOTSYS" << endl;
4014 out << "echo \"############## which root : ##############\"" << endl;
4015 out << "which root" << endl;
4016 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4017 out << "echo $ALICE_ROOT" << endl;
4018 out << "echo \"############## which aliroot : ##############\"" << endl;
4019 out << "which aliroot" << endl;
4020 out << "echo \"############## system limits : ##############\"" << endl;
4021 out << "ulimit -a" << endl;
4022 out << "echo \"############## memory : ##############\"" << endl;
4023 out << "free -m" << endl;
4024 out << "echo \"=========================================\"" << endl << endl;
0f389141 4025 TString mergeMacro = fExecutable;
4026 mergeMacro.ReplaceAll(".sh", "_merge.C");
f790bc1b 4027 if (IsOneStageMerging())
4028 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4029 else
f47d5cb4 4030 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
0f389141 4031 out << fExecutableCommand << " " << "$ARG" << endl;
4032 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4033 out << "echo \"############## memory after: ##############\"" << endl;
4034 out << "free -m" << endl;
0f389141 4035 }
4036 Bool_t copy = kTRUE;
d3b18c4c 4037 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
0f389141 4038 if (copy) {
4039 CdWork();
4040 TString workdir = gGrid->GetHomeDirectory();
4041 TString bindir = Form("%s/bin", workdir.Data());
b93f8109 4042 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
0f389141 4043 workdir += fGridWorkingDir;
4044 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4045 if (FileExists(executable)) gGrid->Rm(executable);
d3b18c4c 4046 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
0f389141 4047 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4048 }
4049}
4050
c57f56b7 4051//______________________________________________________________________________
5513444a 4052void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4053{
4054// Write the production file to be submitted by LPM manager. The format is:
f5e8c702 4055// First line: full_path_to_jdl estimated_no_subjobs_per_master
5513444a 4056// Next lines: full_path_to_dataset XXX (XXX is a string)
4057// To submit, one has to: submit jdl XXX for all lines
4058 ofstream out;
4059 out.open(filename, ios::out);
4060 if (out.bad()) {
4061 Error("WriteProductionFile", "Bad file name: %s", filename);
4062 return;
4063 }
d3b18c4c 4064 TString workdir;
4065 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4066 workdir = gGrid->GetHomeDirectory();
5513444a 4067 workdir += fGridWorkingDir;
f5e8c702 4068 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
5513444a 4069 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
f5e8c702 4070 out << locjdl << " " << njobspermaster << endl;
5513444a 4071 Int_t nmasterjobs = fInputFiles->GetEntries();
4072 for (Int_t i=0; i<nmasterjobs; i++) {
409b4ada 4073 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4074 runOutDir.ReplaceAll(".xml", "");
4075 if (fOutputToRunNo)
4076 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4077 else
4078 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
5513444a 4079 }
d3b18c4c 4080 if (gGrid) {
4081 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4082 if (FileExists(filename)) gGrid->Rm(filename);
4083 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4084 }
5513444a 4085}
4086
4087//______________________________________________________________________________
0f389141 4088void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
c57f56b7 4089{
4090// Generate the alien validation script.
4091 // Generate the validation script
4092 TObjString *os;
d3b18c4c 4093 if (fValidationScript.IsNull()) {
4094 fValidationScript = fExecutable;
4095 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4096 }
4097 TString validationScript = fValidationScript;
4098 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
c57f56b7 4099 if (!Connect()) {
4100 Error("WriteValidationScript", "Alien connection required");
4101 return;
4102 }
d3b18c4c 4103 if (!fTerminateFiles.IsNull()) {
4104 fTerminateFiles.Strip();
4105 fTerminateFiles.ReplaceAll(" ",",");
4106 }
a2f5fc01 4107 TString outStream = "";
4108 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
c57f56b7 4109 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4110 ofstream out;
0d5d317c 4111 out.open(validationScript, ios::out);
c57f56b7 4112 out << "#!/bin/bash" << endl;
4113 out << "##################################################" << endl;
4114 out << "validateout=`dirname $0`" << endl;
4115 out << "validatetime=`date`" << endl;
4116 out << "validated=\"0\";" << endl;
4117 out << "error=0" << endl;
4118 out << "if [ -z $validateout ]" << endl;
4119 out << "then" << endl;
4120 out << " validateout=\".\"" << endl;
4121 out << "fi" << endl << endl;
4122 out << "cd $validateout;" << endl;
4123 out << "validateworkdir=`pwd`;" << endl << endl;
a2f5fc01 4124 out << "echo \"*******************************************************\"" << outStream << endl;
4125 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
c57f56b7 4126 out << "" << endl;
a2f5fc01 4127 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4128 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4129 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4130 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4131 out << "ls -la ./" << outStream << endl;
4132 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
c57f56b7 4133 out << "##################################################" << endl;
ebec370a 4134 out << "" << endl;
4135
4136 out << "if [ ! -f stderr ] ; then" << endl;
4137 out << " error=1" << endl;
a2f5fc01 4138 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4139 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4140 out << "fi" << endl;
4141
b34c9f51 4142 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4143 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4144 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4145 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4146 out << "" << endl;
4147
ebec370a 4148 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4149 out << " error=1" << endl;
a2f5fc01 4150 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4151 out << " echo \"$parArch\" " << outStream << endl;
4152 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4153 out << "fi" << endl;
4154
4155 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4156 out << " error=1" << endl;
a2f5fc01 4157 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4158 out << " echo \"$segViol\" " << outStream << endl;
4159 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4160 out << "fi" << endl;
4161
4162 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4163 out << " error=1" << endl;
a2f5fc01 4164 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4165 out << " echo \"$segFault\" " << outStream << endl;
4166 out << " echo \"Error = $error\" " << outStream << endl;
ebec370a 4167 out << "fi" << endl;
4168
b34c9f51 4169 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4170 out << " error=1" << endl;
a2f5fc01 4171 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4172 out << " echo \"$glibcErr\" " << outStream << endl;
4173 out << " echo \"Error = $error\" " << outStream << endl;
b34c9f51 4174 out << "fi" << endl;
4175
ebec370a 4176 // Part dedicated to the specific analyses running into the train
4177
d3b18c4c 4178 TString outputFiles = fOutputFiles;
4179 if (merge && !fTerminateFiles.IsNull()) {
4180 outputFiles += ",";
4181 outputFiles += fTerminateFiles;
4182 }
4183 TObjArray *arr = outputFiles.Tokenize(",");
c57f56b7 4184 TIter next1(arr);
a2f5fc01 4185 TString outputFile;
bbd88db8 4186 while (!merge && (os=(TObjString*)next1())) {
4187 // No need to validate outputs produced by merging since the merging macro does this
a2f5fc01 4188 outputFile = os->GetString();
4189 Int_t index = outputFile.Index("@");
4190 if (index > 0) outputFile.Remove(index);
bbd88db8 4191 if (fTerminateFiles.Contains(outputFile)) continue;
a2f5fc01 4192 if (outputFile.Contains("*")) continue;
4193 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
c57f56b7 4194 out << " error=1" << endl;
7c2cd90a 4195 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4196 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
c57f56b7 4197 out << "fi" << endl;
4198 }
4199 delete arr;
7c2cd90a 4200 out << "if ! [ -f outputs_valid ] ; then" << endl;
4201 out << " error=1" << endl;
4202 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4203 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4204 out << "fi" << endl;
923e2ca5 4205
c57f56b7 4206 out << "if [ $error = 0 ] ; then" << endl;
a2f5fc01 4207 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
149d288c 4208 if (!IsKeepLogs()) {
4209 out << " echo \"* === Logs std* will be deleted === \"" << endl;
a2f5fc01 4210 outStream = "";
149d288c 4211 out << " rm -f std*" << endl;
4212 }
c57f56b7 4213 out << "fi" << endl;
4214
a2f5fc01 4215 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4216 out << "echo \"*******************************************************\"" << outStream << endl;
c57f56b7 4217 out << "cd -" << endl;
4218 out << "exit $error" << endl;
4219 }
4220 Bool_t copy = kTRUE;
d3b18c4c 4221 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
c57f56b7 4222 if (copy) {
4223 CdWork();
4224 TString workdir = gGrid->GetHomeDirectory();
4225 workdir += fGridWorkingDir;
d3b18c4c 4226 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
0d5d317c 4227 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4228 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
c57f56b7 4229 }
4230}