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 // Check if there is an old active session
2393 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2395 Error("StartAnalysis","You have to reset your old session first\n");
2398 // Do we need to change the ROOT version ? The success of this cannot be checked.
2399 if (!fRootVersionForProof.IsNull() && !testMode) {
2400 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2401 fProofCluster.Data(), fRootVersionForProof.Data()));
2403 // Connect to PROOF and check the status
2406 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2407 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2409 if (!sworkers.IsNull())
2410 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2412 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2414 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2416 Error("StartAnalysis", "Could not start PROOF in test mode");
2421 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2424 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2425 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2426 // Is dataset existing ?
2428 TString dataset = fProofDataSet;
2429 Int_t index = dataset.Index("#");
2430 if (index>=0) dataset.Remove(index);
2431 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2432 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2435 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2437 // Is ClearPackages() needed ?
2438 if (TestSpecialBit(kClearPackages)) {
2439 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2440 gROOT->ProcessLine("gProof->ClearPackages();");
2442 // Is a given aliroot mode requested ?
2445 if (!fAliRootMode.IsNull()) {
2446 TString alirootMode = fAliRootMode;
2447 if (alirootMode == "default") alirootMode = "";
2448 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2449 optionsList.SetOwner();
2450 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2451 // Check the additional libs to be loaded
2453 Bool_t parMode = kFALSE;
2454 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2455 // Parse the extra libs for .so
2456 if (fAdditionalLibs.Length()) {
2457 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2460 while((str=(TObjString*)next())) {
2461 if (str->GetString().Contains(".so")) {
2463 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());
2466 TString stmp = str->GetName();
2467 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2468 stmp.ReplaceAll(".so","");
2469 if (!extraLibs.IsNull()) extraLibs += ":";
2473 if (str->GetString().Contains(".par")) {
2474 // The first par file found in the list will not allow any further .so
2476 if (!parLibs.IsNull()) parLibs += ":";
2477 parLibs += str->GetName();
2481 if (list) delete list;
2483 if (!extraLibs.IsNull()) {
2484 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
2485 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2487 // Check extra includes
2488 if (!fIncludePath.IsNull()) {
2489 TString includePath = fIncludePath;
2490 includePath.ReplaceAll(" ",":");
2491 includePath.ReplaceAll("$ALICE_ROOT/","");
2492 includePath.ReplaceAll("${ALICE_ROOT}/","");
2493 includePath.ReplaceAll("-I","");
2494 includePath.Remove(TString::kTrailing, ':');
2495 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2496 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2498 // Check if connection to grid is requested
2499 if (TestSpecialBit(kProofConnectGrid))
2500 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2501 // Enable AliRoot par
2503 // Enable proof lite package
2504 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2505 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2506 TNamed *obj = (TNamed*)optionsList.At(i);
2507 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2509 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2510 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2511 Info("StartAnalysis", "AliRootProofLite enabled");
2513 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2517 if ( ! fAliROOTVersion.IsNull() ) {
2518 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2519 fAliROOTVersion.Data(), &optionsList))) {
2520 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2525 // Enable first par files from fAdditionalLibs
2526 if (!parLibs.IsNull()) {
2527 TObjArray *list = parLibs.Tokenize(":");
2529 TObjString *package;
2530 while((package=(TObjString*)next())) {
2531 TString spkg = package->GetName();
2532 spkg.ReplaceAll(".par", "");
2533 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2534 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2535 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2536 if (gROOT->ProcessLine(enablePackage)) {
2537 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2541 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2545 if (list) delete list;
2548 if (fAdditionalLibs.Contains(".so") && !testMode) {
2549 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2550 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2554 // Enable par files if requested
2555 if (fPackages && fPackages->GetEntries()) {
2556 TIter next(fPackages);
2558 while ((package=next())) {
2559 // Skip packages already enabled
2560 if (parLibs.Contains(package->GetName())) continue;
2561 TString spkg = package->GetName();
2562 spkg.ReplaceAll(".par", "");
2563 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2564 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2565 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2566 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2570 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2575 // Do we need to load analysis source files ?
2576 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2577 if (fAnalysisSource.Length()) {
2578 TObjArray *list = fAnalysisSource.Tokenize(" ");
2581 while((str=(TObjString*)next())) {
2582 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2584 if (list) delete list;
2587 // Register dataset to proof lite.
2588 if (fFileForTestMode.IsNull()) {
2589 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2592 if (gSystem->AccessPathName(fFileForTestMode)) {
2593 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2596 TFileCollection *coll = new TFileCollection();
2597 coll->AddFromFile(fFileForTestMode);
2598 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2599 gROOT->ProcessLine("gProof->ShowDataSets()");
2604 // Check if output files have to be taken from the analysis manager
2605 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2606 // Add output files and AOD files
2607 fOutputFiles = GetListOfFiles("outaod");
2608 // Add extra files registered to the analysis manager
2609 TString extra = GetListOfFiles("ext");
2610 if (!extra.IsNull()) {
2611 extra.ReplaceAll(".root", "*.root");
2612 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2613 fOutputFiles += extra;
2615 // Compose the output archive.
2616 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2617 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2619 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2620 if (TestBit(AliAnalysisGrid::kOffline)) {
2621 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2622 \n there nor any job run. You can revise the JDL and analysis \
2623 \n macro then run the same in \"submit\" mode.");
2624 } else if (TestBit(AliAnalysisGrid::kTest)) {
2625 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2627 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2628 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2629 \n space and job submitted.");
2630 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2631 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2632 if (fMergeViaJDL) CheckInputData();
2635 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2640 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2643 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2644 if (!CheckInputData()) {
2645 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2648 if (!CreateDataset(fDataPattern)) {
2650 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2651 if (fRunNumbers.Length()) serror = "run numbers";
2652 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2653 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2654 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2657 WriteAnalysisFile();
2658 WriteAnalysisMacro();
2660 WriteValidationScript();
2662 WriteMergingMacro();
2663 WriteMergeExecutable();
2664 WriteValidationScript(kTRUE);
2666 if (!CreateJDL()) return kFALSE;
2667 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2669 // Locally testing the analysis
2670 Info("StartAnalysis", "\n_______________________________________________________________________ \
2671 \n Running analysis script in a daughter shell as on a worker node \
2672 \n_______________________________________________________________________");
2673 TObjArray *list = fOutputFiles.Tokenize(",");
2677 while((str=(TObjString*)next())) {
2678 outputFile = str->GetString();
2679 Int_t index = outputFile.Index("@");
2680 if (index > 0) outputFile.Remove(index);
2681 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2684 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2685 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2686 // gSystem->Exec("cat stdout");
2689 // Check if submitting is managed by LPM manager
2690 if (fProductionMode) {
2691 TString prodfile = fJDLName;
2692 prodfile.ReplaceAll(".jdl", ".prod");
2693 WriteProductionFile(prodfile);
2694 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2697 // Submit AliEn job(s)
2698 gGrid->Cd(fGridOutputDir);
2701 if (!fRunNumbers.Length() && !fRunRange[0]) {
2702 // Submit a given xml or a set of runs
2703 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2704 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2706 const char *cjobId = res->GetKey(0,"jobId");
2710 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2713 Info("StartAnalysis", "\n_______________________________________________________________________ \
2714 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2715 \n_______________________________________________________________________",
2716 fJDLName.Data(), cjobId);
2721 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2725 // Submit for a range of enumeration of runs.
2726 if (!Submit()) return kFALSE;
2729 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2730 \n You may exit at any time and terminate the job later using the option <terminate> \
2731 \n ##################################################################################", jobID.Data());
2732 gSystem->Exec("aliensh");
2736 //______________________________________________________________________________
2737 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2739 // Get a comma-separated list of output files of the requested type.
2740 // Type can be (case unsensitive):
2741 // aod - list of aod files (std, extensions and filters)
2742 // out - list of output files connected to containers (but not aod's or extras)
2743 // ext - list of extra files registered to the manager
2744 // ter - list of files produced in terminate
2745 static TString files;
2747 TString stype = type;
2749 TString aodfiles, extra;
2750 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2752 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2753 return files.Data();
2755 if (mgr->GetOutputEventHandler()) {
2756 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2757 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2758 if (!extraaod.IsNull()) {
2760 aodfiles += extraaod;
2763 if (stype.Contains("aod")) {
2765 if (stype == "aod") return files.Data();
2767 // Add output files that are not in the list of AOD files
2768 TString outputfiles = "";
2769 TIter next(mgr->GetOutputs());
2770 AliAnalysisDataContainer *output;
2771 const char *filename = 0;
2772 while ((output=(AliAnalysisDataContainer*)next())) {
2773 filename = output->GetFileName();
2774 if (!(strcmp(filename, "default"))) continue;
2775 if (outputfiles.Contains(filename)) continue;
2776 if (aodfiles.Contains(filename)) continue;
2777 if (!outputfiles.IsNull()) outputfiles += ",";
2778 outputfiles += filename;
2780 if (stype.Contains("out")) {
2781 if (!files.IsNull()) files += ",";
2782 files += outputfiles;
2783 if (stype == "out") return files.Data();
2785 // Add extra files registered to the analysis manager
2787 extra = mgr->GetExtraFiles();
2788 if (!extra.IsNull()) {
2790 extra.ReplaceAll(" ", ",");
2791 TObjArray *fextra = extra.Tokenize(",");
2792 TIter nextx(fextra);
2794 while ((obj=nextx())) {
2795 if (aodfiles.Contains(obj->GetName())) continue;
2796 if (outputfiles.Contains(obj->GetName())) continue;
2797 if (sextra.Contains(obj->GetName())) continue;
2798 if (!sextra.IsNull()) sextra += ",";
2799 sextra += obj->GetName();
2802 if (stype.Contains("ext")) {
2803 if (!files.IsNull()) files += ",";
2807 if (stype == "ext") return files.Data();
2809 if (!fTerminateFiles.IsNull()) {
2810 fTerminateFiles.Strip();
2811 fTerminateFiles.ReplaceAll(" ",",");
2812 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2813 TIter nextx(fextra);
2815 while ((obj=nextx())) {
2816 if (aodfiles.Contains(obj->GetName())) continue;
2817 if (outputfiles.Contains(obj->GetName())) continue;
2818 if (termfiles.Contains(obj->GetName())) continue;
2819 if (sextra.Contains(obj->GetName())) continue;
2820 if (!termfiles.IsNull()) termfiles += ",";
2821 termfiles += obj->GetName();
2825 if (stype.Contains("ter")) {
2826 if (!files.IsNull() && !termfiles.IsNull()) {
2831 return files.Data();
2834 //______________________________________________________________________________
2835 Bool_t AliAnalysisAlien::Submit()
2837 // Submit all master jobs.
2838 Int_t nmasterjobs = fInputFiles->GetEntries();
2839 Long_t tshoot = gSystem->Now();
2840 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2841 while (fNsubmitted < nmasterjobs) {
2842 Long_t now = gSystem->Now();
2843 if ((now-tshoot)>30000) {
2845 if (!SubmitNext()) return kFALSE;
2851 //______________________________________________________________________________
2852 Bool_t AliAnalysisAlien::SubmitMerging()
2854 // Submit all merging jobs.
2855 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2856 gGrid->Cd(fGridOutputDir);
2857 TString mergeJDLName = fExecutable;
2858 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2860 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
2863 Int_t ntosubmit = fInputFiles->GetEntries();
2864 for (Int_t i=0; i<ntosubmit; i++) {
2865 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2866 runOutDir.ReplaceAll(".xml", "");
2867 if (fOutputToRunNo) {
2868 // The output directory is the run number
2869 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2870 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2872 if (!fRunNumbers.Length() && !fRunRange[0]) {
2873 // The output directory is the grid outdir
2874 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
2875 runOutDir = fGridOutputDir;
2877 // The output directory is the master number in 3 digits format
2878 printf("### Submitting merging job for master <%03d>\n", i);
2879 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2882 // Check now the number of merging stages.
2883 TObjArray *list = fOutputFiles.Tokenize(",");
2887 while((str=(TObjString*)next())) {
2888 outputFile = str->GetString();
2889 Int_t index = outputFile.Index("@");
2890 if (index > 0) outputFile.Remove(index);
2891 if (!fMergeExcludes.Contains(outputFile)) break;
2894 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2895 if (!done && (i==ntosubmit-1)) return kFALSE;
2896 if (!fRunNumbers.Length() && !fRunRange[0]) break;
2898 if (!ntosubmit) return kTRUE;
2899 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
2900 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
2901 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
2902 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
2903 \n ################################################################################################################");
2904 gSystem->Exec("aliensh");
2908 //______________________________________________________________________________
2909 Bool_t AliAnalysisAlien::SubmitNext()
2911 // Submit next bunch of master jobs if the queue is free. The first master job is
2912 // submitted right away, while the next will not be unless the previous was split.
2913 // The plugin will not submit new master jobs if there are more that 500 jobs in
2915 static Bool_t iscalled = kFALSE;
2916 static Int_t firstmaster = 0;
2917 static Int_t lastmaster = 0;
2918 static Int_t npermaster = 0;
2919 if (iscalled) return kTRUE;
2921 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2922 Int_t ntosubmit = 0;
2925 Int_t nmasterjobs = fInputFiles->GetEntries();
2928 if (!IsUseSubmitPolicy()) {
2930 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2931 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2932 ntosubmit = nmasterjobs;
2935 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2936 printf("=== master %d: %s\n", lastmaster, status.Data());
2937 // If last master not split, just return
2938 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2939 // No more than 100 waiting jobs
2940 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2941 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2942 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2943 if (!ntosubmit) ntosubmit = 1;
2944 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2945 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2947 for (Int_t i=0; i<ntosubmit; i++) {
2948 // Submit for a range of enumeration of runs.
2949 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2951 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2952 runOutDir.ReplaceAll(".xml", "");
2954 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2956 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2957 printf("********* %s\n",query.Data());
2958 res = gGrid->Command(query);
2960 TString cjobId1 = res->GetKey(0,"jobId");
2961 if (!cjobId1.Length()) {
2965 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2968 Info("StartAnalysis", "\n_______________________________________________________________________ \
2969 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2970 \n_______________________________________________________________________",
2971 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2974 lastmaster = cjobId1.Atoi();
2975 if (!firstmaster) firstmaster = lastmaster;
2980 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2988 //______________________________________________________________________________
2989 void AliAnalysisAlien::WriteAnalysisFile()
2991 // Write current analysis manager into the file <analysisFile>
2992 TString analysisFile = fExecutable;
2993 analysisFile.ReplaceAll(".sh", ".root");
2994 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2995 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2996 if (!mgr || !mgr->IsInitialized()) {
2997 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3000 // Check analysis type
3002 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3003 handler = (TObject*)mgr->GetInputEventHandler();
3005 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3006 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3007 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3008 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3010 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3011 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3014 TDirectory *cdir = gDirectory;
3015 TFile *file = TFile::Open(analysisFile, "RECREATE");
3017 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3018 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3019 // Unless merging makes no sense
3020 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3023 // Enable termination for local jobs
3024 mgr->SetSkipTerminate(kFALSE);
3026 if (cdir) cdir->cd();
3027 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3029 Bool_t copy = kTRUE;
3030 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3033 TString workdir = gGrid->GetHomeDirectory();
3034 workdir += fGridWorkingDir;
3035 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3036 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3037 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
3041 //______________________________________________________________________________
3042 void AliAnalysisAlien::WriteAnalysisMacro()
3044 // Write the analysis macro that will steer the analysis in grid mode.
3045 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3047 out.open(fAnalysisMacro.Data(), ios::out);
3049 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3052 Bool_t hasSTEERBase = kFALSE;
3053 Bool_t hasESD = kFALSE;
3054 Bool_t hasAOD = kFALSE;
3055 Bool_t hasANALYSIS = kFALSE;
3056 Bool_t hasOADB = kFALSE;
3057 Bool_t hasANALYSISalice = kFALSE;
3058 Bool_t hasCORRFW = kFALSE;
3059 TString func = fAnalysisMacro;
3060 TString type = "ESD";
3061 TString comment = "// Analysis using ";
3062 if (IsUseMCchain()) {
3066 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3067 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3072 if (type!="AOD" && fFriendChainName!="") {
3073 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3076 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3077 else comment += " data";
3078 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3079 func.ReplaceAll(".C", "");
3080 out << "void " << func.Data() << "()" << endl;
3082 out << comment.Data() << endl;
3083 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3084 out << " TStopwatch timer;" << endl;
3085 out << " timer.Start();" << endl << endl;
3086 // Change temp directory to current one
3087 out << "// Set temporary merging directory to current one" << endl;
3088 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3089 out << "// Set temporary compilation directory to current one" << endl;
3090 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3091 // Reset existing include path
3092 out << "// Reset existing include path and add current directory first in the search" << endl;
3093 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3094 if (!fExecutableCommand.Contains("aliroot")) {
3095 out << "// load base root libraries" << endl;
3096 out << " gSystem->Load(\"libTree\");" << endl;
3097 out << " gSystem->Load(\"libGeom\");" << endl;
3098 out << " gSystem->Load(\"libVMC\");" << endl;
3099 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3100 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3102 if (fAdditionalRootLibs.Length()) {
3103 // in principle libtree /lib geom libvmc etc. can go into this list, too
3104 out << "// Add aditional libraries" << endl;
3105 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3108 while((str=(TObjString*)next())) {
3109 if (str->GetString().Contains(".so"))
3110 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3112 if (list) delete list;
3114 out << "// Load analysis framework libraries" << endl;
3115 TString setupPar = "AliAnalysisAlien::SetupPar";
3117 if (!fExecutableCommand.Contains("aliroot")) {
3118 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3119 out << " gSystem->Load(\"libESD\");" << endl;
3120 out << " gSystem->Load(\"libAOD\");" << endl;
3122 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3123 out << " gSystem->Load(\"libOADB\");" << endl;
3124 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3125 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3127 TIter next(fPackages);
3130 while ((obj=next())) {
3131 pkgname = obj->GetName();
3132 if (pkgname == "STEERBase" ||
3133 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3134 if (pkgname == "ESD" ||
3135 pkgname == "ESD.par") hasESD = kTRUE;
3136 if (pkgname == "AOD" ||
3137 pkgname == "AOD.par") hasAOD = kTRUE;
3138 if (pkgname == "ANALYSIS" ||
3139 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3140 if (pkgname == "OADB" ||
3141 pkgname == "OADB.par") hasOADB = kTRUE;
3142 if (pkgname == "ANALYSISalice" ||
3143 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3144 if (pkgname == "CORRFW" ||
3145 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3147 if (hasANALYSISalice) setupPar = "SetupPar";
3148 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3149 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3150 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3151 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3152 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3153 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3154 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3155 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3156 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3157 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3158 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3159 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3160 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3161 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3162 out << "// Compile other par packages" << endl;
3164 while ((obj=next())) {
3165 pkgname = obj->GetName();
3166 if (pkgname == "STEERBase" ||
3167 pkgname == "STEERBase.par" ||
3169 pkgname == "ESD.par" ||
3171 pkgname == "AOD.par" ||
3172 pkgname == "ANALYSIS" ||
3173 pkgname == "ANALYSIS.par" ||
3174 pkgname == "OADB" ||
3175 pkgname == "OADB.par" ||
3176 pkgname == "ANALYSISalice" ||
3177 pkgname == "ANALYSISalice.par" ||
3178 pkgname == "CORRFW" ||
3179 pkgname == "CORRFW.par") continue;
3180 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3183 out << "// include path" << endl;
3184 // Get the include path from the interpreter and remove entries pointing to AliRoot
3185 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3186 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3187 out << " TIter nextpath(listpaths);" << endl;
3188 out << " TObjString *pname;" << endl;
3189 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3190 out << " TString current = pname->GetName();" << endl;
3191 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3192 out << " gSystem->AddIncludePath(current);" << endl;
3193 out << " }" << endl;
3194 out << " if (listpaths) delete listpaths;" << endl;
3195 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3196 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3197 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3198 if (fAdditionalLibs.Length()) {
3199 out << "// Add aditional AliRoot libraries" << endl;
3200 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3203 while((str=(TObjString*)next())) {
3204 if (str->GetString().Contains(".so"))
3205 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3206 if (str->GetString().Contains(".par"))
3207 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3209 if (list) delete list;
3212 out << "// analysis source to be compiled at runtime (if any)" << endl;
3213 if (fAnalysisSource.Length()) {
3214 TObjArray *list = fAnalysisSource.Tokenize(" ");
3217 while((str=(TObjString*)next())) {
3218 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3220 if (list) delete list;
3223 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3224 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3225 if (fFastReadOption) {
3226 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 !!! \
3227 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3228 out << "// fast xrootd reading enabled" << endl;
3229 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3230 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3231 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3232 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3233 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3234 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3236 out << "// connect to AliEn and make the chain" << endl;
3237 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3238 out << "// read the analysis manager from file" << endl;
3239 TString analysisFile = fExecutable;
3240 analysisFile.ReplaceAll(".sh", ".root");
3241 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3242 out << " if (!file) return;" << endl;
3243 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3244 out << " AliAnalysisManager *mgr = 0;" << endl;
3245 out << " TKey *key;" << endl;
3246 out << " while ((key=(TKey*)nextkey())) {" << endl;
3247 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3248 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3249 out << " };" << endl;
3250 out << " if (!mgr) {" << endl;
3251 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3252 out << " return;" << endl;
3253 out << " }" << endl << endl;
3254 out << " mgr->PrintStatus();" << endl;
3255 if (AliAnalysisManager::GetAnalysisManager()) {
3256 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3257 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3259 if (TestBit(AliAnalysisGrid::kTest))
3260 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3262 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3265 if (IsUsingTags()) {
3266 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3268 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3270 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3271 out << " timer.Stop();" << endl;
3272 out << " timer.Print();" << endl;
3273 out << "}" << endl << endl;
3274 if (IsUsingTags()) {
3275 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3277 out << "// Create a chain using tags from the xml file." << endl;
3278 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3279 out << " if (!coll) {" << endl;
3280 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3281 out << " return NULL;" << endl;
3282 out << " }" << endl;
3283 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3284 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3285 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3286 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3287 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3288 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3289 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3290 out << " // Check if the cuts configuration file was provided" << endl;
3291 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3292 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3293 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3294 out << " }" << endl;
3295 if (fFriendChainName=="") {
3296 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3298 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3299 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3300 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3302 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3303 out << " chain->ls();" << endl;
3304 out << " return chain;" << endl;
3305 out << "}" << endl << endl;
3306 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3307 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3308 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3309 msg += " AliLHCTagCuts *lhcCuts,\n";
3310 msg += " AliDetectorTagCuts *detCuts,\n";
3311 msg += " AliEventTagCuts *evCuts)";
3312 Info("WriteAnalysisMacro", "%s", msg.Data());
3315 if (!IsUsingTags() || fFriendChainName!="") {
3316 out <<"//________________________________________________________________________________" << endl;
3317 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3319 out << "// Create a chain using url's from xml file" << endl;
3320 out << " TString filename;" << endl;
3321 out << " Int_t run = 0;" << endl;
3322 if (IsUseMCchain()) {
3323 out << " TString treename = \"TE\";" << endl;
3325 out << " TString treename = type;" << endl;
3326 out << " treename.ToLower();" << endl;
3327 out << " treename += \"Tree\";" << endl;
3329 out << " printf(\"***************************************\\n\");" << endl;
3330 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3331 out << " printf(\"***************************************\\n\");" << endl;
3332 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3333 out << " if (!coll) {" << endl;
3334 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3335 out << " return NULL;" << endl;
3336 out << " }" << endl;
3337 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3338 out << " TChain *chain = new TChain(treename);" << endl;
3339 if(fFriendChainName!="") {
3340 out << " TChain *chainFriend = new TChain(treename);" << endl;
3342 out << " coll->Reset();" << endl;
3343 out << " while (coll->Next()) {" << endl;
3344 out << " filename = coll->GetTURL("");" << endl;
3345 out << " if (mgr) {" << endl;
3346 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3347 out << " if (nrun && nrun != run) {" << endl;
3348 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3349 out << " mgr->SetRunFromPath(nrun);" << endl;
3350 out << " run = nrun;" << endl;
3351 out << " }" << endl;
3352 out << " }" << endl;
3353 out << " chain->Add(filename);" << endl;
3354 if(fFriendChainName!="") {
3355 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3356 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3357 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3358 out << " chainFriend->Add(fileFriend.Data());" << endl;
3360 out << " }" << endl;
3361 out << " if (!chain->GetNtrees()) {" << endl;
3362 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3363 out << " return NULL;" << endl;
3364 out << " }" << endl;
3365 if(fFriendChainName!="") {
3366 out << " chain->AddFriend(chainFriend);" << endl;
3368 out << " return chain;" << endl;
3369 out << "}" << endl << endl;
3371 if (hasANALYSISalice) {
3372 out <<"//________________________________________________________________________________" << endl;
3373 out << "Bool_t SetupPar(const char *package) {" << endl;
3374 out << "// Compile the package and set it up." << endl;
3375 out << " TString pkgdir = package;" << endl;
3376 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3377 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3378 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3379 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3380 out << " // Check for BUILD.sh and execute" << endl;
3381 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3382 out << " printf(\"*******************************\\n\");" << endl;
3383 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3384 out << " printf(\"*******************************\\n\");" << endl;
3385 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3386 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3387 out << " gSystem->ChangeDirectory(cdir);" << endl;
3388 out << " return kFALSE;" << endl;
3389 out << " }" << endl;
3390 out << " } else {" << endl;
3391 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3392 out << " gSystem->ChangeDirectory(cdir);" << endl;
3393 out << " return kFALSE;" << endl;
3394 out << " }" << endl;
3395 out << " // Check for SETUP.C and execute" << endl;
3396 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3397 out << " printf(\"*******************************\\n\");" << endl;
3398 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3399 out << " printf(\"*******************************\\n\");" << endl;
3400 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3401 out << " } else {" << endl;
3402 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3403 out << " gSystem->ChangeDirectory(cdir);" << endl;
3404 out << " return kFALSE;" << endl;
3405 out << " }" << endl;
3406 out << " // Restore original workdir" << endl;
3407 out << " gSystem->ChangeDirectory(cdir);" << endl;
3408 out << " return kTRUE;" << endl;
3411 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3413 Bool_t copy = kTRUE;
3414 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3417 TString workdir = gGrid->GetHomeDirectory();
3418 workdir += fGridWorkingDir;
3419 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3420 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3421 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3422 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3423 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3425 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3426 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3430 //______________________________________________________________________________
3431 void AliAnalysisAlien::WriteMergingMacro()
3433 // Write a macro to merge the outputs per master job.
3434 if (!fMergeViaJDL) return;
3435 if (!fOutputFiles.Length()) {
3436 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3439 TString mergingMacro = fExecutable;
3440 mergingMacro.ReplaceAll(".sh","_merge.C");
3441 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3442 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3444 out.open(mergingMacro.Data(), ios::out);
3446 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3449 Bool_t hasSTEERBase = kFALSE;
3450 Bool_t hasESD = kFALSE;
3451 Bool_t hasAOD = kFALSE;
3452 Bool_t hasANALYSIS = kFALSE;
3453 Bool_t hasOADB = kFALSE;
3454 Bool_t hasANALYSISalice = kFALSE;
3455 Bool_t hasCORRFW = kFALSE;
3456 TString func = mergingMacro;
3458 func.ReplaceAll(".C", "");
3459 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3461 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3462 out << " TStopwatch timer;" << endl;
3463 out << " timer.Start();" << endl << endl;
3464 // Reset existing include path
3465 out << "// Reset existing include path and add current directory first in the search" << endl;
3466 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3467 if (!fExecutableCommand.Contains("aliroot")) {
3468 out << "// load base root libraries" << endl;
3469 out << " gSystem->Load(\"libTree\");" << endl;
3470 out << " gSystem->Load(\"libGeom\");" << endl;
3471 out << " gSystem->Load(\"libVMC\");" << endl;
3472 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3473 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3475 if (fAdditionalRootLibs.Length()) {
3476 // in principle libtree /lib geom libvmc etc. can go into this list, too
3477 out << "// Add aditional libraries" << endl;
3478 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3481 while((str=(TObjString*)next())) {
3482 if (str->GetString().Contains(".so"))
3483 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3485 if (list) delete list;
3487 out << "// Load analysis framework libraries" << endl;
3489 if (!fExecutableCommand.Contains("aliroot")) {
3490 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3491 out << " gSystem->Load(\"libESD\");" << endl;
3492 out << " gSystem->Load(\"libAOD\");" << endl;
3494 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3495 out << " gSystem->Load(\"libOADB\");" << endl;
3496 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3497 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3499 TIter next(fPackages);
3502 TString setupPar = "AliAnalysisAlien::SetupPar";
3503 while ((obj=next())) {
3504 pkgname = obj->GetName();
3505 if (pkgname == "STEERBase" ||
3506 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3507 if (pkgname == "ESD" ||
3508 pkgname == "ESD.par") hasESD = kTRUE;
3509 if (pkgname == "AOD" ||
3510 pkgname == "AOD.par") hasAOD = kTRUE;
3511 if (pkgname == "ANALYSIS" ||
3512 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3513 if (pkgname == "OADB" ||
3514 pkgname == "OADB.par") hasOADB = kTRUE;
3515 if (pkgname == "ANALYSISalice" ||
3516 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3517 if (pkgname == "CORRFW" ||
3518 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3520 if (hasANALYSISalice) setupPar = "SetupPar";
3521 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3522 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3523 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3524 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3525 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3526 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3527 out << " gSystem->Load(\"libOADB\");" << endl;
3528 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3529 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3530 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3531 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3532 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3533 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3534 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3535 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3536 out << "// Compile other par packages" << endl;
3538 while ((obj=next())) {
3539 pkgname = obj->GetName();
3540 if (pkgname == "STEERBase" ||
3541 pkgname == "STEERBase.par" ||
3543 pkgname == "ESD.par" ||
3545 pkgname == "AOD.par" ||
3546 pkgname == "ANALYSIS" ||
3547 pkgname == "ANALYSIS.par" ||
3548 pkgname == "OADB" ||
3549 pkgname == "OADB.par" ||
3550 pkgname == "ANALYSISalice" ||
3551 pkgname == "ANALYSISalice.par" ||
3552 pkgname == "CORRFW" ||
3553 pkgname == "CORRFW.par") continue;
3554 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3557 out << "// include path" << endl;
3558 // Get the include path from the interpreter and remove entries pointing to AliRoot
3559 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3560 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3561 out << " TIter nextpath(listpaths);" << endl;
3562 out << " TObjString *pname;" << endl;
3563 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3564 out << " TString current = pname->GetName();" << endl;
3565 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3566 out << " gSystem->AddIncludePath(current);" << endl;
3567 out << " }" << endl;
3568 out << " if (listpaths) delete listpaths;" << endl;
3569 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3570 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3571 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3572 if (fAdditionalLibs.Length()) {
3573 out << "// Add aditional AliRoot libraries" << endl;
3574 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3577 while((str=(TObjString*)next())) {
3578 if (str->GetString().Contains(".so"))
3579 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3581 if (list) delete list;
3584 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3585 if (fAnalysisSource.Length()) {
3586 TObjArray *list = fAnalysisSource.Tokenize(" ");
3589 while((str=(TObjString*)next())) {
3590 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3592 if (list) delete list;
3596 if (fFastReadOption) {
3597 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 !!!");
3598 out << "// fast xrootd reading enabled" << endl;
3599 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3600 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3601 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3602 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3603 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3604 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3606 // Change temp directory to current one
3607 out << "// Set temporary merging directory to current one" << endl;
3608 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3609 out << "// Set temporary compilation directory to current one" << endl;
3610 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3611 out << "// Connect to AliEn" << endl;
3612 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3613 out << " TString outputDir = dir;" << endl;
3614 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3615 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3616 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3617 out << " TIter *iter = new TIter(list);" << endl;
3618 out << " TObjString *str;" << endl;
3619 out << " TString outputFile;" << endl;
3620 out << " Bool_t merged = kTRUE;" << endl;
3621 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3622 out << " outputFile = str->GetString();" << endl;
3623 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3624 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3625 out << " if (index > 0) outputFile.Remove(index);" << endl;
3626 out << " // Skip already merged outputs" << endl;
3627 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3628 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3629 out << " continue;" << endl;
3630 out << " }" << endl;
3631 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3632 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3633 out << " if (!merged) {" << endl;
3634 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3635 out << " return;" << endl;
3636 out << " }" << endl;
3637 out << " }" << endl;
3638 out << " // all outputs merged, validate" << endl;
3639 out << " ofstream out;" << endl;
3640 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3641 out << " out.close();" << endl;
3642 out << " // read the analysis manager from file" << endl;
3643 TString analysisFile = fExecutable;
3644 analysisFile.ReplaceAll(".sh", ".root");
3645 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3646 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3647 out << " if (!file) return;" << endl;
3648 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3649 out << " AliAnalysisManager *mgr = 0;" << endl;
3650 out << " TKey *key;" << endl;
3651 out << " while ((key=(TKey*)nextkey())) {" << endl;
3652 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3653 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3654 out << " };" << endl;
3655 out << " if (!mgr) {" << endl;
3656 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3657 out << " return;" << endl;
3658 out << " }" << endl << endl;
3659 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3660 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3661 out << " mgr->PrintStatus();" << endl;
3662 if (AliAnalysisManager::GetAnalysisManager()) {
3663 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3664 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3666 if (TestBit(AliAnalysisGrid::kTest))
3667 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3669 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3672 out << " TTree *tree = NULL;" << endl;
3673 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3674 out << "}" << endl << endl;
3675 if (hasANALYSISalice) {
3676 out <<"//________________________________________________________________________________" << endl;
3677 out << "Bool_t SetupPar(const char *package) {" << endl;
3678 out << "// Compile the package and set it up." << endl;
3679 out << " TString pkgdir = package;" << endl;
3680 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3681 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3682 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3683 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3684 out << " // Check for BUILD.sh and execute" << endl;
3685 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3686 out << " printf(\"*******************************\\n\");" << endl;
3687 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3688 out << " printf(\"*******************************\\n\");" << endl;
3689 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3690 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3691 out << " gSystem->ChangeDirectory(cdir);" << endl;
3692 out << " return kFALSE;" << endl;
3693 out << " }" << endl;
3694 out << " } else {" << endl;
3695 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3696 out << " gSystem->ChangeDirectory(cdir);" << endl;
3697 out << " return kFALSE;" << endl;
3698 out << " }" << endl;
3699 out << " // Check for SETUP.C and execute" << endl;
3700 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3701 out << " printf(\"*******************************\\n\");" << endl;
3702 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3703 out << " printf(\"*******************************\\n\");" << endl;
3704 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3705 out << " } else {" << endl;
3706 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3707 out << " gSystem->ChangeDirectory(cdir);" << endl;
3708 out << " return kFALSE;" << endl;
3709 out << " }" << endl;
3710 out << " // Restore original workdir" << endl;
3711 out << " gSystem->ChangeDirectory(cdir);" << endl;
3712 out << " return kTRUE;" << endl;
3716 Bool_t copy = kTRUE;
3717 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3720 TString workdir = gGrid->GetHomeDirectory();
3721 workdir += fGridWorkingDir;
3722 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3723 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3724 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3728 //______________________________________________________________________________
3729 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3731 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3732 // Note that for loading the compiled library. The current directory should have precedence in
3734 TString pkgdir = package;
3735 pkgdir.ReplaceAll(".par","");
3736 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3737 TString cdir = gSystem->WorkingDirectory();
3738 gSystem->ChangeDirectory(pkgdir);
3739 // Check for BUILD.sh and execute
3740 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3741 printf("**************************************************\n");
3742 printf("*** Building PAR archive %s\n", package);
3743 printf("**************************************************\n");
3744 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3745 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3746 gSystem->ChangeDirectory(cdir);
3750 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3751 gSystem->ChangeDirectory(cdir);
3754 // Check for SETUP.C and execute
3755 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3756 printf("**************************************************\n");
3757 printf("*** Setup PAR archive %s\n", package);
3758 printf("**************************************************\n");
3759 gROOT->Macro("PROOF-INF/SETUP.C");
3760 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3762 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3763 gSystem->ChangeDirectory(cdir);
3766 // Restore original workdir
3767 gSystem->ChangeDirectory(cdir);
3771 //______________________________________________________________________________
3772 void AliAnalysisAlien::WriteExecutable()
3774 // Generate the alien executable script.
3775 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3777 out.open(fExecutable.Data(), ios::out);
3779 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3782 out << "#!/bin/bash" << endl;
3783 // Make sure we can properly compile par files
3784 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3785 out << "echo \"=========================================\"" << endl;
3786 out << "echo \"############## PATH : ##############\"" << endl;
3787 out << "echo $PATH" << endl;
3788 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3789 out << "echo $LD_LIBRARY_PATH" << endl;
3790 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3791 out << "echo $ROOTSYS" << endl;
3792 out << "echo \"############## which root : ##############\"" << endl;
3793 out << "which root" << endl;
3794 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3795 out << "echo $ALICE_ROOT" << endl;
3796 out << "echo \"############## which aliroot : ##############\"" << endl;
3797 out << "which aliroot" << endl;
3798 out << "echo \"############## system limits : ##############\"" << endl;
3799 out << "ulimit -a" << endl;
3800 out << "echo \"############## memory : ##############\"" << endl;
3801 out << "free -m" << endl;
3802 out << "echo \"=========================================\"" << endl << endl;
3803 out << fExecutableCommand << " ";
3804 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3805 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3806 out << "echo \"############## memory after: ##############\"" << endl;
3807 out << "free -m" << endl;
3809 Bool_t copy = kTRUE;
3810 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3813 TString workdir = gGrid->GetHomeDirectory();
3814 TString bindir = Form("%s/bin", workdir.Data());
3815 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3816 workdir += fGridWorkingDir;
3817 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3818 if (FileExists(executable)) gGrid->Rm(executable);
3819 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3820 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3824 //______________________________________________________________________________
3825 void AliAnalysisAlien::WriteMergeExecutable()
3827 // Generate the alien executable script for the merging job.
3828 if (!fMergeViaJDL) return;
3829 TString mergeExec = fExecutable;
3830 mergeExec.ReplaceAll(".sh", "_merge.sh");
3831 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3833 out.open(mergeExec.Data(), ios::out);
3835 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3838 out << "#!/bin/bash" << endl;
3839 // Make sure we can properly compile par files
3840 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3841 out << "echo \"=========================================\"" << endl;
3842 out << "echo \"############## PATH : ##############\"" << endl;
3843 out << "echo $PATH" << endl;
3844 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3845 out << "echo $LD_LIBRARY_PATH" << endl;
3846 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3847 out << "echo $ROOTSYS" << endl;
3848 out << "echo \"############## which root : ##############\"" << endl;
3849 out << "which root" << endl;
3850 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3851 out << "echo $ALICE_ROOT" << endl;
3852 out << "echo \"############## which aliroot : ##############\"" << endl;
3853 out << "which aliroot" << endl;
3854 out << "echo \"############## system limits : ##############\"" << endl;
3855 out << "ulimit -a" << endl;
3856 out << "echo \"############## memory : ##############\"" << endl;
3857 out << "free -m" << endl;
3858 out << "echo \"=========================================\"" << endl << endl;
3859 TString mergeMacro = fExecutable;
3860 mergeMacro.ReplaceAll(".sh", "_merge.C");
3861 if (IsOneStageMerging())
3862 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3864 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3865 out << fExecutableCommand << " " << "$ARG" << endl;
3866 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3867 out << "echo \"############## memory after: ##############\"" << endl;
3868 out << "free -m" << endl;
3870 Bool_t copy = kTRUE;
3871 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3874 TString workdir = gGrid->GetHomeDirectory();
3875 TString bindir = Form("%s/bin", workdir.Data());
3876 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3877 workdir += fGridWorkingDir;
3878 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3879 if (FileExists(executable)) gGrid->Rm(executable);
3880 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3881 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3885 //______________________________________________________________________________
3886 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3888 // Write the production file to be submitted by LPM manager. The format is:
3889 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3890 // Next lines: full_path_to_dataset XXX (XXX is a string)
3891 // To submit, one has to: submit jdl XXX for all lines
3893 out.open(filename, ios::out);
3895 Error("WriteProductionFile", "Bad file name: %s", filename);
3899 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3900 workdir = gGrid->GetHomeDirectory();
3901 workdir += fGridWorkingDir;
3902 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3903 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3904 out << locjdl << " " << njobspermaster << endl;
3905 Int_t nmasterjobs = fInputFiles->GetEntries();
3906 for (Int_t i=0; i<nmasterjobs; i++) {
3907 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3908 runOutDir.ReplaceAll(".xml", "");
3910 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3912 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3915 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3916 if (FileExists(filename)) gGrid->Rm(filename);
3917 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3921 //______________________________________________________________________________
3922 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3924 // Generate the alien validation script.
3925 // Generate the validation script
3927 if (fValidationScript.IsNull()) {
3928 fValidationScript = fExecutable;
3929 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3931 TString validationScript = fValidationScript;
3932 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3934 Error("WriteValidationScript", "Alien connection required");
3937 if (!fTerminateFiles.IsNull()) {
3938 fTerminateFiles.Strip();
3939 fTerminateFiles.ReplaceAll(" ",",");
3941 TString outStream = "";
3942 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3943 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3945 out.open(validationScript, ios::out);
3946 out << "#!/bin/bash" << endl;
3947 out << "##################################################" << endl;
3948 out << "validateout=`dirname $0`" << endl;
3949 out << "validatetime=`date`" << endl;
3950 out << "validated=\"0\";" << endl;
3951 out << "error=0" << endl;
3952 out << "if [ -z $validateout ]" << endl;
3953 out << "then" << endl;
3954 out << " validateout=\".\"" << endl;
3955 out << "fi" << endl << endl;
3956 out << "cd $validateout;" << endl;
3957 out << "validateworkdir=`pwd`;" << endl << endl;
3958 out << "echo \"*******************************************************\"" << outStream << endl;
3959 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3961 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3962 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3963 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3964 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3965 out << "ls -la ./" << outStream << endl;
3966 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3967 out << "##################################################" << endl;
3970 out << "if [ ! -f stderr ] ; then" << endl;
3971 out << " error=1" << endl;
3972 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3973 out << " echo \"Error = $error\" " << outStream << endl;
3974 out << "fi" << endl;
3976 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3977 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3978 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3979 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3982 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3983 out << " error=1" << endl;
3984 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3985 out << " echo \"$parArch\" " << outStream << endl;
3986 out << " echo \"Error = $error\" " << outStream << endl;
3987 out << "fi" << endl;
3989 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3990 out << " error=1" << endl;
3991 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3992 out << " echo \"$segViol\" " << outStream << endl;
3993 out << " echo \"Error = $error\" " << outStream << endl;
3994 out << "fi" << endl;
3996 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3997 out << " error=1" << endl;
3998 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3999 out << " echo \"$segFault\" " << outStream << endl;
4000 out << " echo \"Error = $error\" " << outStream << endl;
4001 out << "fi" << endl;
4003 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4004 out << " error=1" << endl;
4005 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4006 out << " echo \"$glibcErr\" " << outStream << endl;
4007 out << " echo \"Error = $error\" " << outStream << endl;
4008 out << "fi" << endl;
4010 // Part dedicated to the specific analyses running into the train
4012 TString outputFiles = fOutputFiles;
4013 if (merge && !fTerminateFiles.IsNull()) {
4015 outputFiles += fTerminateFiles;
4017 TObjArray *arr = outputFiles.Tokenize(",");
4020 while (!merge && (os=(TObjString*)next1())) {
4021 // No need to validate outputs produced by merging since the merging macro does this
4022 outputFile = os->GetString();
4023 Int_t index = outputFile.Index("@");
4024 if (index > 0) outputFile.Remove(index);
4025 if (fTerminateFiles.Contains(outputFile)) continue;
4026 if (outputFile.Contains("*")) continue;
4027 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4028 out << " error=1" << endl;
4029 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4030 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4031 out << "fi" << endl;
4034 out << "if ! [ -f outputs_valid ] ; then" << endl;
4035 out << " error=1" << endl;
4036 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4037 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4038 out << "fi" << endl;
4040 out << "if [ $error = 0 ] ; then" << endl;
4041 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4042 if (!IsKeepLogs()) {
4043 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4045 out << " rm -f std*" << endl;
4047 out << "fi" << endl;
4049 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4050 out << "echo \"*******************************************************\"" << outStream << endl;
4051 out << "cd -" << endl;
4052 out << "exit $error" << endl;
4054 Bool_t copy = kTRUE;
4055 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4058 TString workdir = gGrid->GetHomeDirectory();
4059 workdir += fGridWorkingDir;
4060 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4061 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4062 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));