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 "AliAnalysisAlien.h"
25 #include "Riostream.h"
32 #include "TFileCollection.h"
34 #include "TObjString.h"
35 #include "TObjArray.h"
37 #include "TGridResult.h"
38 #include "TGridCollection.h"
40 #include "TGridJobStatusList.h"
41 #include "TGridJobStatus.h"
42 #include "TFileMerger.h"
43 #include "AliAnalysisManager.h"
44 #include "AliVEventHandler.h"
45 #include "AliAnalysisDataContainer.h"
46 #include "AliMultiInputEventHandler.h"
48 ClassImp(AliAnalysisAlien)
50 //______________________________________________________________________________
51 AliAnalysisAlien::AliAnalysisAlien()
57 fSplitMaxInputFileNumber(0),
59 fMasterResubmitThreshold(0),
72 fNproofWorkersPerSlave(0),
82 fAdditionalRootLibs(),
110 fRootVersionForProof(),
120 //______________________________________________________________________________
121 AliAnalysisAlien::AliAnalysisAlien(const char *name)
122 :AliAnalysisGrid(name),
127 fSplitMaxInputFileNumber(0),
129 fMasterResubmitThreshold(0),
142 fNproofWorkersPerSlave(0),
146 fExecutableCommand(),
152 fAdditionalRootLibs(),
180 fRootVersionForProof(),
190 //______________________________________________________________________________
191 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
192 :AliAnalysisGrid(other),
195 fPrice(other.fPrice),
197 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
198 fMaxInitFailed(other.fMaxInitFailed),
199 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
200 fNtestFiles(other.fNtestFiles),
201 fNrunsPerMaster(other.fNrunsPerMaster),
202 fMaxMergeFiles(other.fMaxMergeFiles),
203 fMaxMergeStages(other.fMaxMergeStages),
204 fNsubmitted(other.fNsubmitted),
205 fProductionMode(other.fProductionMode),
206 fOutputToRunNo(other.fOutputToRunNo),
207 fMergeViaJDL(other.fMergeViaJDL),
208 fFastReadOption(other.fFastReadOption),
209 fOverwriteMode(other.fOverwriteMode),
210 fNreplicas(other.fNreplicas),
211 fNproofWorkers(other.fNproofWorkers),
212 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
213 fProofReset(other.fProofReset),
214 fRunNumbers(other.fRunNumbers),
215 fExecutable(other.fExecutable),
216 fExecutableCommand(other.fExecutableCommand),
217 fArguments(other.fArguments),
218 fExecutableArgs(other.fExecutableArgs),
219 fAnalysisMacro(other.fAnalysisMacro),
220 fAnalysisSource(other.fAnalysisSource),
221 fValidationScript(other.fValidationScript),
222 fAdditionalRootLibs(other.fAdditionalRootLibs),
223 fAdditionalLibs(other.fAdditionalLibs),
224 fSplitMode(other.fSplitMode),
225 fAPIVersion(other.fAPIVersion),
226 fROOTVersion(other.fROOTVersion),
227 fAliROOTVersion(other.fAliROOTVersion),
228 fExternalPackages(other.fExternalPackages),
230 fGridWorkingDir(other.fGridWorkingDir),
231 fGridDataDir(other.fGridDataDir),
232 fDataPattern(other.fDataPattern),
233 fGridOutputDir(other.fGridOutputDir),
234 fOutputArchive(other.fOutputArchive),
235 fOutputFiles(other.fOutputFiles),
236 fInputFormat(other.fInputFormat),
237 fDatasetName(other.fDatasetName),
238 fJDLName(other.fJDLName),
239 fTerminateFiles(other.fTerminateFiles),
240 fMergeExcludes(other.fMergeExcludes),
241 fIncludePath(other.fIncludePath),
242 fCloseSE(other.fCloseSE),
243 fFriendChainName(other.fFriendChainName),
244 fJobTag(other.fJobTag),
245 fOutputSingle(other.fOutputSingle),
246 fRunPrefix(other.fRunPrefix),
247 fProofCluster(other.fProofCluster),
248 fProofDataSet(other.fProofDataSet),
249 fFileForTestMode(other.fFileForTestMode),
250 fRootVersionForProof(other.fRootVersionForProof),
251 fAliRootMode(other.fAliRootMode),
252 fMergeDirName(other.fMergeDirName),
257 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
258 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
259 fRunRange[0] = other.fRunRange[0];
260 fRunRange[1] = other.fRunRange[1];
261 if (other.fInputFiles) {
262 fInputFiles = new TObjArray();
263 TIter next(other.fInputFiles);
265 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
266 fInputFiles->SetOwner();
268 if (other.fPackages) {
269 fPackages = new TObjArray();
270 TIter next(other.fPackages);
272 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
273 fPackages->SetOwner();
277 //______________________________________________________________________________
278 AliAnalysisAlien::~AliAnalysisAlien()
281 if (fGridJDL) delete fGridJDL;
282 if (fMergingJDL) delete fMergingJDL;
283 if (fInputFiles) delete fInputFiles;
284 if (fPackages) delete fPackages;
287 //______________________________________________________________________________
288 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
291 if (this != &other) {
292 AliAnalysisGrid::operator=(other);
293 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
294 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
295 fPrice = other.fPrice;
297 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
298 fMaxInitFailed = other.fMaxInitFailed;
299 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
300 fNtestFiles = other.fNtestFiles;
301 fNrunsPerMaster = other.fNrunsPerMaster;
302 fMaxMergeFiles = other.fMaxMergeFiles;
303 fMaxMergeStages = other.fMaxMergeStages;
304 fNsubmitted = other.fNsubmitted;
305 fProductionMode = other.fProductionMode;
306 fOutputToRunNo = other.fOutputToRunNo;
307 fMergeViaJDL = other.fMergeViaJDL;
308 fFastReadOption = other.fFastReadOption;
309 fOverwriteMode = other.fOverwriteMode;
310 fNreplicas = other.fNreplicas;
311 fNproofWorkers = other.fNproofWorkers;
312 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
313 fProofReset = other.fProofReset;
314 fRunNumbers = other.fRunNumbers;
315 fExecutable = other.fExecutable;
316 fExecutableCommand = other.fExecutableCommand;
317 fArguments = other.fArguments;
318 fExecutableArgs = other.fExecutableArgs;
319 fAnalysisMacro = other.fAnalysisMacro;
320 fAnalysisSource = other.fAnalysisSource;
321 fValidationScript = other.fValidationScript;
322 fAdditionalRootLibs = other.fAdditionalRootLibs;
323 fAdditionalLibs = other.fAdditionalLibs;
324 fSplitMode = other.fSplitMode;
325 fAPIVersion = other.fAPIVersion;
326 fROOTVersion = other.fROOTVersion;
327 fAliROOTVersion = other.fAliROOTVersion;
328 fExternalPackages = other.fExternalPackages;
330 fGridWorkingDir = other.fGridWorkingDir;
331 fGridDataDir = other.fGridDataDir;
332 fDataPattern = other.fDataPattern;
333 fGridOutputDir = other.fGridOutputDir;
334 fOutputArchive = other.fOutputArchive;
335 fOutputFiles = other.fOutputFiles;
336 fInputFormat = other.fInputFormat;
337 fDatasetName = other.fDatasetName;
338 fJDLName = other.fJDLName;
339 fTerminateFiles = other.fTerminateFiles;
340 fMergeExcludes = other.fMergeExcludes;
341 fIncludePath = other.fIncludePath;
342 fCloseSE = other.fCloseSE;
343 fFriendChainName = other.fFriendChainName;
344 fJobTag = other.fJobTag;
345 fOutputSingle = other.fOutputSingle;
346 fRunPrefix = other.fRunPrefix;
347 fProofCluster = other.fProofCluster;
348 fProofDataSet = other.fProofDataSet;
349 fFileForTestMode = other.fFileForTestMode;
350 fRootVersionForProof = other.fRootVersionForProof;
351 fAliRootMode = other.fAliRootMode;
352 fMergeDirName = other.fMergeDirName;
353 if (other.fInputFiles) {
354 fInputFiles = new TObjArray();
355 TIter next(other.fInputFiles);
357 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
358 fInputFiles->SetOwner();
360 if (other.fPackages) {
361 fPackages = new TObjArray();
362 TIter next(other.fPackages);
364 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
365 fPackages->SetOwner();
371 //______________________________________________________________________________
372 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
374 // Set the run number format. Can be a prefix or a format like "%09d"
376 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
379 //______________________________________________________________________________
380 void AliAnalysisAlien::AddIncludePath(const char *path)
382 // Add include path in the remote analysis macro.
384 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
385 else fIncludePath += Form("-I%s ", path);
388 //______________________________________________________________________________
389 void AliAnalysisAlien::AddRunNumber(Int_t run)
391 // Add a run number to the list of runs to be processed.
392 if (fRunNumbers.Length()) fRunNumbers += " ";
393 fRunNumbers += Form(fRunPrefix.Data(), run);
396 //______________________________________________________________________________
397 void AliAnalysisAlien::AddRunList(const char* runList)
399 // Add several runs into the list of runs; they are expected to be separated by a blank character.
400 TString sList = runList;
401 TObjArray *list = sList.Tokenize(" ");
402 Int_t n = list->GetEntries();
403 for (Int_t i = 0; i < n; i++) {
404 TObjString *os = (TObjString*)list->At(i);
405 AddRunNumber(os->GetString().Atoi());
410 //______________________________________________________________________________
411 void AliAnalysisAlien::AddRunNumber(const char* run)
413 // Add a run number to the list of runs to be processed.
416 TObjArray *arr = runs.Tokenize(" ");
419 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
420 while ((os=(TObjString*)next())){
421 if (fRunNumbers.Length()) fRunNumbers += " ";
422 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
427 //______________________________________________________________________________
428 void AliAnalysisAlien::AddDataFile(const char *lfn)
430 // Adds a data file to the input to be analysed. The file should be a valid LFN
431 // or point to an existing file in the alien workdir.
432 if (!fInputFiles) fInputFiles = new TObjArray();
433 fInputFiles->Add(new TObjString(lfn));
436 //______________________________________________________________________________
437 void AliAnalysisAlien::AddExternalPackage(const char *package)
439 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
440 if (fExternalPackages) fExternalPackages += " ";
441 fExternalPackages += package;
444 //______________________________________________________________________________
445 Bool_t AliAnalysisAlien::Connect()
447 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
448 if (gGrid && gGrid->IsConnected()) return kTRUE;
449 if (fProductionMode) return kTRUE;
451 Info("Connect", "Trying to connect to AliEn ...");
452 TGrid::Connect("alien://");
454 if (!gGrid || !gGrid->IsConnected()) {
455 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
458 fUser = gGrid->GetUser();
459 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
463 //______________________________________________________________________________
464 void AliAnalysisAlien::CdWork()
466 // Check validity of alien workspace. Create directory if possible.
468 Error("CdWork", "Alien connection required");
471 TString homedir = gGrid->GetHomeDirectory();
472 TString workdir = homedir + fGridWorkingDir;
473 if (DirectoryExists(workdir)) {
477 // Work directory not existing - create it
479 if (gGrid->Mkdir(workdir, "-p")) {
480 gGrid->Cd(fGridWorkingDir);
481 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
483 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
484 workdir.Data(), homedir.Data());
485 fGridWorkingDir = "";
489 //______________________________________________________________________________
490 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
492 // Check if file copying is possible.
493 if (fProductionMode) return kTRUE;
495 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
498 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
499 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
500 // Check if alien_CLOSE_SE is defined
501 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
502 if (!closeSE.IsNull()) {
503 Info("CheckFileCopy", "Your current close storage is pointing to: \
504 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
506 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
508 // Check if grid directory exists.
509 if (!DirectoryExists(alienpath)) {
510 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
513 TFile f("plugin_test_copy", "RECREATE");
514 // User may not have write permissions to current directory
516 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
517 gSystem->WorkingDirectory());
521 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
522 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
523 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
524 \n# 1. Make sure you have write permissions there. If this is the case: \
525 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
526 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
527 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
528 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
529 gSystem->Unlink(f.GetName());
532 gSystem->Unlink(f.GetName());
533 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
534 Info("CheckFileCopy", "### ...SUCCESS ###");
538 //______________________________________________________________________________
539 Bool_t AliAnalysisAlien::CheckInputData()
541 // Check validity of input data. If necessary, create xml files.
542 if (fProductionMode) return kTRUE;
543 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
544 if (!fGridDataDir.Length()) {
545 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
549 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
552 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
553 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
554 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
557 // Process declared files
558 Bool_t isCollection = kFALSE;
559 Bool_t isXml = kFALSE;
560 Bool_t useTags = kFALSE;
561 Bool_t checked = kFALSE;
562 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
564 TString workdir = gGrid->GetHomeDirectory();
565 workdir += fGridWorkingDir;
568 TIter next(fInputFiles);
569 while ((objstr=(TObjString*)next())) {
572 file += objstr->GetString();
573 // Store full lfn path
574 if (FileExists(file)) objstr->SetString(file);
576 file = objstr->GetName();
577 if (!FileExists(objstr->GetName())) {
578 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
579 objstr->GetName(), workdir.Data());
583 Bool_t iscoll, isxml, usetags;
584 CheckDataType(file, iscoll, isxml, usetags);
587 isCollection = iscoll;
590 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
592 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
593 Error("CheckInputData", "Some conflict was found in the types of inputs");
599 // Process requested run numbers
600 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
601 // Check validity of alien data directory
602 if (!fGridDataDir.Length()) {
603 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
606 if (!DirectoryExists(fGridDataDir)) {
607 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
611 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
615 if (checked && !isXml) {
616 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
619 // Check validity of run number(s)
624 TString schunk, schunk2;
628 useTags = fDataPattern.Contains("tag");
629 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
631 if (useTags != fDataPattern.Contains("tag")) {
632 Error("CheckInputData", "Cannot mix input files using/not using tags");
635 if (fRunNumbers.Length()) {
636 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
637 arr = fRunNumbers.Tokenize(" ");
639 while ((os=(TObjString*)next())) {
640 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
641 if (!DirectoryExists(path)) {
642 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
645 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
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 AddDataFile(Form("%s.xml", os->GetString().Data()));
656 if (((nruns-1)%fNrunsPerMaster) == 0) {
657 schunk = os->GetString();
659 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
660 schunk += Form("_%s.xml", os->GetString().Data());
666 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
667 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
668 format = Form("%%s/%s ", fRunPrefix.Data());
669 path = Form(format.Data(), fGridDataDir.Data(), irun);
670 if (!DirectoryExists(path)) {
673 format = Form("%%s/%s.xml", fRunPrefix.Data());
674 path = Form(format.Data(), workdir.Data(),irun);
675 TString msg = "\n##### file: ";
677 msg += " type: xml_collection;";
678 if (useTags) msg += " using_tags: Yes";
679 else msg += " using_tags: No";
680 Info("CheckDataType", "%s", msg.Data());
681 if (fNrunsPerMaster<2) {
682 format = Form("%s.xml", fRunPrefix.Data());
683 AddDataFile(Form(format.Data(),irun));
686 if (((nruns-1)%fNrunsPerMaster) == 0) {
687 schunk = Form(fRunPrefix.Data(),irun);
689 format = Form("_%s.xml", fRunPrefix.Data());
690 schunk2 = Form(format.Data(), irun);
691 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
704 //______________________________________________________________________________
705 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
707 // Create dataset for the grid data directory + run number.
708 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
710 Error("CreateDataset", "Cannot create dataset with no grid connection");
715 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
716 TString workdir = gGrid->GetHomeDirectory();
717 workdir += fGridWorkingDir;
719 // Compose the 'find' command arguments
722 TString options = "-x collection ";
723 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
724 TString conditions = "";
729 TString schunk, schunk2;
730 TGridCollection *cbase=0, *cadd=0;
731 if (!fRunNumbers.Length() && !fRunRange[0]) {
732 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
733 // Make a single data collection from data directory.
735 if (!DirectoryExists(path)) {
736 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
740 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
741 else file = Form("%s.xml", gSystem->BaseName(path));
742 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
748 command += conditions;
749 printf("command: %s\n", command.Data());
750 TGridResult *res = gGrid->Command(command);
752 // Write standard output to file
753 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
754 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
755 Bool_t nullFile = kFALSE;
757 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
759 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
761 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
766 Bool_t fileExists = FileExists(file);
767 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
768 // Copy xml file to alien space
769 if (fileExists) gGrid->Rm(file);
770 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
771 if (!FileExists(file)) {
772 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
775 // Update list of files to be processed.
777 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
781 Bool_t nullResult = kTRUE;
782 if (fRunNumbers.Length()) {
783 TObjArray *arr = fRunNumbers.Tokenize(" ");
786 while ((os=(TObjString*)next())) {
787 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
788 if (!DirectoryExists(path)) continue;
790 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
791 else file = Form("%s.xml", os->GetString().Data());
792 // If local collection file does not exist, create it via 'find' command.
793 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
798 command += conditions;
799 TGridResult *res = gGrid->Command(command);
801 // Write standard output to file
802 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
803 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
804 Bool_t nullFile = kFALSE;
806 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
808 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
810 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
811 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
817 if (TestBit(AliAnalysisGrid::kTest)) break;
818 // Check if there is one run per master job.
819 if (fNrunsPerMaster<2) {
820 if (FileExists(file)) {
821 if (fOverwriteMode) gGrid->Rm(file);
823 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
827 // Copy xml file to alien space
828 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
829 if (!FileExists(file)) {
830 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
836 if (((nruns-1)%fNrunsPerMaster) == 0) {
837 schunk = os->GetString();
838 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
840 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
841 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
845 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
848 schunk += Form("_%s.xml", os->GetString().Data());
849 if (FileExists(schunk)) {
850 if (fOverwriteMode) gGrid->Rm(file);
852 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
856 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
857 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
858 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
859 if (!FileExists(schunk)) {
860 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
868 Error("CreateDataset", "No valid dataset corresponding to the query!");
872 // Process a full run range.
873 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
874 format = Form("%%s/%s ", fRunPrefix.Data());
875 path = Form(format.Data(), fGridDataDir.Data(), irun);
876 if (!DirectoryExists(path)) continue;
878 format = Form("%s.xml", fRunPrefix.Data());
879 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
880 else file = Form(format.Data(), irun);
881 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
882 if (fOverwriteMode) gGrid->Rm(file);
884 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
888 // If local collection file does not exist, create it via 'find' command.
889 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
894 command += conditions;
895 TGridResult *res = gGrid->Command(command);
897 // Write standard output to file
898 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
899 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
900 Bool_t nullFile = kFALSE;
902 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
904 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
906 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
912 if (TestBit(AliAnalysisGrid::kTest)) break;
913 // Check if there is one run per master job.
914 if (fNrunsPerMaster<2) {
915 if (FileExists(file)) {
916 if (fOverwriteMode) gGrid->Rm(file);
918 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
922 // Copy xml file to alien space
923 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
924 if (!FileExists(file)) {
925 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
930 // Check if the collection for the chunk exist locally.
931 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
932 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
933 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
936 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
937 if (((nruns-1)%fNrunsPerMaster) == 0) {
938 schunk = Form(fRunPrefix.Data(), irun);
939 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
941 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
945 format = Form("%%s_%s.xml", fRunPrefix.Data());
946 schunk2 = Form(format.Data(), schunk.Data(), irun);
947 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
951 if (FileExists(schunk)) {
952 if (fOverwriteMode) gGrid->Rm(schunk);
954 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
958 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
959 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
960 if (FileExists(schunk)) {
961 if (fOverwriteMode) gGrid->Rm(schunk);
963 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
967 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
968 if (!FileExists(schunk)) {
969 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
975 Error("CreateDataset", "No valid dataset corresponding to the query!");
982 //______________________________________________________________________________
983 Bool_t AliAnalysisAlien::CreateJDL()
985 // Generate a JDL file according to current settings. The name of the file is
986 // specified by fJDLName.
987 Bool_t error = kFALSE;
990 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
991 Bool_t generate = kTRUE;
992 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
994 Error("CreateJDL", "Alien connection required");
997 // Check validity of alien workspace
999 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1000 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1001 workdir += fGridWorkingDir;
1005 Error("CreateJDL()", "Define some input files for your analysis.");
1008 // Compose list of input files
1009 // Check if output files were defined
1010 if (!fOutputFiles.Length()) {
1011 Error("CreateJDL", "You must define at least one output file");
1014 // Check if an output directory was defined and valid
1015 if (!fGridOutputDir.Length()) {
1016 Error("CreateJDL", "You must define AliEn output directory");
1019 if (!fProductionMode) {
1020 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1021 if (!DirectoryExists(fGridOutputDir)) {
1022 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1023 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1025 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1029 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1034 // Exit if any error up to now
1035 if (error) return kFALSE;
1037 if (!fUser.IsNull()) {
1038 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1039 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1041 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1042 TString mergeExec = fExecutable;
1043 mergeExec.ReplaceAll(".sh", "_merge.sh");
1044 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1045 mergeExec.ReplaceAll(".sh", ".C");
1046 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1047 if (!fArguments.IsNull())
1048 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1049 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1051 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1052 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1055 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1056 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1057 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1058 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1060 if (fMaxInitFailed > 0) {
1061 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1062 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1064 if (fSplitMaxInputFileNumber > 0) {
1065 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1066 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1068 if (!IsOneStageMerging()) {
1069 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1070 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1072 if (fSplitMode.Length()) {
1073 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1074 fGridJDL->SetDescription("Split", "We split per SE or file");
1076 fMergingJDL->SetValue("Split", "\"se\"");
1077 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1078 if (!fAliROOTVersion.IsNull()) {
1079 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1080 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1082 if (!fROOTVersion.IsNull()) {
1083 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1084 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1086 if (!fAPIVersion.IsNull()) {
1087 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1088 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1090 if (!fExternalPackages.IsNull()) {
1091 arr = fExternalPackages.Tokenize(" ");
1093 while ((os=(TObjString*)next())) {
1094 TString pkgname = os->GetString();
1095 Int_t index = pkgname.Index("::");
1096 TString pkgversion = pkgname(index+2, pkgname.Length());
1097 pkgname.Remove(index);
1098 fGridJDL->AddToPackages(pkgname, pkgversion);
1099 fMergingJDL->AddToPackages(pkgname, pkgversion);
1103 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1104 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1105 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1106 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1107 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1108 TString analysisFile = fExecutable;
1109 analysisFile.ReplaceAll(".sh", ".root");
1110 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1111 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1112 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1113 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1114 if (fAdditionalLibs.Length()) {
1115 arr = fAdditionalLibs.Tokenize(" ");
1117 while ((os=(TObjString*)next())) {
1118 if (os->GetString().Contains(".so")) continue;
1119 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1120 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1125 TIter next(fPackages);
1127 while ((obj=next())) {
1128 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1129 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1132 if (fOutputArchive.Length()) {
1133 arr = fOutputArchive.Tokenize(" ");
1135 Bool_t first = kTRUE;
1136 const char *comment = "Files to be archived";
1137 const char *comment1 = comment;
1138 while ((os=(TObjString*)next())) {
1139 if (!first) comment = NULL;
1140 if (!os->GetString().Contains("@") && fCloseSE.Length())
1141 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1143 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1147 // Output archive for the merging jdl
1148 TString outputArchive;
1149 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1150 outputArchive = "log_archive.zip:std*@disk=1 ";
1151 // Add normal output files, extra files + terminate files
1152 TString files = GetListOfFiles("outextter");
1153 // Do not register merge excludes
1154 if (!fMergeExcludes.IsNull()) {
1155 arr = fMergeExcludes.Tokenize(" ");
1157 while ((os=(TObjString*)next1())) {
1158 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1159 files.ReplaceAll(os->GetString(),"");
1163 files.ReplaceAll(".root", "*.root");
1164 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1166 TString files = fOutputArchive;
1167 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1168 outputArchive = files;
1170 arr = outputArchive.Tokenize(" ");
1174 while ((os=(TObjString*)next2())) {
1175 if (!first) comment = NULL;
1176 TString currentfile = os->GetString();
1177 if (!currentfile.Contains("@") && fCloseSE.Length())
1178 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1180 fMergingJDL->AddToOutputArchive(currentfile, comment);
1185 arr = fOutputFiles.Tokenize(",");
1187 Bool_t first = kTRUE;
1188 const char *comment = "Files to be saved";
1189 while ((os=(TObjString*)next())) {
1190 // Ignore ouputs in jdl that are also in outputarchive
1191 TString sout = os->GetString();
1192 sout.ReplaceAll("*", "");
1193 sout.ReplaceAll(".root", "");
1194 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1195 if (fOutputArchive.Contains(sout)) continue;
1196 if (!first) comment = NULL;
1197 if (!os->GetString().Contains("@") && fCloseSE.Length())
1198 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1200 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1202 if (fMergeExcludes.Contains(sout)) continue;
1203 if (!os->GetString().Contains("@") && fCloseSE.Length())
1204 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1206 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1209 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1210 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1211 TString validationScript = fValidationScript;
1212 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1213 validationScript.ReplaceAll(".sh", "_merge.sh");
1214 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1215 if (fMasterResubmitThreshold) {
1216 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1217 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1219 // Write a jdl with 2 input parameters: collection name and output dir name.
1222 // Copy jdl to grid workspace
1224 // Check if an output directory was defined and valid
1225 if (!fGridOutputDir.Length()) {
1226 Error("CreateJDL", "You must define AliEn output directory");
1229 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1230 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1231 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1232 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1234 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1240 if (TestBit(AliAnalysisGrid::kSubmit)) {
1241 TString mergeJDLName = fExecutable;
1242 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1243 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1244 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1245 if (fProductionMode) {
1246 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1247 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1249 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1250 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1251 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1252 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1254 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1255 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1258 if (fAdditionalLibs.Length()) {
1259 arr = fAdditionalLibs.Tokenize(" ");
1262 while ((os=(TObjString*)next())) {
1263 if (os->GetString().Contains(".so")) continue;
1264 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1265 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1266 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1271 TIter next(fPackages);
1273 while ((obj=next())) {
1274 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1275 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1276 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1283 //______________________________________________________________________________
1284 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1286 // Writes one or more JDL's corresponding to findex. If findex is negative,
1287 // all run numbers are considered in one go (jdl). For non-negative indices
1288 // they correspond to the indices in the array fInputFiles.
1289 if (!fInputFiles) return kFALSE;
1292 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1293 workdir += fGridWorkingDir;
1294 TString stageName = "$2";
1295 if (fProductionMode) stageName = "$4";
1296 if (!fMergeDirName.IsNull()) {
1297 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1298 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1300 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1301 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1303 if (fProductionMode) {
1304 TIter next(fInputFiles);
1305 while ((os=next())) {
1306 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1308 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1310 if (!fRunNumbers.Length() && !fRunRange[0]) {
1311 // One jdl with no parameters in case input data is specified by name.
1312 TIter next(fInputFiles);
1314 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1315 if (!fOutputSingle.IsNull())
1316 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1318 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1319 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1322 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1323 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1324 if (!fOutputSingle.IsNull()) {
1325 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1326 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1328 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1333 // Generate the JDL as a string
1334 TString sjdl = fGridJDL->Generate();
1335 TString sjdl1 = fMergingJDL->Generate();
1337 if (!fMergeDirName.IsNull()) {
1338 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1339 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1341 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1342 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1344 TString sjdl2 = fMergingJDL->Generate();
1345 Int_t index, index1;
1346 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1347 sjdl.ReplaceAll("(member", "\n (member");
1348 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1349 sjdl.ReplaceAll("{", "{\n ");
1350 sjdl.ReplaceAll("};", "\n};");
1351 sjdl.ReplaceAll("{\n \n", "{\n");
1352 sjdl.ReplaceAll("\n\n", "\n");
1353 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1354 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1355 sjdl1.ReplaceAll("(member", "\n (member");
1356 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1357 sjdl1.ReplaceAll("{", "{\n ");
1358 sjdl1.ReplaceAll("};", "\n};");
1359 sjdl1.ReplaceAll("{\n \n", "{\n");
1360 sjdl1.ReplaceAll("\n\n", "\n");
1361 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1362 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1363 sjdl2.ReplaceAll("(member", "\n (member");
1364 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1365 sjdl2.ReplaceAll("{", "{\n ");
1366 sjdl2.ReplaceAll("};", "\n};");
1367 sjdl2.ReplaceAll("{\n \n", "{\n");
1368 sjdl2.ReplaceAll("\n\n", "\n");
1369 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1370 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1371 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1372 index = sjdl.Index("JDLVariables");
1373 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1374 sjdl += "Workdirectorysize = {\"5000MB\"};";
1375 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1376 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1377 index = fJobTag.Index(":");
1378 if (index < 0) index = fJobTag.Length();
1379 TString jobTag = fJobTag;
1380 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1381 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1382 if (fProductionMode) {
1383 sjdl1.Prepend("# Generated merging jdl (production mode) \
1384 \n# $1 = full alien path to output directory to be merged \
1385 \n# $2 = train number \
1386 \n# $3 = production (like LHC10b) \
1387 \n# $4 = merging stage \
1388 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1389 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1390 sjdl2.Prepend("# Generated merging jdl \
1391 \n# $1 = full alien path to output directory to be merged \
1392 \n# $2 = train number \
1393 \n# $3 = production (like LHC10b) \
1394 \n# $4 = merging stage \
1395 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1397 sjdl1.Prepend("# Generated merging jdl \
1398 \n# $1 = full alien path to output directory to be merged \
1399 \n# $2 = merging stage \
1400 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1401 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1402 sjdl2.Prepend("# Generated merging jdl \
1403 \n# $1 = full alien path to output directory to be merged \
1404 \n# $2 = merging stage \
1405 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1407 index = sjdl1.Index("JDLVariables");
1408 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1409 index = sjdl2.Index("JDLVariables");
1410 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1411 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1412 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1413 index = sjdl2.Index("Split =");
1415 index1 = sjdl2.Index("\n", index);
1416 sjdl2.Remove(index, index1-index+1);
1418 index = sjdl2.Index("SplitMaxInputFileNumber");
1420 index1 = sjdl2.Index("\n", index);
1421 sjdl2.Remove(index, index1-index+1);
1423 index = sjdl2.Index("InputDataCollection");
1425 index1 = sjdl2.Index(";", index);
1426 sjdl2.Remove(index, index1-index+1);
1428 index = sjdl2.Index("InputDataListFormat");
1430 index1 = sjdl2.Index("\n", index);
1431 sjdl2.Remove(index, index1-index+1);
1433 index = sjdl2.Index("InputDataList");
1435 index1 = sjdl2.Index("\n", index);
1436 sjdl2.Remove(index, index1-index+1);
1438 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1439 // Write jdl to file
1441 out.open(fJDLName.Data(), ios::out);
1443 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1446 out << sjdl << endl;
1448 TString mergeJDLName = fExecutable;
1449 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1452 out1.open(mergeJDLName.Data(), ios::out);
1454 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1457 out1 << sjdl1 << endl;
1460 TString finalJDL = mergeJDLName;
1461 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1462 out2.open(finalJDL.Data(), ios::out);
1464 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1467 out2 << sjdl2 << endl;
1471 // Copy jdl to grid workspace
1473 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1475 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1476 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1477 TString finalJDL = mergeJDLName;
1478 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1479 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1480 if (fProductionMode) {
1481 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1482 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1483 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1485 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1486 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1487 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1488 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1489 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1491 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1492 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1493 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1499 //______________________________________________________________________________
1500 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1502 // Returns true if file exists.
1503 if (!gGrid) return kFALSE;
1505 slfn.ReplaceAll("alien://","");
1506 TGridResult *res = gGrid->Ls(slfn);
1507 if (!res) return kFALSE;
1508 TMap *map = dynamic_cast<TMap*>(res->At(0));
1513 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1514 if (!objs || !objs->GetString().Length()) {
1522 //______________________________________________________________________________
1523 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1525 // Returns true if directory exists. Can be also a path.
1526 if (!gGrid) return kFALSE;
1527 // Check if dirname is a path
1528 TString dirstripped = dirname;
1529 dirstripped = dirstripped.Strip();
1530 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1531 TString dir = gSystem->BaseName(dirstripped);
1533 TString path = gSystem->DirName(dirstripped);
1534 TGridResult *res = gGrid->Ls(path, "-F");
1535 if (!res) return kFALSE;
1539 while ((map=dynamic_cast<TMap*>(next()))) {
1540 obj = map->GetValue("name");
1542 if (dir == obj->GetName()) {
1551 //______________________________________________________________________________
1552 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1554 // Check input data type.
1555 isCollection = kFALSE;
1559 Error("CheckDataType", "No connection to grid");
1562 isCollection = IsCollection(lfn);
1563 TString msg = "\n##### file: ";
1566 msg += " type: raw_collection;";
1567 // special treatment for collections
1569 // check for tag files in the collection
1570 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1572 msg += " using_tags: No (unknown)";
1573 Info("CheckDataType", "%s", msg.Data());
1576 const char* typeStr = res->GetKey(0, "origLFN");
1577 if (!typeStr || !strlen(typeStr)) {
1578 msg += " using_tags: No (unknown)";
1579 Info("CheckDataType", "%s", msg.Data());
1582 TString file = typeStr;
1583 useTags = file.Contains(".tag");
1584 if (useTags) msg += " using_tags: Yes";
1585 else msg += " using_tags: No";
1586 Info("CheckDataType", "%s", msg.Data());
1591 isXml = slfn.Contains(".xml");
1593 // Open xml collection and check if there are tag files inside
1594 msg += " type: xml_collection;";
1595 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1597 msg += " using_tags: No (unknown)";
1598 Info("CheckDataType", "%s", msg.Data());
1601 TMap *map = coll->Next();
1603 msg += " using_tags: No (unknown)";
1604 Info("CheckDataType", "%s", msg.Data());
1607 map = (TMap*)map->GetValue("");
1609 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1610 useTags = file.Contains(".tag");
1612 if (useTags) msg += " using_tags: Yes";
1613 else msg += " using_tags: No";
1614 Info("CheckDataType", "%s", msg.Data());
1617 useTags = slfn.Contains(".tag");
1618 if (slfn.Contains(".root")) msg += " type: root file;";
1619 else msg += " type: unknown file;";
1620 if (useTags) msg += " using_tags: Yes";
1621 else msg += " using_tags: No";
1622 Info("CheckDataType", "%s", msg.Data());
1625 //______________________________________________________________________________
1626 void AliAnalysisAlien::EnablePackage(const char *package)
1628 // Enables a par file supposed to exist in the current directory.
1629 TString pkg(package);
1630 pkg.ReplaceAll(".par", "");
1632 if (gSystem->AccessPathName(pkg)) {
1633 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1636 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1637 Info("EnablePackage", "AliEn plugin will use .par packages");
1638 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1640 fPackages = new TObjArray();
1641 fPackages->SetOwner();
1643 fPackages->Add(new TObjString(pkg));
1646 //______________________________________________________________________________
1647 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1649 // Make a tree from files having the location specified in fFileForTestMode.
1650 // Inspired from JF's CreateESDChain.
1651 if (fFileForTestMode.IsNull()) {
1652 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1655 if (gSystem->AccessPathName(fFileForTestMode)) {
1656 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1661 in.open(fFileForTestMode);
1663 // Read the input list of files and add them to the chain
1665 TChain *chain = new TChain(treeName);
1669 if (line.IsNull()) continue;
1670 if (count++ == fNtestFiles) break;
1671 TString esdFile(line);
1672 TFile *file = TFile::Open(esdFile);
1674 if (!file->IsZombie()) chain->Add(esdFile);
1677 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1681 if (!chain->GetListOfFiles()->GetEntries()) {
1682 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1690 //______________________________________________________________________________
1691 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1693 // Get job status for all jobs with jobid>jobidstart.
1694 static char mstatus[20];
1700 TGridJobStatusList *list = gGrid->Ps("");
1701 if (!list) return mstatus;
1702 Int_t nentries = list->GetSize();
1703 TGridJobStatus *status;
1705 for (Int_t ijob=0; ijob<nentries; ijob++) {
1706 status = (TGridJobStatus *)list->At(ijob);
1707 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1708 if (pid<jobidstart) continue;
1709 if (pid == lastid) {
1710 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1712 switch (status->GetStatus()) {
1713 case TGridJobStatus::kWAITING:
1715 case TGridJobStatus::kRUNNING:
1717 case TGridJobStatus::kABORTED:
1718 case TGridJobStatus::kFAIL:
1719 case TGridJobStatus::kUNKNOWN:
1721 case TGridJobStatus::kDONE:
1730 //______________________________________________________________________________
1731 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1733 // Returns true if file is a collection. Functionality duplicated from
1734 // TAlien::Type() because we don't want to directly depend on TAlien.
1736 Error("IsCollection", "No connection to grid");
1739 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1740 if (!res) return kFALSE;
1741 const char* typeStr = res->GetKey(0, "type");
1742 if (!typeStr || !strlen(typeStr)) return kFALSE;
1743 if (!strcmp(typeStr, "collection")) return kTRUE;
1748 //______________________________________________________________________________
1749 Bool_t AliAnalysisAlien::IsSingleOutput() const
1751 // Check if single-ouput option is on.
1752 return (!fOutputSingle.IsNull());
1755 //______________________________________________________________________________
1756 void AliAnalysisAlien::Print(Option_t *) const
1758 // Print current plugin settings.
1759 printf("### AliEn analysis plugin current settings ###\n");
1760 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1761 if (mgr && mgr->IsProofMode()) {
1762 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1763 if (TestBit(AliAnalysisGrid::kTest))
1764 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1765 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1766 if (!fProofDataSet.IsNull())
1767 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1769 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1771 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1772 if (!fRootVersionForProof.IsNull())
1773 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1775 printf("= ROOT version requested________________________ default\n");
1776 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1777 if (!fAliRootMode.IsNull())
1778 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1780 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1781 if (fNproofWorkersPerSlave)
1782 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1783 if (TestSpecialBit(kClearPackages))
1784 printf("= ClearPackages requested...\n");
1785 if (fIncludePath.Data())
1786 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1787 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1788 if (fPackages && fPackages->GetEntries()) {
1789 TIter next(fPackages);
1792 while ((obj=next())) list += obj->GetName();
1793 printf("= Par files to be used: ________________________ %s\n", list.Data());
1795 if (TestSpecialBit(kProofConnectGrid))
1796 printf("= Requested PROOF connection to grid\n");
1799 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1800 if (fOverwriteMode) {
1801 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1802 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1804 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1805 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1806 printf("= Production mode:______________________________ %d\n", fProductionMode);
1807 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1808 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1809 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1811 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1812 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1813 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1814 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1815 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1816 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1817 if (fRunNumbers.Length())
1818 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1820 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1821 if (!fRunRange[0] && !fRunNumbers.Length()) {
1822 TIter next(fInputFiles);
1825 while ((obj=next())) list += obj->GetName();
1826 printf("= Input files to be processed: _________________ %s\n", list.Data());
1828 if (TestBit(AliAnalysisGrid::kTest))
1829 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1830 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1831 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1832 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1833 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1834 printf("=====================================================================\n");
1835 printf("= Job price: ___________________________________ %d\n", fPrice);
1836 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1837 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1838 if (fMaxInitFailed>0)
1839 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1840 if (fMasterResubmitThreshold>0)
1841 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1842 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1843 if (fNrunsPerMaster>0)
1844 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1845 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1846 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1847 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1848 if (fArguments.Length())
1849 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1850 if (fExecutableArgs.Length())
1851 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1852 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1853 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1854 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1855 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1857 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1858 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1859 if (fIncludePath.Data())
1860 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1861 if (fCloseSE.Length())
1862 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1863 if (fFriendChainName.Length())
1864 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1865 if (fPackages && fPackages->GetEntries()) {
1866 TIter next(fPackages);
1869 while ((obj=next())) list += obj->GetName();
1870 printf("= Par files to be used: ________________________ %s\n", list.Data());
1874 //______________________________________________________________________________
1875 void AliAnalysisAlien::SetDefaults()
1877 // Set default values for everything. What cannot be filled will be left empty.
1878 if (fGridJDL) delete fGridJDL;
1879 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1880 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1883 fSplitMaxInputFileNumber = 100;
1885 fMasterResubmitThreshold = 0;
1891 fNrunsPerMaster = 1;
1892 fMaxMergeFiles = 100;
1894 fExecutable = "analysis.sh";
1895 fExecutableCommand = "root -b -q";
1897 fExecutableArgs = "";
1898 fAnalysisMacro = "myAnalysis.C";
1899 fAnalysisSource = "";
1900 fAdditionalLibs = "";
1904 fAliROOTVersion = "";
1905 fUser = ""; // Your alien user name
1906 fGridWorkingDir = "";
1907 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1908 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1909 fFriendChainName = "";
1910 fGridOutputDir = "output";
1911 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1912 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1913 fInputFormat = "xml-single";
1914 fJDLName = "analysis.jdl";
1915 fJobTag = "Automatically generated analysis JDL";
1916 fMergeExcludes = "";
1919 SetCheckCopy(kTRUE);
1920 SetDefaultOutputs(kTRUE);
1924 //______________________________________________________________________________
1925 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
1927 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1928 // First check if the result is already in the output directory.
1929 if (FileExists(Form("%s/%s",aliendir,filename))) {
1930 printf("Final merged results found. Not merging again.\n");
1933 // Now check the last stage done.
1936 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1939 // Next stage of merging
1941 TString pattern = "*root_archive.zip";
1942 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1943 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1944 if (res) delete res;
1945 // Write standard output to file
1946 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1947 // Count the number of files inside
1949 ifile.open(Form("Stage_%d.xml",stage));
1950 if (!ifile.good()) {
1951 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
1956 while (!ifile.eof()) {
1958 if (line.Contains("/event")) nfiles++;
1962 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1965 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
1967 // Copy the file in the output directory
1968 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1969 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1970 // Check if this is the last stage to be done.
1971 Bool_t laststage = (nfiles<nperchunk);
1972 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1974 printf("### Submiting final merging stage %d\n", stage);
1975 TString finalJDL = jdl;
1976 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1977 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
1978 Int_t jobId = SubmitSingleJob(query);
1979 if (!jobId) return kFALSE;
1981 printf("### Submiting merging stage %d\n", stage);
1982 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
1983 Int_t jobId = SubmitSingleJob(query);
1984 if (!jobId) return kFALSE;
1989 //______________________________________________________________________________
1990 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1992 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1993 if (!gGrid) return 0;
1994 printf("=> %s ------> ",query);
1995 TGridResult *res = gGrid->Command(query);
1997 TString jobId = res->GetKey(0,"jobId");
1999 if (jobId.IsNull()) {
2000 printf("submission failed. Reason:\n");
2003 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2006 printf(" Job id: %s\n", jobId.Data());
2010 //______________________________________________________________________________
2011 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2013 // Merge given output files from basedir. Basedir can be an alien output directory
2014 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2015 // files in a group (ignored for xml input). Merging can be done in stages:
2016 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2017 // stage=1 : works with an xml of all root_archive.zip in the output directory
2018 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2019 TString outputFile = output;
2021 TString outputChunk;
2022 TString previousChunk = "";
2023 TObjArray *listoffiles = new TObjArray();
2024 // listoffiles->SetOwner();
2025 Int_t countChunk = 0;
2026 Int_t countZero = nmaxmerge;
2027 Bool_t merged = kTRUE;
2028 Int_t index = outputFile.Index("@");
2029 if (index > 0) outputFile.Remove(index);
2030 TString inputFile = outputFile;
2031 TString sbasedir = basedir;
2032 if (sbasedir.Contains(".xml")) {
2033 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2034 nmaxmerge = 9999999;
2035 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2037 ::Error("MergeOutput", "Input XML collection empty.");
2040 // Iterate grid collection
2041 while (coll->Next()) {
2042 TString fname = gSystem->DirName(coll->GetTURL());
2045 listoffiles->Add(new TNamed(fname.Data(),""));
2048 command = Form("find %s/ *%s", basedir, inputFile.Data());
2049 printf("command: %s\n", command.Data());
2050 TGridResult *res = gGrid->Command(command);
2052 ::Error("MergeOutput","No result for the find command\n");
2058 while ((map=(TMap*)nextmap())) {
2059 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2060 if (!objs || !objs->GetString().Length()) {
2061 // Nothing found - skip this output
2066 listoffiles->Add(new TNamed(objs->GetName(),""));
2070 if (!listoffiles->GetEntries()) {
2071 ::Error("MergeOutput","No result for the find command\n");
2076 TFileMerger *fm = 0;
2077 TIter next0(listoffiles);
2078 TObjArray *listoffilestmp = new TObjArray();
2079 listoffilestmp->SetOwner();
2082 // Keep only the files at upper level
2083 Int_t countChar = 0;
2084 while ((nextfile=next0())) {
2085 snextfile = nextfile->GetName();
2086 Int_t crtCount = snextfile.CountChar('/');
2087 if (nextfile == listoffiles->First()) countChar = crtCount;
2088 if (crtCount < countChar) countChar = crtCount;
2091 while ((nextfile=next0())) {
2092 snextfile = nextfile->GetName();
2093 Int_t crtCount = snextfile.CountChar('/');
2094 if (crtCount > countChar) {
2098 listoffilestmp->Add(nextfile);
2101 listoffiles = listoffilestmp; // Now contains 'good' files
2102 listoffiles->Print();
2103 TIter next(listoffiles);
2104 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2105 outputChunk = outputFile;
2106 outputChunk.ReplaceAll(".root", "_*.root");
2107 // Check for existent temporary merge files
2108 // Check overwrite mode and remove previous partial results if needed
2109 // Preserve old merging functionality for stage 0.
2111 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2113 // Skip as many input files as in a chunk
2114 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2117 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2121 snextfile = nextfile->GetName();
2123 outputChunk = outputFile;
2124 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2126 if (gSystem->AccessPathName(outputChunk)) continue;
2127 // Merged file with chunks up to <countChunk> found
2128 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2129 previousChunk = outputChunk;
2133 countZero = nmaxmerge;
2135 while ((nextfile=next())) {
2136 snextfile = nextfile->GetName();
2137 // Loop 'find' results and get next LFN
2138 if (countZero == nmaxmerge) {
2139 // First file in chunk - create file merger and add previous chunk if any.
2140 fm = new TFileMerger(kFALSE);
2141 fm->SetFastMethod(kTRUE);
2142 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2143 outputChunk = outputFile;
2144 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2146 // If last file found, put merged results in the output file
2147 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2148 // Add file to be merged and decrement chunk counter.
2149 fm->AddFile(snextfile);
2151 if (countZero==0 || nextfile == listoffiles->Last()) {
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(outputChunk);
2159 // Merge the outputs, then go to next chunk
2161 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2165 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2166 gSystem->Unlink(previousChunk);
2168 if (nextfile == listoffiles->Last()) break;
2170 countZero = nmaxmerge;
2171 previousChunk = outputChunk;
2178 // Merging stage different than 0.
2179 // Move to the begining of the requested chunk.
2180 fm = new TFileMerger(kFALSE);
2181 fm->SetFastMethod(kTRUE);
2182 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2184 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2185 // Nothing found - skip this output
2186 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2190 fm->OutputFile(outputFile);
2191 // Merge the outputs
2193 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2197 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2203 //______________________________________________________________________________
2204 Bool_t AliAnalysisAlien::MergeOutputs()
2206 // Merge analysis outputs existing in the AliEn space.
2207 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2208 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2210 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2214 if (!TestBit(AliAnalysisGrid::kMerge)) {
2215 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2218 if (fProductionMode) {
2219 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2222 Info("MergeOutputs", "Submitting merging JDL");
2223 if (!SubmitMerging()) return kFALSE;
2224 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2225 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2228 // Get the output path
2229 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2230 if (!DirectoryExists(fGridOutputDir)) {
2231 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2234 if (!fOutputFiles.Length()) {
2235 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2238 // Check if fast read option was requested
2239 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2240 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2241 if (fFastReadOption) {
2242 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2243 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2244 gEnv->SetValue("XNet.ConnectTimeout",50);
2245 gEnv->SetValue("XNet.RequestTimeout",50);
2246 gEnv->SetValue("XNet.MaxRedirectCount",2);
2247 gEnv->SetValue("XNet.ReconnectTimeout",50);
2248 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2250 // Make sure we change the temporary directory
2251 gSystem->Setenv("TMPDIR", gSystem->pwd());
2252 // Set temporary compilation directory to current one
2253 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2254 TObjArray *list = fOutputFiles.Tokenize(",");
2258 Bool_t merged = kTRUE;
2259 while((str=(TObjString*)next())) {
2260 outputFile = str->GetString();
2261 Int_t index = outputFile.Index("@");
2262 if (index > 0) outputFile.Remove(index);
2263 TString outputChunk = outputFile;
2264 outputChunk.ReplaceAll(".root", "_*.root");
2265 // Skip already merged outputs
2266 if (!gSystem->AccessPathName(outputFile)) {
2267 if (fOverwriteMode) {
2268 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2269 gSystem->Unlink(outputFile);
2270 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2271 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2272 outputChunk.Data());
2273 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2276 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2280 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2281 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2282 outputChunk.Data());
2283 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2286 if (fMergeExcludes.Length() &&
2287 fMergeExcludes.Contains(outputFile.Data())) continue;
2288 // Perform a 'find' command in the output directory, looking for registered outputs
2289 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2291 Error("MergeOutputs", "Terminate() will NOT be executed");
2294 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2295 if (fileOpened) fileOpened->Close();
2300 //______________________________________________________________________________
2301 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2303 // Use the output files connected to output containers from the analysis manager
2304 // rather than the files defined by SetOutputFiles
2305 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2306 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2307 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2310 //______________________________________________________________________________
2311 void AliAnalysisAlien::SetOutputFiles(const char *list)
2313 // Manually set the output files list.
2314 // Removes duplicates. Not allowed if default outputs are not disabled.
2315 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2316 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2319 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2321 TString slist = list;
2322 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2323 TObjArray *arr = slist.Tokenize(" ");
2327 while ((os=(TObjString*)next())) {
2328 sout = os->GetString();
2329 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2330 if (fOutputFiles.Contains(sout)) continue;
2331 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2332 fOutputFiles += sout;
2337 //______________________________________________________________________________
2338 void AliAnalysisAlien::SetOutputArchive(const char *list)
2340 // Manually set the output archive list. Free text - you are on your own...
2341 // Not allowed if default outputs are not disabled.
2342 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2343 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2346 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2347 fOutputArchive = list;
2350 //______________________________________________________________________________
2351 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2353 // Setting a prefered output SE is not allowed anymore.
2354 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2357 //______________________________________________________________________________
2358 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2360 // Start remote grid analysis.
2361 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2362 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2363 if (!mgr || !mgr->IsInitialized()) {
2364 Error("StartAnalysis", "You need an initialized analysis manager for this");
2367 // Are we in PROOF mode ?
2368 if (mgr->IsProofMode()) {
2369 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2370 if (fProofCluster.IsNull()) {
2371 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2374 if (fProofDataSet.IsNull() && !testMode) {
2375 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2378 // Set the needed environment
2379 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2380 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2381 if (fProofReset && !testMode) {
2382 if (fProofReset==1) {
2383 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2384 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2386 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2387 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2389 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2392 // Do we need to change the ROOT version ? The success of this cannot be checked.
2393 if (!fRootVersionForProof.IsNull() && !testMode) {
2394 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2395 fProofCluster.Data(), fRootVersionForProof.Data()));
2397 // Connect to PROOF and check the status
2400 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2401 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2403 if (!sworkers.IsNull())
2404 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2406 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2408 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2410 Error("StartAnalysis", "Could not start PROOF in test mode");
2415 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2418 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2419 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2420 // Is dataset existing ?
2422 TString dataset = fProofDataSet;
2423 Int_t index = dataset.Index("#");
2424 if (index>=0) dataset.Remove(index);
2425 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2426 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2429 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2431 // Is ClearPackages() needed ?
2432 if (TestSpecialBit(kClearPackages)) {
2433 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2434 gROOT->ProcessLine("gProof->ClearPackages();");
2436 // Is a given aliroot mode requested ?
2439 if (!fAliRootMode.IsNull()) {
2440 TString alirootMode = fAliRootMode;
2441 if (alirootMode == "default") alirootMode = "";
2442 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2443 optionsList.SetOwner();
2444 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2445 // Check the additional libs to be loaded
2447 Bool_t parMode = kFALSE;
2448 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2449 // Parse the extra libs for .so
2450 if (fAdditionalLibs.Length()) {
2451 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2454 while((str=(TObjString*)next())) {
2455 if (str->GetString().Contains(".so")) {
2457 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());
2460 TString stmp = str->GetName();
2461 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2462 stmp.ReplaceAll(".so","");
2463 if (!extraLibs.IsNull()) extraLibs += ":";
2467 if (str->GetString().Contains(".par")) {
2468 // The first par file found in the list will not allow any further .so
2470 if (!parLibs.IsNull()) parLibs += ":";
2471 parLibs += str->GetName();
2475 if (list) delete list;
2477 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2478 // Check extra includes
2479 if (!fIncludePath.IsNull()) {
2480 TString includePath = fIncludePath;
2481 includePath.ReplaceAll(" ",":");
2482 includePath.ReplaceAll("$ALICE_ROOT","");
2483 includePath.ReplaceAll("${ALICE_ROOT}","");
2484 includePath.ReplaceAll("-I","");
2485 includePath.Strip(TString::kTrailing, ':');
2486 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2487 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2489 // Check if connection to grid is requested
2490 if (TestSpecialBit(kProofConnectGrid))
2491 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2492 // Enable AliRoot par
2494 // Enable proof lite package
2495 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2496 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2497 TNamed *obj = (TNamed*)optionsList.At(i);
2498 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2500 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2501 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2502 Info("StartAnalysis", "AliRootProofLite enabled");
2504 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2508 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2509 fAliROOTVersion.Data(), &optionsList))) {
2510 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2514 // Enable first par files from fAdditionalLibs
2515 if (!parLibs.IsNull()) {
2516 TObjArray *list = parLibs.Tokenize(":");
2518 TObjString *package;
2519 while((package=(TObjString*)next())) {
2520 TString spkg = package->GetName();
2521 spkg.ReplaceAll(".par", "");
2522 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2523 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2524 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2525 if (gROOT->ProcessLine(enablePackage)) {
2526 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2530 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2534 if (list) delete list;
2537 if (fAdditionalLibs.Contains(".so") && !testMode) {
2538 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2539 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2543 // Enable par files if requested
2544 if (fPackages && fPackages->GetEntries()) {
2545 TIter next(fPackages);
2547 while ((package=next())) {
2548 // Skip packages already enabled
2549 if (parLibs.Contains(package->GetName())) continue;
2550 TString spkg = package->GetName();
2551 spkg.ReplaceAll(".par", "");
2552 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2553 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2554 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2555 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2559 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2564 // Do we need to load analysis source files ?
2565 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2566 if (fAnalysisSource.Length()) {
2567 TObjArray *list = fAnalysisSource.Tokenize(" ");
2570 while((str=(TObjString*)next())) {
2571 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2573 if (list) delete list;
2576 // Register dataset to proof lite.
2577 if (fFileForTestMode.IsNull()) {
2578 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2581 if (gSystem->AccessPathName(fFileForTestMode)) {
2582 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2585 TFileCollection *coll = new TFileCollection();
2586 coll->AddFromFile(fFileForTestMode);
2587 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2588 gROOT->ProcessLine("gProof->ShowDataSets()");
2593 // Check if output files have to be taken from the analysis manager
2594 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2595 // Add output files and AOD files
2596 fOutputFiles = GetListOfFiles("outaod");
2597 // Add extra files registered to the analysis manager
2598 TString extra = GetListOfFiles("ext");
2599 if (!extra.IsNull()) {
2600 extra.ReplaceAll(".root", "*.root");
2601 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2602 fOutputFiles += extra;
2604 // Compose the output archive.
2605 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2606 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2608 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2609 if (TestBit(AliAnalysisGrid::kOffline)) {
2610 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2611 \n there nor any job run. You can revise the JDL and analysis \
2612 \n macro then run the same in \"submit\" mode.");
2613 } else if (TestBit(AliAnalysisGrid::kTest)) {
2614 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2616 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2617 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2618 \n space and job submitted.");
2619 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2620 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2621 if (fMergeViaJDL) CheckInputData();
2624 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2629 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2632 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2633 if (!CheckInputData()) {
2634 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2637 if (!CreateDataset(fDataPattern)) {
2639 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2640 if (fRunNumbers.Length()) serror = "run numbers";
2641 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2642 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2643 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2646 WriteAnalysisFile();
2647 WriteAnalysisMacro();
2649 WriteValidationScript();
2651 WriteMergingMacro();
2652 WriteMergeExecutable();
2653 WriteValidationScript(kTRUE);
2655 if (!CreateJDL()) return kFALSE;
2656 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2658 // Locally testing the analysis
2659 Info("StartAnalysis", "\n_______________________________________________________________________ \
2660 \n Running analysis script in a daughter shell as on a worker node \
2661 \n_______________________________________________________________________");
2662 TObjArray *list = fOutputFiles.Tokenize(",");
2666 while((str=(TObjString*)next())) {
2667 outputFile = str->GetString();
2668 Int_t index = outputFile.Index("@");
2669 if (index > 0) outputFile.Remove(index);
2670 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2673 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2674 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2675 // gSystem->Exec("cat stdout");
2678 // Check if submitting is managed by LPM manager
2679 if (fProductionMode) {
2680 TString prodfile = fJDLName;
2681 prodfile.ReplaceAll(".jdl", ".prod");
2682 WriteProductionFile(prodfile);
2683 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2686 // Submit AliEn job(s)
2687 gGrid->Cd(fGridOutputDir);
2690 if (!fRunNumbers.Length() && !fRunRange[0]) {
2691 // Submit a given xml or a set of runs
2692 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2693 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2695 const char *cjobId = res->GetKey(0,"jobId");
2699 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2702 Info("StartAnalysis", "\n_______________________________________________________________________ \
2703 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2704 \n_______________________________________________________________________",
2705 fJDLName.Data(), cjobId);
2710 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2714 // Submit for a range of enumeration of runs.
2715 if (!Submit()) return kFALSE;
2718 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2719 \n You may exit at any time and terminate the job later using the option <terminate> \
2720 \n ##################################################################################", jobID.Data());
2721 gSystem->Exec("aliensh");
2725 //______________________________________________________________________________
2726 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2728 // Get a comma-separated list of output files of the requested type.
2729 // Type can be (case unsensitive):
2730 // aod - list of aod files (std, extensions and filters)
2731 // out - list of output files connected to containers (but not aod's or extras)
2732 // ext - list of extra files registered to the manager
2733 // ter - list of files produced in terminate
2734 static TString files;
2736 TString stype = type;
2738 TString aodfiles, extra;
2739 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2741 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2742 return files.Data();
2744 if (mgr->GetOutputEventHandler()) {
2745 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2746 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2747 if (!extraaod.IsNull()) {
2749 aodfiles += extraaod;
2752 if (stype.Contains("aod")) {
2754 if (stype == "aod") return files.Data();
2756 // Add output files that are not in the list of AOD files
2757 TString outputfiles = "";
2758 TIter next(mgr->GetOutputs());
2759 AliAnalysisDataContainer *output;
2760 const char *filename = 0;
2761 while ((output=(AliAnalysisDataContainer*)next())) {
2762 filename = output->GetFileName();
2763 if (!(strcmp(filename, "default"))) continue;
2764 if (outputfiles.Contains(filename)) continue;
2765 if (aodfiles.Contains(filename)) continue;
2766 if (!outputfiles.IsNull()) outputfiles += ",";
2767 outputfiles += filename;
2769 if (stype.Contains("out")) {
2770 if (!files.IsNull()) files += ",";
2771 files += outputfiles;
2772 if (stype == "out") return files.Data();
2774 // Add extra files registered to the analysis manager
2776 extra = mgr->GetExtraFiles();
2777 if (!extra.IsNull()) {
2779 extra.ReplaceAll(" ", ",");
2780 TObjArray *fextra = extra.Tokenize(",");
2781 TIter nextx(fextra);
2783 while ((obj=nextx())) {
2784 if (aodfiles.Contains(obj->GetName())) continue;
2785 if (outputfiles.Contains(obj->GetName())) continue;
2786 if (sextra.Contains(obj->GetName())) continue;
2787 if (!sextra.IsNull()) sextra += ",";
2788 sextra += obj->GetName();
2791 if (stype.Contains("ext")) {
2792 if (!files.IsNull()) files += ",";
2796 if (stype == "ext") return files.Data();
2798 if (!fTerminateFiles.IsNull()) {
2799 fTerminateFiles.Strip();
2800 fTerminateFiles.ReplaceAll(" ",",");
2801 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2802 TIter nextx(fextra);
2804 while ((obj=nextx())) {
2805 if (aodfiles.Contains(obj->GetName())) continue;
2806 if (outputfiles.Contains(obj->GetName())) continue;
2807 if (termfiles.Contains(obj->GetName())) continue;
2808 if (sextra.Contains(obj->GetName())) continue;
2809 if (!termfiles.IsNull()) termfiles += ",";
2810 termfiles += obj->GetName();
2814 if (stype.Contains("ter")) {
2815 if (!files.IsNull() && !termfiles.IsNull()) {
2820 return files.Data();
2823 //______________________________________________________________________________
2824 Bool_t AliAnalysisAlien::Submit()
2826 // Submit all master jobs.
2827 Int_t nmasterjobs = fInputFiles->GetEntries();
2828 Long_t tshoot = gSystem->Now();
2829 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2830 while (fNsubmitted < nmasterjobs) {
2831 Long_t now = gSystem->Now();
2832 if ((now-tshoot)>30000) {
2834 if (!SubmitNext()) return kFALSE;
2840 //______________________________________________________________________________
2841 Bool_t AliAnalysisAlien::SubmitMerging()
2843 // Submit all merging jobs.
2844 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2845 gGrid->Cd(fGridOutputDir);
2846 TString mergeJDLName = fExecutable;
2847 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2849 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
2852 Int_t ntosubmit = fInputFiles->GetEntries();
2853 for (Int_t i=0; i<ntosubmit; i++) {
2854 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2855 runOutDir.ReplaceAll(".xml", "");
2856 if (fOutputToRunNo) {
2857 // The output directory is the run number
2858 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2859 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2861 if (!fRunNumbers.Length() && !fRunRange[0]) {
2862 // The output directory is the grid outdir
2863 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
2864 runOutDir = fGridOutputDir;
2866 // The output directory is the master number in 3 digits format
2867 printf("### Submitting merging job for master <%03d>\n", i);
2868 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2871 // Check now the number of merging stages.
2872 TObjArray *list = fOutputFiles.Tokenize(",");
2876 while((str=(TObjString*)next())) {
2877 outputFile = str->GetString();
2878 Int_t index = outputFile.Index("@");
2879 if (index > 0) outputFile.Remove(index);
2880 if (!fMergeExcludes.Contains(outputFile)) break;
2883 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2884 if (!done && (i==ntosubmit-1)) return kFALSE;
2885 if (!fRunNumbers.Length() && !fRunRange[0]) break;
2887 if (!ntosubmit) return kTRUE;
2888 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
2889 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
2890 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
2891 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
2892 \n ################################################################################################################");
2893 gSystem->Exec("aliensh");
2897 //______________________________________________________________________________
2898 Bool_t AliAnalysisAlien::SubmitNext()
2900 // Submit next bunch of master jobs if the queue is free. The first master job is
2901 // submitted right away, while the next will not be unless the previous was split.
2902 // The plugin will not submit new master jobs if there are more that 500 jobs in
2904 static Bool_t iscalled = kFALSE;
2905 static Int_t firstmaster = 0;
2906 static Int_t lastmaster = 0;
2907 static Int_t npermaster = 0;
2908 if (iscalled) return kTRUE;
2910 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2911 Int_t ntosubmit = 0;
2914 Int_t nmasterjobs = fInputFiles->GetEntries();
2917 if (!IsUseSubmitPolicy()) {
2919 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2920 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2921 ntosubmit = nmasterjobs;
2924 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2925 printf("=== master %d: %s\n", lastmaster, status.Data());
2926 // If last master not split, just return
2927 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2928 // No more than 100 waiting jobs
2929 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2930 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2931 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2932 if (!ntosubmit) ntosubmit = 1;
2933 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2934 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2936 for (Int_t i=0; i<ntosubmit; i++) {
2937 // Submit for a range of enumeration of runs.
2938 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2940 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2941 runOutDir.ReplaceAll(".xml", "");
2943 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2945 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2946 printf("********* %s\n",query.Data());
2947 res = gGrid->Command(query);
2949 TString cjobId1 = res->GetKey(0,"jobId");
2950 if (!cjobId1.Length()) {
2954 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2957 Info("StartAnalysis", "\n_______________________________________________________________________ \
2958 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2959 \n_______________________________________________________________________",
2960 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2963 lastmaster = cjobId1.Atoi();
2964 if (!firstmaster) firstmaster = lastmaster;
2969 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2977 //______________________________________________________________________________
2978 void AliAnalysisAlien::WriteAnalysisFile()
2980 // Write current analysis manager into the file <analysisFile>
2981 TString analysisFile = fExecutable;
2982 analysisFile.ReplaceAll(".sh", ".root");
2983 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2984 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2985 if (!mgr || !mgr->IsInitialized()) {
2986 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2989 // Check analysis type
2991 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2992 handler = (TObject*)mgr->GetInputEventHandler();
2994 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
2995 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
2996 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2997 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2999 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3000 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3003 TDirectory *cdir = gDirectory;
3004 TFile *file = TFile::Open(analysisFile, "RECREATE");
3006 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3007 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3008 // Unless merging makes no sense
3009 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3012 // Enable termination for local jobs
3013 mgr->SetSkipTerminate(kFALSE);
3015 if (cdir) cdir->cd();
3016 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3018 Bool_t copy = kTRUE;
3019 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3022 TString workdir = gGrid->GetHomeDirectory();
3023 workdir += fGridWorkingDir;
3024 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3025 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3026 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
3030 //______________________________________________________________________________
3031 void AliAnalysisAlien::WriteAnalysisMacro()
3033 // Write the analysis macro that will steer the analysis in grid mode.
3034 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3036 out.open(fAnalysisMacro.Data(), ios::out);
3038 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3041 Bool_t hasSTEERBase = kFALSE;
3042 Bool_t hasESD = kFALSE;
3043 Bool_t hasAOD = kFALSE;
3044 Bool_t hasANALYSIS = kFALSE;
3045 Bool_t hasANALYSISalice = kFALSE;
3046 Bool_t hasCORRFW = kFALSE;
3047 TString func = fAnalysisMacro;
3048 TString type = "ESD";
3049 TString comment = "// Analysis using ";
3050 if (IsUseMCchain()) {
3054 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3055 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3060 if (type!="AOD" && fFriendChainName!="") {
3061 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3064 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3065 else comment += " data";
3066 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3067 func.ReplaceAll(".C", "");
3068 out << "void " << func.Data() << "()" << endl;
3070 out << comment.Data() << endl;
3071 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3072 out << " TStopwatch timer;" << endl;
3073 out << " timer.Start();" << endl << endl;
3074 // Change temp directory to current one
3075 out << "// Set temporary merging directory to current one" << endl;
3076 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3077 out << "// Set temporary compilation directory to current one" << endl;
3078 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3079 // Reset existing include path
3080 out << "// Reset existing include path and add current directory first in the search" << endl;
3081 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3082 if (!fExecutableCommand.Contains("aliroot")) {
3083 out << "// load base root libraries" << endl;
3084 out << " gSystem->Load(\"libTree\");" << endl;
3085 out << " gSystem->Load(\"libGeom\");" << endl;
3086 out << " gSystem->Load(\"libVMC\");" << endl;
3087 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3088 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3090 if (fAdditionalRootLibs.Length()) {
3091 // in principle libtree /lib geom libvmc etc. can go into this list, too
3092 out << "// Add aditional libraries" << endl;
3093 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3096 while((str=(TObjString*)next())) {
3097 if (str->GetString().Contains(".so"))
3098 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3100 if (list) delete list;
3102 out << "// Load analysis framework libraries" << endl;
3103 TString setupPar = "AliAnalysisAlien::SetupPar";
3105 if (!fExecutableCommand.Contains("aliroot")) {
3106 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3107 out << " gSystem->Load(\"libESD\");" << endl;
3108 out << " gSystem->Load(\"libAOD\");" << endl;
3110 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3111 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3112 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3114 TIter next(fPackages);
3117 while ((obj=next())) {
3118 pkgname = obj->GetName();
3119 if (pkgname == "STEERBase" ||
3120 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3121 if (pkgname == "ESD" ||
3122 pkgname == "ESD.par") hasESD = kTRUE;
3123 if (pkgname == "AOD" ||
3124 pkgname == "AOD.par") hasAOD = kTRUE;
3125 if (pkgname == "ANALYSIS" ||
3126 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3127 if (pkgname == "ANALYSISalice" ||
3128 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3129 if (pkgname == "CORRFW" ||
3130 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3132 if (hasANALYSISalice) setupPar = "SetupPar";
3133 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3134 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3135 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3136 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3137 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3138 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3139 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3140 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3141 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3142 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3143 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3144 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3145 out << "// Compile other par packages" << endl;
3147 while ((obj=next())) {
3148 pkgname = obj->GetName();
3149 if (pkgname == "STEERBase" ||
3150 pkgname == "STEERBase.par" ||
3152 pkgname == "ESD.par" ||
3154 pkgname == "AOD.par" ||
3155 pkgname == "ANALYSIS" ||
3156 pkgname == "ANALYSIS.par" ||
3157 pkgname == "ANALYSISalice" ||
3158 pkgname == "ANALYSISalice.par" ||
3159 pkgname == "CORRFW" ||
3160 pkgname == "CORRFW.par") continue;
3161 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3164 out << "// include path" << endl;
3165 // Get the include path from the interpreter and remove entries pointing to AliRoot
3166 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3167 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3168 out << " TIter nextpath(listpaths);" << endl;
3169 out << " TObjString *pname;" << endl;
3170 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3171 out << " TString current = pname->GetName();" << endl;
3172 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3173 out << " gSystem->AddIncludePath(current);" << endl;
3174 out << " }" << endl;
3175 out << " if (listpaths) delete listpaths;" << endl;
3176 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3177 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3178 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3179 if (fAdditionalLibs.Length()) {
3180 out << "// Add aditional AliRoot libraries" << endl;
3181 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3184 while((str=(TObjString*)next())) {
3185 if (str->GetString().Contains(".so"))
3186 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3187 if (str->GetString().Contains(".par"))
3188 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3190 if (list) delete list;
3193 out << "// analysis source to be compiled at runtime (if any)" << endl;
3194 if (fAnalysisSource.Length()) {
3195 TObjArray *list = fAnalysisSource.Tokenize(" ");
3198 while((str=(TObjString*)next())) {
3199 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3201 if (list) delete list;
3204 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3205 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3206 if (fFastReadOption) {
3207 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 !!! \
3208 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3209 out << "// fast xrootd reading enabled" << endl;
3210 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3211 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3212 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3213 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3214 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3215 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3217 out << "// connect to AliEn and make the chain" << endl;
3218 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3219 out << "// read the analysis manager from file" << endl;
3220 TString analysisFile = fExecutable;
3221 analysisFile.ReplaceAll(".sh", ".root");
3222 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3223 out << " if (!file) return;" << endl;
3224 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3225 out << " AliAnalysisManager *mgr = 0;" << endl;
3226 out << " TKey *key;" << endl;
3227 out << " while ((key=(TKey*)nextkey())) {" << endl;
3228 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3229 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3230 out << " };" << endl;
3231 out << " if (!mgr) {" << endl;
3232 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3233 out << " return;" << endl;
3234 out << " }" << endl << endl;
3235 out << " mgr->PrintStatus();" << endl;
3236 if (AliAnalysisManager::GetAnalysisManager()) {
3237 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3238 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3240 if (TestBit(AliAnalysisGrid::kTest))
3241 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3243 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3246 if (IsUsingTags()) {
3247 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3249 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3251 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3252 out << " timer.Stop();" << endl;
3253 out << " timer.Print();" << endl;
3254 out << "}" << endl << endl;
3255 if (IsUsingTags()) {
3256 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3258 out << "// Create a chain using tags from the xml file." << endl;
3259 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3260 out << " if (!coll) {" << endl;
3261 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3262 out << " return NULL;" << endl;
3263 out << " }" << endl;
3264 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3265 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3266 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3267 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3268 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3269 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3270 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3271 out << " // Check if the cuts configuration file was provided" << endl;
3272 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3273 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3274 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3275 out << " }" << endl;
3276 if (fFriendChainName=="") {
3277 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3279 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3280 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3281 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3283 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3284 out << " chain->ls();" << endl;
3285 out << " return chain;" << endl;
3286 out << "}" << endl << endl;
3287 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3288 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3289 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3290 msg += " AliLHCTagCuts *lhcCuts,\n";
3291 msg += " AliDetectorTagCuts *detCuts,\n";
3292 msg += " AliEventTagCuts *evCuts)";
3293 Info("WriteAnalysisMacro", "%s", msg.Data());
3296 if (!IsUsingTags() || fFriendChainName!="") {
3297 out <<"//________________________________________________________________________________" << endl;
3298 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3300 out << "// Create a chain using url's from xml file" << endl;
3301 out << " TString filename;" << endl;
3302 out << " Int_t run = 0;" << endl;
3303 if (IsUseMCchain()) {
3304 out << " TString treename = \"TE\";" << endl;
3306 out << " TString treename = type;" << endl;
3307 out << " treename.ToLower();" << endl;
3308 out << " treename += \"Tree\";" << endl;
3310 out << " printf(\"***************************************\\n\");" << endl;
3311 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3312 out << " printf(\"***************************************\\n\");" << endl;
3313 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3314 out << " if (!coll) {" << endl;
3315 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3316 out << " return NULL;" << endl;
3317 out << " }" << endl;
3318 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3319 out << " TChain *chain = new TChain(treename);" << endl;
3320 if(fFriendChainName!="") {
3321 out << " TChain *chainFriend = new TChain(treename);" << endl;
3323 out << " coll->Reset();" << endl;
3324 out << " while (coll->Next()) {" << endl;
3325 out << " filename = coll->GetTURL("");" << endl;
3326 out << " if (mgr) {" << endl;
3327 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3328 out << " if (nrun && nrun != run) {" << endl;
3329 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3330 out << " mgr->SetRunFromPath(nrun);" << endl;
3331 out << " run = nrun;" << endl;
3332 out << " }" << endl;
3333 out << " }" << endl;
3334 out << " chain->Add(filename);" << endl;
3335 if(fFriendChainName!="") {
3336 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3337 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3338 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3339 out << " chainFriend->Add(fileFriend.Data());" << endl;
3341 out << " }" << endl;
3342 out << " if (!chain->GetNtrees()) {" << endl;
3343 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3344 out << " return NULL;" << endl;
3345 out << " }" << endl;
3346 if(fFriendChainName!="") {
3347 out << " chain->AddFriend(chainFriend);" << endl;
3349 out << " return chain;" << endl;
3350 out << "}" << endl << endl;
3352 if (hasANALYSISalice) {
3353 out <<"//________________________________________________________________________________" << endl;
3354 out << "Bool_t SetupPar(const char *package) {" << endl;
3355 out << "// Compile the package and set it up." << endl;
3356 out << " TString pkgdir = package;" << endl;
3357 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3358 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3359 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3360 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3361 out << " // Check for BUILD.sh and execute" << endl;
3362 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3363 out << " printf(\"*******************************\\n\");" << endl;
3364 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3365 out << " printf(\"*******************************\\n\");" << endl;
3366 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3367 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3368 out << " gSystem->ChangeDirectory(cdir);" << endl;
3369 out << " return kFALSE;" << endl;
3370 out << " }" << endl;
3371 out << " } else {" << endl;
3372 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3373 out << " gSystem->ChangeDirectory(cdir);" << endl;
3374 out << " return kFALSE;" << endl;
3375 out << " }" << endl;
3376 out << " // Check for SETUP.C and execute" << endl;
3377 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3378 out << " printf(\"*******************************\\n\");" << endl;
3379 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3380 out << " printf(\"*******************************\\n\");" << endl;
3381 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3382 out << " } else {" << endl;
3383 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3384 out << " gSystem->ChangeDirectory(cdir);" << endl;
3385 out << " return kFALSE;" << endl;
3386 out << " }" << endl;
3387 out << " // Restore original workdir" << endl;
3388 out << " gSystem->ChangeDirectory(cdir);" << endl;
3389 out << " return kTRUE;" << endl;
3392 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3394 Bool_t copy = kTRUE;
3395 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3398 TString workdir = gGrid->GetHomeDirectory();
3399 workdir += fGridWorkingDir;
3400 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3401 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3402 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3403 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3404 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3406 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3407 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3411 //______________________________________________________________________________
3412 void AliAnalysisAlien::WriteMergingMacro()
3414 // Write a macro to merge the outputs per master job.
3415 if (!fMergeViaJDL) return;
3416 if (!fOutputFiles.Length()) {
3417 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3420 TString mergingMacro = fExecutable;
3421 mergingMacro.ReplaceAll(".sh","_merge.C");
3422 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3423 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3425 out.open(mergingMacro.Data(), ios::out);
3427 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3430 Bool_t hasSTEERBase = kFALSE;
3431 Bool_t hasESD = kFALSE;
3432 Bool_t hasAOD = kFALSE;
3433 Bool_t hasANALYSIS = kFALSE;
3434 Bool_t hasANALYSISalice = kFALSE;
3435 Bool_t hasCORRFW = kFALSE;
3436 TString func = mergingMacro;
3438 func.ReplaceAll(".C", "");
3439 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3441 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3442 out << " TStopwatch timer;" << endl;
3443 out << " timer.Start();" << endl << endl;
3444 // Reset existing include path
3445 out << "// Reset existing include path and add current directory first in the search" << endl;
3446 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3447 if (!fExecutableCommand.Contains("aliroot")) {
3448 out << "// load base root libraries" << endl;
3449 out << " gSystem->Load(\"libTree\");" << endl;
3450 out << " gSystem->Load(\"libGeom\");" << endl;
3451 out << " gSystem->Load(\"libVMC\");" << endl;
3452 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3453 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3455 if (fAdditionalRootLibs.Length()) {
3456 // in principle libtree /lib geom libvmc etc. can go into this list, too
3457 out << "// Add aditional libraries" << endl;
3458 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3461 while((str=(TObjString*)next())) {
3462 if (str->GetString().Contains(".so"))
3463 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3465 if (list) delete list;
3467 out << "// Load analysis framework libraries" << endl;
3469 if (!fExecutableCommand.Contains("aliroot")) {
3470 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3471 out << " gSystem->Load(\"libESD\");" << endl;
3472 out << " gSystem->Load(\"libAOD\");" << endl;
3474 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3475 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3476 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3478 TIter next(fPackages);
3481 TString setupPar = "AliAnalysisAlien::SetupPar";
3482 while ((obj=next())) {
3483 pkgname = obj->GetName();
3484 if (pkgname == "STEERBase" ||
3485 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3486 if (pkgname == "ESD" ||
3487 pkgname == "ESD.par") hasESD = kTRUE;
3488 if (pkgname == "AOD" ||
3489 pkgname == "AOD.par") hasAOD = kTRUE;
3490 if (pkgname == "ANALYSIS" ||
3491 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3492 if (pkgname == "ANALYSISalice" ||
3493 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3494 if (pkgname == "CORRFW" ||
3495 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3497 if (hasANALYSISalice) setupPar = "SetupPar";
3498 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3499 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3500 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3501 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3502 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3503 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3504 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3505 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3506 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3507 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3508 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3509 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3510 out << "// Compile other par packages" << endl;
3512 while ((obj=next())) {
3513 pkgname = obj->GetName();
3514 if (pkgname == "STEERBase" ||
3515 pkgname == "STEERBase.par" ||
3517 pkgname == "ESD.par" ||
3519 pkgname == "AOD.par" ||
3520 pkgname == "ANALYSIS" ||
3521 pkgname == "ANALYSIS.par" ||
3522 pkgname == "ANALYSISalice" ||
3523 pkgname == "ANALYSISalice.par" ||
3524 pkgname == "CORRFW" ||
3525 pkgname == "CORRFW.par") continue;
3526 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3529 out << "// include path" << endl;
3530 // Get the include path from the interpreter and remove entries pointing to AliRoot
3531 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3532 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3533 out << " TIter nextpath(listpaths);" << endl;
3534 out << " TObjString *pname;" << endl;
3535 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3536 out << " TString current = pname->GetName();" << endl;
3537 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3538 out << " gSystem->AddIncludePath(current);" << endl;
3539 out << " }" << endl;
3540 out << " if (listpaths) delete listpaths;" << endl;
3541 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3542 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3543 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3544 if (fAdditionalLibs.Length()) {
3545 out << "// Add aditional AliRoot libraries" << endl;
3546 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3549 while((str=(TObjString*)next())) {
3550 if (str->GetString().Contains(".so"))
3551 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3553 if (list) delete list;
3556 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3557 if (fAnalysisSource.Length()) {
3558 TObjArray *list = fAnalysisSource.Tokenize(" ");
3561 while((str=(TObjString*)next())) {
3562 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3564 if (list) delete list;
3568 if (fFastReadOption) {
3569 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 !!!");
3570 out << "// fast xrootd reading enabled" << endl;
3571 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3572 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3573 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3574 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3575 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3576 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3578 // Change temp directory to current one
3579 out << "// Set temporary merging directory to current one" << endl;
3580 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3581 out << "// Set temporary compilation directory to current one" << endl;
3582 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3583 out << "// Connect to AliEn" << endl;
3584 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3585 out << " TString outputDir = dir;" << endl;
3586 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3587 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3588 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3589 out << " TIter *iter = new TIter(list);" << endl;
3590 out << " TObjString *str;" << endl;
3591 out << " TString outputFile;" << endl;
3592 out << " Bool_t merged = kTRUE;" << endl;
3593 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3594 out << " outputFile = str->GetString();" << endl;
3595 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3596 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3597 out << " if (index > 0) outputFile.Remove(index);" << endl;
3598 out << " // Skip already merged outputs" << endl;
3599 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3600 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3601 out << " continue;" << endl;
3602 out << " }" << endl;
3603 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3604 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3605 out << " if (!merged) {" << endl;
3606 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3607 out << " return;" << endl;
3608 out << " }" << endl;
3609 out << " }" << endl;
3610 out << " // all outputs merged, validate" << endl;
3611 out << " ofstream out;" << endl;
3612 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3613 out << " out.close();" << endl;
3614 out << " // read the analysis manager from file" << endl;
3615 TString analysisFile = fExecutable;
3616 analysisFile.ReplaceAll(".sh", ".root");
3617 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3618 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3619 out << " if (!file) return;" << endl;
3620 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3621 out << " AliAnalysisManager *mgr = 0;" << endl;
3622 out << " TKey *key;" << endl;
3623 out << " while ((key=(TKey*)nextkey())) {" << endl;
3624 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3625 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3626 out << " };" << endl;
3627 out << " if (!mgr) {" << endl;
3628 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3629 out << " return;" << endl;
3630 out << " }" << endl << endl;
3631 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3632 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3633 out << " mgr->PrintStatus();" << endl;
3634 if (AliAnalysisManager::GetAnalysisManager()) {
3635 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3636 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3638 if (TestBit(AliAnalysisGrid::kTest))
3639 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3641 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3644 out << " TTree *tree = NULL;" << endl;
3645 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3646 out << "}" << endl << endl;
3647 if (hasANALYSISalice) {
3648 out <<"//________________________________________________________________________________" << endl;
3649 out << "Bool_t SetupPar(const char *package) {" << endl;
3650 out << "// Compile the package and set it up." << endl;
3651 out << " TString pkgdir = package;" << endl;
3652 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3653 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3654 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3655 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3656 out << " // Check for BUILD.sh and execute" << endl;
3657 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3658 out << " printf(\"*******************************\\n\");" << endl;
3659 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3660 out << " printf(\"*******************************\\n\");" << endl;
3661 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3662 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3663 out << " gSystem->ChangeDirectory(cdir);" << endl;
3664 out << " return kFALSE;" << endl;
3665 out << " }" << endl;
3666 out << " } else {" << endl;
3667 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3668 out << " gSystem->ChangeDirectory(cdir);" << endl;
3669 out << " return kFALSE;" << endl;
3670 out << " }" << endl;
3671 out << " // Check for SETUP.C and execute" << endl;
3672 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3673 out << " printf(\"*******************************\\n\");" << endl;
3674 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3675 out << " printf(\"*******************************\\n\");" << endl;
3676 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3677 out << " } else {" << endl;
3678 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3679 out << " gSystem->ChangeDirectory(cdir);" << endl;
3680 out << " return kFALSE;" << endl;
3681 out << " }" << endl;
3682 out << " // Restore original workdir" << endl;
3683 out << " gSystem->ChangeDirectory(cdir);" << endl;
3684 out << " return kTRUE;" << endl;
3688 Bool_t copy = kTRUE;
3689 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3692 TString workdir = gGrid->GetHomeDirectory();
3693 workdir += fGridWorkingDir;
3694 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3695 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3696 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3700 //______________________________________________________________________________
3701 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3703 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3704 // Note that for loading the compiled library. The current directory should have precedence in
3706 TString pkgdir = package;
3707 pkgdir.ReplaceAll(".par","");
3708 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3709 TString cdir = gSystem->WorkingDirectory();
3710 gSystem->ChangeDirectory(pkgdir);
3711 // Check for BUILD.sh and execute
3712 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3713 printf("**************************************************\n");
3714 printf("*** Building PAR archive %s\n", package);
3715 printf("**************************************************\n");
3716 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3717 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3718 gSystem->ChangeDirectory(cdir);
3722 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3723 gSystem->ChangeDirectory(cdir);
3726 // Check for SETUP.C and execute
3727 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3728 printf("**************************************************\n");
3729 printf("*** Setup PAR archive %s\n", package);
3730 printf("**************************************************\n");
3731 gROOT->Macro("PROOF-INF/SETUP.C");
3732 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3734 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3735 gSystem->ChangeDirectory(cdir);
3738 // Restore original workdir
3739 gSystem->ChangeDirectory(cdir);
3743 //______________________________________________________________________________
3744 void AliAnalysisAlien::WriteExecutable()
3746 // Generate the alien executable script.
3747 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3749 out.open(fExecutable.Data(), ios::out);
3751 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3754 out << "#!/bin/bash" << endl;
3755 // Make sure we can properly compile par files
3756 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3757 out << "echo \"=========================================\"" << endl;
3758 out << "echo \"############## PATH : ##############\"" << endl;
3759 out << "echo $PATH" << endl;
3760 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3761 out << "echo $LD_LIBRARY_PATH" << endl;
3762 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3763 out << "echo $ROOTSYS" << endl;
3764 out << "echo \"############## which root : ##############\"" << endl;
3765 out << "which root" << endl;
3766 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3767 out << "echo $ALICE_ROOT" << endl;
3768 out << "echo \"############## which aliroot : ##############\"" << endl;
3769 out << "which aliroot" << endl;
3770 out << "echo \"############## system limits : ##############\"" << endl;
3771 out << "ulimit -a" << endl;
3772 out << "echo \"############## memory : ##############\"" << endl;
3773 out << "free -m" << endl;
3774 out << "echo \"=========================================\"" << endl << endl;
3775 out << fExecutableCommand << " ";
3776 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3777 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3778 out << "echo \"############## memory after: ##############\"" << endl;
3779 out << "free -m" << endl;
3781 Bool_t copy = kTRUE;
3782 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3785 TString workdir = gGrid->GetHomeDirectory();
3786 TString bindir = Form("%s/bin", workdir.Data());
3787 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3788 workdir += fGridWorkingDir;
3789 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3790 if (FileExists(executable)) gGrid->Rm(executable);
3791 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3792 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3796 //______________________________________________________________________________
3797 void AliAnalysisAlien::WriteMergeExecutable()
3799 // Generate the alien executable script for the merging job.
3800 if (!fMergeViaJDL) return;
3801 TString mergeExec = fExecutable;
3802 mergeExec.ReplaceAll(".sh", "_merge.sh");
3803 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3805 out.open(mergeExec.Data(), ios::out);
3807 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3810 out << "#!/bin/bash" << endl;
3811 // Make sure we can properly compile par files
3812 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3813 out << "echo \"=========================================\"" << endl;
3814 out << "echo \"############## PATH : ##############\"" << endl;
3815 out << "echo $PATH" << endl;
3816 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3817 out << "echo $LD_LIBRARY_PATH" << endl;
3818 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3819 out << "echo $ROOTSYS" << endl;
3820 out << "echo \"############## which root : ##############\"" << endl;
3821 out << "which root" << endl;
3822 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3823 out << "echo $ALICE_ROOT" << endl;
3824 out << "echo \"############## which aliroot : ##############\"" << endl;
3825 out << "which aliroot" << endl;
3826 out << "echo \"############## system limits : ##############\"" << endl;
3827 out << "ulimit -a" << endl;
3828 out << "echo \"############## memory : ##############\"" << endl;
3829 out << "free -m" << endl;
3830 out << "echo \"=========================================\"" << endl << endl;
3831 TString mergeMacro = fExecutable;
3832 mergeMacro.ReplaceAll(".sh", "_merge.C");
3833 if (IsOneStageMerging())
3834 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3836 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3837 out << fExecutableCommand << " " << "$ARG" << endl;
3838 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3839 out << "echo \"############## memory after: ##############\"" << endl;
3840 out << "free -m" << endl;
3842 Bool_t copy = kTRUE;
3843 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3846 TString workdir = gGrid->GetHomeDirectory();
3847 TString bindir = Form("%s/bin", workdir.Data());
3848 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3849 workdir += fGridWorkingDir;
3850 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3851 if (FileExists(executable)) gGrid->Rm(executable);
3852 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3853 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3857 //______________________________________________________________________________
3858 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3860 // Write the production file to be submitted by LPM manager. The format is:
3861 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3862 // Next lines: full_path_to_dataset XXX (XXX is a string)
3863 // To submit, one has to: submit jdl XXX for all lines
3865 out.open(filename, ios::out);
3867 Error("WriteProductionFile", "Bad file name: %s", filename);
3871 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3872 workdir = gGrid->GetHomeDirectory();
3873 workdir += fGridWorkingDir;
3874 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3875 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3876 out << locjdl << " " << njobspermaster << endl;
3877 Int_t nmasterjobs = fInputFiles->GetEntries();
3878 for (Int_t i=0; i<nmasterjobs; i++) {
3879 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3880 runOutDir.ReplaceAll(".xml", "");
3882 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3884 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3887 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3888 if (FileExists(filename)) gGrid->Rm(filename);
3889 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3893 //______________________________________________________________________________
3894 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3896 // Generate the alien validation script.
3897 // Generate the validation script
3899 if (fValidationScript.IsNull()) {
3900 fValidationScript = fExecutable;
3901 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3903 TString validationScript = fValidationScript;
3904 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3906 Error("WriteValidationScript", "Alien connection required");
3909 if (!fTerminateFiles.IsNull()) {
3910 fTerminateFiles.Strip();
3911 fTerminateFiles.ReplaceAll(" ",",");
3913 TString outStream = "";
3914 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3915 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3917 out.open(validationScript, ios::out);
3918 out << "#!/bin/bash" << endl;
3919 out << "##################################################" << endl;
3920 out << "validateout=`dirname $0`" << endl;
3921 out << "validatetime=`date`" << endl;
3922 out << "validated=\"0\";" << endl;
3923 out << "error=0" << endl;
3924 out << "if [ -z $validateout ]" << endl;
3925 out << "then" << endl;
3926 out << " validateout=\".\"" << endl;
3927 out << "fi" << endl << endl;
3928 out << "cd $validateout;" << endl;
3929 out << "validateworkdir=`pwd`;" << endl << endl;
3930 out << "echo \"*******************************************************\"" << outStream << endl;
3931 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3933 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3934 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3935 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3936 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3937 out << "ls -la ./" << outStream << endl;
3938 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3939 out << "##################################################" << endl;
3942 out << "if [ ! -f stderr ] ; then" << endl;
3943 out << " error=1" << endl;
3944 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3945 out << " echo \"Error = $error\" " << outStream << endl;
3946 out << "fi" << endl;
3948 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3949 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3950 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3951 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3954 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3955 out << " error=1" << endl;
3956 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3957 out << " echo \"$parArch\" " << outStream << endl;
3958 out << " echo \"Error = $error\" " << outStream << endl;
3959 out << "fi" << endl;
3961 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3962 out << " error=1" << endl;
3963 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3964 out << " echo \"$segViol\" " << outStream << endl;
3965 out << " echo \"Error = $error\" " << outStream << endl;
3966 out << "fi" << endl;
3968 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3969 out << " error=1" << endl;
3970 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3971 out << " echo \"$segFault\" " << outStream << endl;
3972 out << " echo \"Error = $error\" " << outStream << endl;
3973 out << "fi" << endl;
3975 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3976 out << " error=1" << endl;
3977 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3978 out << " echo \"$glibcErr\" " << outStream << endl;
3979 out << " echo \"Error = $error\" " << outStream << endl;
3980 out << "fi" << endl;
3982 // Part dedicated to the specific analyses running into the train
3984 TString outputFiles = fOutputFiles;
3985 if (merge && !fTerminateFiles.IsNull()) {
3987 outputFiles += fTerminateFiles;
3989 TObjArray *arr = outputFiles.Tokenize(",");
3992 while (!merge && (os=(TObjString*)next1())) {
3993 // No need to validate outputs produced by merging since the merging macro does this
3994 outputFile = os->GetString();
3995 Int_t index = outputFile.Index("@");
3996 if (index > 0) outputFile.Remove(index);
3997 if (fTerminateFiles.Contains(outputFile)) continue;
3998 if (outputFile.Contains("*")) continue;
3999 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4000 out << " error=1" << endl;
4001 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4002 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4003 out << "fi" << endl;
4006 out << "if ! [ -f outputs_valid ] ; then" << endl;
4007 out << " error=1" << endl;
4008 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4009 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4010 out << "fi" << endl;
4012 out << "if [ $error = 0 ] ; then" << endl;
4013 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4014 if (!IsKeepLogs()) {
4015 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4017 out << " rm -f std*" << endl;
4019 out << "fi" << endl;
4021 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4022 out << "echo \"*******************************************************\"" << outStream << endl;
4023 out << "cd -" << endl;
4024 out << "exit $error" << endl;
4026 Bool_t copy = kTRUE;
4027 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4030 TString workdir = gGrid->GetHomeDirectory();
4031 workdir += fGridWorkingDir;
4032 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4033 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4034 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));