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());
1003 // Exit if any error up to now
1004 if (error) return kFALSE;
1006 if (!fUser.IsNull()) {
1007 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1008 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1010 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1011 TString mergeExec = fExecutable;
1012 mergeExec.ReplaceAll(".sh", "_merge.sh");
1013 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1014 mergeExec.ReplaceAll(".sh", ".C");
1015 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1016 if (!fArguments.IsNull())
1017 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1018 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1020 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1021 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1024 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1025 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1026 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1027 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1029 if (fMaxInitFailed > 0) {
1030 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1031 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1033 if (fSplitMaxInputFileNumber > 0) {
1034 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1035 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1037 if (!IsOneStageMerging()) {
1038 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1039 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1041 if (fSplitMode.Length()) {
1042 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1043 fGridJDL->SetDescription("Split", "We split per SE or file");
1045 fMergingJDL->SetValue("Split", "\"se\"");
1046 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1047 if (!fAliROOTVersion.IsNull()) {
1048 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1049 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1051 if (!fROOTVersion.IsNull()) {
1052 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1053 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1055 if (!fAPIVersion.IsNull()) {
1056 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1057 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1059 if (!fExternalPackages.IsNull()) {
1060 arr = fExternalPackages.Tokenize(" ");
1062 while ((os=(TObjString*)next())) {
1063 TString pkgname = os->GetString();
1064 Int_t index = pkgname.Index("::");
1065 TString pkgversion = pkgname(index+2, pkgname.Length());
1066 pkgname.Remove(index);
1067 fGridJDL->AddToPackages(pkgname, pkgversion);
1068 fMergingJDL->AddToPackages(pkgname, pkgversion);
1072 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1073 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1074 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1075 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1076 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1077 TString analysisFile = fExecutable;
1078 analysisFile.ReplaceAll(".sh", ".root");
1079 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1080 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1081 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1082 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1083 if (fAdditionalLibs.Length()) {
1084 arr = fAdditionalLibs.Tokenize(" ");
1086 while ((os=(TObjString*)next())) {
1087 if (os->GetString().Contains(".so")) continue;
1088 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1089 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1094 TIter next(fPackages);
1096 while ((obj=next())) {
1097 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1098 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1101 if (fOutputArchive.Length()) {
1102 arr = fOutputArchive.Tokenize(" ");
1104 Bool_t first = kTRUE;
1105 const char *comment = "Files to be archived";
1106 const char *comment1 = comment;
1107 while ((os=(TObjString*)next())) {
1108 if (!first) comment = NULL;
1109 if (!os->GetString().Contains("@") && fCloseSE.Length())
1110 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1112 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1116 // Output archive for the merging jdl
1117 TString outputArchive;
1118 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1119 outputArchive = "log_archive.zip:std*@disk=1 ";
1120 // Add normal output files, extra files + terminate files
1121 TString files = GetListOfFiles("outextter");
1122 // Do not register merge excludes
1123 if (!fMergeExcludes.IsNull()) {
1124 arr = fMergeExcludes.Tokenize(" ");
1126 while ((os=(TObjString*)next1())) {
1127 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1128 files.ReplaceAll(os->GetString(),"");
1132 files.ReplaceAll(".root", "*.root");
1133 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1135 TString files = fOutputArchive;
1136 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1137 outputArchive = files;
1139 arr = outputArchive.Tokenize(" ");
1143 while ((os=(TObjString*)next2())) {
1144 if (!first) comment = NULL;
1145 TString currentfile = os->GetString();
1146 if (!currentfile.Contains("@") && fCloseSE.Length())
1147 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1149 fMergingJDL->AddToOutputArchive(currentfile, comment);
1154 arr = fOutputFiles.Tokenize(",");
1156 Bool_t first = kTRUE;
1157 const char *comment = "Files to be saved";
1158 while ((os=(TObjString*)next())) {
1159 // Ignore ouputs in jdl that are also in outputarchive
1160 TString sout = os->GetString();
1161 sout.ReplaceAll("*", "");
1162 sout.ReplaceAll(".root", "");
1163 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1164 if (fOutputArchive.Contains(sout)) continue;
1165 if (!first) comment = NULL;
1166 if (!os->GetString().Contains("@") && fCloseSE.Length())
1167 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1169 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1171 if (fMergeExcludes.Contains(sout)) continue;
1172 if (!os->GetString().Contains("@") && fCloseSE.Length())
1173 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1175 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1178 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1179 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1180 TString validationScript = fValidationScript;
1181 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1182 validationScript.ReplaceAll(".sh", "_merge.sh");
1183 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1184 if (fMasterResubmitThreshold) {
1185 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1186 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1188 // Write a jdl with 2 input parameters: collection name and output dir name.
1191 // Copy jdl to grid workspace
1193 // Check if an output directory was defined and valid
1194 if (!fGridOutputDir.Length()) {
1195 Error("CreateJDL", "You must define AliEn output directory");
1198 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1199 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1200 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1201 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1203 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1209 if (TestBit(AliAnalysisGrid::kSubmit)) {
1210 TString mergeJDLName = fExecutable;
1211 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1212 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1213 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1214 if (fProductionMode) {
1215 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1216 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1218 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1219 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1220 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1221 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1223 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1224 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1227 if (fAdditionalLibs.Length()) {
1228 arr = fAdditionalLibs.Tokenize(" ");
1231 while ((os=(TObjString*)next())) {
1232 if (os->GetString().Contains(".so")) continue;
1233 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1234 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1235 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1240 TIter next(fPackages);
1242 while ((obj=next())) {
1243 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1244 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1245 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1252 //______________________________________________________________________________
1253 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1255 // Writes one or more JDL's corresponding to findex. If findex is negative,
1256 // all run numbers are considered in one go (jdl). For non-negative indices
1257 // they correspond to the indices in the array fInputFiles.
1258 if (!fInputFiles) return kFALSE;
1261 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1262 workdir += fGridWorkingDir;
1263 TString stageName = "$2";
1264 if (fProductionMode) stageName = "$4";
1265 if (!fMergeDirName.IsNull()) {
1266 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1267 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1269 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1270 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1272 if (fProductionMode) {
1273 TIter next(fInputFiles);
1274 while ((os=next())) {
1275 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1277 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1279 if (!fRunNumbers.Length() && !fRunRange[0]) {
1280 // One jdl with no parameters in case input data is specified by name.
1281 TIter next(fInputFiles);
1283 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1284 if (!fOutputSingle.IsNull())
1285 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1287 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1288 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1291 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1292 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1293 if (!fOutputSingle.IsNull()) {
1294 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1295 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1297 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1302 // Generate the JDL as a string
1303 TString sjdl = fGridJDL->Generate();
1304 TString sjdl1 = fMergingJDL->Generate();
1306 if (!fMergeDirName.IsNull()) {
1307 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1308 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1310 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1311 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1313 TString sjdl2 = fMergingJDL->Generate();
1314 Int_t index, index1;
1315 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1316 sjdl.ReplaceAll("(member", "\n (member");
1317 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1318 sjdl.ReplaceAll("{", "{\n ");
1319 sjdl.ReplaceAll("};", "\n};");
1320 sjdl.ReplaceAll("{\n \n", "{\n");
1321 sjdl.ReplaceAll("\n\n", "\n");
1322 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1323 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1324 sjdl1.ReplaceAll("(member", "\n (member");
1325 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1326 sjdl1.ReplaceAll("{", "{\n ");
1327 sjdl1.ReplaceAll("};", "\n};");
1328 sjdl1.ReplaceAll("{\n \n", "{\n");
1329 sjdl1.ReplaceAll("\n\n", "\n");
1330 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1331 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1332 sjdl2.ReplaceAll("(member", "\n (member");
1333 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1334 sjdl2.ReplaceAll("{", "{\n ");
1335 sjdl2.ReplaceAll("};", "\n};");
1336 sjdl2.ReplaceAll("{\n \n", "{\n");
1337 sjdl2.ReplaceAll("\n\n", "\n");
1338 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1339 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1340 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1341 index = sjdl.Index("JDLVariables");
1342 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1343 sjdl += "Workdirectorysize = {\"5000MB\"};";
1344 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1345 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1346 index = fJobTag.Index(":");
1347 if (index < 0) index = fJobTag.Length();
1348 TString jobTag = fJobTag;
1349 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1350 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1351 if (fProductionMode) {
1352 sjdl1.Prepend("# Generated merging jdl (production mode) \
1353 \n# $1 = full alien path to output directory to be merged \
1354 \n# $2 = train number \
1355 \n# $3 = production (like LHC10b) \
1356 \n# $4 = merging stage \
1357 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1358 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1359 sjdl2.Prepend("# Generated merging jdl \
1360 \n# $1 = full alien path to output directory to be merged \
1361 \n# $2 = train number \
1362 \n# $3 = production (like LHC10b) \
1363 \n# $4 = merging stage \
1364 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1366 sjdl1.Prepend("# Generated merging jdl \
1367 \n# $1 = full alien path to output directory to be merged \
1368 \n# $2 = merging stage \
1369 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1370 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1371 sjdl2.Prepend("# Generated merging jdl \
1372 \n# $1 = full alien path to output directory to be merged \
1373 \n# $2 = merging stage \
1374 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1376 index = sjdl1.Index("JDLVariables");
1377 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1378 index = sjdl2.Index("JDLVariables");
1379 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1380 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1381 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1382 index = sjdl2.Index("Split =");
1384 index1 = sjdl2.Index("\n", index);
1385 sjdl2.Remove(index, index1-index+1);
1387 index = sjdl2.Index("SplitMaxInputFileNumber");
1389 index1 = sjdl2.Index("\n", index);
1390 sjdl2.Remove(index, index1-index+1);
1392 index = sjdl2.Index("InputDataCollection");
1394 index1 = sjdl2.Index(";", index);
1395 sjdl2.Remove(index, index1-index+1);
1397 index = sjdl2.Index("InputDataListFormat");
1399 index1 = sjdl2.Index("\n", index);
1400 sjdl2.Remove(index, index1-index+1);
1402 index = sjdl2.Index("InputDataList");
1404 index1 = sjdl2.Index("\n", index);
1405 sjdl2.Remove(index, index1-index+1);
1407 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1408 // Write jdl to file
1410 out.open(fJDLName.Data(), ios::out);
1412 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1415 out << sjdl << endl;
1417 TString mergeJDLName = fExecutable;
1418 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1421 out1.open(mergeJDLName.Data(), ios::out);
1423 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1426 out1 << sjdl1 << endl;
1429 TString finalJDL = mergeJDLName;
1430 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1431 out2.open(finalJDL.Data(), ios::out);
1433 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1436 out2 << sjdl2 << endl;
1440 // Copy jdl to grid workspace
1442 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1444 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1445 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1446 TString finalJDL = mergeJDLName;
1447 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1448 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1449 if (fProductionMode) {
1450 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1451 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1452 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1454 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1455 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1456 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1457 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1458 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1460 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1461 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1462 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1468 //______________________________________________________________________________
1469 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1471 // Returns true if file exists.
1472 if (!gGrid) return kFALSE;
1474 slfn.ReplaceAll("alien://","");
1475 TGridResult *res = gGrid->Ls(slfn);
1476 if (!res) return kFALSE;
1477 TMap *map = dynamic_cast<TMap*>(res->At(0));
1482 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1483 if (!objs || !objs->GetString().Length()) {
1491 //______________________________________________________________________________
1492 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1494 // Returns true if directory exists. Can be also a path.
1495 if (!gGrid) return kFALSE;
1496 // Check if dirname is a path
1497 TString dirstripped = dirname;
1498 dirstripped = dirstripped.Strip();
1499 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1500 TString dir = gSystem->BaseName(dirstripped);
1502 TString path = gSystem->DirName(dirstripped);
1503 TGridResult *res = gGrid->Ls(path, "-F");
1504 if (!res) return kFALSE;
1508 while ((map=dynamic_cast<TMap*>(next()))) {
1509 obj = map->GetValue("name");
1511 if (dir == obj->GetName()) {
1520 //______________________________________________________________________________
1521 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1523 // Check input data type.
1524 isCollection = kFALSE;
1528 Error("CheckDataType", "No connection to grid");
1531 isCollection = IsCollection(lfn);
1532 TString msg = "\n##### file: ";
1535 msg += " type: raw_collection;";
1536 // special treatment for collections
1538 // check for tag files in the collection
1539 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1541 msg += " using_tags: No (unknown)";
1542 Info("CheckDataType", "%s", msg.Data());
1545 const char* typeStr = res->GetKey(0, "origLFN");
1546 if (!typeStr || !strlen(typeStr)) {
1547 msg += " using_tags: No (unknown)";
1548 Info("CheckDataType", "%s", msg.Data());
1551 TString file = typeStr;
1552 useTags = file.Contains(".tag");
1553 if (useTags) msg += " using_tags: Yes";
1554 else msg += " using_tags: No";
1555 Info("CheckDataType", "%s", msg.Data());
1560 isXml = slfn.Contains(".xml");
1562 // Open xml collection and check if there are tag files inside
1563 msg += " type: xml_collection;";
1564 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1566 msg += " using_tags: No (unknown)";
1567 Info("CheckDataType", "%s", msg.Data());
1570 TMap *map = coll->Next();
1572 msg += " using_tags: No (unknown)";
1573 Info("CheckDataType", "%s", msg.Data());
1576 map = (TMap*)map->GetValue("");
1578 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1579 useTags = file.Contains(".tag");
1581 if (useTags) msg += " using_tags: Yes";
1582 else msg += " using_tags: No";
1583 Info("CheckDataType", "%s", msg.Data());
1586 useTags = slfn.Contains(".tag");
1587 if (slfn.Contains(".root")) msg += " type: root file;";
1588 else msg += " type: unknown file;";
1589 if (useTags) msg += " using_tags: Yes";
1590 else msg += " using_tags: No";
1591 Info("CheckDataType", "%s", msg.Data());
1594 //______________________________________________________________________________
1595 void AliAnalysisAlien::EnablePackage(const char *package)
1597 // Enables a par file supposed to exist in the current directory.
1598 TString pkg(package);
1599 pkg.ReplaceAll(".par", "");
1601 if (gSystem->AccessPathName(pkg)) {
1602 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1605 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1606 Info("EnablePackage", "AliEn plugin will use .par packages");
1607 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1609 fPackages = new TObjArray();
1610 fPackages->SetOwner();
1612 fPackages->Add(new TObjString(pkg));
1615 //______________________________________________________________________________
1616 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1618 // Make a tree from files having the location specified in fFileForTestMode.
1619 // Inspired from JF's CreateESDChain.
1620 if (fFileForTestMode.IsNull()) {
1621 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1624 if (gSystem->AccessPathName(fFileForTestMode)) {
1625 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1630 in.open(fFileForTestMode);
1632 // Read the input list of files and add them to the chain
1634 TChain *chain = new TChain(treeName);
1638 if (line.IsNull()) continue;
1639 if (count++ == fNtestFiles) break;
1640 TString esdFile(line);
1641 TFile *file = TFile::Open(esdFile);
1643 if (!file->IsZombie()) chain->Add(esdFile);
1646 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1650 if (!chain->GetListOfFiles()->GetEntries()) {
1651 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1659 //______________________________________________________________________________
1660 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1662 // Get job status for all jobs with jobid>jobidstart.
1663 static char mstatus[20];
1669 TGridJobStatusList *list = gGrid->Ps("");
1670 if (!list) return mstatus;
1671 Int_t nentries = list->GetSize();
1672 TGridJobStatus *status;
1674 for (Int_t ijob=0; ijob<nentries; ijob++) {
1675 status = (TGridJobStatus *)list->At(ijob);
1676 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1677 if (pid<jobidstart) continue;
1678 if (pid == lastid) {
1679 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1681 switch (status->GetStatus()) {
1682 case TGridJobStatus::kWAITING:
1684 case TGridJobStatus::kRUNNING:
1686 case TGridJobStatus::kABORTED:
1687 case TGridJobStatus::kFAIL:
1688 case TGridJobStatus::kUNKNOWN:
1690 case TGridJobStatus::kDONE:
1699 //______________________________________________________________________________
1700 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1702 // Returns true if file is a collection. Functionality duplicated from
1703 // TAlien::Type() because we don't want to directly depend on TAlien.
1705 Error("IsCollection", "No connection to grid");
1708 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1709 if (!res) return kFALSE;
1710 const char* typeStr = res->GetKey(0, "type");
1711 if (!typeStr || !strlen(typeStr)) return kFALSE;
1712 if (!strcmp(typeStr, "collection")) return kTRUE;
1717 //______________________________________________________________________________
1718 Bool_t AliAnalysisAlien::IsSingleOutput() const
1720 // Check if single-ouput option is on.
1721 return (!fOutputSingle.IsNull());
1724 //______________________________________________________________________________
1725 void AliAnalysisAlien::Print(Option_t *) const
1727 // Print current plugin settings.
1728 printf("### AliEn analysis plugin current settings ###\n");
1729 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1730 if (mgr && mgr->IsProofMode()) {
1731 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1732 if (TestBit(AliAnalysisGrid::kTest))
1733 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1734 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1735 if (!fProofDataSet.IsNull())
1736 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1738 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1740 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1741 if (!fRootVersionForProof.IsNull())
1742 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1744 printf("= ROOT version requested________________________ default\n");
1745 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1746 if (!fAliRootMode.IsNull())
1747 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1749 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1750 if (fNproofWorkersPerSlave)
1751 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1752 if (TestSpecialBit(kClearPackages))
1753 printf("= ClearPackages requested...\n");
1754 if (fIncludePath.Data())
1755 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1756 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1757 if (fPackages && fPackages->GetEntries()) {
1758 TIter next(fPackages);
1761 while ((obj=next())) list += obj->GetName();
1762 printf("= Par files to be used: ________________________ %s\n", list.Data());
1764 if (TestSpecialBit(kProofConnectGrid))
1765 printf("= Requested PROOF connection to grid\n");
1768 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1769 if (fOverwriteMode) {
1770 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1771 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1773 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1774 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1775 printf("= Production mode:______________________________ %d\n", fProductionMode);
1776 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1777 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1778 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1780 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1781 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1782 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1783 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1784 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1785 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1786 if (fRunNumbers.Length())
1787 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1789 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1790 if (!fRunRange[0] && !fRunNumbers.Length()) {
1791 TIter next(fInputFiles);
1794 while ((obj=next())) list += obj->GetName();
1795 printf("= Input files to be processed: _________________ %s\n", list.Data());
1797 if (TestBit(AliAnalysisGrid::kTest))
1798 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1799 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1800 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1801 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1802 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1803 printf("=====================================================================\n");
1804 printf("= Job price: ___________________________________ %d\n", fPrice);
1805 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1806 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1807 if (fMaxInitFailed>0)
1808 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1809 if (fMasterResubmitThreshold>0)
1810 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1811 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1812 if (fNrunsPerMaster>0)
1813 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1814 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1815 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1816 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1817 if (fArguments.Length())
1818 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1819 if (fExecutableArgs.Length())
1820 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1821 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1822 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1823 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1824 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1826 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1827 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1828 if (fIncludePath.Data())
1829 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1830 if (fCloseSE.Length())
1831 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1832 if (fFriendChainName.Length())
1833 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1834 if (fPackages && fPackages->GetEntries()) {
1835 TIter next(fPackages);
1838 while ((obj=next())) list += obj->GetName();
1839 printf("= Par files to be used: ________________________ %s\n", list.Data());
1843 //______________________________________________________________________________
1844 void AliAnalysisAlien::SetDefaults()
1846 // Set default values for everything. What cannot be filled will be left empty.
1847 if (fGridJDL) delete fGridJDL;
1848 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1849 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1852 fSplitMaxInputFileNumber = 100;
1854 fMasterResubmitThreshold = 0;
1859 fNrunsPerMaster = 1;
1860 fMaxMergeFiles = 100;
1862 fExecutable = "analysis.sh";
1863 fExecutableCommand = "root -b -q";
1865 fExecutableArgs = "";
1866 fAnalysisMacro = "myAnalysis.C";
1867 fAnalysisSource = "";
1868 fAdditionalLibs = "";
1872 fAliROOTVersion = "";
1873 fUser = ""; // Your alien user name
1874 fGridWorkingDir = "";
1875 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1876 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1877 fFriendChainName = "";
1878 fGridOutputDir = "output";
1879 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1880 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1881 fInputFormat = "xml-single";
1882 fJDLName = "analysis.jdl";
1883 fJobTag = "Automatically generated analysis JDL";
1884 fMergeExcludes = "";
1887 SetCheckCopy(kTRUE);
1888 SetDefaultOutputs(kTRUE);
1892 //______________________________________________________________________________
1893 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
1895 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1896 // First check if the result is already in the output directory.
1897 if (FileExists(Form("%s/%s",aliendir,filename))) {
1898 printf("Final merged results found. Not merging again.\n");
1901 // Now check the last stage done.
1904 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1907 // Next stage of merging
1909 TString pattern = "*root_archive.zip";
1910 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1911 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1912 if (res) delete res;
1913 // Write standard output to file
1914 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1915 // Count the number of files inside
1917 ifile.open(Form("Stage_%d.xml",stage));
1918 if (!ifile.good()) {
1919 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
1924 while (!ifile.eof()) {
1926 if (line.Contains("/event")) nfiles++;
1930 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1933 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
1935 // Copy the file in the output directory
1936 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1937 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1938 // Check if this is the last stage to be done.
1939 Bool_t laststage = (nfiles<nperchunk);
1940 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1942 printf("### Submiting final merging stage %d\n", stage);
1943 TString finalJDL = jdl;
1944 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1945 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
1946 Int_t jobId = SubmitSingleJob(query);
1947 if (!jobId) return kFALSE;
1949 printf("### Submiting merging stage %d\n", stage);
1950 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
1951 Int_t jobId = SubmitSingleJob(query);
1952 if (!jobId) return kFALSE;
1957 //______________________________________________________________________________
1958 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1960 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1961 if (!gGrid) return 0;
1962 printf("=> %s ------> ",query);
1963 TGridResult *res = gGrid->Command(query);
1965 TString jobId = res->GetKey(0,"jobId");
1967 if (jobId.IsNull()) {
1968 printf("submission failed. Reason:\n");
1971 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
1974 printf(" Job id: %s\n", jobId.Data());
1978 //______________________________________________________________________________
1979 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
1981 // Merge given output files from basedir. Basedir can be an alien output directory
1982 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
1983 // files in a group (ignored for xml input). Merging can be done in stages:
1984 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
1985 // stage=1 : works with an xml of all root_archive.zip in the output directory
1986 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
1987 TString outputFile = output;
1989 TString outputChunk;
1990 TString previousChunk = "";
1991 TObjArray *listoffiles = new TObjArray();
1992 // listoffiles->SetOwner();
1993 Int_t countChunk = 0;
1994 Int_t countZero = nmaxmerge;
1995 Bool_t merged = kTRUE;
1996 Int_t index = outputFile.Index("@");
1997 if (index > 0) outputFile.Remove(index);
1998 TString inputFile = outputFile;
1999 TString sbasedir = basedir;
2000 if (sbasedir.Contains(".xml")) {
2001 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2002 nmaxmerge = 9999999;
2003 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2005 ::Error("MergeOutput", "Input XML collection empty.");
2008 // Iterate grid collection
2009 while (coll->Next()) {
2010 TString fname = gSystem->DirName(coll->GetTURL());
2013 listoffiles->Add(new TNamed(fname.Data(),""));
2016 command = Form("find %s/ *%s", basedir, inputFile.Data());
2017 printf("command: %s\n", command.Data());
2018 TGridResult *res = gGrid->Command(command);
2020 ::Error("MergeOutput","No result for the find command\n");
2026 while ((map=(TMap*)nextmap())) {
2027 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2028 if (!objs || !objs->GetString().Length()) {
2029 // Nothing found - skip this output
2034 listoffiles->Add(new TNamed(objs->GetName(),""));
2038 if (!listoffiles->GetEntries()) {
2039 ::Error("MergeOutput","No result for the find command\n");
2044 TFileMerger *fm = 0;
2045 TIter next0(listoffiles);
2046 TObjArray *listoffilestmp = new TObjArray();
2047 listoffilestmp->SetOwner();
2050 // Keep only the files at upper level
2051 Int_t countChar = 0;
2052 while ((nextfile=next0())) {
2053 snextfile = nextfile->GetName();
2054 Int_t crtCount = snextfile.CountChar('/');
2055 if (nextfile == listoffiles->First()) countChar = crtCount;
2056 if (crtCount < countChar) countChar = crtCount;
2059 while ((nextfile=next0())) {
2060 snextfile = nextfile->GetName();
2061 Int_t crtCount = snextfile.CountChar('/');
2062 if (crtCount > countChar) {
2066 listoffilestmp->Add(nextfile);
2069 listoffiles = listoffilestmp; // Now contains 'good' files
2070 listoffiles->Print();
2071 TIter next(listoffiles);
2072 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2073 outputChunk = outputFile;
2074 outputChunk.ReplaceAll(".root", "_*.root");
2075 // Check for existent temporary merge files
2076 // Check overwrite mode and remove previous partial results if needed
2077 // Preserve old merging functionality for stage 0.
2079 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2081 // Skip as many input files as in a chunk
2082 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2085 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2089 snextfile = nextfile->GetName();
2091 outputChunk = outputFile;
2092 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2094 if (gSystem->AccessPathName(outputChunk)) continue;
2095 // Merged file with chunks up to <countChunk> found
2096 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2097 previousChunk = outputChunk;
2101 countZero = nmaxmerge;
2103 while ((nextfile=next())) {
2104 snextfile = nextfile->GetName();
2105 // Loop 'find' results and get next LFN
2106 if (countZero == nmaxmerge) {
2107 // First file in chunk - create file merger and add previous chunk if any.
2108 fm = new TFileMerger(kFALSE);
2109 fm->SetFastMethod(kTRUE);
2110 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2111 outputChunk = outputFile;
2112 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2114 // If last file found, put merged results in the output file
2115 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2116 // Add file to be merged and decrement chunk counter.
2117 fm->AddFile(snextfile);
2119 if (countZero==0 || nextfile == listoffiles->Last()) {
2120 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2121 // Nothing found - skip this output
2122 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2126 fm->OutputFile(outputChunk);
2127 // Merge the outputs, then go to next chunk
2129 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2133 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2134 gSystem->Unlink(previousChunk);
2136 if (nextfile == listoffiles->Last()) break;
2138 countZero = nmaxmerge;
2139 previousChunk = outputChunk;
2146 // Merging stage different than 0.
2147 // Move to the begining of the requested chunk.
2148 fm = new TFileMerger(kFALSE);
2149 fm->SetFastMethod(kTRUE);
2150 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2152 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2153 // Nothing found - skip this output
2154 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2158 fm->OutputFile(outputFile);
2159 // Merge the outputs
2161 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2165 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2171 //______________________________________________________________________________
2172 Bool_t AliAnalysisAlien::MergeOutputs()
2174 // Merge analysis outputs existing in the AliEn space.
2175 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2176 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2178 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2182 if (!TestBit(AliAnalysisGrid::kMerge)) {
2183 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2186 if (fProductionMode) {
2187 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2190 Info("MergeOutputs", "Submitting merging JDL");
2191 if (!SubmitMerging()) return kFALSE;
2192 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2193 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2196 // Get the output path
2197 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2198 if (!DirectoryExists(fGridOutputDir)) {
2199 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2202 if (!fOutputFiles.Length()) {
2203 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2206 // Check if fast read option was requested
2207 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2208 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2209 if (fFastReadOption) {
2210 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2211 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2212 gEnv->SetValue("XNet.ConnectTimeout",50);
2213 gEnv->SetValue("XNet.RequestTimeout",50);
2214 gEnv->SetValue("XNet.MaxRedirectCount",2);
2215 gEnv->SetValue("XNet.ReconnectTimeout",50);
2216 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2218 // Make sure we change the temporary directory
2219 gSystem->Setenv("TMPDIR", gSystem->pwd());
2220 TObjArray *list = fOutputFiles.Tokenize(",");
2224 Bool_t merged = kTRUE;
2225 while((str=(TObjString*)next())) {
2226 outputFile = str->GetString();
2227 Int_t index = outputFile.Index("@");
2228 if (index > 0) outputFile.Remove(index);
2229 TString outputChunk = outputFile;
2230 outputChunk.ReplaceAll(".root", "_*.root");
2231 // Skip already merged outputs
2232 if (!gSystem->AccessPathName(outputFile)) {
2233 if (fOverwriteMode) {
2234 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2235 gSystem->Unlink(outputFile);
2236 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2237 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2238 outputChunk.Data());
2239 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2242 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2246 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2247 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2248 outputChunk.Data());
2249 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2252 if (fMergeExcludes.Length() &&
2253 fMergeExcludes.Contains(outputFile.Data())) continue;
2254 // Perform a 'find' command in the output directory, looking for registered outputs
2255 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2257 Error("MergeOutputs", "Terminate() will NOT be executed");
2260 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2261 if (fileOpened) fileOpened->Close();
2266 //______________________________________________________________________________
2267 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2269 // Use the output files connected to output containers from the analysis manager
2270 // rather than the files defined by SetOutputFiles
2271 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2272 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2273 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2276 //______________________________________________________________________________
2277 void AliAnalysisAlien::SetOutputFiles(const char *list)
2279 // Manually set the output files list.
2280 // Removes duplicates. Not allowed if default outputs are not disabled.
2281 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2282 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2285 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2287 TString slist = list;
2288 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2289 TObjArray *arr = slist.Tokenize(" ");
2293 while ((os=(TObjString*)next())) {
2294 sout = os->GetString();
2295 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2296 if (fOutputFiles.Contains(sout)) continue;
2297 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2298 fOutputFiles += sout;
2303 //______________________________________________________________________________
2304 void AliAnalysisAlien::SetOutputArchive(const char *list)
2306 // Manually set the output archive list. Free text - you are on your own...
2307 // Not allowed if default outputs are not disabled.
2308 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2309 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2312 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2313 fOutputArchive = list;
2316 //______________________________________________________________________________
2317 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2319 // Setting a prefered output SE is not allowed anymore.
2320 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2323 //______________________________________________________________________________
2324 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2326 // Start remote grid analysis.
2327 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2328 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2329 if (!mgr || !mgr->IsInitialized()) {
2330 Error("StartAnalysis", "You need an initialized analysis manager for this");
2333 // Are we in PROOF mode ?
2334 if (mgr->IsProofMode()) {
2335 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2336 if (fProofCluster.IsNull()) {
2337 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2340 if (fProofDataSet.IsNull() && !testMode) {
2341 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2344 // Set the needed environment
2345 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2346 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2347 if (fProofReset && !testMode) {
2348 if (fProofReset==1) {
2349 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2350 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2352 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2353 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2355 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2358 // Do we need to change the ROOT version ? The success of this cannot be checked.
2359 if (!fRootVersionForProof.IsNull() && !testMode) {
2360 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2361 fProofCluster.Data(), fRootVersionForProof.Data()));
2363 // Connect to PROOF and check the status
2366 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2367 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2369 if (!sworkers.IsNull())
2370 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2372 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2374 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2376 Error("StartAnalysis", "Could not start PROOF in test mode");
2381 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2384 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2385 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2386 // Is dataset existing ?
2388 TString dataset = fProofDataSet;
2389 Int_t index = dataset.Index("#");
2390 if (index>=0) dataset.Remove(index);
2391 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2392 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2395 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2397 // Is ClearPackages() needed ?
2398 if (TestSpecialBit(kClearPackages)) {
2399 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2400 gROOT->ProcessLine("gProof->ClearPackages();");
2402 // Is a given aliroot mode requested ?
2405 if (!fAliRootMode.IsNull()) {
2406 TString alirootMode = fAliRootMode;
2407 if (alirootMode == "default") alirootMode = "";
2408 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2409 optionsList.SetOwner();
2410 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2411 // Check the additional libs to be loaded
2413 Bool_t parMode = kFALSE;
2414 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2415 // Parse the extra libs for .so
2416 if (fAdditionalLibs.Length()) {
2417 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2420 while((str=(TObjString*)next())) {
2421 if (str->GetString().Contains(".so")) {
2423 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());
2426 TString stmp = str->GetName();
2427 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2428 stmp.ReplaceAll(".so","");
2429 if (!extraLibs.IsNull()) extraLibs += ":";
2433 if (str->GetString().Contains(".par")) {
2434 // The first par file found in the list will not allow any further .so
2436 if (!parLibs.IsNull()) parLibs += ":";
2437 parLibs += str->GetName();
2441 if (list) delete list;
2443 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2444 // Check extra includes
2445 if (!fIncludePath.IsNull()) {
2446 TString includePath = fIncludePath;
2447 includePath.ReplaceAll(" ",":");
2448 includePath.ReplaceAll("$ALICE_ROOT","");
2449 includePath.ReplaceAll("${ALICE_ROOT}","");
2450 includePath.ReplaceAll("-I","");
2451 includePath.Strip(TString::kTrailing, ':');
2452 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2453 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2455 // Check if connection to grid is requested
2456 if (TestSpecialBit(kProofConnectGrid))
2457 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2458 // Enable AliRoot par
2460 // Enable proof lite package
2461 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2462 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2463 TNamed *obj = (TNamed*)optionsList.At(i);
2464 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2466 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2467 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2468 Info("StartAnalysis", "AliRootProofLite enabled");
2470 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2474 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2475 fAliROOTVersion.Data(), &optionsList))) {
2476 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2480 // Enable first par files from fAdditionalLibs
2481 if (!parLibs.IsNull()) {
2482 TObjArray *list = parLibs.Tokenize(":");
2484 TObjString *package;
2485 while((package=(TObjString*)next())) {
2486 TString spkg = package->GetName();
2487 spkg.ReplaceAll(".par", "");
2488 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2489 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2490 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2491 if (gROOT->ProcessLine(enablePackage)) {
2492 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2496 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2500 if (list) delete list;
2503 if (fAdditionalLibs.Contains(".so") && !testMode) {
2504 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2505 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2509 // Enable par files if requested
2510 if (fPackages && fPackages->GetEntries()) {
2511 TIter next(fPackages);
2513 while ((package=next())) {
2514 // Skip packages already enabled
2515 if (parLibs.Contains(package->GetName())) continue;
2516 TString spkg = package->GetName();
2517 spkg.ReplaceAll(".par", "");
2518 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2519 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2520 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2521 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2525 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2530 // Do we need to load analysis source files ?
2531 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2532 if (fAnalysisSource.Length()) {
2533 TObjArray *list = fAnalysisSource.Tokenize(" ");
2536 while((str=(TObjString*)next())) {
2537 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2539 if (list) delete list;
2542 // Register dataset to proof lite.
2543 if (fFileForTestMode.IsNull()) {
2544 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2547 if (gSystem->AccessPathName(fFileForTestMode)) {
2548 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2551 TFileCollection *coll = new TFileCollection();
2552 coll->AddFromFile(fFileForTestMode);
2553 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2554 gROOT->ProcessLine("gProof->ShowDataSets()");
2559 // Check if output files have to be taken from the analysis manager
2560 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2561 // Add output files and AOD files
2562 fOutputFiles = GetListOfFiles("outaod");
2563 // Add extra files registered to the analysis manager
2564 TString extra = GetListOfFiles("ext");
2565 if (!extra.IsNull()) {
2566 extra.ReplaceAll(".root", "*.root");
2567 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2568 fOutputFiles += extra;
2570 // Compose the output archive.
2571 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2572 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2574 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2575 if (TestBit(AliAnalysisGrid::kOffline)) {
2576 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2577 \n there nor any job run. You can revise the JDL and analysis \
2578 \n macro then run the same in \"submit\" mode.");
2579 } else if (TestBit(AliAnalysisGrid::kTest)) {
2580 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2582 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2583 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2584 \n space and job submitted.");
2585 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2586 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2587 if (fMergeViaJDL) CheckInputData();
2590 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2595 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2598 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2599 if (!CheckInputData()) {
2600 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2603 if (!CreateDataset(fDataPattern)) {
2605 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2606 if (fRunNumbers.Length()) serror = "run numbers";
2607 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2608 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2609 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2612 WriteAnalysisFile();
2613 WriteAnalysisMacro();
2615 WriteValidationScript();
2617 WriteMergingMacro();
2618 WriteMergeExecutable();
2619 WriteValidationScript(kTRUE);
2621 if (!CreateJDL()) return kFALSE;
2622 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2624 // Locally testing the analysis
2625 Info("StartAnalysis", "\n_______________________________________________________________________ \
2626 \n Running analysis script in a daughter shell as on a worker node \
2627 \n_______________________________________________________________________");
2628 TObjArray *list = fOutputFiles.Tokenize(",");
2632 while((str=(TObjString*)next())) {
2633 outputFile = str->GetString();
2634 Int_t index = outputFile.Index("@");
2635 if (index > 0) outputFile.Remove(index);
2636 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2639 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2640 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2641 // gSystem->Exec("cat stdout");
2644 // Check if submitting is managed by LPM manager
2645 if (fProductionMode) {
2646 TString prodfile = fJDLName;
2647 prodfile.ReplaceAll(".jdl", ".prod");
2648 WriteProductionFile(prodfile);
2649 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2652 // Submit AliEn job(s)
2653 gGrid->Cd(fGridOutputDir);
2656 if (!fRunNumbers.Length() && !fRunRange[0]) {
2657 // Submit a given xml or a set of runs
2658 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2659 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2661 const char *cjobId = res->GetKey(0,"jobId");
2665 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2668 Info("StartAnalysis", "\n_______________________________________________________________________ \
2669 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2670 \n_______________________________________________________________________",
2671 fJDLName.Data(), cjobId);
2676 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2680 // Submit for a range of enumeration of runs.
2681 if (!Submit()) return kFALSE;
2684 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2685 \n You may exit at any time and terminate the job later using the option <terminate> \
2686 \n ##################################################################################", jobID.Data());
2687 gSystem->Exec("aliensh");
2691 //______________________________________________________________________________
2692 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2694 // Get a comma-separated list of output files of the requested type.
2695 // Type can be (case unsensitive):
2696 // aod - list of aod files (std, extensions and filters)
2697 // out - list of output files connected to containers (but not aod's or extras)
2698 // ext - list of extra files registered to the manager
2699 // ter - list of files produced in terminate
2700 static TString files;
2702 TString stype = type;
2704 TString aodfiles, extra;
2705 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2707 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2708 return files.Data();
2710 if (mgr->GetOutputEventHandler()) {
2711 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2712 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2713 if (!extraaod.IsNull()) {
2715 aodfiles += extraaod;
2718 if (stype.Contains("aod")) {
2720 if (stype == "aod") return files.Data();
2722 // Add output files that are not in the list of AOD files
2723 TString outputfiles = "";
2724 TIter next(mgr->GetOutputs());
2725 AliAnalysisDataContainer *output;
2726 const char *filename = 0;
2727 while ((output=(AliAnalysisDataContainer*)next())) {
2728 filename = output->GetFileName();
2729 if (!(strcmp(filename, "default"))) continue;
2730 if (outputfiles.Contains(filename)) continue;
2731 if (aodfiles.Contains(filename)) continue;
2732 if (!outputfiles.IsNull()) outputfiles += ",";
2733 outputfiles += filename;
2735 if (stype.Contains("out")) {
2736 if (!files.IsNull()) files += ",";
2737 files += outputfiles;
2738 if (stype == "out") return files.Data();
2740 // Add extra files registered to the analysis manager
2742 extra = mgr->GetExtraFiles();
2743 if (!extra.IsNull()) {
2745 extra.ReplaceAll(" ", ",");
2746 TObjArray *fextra = extra.Tokenize(",");
2747 TIter nextx(fextra);
2749 while ((obj=nextx())) {
2750 if (aodfiles.Contains(obj->GetName())) continue;
2751 if (outputfiles.Contains(obj->GetName())) continue;
2752 if (sextra.Contains(obj->GetName())) continue;
2753 if (!sextra.IsNull()) sextra += ",";
2754 sextra += obj->GetName();
2757 if (stype.Contains("ext")) {
2758 if (!files.IsNull()) files += ",";
2762 if (stype == "ext") return files.Data();
2764 if (!fTerminateFiles.IsNull()) {
2765 fTerminateFiles.Strip();
2766 fTerminateFiles.ReplaceAll(" ",",");
2767 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2768 TIter nextx(fextra);
2770 while ((obj=nextx())) {
2771 if (aodfiles.Contains(obj->GetName())) continue;
2772 if (outputfiles.Contains(obj->GetName())) continue;
2773 if (termfiles.Contains(obj->GetName())) continue;
2774 if (sextra.Contains(obj->GetName())) continue;
2775 if (!termfiles.IsNull()) termfiles += ",";
2776 termfiles += obj->GetName();
2780 if (stype.Contains("ter")) {
2781 if (!files.IsNull() && !termfiles.IsNull()) {
2786 return files.Data();
2789 //______________________________________________________________________________
2790 Bool_t AliAnalysisAlien::Submit()
2792 // Submit all master jobs.
2793 Int_t nmasterjobs = fInputFiles->GetEntries();
2794 Long_t tshoot = gSystem->Now();
2795 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2796 while (fNsubmitted < nmasterjobs) {
2797 Long_t now = gSystem->Now();
2798 if ((now-tshoot)>30000) {
2800 if (!SubmitNext()) return kFALSE;
2806 //______________________________________________________________________________
2807 Bool_t AliAnalysisAlien::SubmitMerging()
2809 // Submit all merging jobs.
2810 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2811 gGrid->Cd(fGridOutputDir);
2812 TString mergeJDLName = fExecutable;
2813 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2814 Int_t ntosubmit = fInputFiles->GetEntries();
2815 for (Int_t i=0; i<ntosubmit; i++) {
2816 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2817 runOutDir.ReplaceAll(".xml", "");
2818 if (fOutputToRunNo) {
2819 // The output directory is the run number
2820 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2821 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2823 // The output directory is the master number in 3 digits format
2824 printf("### Submitting merging job for master <%03d>\n", i);
2825 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2827 // Check now the number of merging stages.
2828 TObjArray *list = fOutputFiles.Tokenize(",");
2832 while((str=(TObjString*)next())) {
2833 outputFile = str->GetString();
2834 Int_t index = outputFile.Index("@");
2835 if (index > 0) outputFile.Remove(index);
2836 if (!fMergeExcludes.Contains(outputFile)) break;
2839 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2840 if (!done) return kFALSE;
2842 if (!ntosubmit) return kTRUE;
2843 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
2844 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
2845 \n ##################################################################################");
2846 gSystem->Exec("aliensh");
2850 //______________________________________________________________________________
2851 Bool_t AliAnalysisAlien::SubmitNext()
2853 // Submit next bunch of master jobs if the queue is free. The first master job is
2854 // submitted right away, while the next will not be unless the previous was split.
2855 // The plugin will not submit new master jobs if there are more that 500 jobs in
2857 static Bool_t iscalled = kFALSE;
2858 static Int_t firstmaster = 0;
2859 static Int_t lastmaster = 0;
2860 static Int_t npermaster = 0;
2861 if (iscalled) return kTRUE;
2863 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2864 Int_t ntosubmit = 0;
2867 Int_t nmasterjobs = fInputFiles->GetEntries();
2870 if (!IsUseSubmitPolicy()) {
2872 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2873 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2874 ntosubmit = nmasterjobs;
2877 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2878 printf("=== master %d: %s\n", lastmaster, status.Data());
2879 // If last master not split, just return
2880 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2881 // No more than 100 waiting jobs
2882 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2883 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2884 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2885 if (!ntosubmit) ntosubmit = 1;
2886 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2887 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2889 for (Int_t i=0; i<ntosubmit; i++) {
2890 // Submit for a range of enumeration of runs.
2891 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2893 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2894 runOutDir.ReplaceAll(".xml", "");
2896 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2898 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2899 printf("********* %s\n",query.Data());
2900 res = gGrid->Command(query);
2902 TString cjobId1 = res->GetKey(0,"jobId");
2903 if (!cjobId1.Length()) {
2907 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2910 Info("StartAnalysis", "\n_______________________________________________________________________ \
2911 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2912 \n_______________________________________________________________________",
2913 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2916 lastmaster = cjobId1.Atoi();
2917 if (!firstmaster) firstmaster = lastmaster;
2922 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2930 //______________________________________________________________________________
2931 void AliAnalysisAlien::WriteAnalysisFile()
2933 // Write current analysis manager into the file <analysisFile>
2934 TString analysisFile = fExecutable;
2935 analysisFile.ReplaceAll(".sh", ".root");
2936 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2937 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2938 if (!mgr || !mgr->IsInitialized()) {
2939 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2942 // Check analysis type
2944 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2945 handler = (TObject*)mgr->GetInputEventHandler();
2947 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2948 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2950 TDirectory *cdir = gDirectory;
2951 TFile *file = TFile::Open(analysisFile, "RECREATE");
2953 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2954 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
2955 // Unless merging makes no sense
2956 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2959 // Enable termination for local jobs
2960 mgr->SetSkipTerminate(kFALSE);
2962 if (cdir) cdir->cd();
2963 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2965 Bool_t copy = kTRUE;
2966 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2969 TString workdir = gGrid->GetHomeDirectory();
2970 workdir += fGridWorkingDir;
2971 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2972 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2973 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2977 //______________________________________________________________________________
2978 void AliAnalysisAlien::WriteAnalysisMacro()
2980 // Write the analysis macro that will steer the analysis in grid mode.
2981 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2983 out.open(fAnalysisMacro.Data(), ios::out);
2985 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2988 Bool_t hasSTEERBase = kFALSE;
2989 Bool_t hasESD = kFALSE;
2990 Bool_t hasAOD = kFALSE;
2991 Bool_t hasANALYSIS = kFALSE;
2992 Bool_t hasANALYSISalice = kFALSE;
2993 Bool_t hasCORRFW = kFALSE;
2994 TString func = fAnalysisMacro;
2995 TString type = "ESD";
2996 TString comment = "// Analysis using ";
2997 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2998 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3002 if (type!="AOD" && fFriendChainName!="") {
3003 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3006 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3007 else comment += " data";
3008 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3009 func.ReplaceAll(".C", "");
3010 out << "void " << func.Data() << "()" << endl;
3012 out << comment.Data() << endl;
3013 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3014 out << " TStopwatch timer;" << endl;
3015 out << " timer.Start();" << endl << endl;
3016 // Change temp directory to current one
3017 out << "// Set temporary merging directory to current one" << endl;
3018 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3019 // Reset existing include path
3020 out << "// Reset existing include path and add current directory first in the search" << endl;
3021 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3022 if (!fExecutableCommand.Contains("aliroot")) {
3023 out << "// load base root libraries" << endl;
3024 out << " gSystem->Load(\"libTree\");" << endl;
3025 out << " gSystem->Load(\"libGeom\");" << endl;
3026 out << " gSystem->Load(\"libVMC\");" << endl;
3027 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3028 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3030 if (fAdditionalRootLibs.Length()) {
3031 // in principle libtree /lib geom libvmc etc. can go into this list, too
3032 out << "// Add aditional libraries" << endl;
3033 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3036 while((str=(TObjString*)next())) {
3037 if (str->GetString().Contains(".so"))
3038 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3040 if (list) delete list;
3042 out << "// Load analysis framework libraries" << endl;
3043 TString setupPar = "AliAnalysisAlien::SetupPar";
3045 if (!fExecutableCommand.Contains("aliroot")) {
3046 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3047 out << " gSystem->Load(\"libESD\");" << endl;
3048 out << " gSystem->Load(\"libAOD\");" << endl;
3050 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3051 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3052 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3054 TIter next(fPackages);
3057 while ((obj=next())) {
3058 pkgname = obj->GetName();
3059 if (pkgname == "STEERBase" ||
3060 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3061 if (pkgname == "ESD" ||
3062 pkgname == "ESD.par") hasESD = kTRUE;
3063 if (pkgname == "AOD" ||
3064 pkgname == "AOD.par") hasAOD = kTRUE;
3065 if (pkgname == "ANALYSIS" ||
3066 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3067 if (pkgname == "ANALYSISalice" ||
3068 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3069 if (pkgname == "CORRFW" ||
3070 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3072 if (hasANALYSISalice) setupPar = "SetupPar";
3073 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3074 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3075 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3076 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3077 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3078 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3079 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3080 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3081 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3082 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3083 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3084 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3085 out << "// Compile other par packages" << endl;
3087 while ((obj=next())) {
3088 pkgname = obj->GetName();
3089 if (pkgname == "STEERBase" ||
3090 pkgname == "STEERBase.par" ||
3092 pkgname == "ESD.par" ||
3094 pkgname == "AOD.par" ||
3095 pkgname == "ANALYSIS" ||
3096 pkgname == "ANALYSIS.par" ||
3097 pkgname == "ANALYSISalice" ||
3098 pkgname == "ANALYSISalice.par" ||
3099 pkgname == "CORRFW" ||
3100 pkgname == "CORRFW.par") continue;
3101 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3104 out << "// include path" << endl;
3105 // Get the include path from the interpreter and remove entries pointing to AliRoot
3106 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3107 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3108 out << " TIter nextpath(listpaths);" << endl;
3109 out << " TObjString *pname;" << endl;
3110 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3111 out << " TString current = pname->GetName();" << endl;
3112 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3113 out << " gSystem->AddIncludePath(current);" << endl;
3114 out << " }" << endl;
3115 out << " if (listpaths) delete listpaths;" << endl;
3116 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3117 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3118 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3119 if (fAdditionalLibs.Length()) {
3120 out << "// Add aditional AliRoot libraries" << endl;
3121 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3124 while((str=(TObjString*)next())) {
3125 if (str->GetString().Contains(".so"))
3126 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3127 if (str->GetString().Contains(".par"))
3128 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3130 if (list) delete list;
3133 out << "// analysis source to be compiled at runtime (if any)" << endl;
3134 if (fAnalysisSource.Length()) {
3135 TObjArray *list = fAnalysisSource.Tokenize(" ");
3138 while((str=(TObjString*)next())) {
3139 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3141 if (list) delete list;
3144 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3145 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3146 if (fFastReadOption) {
3147 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 !!! \
3148 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3149 out << "// fast xrootd reading enabled" << endl;
3150 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3151 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3152 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3153 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3154 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3155 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3157 out << "// connect to AliEn and make the chain" << endl;
3158 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3159 out << "// read the analysis manager from file" << endl;
3160 TString analysisFile = fExecutable;
3161 analysisFile.ReplaceAll(".sh", ".root");
3162 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3163 out << " if (!file) return;" << endl;
3164 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3165 out << " AliAnalysisManager *mgr = 0;" << endl;
3166 out << " TKey *key;" << endl;
3167 out << " while ((key=(TKey*)nextkey())) {" << endl;
3168 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3169 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3170 out << " };" << endl;
3171 out << " if (!mgr) {" << endl;
3172 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3173 out << " return;" << endl;
3174 out << " }" << endl << endl;
3175 out << " mgr->PrintStatus();" << endl;
3176 if (AliAnalysisManager::GetAnalysisManager()) {
3177 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3178 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3180 if (TestBit(AliAnalysisGrid::kTest))
3181 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3183 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3186 if (IsUsingTags()) {
3187 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3189 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3191 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3192 out << " timer.Stop();" << endl;
3193 out << " timer.Print();" << endl;
3194 out << "}" << endl << endl;
3195 if (IsUsingTags()) {
3196 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3198 out << "// Create a chain using tags from the xml file." << endl;
3199 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3200 out << " if (!coll) {" << endl;
3201 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3202 out << " return NULL;" << endl;
3203 out << " }" << endl;
3204 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3205 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3206 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3207 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3208 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3209 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3210 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3211 out << " // Check if the cuts configuration file was provided" << endl;
3212 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3213 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3214 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3215 out << " }" << endl;
3216 if (fFriendChainName=="") {
3217 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3219 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3220 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3221 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3223 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3224 out << " chain->ls();" << endl;
3225 out << " return chain;" << endl;
3226 out << "}" << endl << endl;
3227 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3228 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3229 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3230 msg += " AliLHCTagCuts *lhcCuts,\n";
3231 msg += " AliDetectorTagCuts *detCuts,\n";
3232 msg += " AliEventTagCuts *evCuts)";
3233 Info("WriteAnalysisMacro", "%s", msg.Data());
3236 if (!IsUsingTags() || fFriendChainName!="") {
3237 out <<"//________________________________________________________________________________" << endl;
3238 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3240 out << "// Create a chain using url's from xml file" << endl;
3241 out << " TString filename;" << endl;
3242 out << " Int_t run = 0;" << endl;
3243 out << " TString treename = type;" << endl;
3244 out << " treename.ToLower();" << endl;
3245 out << " treename += \"Tree\";" << endl;
3246 out << " printf(\"***************************************\\n\");" << endl;
3247 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3248 out << " printf(\"***************************************\\n\");" << endl;
3249 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3250 out << " if (!coll) {" << endl;
3251 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3252 out << " return NULL;" << endl;
3253 out << " }" << endl;
3254 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3255 out << " TChain *chain = new TChain(treename);" << endl;
3256 if(fFriendChainName!="") {
3257 out << " TChain *chainFriend = new TChain(treename);" << endl;
3259 out << " coll->Reset();" << endl;
3260 out << " while (coll->Next()) {" << endl;
3261 out << " filename = coll->GetTURL("");" << endl;
3262 out << " if (mgr) {" << endl;
3263 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3264 out << " if (nrun && nrun != run) {" << endl;
3265 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3266 out << " mgr->SetRunFromPath(nrun);" << endl;
3267 out << " run = nrun;" << endl;
3268 out << " }" << endl;
3269 out << " }" << endl;
3270 out << " chain->Add(filename);" << endl;
3271 if(fFriendChainName!="") {
3272 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3273 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3274 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3275 out << " chainFriend->Add(fileFriend.Data());" << endl;
3277 out << " }" << endl;
3278 out << " if (!chain->GetNtrees()) {" << endl;
3279 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3280 out << " return NULL;" << endl;
3281 out << " }" << endl;
3282 if(fFriendChainName!="") {
3283 out << " chain->AddFriend(chainFriend);" << endl;
3285 out << " return chain;" << endl;
3286 out << "}" << endl << endl;
3288 if (hasANALYSISalice) {
3289 out <<"//________________________________________________________________________________" << endl;
3290 out << "Bool_t SetupPar(const char *package) {" << endl;
3291 out << "// Compile the package and set it up." << endl;
3292 out << " TString pkgdir = package;" << endl;
3293 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3294 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3295 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3296 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3297 out << " // Check for BUILD.sh and execute" << endl;
3298 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3299 out << " printf(\"*******************************\\n\");" << endl;
3300 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3301 out << " printf(\"*******************************\\n\");" << endl;
3302 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3303 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3304 out << " gSystem->ChangeDirectory(cdir);" << endl;
3305 out << " return kFALSE;" << endl;
3306 out << " }" << endl;
3307 out << " } else {" << endl;
3308 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3309 out << " gSystem->ChangeDirectory(cdir);" << endl;
3310 out << " return kFALSE;" << endl;
3311 out << " }" << endl;
3312 out << " // Check for SETUP.C and execute" << endl;
3313 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3314 out << " printf(\"*******************************\\n\");" << endl;
3315 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3316 out << " printf(\"*******************************\\n\");" << endl;
3317 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3318 out << " } else {" << endl;
3319 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3320 out << " gSystem->ChangeDirectory(cdir);" << endl;
3321 out << " return kFALSE;" << endl;
3322 out << " }" << endl;
3323 out << " // Restore original workdir" << endl;
3324 out << " gSystem->ChangeDirectory(cdir);" << endl;
3325 out << " return kTRUE;" << endl;
3328 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3330 Bool_t copy = kTRUE;
3331 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3334 TString workdir = gGrid->GetHomeDirectory();
3335 workdir += fGridWorkingDir;
3336 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3337 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3338 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3339 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3340 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3342 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3343 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3347 //______________________________________________________________________________
3348 void AliAnalysisAlien::WriteMergingMacro()
3350 // Write a macro to merge the outputs per master job.
3351 if (!fMergeViaJDL) return;
3352 if (!fOutputFiles.Length()) {
3353 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3356 TString mergingMacro = fExecutable;
3357 mergingMacro.ReplaceAll(".sh","_merge.C");
3358 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3359 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3361 out.open(mergingMacro.Data(), ios::out);
3363 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3366 Bool_t hasSTEERBase = kFALSE;
3367 Bool_t hasESD = kFALSE;
3368 Bool_t hasAOD = kFALSE;
3369 Bool_t hasANALYSIS = kFALSE;
3370 Bool_t hasANALYSISalice = kFALSE;
3371 Bool_t hasCORRFW = kFALSE;
3372 TString func = mergingMacro;
3374 func.ReplaceAll(".C", "");
3375 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3377 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3378 out << " TStopwatch timer;" << endl;
3379 out << " timer.Start();" << endl << endl;
3380 // Reset existing include path
3381 out << "// Reset existing include path and add current directory first in the search" << endl;
3382 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3383 if (!fExecutableCommand.Contains("aliroot")) {
3384 out << "// load base root libraries" << endl;
3385 out << " gSystem->Load(\"libTree\");" << endl;
3386 out << " gSystem->Load(\"libGeom\");" << endl;
3387 out << " gSystem->Load(\"libVMC\");" << endl;
3388 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3389 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3391 if (fAdditionalRootLibs.Length()) {
3392 // in principle libtree /lib geom libvmc etc. can go into this list, too
3393 out << "// Add aditional libraries" << endl;
3394 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3397 while((str=(TObjString*)next())) {
3398 if (str->GetString().Contains(".so"))
3399 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3401 if (list) delete list;
3403 out << "// Load analysis framework libraries" << endl;
3405 if (!fExecutableCommand.Contains("aliroot")) {
3406 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3407 out << " gSystem->Load(\"libESD\");" << endl;
3408 out << " gSystem->Load(\"libAOD\");" << endl;
3410 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3411 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3412 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3414 TIter next(fPackages);
3417 TString setupPar = "AliAnalysisAlien::SetupPar";
3418 while ((obj=next())) {
3419 pkgname = obj->GetName();
3420 if (pkgname == "STEERBase" ||
3421 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3422 if (pkgname == "ESD" ||
3423 pkgname == "ESD.par") hasESD = kTRUE;
3424 if (pkgname == "AOD" ||
3425 pkgname == "AOD.par") hasAOD = kTRUE;
3426 if (pkgname == "ANALYSIS" ||
3427 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3428 if (pkgname == "ANALYSISalice" ||
3429 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3430 if (pkgname == "CORRFW" ||
3431 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3433 if (hasANALYSISalice) setupPar = "SetupPar";
3434 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3435 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3436 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3437 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3438 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3439 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3440 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3441 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3442 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3443 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3444 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3445 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3446 out << "// Compile other par packages" << endl;
3448 while ((obj=next())) {
3449 pkgname = obj->GetName();
3450 if (pkgname == "STEERBase" ||
3451 pkgname == "STEERBase.par" ||
3453 pkgname == "ESD.par" ||
3455 pkgname == "AOD.par" ||
3456 pkgname == "ANALYSIS" ||
3457 pkgname == "ANALYSIS.par" ||
3458 pkgname == "ANALYSISalice" ||
3459 pkgname == "ANALYSISalice.par" ||
3460 pkgname == "CORRFW" ||
3461 pkgname == "CORRFW.par") continue;
3462 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3465 out << "// include path" << endl;
3466 // Get the include path from the interpreter and remove entries pointing to AliRoot
3467 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3468 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3469 out << " TIter nextpath(listpaths);" << endl;
3470 out << " TObjString *pname;" << endl;
3471 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3472 out << " TString current = pname->GetName();" << endl;
3473 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3474 out << " gSystem->AddIncludePath(current);" << endl;
3475 out << " }" << endl;
3476 out << " if (listpaths) delete listpaths;" << endl;
3477 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3478 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3479 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3480 if (fAdditionalLibs.Length()) {
3481 out << "// Add aditional AliRoot libraries" << endl;
3482 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3485 while((str=(TObjString*)next())) {
3486 if (str->GetString().Contains(".so"))
3487 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3489 if (list) delete list;
3492 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3493 if (fAnalysisSource.Length()) {
3494 TObjArray *list = fAnalysisSource.Tokenize(" ");
3497 while((str=(TObjString*)next())) {
3498 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3500 if (list) delete list;
3504 if (fFastReadOption) {
3505 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 !!!");
3506 out << "// fast xrootd reading enabled" << endl;
3507 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3508 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3509 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3510 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3511 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3512 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3514 // Change temp directory to current one
3515 out << "// Set temporary merging directory to current one" << endl;
3516 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3517 out << "// Connect to AliEn" << endl;
3518 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3519 out << " TString outputDir = dir;" << endl;
3520 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3521 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3522 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3523 out << " TIter *iter = new TIter(list);" << endl;
3524 out << " TObjString *str;" << endl;
3525 out << " TString outputFile;" << endl;
3526 out << " Bool_t merged = kTRUE;" << endl;
3527 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3528 out << " outputFile = str->GetString();" << endl;
3529 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3530 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3531 out << " if (index > 0) outputFile.Remove(index);" << endl;
3532 out << " // Skip already merged outputs" << endl;
3533 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3534 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3535 out << " continue;" << endl;
3536 out << " }" << endl;
3537 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3538 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3539 out << " if (!merged) {" << endl;
3540 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3541 out << " return;" << endl;
3542 out << " }" << endl;
3543 out << " }" << endl;
3544 out << " // all outputs merged, validate" << endl;
3545 out << " ofstream out;" << endl;
3546 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3547 out << " out.close();" << endl;
3548 out << " // read the analysis manager from file" << endl;
3549 TString analysisFile = fExecutable;
3550 analysisFile.ReplaceAll(".sh", ".root");
3551 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3552 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3553 out << " if (!file) return;" << endl;
3554 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3555 out << " AliAnalysisManager *mgr = 0;" << endl;
3556 out << " TKey *key;" << endl;
3557 out << " while ((key=(TKey*)nextkey())) {" << endl;
3558 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3559 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3560 out << " };" << endl;
3561 out << " if (!mgr) {" << endl;
3562 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3563 out << " return;" << endl;
3564 out << " }" << endl << endl;
3565 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3566 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3567 out << " mgr->PrintStatus();" << endl;
3568 if (AliAnalysisManager::GetAnalysisManager()) {
3569 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3570 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3572 if (TestBit(AliAnalysisGrid::kTest))
3573 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3575 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3578 out << " TTree *tree = NULL;" << endl;
3579 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3580 out << "}" << endl << endl;
3581 if (hasANALYSISalice) {
3582 out <<"//________________________________________________________________________________" << endl;
3583 out << "Bool_t SetupPar(const char *package) {" << endl;
3584 out << "// Compile the package and set it up." << endl;
3585 out << " TString pkgdir = package;" << endl;
3586 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3587 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3588 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3589 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3590 out << " // Check for BUILD.sh and execute" << endl;
3591 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3592 out << " printf(\"*******************************\\n\");" << endl;
3593 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3594 out << " printf(\"*******************************\\n\");" << endl;
3595 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3596 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3597 out << " gSystem->ChangeDirectory(cdir);" << endl;
3598 out << " return kFALSE;" << endl;
3599 out << " }" << endl;
3600 out << " } else {" << endl;
3601 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3602 out << " gSystem->ChangeDirectory(cdir);" << endl;
3603 out << " return kFALSE;" << endl;
3604 out << " }" << endl;
3605 out << " // Check for SETUP.C and execute" << endl;
3606 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3607 out << " printf(\"*******************************\\n\");" << endl;
3608 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3609 out << " printf(\"*******************************\\n\");" << endl;
3610 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3611 out << " } else {" << endl;
3612 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3613 out << " gSystem->ChangeDirectory(cdir);" << endl;
3614 out << " return kFALSE;" << endl;
3615 out << " }" << endl;
3616 out << " // Restore original workdir" << endl;
3617 out << " gSystem->ChangeDirectory(cdir);" << endl;
3618 out << " return kTRUE;" << endl;
3622 Bool_t copy = kTRUE;
3623 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3626 TString workdir = gGrid->GetHomeDirectory();
3627 workdir += fGridWorkingDir;
3628 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3629 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3630 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3634 //______________________________________________________________________________
3635 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3637 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3638 // Note that for loading the compiled library. The current directory should have precedence in
3640 TString pkgdir = package;
3641 pkgdir.ReplaceAll(".par","");
3642 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3643 TString cdir = gSystem->WorkingDirectory();
3644 gSystem->ChangeDirectory(pkgdir);
3645 // Check for BUILD.sh and execute
3646 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3647 printf("**************************************************\n");
3648 printf("*** Building PAR archive %s\n", package);
3649 printf("**************************************************\n");
3650 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3651 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3652 gSystem->ChangeDirectory(cdir);
3656 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3657 gSystem->ChangeDirectory(cdir);
3660 // Check for SETUP.C and execute
3661 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3662 printf("**************************************************\n");
3663 printf("*** Setup PAR archive %s\n", package);
3664 printf("**************************************************\n");
3665 gROOT->Macro("PROOF-INF/SETUP.C");
3666 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3668 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3669 gSystem->ChangeDirectory(cdir);
3672 // Restore original workdir
3673 gSystem->ChangeDirectory(cdir);
3677 //______________________________________________________________________________
3678 void AliAnalysisAlien::WriteExecutable()
3680 // Generate the alien executable script.
3681 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3683 out.open(fExecutable.Data(), ios::out);
3685 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3688 out << "#!/bin/bash" << endl;
3689 // Make sure we can properly compile par files
3690 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3691 out << "echo \"=========================================\"" << endl;
3692 out << "echo \"############## PATH : ##############\"" << endl;
3693 out << "echo $PATH" << endl;
3694 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3695 out << "echo $LD_LIBRARY_PATH" << endl;
3696 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3697 out << "echo $ROOTSYS" << endl;
3698 out << "echo \"############## which root : ##############\"" << endl;
3699 out << "which root" << endl;
3700 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3701 out << "echo $ALICE_ROOT" << endl;
3702 out << "echo \"############## which aliroot : ##############\"" << endl;
3703 out << "which aliroot" << endl;
3704 out << "echo \"############## system limits : ##############\"" << endl;
3705 out << "ulimit -a" << endl;
3706 out << "echo \"############## memory : ##############\"" << endl;
3707 out << "free -m" << endl;
3708 out << "echo \"=========================================\"" << endl << endl;
3709 out << fExecutableCommand << " ";
3710 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3711 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3712 out << "echo \"############## memory after: ##############\"" << endl;
3713 out << "free -m" << endl;
3715 Bool_t copy = kTRUE;
3716 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3719 TString workdir = gGrid->GetHomeDirectory();
3720 TString bindir = Form("%s/bin", workdir.Data());
3721 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3722 workdir += fGridWorkingDir;
3723 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3724 if (FileExists(executable)) gGrid->Rm(executable);
3725 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3726 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3730 //______________________________________________________________________________
3731 void AliAnalysisAlien::WriteMergeExecutable()
3733 // Generate the alien executable script for the merging job.
3734 if (!fMergeViaJDL) return;
3735 TString mergeExec = fExecutable;
3736 mergeExec.ReplaceAll(".sh", "_merge.sh");
3737 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3739 out.open(mergeExec.Data(), ios::out);
3741 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3744 out << "#!/bin/bash" << endl;
3745 // Make sure we can properly compile par files
3746 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3747 out << "echo \"=========================================\"" << endl;
3748 out << "echo \"############## PATH : ##############\"" << endl;
3749 out << "echo $PATH" << endl;
3750 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3751 out << "echo $LD_LIBRARY_PATH" << endl;
3752 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3753 out << "echo $ROOTSYS" << endl;
3754 out << "echo \"############## which root : ##############\"" << endl;
3755 out << "which root" << endl;
3756 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3757 out << "echo $ALICE_ROOT" << endl;
3758 out << "echo \"############## which aliroot : ##############\"" << endl;
3759 out << "which aliroot" << endl;
3760 out << "echo \"############## system limits : ##############\"" << endl;
3761 out << "ulimit -a" << endl;
3762 out << "echo \"############## memory : ##############\"" << endl;
3763 out << "free -m" << endl;
3764 out << "echo \"=========================================\"" << endl << endl;
3765 TString mergeMacro = fExecutable;
3766 mergeMacro.ReplaceAll(".sh", "_merge.C");
3767 if (IsOneStageMerging())
3768 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3770 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3771 out << fExecutableCommand << " " << "$ARG" << endl;
3772 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3773 out << "echo \"############## memory after: ##############\"" << endl;
3774 out << "free -m" << endl;
3776 Bool_t copy = kTRUE;
3777 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3780 TString workdir = gGrid->GetHomeDirectory();
3781 TString bindir = Form("%s/bin", workdir.Data());
3782 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3783 workdir += fGridWorkingDir;
3784 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3785 if (FileExists(executable)) gGrid->Rm(executable);
3786 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3787 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3791 //______________________________________________________________________________
3792 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3794 // Write the production file to be submitted by LPM manager. The format is:
3795 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3796 // Next lines: full_path_to_dataset XXX (XXX is a string)
3797 // To submit, one has to: submit jdl XXX for all lines
3799 out.open(filename, ios::out);
3801 Error("WriteProductionFile", "Bad file name: %s", filename);
3805 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3806 workdir = gGrid->GetHomeDirectory();
3807 workdir += fGridWorkingDir;
3808 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3809 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3810 out << locjdl << " " << njobspermaster << endl;
3811 Int_t nmasterjobs = fInputFiles->GetEntries();
3812 for (Int_t i=0; i<nmasterjobs; i++) {
3813 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3814 runOutDir.ReplaceAll(".xml", "");
3816 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3818 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3821 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3822 if (FileExists(filename)) gGrid->Rm(filename);
3823 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3827 //______________________________________________________________________________
3828 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3830 // Generate the alien validation script.
3831 // Generate the validation script
3833 if (fValidationScript.IsNull()) {
3834 fValidationScript = fExecutable;
3835 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3837 TString validationScript = fValidationScript;
3838 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3840 Error("WriteValidationScript", "Alien connection required");
3843 if (!fTerminateFiles.IsNull()) {
3844 fTerminateFiles.Strip();
3845 fTerminateFiles.ReplaceAll(" ",",");
3847 TString outStream = "";
3848 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3849 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3851 out.open(validationScript, ios::out);
3852 out << "#!/bin/bash" << endl;
3853 out << "##################################################" << endl;
3854 out << "validateout=`dirname $0`" << endl;
3855 out << "validatetime=`date`" << endl;
3856 out << "validated=\"0\";" << endl;
3857 out << "error=0" << endl;
3858 out << "if [ -z $validateout ]" << endl;
3859 out << "then" << endl;
3860 out << " validateout=\".\"" << endl;
3861 out << "fi" << endl << endl;
3862 out << "cd $validateout;" << endl;
3863 out << "validateworkdir=`pwd`;" << endl << endl;
3864 out << "echo \"*******************************************************\"" << outStream << endl;
3865 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3867 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3868 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3869 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3870 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3871 out << "ls -la ./" << outStream << endl;
3872 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3873 out << "##################################################" << endl;
3876 out << "if [ ! -f stderr ] ; then" << endl;
3877 out << " error=1" << endl;
3878 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3879 out << " echo \"Error = $error\" " << outStream << endl;
3880 out << "fi" << endl;
3882 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3883 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3884 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3885 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3888 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3889 out << " error=1" << endl;
3890 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3891 out << " echo \"$parArch\" " << outStream << endl;
3892 out << " echo \"Error = $error\" " << outStream << endl;
3893 out << "fi" << endl;
3895 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3896 out << " error=1" << endl;
3897 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3898 out << " echo \"$segViol\" " << outStream << endl;
3899 out << " echo \"Error = $error\" " << outStream << endl;
3900 out << "fi" << endl;
3902 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3903 out << " error=1" << endl;
3904 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3905 out << " echo \"$segFault\" " << outStream << endl;
3906 out << " echo \"Error = $error\" " << outStream << endl;
3907 out << "fi" << endl;
3909 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3910 out << " error=1" << endl;
3911 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3912 out << " echo \"$glibcErr\" " << outStream << endl;
3913 out << " echo \"Error = $error\" " << outStream << endl;
3914 out << "fi" << endl;
3916 // Part dedicated to the specific analyses running into the train
3918 TString outputFiles = fOutputFiles;
3919 if (merge && !fTerminateFiles.IsNull()) {
3921 outputFiles += fTerminateFiles;
3923 TObjArray *arr = outputFiles.Tokenize(",");
3926 while (!merge && (os=(TObjString*)next1())) {
3927 // No need to validate outputs produced by merging since the merging macro does this
3928 outputFile = os->GetString();
3929 Int_t index = outputFile.Index("@");
3930 if (index > 0) outputFile.Remove(index);
3931 if (fTerminateFiles.Contains(outputFile)) continue;
3932 if (outputFile.Contains("*")) continue;
3933 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
3934 out << " error=1" << endl;
3935 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
3936 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
3937 out << "fi" << endl;
3940 out << "if ! [ -f outputs_valid ] ; then" << endl;
3941 out << " error=1" << endl;
3942 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3943 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3944 out << "fi" << endl;
3946 out << "if [ $error = 0 ] ; then" << endl;
3947 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
3948 if (!IsKeepLogs()) {
3949 out << " echo \"* === Logs std* will be deleted === \"" << endl;
3951 out << " rm -f std*" << endl;
3953 out << "fi" << endl;
3955 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3956 out << "echo \"*******************************************************\"" << outStream << endl;
3957 out << "cd -" << endl;
3958 out << "exit $error" << endl;
3960 Bool_t copy = kTRUE;
3961 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3964 TString workdir = gGrid->GetHomeDirectory();
3965 workdir += fGridWorkingDir;
3966 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
3967 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3968 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));