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