1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "Riostream.h"
30 #include "TFileCollection.h"
32 #include "TObjString.h"
33 #include "TObjArray.h"
35 #include "TGridResult.h"
36 #include "TGridCollection.h"
38 #include "TGridJobStatusList.h"
39 #include "TGridJobStatus.h"
40 #include "TFileMerger.h"
41 #include "AliAnalysisManager.h"
42 #include "AliVEventHandler.h"
43 #include "AliAnalysisDataContainer.h"
44 #include "AliAnalysisAlien.h"
46 ClassImp(AliAnalysisAlien)
48 //______________________________________________________________________________
49 AliAnalysisAlien::AliAnalysisAlien()
55 fSplitMaxInputFileNumber(0),
57 fMasterResubmitThreshold(0),
70 fNproofWorkersPerSlave(0),
80 fAdditionalRootLibs(),
108 fRootVersionForProof(),
118 //______________________________________________________________________________
119 AliAnalysisAlien::AliAnalysisAlien(const char *name)
120 :AliAnalysisGrid(name),
125 fSplitMaxInputFileNumber(0),
127 fMasterResubmitThreshold(0),
140 fNproofWorkersPerSlave(0),
144 fExecutableCommand(),
150 fAdditionalRootLibs(),
178 fRootVersionForProof(),
188 //______________________________________________________________________________
189 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
190 :AliAnalysisGrid(other),
193 fPrice(other.fPrice),
195 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
196 fMaxInitFailed(other.fMaxInitFailed),
197 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
198 fNtestFiles(other.fNtestFiles),
199 fNrunsPerMaster(other.fNrunsPerMaster),
200 fMaxMergeFiles(other.fMaxMergeFiles),
201 fMaxMergeStages(other.fMaxMergeStages),
202 fNsubmitted(other.fNsubmitted),
203 fProductionMode(other.fProductionMode),
204 fOutputToRunNo(other.fOutputToRunNo),
205 fMergeViaJDL(other.fMergeViaJDL),
206 fFastReadOption(other.fFastReadOption),
207 fOverwriteMode(other.fOverwriteMode),
208 fNreplicas(other.fNreplicas),
209 fNproofWorkers(other.fNproofWorkers),
210 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
211 fProofReset(other.fProofReset),
212 fRunNumbers(other.fRunNumbers),
213 fExecutable(other.fExecutable),
214 fExecutableCommand(other.fExecutableCommand),
215 fArguments(other.fArguments),
216 fExecutableArgs(other.fExecutableArgs),
217 fAnalysisMacro(other.fAnalysisMacro),
218 fAnalysisSource(other.fAnalysisSource),
219 fValidationScript(other.fValidationScript),
220 fAdditionalRootLibs(other.fAdditionalRootLibs),
221 fAdditionalLibs(other.fAdditionalLibs),
222 fSplitMode(other.fSplitMode),
223 fAPIVersion(other.fAPIVersion),
224 fROOTVersion(other.fROOTVersion),
225 fAliROOTVersion(other.fAliROOTVersion),
226 fExternalPackages(other.fExternalPackages),
228 fGridWorkingDir(other.fGridWorkingDir),
229 fGridDataDir(other.fGridDataDir),
230 fDataPattern(other.fDataPattern),
231 fGridOutputDir(other.fGridOutputDir),
232 fOutputArchive(other.fOutputArchive),
233 fOutputFiles(other.fOutputFiles),
234 fInputFormat(other.fInputFormat),
235 fDatasetName(other.fDatasetName),
236 fJDLName(other.fJDLName),
237 fTerminateFiles(other.fTerminateFiles),
238 fMergeExcludes(other.fMergeExcludes),
239 fIncludePath(other.fIncludePath),
240 fCloseSE(other.fCloseSE),
241 fFriendChainName(other.fFriendChainName),
242 fJobTag(other.fJobTag),
243 fOutputSingle(other.fOutputSingle),
244 fRunPrefix(other.fRunPrefix),
245 fProofCluster(other.fProofCluster),
246 fProofDataSet(other.fProofDataSet),
247 fFileForTestMode(other.fFileForTestMode),
248 fRootVersionForProof(other.fRootVersionForProof),
249 fAliRootMode(other.fAliRootMode),
250 fMergeDirName(other.fMergeDirName),
255 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
256 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
257 fRunRange[0] = other.fRunRange[0];
258 fRunRange[1] = other.fRunRange[1];
259 if (other.fInputFiles) {
260 fInputFiles = new TObjArray();
261 TIter next(other.fInputFiles);
263 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
264 fInputFiles->SetOwner();
266 if (other.fPackages) {
267 fPackages = new TObjArray();
268 TIter next(other.fPackages);
270 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
271 fPackages->SetOwner();
275 //______________________________________________________________________________
276 AliAnalysisAlien::~AliAnalysisAlien()
279 if (fGridJDL) delete fGridJDL;
280 if (fMergingJDL) delete fMergingJDL;
281 if (fInputFiles) delete fInputFiles;
282 if (fPackages) delete fPackages;
285 //______________________________________________________________________________
286 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
289 if (this != &other) {
290 AliAnalysisGrid::operator=(other);
291 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
292 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
293 fPrice = other.fPrice;
295 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
296 fMaxInitFailed = other.fMaxInitFailed;
297 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
298 fNtestFiles = other.fNtestFiles;
299 fNrunsPerMaster = other.fNrunsPerMaster;
300 fMaxMergeFiles = other.fMaxMergeFiles;
301 fMaxMergeStages = other.fMaxMergeStages;
302 fNsubmitted = other.fNsubmitted;
303 fProductionMode = other.fProductionMode;
304 fOutputToRunNo = other.fOutputToRunNo;
305 fMergeViaJDL = other.fMergeViaJDL;
306 fFastReadOption = other.fFastReadOption;
307 fOverwriteMode = other.fOverwriteMode;
308 fNreplicas = other.fNreplicas;
309 fNproofWorkers = other.fNproofWorkers;
310 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
311 fProofReset = other.fProofReset;
312 fRunNumbers = other.fRunNumbers;
313 fExecutable = other.fExecutable;
314 fExecutableCommand = other.fExecutableCommand;
315 fArguments = other.fArguments;
316 fExecutableArgs = other.fExecutableArgs;
317 fAnalysisMacro = other.fAnalysisMacro;
318 fAnalysisSource = other.fAnalysisSource;
319 fValidationScript = other.fValidationScript;
320 fAdditionalRootLibs = other.fAdditionalRootLibs;
321 fAdditionalLibs = other.fAdditionalLibs;
322 fSplitMode = other.fSplitMode;
323 fAPIVersion = other.fAPIVersion;
324 fROOTVersion = other.fROOTVersion;
325 fAliROOTVersion = other.fAliROOTVersion;
326 fExternalPackages = other.fExternalPackages;
328 fGridWorkingDir = other.fGridWorkingDir;
329 fGridDataDir = other.fGridDataDir;
330 fDataPattern = other.fDataPattern;
331 fGridOutputDir = other.fGridOutputDir;
332 fOutputArchive = other.fOutputArchive;
333 fOutputFiles = other.fOutputFiles;
334 fInputFormat = other.fInputFormat;
335 fDatasetName = other.fDatasetName;
336 fJDLName = other.fJDLName;
337 fTerminateFiles = other.fTerminateFiles;
338 fMergeExcludes = other.fMergeExcludes;
339 fIncludePath = other.fIncludePath;
340 fCloseSE = other.fCloseSE;
341 fFriendChainName = other.fFriendChainName;
342 fJobTag = other.fJobTag;
343 fOutputSingle = other.fOutputSingle;
344 fRunPrefix = other.fRunPrefix;
345 fProofCluster = other.fProofCluster;
346 fProofDataSet = other.fProofDataSet;
347 fFileForTestMode = other.fFileForTestMode;
348 fRootVersionForProof = other.fRootVersionForProof;
349 fAliRootMode = other.fAliRootMode;
350 fMergeDirName = other.fMergeDirName;
351 if (other.fInputFiles) {
352 fInputFiles = new TObjArray();
353 TIter next(other.fInputFiles);
355 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
356 fInputFiles->SetOwner();
358 if (other.fPackages) {
359 fPackages = new TObjArray();
360 TIter next(other.fPackages);
362 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
363 fPackages->SetOwner();
369 //______________________________________________________________________________
370 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
372 // Set the run number format. Can be a prefix or a format like "%09d"
374 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
377 //______________________________________________________________________________
378 void AliAnalysisAlien::AddIncludePath(const char *path)
380 // Add include path in the remote analysis macro.
382 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
383 else fIncludePath += Form("-I%s ", path);
386 //______________________________________________________________________________
387 void AliAnalysisAlien::AddRunNumber(Int_t run)
389 // Add a run number to the list of runs to be processed.
390 if (fRunNumbers.Length()) fRunNumbers += " ";
391 fRunNumbers += Form(fRunPrefix.Data(), run);
394 //______________________________________________________________________________
395 void AliAnalysisAlien::AddRunNumber(const char* run)
397 // Add a run number to the list of runs to be processed.
398 if (fRunNumbers.Length()) fRunNumbers += " ";
402 //______________________________________________________________________________
403 void AliAnalysisAlien::AddDataFile(const char *lfn)
405 // Adds a data file to the input to be analysed. The file should be a valid LFN
406 // or point to an existing file in the alien workdir.
407 if (!fInputFiles) fInputFiles = new TObjArray();
408 fInputFiles->Add(new TObjString(lfn));
411 //______________________________________________________________________________
412 void AliAnalysisAlien::AddExternalPackage(const char *package)
414 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
415 if (fExternalPackages) fExternalPackages += " ";
416 fExternalPackages += package;
419 //______________________________________________________________________________
420 Bool_t AliAnalysisAlien::Connect()
422 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
423 if (gGrid && gGrid->IsConnected()) return kTRUE;
424 if (fProductionMode) return kTRUE;
426 Info("Connect", "Trying to connect to AliEn ...");
427 TGrid::Connect("alien://");
429 if (!gGrid || !gGrid->IsConnected()) {
430 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
433 fUser = gGrid->GetUser();
434 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
438 //______________________________________________________________________________
439 void AliAnalysisAlien::CdWork()
441 // Check validity of alien workspace. Create directory if possible.
443 Error("CdWork", "Alien connection required");
446 TString homedir = gGrid->GetHomeDirectory();
447 TString workdir = homedir + fGridWorkingDir;
448 if (DirectoryExists(workdir)) {
452 // Work directory not existing - create it
454 if (gGrid->Mkdir(workdir, "-p")) {
455 gGrid->Cd(fGridWorkingDir);
456 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
458 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
459 workdir.Data(), homedir.Data());
460 fGridWorkingDir = "";
464 //______________________________________________________________________________
465 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
467 // Check if file copying is possible.
468 if (fProductionMode) return kTRUE;
470 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
473 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
474 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
475 // Check if alien_CLOSE_SE is defined
476 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
477 if (!closeSE.IsNull()) {
478 Info("CheckFileCopy", "Your current close storage is pointing to: \
479 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
481 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
483 // Check if grid directory exists.
484 if (!DirectoryExists(alienpath)) {
485 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
488 TFile f("plugin_test_copy", "RECREATE");
489 // User may not have write permissions to current directory
491 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
492 gSystem->WorkingDirectory());
496 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
497 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
498 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
499 \n# 1. Make sure you have write permissions there. If this is the case: \
500 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
501 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
502 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
503 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
504 gSystem->Unlink(f.GetName());
507 gSystem->Unlink(f.GetName());
508 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
509 Info("CheckFileCopy", "### ...SUCCESS ###");
513 //______________________________________________________________________________
514 Bool_t AliAnalysisAlien::CheckInputData()
516 // Check validity of input data. If necessary, create xml files.
517 if (fProductionMode) return kTRUE;
518 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
519 if (!fGridDataDir.Length()) {
520 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
523 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
524 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
525 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
528 // Process declared files
529 Bool_t isCollection = kFALSE;
530 Bool_t isXml = kFALSE;
531 Bool_t useTags = kFALSE;
532 Bool_t checked = kFALSE;
533 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
535 TString workdir = gGrid->GetHomeDirectory();
536 workdir += fGridWorkingDir;
539 TIter next(fInputFiles);
540 while ((objstr=(TObjString*)next())) {
543 file += objstr->GetString();
544 // Store full lfn path
545 if (FileExists(file)) objstr->SetString(file);
547 file = objstr->GetName();
548 if (!FileExists(objstr->GetName())) {
549 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
550 objstr->GetName(), workdir.Data());
554 Bool_t iscoll, isxml, usetags;
555 CheckDataType(file, iscoll, isxml, usetags);
558 isCollection = iscoll;
561 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
563 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
564 Error("CheckInputData", "Some conflict was found in the types of inputs");
570 // Process requested run numbers
571 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
572 // Check validity of alien data directory
573 if (!fGridDataDir.Length()) {
574 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
577 if (!DirectoryExists(fGridDataDir)) {
578 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
582 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
586 if (checked && !isXml) {
587 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
590 // Check validity of run number(s)
595 TString schunk, schunk2;
599 useTags = fDataPattern.Contains("tag");
600 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
602 if (useTags != fDataPattern.Contains("tag")) {
603 Error("CheckInputData", "Cannot mix input files using/not using tags");
606 if (fRunNumbers.Length()) {
607 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
608 arr = fRunNumbers.Tokenize(" ");
610 while ((os=(TObjString*)next())) {
611 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
612 if (!DirectoryExists(path)) {
613 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
616 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
617 TString msg = "\n##### file: ";
619 msg += " type: xml_collection;";
620 if (useTags) msg += " using_tags: Yes";
621 else msg += " using_tags: No";
622 Info("CheckDataType", "%s", msg.Data());
623 if (fNrunsPerMaster<2) {
624 AddDataFile(Form("%s.xml", os->GetString().Data()));
627 if (((nruns-1)%fNrunsPerMaster) == 0) {
628 schunk = os->GetString();
630 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
631 schunk += Form("_%s.xml", os->GetString().Data());
637 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
638 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
639 format = Form("%%s/%s ", fRunPrefix.Data());
640 path = Form(format.Data(), fGridDataDir.Data(), irun);
641 if (!DirectoryExists(path)) {
644 format = Form("%%s/%s.xml", fRunPrefix.Data());
645 path = Form(format.Data(), workdir.Data(),irun);
646 TString msg = "\n##### file: ";
648 msg += " type: xml_collection;";
649 if (useTags) msg += " using_tags: Yes";
650 else msg += " using_tags: No";
651 Info("CheckDataType", "%s", msg.Data());
652 if (fNrunsPerMaster<2) {
653 format = Form("%s.xml", fRunPrefix.Data());
654 AddDataFile(Form(format.Data(),irun));
657 if (((nruns-1)%fNrunsPerMaster) == 0) {
658 schunk = Form(fRunPrefix.Data(),irun);
660 format = Form("_%s.xml", fRunPrefix.Data());
661 schunk2 = Form(format.Data(), irun);
662 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
675 //______________________________________________________________________________
676 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
678 // Create dataset for the grid data directory + run number.
679 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
681 Error("CreateDataset", "Cannot create dataset with no grid connection");
686 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
687 TString workdir = gGrid->GetHomeDirectory();
688 workdir += fGridWorkingDir;
690 // Compose the 'find' command arguments
693 TString options = "-x collection ";
694 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
695 TString conditions = "";
700 TString schunk, schunk2;
701 TGridCollection *cbase=0, *cadd=0;
702 if (!fRunNumbers.Length() && !fRunRange[0]) {
703 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
704 // Make a single data collection from data directory.
706 if (!DirectoryExists(path)) {
707 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
711 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
712 else file = Form("%s.xml", gSystem->BaseName(path));
713 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
719 command += conditions;
720 printf("command: %s\n", command.Data());
721 TGridResult *res = gGrid->Command(command);
723 // Write standard output to file
724 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
725 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
726 Bool_t nullFile = kFALSE;
728 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
730 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
732 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
737 Bool_t fileExists = FileExists(file);
738 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
739 // Copy xml file to alien space
740 if (fileExists) gGrid->Rm(file);
741 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
742 if (!FileExists(file)) {
743 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
746 // Update list of files to be processed.
748 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
752 Bool_t nullResult = kTRUE;
753 if (fRunNumbers.Length()) {
754 TObjArray *arr = fRunNumbers.Tokenize(" ");
757 while ((os=(TObjString*)next())) {
758 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
759 if (!DirectoryExists(path)) continue;
761 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
762 else file = Form("%s.xml", os->GetString().Data());
763 // If local collection file does not exist, create it via 'find' command.
764 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
769 command += conditions;
770 TGridResult *res = gGrid->Command(command);
772 // Write standard output to file
773 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
774 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
775 Bool_t nullFile = kFALSE;
777 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
779 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
781 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
782 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
788 if (TestBit(AliAnalysisGrid::kTest)) break;
789 // Check if there is one run per master job.
790 if (fNrunsPerMaster<2) {
791 if (FileExists(file)) {
792 if (fOverwriteMode) gGrid->Rm(file);
794 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
798 // Copy xml file to alien space
799 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
800 if (!FileExists(file)) {
801 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
807 if (((nruns-1)%fNrunsPerMaster) == 0) {
808 schunk = os->GetString();
809 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
811 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
812 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
816 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
819 schunk += Form("_%s.xml", os->GetString().Data());
820 if (FileExists(schunk)) {
821 if (fOverwriteMode) gGrid->Rm(file);
823 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
827 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
828 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
829 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
830 if (!FileExists(schunk)) {
831 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
839 Error("CreateDataset", "No valid dataset corresponding to the query!");
843 // Process a full run range.
844 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
845 format = Form("%%s/%s ", fRunPrefix.Data());
846 path = Form(format.Data(), fGridDataDir.Data(), irun);
847 if (!DirectoryExists(path)) continue;
849 format = Form("%s.xml", fRunPrefix.Data());
850 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
851 else file = Form(format.Data(), irun);
852 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
853 if (fOverwriteMode) gGrid->Rm(file);
855 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
859 // If local collection file does not exist, create it via 'find' command.
860 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
865 command += conditions;
866 TGridResult *res = gGrid->Command(command);
868 // Write standard output to file
869 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
870 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
871 Bool_t nullFile = kFALSE;
873 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
875 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
877 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
883 if (TestBit(AliAnalysisGrid::kTest)) break;
884 // Check if there is one run per master job.
885 if (fNrunsPerMaster<2) {
886 if (FileExists(file)) {
887 if (fOverwriteMode) gGrid->Rm(file);
889 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
893 // Copy xml file to alien space
894 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
895 if (!FileExists(file)) {
896 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
901 // Check if the collection for the chunk exist locally.
902 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
903 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
904 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
907 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
908 if (((nruns-1)%fNrunsPerMaster) == 0) {
909 schunk = Form(fRunPrefix.Data(), irun);
910 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
912 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
916 format = Form("%%s_%s.xml", fRunPrefix.Data());
917 schunk2 = Form(format.Data(), schunk.Data(), irun);
918 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
922 if (FileExists(schunk)) {
923 if (fOverwriteMode) gGrid->Rm(schunk);
925 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
929 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
930 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
931 if (FileExists(schunk)) {
932 if (fOverwriteMode) gGrid->Rm(schunk);
934 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
938 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
939 if (!FileExists(schunk)) {
940 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
946 Error("CreateDataset", "No valid dataset corresponding to the query!");
953 //______________________________________________________________________________
954 Bool_t AliAnalysisAlien::CreateJDL()
956 // Generate a JDL file according to current settings. The name of the file is
957 // specified by fJDLName.
958 Bool_t error = kFALSE;
961 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
962 Bool_t generate = kTRUE;
963 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
965 Error("CreateJDL", "Alien connection required");
968 // Check validity of alien workspace
970 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
971 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
972 workdir += fGridWorkingDir;
976 Error("CreateJDL()", "Define some input files for your analysis.");
979 // Compose list of input files
980 // Check if output files were defined
981 if (!fOutputFiles.Length()) {
982 Error("CreateJDL", "You must define at least one output file");
985 // Check if an output directory was defined and valid
986 if (!fGridOutputDir.Length()) {
987 Error("CreateJDL", "You must define AliEn output directory");
990 if (!fProductionMode) {
991 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
992 if (!DirectoryExists(fGridOutputDir)) {
993 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
994 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
996 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1000 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1005 // Exit if any error up to now
1006 if (error) return kFALSE;
1008 if (!fUser.IsNull()) {
1009 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1010 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1012 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1013 TString mergeExec = fExecutable;
1014 mergeExec.ReplaceAll(".sh", "_merge.sh");
1015 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1016 mergeExec.ReplaceAll(".sh", ".C");
1017 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1018 if (!fArguments.IsNull())
1019 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1020 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1022 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1023 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1026 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1027 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1028 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1029 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1031 if (fMaxInitFailed > 0) {
1032 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1033 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1035 if (fSplitMaxInputFileNumber > 0) {
1036 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1037 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1039 if (!IsOneStageMerging()) {
1040 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1041 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1043 if (fSplitMode.Length()) {
1044 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1045 fGridJDL->SetDescription("Split", "We split per SE or file");
1047 fMergingJDL->SetValue("Split", "\"se\"");
1048 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1049 if (!fAliROOTVersion.IsNull()) {
1050 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1051 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1053 if (!fROOTVersion.IsNull()) {
1054 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1055 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1057 if (!fAPIVersion.IsNull()) {
1058 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1059 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1061 if (!fExternalPackages.IsNull()) {
1062 arr = fExternalPackages.Tokenize(" ");
1064 while ((os=(TObjString*)next())) {
1065 TString pkgname = os->GetString();
1066 Int_t index = pkgname.Index("::");
1067 TString pkgversion = pkgname(index+2, pkgname.Length());
1068 pkgname.Remove(index);
1069 fGridJDL->AddToPackages(pkgname, pkgversion);
1070 fMergingJDL->AddToPackages(pkgname, pkgversion);
1074 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1075 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1076 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1077 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1078 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1079 TString analysisFile = fExecutable;
1080 analysisFile.ReplaceAll(".sh", ".root");
1081 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1082 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1083 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1084 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1085 if (fAdditionalLibs.Length()) {
1086 arr = fAdditionalLibs.Tokenize(" ");
1088 while ((os=(TObjString*)next())) {
1089 if (os->GetString().Contains(".so")) continue;
1090 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1091 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1096 TIter next(fPackages);
1098 while ((obj=next())) {
1099 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1100 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1103 if (fOutputArchive.Length()) {
1104 arr = fOutputArchive.Tokenize(" ");
1106 Bool_t first = kTRUE;
1107 const char *comment = "Files to be archived";
1108 const char *comment1 = comment;
1109 while ((os=(TObjString*)next())) {
1110 if (!first) comment = NULL;
1111 if (!os->GetString().Contains("@") && fCloseSE.Length())
1112 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1114 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1118 // Output archive for the merging jdl
1119 TString outputArchive;
1120 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1121 outputArchive = "log_archive.zip:std*@disk=1 ";
1122 // Add normal output files, extra files + terminate files
1123 TString files = GetListOfFiles("outextter");
1124 // Do not register merge excludes
1125 if (!fMergeExcludes.IsNull()) {
1126 arr = fMergeExcludes.Tokenize(" ");
1128 while ((os=(TObjString*)next1())) {
1129 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1130 files.ReplaceAll(os->GetString(),"");
1134 files.ReplaceAll(".root", "*.root");
1135 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1137 TString files = fOutputArchive;
1138 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1139 outputArchive = files;
1141 arr = outputArchive.Tokenize(" ");
1145 while ((os=(TObjString*)next2())) {
1146 if (!first) comment = NULL;
1147 TString currentfile = os->GetString();
1148 if (!currentfile.Contains("@") && fCloseSE.Length())
1149 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1151 fMergingJDL->AddToOutputArchive(currentfile, comment);
1156 arr = fOutputFiles.Tokenize(",");
1158 Bool_t first = kTRUE;
1159 const char *comment = "Files to be saved";
1160 while ((os=(TObjString*)next())) {
1161 // Ignore ouputs in jdl that are also in outputarchive
1162 TString sout = os->GetString();
1163 sout.ReplaceAll("*", "");
1164 sout.ReplaceAll(".root", "");
1165 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1166 if (fOutputArchive.Contains(sout)) continue;
1167 if (!first) comment = NULL;
1168 if (!os->GetString().Contains("@") && fCloseSE.Length())
1169 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1171 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1173 if (fMergeExcludes.Contains(sout)) continue;
1174 if (!os->GetString().Contains("@") && fCloseSE.Length())
1175 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1177 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1180 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1181 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1182 TString validationScript = fValidationScript;
1183 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1184 validationScript.ReplaceAll(".sh", "_merge.sh");
1185 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1186 if (fMasterResubmitThreshold) {
1187 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1188 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1190 // Write a jdl with 2 input parameters: collection name and output dir name.
1193 // Copy jdl to grid workspace
1195 // Check if an output directory was defined and valid
1196 if (!fGridOutputDir.Length()) {
1197 Error("CreateJDL", "You must define AliEn output directory");
1200 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1201 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1202 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1203 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1205 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1211 if (TestBit(AliAnalysisGrid::kSubmit)) {
1212 TString mergeJDLName = fExecutable;
1213 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1214 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1215 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1216 if (fProductionMode) {
1217 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1218 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1220 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1221 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1222 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1223 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1225 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1226 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1229 if (fAdditionalLibs.Length()) {
1230 arr = fAdditionalLibs.Tokenize(" ");
1233 while ((os=(TObjString*)next())) {
1234 if (os->GetString().Contains(".so")) continue;
1235 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1236 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1237 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1242 TIter next(fPackages);
1244 while ((obj=next())) {
1245 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1246 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1247 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1254 //______________________________________________________________________________
1255 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1257 // Writes one or more JDL's corresponding to findex. If findex is negative,
1258 // all run numbers are considered in one go (jdl). For non-negative indices
1259 // they correspond to the indices in the array fInputFiles.
1260 if (!fInputFiles) return kFALSE;
1263 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1264 workdir += fGridWorkingDir;
1265 TString stageName = "$2";
1266 if (fProductionMode) stageName = "$4";
1267 if (!fMergeDirName.IsNull()) {
1268 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1269 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1271 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1272 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1274 if (fProductionMode) {
1275 TIter next(fInputFiles);
1276 while ((os=next())) {
1277 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1279 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1281 if (!fRunNumbers.Length() && !fRunRange[0]) {
1282 // One jdl with no parameters in case input data is specified by name.
1283 TIter next(fInputFiles);
1285 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1286 if (!fOutputSingle.IsNull())
1287 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1289 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1290 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1293 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1294 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1295 if (!fOutputSingle.IsNull()) {
1296 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1297 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1299 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1304 // Generate the JDL as a string
1305 TString sjdl = fGridJDL->Generate();
1306 TString sjdl1 = fMergingJDL->Generate();
1308 if (!fMergeDirName.IsNull()) {
1309 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1310 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1312 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1313 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1315 TString sjdl2 = fMergingJDL->Generate();
1316 Int_t index, index1;
1317 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1318 sjdl.ReplaceAll("(member", "\n (member");
1319 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1320 sjdl.ReplaceAll("{", "{\n ");
1321 sjdl.ReplaceAll("};", "\n};");
1322 sjdl.ReplaceAll("{\n \n", "{\n");
1323 sjdl.ReplaceAll("\n\n", "\n");
1324 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1325 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1326 sjdl1.ReplaceAll("(member", "\n (member");
1327 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1328 sjdl1.ReplaceAll("{", "{\n ");
1329 sjdl1.ReplaceAll("};", "\n};");
1330 sjdl1.ReplaceAll("{\n \n", "{\n");
1331 sjdl1.ReplaceAll("\n\n", "\n");
1332 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1333 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1334 sjdl2.ReplaceAll("(member", "\n (member");
1335 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1336 sjdl2.ReplaceAll("{", "{\n ");
1337 sjdl2.ReplaceAll("};", "\n};");
1338 sjdl2.ReplaceAll("{\n \n", "{\n");
1339 sjdl2.ReplaceAll("\n\n", "\n");
1340 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1341 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1342 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1343 index = sjdl.Index("JDLVariables");
1344 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1345 sjdl += "Workdirectorysize = {\"5000MB\"};";
1346 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1347 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1348 index = fJobTag.Index(":");
1349 if (index < 0) index = fJobTag.Length();
1350 TString jobTag = fJobTag;
1351 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1352 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1353 if (fProductionMode) {
1354 sjdl1.Prepend("# Generated merging jdl (production mode) \
1355 \n# $1 = full alien path to output directory to be merged \
1356 \n# $2 = train number \
1357 \n# $3 = production (like LHC10b) \
1358 \n# $4 = merging stage \
1359 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1360 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1361 sjdl2.Prepend("# Generated merging jdl \
1362 \n# $1 = full alien path to output directory to be merged \
1363 \n# $2 = train number \
1364 \n# $3 = production (like LHC10b) \
1365 \n# $4 = merging stage \
1366 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1368 sjdl1.Prepend("# Generated merging jdl \
1369 \n# $1 = full alien path to output directory to be merged \
1370 \n# $2 = merging stage \
1371 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1372 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1373 sjdl2.Prepend("# Generated merging jdl \
1374 \n# $1 = full alien path to output directory to be merged \
1375 \n# $2 = merging stage \
1376 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1378 index = sjdl1.Index("JDLVariables");
1379 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1380 index = sjdl2.Index("JDLVariables");
1381 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1382 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1383 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1384 index = sjdl2.Index("Split =");
1386 index1 = sjdl2.Index("\n", index);
1387 sjdl2.Remove(index, index1-index+1);
1389 index = sjdl2.Index("SplitMaxInputFileNumber");
1391 index1 = sjdl2.Index("\n", index);
1392 sjdl2.Remove(index, index1-index+1);
1394 index = sjdl2.Index("InputDataCollection");
1396 index1 = sjdl2.Index(";", index);
1397 sjdl2.Remove(index, index1-index+1);
1399 index = sjdl2.Index("InputDataListFormat");
1401 index1 = sjdl2.Index("\n", index);
1402 sjdl2.Remove(index, index1-index+1);
1404 index = sjdl2.Index("InputDataList");
1406 index1 = sjdl2.Index("\n", index);
1407 sjdl2.Remove(index, index1-index+1);
1409 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1410 // Write jdl to file
1412 out.open(fJDLName.Data(), ios::out);
1414 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1417 out << sjdl << endl;
1419 TString mergeJDLName = fExecutable;
1420 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1423 out1.open(mergeJDLName.Data(), ios::out);
1425 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1428 out1 << sjdl1 << endl;
1431 TString finalJDL = mergeJDLName;
1432 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1433 out2.open(finalJDL.Data(), ios::out);
1435 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1438 out2 << sjdl2 << endl;
1442 // Copy jdl to grid workspace
1444 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1446 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1447 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1448 TString finalJDL = mergeJDLName;
1449 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1450 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1451 if (fProductionMode) {
1452 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1453 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1454 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1456 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1457 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1458 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1459 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1460 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1462 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1463 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1464 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1470 //______________________________________________________________________________
1471 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1473 // Returns true if file exists.
1474 if (!gGrid) return kFALSE;
1476 slfn.ReplaceAll("alien://","");
1477 TGridResult *res = gGrid->Ls(slfn);
1478 if (!res) return kFALSE;
1479 TMap *map = dynamic_cast<TMap*>(res->At(0));
1484 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1485 if (!objs || !objs->GetString().Length()) {
1493 //______________________________________________________________________________
1494 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1496 // Returns true if directory exists. Can be also a path.
1497 if (!gGrid) return kFALSE;
1498 // Check if dirname is a path
1499 TString dirstripped = dirname;
1500 dirstripped = dirstripped.Strip();
1501 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1502 TString dir = gSystem->BaseName(dirstripped);
1504 TString path = gSystem->DirName(dirstripped);
1505 TGridResult *res = gGrid->Ls(path, "-F");
1506 if (!res) return kFALSE;
1510 while ((map=dynamic_cast<TMap*>(next()))) {
1511 obj = map->GetValue("name");
1513 if (dir == obj->GetName()) {
1522 //______________________________________________________________________________
1523 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1525 // Check input data type.
1526 isCollection = kFALSE;
1530 Error("CheckDataType", "No connection to grid");
1533 isCollection = IsCollection(lfn);
1534 TString msg = "\n##### file: ";
1537 msg += " type: raw_collection;";
1538 // special treatment for collections
1540 // check for tag files in the collection
1541 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1543 msg += " using_tags: No (unknown)";
1544 Info("CheckDataType", "%s", msg.Data());
1547 const char* typeStr = res->GetKey(0, "origLFN");
1548 if (!typeStr || !strlen(typeStr)) {
1549 msg += " using_tags: No (unknown)";
1550 Info("CheckDataType", "%s", msg.Data());
1553 TString file = typeStr;
1554 useTags = file.Contains(".tag");
1555 if (useTags) msg += " using_tags: Yes";
1556 else msg += " using_tags: No";
1557 Info("CheckDataType", "%s", msg.Data());
1562 isXml = slfn.Contains(".xml");
1564 // Open xml collection and check if there are tag files inside
1565 msg += " type: xml_collection;";
1566 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1568 msg += " using_tags: No (unknown)";
1569 Info("CheckDataType", "%s", msg.Data());
1572 TMap *map = coll->Next();
1574 msg += " using_tags: No (unknown)";
1575 Info("CheckDataType", "%s", msg.Data());
1578 map = (TMap*)map->GetValue("");
1580 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1581 useTags = file.Contains(".tag");
1583 if (useTags) msg += " using_tags: Yes";
1584 else msg += " using_tags: No";
1585 Info("CheckDataType", "%s", msg.Data());
1588 useTags = slfn.Contains(".tag");
1589 if (slfn.Contains(".root")) msg += " type: root file;";
1590 else msg += " type: unknown file;";
1591 if (useTags) msg += " using_tags: Yes";
1592 else msg += " using_tags: No";
1593 Info("CheckDataType", "%s", msg.Data());
1596 //______________________________________________________________________________
1597 void AliAnalysisAlien::EnablePackage(const char *package)
1599 // Enables a par file supposed to exist in the current directory.
1600 TString pkg(package);
1601 pkg.ReplaceAll(".par", "");
1603 if (gSystem->AccessPathName(pkg)) {
1604 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1607 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1608 Info("EnablePackage", "AliEn plugin will use .par packages");
1609 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1611 fPackages = new TObjArray();
1612 fPackages->SetOwner();
1614 fPackages->Add(new TObjString(pkg));
1617 //______________________________________________________________________________
1618 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1620 // Make a tree from files having the location specified in fFileForTestMode.
1621 // Inspired from JF's CreateESDChain.
1622 if (fFileForTestMode.IsNull()) {
1623 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1626 if (gSystem->AccessPathName(fFileForTestMode)) {
1627 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1632 in.open(fFileForTestMode);
1634 // Read the input list of files and add them to the chain
1636 TChain *chain = new TChain(treeName);
1640 if (line.IsNull()) continue;
1641 if (count++ == fNtestFiles) break;
1642 TString esdFile(line);
1643 TFile *file = TFile::Open(esdFile);
1645 if (!file->IsZombie()) chain->Add(esdFile);
1648 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1652 if (!chain->GetListOfFiles()->GetEntries()) {
1653 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1661 //______________________________________________________________________________
1662 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1664 // Get job status for all jobs with jobid>jobidstart.
1665 static char mstatus[20];
1671 TGridJobStatusList *list = gGrid->Ps("");
1672 if (!list) return mstatus;
1673 Int_t nentries = list->GetSize();
1674 TGridJobStatus *status;
1676 for (Int_t ijob=0; ijob<nentries; ijob++) {
1677 status = (TGridJobStatus *)list->At(ijob);
1678 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1679 if (pid<jobidstart) continue;
1680 if (pid == lastid) {
1681 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1683 switch (status->GetStatus()) {
1684 case TGridJobStatus::kWAITING:
1686 case TGridJobStatus::kRUNNING:
1688 case TGridJobStatus::kABORTED:
1689 case TGridJobStatus::kFAIL:
1690 case TGridJobStatus::kUNKNOWN:
1692 case TGridJobStatus::kDONE:
1701 //______________________________________________________________________________
1702 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1704 // Returns true if file is a collection. Functionality duplicated from
1705 // TAlien::Type() because we don't want to directly depend on TAlien.
1707 Error("IsCollection", "No connection to grid");
1710 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1711 if (!res) return kFALSE;
1712 const char* typeStr = res->GetKey(0, "type");
1713 if (!typeStr || !strlen(typeStr)) return kFALSE;
1714 if (!strcmp(typeStr, "collection")) return kTRUE;
1719 //______________________________________________________________________________
1720 Bool_t AliAnalysisAlien::IsSingleOutput() const
1722 // Check if single-ouput option is on.
1723 return (!fOutputSingle.IsNull());
1726 //______________________________________________________________________________
1727 void AliAnalysisAlien::Print(Option_t *) const
1729 // Print current plugin settings.
1730 printf("### AliEn analysis plugin current settings ###\n");
1731 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1732 if (mgr && mgr->IsProofMode()) {
1733 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1734 if (TestBit(AliAnalysisGrid::kTest))
1735 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1736 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1737 if (!fProofDataSet.IsNull())
1738 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1740 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1742 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1743 if (!fRootVersionForProof.IsNull())
1744 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1746 printf("= ROOT version requested________________________ default\n");
1747 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1748 if (!fAliRootMode.IsNull())
1749 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1751 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1752 if (fNproofWorkersPerSlave)
1753 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1754 if (TestSpecialBit(kClearPackages))
1755 printf("= ClearPackages requested...\n");
1756 if (fIncludePath.Data())
1757 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1758 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1759 if (fPackages && fPackages->GetEntries()) {
1760 TIter next(fPackages);
1763 while ((obj=next())) list += obj->GetName();
1764 printf("= Par files to be used: ________________________ %s\n", list.Data());
1766 if (TestSpecialBit(kProofConnectGrid))
1767 printf("= Requested PROOF connection to grid\n");
1770 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1771 if (fOverwriteMode) {
1772 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1773 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1775 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1776 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1777 printf("= Production mode:______________________________ %d\n", fProductionMode);
1778 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1779 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1780 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1782 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1783 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1784 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1785 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1786 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1787 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1788 if (fRunNumbers.Length())
1789 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1791 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1792 if (!fRunRange[0] && !fRunNumbers.Length()) {
1793 TIter next(fInputFiles);
1796 while ((obj=next())) list += obj->GetName();
1797 printf("= Input files to be processed: _________________ %s\n", list.Data());
1799 if (TestBit(AliAnalysisGrid::kTest))
1800 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1801 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1802 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1803 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1804 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1805 printf("=====================================================================\n");
1806 printf("= Job price: ___________________________________ %d\n", fPrice);
1807 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1808 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1809 if (fMaxInitFailed>0)
1810 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1811 if (fMasterResubmitThreshold>0)
1812 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1813 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1814 if (fNrunsPerMaster>0)
1815 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1816 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1817 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1818 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1819 if (fArguments.Length())
1820 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1821 if (fExecutableArgs.Length())
1822 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1823 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1824 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1825 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1826 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1828 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1829 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1830 if (fIncludePath.Data())
1831 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1832 if (fCloseSE.Length())
1833 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1834 if (fFriendChainName.Length())
1835 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1836 if (fPackages && fPackages->GetEntries()) {
1837 TIter next(fPackages);
1840 while ((obj=next())) list += obj->GetName();
1841 printf("= Par files to be used: ________________________ %s\n", list.Data());
1845 //______________________________________________________________________________
1846 void AliAnalysisAlien::SetDefaults()
1848 // Set default values for everything. What cannot be filled will be left empty.
1849 if (fGridJDL) delete fGridJDL;
1850 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1851 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1854 fSplitMaxInputFileNumber = 100;
1856 fMasterResubmitThreshold = 0;
1862 fNrunsPerMaster = 1;
1863 fMaxMergeFiles = 100;
1865 fExecutable = "analysis.sh";
1866 fExecutableCommand = "root -b -q";
1868 fExecutableArgs = "";
1869 fAnalysisMacro = "myAnalysis.C";
1870 fAnalysisSource = "";
1871 fAdditionalLibs = "";
1875 fAliROOTVersion = "";
1876 fUser = ""; // Your alien user name
1877 fGridWorkingDir = "";
1878 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1879 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1880 fFriendChainName = "";
1881 fGridOutputDir = "output";
1882 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1883 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1884 fInputFormat = "xml-single";
1885 fJDLName = "analysis.jdl";
1886 fJobTag = "Automatically generated analysis JDL";
1887 fMergeExcludes = "";
1890 SetCheckCopy(kTRUE);
1891 SetDefaultOutputs(kTRUE);
1895 //______________________________________________________________________________
1896 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
1898 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1899 // First check if the result is already in the output directory.
1900 if (FileExists(Form("%s/%s",aliendir,filename))) {
1901 printf("Final merged results found. Not merging again.\n");
1904 // Now check the last stage done.
1907 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1910 // Next stage of merging
1912 TString pattern = "*root_archive.zip";
1913 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1914 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1915 if (res) delete res;
1916 // Write standard output to file
1917 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1918 // Count the number of files inside
1920 ifile.open(Form("Stage_%d.xml",stage));
1921 if (!ifile.good()) {
1922 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
1927 while (!ifile.eof()) {
1929 if (line.Contains("/event")) nfiles++;
1933 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1936 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
1938 // Copy the file in the output directory
1939 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1940 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1941 // Check if this is the last stage to be done.
1942 Bool_t laststage = (nfiles<nperchunk);
1943 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1945 printf("### Submiting final merging stage %d\n", stage);
1946 TString finalJDL = jdl;
1947 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1948 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
1949 Int_t jobId = SubmitSingleJob(query);
1950 if (!jobId) return kFALSE;
1952 printf("### Submiting merging stage %d\n", stage);
1953 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
1954 Int_t jobId = SubmitSingleJob(query);
1955 if (!jobId) return kFALSE;
1960 //______________________________________________________________________________
1961 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1963 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1964 if (!gGrid) return 0;
1965 printf("=> %s ------> ",query);
1966 TGridResult *res = gGrid->Command(query);
1968 TString jobId = res->GetKey(0,"jobId");
1970 if (jobId.IsNull()) {
1971 printf("submission failed. Reason:\n");
1974 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
1977 printf(" Job id: %s\n", jobId.Data());
1981 //______________________________________________________________________________
1982 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
1984 // Merge given output files from basedir. Basedir can be an alien output directory
1985 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
1986 // files in a group (ignored for xml input). Merging can be done in stages:
1987 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
1988 // stage=1 : works with an xml of all root_archive.zip in the output directory
1989 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
1990 TString outputFile = output;
1992 TString outputChunk;
1993 TString previousChunk = "";
1994 TObjArray *listoffiles = new TObjArray();
1995 // listoffiles->SetOwner();
1996 Int_t countChunk = 0;
1997 Int_t countZero = nmaxmerge;
1998 Bool_t merged = kTRUE;
1999 Int_t index = outputFile.Index("@");
2000 if (index > 0) outputFile.Remove(index);
2001 TString inputFile = outputFile;
2002 TString sbasedir = basedir;
2003 if (sbasedir.Contains(".xml")) {
2004 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2005 nmaxmerge = 9999999;
2006 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2008 ::Error("MergeOutput", "Input XML collection empty.");
2011 // Iterate grid collection
2012 while (coll->Next()) {
2013 TString fname = gSystem->DirName(coll->GetTURL());
2016 listoffiles->Add(new TNamed(fname.Data(),""));
2019 command = Form("find %s/ *%s", basedir, inputFile.Data());
2020 printf("command: %s\n", command.Data());
2021 TGridResult *res = gGrid->Command(command);
2023 ::Error("MergeOutput","No result for the find command\n");
2029 while ((map=(TMap*)nextmap())) {
2030 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2031 if (!objs || !objs->GetString().Length()) {
2032 // Nothing found - skip this output
2037 listoffiles->Add(new TNamed(objs->GetName(),""));
2041 if (!listoffiles->GetEntries()) {
2042 ::Error("MergeOutput","No result for the find command\n");
2047 TFileMerger *fm = 0;
2048 TIter next0(listoffiles);
2049 TObjArray *listoffilestmp = new TObjArray();
2050 listoffilestmp->SetOwner();
2053 // Keep only the files at upper level
2054 Int_t countChar = 0;
2055 while ((nextfile=next0())) {
2056 snextfile = nextfile->GetName();
2057 Int_t crtCount = snextfile.CountChar('/');
2058 if (nextfile == listoffiles->First()) countChar = crtCount;
2059 if (crtCount < countChar) countChar = crtCount;
2062 while ((nextfile=next0())) {
2063 snextfile = nextfile->GetName();
2064 Int_t crtCount = snextfile.CountChar('/');
2065 if (crtCount > countChar) {
2069 listoffilestmp->Add(nextfile);
2072 listoffiles = listoffilestmp; // Now contains 'good' files
2073 listoffiles->Print();
2074 TIter next(listoffiles);
2075 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2076 outputChunk = outputFile;
2077 outputChunk.ReplaceAll(".root", "_*.root");
2078 // Check for existent temporary merge files
2079 // Check overwrite mode and remove previous partial results if needed
2080 // Preserve old merging functionality for stage 0.
2082 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2084 // Skip as many input files as in a chunk
2085 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2088 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2092 snextfile = nextfile->GetName();
2094 outputChunk = outputFile;
2095 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2097 if (gSystem->AccessPathName(outputChunk)) continue;
2098 // Merged file with chunks up to <countChunk> found
2099 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2100 previousChunk = outputChunk;
2104 countZero = nmaxmerge;
2106 while ((nextfile=next())) {
2107 snextfile = nextfile->GetName();
2108 // Loop 'find' results and get next LFN
2109 if (countZero == nmaxmerge) {
2110 // First file in chunk - create file merger and add previous chunk if any.
2111 fm = new TFileMerger(kFALSE);
2112 fm->SetFastMethod(kTRUE);
2113 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2114 outputChunk = outputFile;
2115 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2117 // If last file found, put merged results in the output file
2118 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2119 // Add file to be merged and decrement chunk counter.
2120 fm->AddFile(snextfile);
2122 if (countZero==0 || nextfile == listoffiles->Last()) {
2123 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2124 // Nothing found - skip this output
2125 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2129 fm->OutputFile(outputChunk);
2130 // Merge the outputs, then go to next chunk
2132 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2136 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2137 gSystem->Unlink(previousChunk);
2139 if (nextfile == listoffiles->Last()) break;
2141 countZero = nmaxmerge;
2142 previousChunk = outputChunk;
2149 // Merging stage different than 0.
2150 // Move to the begining of the requested chunk.
2151 fm = new TFileMerger(kFALSE);
2152 fm->SetFastMethod(kTRUE);
2153 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2155 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2156 // Nothing found - skip this output
2157 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2161 fm->OutputFile(outputFile);
2162 // Merge the outputs
2164 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2168 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2174 //______________________________________________________________________________
2175 Bool_t AliAnalysisAlien::MergeOutputs()
2177 // Merge analysis outputs existing in the AliEn space.
2178 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2179 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2181 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2185 if (!TestBit(AliAnalysisGrid::kMerge)) {
2186 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2189 if (fProductionMode) {
2190 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2193 Info("MergeOutputs", "Submitting merging JDL");
2194 if (!SubmitMerging()) return kFALSE;
2195 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2196 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2199 // Get the output path
2200 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2201 if (!DirectoryExists(fGridOutputDir)) {
2202 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2205 if (!fOutputFiles.Length()) {
2206 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2209 // Check if fast read option was requested
2210 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2211 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2212 if (fFastReadOption) {
2213 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2214 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2215 gEnv->SetValue("XNet.ConnectTimeout",50);
2216 gEnv->SetValue("XNet.RequestTimeout",50);
2217 gEnv->SetValue("XNet.MaxRedirectCount",2);
2218 gEnv->SetValue("XNet.ReconnectTimeout",50);
2219 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2221 // Make sure we change the temporary directory
2222 gSystem->Setenv("TMPDIR", gSystem->pwd());
2223 TObjArray *list = fOutputFiles.Tokenize(",");
2227 Bool_t merged = kTRUE;
2228 while((str=(TObjString*)next())) {
2229 outputFile = str->GetString();
2230 Int_t index = outputFile.Index("@");
2231 if (index > 0) outputFile.Remove(index);
2232 TString outputChunk = outputFile;
2233 outputChunk.ReplaceAll(".root", "_*.root");
2234 // Skip already merged outputs
2235 if (!gSystem->AccessPathName(outputFile)) {
2236 if (fOverwriteMode) {
2237 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2238 gSystem->Unlink(outputFile);
2239 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2240 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2241 outputChunk.Data());
2242 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2245 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2249 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2250 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2251 outputChunk.Data());
2252 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2255 if (fMergeExcludes.Length() &&
2256 fMergeExcludes.Contains(outputFile.Data())) continue;
2257 // Perform a 'find' command in the output directory, looking for registered outputs
2258 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2260 Error("MergeOutputs", "Terminate() will NOT be executed");
2263 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2264 if (fileOpened) fileOpened->Close();
2269 //______________________________________________________________________________
2270 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2272 // Use the output files connected to output containers from the analysis manager
2273 // rather than the files defined by SetOutputFiles
2274 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2275 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2276 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2279 //______________________________________________________________________________
2280 void AliAnalysisAlien::SetOutputFiles(const char *list)
2282 // Manually set the output files list.
2283 // Removes duplicates. Not allowed if default outputs are not disabled.
2284 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2285 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2288 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2290 TString slist = list;
2291 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2292 TObjArray *arr = slist.Tokenize(" ");
2296 while ((os=(TObjString*)next())) {
2297 sout = os->GetString();
2298 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2299 if (fOutputFiles.Contains(sout)) continue;
2300 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2301 fOutputFiles += sout;
2306 //______________________________________________________________________________
2307 void AliAnalysisAlien::SetOutputArchive(const char *list)
2309 // Manually set the output archive list. Free text - you are on your own...
2310 // Not allowed if default outputs are not disabled.
2311 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2312 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2315 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2316 fOutputArchive = list;
2319 //______________________________________________________________________________
2320 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2322 // Setting a prefered output SE is not allowed anymore.
2323 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2326 //______________________________________________________________________________
2327 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2329 // Start remote grid analysis.
2330 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2331 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2332 if (!mgr || !mgr->IsInitialized()) {
2333 Error("StartAnalysis", "You need an initialized analysis manager for this");
2336 // Are we in PROOF mode ?
2337 if (mgr->IsProofMode()) {
2338 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2339 if (fProofCluster.IsNull()) {
2340 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2343 if (fProofDataSet.IsNull() && !testMode) {
2344 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2347 // Set the needed environment
2348 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2349 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2350 if (fProofReset && !testMode) {
2351 if (fProofReset==1) {
2352 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2353 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2355 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2356 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2358 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2361 // Do we need to change the ROOT version ? The success of this cannot be checked.
2362 if (!fRootVersionForProof.IsNull() && !testMode) {
2363 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2364 fProofCluster.Data(), fRootVersionForProof.Data()));
2366 // Connect to PROOF and check the status
2369 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2370 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2372 if (!sworkers.IsNull())
2373 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2375 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2377 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2379 Error("StartAnalysis", "Could not start PROOF in test mode");
2384 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2387 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2388 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2389 // Is dataset existing ?
2391 TString dataset = fProofDataSet;
2392 Int_t index = dataset.Index("#");
2393 if (index>=0) dataset.Remove(index);
2394 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2395 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2398 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2400 // Is ClearPackages() needed ?
2401 if (TestSpecialBit(kClearPackages)) {
2402 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2403 gROOT->ProcessLine("gProof->ClearPackages();");
2405 // Is a given aliroot mode requested ?
2408 if (!fAliRootMode.IsNull()) {
2409 TString alirootMode = fAliRootMode;
2410 if (alirootMode == "default") alirootMode = "";
2411 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2412 optionsList.SetOwner();
2413 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2414 // Check the additional libs to be loaded
2416 Bool_t parMode = kFALSE;
2417 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2418 // Parse the extra libs for .so
2419 if (fAdditionalLibs.Length()) {
2420 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2423 while((str=(TObjString*)next())) {
2424 if (str->GetString().Contains(".so")) {
2426 Warning("StartAnalysis", "Plugin does not support loading libs after par files in PROOF mode. Library %s and following will not load on workers", str->GetName());
2429 TString stmp = str->GetName();
2430 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2431 stmp.ReplaceAll(".so","");
2432 if (!extraLibs.IsNull()) extraLibs += ":";
2436 if (str->GetString().Contains(".par")) {
2437 // The first par file found in the list will not allow any further .so
2439 if (!parLibs.IsNull()) parLibs += ":";
2440 parLibs += str->GetName();
2444 if (list) delete list;
2446 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2447 // Check extra includes
2448 if (!fIncludePath.IsNull()) {
2449 TString includePath = fIncludePath;
2450 includePath.ReplaceAll(" ",":");
2451 includePath.ReplaceAll("$ALICE_ROOT","");
2452 includePath.ReplaceAll("${ALICE_ROOT}","");
2453 includePath.ReplaceAll("-I","");
2454 includePath.Strip(TString::kTrailing, ':');
2455 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2456 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2458 // Check if connection to grid is requested
2459 if (TestSpecialBit(kProofConnectGrid))
2460 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2461 // Enable AliRoot par
2463 // Enable proof lite package
2464 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2465 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2466 TNamed *obj = (TNamed*)optionsList.At(i);
2467 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2469 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2470 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2471 Info("StartAnalysis", "AliRootProofLite enabled");
2473 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2477 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2478 fAliROOTVersion.Data(), &optionsList))) {
2479 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2483 // Enable first par files from fAdditionalLibs
2484 if (!parLibs.IsNull()) {
2485 TObjArray *list = parLibs.Tokenize(":");
2487 TObjString *package;
2488 while((package=(TObjString*)next())) {
2489 TString spkg = package->GetName();
2490 spkg.ReplaceAll(".par", "");
2491 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2492 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2493 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2494 if (gROOT->ProcessLine(enablePackage)) {
2495 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2499 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2503 if (list) delete list;
2506 if (fAdditionalLibs.Contains(".so") && !testMode) {
2507 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2508 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2512 // Enable par files if requested
2513 if (fPackages && fPackages->GetEntries()) {
2514 TIter next(fPackages);
2516 while ((package=next())) {
2517 // Skip packages already enabled
2518 if (parLibs.Contains(package->GetName())) continue;
2519 TString spkg = package->GetName();
2520 spkg.ReplaceAll(".par", "");
2521 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2522 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2523 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2524 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2528 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2533 // Do we need to load analysis source files ?
2534 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2535 if (fAnalysisSource.Length()) {
2536 TObjArray *list = fAnalysisSource.Tokenize(" ");
2539 while((str=(TObjString*)next())) {
2540 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2542 if (list) delete list;
2545 // Register dataset to proof lite.
2546 if (fFileForTestMode.IsNull()) {
2547 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2550 if (gSystem->AccessPathName(fFileForTestMode)) {
2551 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2554 TFileCollection *coll = new TFileCollection();
2555 coll->AddFromFile(fFileForTestMode);
2556 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2557 gROOT->ProcessLine("gProof->ShowDataSets()");
2562 // Check if output files have to be taken from the analysis manager
2563 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2564 // Add output files and AOD files
2565 fOutputFiles = GetListOfFiles("outaod");
2566 // Add extra files registered to the analysis manager
2567 TString extra = GetListOfFiles("ext");
2568 if (!extra.IsNull()) {
2569 extra.ReplaceAll(".root", "*.root");
2570 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2571 fOutputFiles += extra;
2573 // Compose the output archive.
2574 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2575 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2577 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2578 if (TestBit(AliAnalysisGrid::kOffline)) {
2579 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2580 \n there nor any job run. You can revise the JDL and analysis \
2581 \n macro then run the same in \"submit\" mode.");
2582 } else if (TestBit(AliAnalysisGrid::kTest)) {
2583 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2585 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2586 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2587 \n space and job submitted.");
2588 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2589 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2590 if (fMergeViaJDL) CheckInputData();
2593 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2598 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2601 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2602 if (!CheckInputData()) {
2603 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2606 if (!CreateDataset(fDataPattern)) {
2608 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2609 if (fRunNumbers.Length()) serror = "run numbers";
2610 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2611 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2612 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2615 WriteAnalysisFile();
2616 WriteAnalysisMacro();
2618 WriteValidationScript();
2620 WriteMergingMacro();
2621 WriteMergeExecutable();
2622 WriteValidationScript(kTRUE);
2624 if (!CreateJDL()) return kFALSE;
2625 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2627 // Locally testing the analysis
2628 Info("StartAnalysis", "\n_______________________________________________________________________ \
2629 \n Running analysis script in a daughter shell as on a worker node \
2630 \n_______________________________________________________________________");
2631 TObjArray *list = fOutputFiles.Tokenize(",");
2635 while((str=(TObjString*)next())) {
2636 outputFile = str->GetString();
2637 Int_t index = outputFile.Index("@");
2638 if (index > 0) outputFile.Remove(index);
2639 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2642 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2643 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2644 // gSystem->Exec("cat stdout");
2647 // Check if submitting is managed by LPM manager
2648 if (fProductionMode) {
2649 TString prodfile = fJDLName;
2650 prodfile.ReplaceAll(".jdl", ".prod");
2651 WriteProductionFile(prodfile);
2652 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2655 // Submit AliEn job(s)
2656 gGrid->Cd(fGridOutputDir);
2659 if (!fRunNumbers.Length() && !fRunRange[0]) {
2660 // Submit a given xml or a set of runs
2661 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2662 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2664 const char *cjobId = res->GetKey(0,"jobId");
2668 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2671 Info("StartAnalysis", "\n_______________________________________________________________________ \
2672 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2673 \n_______________________________________________________________________",
2674 fJDLName.Data(), cjobId);
2679 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2683 // Submit for a range of enumeration of runs.
2684 if (!Submit()) return kFALSE;
2687 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2688 \n You may exit at any time and terminate the job later using the option <terminate> \
2689 \n ##################################################################################", jobID.Data());
2690 gSystem->Exec("aliensh");
2694 //______________________________________________________________________________
2695 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2697 // Get a comma-separated list of output files of the requested type.
2698 // Type can be (case unsensitive):
2699 // aod - list of aod files (std, extensions and filters)
2700 // out - list of output files connected to containers (but not aod's or extras)
2701 // ext - list of extra files registered to the manager
2702 // ter - list of files produced in terminate
2703 static TString files;
2705 TString stype = type;
2707 TString aodfiles, extra;
2708 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2710 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2711 return files.Data();
2713 if (mgr->GetOutputEventHandler()) {
2714 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2715 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2716 if (!extraaod.IsNull()) {
2718 aodfiles += extraaod;
2721 if (stype.Contains("aod")) {
2723 if (stype == "aod") return files.Data();
2725 // Add output files that are not in the list of AOD files
2726 TString outputfiles = "";
2727 TIter next(mgr->GetOutputs());
2728 AliAnalysisDataContainer *output;
2729 const char *filename = 0;
2730 while ((output=(AliAnalysisDataContainer*)next())) {
2731 filename = output->GetFileName();
2732 if (!(strcmp(filename, "default"))) continue;
2733 if (outputfiles.Contains(filename)) continue;
2734 if (aodfiles.Contains(filename)) continue;
2735 if (!outputfiles.IsNull()) outputfiles += ",";
2736 outputfiles += filename;
2738 if (stype.Contains("out")) {
2739 if (!files.IsNull()) files += ",";
2740 files += outputfiles;
2741 if (stype == "out") return files.Data();
2743 // Add extra files registered to the analysis manager
2745 extra = mgr->GetExtraFiles();
2746 if (!extra.IsNull()) {
2748 extra.ReplaceAll(" ", ",");
2749 TObjArray *fextra = extra.Tokenize(",");
2750 TIter nextx(fextra);
2752 while ((obj=nextx())) {
2753 if (aodfiles.Contains(obj->GetName())) continue;
2754 if (outputfiles.Contains(obj->GetName())) continue;
2755 if (sextra.Contains(obj->GetName())) continue;
2756 if (!sextra.IsNull()) sextra += ",";
2757 sextra += obj->GetName();
2760 if (stype.Contains("ext")) {
2761 if (!files.IsNull()) files += ",";
2765 if (stype == "ext") return files.Data();
2767 if (!fTerminateFiles.IsNull()) {
2768 fTerminateFiles.Strip();
2769 fTerminateFiles.ReplaceAll(" ",",");
2770 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2771 TIter nextx(fextra);
2773 while ((obj=nextx())) {
2774 if (aodfiles.Contains(obj->GetName())) continue;
2775 if (outputfiles.Contains(obj->GetName())) continue;
2776 if (termfiles.Contains(obj->GetName())) continue;
2777 if (sextra.Contains(obj->GetName())) continue;
2778 if (!termfiles.IsNull()) termfiles += ",";
2779 termfiles += obj->GetName();
2783 if (stype.Contains("ter")) {
2784 if (!files.IsNull() && !termfiles.IsNull()) {
2789 return files.Data();
2792 //______________________________________________________________________________
2793 Bool_t AliAnalysisAlien::Submit()
2795 // Submit all master jobs.
2796 Int_t nmasterjobs = fInputFiles->GetEntries();
2797 Long_t tshoot = gSystem->Now();
2798 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2799 while (fNsubmitted < nmasterjobs) {
2800 Long_t now = gSystem->Now();
2801 if ((now-tshoot)>30000) {
2803 if (!SubmitNext()) return kFALSE;
2809 //______________________________________________________________________________
2810 Bool_t AliAnalysisAlien::SubmitMerging()
2812 // Submit all merging jobs.
2813 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2814 gGrid->Cd(fGridOutputDir);
2815 TString mergeJDLName = fExecutable;
2816 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2817 Int_t ntosubmit = fInputFiles->GetEntries();
2818 for (Int_t i=0; i<ntosubmit; i++) {
2819 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2820 runOutDir.ReplaceAll(".xml", "");
2821 if (fOutputToRunNo) {
2822 // The output directory is the run number
2823 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2824 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2826 // The output directory is the master number in 3 digits format
2827 printf("### Submitting merging job for master <%03d>\n", i);
2828 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2830 // Check now the number of merging stages.
2831 TObjArray *list = fOutputFiles.Tokenize(",");
2835 while((str=(TObjString*)next())) {
2836 outputFile = str->GetString();
2837 Int_t index = outputFile.Index("@");
2838 if (index > 0) outputFile.Remove(index);
2839 if (!fMergeExcludes.Contains(outputFile)) break;
2842 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2843 if (!done) return kFALSE;
2845 if (!ntosubmit) return kTRUE;
2846 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
2847 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
2848 \n ##################################################################################");
2849 gSystem->Exec("aliensh");
2853 //______________________________________________________________________________
2854 Bool_t AliAnalysisAlien::SubmitNext()
2856 // Submit next bunch of master jobs if the queue is free. The first master job is
2857 // submitted right away, while the next will not be unless the previous was split.
2858 // The plugin will not submit new master jobs if there are more that 500 jobs in
2860 static Bool_t iscalled = kFALSE;
2861 static Int_t firstmaster = 0;
2862 static Int_t lastmaster = 0;
2863 static Int_t npermaster = 0;
2864 if (iscalled) return kTRUE;
2866 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2867 Int_t ntosubmit = 0;
2870 Int_t nmasterjobs = fInputFiles->GetEntries();
2873 if (!IsUseSubmitPolicy()) {
2875 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2876 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2877 ntosubmit = nmasterjobs;
2880 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2881 printf("=== master %d: %s\n", lastmaster, status.Data());
2882 // If last master not split, just return
2883 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2884 // No more than 100 waiting jobs
2885 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2886 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2887 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2888 if (!ntosubmit) ntosubmit = 1;
2889 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2890 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2892 for (Int_t i=0; i<ntosubmit; i++) {
2893 // Submit for a range of enumeration of runs.
2894 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2896 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2897 runOutDir.ReplaceAll(".xml", "");
2899 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2901 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2902 printf("********* %s\n",query.Data());
2903 res = gGrid->Command(query);
2905 TString cjobId1 = res->GetKey(0,"jobId");
2906 if (!cjobId1.Length()) {
2910 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2913 Info("StartAnalysis", "\n_______________________________________________________________________ \
2914 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2915 \n_______________________________________________________________________",
2916 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2919 lastmaster = cjobId1.Atoi();
2920 if (!firstmaster) firstmaster = lastmaster;
2925 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2933 //______________________________________________________________________________
2934 void AliAnalysisAlien::WriteAnalysisFile()
2936 // Write current analysis manager into the file <analysisFile>
2937 TString analysisFile = fExecutable;
2938 analysisFile.ReplaceAll(".sh", ".root");
2939 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2940 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2941 if (!mgr || !mgr->IsInitialized()) {
2942 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2945 // Check analysis type
2947 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2948 handler = (TObject*)mgr->GetInputEventHandler();
2950 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2951 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2953 TDirectory *cdir = gDirectory;
2954 TFile *file = TFile::Open(analysisFile, "RECREATE");
2956 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2957 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
2958 // Unless merging makes no sense
2959 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2962 // Enable termination for local jobs
2963 mgr->SetSkipTerminate(kFALSE);
2965 if (cdir) cdir->cd();
2966 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2968 Bool_t copy = kTRUE;
2969 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2972 TString workdir = gGrid->GetHomeDirectory();
2973 workdir += fGridWorkingDir;
2974 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2975 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2976 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2980 //______________________________________________________________________________
2981 void AliAnalysisAlien::WriteAnalysisMacro()
2983 // Write the analysis macro that will steer the analysis in grid mode.
2984 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2986 out.open(fAnalysisMacro.Data(), ios::out);
2988 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2991 Bool_t hasSTEERBase = kFALSE;
2992 Bool_t hasESD = kFALSE;
2993 Bool_t hasAOD = kFALSE;
2994 Bool_t hasANALYSIS = kFALSE;
2995 Bool_t hasANALYSISalice = kFALSE;
2996 Bool_t hasCORRFW = kFALSE;
2997 TString func = fAnalysisMacro;
2998 TString type = "ESD";
2999 TString comment = "// Analysis using ";
3000 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3001 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3005 if (type!="AOD" && fFriendChainName!="") {
3006 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3009 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3010 else comment += " data";
3011 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3012 func.ReplaceAll(".C", "");
3013 out << "void " << func.Data() << "()" << endl;
3015 out << comment.Data() << endl;
3016 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3017 out << " TStopwatch timer;" << endl;
3018 out << " timer.Start();" << endl << endl;
3019 // Change temp directory to current one
3020 out << "// Set temporary merging directory to current one" << endl;
3021 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3022 // Reset existing include path
3023 out << "// Reset existing include path and add current directory first in the search" << endl;
3024 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3025 if (!fExecutableCommand.Contains("aliroot")) {
3026 out << "// load base root libraries" << endl;
3027 out << " gSystem->Load(\"libTree\");" << endl;
3028 out << " gSystem->Load(\"libGeom\");" << endl;
3029 out << " gSystem->Load(\"libVMC\");" << endl;
3030 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3031 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3033 if (fAdditionalRootLibs.Length()) {
3034 // in principle libtree /lib geom libvmc etc. can go into this list, too
3035 out << "// Add aditional libraries" << endl;
3036 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3039 while((str=(TObjString*)next())) {
3040 if (str->GetString().Contains(".so"))
3041 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3043 if (list) delete list;
3045 out << "// Load analysis framework libraries" << endl;
3046 TString setupPar = "AliAnalysisAlien::SetupPar";
3048 if (!fExecutableCommand.Contains("aliroot")) {
3049 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3050 out << " gSystem->Load(\"libESD\");" << endl;
3051 out << " gSystem->Load(\"libAOD\");" << endl;
3053 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3054 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3055 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3057 TIter next(fPackages);
3060 while ((obj=next())) {
3061 pkgname = obj->GetName();
3062 if (pkgname == "STEERBase" ||
3063 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3064 if (pkgname == "ESD" ||
3065 pkgname == "ESD.par") hasESD = kTRUE;
3066 if (pkgname == "AOD" ||
3067 pkgname == "AOD.par") hasAOD = kTRUE;
3068 if (pkgname == "ANALYSIS" ||
3069 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3070 if (pkgname == "ANALYSISalice" ||
3071 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3072 if (pkgname == "CORRFW" ||
3073 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3075 if (hasANALYSISalice) setupPar = "SetupPar";
3076 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3077 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3078 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3079 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3080 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3081 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3082 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3083 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3084 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3085 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3086 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3087 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3088 out << "// Compile other par packages" << endl;
3090 while ((obj=next())) {
3091 pkgname = obj->GetName();
3092 if (pkgname == "STEERBase" ||
3093 pkgname == "STEERBase.par" ||
3095 pkgname == "ESD.par" ||
3097 pkgname == "AOD.par" ||
3098 pkgname == "ANALYSIS" ||
3099 pkgname == "ANALYSIS.par" ||
3100 pkgname == "ANALYSISalice" ||
3101 pkgname == "ANALYSISalice.par" ||
3102 pkgname == "CORRFW" ||
3103 pkgname == "CORRFW.par") continue;
3104 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3107 out << "// include path" << endl;
3108 // Get the include path from the interpreter and remove entries pointing to AliRoot
3109 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3110 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3111 out << " TIter nextpath(listpaths);" << endl;
3112 out << " TObjString *pname;" << endl;
3113 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3114 out << " TString current = pname->GetName();" << endl;
3115 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3116 out << " gSystem->AddIncludePath(current);" << endl;
3117 out << " }" << endl;
3118 out << " if (listpaths) delete listpaths;" << endl;
3119 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3120 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3121 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3122 if (fAdditionalLibs.Length()) {
3123 out << "// Add aditional AliRoot libraries" << endl;
3124 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3127 while((str=(TObjString*)next())) {
3128 if (str->GetString().Contains(".so"))
3129 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3130 if (str->GetString().Contains(".par"))
3131 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3133 if (list) delete list;
3136 out << "// analysis source to be compiled at runtime (if any)" << endl;
3137 if (fAnalysisSource.Length()) {
3138 TObjArray *list = fAnalysisSource.Tokenize(" ");
3141 while((str=(TObjString*)next())) {
3142 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3144 if (list) delete list;
3147 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3148 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3149 if (fFastReadOption) {
3150 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. This may skip some files that could be accessed !!! \
3151 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3152 out << "// fast xrootd reading enabled" << endl;
3153 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3154 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3155 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3156 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3157 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3158 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3160 out << "// connect to AliEn and make the chain" << endl;
3161 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3162 out << "// read the analysis manager from file" << endl;
3163 TString analysisFile = fExecutable;
3164 analysisFile.ReplaceAll(".sh", ".root");
3165 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3166 out << " if (!file) return;" << endl;
3167 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3168 out << " AliAnalysisManager *mgr = 0;" << endl;
3169 out << " TKey *key;" << endl;
3170 out << " while ((key=(TKey*)nextkey())) {" << endl;
3171 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3172 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3173 out << " };" << endl;
3174 out << " if (!mgr) {" << endl;
3175 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3176 out << " return;" << endl;
3177 out << " }" << endl << endl;
3178 out << " mgr->PrintStatus();" << endl;
3179 if (AliAnalysisManager::GetAnalysisManager()) {
3180 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3181 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3183 if (TestBit(AliAnalysisGrid::kTest))
3184 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3186 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3189 if (IsUsingTags()) {
3190 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3192 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3194 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3195 out << " timer.Stop();" << endl;
3196 out << " timer.Print();" << endl;
3197 out << "}" << endl << endl;
3198 if (IsUsingTags()) {
3199 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3201 out << "// Create a chain using tags from the xml file." << endl;
3202 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3203 out << " if (!coll) {" << endl;
3204 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3205 out << " return NULL;" << endl;
3206 out << " }" << endl;
3207 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3208 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3209 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3210 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3211 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3212 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3213 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3214 out << " // Check if the cuts configuration file was provided" << endl;
3215 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3216 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3217 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3218 out << " }" << endl;
3219 if (fFriendChainName=="") {
3220 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3222 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3223 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3224 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3226 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3227 out << " chain->ls();" << endl;
3228 out << " return chain;" << endl;
3229 out << "}" << endl << endl;
3230 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3231 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3232 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3233 msg += " AliLHCTagCuts *lhcCuts,\n";
3234 msg += " AliDetectorTagCuts *detCuts,\n";
3235 msg += " AliEventTagCuts *evCuts)";
3236 Info("WriteAnalysisMacro", "%s", msg.Data());
3239 if (!IsUsingTags() || fFriendChainName!="") {
3240 out <<"//________________________________________________________________________________" << endl;
3241 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3243 out << "// Create a chain using url's from xml file" << endl;
3244 out << " TString filename;" << endl;
3245 out << " Int_t run = 0;" << endl;
3246 out << " TString treename = type;" << endl;
3247 out << " treename.ToLower();" << endl;
3248 out << " treename += \"Tree\";" << endl;
3249 out << " printf(\"***************************************\\n\");" << endl;
3250 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3251 out << " printf(\"***************************************\\n\");" << endl;
3252 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3253 out << " if (!coll) {" << endl;
3254 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3255 out << " return NULL;" << endl;
3256 out << " }" << endl;
3257 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3258 out << " TChain *chain = new TChain(treename);" << endl;
3259 if(fFriendChainName!="") {
3260 out << " TChain *chainFriend = new TChain(treename);" << endl;
3262 out << " coll->Reset();" << endl;
3263 out << " while (coll->Next()) {" << endl;
3264 out << " filename = coll->GetTURL("");" << endl;
3265 out << " if (mgr) {" << endl;
3266 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3267 out << " if (nrun && nrun != run) {" << endl;
3268 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3269 out << " mgr->SetRunFromPath(nrun);" << endl;
3270 out << " run = nrun;" << endl;
3271 out << " }" << endl;
3272 out << " }" << endl;
3273 out << " chain->Add(filename);" << endl;
3274 if(fFriendChainName!="") {
3275 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3276 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3277 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3278 out << " chainFriend->Add(fileFriend.Data());" << endl;
3280 out << " }" << endl;
3281 out << " if (!chain->GetNtrees()) {" << endl;
3282 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3283 out << " return NULL;" << endl;
3284 out << " }" << endl;
3285 if(fFriendChainName!="") {
3286 out << " chain->AddFriend(chainFriend);" << endl;
3288 out << " return chain;" << endl;
3289 out << "}" << endl << endl;
3291 if (hasANALYSISalice) {
3292 out <<"//________________________________________________________________________________" << endl;
3293 out << "Bool_t SetupPar(const char *package) {" << endl;
3294 out << "// Compile the package and set it up." << endl;
3295 out << " TString pkgdir = package;" << endl;
3296 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3297 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3298 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3299 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3300 out << " // Check for BUILD.sh and execute" << endl;
3301 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3302 out << " printf(\"*******************************\\n\");" << endl;
3303 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3304 out << " printf(\"*******************************\\n\");" << endl;
3305 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3306 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3307 out << " gSystem->ChangeDirectory(cdir);" << endl;
3308 out << " return kFALSE;" << endl;
3309 out << " }" << endl;
3310 out << " } else {" << endl;
3311 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3312 out << " gSystem->ChangeDirectory(cdir);" << endl;
3313 out << " return kFALSE;" << endl;
3314 out << " }" << endl;
3315 out << " // Check for SETUP.C and execute" << endl;
3316 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3317 out << " printf(\"*******************************\\n\");" << endl;
3318 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3319 out << " printf(\"*******************************\\n\");" << endl;
3320 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3321 out << " } else {" << endl;
3322 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3323 out << " gSystem->ChangeDirectory(cdir);" << endl;
3324 out << " return kFALSE;" << endl;
3325 out << " }" << endl;
3326 out << " // Restore original workdir" << endl;
3327 out << " gSystem->ChangeDirectory(cdir);" << endl;
3328 out << " return kTRUE;" << endl;
3331 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3333 Bool_t copy = kTRUE;
3334 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3337 TString workdir = gGrid->GetHomeDirectory();
3338 workdir += fGridWorkingDir;
3339 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3340 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3341 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3342 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3343 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3345 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3346 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3350 //______________________________________________________________________________
3351 void AliAnalysisAlien::WriteMergingMacro()
3353 // Write a macro to merge the outputs per master job.
3354 if (!fMergeViaJDL) return;
3355 if (!fOutputFiles.Length()) {
3356 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3359 TString mergingMacro = fExecutable;
3360 mergingMacro.ReplaceAll(".sh","_merge.C");
3361 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3362 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3364 out.open(mergingMacro.Data(), ios::out);
3366 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3369 Bool_t hasSTEERBase = kFALSE;
3370 Bool_t hasESD = kFALSE;
3371 Bool_t hasAOD = kFALSE;
3372 Bool_t hasANALYSIS = kFALSE;
3373 Bool_t hasANALYSISalice = kFALSE;
3374 Bool_t hasCORRFW = kFALSE;
3375 TString func = mergingMacro;
3377 func.ReplaceAll(".C", "");
3378 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3380 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3381 out << " TStopwatch timer;" << endl;
3382 out << " timer.Start();" << endl << endl;
3383 // Reset existing include path
3384 out << "// Reset existing include path and add current directory first in the search" << endl;
3385 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3386 if (!fExecutableCommand.Contains("aliroot")) {
3387 out << "// load base root libraries" << endl;
3388 out << " gSystem->Load(\"libTree\");" << endl;
3389 out << " gSystem->Load(\"libGeom\");" << endl;
3390 out << " gSystem->Load(\"libVMC\");" << endl;
3391 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3392 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3394 if (fAdditionalRootLibs.Length()) {
3395 // in principle libtree /lib geom libvmc etc. can go into this list, too
3396 out << "// Add aditional libraries" << endl;
3397 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3400 while((str=(TObjString*)next())) {
3401 if (str->GetString().Contains(".so"))
3402 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3404 if (list) delete list;
3406 out << "// Load analysis framework libraries" << endl;
3408 if (!fExecutableCommand.Contains("aliroot")) {
3409 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3410 out << " gSystem->Load(\"libESD\");" << endl;
3411 out << " gSystem->Load(\"libAOD\");" << endl;
3413 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3414 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3415 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3417 TIter next(fPackages);
3420 TString setupPar = "AliAnalysisAlien::SetupPar";
3421 while ((obj=next())) {
3422 pkgname = obj->GetName();
3423 if (pkgname == "STEERBase" ||
3424 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3425 if (pkgname == "ESD" ||
3426 pkgname == "ESD.par") hasESD = kTRUE;
3427 if (pkgname == "AOD" ||
3428 pkgname == "AOD.par") hasAOD = kTRUE;
3429 if (pkgname == "ANALYSIS" ||
3430 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3431 if (pkgname == "ANALYSISalice" ||
3432 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3433 if (pkgname == "CORRFW" ||
3434 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3436 if (hasANALYSISalice) setupPar = "SetupPar";
3437 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3438 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3439 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3440 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3441 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3442 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3443 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3444 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3445 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3446 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3447 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3448 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3449 out << "// Compile other par packages" << endl;
3451 while ((obj=next())) {
3452 pkgname = obj->GetName();
3453 if (pkgname == "STEERBase" ||
3454 pkgname == "STEERBase.par" ||
3456 pkgname == "ESD.par" ||
3458 pkgname == "AOD.par" ||
3459 pkgname == "ANALYSIS" ||
3460 pkgname == "ANALYSIS.par" ||
3461 pkgname == "ANALYSISalice" ||
3462 pkgname == "ANALYSISalice.par" ||
3463 pkgname == "CORRFW" ||
3464 pkgname == "CORRFW.par") continue;
3465 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3468 out << "// include path" << endl;
3469 // Get the include path from the interpreter and remove entries pointing to AliRoot
3470 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3471 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3472 out << " TIter nextpath(listpaths);" << endl;
3473 out << " TObjString *pname;" << endl;
3474 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3475 out << " TString current = pname->GetName();" << endl;
3476 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3477 out << " gSystem->AddIncludePath(current);" << endl;
3478 out << " }" << endl;
3479 out << " if (listpaths) delete listpaths;" << endl;
3480 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3481 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3482 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3483 if (fAdditionalLibs.Length()) {
3484 out << "// Add aditional AliRoot libraries" << endl;
3485 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3488 while((str=(TObjString*)next())) {
3489 if (str->GetString().Contains(".so"))
3490 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3492 if (list) delete list;
3495 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3496 if (fAnalysisSource.Length()) {
3497 TObjArray *list = fAnalysisSource.Tokenize(" ");
3500 while((str=(TObjString*)next())) {
3501 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3503 if (list) delete list;
3507 if (fFastReadOption) {
3508 Warning("WriteMergingMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid merging jobs. Note that this may skip some files that could be accessed !!!");
3509 out << "// fast xrootd reading enabled" << endl;
3510 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3511 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3512 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3513 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3514 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3515 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3517 // Change temp directory to current one
3518 out << "// Set temporary merging directory to current one" << endl;
3519 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3520 out << "// Connect to AliEn" << endl;
3521 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3522 out << " TString outputDir = dir;" << endl;
3523 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3524 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3525 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3526 out << " TIter *iter = new TIter(list);" << endl;
3527 out << " TObjString *str;" << endl;
3528 out << " TString outputFile;" << endl;
3529 out << " Bool_t merged = kTRUE;" << endl;
3530 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3531 out << " outputFile = str->GetString();" << endl;
3532 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3533 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3534 out << " if (index > 0) outputFile.Remove(index);" << endl;
3535 out << " // Skip already merged outputs" << endl;
3536 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3537 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3538 out << " continue;" << endl;
3539 out << " }" << endl;
3540 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3541 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3542 out << " if (!merged) {" << endl;
3543 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3544 out << " return;" << endl;
3545 out << " }" << endl;
3546 out << " }" << endl;
3547 out << " // all outputs merged, validate" << endl;
3548 out << " ofstream out;" << endl;
3549 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3550 out << " out.close();" << endl;
3551 out << " // read the analysis manager from file" << endl;
3552 TString analysisFile = fExecutable;
3553 analysisFile.ReplaceAll(".sh", ".root");
3554 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3555 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3556 out << " if (!file) return;" << endl;
3557 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3558 out << " AliAnalysisManager *mgr = 0;" << endl;
3559 out << " TKey *key;" << endl;
3560 out << " while ((key=(TKey*)nextkey())) {" << endl;
3561 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3562 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3563 out << " };" << endl;
3564 out << " if (!mgr) {" << endl;
3565 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3566 out << " return;" << endl;
3567 out << " }" << endl << endl;
3568 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3569 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3570 out << " mgr->PrintStatus();" << endl;
3571 if (AliAnalysisManager::GetAnalysisManager()) {
3572 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3573 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3575 if (TestBit(AliAnalysisGrid::kTest))
3576 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3578 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3581 out << " TTree *tree = NULL;" << endl;
3582 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3583 out << "}" << endl << endl;
3584 if (hasANALYSISalice) {
3585 out <<"//________________________________________________________________________________" << endl;
3586 out << "Bool_t SetupPar(const char *package) {" << endl;
3587 out << "// Compile the package and set it up." << endl;
3588 out << " TString pkgdir = package;" << endl;
3589 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3590 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3591 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3592 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3593 out << " // Check for BUILD.sh and execute" << endl;
3594 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3595 out << " printf(\"*******************************\\n\");" << endl;
3596 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3597 out << " printf(\"*******************************\\n\");" << endl;
3598 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3599 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3600 out << " gSystem->ChangeDirectory(cdir);" << endl;
3601 out << " return kFALSE;" << endl;
3602 out << " }" << endl;
3603 out << " } else {" << endl;
3604 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3605 out << " gSystem->ChangeDirectory(cdir);" << endl;
3606 out << " return kFALSE;" << endl;
3607 out << " }" << endl;
3608 out << " // Check for SETUP.C and execute" << endl;
3609 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3610 out << " printf(\"*******************************\\n\");" << endl;
3611 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3612 out << " printf(\"*******************************\\n\");" << endl;
3613 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3614 out << " } else {" << endl;
3615 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3616 out << " gSystem->ChangeDirectory(cdir);" << endl;
3617 out << " return kFALSE;" << endl;
3618 out << " }" << endl;
3619 out << " // Restore original workdir" << endl;
3620 out << " gSystem->ChangeDirectory(cdir);" << endl;
3621 out << " return kTRUE;" << endl;
3625 Bool_t copy = kTRUE;
3626 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3629 TString workdir = gGrid->GetHomeDirectory();
3630 workdir += fGridWorkingDir;
3631 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3632 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3633 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3637 //______________________________________________________________________________
3638 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3640 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3641 // Note that for loading the compiled library. The current directory should have precedence in
3643 TString pkgdir = package;
3644 pkgdir.ReplaceAll(".par","");
3645 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3646 TString cdir = gSystem->WorkingDirectory();
3647 gSystem->ChangeDirectory(pkgdir);
3648 // Check for BUILD.sh and execute
3649 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3650 printf("**************************************************\n");
3651 printf("*** Building PAR archive %s\n", package);
3652 printf("**************************************************\n");
3653 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3654 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3655 gSystem->ChangeDirectory(cdir);
3659 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3660 gSystem->ChangeDirectory(cdir);
3663 // Check for SETUP.C and execute
3664 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3665 printf("**************************************************\n");
3666 printf("*** Setup PAR archive %s\n", package);
3667 printf("**************************************************\n");
3668 gROOT->Macro("PROOF-INF/SETUP.C");
3669 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3671 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3672 gSystem->ChangeDirectory(cdir);
3675 // Restore original workdir
3676 gSystem->ChangeDirectory(cdir);
3680 //______________________________________________________________________________
3681 void AliAnalysisAlien::WriteExecutable()
3683 // Generate the alien executable script.
3684 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3686 out.open(fExecutable.Data(), ios::out);
3688 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3691 out << "#!/bin/bash" << endl;
3692 // Make sure we can properly compile par files
3693 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3694 out << "echo \"=========================================\"" << endl;
3695 out << "echo \"############## PATH : ##############\"" << endl;
3696 out << "echo $PATH" << endl;
3697 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3698 out << "echo $LD_LIBRARY_PATH" << endl;
3699 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3700 out << "echo $ROOTSYS" << endl;
3701 out << "echo \"############## which root : ##############\"" << endl;
3702 out << "which root" << endl;
3703 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3704 out << "echo $ALICE_ROOT" << endl;
3705 out << "echo \"############## which aliroot : ##############\"" << endl;
3706 out << "which aliroot" << endl;
3707 out << "echo \"############## system limits : ##############\"" << endl;
3708 out << "ulimit -a" << endl;
3709 out << "echo \"############## memory : ##############\"" << endl;
3710 out << "free -m" << endl;
3711 out << "echo \"=========================================\"" << endl << endl;
3712 out << fExecutableCommand << " ";
3713 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3714 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3715 out << "echo \"############## memory after: ##############\"" << endl;
3716 out << "free -m" << endl;
3718 Bool_t copy = kTRUE;
3719 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3722 TString workdir = gGrid->GetHomeDirectory();
3723 TString bindir = Form("%s/bin", workdir.Data());
3724 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3725 workdir += fGridWorkingDir;
3726 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3727 if (FileExists(executable)) gGrid->Rm(executable);
3728 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3729 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3733 //______________________________________________________________________________
3734 void AliAnalysisAlien::WriteMergeExecutable()
3736 // Generate the alien executable script for the merging job.
3737 if (!fMergeViaJDL) return;
3738 TString mergeExec = fExecutable;
3739 mergeExec.ReplaceAll(".sh", "_merge.sh");
3740 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3742 out.open(mergeExec.Data(), ios::out);
3744 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3747 out << "#!/bin/bash" << endl;
3748 // Make sure we can properly compile par files
3749 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3750 out << "echo \"=========================================\"" << endl;
3751 out << "echo \"############## PATH : ##############\"" << endl;
3752 out << "echo $PATH" << endl;
3753 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3754 out << "echo $LD_LIBRARY_PATH" << endl;
3755 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3756 out << "echo $ROOTSYS" << endl;
3757 out << "echo \"############## which root : ##############\"" << endl;
3758 out << "which root" << endl;
3759 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3760 out << "echo $ALICE_ROOT" << endl;
3761 out << "echo \"############## which aliroot : ##############\"" << endl;
3762 out << "which aliroot" << endl;
3763 out << "echo \"############## system limits : ##############\"" << endl;
3764 out << "ulimit -a" << endl;
3765 out << "echo \"############## memory : ##############\"" << endl;
3766 out << "free -m" << endl;
3767 out << "echo \"=========================================\"" << endl << endl;
3768 TString mergeMacro = fExecutable;
3769 mergeMacro.ReplaceAll(".sh", "_merge.C");
3770 if (IsOneStageMerging())
3771 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3773 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3774 out << fExecutableCommand << " " << "$ARG" << endl;
3775 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3776 out << "echo \"############## memory after: ##############\"" << endl;
3777 out << "free -m" << endl;
3779 Bool_t copy = kTRUE;
3780 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3783 TString workdir = gGrid->GetHomeDirectory();
3784 TString bindir = Form("%s/bin", workdir.Data());
3785 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3786 workdir += fGridWorkingDir;
3787 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3788 if (FileExists(executable)) gGrid->Rm(executable);
3789 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3790 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3794 //______________________________________________________________________________
3795 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3797 // Write the production file to be submitted by LPM manager. The format is:
3798 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3799 // Next lines: full_path_to_dataset XXX (XXX is a string)
3800 // To submit, one has to: submit jdl XXX for all lines
3802 out.open(filename, ios::out);
3804 Error("WriteProductionFile", "Bad file name: %s", filename);
3808 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3809 workdir = gGrid->GetHomeDirectory();
3810 workdir += fGridWorkingDir;
3811 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3812 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3813 out << locjdl << " " << njobspermaster << endl;
3814 Int_t nmasterjobs = fInputFiles->GetEntries();
3815 for (Int_t i=0; i<nmasterjobs; i++) {
3816 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3817 runOutDir.ReplaceAll(".xml", "");
3819 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3821 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3824 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3825 if (FileExists(filename)) gGrid->Rm(filename);
3826 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3830 //______________________________________________________________________________
3831 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3833 // Generate the alien validation script.
3834 // Generate the validation script
3836 if (fValidationScript.IsNull()) {
3837 fValidationScript = fExecutable;
3838 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3840 TString validationScript = fValidationScript;
3841 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3843 Error("WriteValidationScript", "Alien connection required");
3846 if (!fTerminateFiles.IsNull()) {
3847 fTerminateFiles.Strip();
3848 fTerminateFiles.ReplaceAll(" ",",");
3850 TString outStream = "";
3851 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3852 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3854 out.open(validationScript, ios::out);
3855 out << "#!/bin/bash" << endl;
3856 out << "##################################################" << endl;
3857 out << "validateout=`dirname $0`" << endl;
3858 out << "validatetime=`date`" << endl;
3859 out << "validated=\"0\";" << endl;
3860 out << "error=0" << endl;
3861 out << "if [ -z $validateout ]" << endl;
3862 out << "then" << endl;
3863 out << " validateout=\".\"" << endl;
3864 out << "fi" << endl << endl;
3865 out << "cd $validateout;" << endl;
3866 out << "validateworkdir=`pwd`;" << endl << endl;
3867 out << "echo \"*******************************************************\"" << outStream << endl;
3868 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3870 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3871 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3872 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3873 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3874 out << "ls -la ./" << outStream << endl;
3875 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3876 out << "##################################################" << endl;
3879 out << "if [ ! -f stderr ] ; then" << endl;
3880 out << " error=1" << endl;
3881 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3882 out << " echo \"Error = $error\" " << outStream << endl;
3883 out << "fi" << endl;
3885 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3886 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3887 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3888 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3891 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3892 out << " error=1" << endl;
3893 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3894 out << " echo \"$parArch\" " << outStream << endl;
3895 out << " echo \"Error = $error\" " << outStream << endl;
3896 out << "fi" << endl;
3898 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3899 out << " error=1" << endl;
3900 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3901 out << " echo \"$segViol\" " << outStream << endl;
3902 out << " echo \"Error = $error\" " << outStream << endl;
3903 out << "fi" << endl;
3905 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3906 out << " error=1" << endl;
3907 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3908 out << " echo \"$segFault\" " << outStream << endl;
3909 out << " echo \"Error = $error\" " << outStream << endl;
3910 out << "fi" << endl;
3912 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3913 out << " error=1" << endl;
3914 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3915 out << " echo \"$glibcErr\" " << outStream << endl;
3916 out << " echo \"Error = $error\" " << outStream << endl;
3917 out << "fi" << endl;
3919 // Part dedicated to the specific analyses running into the train
3921 TString outputFiles = fOutputFiles;
3922 if (merge && !fTerminateFiles.IsNull()) {
3924 outputFiles += fTerminateFiles;
3926 TObjArray *arr = outputFiles.Tokenize(",");
3929 while (!merge && (os=(TObjString*)next1())) {
3930 // No need to validate outputs produced by merging since the merging macro does this
3931 outputFile = os->GetString();
3932 Int_t index = outputFile.Index("@");
3933 if (index > 0) outputFile.Remove(index);
3934 if (fTerminateFiles.Contains(outputFile)) continue;
3935 if (outputFile.Contains("*")) continue;
3936 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
3937 out << " error=1" << endl;
3938 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
3939 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
3940 out << "fi" << endl;
3943 out << "if ! [ -f outputs_valid ] ; then" << endl;
3944 out << " error=1" << endl;
3945 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3946 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3947 out << "fi" << endl;
3949 out << "if [ $error = 0 ] ; then" << endl;
3950 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
3951 if (!IsKeepLogs()) {
3952 out << " echo \"* === Logs std* will be deleted === \"" << endl;
3954 out << " rm -f std*" << endl;
3956 out << "fi" << endl;
3958 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3959 out << "echo \"*******************************************************\"" << outStream << endl;
3960 out << "cd -" << endl;
3961 out << "exit $error" << endl;
3963 Bool_t copy = kTRUE;
3964 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3967 TString workdir = gGrid->GetHomeDirectory();
3968 workdir += fGridWorkingDir;
3969 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
3970 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3971 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));