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(),
121 //______________________________________________________________________________
122 AliAnalysisAlien::AliAnalysisAlien(const char *name)
123 :AliAnalysisGrid(name),
128 fSplitMaxInputFileNumber(0),
130 fMasterResubmitThreshold(0),
143 fNproofWorkersPerSlave(0),
147 fExecutableCommand(),
153 fAdditionalRootLibs(),
181 fRootVersionForProof(),
192 //______________________________________________________________________________
193 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
194 :AliAnalysisGrid(other),
197 fPrice(other.fPrice),
199 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
200 fMaxInitFailed(other.fMaxInitFailed),
201 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
202 fNtestFiles(other.fNtestFiles),
203 fNrunsPerMaster(other.fNrunsPerMaster),
204 fMaxMergeFiles(other.fMaxMergeFiles),
205 fMaxMergeStages(other.fMaxMergeStages),
206 fNsubmitted(other.fNsubmitted),
207 fProductionMode(other.fProductionMode),
208 fOutputToRunNo(other.fOutputToRunNo),
209 fMergeViaJDL(other.fMergeViaJDL),
210 fFastReadOption(other.fFastReadOption),
211 fOverwriteMode(other.fOverwriteMode),
212 fNreplicas(other.fNreplicas),
213 fNproofWorkers(other.fNproofWorkers),
214 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
215 fProofReset(other.fProofReset),
216 fRunNumbers(other.fRunNumbers),
217 fExecutable(other.fExecutable),
218 fExecutableCommand(other.fExecutableCommand),
219 fArguments(other.fArguments),
220 fExecutableArgs(other.fExecutableArgs),
221 fAnalysisMacro(other.fAnalysisMacro),
222 fAnalysisSource(other.fAnalysisSource),
223 fValidationScript(other.fValidationScript),
224 fAdditionalRootLibs(other.fAdditionalRootLibs),
225 fAdditionalLibs(other.fAdditionalLibs),
226 fSplitMode(other.fSplitMode),
227 fAPIVersion(other.fAPIVersion),
228 fROOTVersion(other.fROOTVersion),
229 fAliROOTVersion(other.fAliROOTVersion),
230 fExternalPackages(other.fExternalPackages),
232 fGridWorkingDir(other.fGridWorkingDir),
233 fGridDataDir(other.fGridDataDir),
234 fDataPattern(other.fDataPattern),
235 fGridOutputDir(other.fGridOutputDir),
236 fOutputArchive(other.fOutputArchive),
237 fOutputFiles(other.fOutputFiles),
238 fInputFormat(other.fInputFormat),
239 fDatasetName(other.fDatasetName),
240 fJDLName(other.fJDLName),
241 fTerminateFiles(other.fTerminateFiles),
242 fMergeExcludes(other.fMergeExcludes),
243 fIncludePath(other.fIncludePath),
244 fCloseSE(other.fCloseSE),
245 fFriendChainName(other.fFriendChainName),
246 fJobTag(other.fJobTag),
247 fOutputSingle(other.fOutputSingle),
248 fRunPrefix(other.fRunPrefix),
249 fProofCluster(other.fProofCluster),
250 fProofDataSet(other.fProofDataSet),
251 fFileForTestMode(other.fFileForTestMode),
252 fRootVersionForProof(other.fRootVersionForProof),
253 fAliRootMode(other.fAliRootMode),
254 fMergeDirName(other.fMergeDirName),
260 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
261 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
262 fRunRange[0] = other.fRunRange[0];
263 fRunRange[1] = other.fRunRange[1];
264 if (other.fInputFiles) {
265 fInputFiles = new TObjArray();
266 TIter next(other.fInputFiles);
268 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
269 fInputFiles->SetOwner();
271 if (other.fPackages) {
272 fPackages = new TObjArray();
273 TIter next(other.fPackages);
275 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
276 fPackages->SetOwner();
280 //______________________________________________________________________________
281 AliAnalysisAlien::~AliAnalysisAlien()
284 if (fGridJDL) delete fGridJDL;
285 if (fMergingJDL) delete fMergingJDL;
286 if (fInputFiles) delete fInputFiles;
287 if (fPackages) delete fPackages;
288 fProofParam.DeleteAll();
291 //______________________________________________________________________________
292 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
295 if (this != &other) {
296 AliAnalysisGrid::operator=(other);
297 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
298 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
299 fPrice = other.fPrice;
301 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
302 fMaxInitFailed = other.fMaxInitFailed;
303 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
304 fNtestFiles = other.fNtestFiles;
305 fNrunsPerMaster = other.fNrunsPerMaster;
306 fMaxMergeFiles = other.fMaxMergeFiles;
307 fMaxMergeStages = other.fMaxMergeStages;
308 fNsubmitted = other.fNsubmitted;
309 fProductionMode = other.fProductionMode;
310 fOutputToRunNo = other.fOutputToRunNo;
311 fMergeViaJDL = other.fMergeViaJDL;
312 fFastReadOption = other.fFastReadOption;
313 fOverwriteMode = other.fOverwriteMode;
314 fNreplicas = other.fNreplicas;
315 fNproofWorkers = other.fNproofWorkers;
316 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
317 fProofReset = other.fProofReset;
318 fRunNumbers = other.fRunNumbers;
319 fExecutable = other.fExecutable;
320 fExecutableCommand = other.fExecutableCommand;
321 fArguments = other.fArguments;
322 fExecutableArgs = other.fExecutableArgs;
323 fAnalysisMacro = other.fAnalysisMacro;
324 fAnalysisSource = other.fAnalysisSource;
325 fValidationScript = other.fValidationScript;
326 fAdditionalRootLibs = other.fAdditionalRootLibs;
327 fAdditionalLibs = other.fAdditionalLibs;
328 fSplitMode = other.fSplitMode;
329 fAPIVersion = other.fAPIVersion;
330 fROOTVersion = other.fROOTVersion;
331 fAliROOTVersion = other.fAliROOTVersion;
332 fExternalPackages = other.fExternalPackages;
334 fGridWorkingDir = other.fGridWorkingDir;
335 fGridDataDir = other.fGridDataDir;
336 fDataPattern = other.fDataPattern;
337 fGridOutputDir = other.fGridOutputDir;
338 fOutputArchive = other.fOutputArchive;
339 fOutputFiles = other.fOutputFiles;
340 fInputFormat = other.fInputFormat;
341 fDatasetName = other.fDatasetName;
342 fJDLName = other.fJDLName;
343 fTerminateFiles = other.fTerminateFiles;
344 fMergeExcludes = other.fMergeExcludes;
345 fIncludePath = other.fIncludePath;
346 fCloseSE = other.fCloseSE;
347 fFriendChainName = other.fFriendChainName;
348 fJobTag = other.fJobTag;
349 fOutputSingle = other.fOutputSingle;
350 fRunPrefix = other.fRunPrefix;
351 fProofCluster = other.fProofCluster;
352 fProofDataSet = other.fProofDataSet;
353 fFileForTestMode = other.fFileForTestMode;
354 fRootVersionForProof = other.fRootVersionForProof;
355 fAliRootMode = other.fAliRootMode;
356 fMergeDirName = other.fMergeDirName;
357 if (other.fInputFiles) {
358 fInputFiles = new TObjArray();
359 TIter next(other.fInputFiles);
361 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
362 fInputFiles->SetOwner();
364 if (other.fPackages) {
365 fPackages = new TObjArray();
366 TIter next(other.fPackages);
368 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
369 fPackages->SetOwner();
375 //______________________________________________________________________________
376 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
378 // Set the run number format. Can be a prefix or a format like "%09d"
380 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
383 //______________________________________________________________________________
384 void AliAnalysisAlien::AddIncludePath(const char *path)
386 // Add include path in the remote analysis macro.
388 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
389 else fIncludePath += Form("-I%s ", path);
392 //______________________________________________________________________________
393 void AliAnalysisAlien::AddRunNumber(Int_t run)
395 // Add a run number to the list of runs to be processed.
396 if (fRunNumbers.Length()) fRunNumbers += " ";
397 fRunNumbers += Form(fRunPrefix.Data(), run);
400 //______________________________________________________________________________
401 void AliAnalysisAlien::AddRunList(const char* runList)
403 // Add several runs into the list of runs; they are expected to be separated by a blank character.
404 TString sList = runList;
405 TObjArray *list = sList.Tokenize(" ");
406 Int_t n = list->GetEntries();
407 for (Int_t i = 0; i < n; i++) {
408 TObjString *os = (TObjString*)list->At(i);
409 AddRunNumber(os->GetString().Atoi());
414 //______________________________________________________________________________
415 void AliAnalysisAlien::AddRunNumber(const char* run)
417 // Add a run number to the list of runs to be processed.
420 TObjArray *arr = runs.Tokenize(" ");
423 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
424 while ((os=(TObjString*)next())){
425 if (fRunNumbers.Length()) fRunNumbers += " ";
426 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
431 //______________________________________________________________________________
432 void AliAnalysisAlien::AddDataFile(const char *lfn)
434 // Adds a data file to the input to be analysed. The file should be a valid LFN
435 // or point to an existing file in the alien workdir.
436 if (!fInputFiles) fInputFiles = new TObjArray();
437 fInputFiles->Add(new TObjString(lfn));
440 //______________________________________________________________________________
441 void AliAnalysisAlien::AddExternalPackage(const char *package)
443 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
444 if (fExternalPackages) fExternalPackages += " ";
445 fExternalPackages += package;
448 //______________________________________________________________________________
449 Bool_t AliAnalysisAlien::Connect()
451 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
452 if (gGrid && gGrid->IsConnected()) return kTRUE;
453 if (fProductionMode) return kTRUE;
455 Info("Connect", "Trying to connect to AliEn ...");
456 TGrid::Connect("alien://");
458 if (!gGrid || !gGrid->IsConnected()) {
459 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
462 fUser = gGrid->GetUser();
463 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
467 //______________________________________________________________________________
468 void AliAnalysisAlien::CdWork()
470 // Check validity of alien workspace. Create directory if possible.
472 Error("CdWork", "Alien connection required");
475 TString homedir = gGrid->GetHomeDirectory();
476 TString workdir = homedir + fGridWorkingDir;
477 if (DirectoryExists(workdir)) {
481 // Work directory not existing - create it
483 if (gGrid->Mkdir(workdir, "-p")) {
484 gGrid->Cd(fGridWorkingDir);
485 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
487 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
488 workdir.Data(), homedir.Data());
489 fGridWorkingDir = "";
493 //______________________________________________________________________________
494 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
496 // Check if file copying is possible.
497 if (fProductionMode) return kTRUE;
499 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
502 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
503 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
504 // Check if alien_CLOSE_SE is defined
505 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
506 if (!closeSE.IsNull()) {
507 Info("CheckFileCopy", "Your current close storage is pointing to: \
508 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
510 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
512 // Check if grid directory exists.
513 if (!DirectoryExists(alienpath)) {
514 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
517 TFile f("plugin_test_copy", "RECREATE");
518 // User may not have write permissions to current directory
520 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
521 gSystem->WorkingDirectory());
525 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
526 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
527 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
528 \n# 1. Make sure you have write permissions there. If this is the case: \
529 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
530 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
531 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
532 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
533 gSystem->Unlink(f.GetName());
536 gSystem->Unlink(f.GetName());
537 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
538 Info("CheckFileCopy", "### ...SUCCESS ###");
542 //______________________________________________________________________________
543 Bool_t AliAnalysisAlien::CheckInputData()
545 // Check validity of input data. If necessary, create xml files.
546 if (fProductionMode) return kTRUE;
547 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
548 if (!fGridDataDir.Length()) {
549 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
553 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
556 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
557 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
558 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
561 // Process declared files
562 Bool_t isCollection = kFALSE;
563 Bool_t isXml = kFALSE;
564 Bool_t useTags = kFALSE;
565 Bool_t checked = kFALSE;
566 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
568 TString workdir = gGrid->GetHomeDirectory();
569 workdir += fGridWorkingDir;
572 TIter next(fInputFiles);
573 while ((objstr=(TObjString*)next())) {
576 file += objstr->GetString();
577 // Store full lfn path
578 if (FileExists(file)) objstr->SetString(file);
580 file = objstr->GetName();
581 if (!FileExists(objstr->GetName())) {
582 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
583 objstr->GetName(), workdir.Data());
587 Bool_t iscoll, isxml, usetags;
588 CheckDataType(file, iscoll, isxml, usetags);
591 isCollection = iscoll;
594 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
596 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
597 Error("CheckInputData", "Some conflict was found in the types of inputs");
603 // Process requested run numbers
604 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
605 // Check validity of alien data directory
606 if (!fGridDataDir.Length()) {
607 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
610 if (!DirectoryExists(fGridDataDir)) {
611 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
615 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
619 if (checked && !isXml) {
620 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
623 // Check validity of run number(s)
628 TString schunk, schunk2;
632 useTags = fDataPattern.Contains("tag");
633 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
635 if (useTags != fDataPattern.Contains("tag")) {
636 Error("CheckInputData", "Cannot mix input files using/not using tags");
639 if (fRunNumbers.Length()) {
640 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
641 arr = fRunNumbers.Tokenize(" ");
643 while ((os=(TObjString*)next())) {
644 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
645 if (!DirectoryExists(path)) {
646 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
649 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
650 TString msg = "\n##### file: ";
652 msg += " type: xml_collection;";
653 if (useTags) msg += " using_tags: Yes";
654 else msg += " using_tags: No";
655 Info("CheckDataType", "%s", msg.Data());
656 if (fNrunsPerMaster<2) {
657 AddDataFile(Form("%s.xml", os->GetString().Data()));
660 if (((nruns-1)%fNrunsPerMaster) == 0) {
661 schunk = os->GetString();
663 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
664 schunk += Form("_%s.xml", os->GetString().Data());
670 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
671 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
672 format = Form("%%s/%s ", fRunPrefix.Data());
673 path = Form(format.Data(), fGridDataDir.Data(), irun);
674 if (!DirectoryExists(path)) {
677 format = Form("%%s/%s.xml", fRunPrefix.Data());
678 path = Form(format.Data(), workdir.Data(),irun);
679 TString msg = "\n##### file: ";
681 msg += " type: xml_collection;";
682 if (useTags) msg += " using_tags: Yes";
683 else msg += " using_tags: No";
684 Info("CheckDataType", "%s", msg.Data());
685 if (fNrunsPerMaster<2) {
686 format = Form("%s.xml", fRunPrefix.Data());
687 AddDataFile(Form(format.Data(),irun));
690 if (((nruns-1)%fNrunsPerMaster) == 0) {
691 schunk = Form(fRunPrefix.Data(),irun);
693 format = Form("_%s.xml", fRunPrefix.Data());
694 schunk2 = Form(format.Data(), irun);
695 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
708 //______________________________________________________________________________
709 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
711 // Create dataset for the grid data directory + run number.
712 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
714 Error("CreateDataset", "Cannot create dataset with no grid connection");
719 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
720 TString workdir = gGrid->GetHomeDirectory();
721 workdir += fGridWorkingDir;
723 // Compose the 'find' command arguments
726 TString options = "-x collection ";
727 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
728 TString conditions = "";
733 TString schunk, schunk2;
734 TGridCollection *cbase=0, *cadd=0;
735 if (!fRunNumbers.Length() && !fRunRange[0]) {
736 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
737 // Make a single data collection from data directory.
739 if (!DirectoryExists(path)) {
740 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
744 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
745 else file = Form("%s.xml", gSystem->BaseName(path));
746 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
752 command += conditions;
753 printf("command: %s\n", command.Data());
754 TGridResult *res = gGrid->Command(command);
756 // Write standard output to file
757 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
758 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
759 Bool_t nullFile = kFALSE;
761 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
763 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
765 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
770 Bool_t fileExists = FileExists(file);
771 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
772 // Copy xml file to alien space
773 if (fileExists) gGrid->Rm(file);
774 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
775 if (!FileExists(file)) {
776 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
779 // Update list of files to be processed.
781 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
785 Bool_t nullResult = kTRUE;
786 if (fRunNumbers.Length()) {
787 TObjArray *arr = fRunNumbers.Tokenize(" ");
790 while ((os=(TObjString*)next())) {
791 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
792 if (!DirectoryExists(path)) continue;
794 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
795 else file = Form("%s.xml", os->GetString().Data());
796 // If local collection file does not exist, create it via 'find' command.
797 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
802 command += conditions;
803 TGridResult *res = gGrid->Command(command);
805 // Write standard output to file
806 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
807 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
808 Bool_t nullFile = kFALSE;
810 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
812 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
814 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
815 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
821 if (TestBit(AliAnalysisGrid::kTest)) break;
822 // Check if there is one run per master job.
823 if (fNrunsPerMaster<2) {
824 if (FileExists(file)) {
825 if (fOverwriteMode) gGrid->Rm(file);
827 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
831 // Copy xml file to alien space
832 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
833 if (!FileExists(file)) {
834 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
840 if (((nruns-1)%fNrunsPerMaster) == 0) {
841 schunk = os->GetString();
842 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
844 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
845 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
849 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
852 schunk += Form("_%s.xml", os->GetString().Data());
853 if (FileExists(schunk)) {
854 if (fOverwriteMode) gGrid->Rm(file);
856 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
860 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
861 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
862 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
863 if (!FileExists(schunk)) {
864 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
872 Error("CreateDataset", "No valid dataset corresponding to the query!");
876 // Process a full run range.
877 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
878 format = Form("%%s/%s ", fRunPrefix.Data());
879 path = Form(format.Data(), fGridDataDir.Data(), irun);
880 if (!DirectoryExists(path)) continue;
882 format = Form("%s.xml", fRunPrefix.Data());
883 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
884 else file = Form(format.Data(), irun);
885 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
886 if (fOverwriteMode) gGrid->Rm(file);
888 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
892 // If local collection file does not exist, create it via 'find' command.
893 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
898 command += conditions;
899 TGridResult *res = gGrid->Command(command);
901 // Write standard output to file
902 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
903 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
904 Bool_t nullFile = kFALSE;
906 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
908 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
910 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
916 if (TestBit(AliAnalysisGrid::kTest)) break;
917 // Check if there is one run per master job.
918 if (fNrunsPerMaster<2) {
919 if (FileExists(file)) {
920 if (fOverwriteMode) gGrid->Rm(file);
922 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
926 // Copy xml file to alien space
927 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
928 if (!FileExists(file)) {
929 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
934 // Check if the collection for the chunk exist locally.
935 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
936 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
937 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
940 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
941 if (((nruns-1)%fNrunsPerMaster) == 0) {
942 schunk = Form(fRunPrefix.Data(), irun);
943 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
945 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
949 format = Form("%%s_%s.xml", fRunPrefix.Data());
950 schunk2 = Form(format.Data(), schunk.Data(), irun);
951 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
955 if (FileExists(schunk)) {
956 if (fOverwriteMode) gGrid->Rm(schunk);
958 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
962 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
963 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
964 if (FileExists(schunk)) {
965 if (fOverwriteMode) gGrid->Rm(schunk);
967 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
971 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
972 if (!FileExists(schunk)) {
973 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
979 Error("CreateDataset", "No valid dataset corresponding to the query!");
986 //______________________________________________________________________________
987 Bool_t AliAnalysisAlien::CreateJDL()
989 // Generate a JDL file according to current settings. The name of the file is
990 // specified by fJDLName.
991 Bool_t error = kFALSE;
994 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
995 Bool_t generate = kTRUE;
996 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
998 Error("CreateJDL", "Alien connection required");
1001 // Check validity of alien workspace
1003 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1004 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1005 workdir += fGridWorkingDir;
1009 Error("CreateJDL()", "Define some input files for your analysis.");
1012 // Compose list of input files
1013 // Check if output files were defined
1014 if (!fOutputFiles.Length()) {
1015 Error("CreateJDL", "You must define at least one output file");
1018 // Check if an output directory was defined and valid
1019 if (!fGridOutputDir.Length()) {
1020 Error("CreateJDL", "You must define AliEn output directory");
1023 if (!fProductionMode) {
1024 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1025 if (!DirectoryExists(fGridOutputDir)) {
1026 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1027 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1029 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1033 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1038 // Exit if any error up to now
1039 if (error) return kFALSE;
1041 if (!fUser.IsNull()) {
1042 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1043 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1045 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1046 TString mergeExec = fExecutable;
1047 mergeExec.ReplaceAll(".sh", "_merge.sh");
1048 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1049 mergeExec.ReplaceAll(".sh", ".C");
1050 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1051 if (!fArguments.IsNull())
1052 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1053 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1055 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1056 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1059 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1060 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1061 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1062 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1064 if (fMaxInitFailed > 0) {
1065 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1066 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1068 if (fSplitMaxInputFileNumber > 0) {
1069 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1070 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1072 if (!IsOneStageMerging()) {
1073 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1074 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1076 if (fSplitMode.Length()) {
1077 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1078 fGridJDL->SetDescription("Split", "We split per SE or file");
1080 fMergingJDL->SetValue("Split", "\"se\"");
1081 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1082 if (!fAliROOTVersion.IsNull()) {
1083 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1084 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1086 if (!fROOTVersion.IsNull()) {
1087 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1088 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1090 if (!fAPIVersion.IsNull()) {
1091 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1092 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1094 if (!fExternalPackages.IsNull()) {
1095 arr = fExternalPackages.Tokenize(" ");
1097 while ((os=(TObjString*)next())) {
1098 TString pkgname = os->GetString();
1099 Int_t index = pkgname.Index("::");
1100 TString pkgversion = pkgname(index+2, pkgname.Length());
1101 pkgname.Remove(index);
1102 fGridJDL->AddToPackages(pkgname, pkgversion);
1103 fMergingJDL->AddToPackages(pkgname, pkgversion);
1107 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1108 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1109 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1110 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1111 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1112 TString analysisFile = fExecutable;
1113 analysisFile.ReplaceAll(".sh", ".root");
1114 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1115 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1116 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1117 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1118 if (fAdditionalLibs.Length()) {
1119 arr = fAdditionalLibs.Tokenize(" ");
1121 while ((os=(TObjString*)next())) {
1122 if (os->GetString().Contains(".so")) continue;
1123 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1124 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1129 TIter next(fPackages);
1131 while ((obj=next())) {
1132 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1133 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1136 if (fOutputArchive.Length()) {
1137 arr = fOutputArchive.Tokenize(" ");
1139 Bool_t first = kTRUE;
1140 const char *comment = "Files to be archived";
1141 const char *comment1 = comment;
1142 while ((os=(TObjString*)next())) {
1143 if (!first) comment = NULL;
1144 if (!os->GetString().Contains("@") && fCloseSE.Length())
1145 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1147 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1151 // Output archive for the merging jdl
1152 TString outputArchive;
1153 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1154 outputArchive = "log_archive.zip:std*@disk=1 ";
1155 // Add normal output files, extra files + terminate files
1156 TString files = GetListOfFiles("outextter");
1157 // Do not register merge excludes
1158 if (!fMergeExcludes.IsNull()) {
1159 arr = fMergeExcludes.Tokenize(" ");
1161 while ((os=(TObjString*)next1())) {
1162 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1163 files.ReplaceAll(os->GetString(),"");
1167 files.ReplaceAll(".root", "*.root");
1168 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1170 TString files = fOutputArchive;
1171 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1172 outputArchive = files;
1174 arr = outputArchive.Tokenize(" ");
1178 while ((os=(TObjString*)next2())) {
1179 if (!first) comment = NULL;
1180 TString currentfile = os->GetString();
1181 if (!currentfile.Contains("@") && fCloseSE.Length())
1182 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1184 fMergingJDL->AddToOutputArchive(currentfile, comment);
1189 arr = fOutputFiles.Tokenize(",");
1191 Bool_t first = kTRUE;
1192 const char *comment = "Files to be saved";
1193 while ((os=(TObjString*)next())) {
1194 // Ignore ouputs in jdl that are also in outputarchive
1195 TString sout = os->GetString();
1196 sout.ReplaceAll("*", "");
1197 sout.ReplaceAll(".root", "");
1198 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1199 if (fOutputArchive.Contains(sout)) continue;
1200 if (!first) comment = NULL;
1201 if (!os->GetString().Contains("@") && fCloseSE.Length())
1202 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1204 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1206 if (fMergeExcludes.Contains(sout)) continue;
1207 if (!os->GetString().Contains("@") && fCloseSE.Length())
1208 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1210 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1213 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1214 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1215 TString validationScript = fValidationScript;
1216 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1217 validationScript.ReplaceAll(".sh", "_merge.sh");
1218 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1219 if (fMasterResubmitThreshold) {
1220 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1221 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1223 // Write a jdl with 2 input parameters: collection name and output dir name.
1226 // Copy jdl to grid workspace
1228 // Check if an output directory was defined and valid
1229 if (!fGridOutputDir.Length()) {
1230 Error("CreateJDL", "You must define AliEn output directory");
1233 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1234 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1235 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1236 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1238 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1244 if (TestBit(AliAnalysisGrid::kSubmit)) {
1245 TString mergeJDLName = fExecutable;
1246 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1247 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1248 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1249 if (fProductionMode) {
1250 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1251 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1253 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1254 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1255 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1256 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1258 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1259 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1262 if (fAdditionalLibs.Length()) {
1263 arr = fAdditionalLibs.Tokenize(" ");
1266 while ((os=(TObjString*)next())) {
1267 if (os->GetString().Contains(".so")) continue;
1268 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1269 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1270 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1275 TIter next(fPackages);
1277 while ((obj=next())) {
1278 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1279 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1280 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1287 //______________________________________________________________________________
1288 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1290 // Writes one or more JDL's corresponding to findex. If findex is negative,
1291 // all run numbers are considered in one go (jdl). For non-negative indices
1292 // they correspond to the indices in the array fInputFiles.
1293 if (!fInputFiles) return kFALSE;
1296 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1297 workdir += fGridWorkingDir;
1298 TString stageName = "$2";
1299 if (fProductionMode) stageName = "$4";
1300 if (!fMergeDirName.IsNull()) {
1301 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1302 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1304 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1305 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1307 if (fProductionMode) {
1308 TIter next(fInputFiles);
1309 while ((os=next())) {
1310 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1312 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1314 if (!fRunNumbers.Length() && !fRunRange[0]) {
1315 // One jdl with no parameters in case input data is specified by name.
1316 TIter next(fInputFiles);
1318 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1319 if (!fOutputSingle.IsNull())
1320 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1322 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1323 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1326 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1327 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1328 if (!fOutputSingle.IsNull()) {
1329 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1330 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1332 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1337 // Generate the JDL as a string
1338 TString sjdl = fGridJDL->Generate();
1339 TString sjdl1 = fMergingJDL->Generate();
1341 if (!fMergeDirName.IsNull()) {
1342 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1343 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1345 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1346 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1348 TString sjdl2 = fMergingJDL->Generate();
1349 Int_t index, index1;
1350 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1351 sjdl.ReplaceAll("(member", "\n (member");
1352 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1353 sjdl.ReplaceAll("{", "{\n ");
1354 sjdl.ReplaceAll("};", "\n};");
1355 sjdl.ReplaceAll("{\n \n", "{\n");
1356 sjdl.ReplaceAll("\n\n", "\n");
1357 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1358 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1359 sjdl1.ReplaceAll("(member", "\n (member");
1360 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1361 sjdl1.ReplaceAll("{", "{\n ");
1362 sjdl1.ReplaceAll("};", "\n};");
1363 sjdl1.ReplaceAll("{\n \n", "{\n");
1364 sjdl1.ReplaceAll("\n\n", "\n");
1365 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1366 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1367 sjdl2.ReplaceAll("(member", "\n (member");
1368 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1369 sjdl2.ReplaceAll("{", "{\n ");
1370 sjdl2.ReplaceAll("};", "\n};");
1371 sjdl2.ReplaceAll("{\n \n", "{\n");
1372 sjdl2.ReplaceAll("\n\n", "\n");
1373 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1374 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1375 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1376 index = sjdl.Index("JDLVariables");
1377 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1378 sjdl += "Workdirectorysize = {\"5000MB\"};";
1379 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1380 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1381 index = fJobTag.Index(":");
1382 if (index < 0) index = fJobTag.Length();
1383 TString jobTag = fJobTag;
1384 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1385 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1386 if (fProductionMode) {
1387 sjdl1.Prepend("# Generated merging jdl (production mode) \
1388 \n# $1 = full alien path to output directory to be merged \
1389 \n# $2 = train number \
1390 \n# $3 = production (like LHC10b) \
1391 \n# $4 = merging stage \
1392 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1393 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1394 sjdl2.Prepend("# Generated merging jdl \
1395 \n# $1 = full alien path to output directory to be merged \
1396 \n# $2 = train number \
1397 \n# $3 = production (like LHC10b) \
1398 \n# $4 = merging stage \
1399 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1401 sjdl1.Prepend("# Generated merging jdl \
1402 \n# $1 = full alien path to output directory to be merged \
1403 \n# $2 = merging stage \
1404 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1405 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1406 sjdl2.Prepend("# Generated merging jdl \
1407 \n# $1 = full alien path to output directory to be merged \
1408 \n# $2 = merging stage \
1409 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1411 index = sjdl1.Index("JDLVariables");
1412 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1413 index = sjdl2.Index("JDLVariables");
1414 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1415 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1416 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1417 index = sjdl2.Index("Split =");
1419 index1 = sjdl2.Index("\n", index);
1420 sjdl2.Remove(index, index1-index+1);
1422 index = sjdl2.Index("SplitMaxInputFileNumber");
1424 index1 = sjdl2.Index("\n", index);
1425 sjdl2.Remove(index, index1-index+1);
1427 index = sjdl2.Index("InputDataCollection");
1429 index1 = sjdl2.Index(";", index);
1430 sjdl2.Remove(index, index1-index+1);
1432 index = sjdl2.Index("InputDataListFormat");
1434 index1 = sjdl2.Index("\n", index);
1435 sjdl2.Remove(index, index1-index+1);
1437 index = sjdl2.Index("InputDataList");
1439 index1 = sjdl2.Index("\n", index);
1440 sjdl2.Remove(index, index1-index+1);
1442 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1443 // Write jdl to file
1445 out.open(fJDLName.Data(), ios::out);
1447 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1450 out << sjdl << endl;
1452 TString mergeJDLName = fExecutable;
1453 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1456 out1.open(mergeJDLName.Data(), ios::out);
1458 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1461 out1 << sjdl1 << endl;
1464 TString finalJDL = mergeJDLName;
1465 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1466 out2.open(finalJDL.Data(), ios::out);
1468 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1471 out2 << sjdl2 << endl;
1475 // Copy jdl to grid workspace
1477 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1479 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1480 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1481 TString finalJDL = mergeJDLName;
1482 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1483 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1484 if (fProductionMode) {
1485 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1486 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1487 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1489 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1490 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1491 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1492 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1493 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1495 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1496 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1497 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1503 //______________________________________________________________________________
1504 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1506 // Returns true if file exists.
1507 if (!gGrid) return kFALSE;
1509 slfn.ReplaceAll("alien://","");
1510 TGridResult *res = gGrid->Ls(slfn);
1511 if (!res) return kFALSE;
1512 TMap *map = dynamic_cast<TMap*>(res->At(0));
1517 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1518 if (!objs || !objs->GetString().Length()) {
1526 //______________________________________________________________________________
1527 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1529 // Returns true if directory exists. Can be also a path.
1530 if (!gGrid) return kFALSE;
1531 // Check if dirname is a path
1532 TString dirstripped = dirname;
1533 dirstripped = dirstripped.Strip();
1534 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1535 TString dir = gSystem->BaseName(dirstripped);
1537 TString path = gSystem->DirName(dirstripped);
1538 TGridResult *res = gGrid->Ls(path, "-F");
1539 if (!res) return kFALSE;
1543 while ((map=dynamic_cast<TMap*>(next()))) {
1544 obj = map->GetValue("name");
1546 if (dir == obj->GetName()) {
1555 //______________________________________________________________________________
1556 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1558 // Check input data type.
1559 isCollection = kFALSE;
1563 Error("CheckDataType", "No connection to grid");
1566 isCollection = IsCollection(lfn);
1567 TString msg = "\n##### file: ";
1570 msg += " type: raw_collection;";
1571 // special treatment for collections
1573 // check for tag files in the collection
1574 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1576 msg += " using_tags: No (unknown)";
1577 Info("CheckDataType", "%s", msg.Data());
1580 const char* typeStr = res->GetKey(0, "origLFN");
1581 if (!typeStr || !strlen(typeStr)) {
1582 msg += " using_tags: No (unknown)";
1583 Info("CheckDataType", "%s", msg.Data());
1586 TString file = typeStr;
1587 useTags = file.Contains(".tag");
1588 if (useTags) msg += " using_tags: Yes";
1589 else msg += " using_tags: No";
1590 Info("CheckDataType", "%s", msg.Data());
1595 isXml = slfn.Contains(".xml");
1597 // Open xml collection and check if there are tag files inside
1598 msg += " type: xml_collection;";
1599 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1601 msg += " using_tags: No (unknown)";
1602 Info("CheckDataType", "%s", msg.Data());
1605 TMap *map = coll->Next();
1607 msg += " using_tags: No (unknown)";
1608 Info("CheckDataType", "%s", msg.Data());
1611 map = (TMap*)map->GetValue("");
1613 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1614 useTags = file.Contains(".tag");
1616 if (useTags) msg += " using_tags: Yes";
1617 else msg += " using_tags: No";
1618 Info("CheckDataType", "%s", msg.Data());
1621 useTags = slfn.Contains(".tag");
1622 if (slfn.Contains(".root")) msg += " type: root file;";
1623 else msg += " type: unknown file;";
1624 if (useTags) msg += " using_tags: Yes";
1625 else msg += " using_tags: No";
1626 Info("CheckDataType", "%s", msg.Data());
1629 //______________________________________________________________________________
1630 void AliAnalysisAlien::EnablePackage(const char *package)
1632 // Enables a par file supposed to exist in the current directory.
1633 TString pkg(package);
1634 pkg.ReplaceAll(".par", "");
1636 if (gSystem->AccessPathName(pkg)) {
1637 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1640 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1641 Info("EnablePackage", "AliEn plugin will use .par packages");
1642 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1644 fPackages = new TObjArray();
1645 fPackages->SetOwner();
1647 fPackages->Add(new TObjString(pkg));
1650 //______________________________________________________________________________
1651 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1653 // Make a tree from files having the location specified in fFileForTestMode.
1654 // Inspired from JF's CreateESDChain.
1655 if (fFileForTestMode.IsNull()) {
1656 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1659 if (gSystem->AccessPathName(fFileForTestMode)) {
1660 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1665 in.open(fFileForTestMode);
1667 // Read the input list of files and add them to the chain
1669 TChain *chain = new TChain(treeName);
1673 if (line.IsNull()) continue;
1674 if (count++ == fNtestFiles) break;
1675 TString esdFile(line);
1676 TFile *file = TFile::Open(esdFile);
1678 if (!file->IsZombie()) chain->Add(esdFile);
1681 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1685 if (!chain->GetListOfFiles()->GetEntries()) {
1686 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1694 //______________________________________________________________________________
1695 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1697 // Get job status for all jobs with jobid>jobidstart.
1698 static char mstatus[20];
1704 TGridJobStatusList *list = gGrid->Ps("");
1705 if (!list) return mstatus;
1706 Int_t nentries = list->GetSize();
1707 TGridJobStatus *status;
1709 for (Int_t ijob=0; ijob<nentries; ijob++) {
1710 status = (TGridJobStatus *)list->At(ijob);
1711 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1712 if (pid<jobidstart) continue;
1713 if (pid == lastid) {
1714 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1716 switch (status->GetStatus()) {
1717 case TGridJobStatus::kWAITING:
1719 case TGridJobStatus::kRUNNING:
1721 case TGridJobStatus::kABORTED:
1722 case TGridJobStatus::kFAIL:
1723 case TGridJobStatus::kUNKNOWN:
1725 case TGridJobStatus::kDONE:
1734 //______________________________________________________________________________
1735 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1737 // Returns true if file is a collection. Functionality duplicated from
1738 // TAlien::Type() because we don't want to directly depend on TAlien.
1740 Error("IsCollection", "No connection to grid");
1743 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1744 if (!res) return kFALSE;
1745 const char* typeStr = res->GetKey(0, "type");
1746 if (!typeStr || !strlen(typeStr)) return kFALSE;
1747 if (!strcmp(typeStr, "collection")) return kTRUE;
1752 //______________________________________________________________________________
1753 Bool_t AliAnalysisAlien::IsSingleOutput() const
1755 // Check if single-ouput option is on.
1756 return (!fOutputSingle.IsNull());
1759 //______________________________________________________________________________
1760 void AliAnalysisAlien::Print(Option_t *) const
1762 // Print current plugin settings.
1763 printf("### AliEn analysis plugin current settings ###\n");
1764 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1765 if (mgr && mgr->IsProofMode()) {
1766 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1767 if (TestBit(AliAnalysisGrid::kTest))
1768 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1769 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1770 if (!fProofDataSet.IsNull())
1771 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1773 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1775 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1776 if (!fRootVersionForProof.IsNull())
1777 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1779 printf("= ROOT version requested________________________ default\n");
1780 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1781 if (!fAliRootMode.IsNull())
1782 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1784 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1785 if (fNproofWorkersPerSlave)
1786 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1787 if (TestSpecialBit(kClearPackages))
1788 printf("= ClearPackages requested...\n");
1789 if (fIncludePath.Data())
1790 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1791 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1792 if (fPackages && fPackages->GetEntries()) {
1793 TIter next(fPackages);
1796 while ((obj=next())) list += obj->GetName();
1797 printf("= Par files to be used: ________________________ %s\n", list.Data());
1799 if (TestSpecialBit(kProofConnectGrid))
1800 printf("= Requested PROOF connection to grid\n");
1803 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1804 if (fOverwriteMode) {
1805 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1806 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1808 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1809 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1810 printf("= Production mode:______________________________ %d\n", fProductionMode);
1811 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1812 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1813 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1815 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1816 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1817 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1818 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1819 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1820 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1821 if (fRunNumbers.Length())
1822 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1824 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1825 if (!fRunRange[0] && !fRunNumbers.Length()) {
1826 TIter next(fInputFiles);
1829 while ((obj=next())) list += obj->GetName();
1830 printf("= Input files to be processed: _________________ %s\n", list.Data());
1832 if (TestBit(AliAnalysisGrid::kTest))
1833 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1834 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1835 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1836 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1837 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1838 printf("=====================================================================\n");
1839 printf("= Job price: ___________________________________ %d\n", fPrice);
1840 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1841 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1842 if (fMaxInitFailed>0)
1843 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1844 if (fMasterResubmitThreshold>0)
1845 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1846 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1847 if (fNrunsPerMaster>0)
1848 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1849 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1850 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1851 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1852 if (fArguments.Length())
1853 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1854 if (fExecutableArgs.Length())
1855 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1856 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1857 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1858 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1859 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1861 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1862 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1863 if (fIncludePath.Data())
1864 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1865 if (fCloseSE.Length())
1866 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1867 if (fFriendChainName.Length())
1868 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1869 if (fPackages && fPackages->GetEntries()) {
1870 TIter next(fPackages);
1873 while ((obj=next())) list += obj->GetName();
1874 printf("= Par files to be used: ________________________ %s\n", list.Data());
1878 //______________________________________________________________________________
1879 void AliAnalysisAlien::SetDefaults()
1881 // Set default values for everything. What cannot be filled will be left empty.
1882 if (fGridJDL) delete fGridJDL;
1883 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1884 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1887 fSplitMaxInputFileNumber = 100;
1889 fMasterResubmitThreshold = 0;
1895 fNrunsPerMaster = 1;
1896 fMaxMergeFiles = 100;
1898 fExecutable = "analysis.sh";
1899 fExecutableCommand = "root -b -q";
1901 fExecutableArgs = "";
1902 fAnalysisMacro = "myAnalysis.C";
1903 fAnalysisSource = "";
1904 fAdditionalLibs = "";
1908 fAliROOTVersion = "";
1909 fUser = ""; // Your alien user name
1910 fGridWorkingDir = "";
1911 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1912 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1913 fFriendChainName = "";
1914 fGridOutputDir = "output";
1915 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1916 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1917 fInputFormat = "xml-single";
1918 fJDLName = "analysis.jdl";
1919 fJobTag = "Automatically generated analysis JDL";
1920 fMergeExcludes = "";
1923 SetCheckCopy(kTRUE);
1924 SetDefaultOutputs(kTRUE);
1928 //______________________________________________________________________________
1929 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
1931 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1932 // First check if the result is already in the output directory.
1933 if (FileExists(Form("%s/%s",aliendir,filename))) {
1934 printf("Final merged results found. Not merging again.\n");
1937 // Now check the last stage done.
1940 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1943 // Next stage of merging
1945 TString pattern = "*root_archive.zip";
1946 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1947 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1948 if (res) delete res;
1949 // Write standard output to file
1950 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1951 // Count the number of files inside
1953 ifile.open(Form("Stage_%d.xml",stage));
1954 if (!ifile.good()) {
1955 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
1960 while (!ifile.eof()) {
1962 if (line.Contains("/event")) nfiles++;
1966 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1969 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
1971 // Copy the file in the output directory
1972 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1973 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1974 // Check if this is the last stage to be done.
1975 Bool_t laststage = (nfiles<nperchunk);
1976 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1978 printf("### Submiting final merging stage %d\n", stage);
1979 TString finalJDL = jdl;
1980 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1981 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
1982 Int_t jobId = SubmitSingleJob(query);
1983 if (!jobId) return kFALSE;
1985 printf("### Submiting merging stage %d\n", stage);
1986 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
1987 Int_t jobId = SubmitSingleJob(query);
1988 if (!jobId) return kFALSE;
1993 //______________________________________________________________________________
1994 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1996 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1997 if (!gGrid) return 0;
1998 printf("=> %s ------> ",query);
1999 TGridResult *res = gGrid->Command(query);
2001 TString jobId = res->GetKey(0,"jobId");
2003 if (jobId.IsNull()) {
2004 printf("submission failed. Reason:\n");
2007 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2010 printf(" Job id: %s\n", jobId.Data());
2014 //______________________________________________________________________________
2015 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2017 // Merge given output files from basedir. Basedir can be an alien output directory
2018 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2019 // files in a group (ignored for xml input). Merging can be done in stages:
2020 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2021 // stage=1 : works with an xml of all root_archive.zip in the output directory
2022 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2023 TString outputFile = output;
2025 TString outputChunk;
2026 TString previousChunk = "";
2027 TObjArray *listoffiles = new TObjArray();
2028 // listoffiles->SetOwner();
2029 Int_t countChunk = 0;
2030 Int_t countZero = nmaxmerge;
2031 Bool_t merged = kTRUE;
2032 Int_t index = outputFile.Index("@");
2033 if (index > 0) outputFile.Remove(index);
2034 TString inputFile = outputFile;
2035 TString sbasedir = basedir;
2036 if (sbasedir.Contains(".xml")) {
2037 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2038 nmaxmerge = 9999999;
2039 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2041 ::Error("MergeOutput", "Input XML collection empty.");
2044 // Iterate grid collection
2045 while (coll->Next()) {
2046 TString fname = gSystem->DirName(coll->GetTURL());
2049 listoffiles->Add(new TNamed(fname.Data(),""));
2052 command = Form("find %s/ *%s", basedir, inputFile.Data());
2053 printf("command: %s\n", command.Data());
2054 TGridResult *res = gGrid->Command(command);
2056 ::Error("MergeOutput","No result for the find command\n");
2062 while ((map=(TMap*)nextmap())) {
2063 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2064 if (!objs || !objs->GetString().Length()) {
2065 // Nothing found - skip this output
2070 listoffiles->Add(new TNamed(objs->GetName(),""));
2074 if (!listoffiles->GetEntries()) {
2075 ::Error("MergeOutput","No result for the find command\n");
2080 TFileMerger *fm = 0;
2081 TIter next0(listoffiles);
2082 TObjArray *listoffilestmp = new TObjArray();
2083 listoffilestmp->SetOwner();
2086 // Keep only the files at upper level
2087 Int_t countChar = 0;
2088 while ((nextfile=next0())) {
2089 snextfile = nextfile->GetName();
2090 Int_t crtCount = snextfile.CountChar('/');
2091 if (nextfile == listoffiles->First()) countChar = crtCount;
2092 if (crtCount < countChar) countChar = crtCount;
2095 while ((nextfile=next0())) {
2096 snextfile = nextfile->GetName();
2097 Int_t crtCount = snextfile.CountChar('/');
2098 if (crtCount > countChar) {
2102 listoffilestmp->Add(nextfile);
2105 listoffiles = listoffilestmp; // Now contains 'good' files
2106 listoffiles->Print();
2107 TIter next(listoffiles);
2108 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2109 outputChunk = outputFile;
2110 outputChunk.ReplaceAll(".root", "_*.root");
2111 // Check for existent temporary merge files
2112 // Check overwrite mode and remove previous partial results if needed
2113 // Preserve old merging functionality for stage 0.
2115 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2117 // Skip as many input files as in a chunk
2118 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2121 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2125 snextfile = nextfile->GetName();
2127 outputChunk = outputFile;
2128 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2130 if (gSystem->AccessPathName(outputChunk)) continue;
2131 // Merged file with chunks up to <countChunk> found
2132 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2133 previousChunk = outputChunk;
2137 countZero = nmaxmerge;
2139 while ((nextfile=next())) {
2140 snextfile = nextfile->GetName();
2141 // Loop 'find' results and get next LFN
2142 if (countZero == nmaxmerge) {
2143 // First file in chunk - create file merger and add previous chunk if any.
2144 fm = new TFileMerger(kFALSE);
2145 fm->SetFastMethod(kTRUE);
2146 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2147 outputChunk = outputFile;
2148 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2150 // If last file found, put merged results in the output file
2151 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2152 // Add file to be merged and decrement chunk counter.
2153 fm->AddFile(snextfile);
2155 if (countZero==0 || nextfile == listoffiles->Last()) {
2156 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2157 // Nothing found - skip this output
2158 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2162 fm->OutputFile(outputChunk);
2163 // Merge the outputs, then go to next chunk
2165 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2169 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2170 gSystem->Unlink(previousChunk);
2172 if (nextfile == listoffiles->Last()) break;
2174 countZero = nmaxmerge;
2175 previousChunk = outputChunk;
2182 // Merging stage different than 0.
2183 // Move to the begining of the requested chunk.
2184 fm = new TFileMerger(kFALSE);
2185 fm->SetFastMethod(kTRUE);
2186 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2188 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2189 // Nothing found - skip this output
2190 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2194 fm->OutputFile(outputFile);
2195 // Merge the outputs
2197 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2201 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2207 //______________________________________________________________________________
2208 Bool_t AliAnalysisAlien::MergeOutputs()
2210 // Merge analysis outputs existing in the AliEn space.
2211 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2212 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2214 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2218 if (!TestBit(AliAnalysisGrid::kMerge)) {
2219 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2222 if (fProductionMode) {
2223 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2226 Info("MergeOutputs", "Submitting merging JDL");
2227 if (!SubmitMerging()) return kFALSE;
2228 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2229 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2232 // Get the output path
2233 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2234 if (!DirectoryExists(fGridOutputDir)) {
2235 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2238 if (!fOutputFiles.Length()) {
2239 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2242 // Check if fast read option was requested
2243 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2244 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2245 if (fFastReadOption) {
2246 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2247 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2248 gEnv->SetValue("XNet.ConnectTimeout",50);
2249 gEnv->SetValue("XNet.RequestTimeout",50);
2250 gEnv->SetValue("XNet.MaxRedirectCount",2);
2251 gEnv->SetValue("XNet.ReconnectTimeout",50);
2252 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2254 // Make sure we change the temporary directory
2255 gSystem->Setenv("TMPDIR", gSystem->pwd());
2256 // Set temporary compilation directory to current one
2257 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2258 TObjArray *list = fOutputFiles.Tokenize(",");
2262 Bool_t merged = kTRUE;
2263 while((str=(TObjString*)next())) {
2264 outputFile = str->GetString();
2265 Int_t index = outputFile.Index("@");
2266 if (index > 0) outputFile.Remove(index);
2267 TString outputChunk = outputFile;
2268 outputChunk.ReplaceAll(".root", "_*.root");
2269 // Skip already merged outputs
2270 if (!gSystem->AccessPathName(outputFile)) {
2271 if (fOverwriteMode) {
2272 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2273 gSystem->Unlink(outputFile);
2274 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2275 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2276 outputChunk.Data());
2277 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2280 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2284 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2285 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2286 outputChunk.Data());
2287 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2290 if (fMergeExcludes.Length() &&
2291 fMergeExcludes.Contains(outputFile.Data())) continue;
2292 // Perform a 'find' command in the output directory, looking for registered outputs
2293 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2295 Error("MergeOutputs", "Terminate() will NOT be executed");
2298 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2299 if (fileOpened) fileOpened->Close();
2304 //______________________________________________________________________________
2305 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2307 // Use the output files connected to output containers from the analysis manager
2308 // rather than the files defined by SetOutputFiles
2309 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2310 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2311 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2314 //______________________________________________________________________________
2315 void AliAnalysisAlien::SetOutputFiles(const char *list)
2317 // Manually set the output files list.
2318 // Removes duplicates. Not allowed if default outputs are not disabled.
2319 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2320 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2323 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2325 TString slist = list;
2326 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2327 TObjArray *arr = slist.Tokenize(" ");
2331 while ((os=(TObjString*)next())) {
2332 sout = os->GetString();
2333 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2334 if (fOutputFiles.Contains(sout)) continue;
2335 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2336 fOutputFiles += sout;
2341 //______________________________________________________________________________
2342 void AliAnalysisAlien::SetOutputArchive(const char *list)
2344 // Manually set the output archive list. Free text - you are on your own...
2345 // Not allowed if default outputs are not disabled.
2346 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2347 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2350 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2351 fOutputArchive = list;
2354 //______________________________________________________________________________
2355 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2357 // Setting a prefered output SE is not allowed anymore.
2358 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2361 //______________________________________________________________________________
2362 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2364 // Set some PROOF special parameter.
2365 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2367 TObject *old = pair->Key();
2368 TObject *val = pair->Value();
2369 fProofParam.Remove(old);
2373 fProofParam.Add(new TObjString(pname), new TObjString(value));
2376 //______________________________________________________________________________
2377 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2379 // Returns a special PROOF parameter.
2380 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2381 if (!pair) return 0;
2382 return pair->Value()->GetName();
2385 //______________________________________________________________________________
2386 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2388 // Start remote grid analysis.
2389 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2390 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2391 if (!mgr || !mgr->IsInitialized()) {
2392 Error("StartAnalysis", "You need an initialized analysis manager for this");
2395 // Are we in PROOF mode ?
2396 if (mgr->IsProofMode()) {
2397 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2398 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2399 if (fProofCluster.IsNull()) {
2400 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2403 if (fProofDataSet.IsNull() && !testMode) {
2404 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2407 // Set the needed environment
2408 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2409 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2410 if (fProofReset && !testMode) {
2411 if (fProofReset==1) {
2412 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2413 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2415 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2416 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2418 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2423 // Check if there is an old active session
2424 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2426 Error("StartAnalysis","You have to reset your old session first\n");
2430 // Do we need to change the ROOT version ? The success of this cannot be checked.
2431 if (!fRootVersionForProof.IsNull() && !testMode) {
2432 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2433 fProofCluster.Data(), fRootVersionForProof.Data()));
2435 // Connect to PROOF and check the status
2438 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2439 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2441 if (!sworkers.IsNull())
2442 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2444 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2446 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2448 Error("StartAnalysis", "Could not start PROOF in test mode");
2453 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2456 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2457 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2458 // Set proof special parameters if any
2459 TIter nextpp(&fProofParam);
2460 TObject *proofparam;
2461 while ((proofparam=nextpp())) {
2462 TString svalue = GetProofParameter(proofparam->GetName());
2463 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
2465 // Is dataset existing ?
2467 TString dataset = fProofDataSet;
2468 Int_t index = dataset.Index("#");
2469 if (index>=0) dataset.Remove(index);
2470 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2471 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2474 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2476 // Is ClearPackages() needed ?
2477 if (TestSpecialBit(kClearPackages)) {
2478 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2479 gROOT->ProcessLine("gProof->ClearPackages();");
2481 // Is a given aliroot mode requested ?
2484 if (!fAliRootMode.IsNull()) {
2485 TString alirootMode = fAliRootMode;
2486 if (alirootMode == "default") alirootMode = "";
2487 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2488 optionsList.SetOwner();
2489 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2490 // Check the additional libs to be loaded
2492 Bool_t parMode = kFALSE;
2493 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2494 // Parse the extra libs for .so
2495 if (fAdditionalLibs.Length()) {
2496 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2499 while((str=(TObjString*)next())) {
2500 if (str->GetString().Contains(".so")) {
2502 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());
2505 TString stmp = str->GetName();
2506 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2507 stmp.ReplaceAll(".so","");
2508 if (!extraLibs.IsNull()) extraLibs += ":";
2512 if (str->GetString().Contains(".par")) {
2513 // The first par file found in the list will not allow any further .so
2515 if (!parLibs.IsNull()) parLibs += ":";
2516 parLibs += str->GetName();
2520 if (list) delete list;
2522 if (!extraLibs.IsNull()) {
2523 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
2524 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2526 // Check extra includes
2527 if (!fIncludePath.IsNull()) {
2528 TString includePath = fIncludePath;
2529 includePath.ReplaceAll(" ",":");
2530 includePath.ReplaceAll("$ALICE_ROOT/","");
2531 includePath.ReplaceAll("${ALICE_ROOT}/","");
2532 includePath.ReplaceAll("-I","");
2533 includePath.Remove(TString::kTrailing, ':');
2534 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2535 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2537 // Check if connection to grid is requested
2538 if (TestSpecialBit(kProofConnectGrid))
2539 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2540 // Enable AliRoot par
2542 // Enable proof lite package
2543 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2544 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2545 TNamed *obj = (TNamed*)optionsList.At(i);
2546 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2548 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2549 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2550 Info("StartAnalysis", "AliRootProofLite enabled");
2552 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2556 if ( ! fAliROOTVersion.IsNull() ) {
2557 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2558 fAliROOTVersion.Data(), &optionsList))) {
2559 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2564 // Enable first par files from fAdditionalLibs
2565 if (!parLibs.IsNull()) {
2566 TObjArray *list = parLibs.Tokenize(":");
2568 TObjString *package;
2569 while((package=(TObjString*)next())) {
2570 TString spkg = package->GetName();
2571 spkg.ReplaceAll(".par", "");
2572 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2573 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2574 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2575 if (gROOT->ProcessLine(enablePackage)) {
2576 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2580 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2584 if (list) delete list;
2587 if (fAdditionalLibs.Contains(".so") && !testMode) {
2588 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2589 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2593 // Enable par files if requested
2594 if (fPackages && fPackages->GetEntries()) {
2595 TIter next(fPackages);
2597 while ((package=next())) {
2598 // Skip packages already enabled
2599 if (parLibs.Contains(package->GetName())) continue;
2600 TString spkg = package->GetName();
2601 spkg.ReplaceAll(".par", "");
2602 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2603 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2604 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2605 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2609 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2614 // Do we need to load analysis source files ?
2615 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2616 if (fAnalysisSource.Length()) {
2617 TObjArray *list = fAnalysisSource.Tokenize(" ");
2620 while((str=(TObjString*)next())) {
2621 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2623 if (list) delete list;
2626 // Register dataset to proof lite.
2627 if (fFileForTestMode.IsNull()) {
2628 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2631 if (gSystem->AccessPathName(fFileForTestMode)) {
2632 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2635 TFileCollection *coll = new TFileCollection();
2636 coll->AddFromFile(fFileForTestMode);
2637 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2638 gROOT->ProcessLine("gProof->ShowDataSets()");
2643 // Check if output files have to be taken from the analysis manager
2644 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2645 // Add output files and AOD files
2646 fOutputFiles = GetListOfFiles("outaod");
2647 // Add extra files registered to the analysis manager
2648 TString extra = GetListOfFiles("ext");
2649 if (!extra.IsNull()) {
2650 extra.ReplaceAll(".root", "*.root");
2651 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2652 fOutputFiles += extra;
2654 // Compose the output archive.
2655 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2656 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2658 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2659 if (TestBit(AliAnalysisGrid::kOffline)) {
2660 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2661 \n there nor any job run. You can revise the JDL and analysis \
2662 \n macro then run the same in \"submit\" mode.");
2663 } else if (TestBit(AliAnalysisGrid::kTest)) {
2664 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2666 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2667 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2668 \n space and job submitted.");
2669 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2670 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2671 if (fMergeViaJDL) CheckInputData();
2674 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2679 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2682 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2683 if (!CheckInputData()) {
2684 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2687 if (!CreateDataset(fDataPattern)) {
2689 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2690 if (fRunNumbers.Length()) serror = "run numbers";
2691 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2692 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2693 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2696 WriteAnalysisFile();
2697 WriteAnalysisMacro();
2699 WriteValidationScript();
2701 WriteMergingMacro();
2702 WriteMergeExecutable();
2703 WriteValidationScript(kTRUE);
2705 if (!CreateJDL()) return kFALSE;
2706 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2708 // Locally testing the analysis
2709 Info("StartAnalysis", "\n_______________________________________________________________________ \
2710 \n Running analysis script in a daughter shell as on a worker node \
2711 \n_______________________________________________________________________");
2712 TObjArray *list = fOutputFiles.Tokenize(",");
2716 while((str=(TObjString*)next())) {
2717 outputFile = str->GetString();
2718 Int_t index = outputFile.Index("@");
2719 if (index > 0) outputFile.Remove(index);
2720 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2723 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2724 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2725 // gSystem->Exec("cat stdout");
2728 // Check if submitting is managed by LPM manager
2729 if (fProductionMode) {
2730 TString prodfile = fJDLName;
2731 prodfile.ReplaceAll(".jdl", ".prod");
2732 WriteProductionFile(prodfile);
2733 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2736 // Submit AliEn job(s)
2737 gGrid->Cd(fGridOutputDir);
2740 if (!fRunNumbers.Length() && !fRunRange[0]) {
2741 // Submit a given xml or a set of runs
2742 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2743 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2745 const char *cjobId = res->GetKey(0,"jobId");
2749 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2752 Info("StartAnalysis", "\n_______________________________________________________________________ \
2753 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2754 \n_______________________________________________________________________",
2755 fJDLName.Data(), cjobId);
2760 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2764 // Submit for a range of enumeration of runs.
2765 if (!Submit()) return kFALSE;
2768 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2769 \n You may exit at any time and terminate the job later using the option <terminate> \
2770 \n ##################################################################################", jobID.Data());
2771 gSystem->Exec("aliensh");
2775 //______________________________________________________________________________
2776 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2778 // Get a comma-separated list of output files of the requested type.
2779 // Type can be (case unsensitive):
2780 // aod - list of aod files (std, extensions and filters)
2781 // out - list of output files connected to containers (but not aod's or extras)
2782 // ext - list of extra files registered to the manager
2783 // ter - list of files produced in terminate
2784 static TString files;
2786 TString stype = type;
2788 TString aodfiles, extra;
2789 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2791 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2792 return files.Data();
2794 if (mgr->GetOutputEventHandler()) {
2795 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2796 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2797 if (!extraaod.IsNull()) {
2799 aodfiles += extraaod;
2802 if (stype.Contains("aod")) {
2804 if (stype == "aod") return files.Data();
2806 // Add output files that are not in the list of AOD files
2807 TString outputfiles = "";
2808 TIter next(mgr->GetOutputs());
2809 AliAnalysisDataContainer *output;
2810 const char *filename = 0;
2811 while ((output=(AliAnalysisDataContainer*)next())) {
2812 filename = output->GetFileName();
2813 if (!(strcmp(filename, "default"))) continue;
2814 if (outputfiles.Contains(filename)) continue;
2815 if (aodfiles.Contains(filename)) continue;
2816 if (!outputfiles.IsNull()) outputfiles += ",";
2817 outputfiles += filename;
2819 if (stype.Contains("out")) {
2820 if (!files.IsNull()) files += ",";
2821 files += outputfiles;
2822 if (stype == "out") return files.Data();
2824 // Add extra files registered to the analysis manager
2826 extra = mgr->GetExtraFiles();
2827 if (!extra.IsNull()) {
2829 extra.ReplaceAll(" ", ",");
2830 TObjArray *fextra = extra.Tokenize(",");
2831 TIter nextx(fextra);
2833 while ((obj=nextx())) {
2834 if (aodfiles.Contains(obj->GetName())) continue;
2835 if (outputfiles.Contains(obj->GetName())) continue;
2836 if (sextra.Contains(obj->GetName())) continue;
2837 if (!sextra.IsNull()) sextra += ",";
2838 sextra += obj->GetName();
2841 if (stype.Contains("ext")) {
2842 if (!files.IsNull()) files += ",";
2846 if (stype == "ext") return files.Data();
2848 if (!fTerminateFiles.IsNull()) {
2849 fTerminateFiles.Strip();
2850 fTerminateFiles.ReplaceAll(" ",",");
2851 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2852 TIter nextx(fextra);
2854 while ((obj=nextx())) {
2855 if (aodfiles.Contains(obj->GetName())) continue;
2856 if (outputfiles.Contains(obj->GetName())) continue;
2857 if (termfiles.Contains(obj->GetName())) continue;
2858 if (sextra.Contains(obj->GetName())) continue;
2859 if (!termfiles.IsNull()) termfiles += ",";
2860 termfiles += obj->GetName();
2864 if (stype.Contains("ter")) {
2865 if (!files.IsNull() && !termfiles.IsNull()) {
2870 return files.Data();
2873 //______________________________________________________________________________
2874 Bool_t AliAnalysisAlien::Submit()
2876 // Submit all master jobs.
2877 Int_t nmasterjobs = fInputFiles->GetEntries();
2878 Long_t tshoot = gSystem->Now();
2879 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2880 while (fNsubmitted < nmasterjobs) {
2881 Long_t now = gSystem->Now();
2882 if ((now-tshoot)>30000) {
2884 if (!SubmitNext()) return kFALSE;
2890 //______________________________________________________________________________
2891 Bool_t AliAnalysisAlien::SubmitMerging()
2893 // Submit all merging jobs.
2894 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2895 gGrid->Cd(fGridOutputDir);
2896 TString mergeJDLName = fExecutable;
2897 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2899 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
2902 Int_t ntosubmit = fInputFiles->GetEntries();
2903 for (Int_t i=0; i<ntosubmit; i++) {
2904 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2905 runOutDir.ReplaceAll(".xml", "");
2906 if (fOutputToRunNo) {
2907 // The output directory is the run number
2908 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2909 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2911 if (!fRunNumbers.Length() && !fRunRange[0]) {
2912 // The output directory is the grid outdir
2913 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
2914 runOutDir = fGridOutputDir;
2916 // The output directory is the master number in 3 digits format
2917 printf("### Submitting merging job for master <%03d>\n", i);
2918 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2921 // Check now the number of merging stages.
2922 TObjArray *list = fOutputFiles.Tokenize(",");
2926 while((str=(TObjString*)next())) {
2927 outputFile = str->GetString();
2928 Int_t index = outputFile.Index("@");
2929 if (index > 0) outputFile.Remove(index);
2930 if (!fMergeExcludes.Contains(outputFile)) break;
2933 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2934 if (!done && (i==ntosubmit-1)) return kFALSE;
2935 if (!fRunNumbers.Length() && !fRunRange[0]) break;
2937 if (!ntosubmit) return kTRUE;
2938 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
2939 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
2940 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
2941 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
2942 \n ################################################################################################################");
2943 gSystem->Exec("aliensh");
2947 //______________________________________________________________________________
2948 Bool_t AliAnalysisAlien::SubmitNext()
2950 // Submit next bunch of master jobs if the queue is free. The first master job is
2951 // submitted right away, while the next will not be unless the previous was split.
2952 // The plugin will not submit new master jobs if there are more that 500 jobs in
2954 static Bool_t iscalled = kFALSE;
2955 static Int_t firstmaster = 0;
2956 static Int_t lastmaster = 0;
2957 static Int_t npermaster = 0;
2958 if (iscalled) return kTRUE;
2960 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2961 Int_t ntosubmit = 0;
2964 Int_t nmasterjobs = fInputFiles->GetEntries();
2967 if (!IsUseSubmitPolicy()) {
2969 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2970 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2971 ntosubmit = nmasterjobs;
2974 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2975 printf("=== master %d: %s\n", lastmaster, status.Data());
2976 // If last master not split, just return
2977 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2978 // No more than 100 waiting jobs
2979 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2980 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2981 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2982 if (!ntosubmit) ntosubmit = 1;
2983 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2984 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2986 for (Int_t i=0; i<ntosubmit; i++) {
2987 // Submit for a range of enumeration of runs.
2988 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2990 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2991 runOutDir.ReplaceAll(".xml", "");
2993 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2995 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2996 printf("********* %s\n",query.Data());
2997 res = gGrid->Command(query);
2999 TString cjobId1 = res->GetKey(0,"jobId");
3000 if (!cjobId1.Length()) {
3004 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3007 Info("StartAnalysis", "\n_______________________________________________________________________ \
3008 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3009 \n_______________________________________________________________________",
3010 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3013 lastmaster = cjobId1.Atoi();
3014 if (!firstmaster) firstmaster = lastmaster;
3019 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3027 //______________________________________________________________________________
3028 void AliAnalysisAlien::WriteAnalysisFile()
3030 // Write current analysis manager into the file <analysisFile>
3031 TString analysisFile = fExecutable;
3032 analysisFile.ReplaceAll(".sh", ".root");
3033 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3034 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3035 if (!mgr || !mgr->IsInitialized()) {
3036 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3039 // Check analysis type
3041 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3042 handler = (TObject*)mgr->GetInputEventHandler();
3044 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3045 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3046 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3047 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3049 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3050 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3053 TDirectory *cdir = gDirectory;
3054 TFile *file = TFile::Open(analysisFile, "RECREATE");
3056 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3057 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3058 // Unless merging makes no sense
3059 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3062 // Enable termination for local jobs
3063 mgr->SetSkipTerminate(kFALSE);
3065 if (cdir) cdir->cd();
3066 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3068 Bool_t copy = kTRUE;
3069 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3072 TString workdir = gGrid->GetHomeDirectory();
3073 workdir += fGridWorkingDir;
3074 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3075 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3076 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
3080 //______________________________________________________________________________
3081 void AliAnalysisAlien::WriteAnalysisMacro()
3083 // Write the analysis macro that will steer the analysis in grid mode.
3084 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3086 out.open(fAnalysisMacro.Data(), ios::out);
3088 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3091 Bool_t hasSTEERBase = kFALSE;
3092 Bool_t hasESD = kFALSE;
3093 Bool_t hasAOD = kFALSE;
3094 Bool_t hasANALYSIS = kFALSE;
3095 Bool_t hasOADB = kFALSE;
3096 Bool_t hasANALYSISalice = kFALSE;
3097 Bool_t hasCORRFW = kFALSE;
3098 TString func = fAnalysisMacro;
3099 TString type = "ESD";
3100 TString comment = "// Analysis using ";
3101 if (IsUseMCchain()) {
3105 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3106 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3111 if (type!="AOD" && fFriendChainName!="") {
3112 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3115 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3116 else comment += " data";
3117 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3118 func.ReplaceAll(".C", "");
3119 out << "void " << func.Data() << "()" << endl;
3121 out << comment.Data() << endl;
3122 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3123 out << " TStopwatch timer;" << endl;
3124 out << " timer.Start();" << endl << endl;
3125 // Change temp directory to current one
3126 out << "// Set temporary merging directory to current one" << endl;
3127 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3128 out << "// Set temporary compilation directory to current one" << endl;
3129 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3130 // Reset existing include path
3131 out << "// Reset existing include path and add current directory first in the search" << endl;
3132 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3133 if (!fExecutableCommand.Contains("aliroot")) {
3134 out << "// load base root libraries" << endl;
3135 out << " gSystem->Load(\"libTree\");" << endl;
3136 out << " gSystem->Load(\"libGeom\");" << endl;
3137 out << " gSystem->Load(\"libVMC\");" << endl;
3138 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3139 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3141 if (fAdditionalRootLibs.Length()) {
3142 // in principle libtree /lib geom libvmc etc. can go into this list, too
3143 out << "// Add aditional libraries" << endl;
3144 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3147 while((str=(TObjString*)next())) {
3148 if (str->GetString().Contains(".so"))
3149 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3151 if (list) delete list;
3153 out << "// Load analysis framework libraries" << endl;
3154 TString setupPar = "AliAnalysisAlien::SetupPar";
3156 if (!fExecutableCommand.Contains("aliroot")) {
3157 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3158 out << " gSystem->Load(\"libESD\");" << endl;
3159 out << " gSystem->Load(\"libAOD\");" << endl;
3161 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3162 out << " gSystem->Load(\"libOADB\");" << endl;
3163 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3164 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3166 TIter next(fPackages);
3169 while ((obj=next())) {
3170 pkgname = obj->GetName();
3171 if (pkgname == "STEERBase" ||
3172 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3173 if (pkgname == "ESD" ||
3174 pkgname == "ESD.par") hasESD = kTRUE;
3175 if (pkgname == "AOD" ||
3176 pkgname == "AOD.par") hasAOD = kTRUE;
3177 if (pkgname == "ANALYSIS" ||
3178 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3179 if (pkgname == "OADB" ||
3180 pkgname == "OADB.par") hasOADB = kTRUE;
3181 if (pkgname == "ANALYSISalice" ||
3182 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3183 if (pkgname == "CORRFW" ||
3184 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3186 if (hasANALYSISalice) setupPar = "SetupPar";
3187 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3188 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3189 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3190 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3191 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3192 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3193 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3194 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3195 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3196 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3197 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3198 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3199 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3200 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3201 out << "// Compile other par packages" << endl;
3203 while ((obj=next())) {
3204 pkgname = obj->GetName();
3205 if (pkgname == "STEERBase" ||
3206 pkgname == "STEERBase.par" ||
3208 pkgname == "ESD.par" ||
3210 pkgname == "AOD.par" ||
3211 pkgname == "ANALYSIS" ||
3212 pkgname == "ANALYSIS.par" ||
3213 pkgname == "OADB" ||
3214 pkgname == "OADB.par" ||
3215 pkgname == "ANALYSISalice" ||
3216 pkgname == "ANALYSISalice.par" ||
3217 pkgname == "CORRFW" ||
3218 pkgname == "CORRFW.par") continue;
3219 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3222 out << "// include path" << endl;
3223 // Get the include path from the interpreter and remove entries pointing to AliRoot
3224 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3225 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3226 out << " TIter nextpath(listpaths);" << endl;
3227 out << " TObjString *pname;" << endl;
3228 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3229 out << " TString current = pname->GetName();" << endl;
3230 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3231 out << " gSystem->AddIncludePath(current);" << endl;
3232 out << " }" << endl;
3233 out << " if (listpaths) delete listpaths;" << endl;
3234 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3235 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3236 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3237 if (fAdditionalLibs.Length()) {
3238 out << "// Add aditional AliRoot libraries" << endl;
3239 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3242 while((str=(TObjString*)next())) {
3243 if (str->GetString().Contains(".so"))
3244 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3245 if (str->GetString().Contains(".par"))
3246 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3248 if (list) delete list;
3251 out << "// analysis source to be compiled at runtime (if any)" << endl;
3252 if (fAnalysisSource.Length()) {
3253 TObjArray *list = fAnalysisSource.Tokenize(" ");
3256 while((str=(TObjString*)next())) {
3257 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3259 if (list) delete list;
3262 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3263 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3264 if (fFastReadOption) {
3265 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 !!! \
3266 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3267 out << "// fast xrootd reading enabled" << endl;
3268 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3269 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3270 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3271 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3272 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3273 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3275 out << "// connect to AliEn and make the chain" << endl;
3276 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3277 out << "// read the analysis manager from file" << endl;
3278 TString analysisFile = fExecutable;
3279 analysisFile.ReplaceAll(".sh", ".root");
3280 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3281 out << " if (!file) return;" << endl;
3282 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3283 out << " AliAnalysisManager *mgr = 0;" << endl;
3284 out << " TKey *key;" << endl;
3285 out << " while ((key=(TKey*)nextkey())) {" << endl;
3286 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3287 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3288 out << " };" << endl;
3289 out << " if (!mgr) {" << endl;
3290 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3291 out << " return;" << endl;
3292 out << " }" << endl << endl;
3293 out << " mgr->PrintStatus();" << endl;
3294 if (AliAnalysisManager::GetAnalysisManager()) {
3295 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3296 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3298 if (TestBit(AliAnalysisGrid::kTest))
3299 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3301 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3304 if (IsUsingTags()) {
3305 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3307 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3309 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3310 out << " timer.Stop();" << endl;
3311 out << " timer.Print();" << endl;
3312 out << "}" << endl << endl;
3313 if (IsUsingTags()) {
3314 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3316 out << "// Create a chain using tags from the xml file." << endl;
3317 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3318 out << " if (!coll) {" << endl;
3319 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3320 out << " return NULL;" << endl;
3321 out << " }" << endl;
3322 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3323 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3324 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3325 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3326 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3327 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3328 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3329 out << " // Check if the cuts configuration file was provided" << endl;
3330 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3331 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3332 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3333 out << " }" << endl;
3334 if (fFriendChainName=="") {
3335 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3337 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3338 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3339 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3341 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3342 out << " chain->ls();" << endl;
3343 out << " return chain;" << endl;
3344 out << "}" << endl << endl;
3345 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3346 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3347 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3348 msg += " AliLHCTagCuts *lhcCuts,\n";
3349 msg += " AliDetectorTagCuts *detCuts,\n";
3350 msg += " AliEventTagCuts *evCuts)";
3351 Info("WriteAnalysisMacro", "%s", msg.Data());
3354 if (!IsUsingTags() || fFriendChainName!="") {
3355 out <<"//________________________________________________________________________________" << endl;
3356 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3358 out << "// Create a chain using url's from xml file" << endl;
3359 out << " TString filename;" << endl;
3360 out << " Int_t run = 0;" << endl;
3361 if (IsUseMCchain()) {
3362 out << " TString treename = \"TE\";" << endl;
3364 out << " TString treename = type;" << endl;
3365 out << " treename.ToLower();" << endl;
3366 out << " treename += \"Tree\";" << endl;
3368 out << " printf(\"***************************************\\n\");" << endl;
3369 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3370 out << " printf(\"***************************************\\n\");" << endl;
3371 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3372 out << " if (!coll) {" << endl;
3373 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3374 out << " return NULL;" << endl;
3375 out << " }" << endl;
3376 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3377 out << " TChain *chain = new TChain(treename);" << endl;
3378 if(fFriendChainName!="") {
3379 out << " TChain *chainFriend = new TChain(treename);" << endl;
3381 out << " coll->Reset();" << endl;
3382 out << " while (coll->Next()) {" << endl;
3383 out << " filename = coll->GetTURL("");" << endl;
3384 out << " if (mgr) {" << endl;
3385 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3386 out << " if (nrun && nrun != run) {" << endl;
3387 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3388 out << " mgr->SetRunFromPath(nrun);" << endl;
3389 out << " run = nrun;" << endl;
3390 out << " }" << endl;
3391 out << " }" << endl;
3392 out << " chain->Add(filename);" << endl;
3393 if(fFriendChainName!="") {
3394 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3395 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3396 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3397 out << " chainFriend->Add(fileFriend.Data());" << endl;
3399 out << " }" << endl;
3400 out << " if (!chain->GetNtrees()) {" << endl;
3401 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3402 out << " return NULL;" << endl;
3403 out << " }" << endl;
3404 if(fFriendChainName!="") {
3405 out << " chain->AddFriend(chainFriend);" << endl;
3407 out << " return chain;" << endl;
3408 out << "}" << endl << endl;
3410 if (hasANALYSISalice) {
3411 out <<"//________________________________________________________________________________" << endl;
3412 out << "Bool_t SetupPar(const char *package) {" << endl;
3413 out << "// Compile the package and set it up." << endl;
3414 out << " TString pkgdir = package;" << endl;
3415 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3416 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3417 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3418 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3419 out << " // Check for BUILD.sh and execute" << endl;
3420 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3421 out << " printf(\"*******************************\\n\");" << endl;
3422 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3423 out << " printf(\"*******************************\\n\");" << endl;
3424 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3425 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3426 out << " gSystem->ChangeDirectory(cdir);" << endl;
3427 out << " return kFALSE;" << endl;
3428 out << " }" << endl;
3429 out << " } else {" << endl;
3430 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3431 out << " gSystem->ChangeDirectory(cdir);" << endl;
3432 out << " return kFALSE;" << endl;
3433 out << " }" << endl;
3434 out << " // Check for SETUP.C and execute" << endl;
3435 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3436 out << " printf(\"*******************************\\n\");" << endl;
3437 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3438 out << " printf(\"*******************************\\n\");" << endl;
3439 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3440 out << " } else {" << endl;
3441 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3442 out << " gSystem->ChangeDirectory(cdir);" << endl;
3443 out << " return kFALSE;" << endl;
3444 out << " }" << endl;
3445 out << " // Restore original workdir" << endl;
3446 out << " gSystem->ChangeDirectory(cdir);" << endl;
3447 out << " return kTRUE;" << endl;
3450 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3452 Bool_t copy = kTRUE;
3453 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3456 TString workdir = gGrid->GetHomeDirectory();
3457 workdir += fGridWorkingDir;
3458 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3459 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3460 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3461 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3462 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3464 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3465 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3469 //______________________________________________________________________________
3470 void AliAnalysisAlien::WriteMergingMacro()
3472 // Write a macro to merge the outputs per master job.
3473 if (!fMergeViaJDL) return;
3474 if (!fOutputFiles.Length()) {
3475 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3478 TString mergingMacro = fExecutable;
3479 mergingMacro.ReplaceAll(".sh","_merge.C");
3480 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3481 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3483 out.open(mergingMacro.Data(), ios::out);
3485 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3488 Bool_t hasSTEERBase = kFALSE;
3489 Bool_t hasESD = kFALSE;
3490 Bool_t hasAOD = kFALSE;
3491 Bool_t hasANALYSIS = kFALSE;
3492 Bool_t hasOADB = kFALSE;
3493 Bool_t hasANALYSISalice = kFALSE;
3494 Bool_t hasCORRFW = kFALSE;
3495 TString func = mergingMacro;
3497 func.ReplaceAll(".C", "");
3498 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3500 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3501 out << " TStopwatch timer;" << endl;
3502 out << " timer.Start();" << endl << endl;
3503 // Reset existing include path
3504 out << "// Reset existing include path and add current directory first in the search" << endl;
3505 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3506 if (!fExecutableCommand.Contains("aliroot")) {
3507 out << "// load base root libraries" << endl;
3508 out << " gSystem->Load(\"libTree\");" << endl;
3509 out << " gSystem->Load(\"libGeom\");" << endl;
3510 out << " gSystem->Load(\"libVMC\");" << endl;
3511 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3512 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3514 if (fAdditionalRootLibs.Length()) {
3515 // in principle libtree /lib geom libvmc etc. can go into this list, too
3516 out << "// Add aditional libraries" << endl;
3517 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3520 while((str=(TObjString*)next())) {
3521 if (str->GetString().Contains(".so"))
3522 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3524 if (list) delete list;
3526 out << "// Load analysis framework libraries" << endl;
3528 if (!fExecutableCommand.Contains("aliroot")) {
3529 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3530 out << " gSystem->Load(\"libESD\");" << endl;
3531 out << " gSystem->Load(\"libAOD\");" << endl;
3533 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3534 out << " gSystem->Load(\"libOADB\");" << endl;
3535 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3536 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3538 TIter next(fPackages);
3541 TString setupPar = "AliAnalysisAlien::SetupPar";
3542 while ((obj=next())) {
3543 pkgname = obj->GetName();
3544 if (pkgname == "STEERBase" ||
3545 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3546 if (pkgname == "ESD" ||
3547 pkgname == "ESD.par") hasESD = kTRUE;
3548 if (pkgname == "AOD" ||
3549 pkgname == "AOD.par") hasAOD = kTRUE;
3550 if (pkgname == "ANALYSIS" ||
3551 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3552 if (pkgname == "OADB" ||
3553 pkgname == "OADB.par") hasOADB = kTRUE;
3554 if (pkgname == "ANALYSISalice" ||
3555 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3556 if (pkgname == "CORRFW" ||
3557 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3559 if (hasANALYSISalice) setupPar = "SetupPar";
3560 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3561 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3562 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3563 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3564 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3565 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3566 out << " gSystem->Load(\"libOADB\");" << endl;
3567 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3568 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3569 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3570 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3571 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3572 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3573 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3574 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3575 out << "// Compile other par packages" << endl;
3577 while ((obj=next())) {
3578 pkgname = obj->GetName();
3579 if (pkgname == "STEERBase" ||
3580 pkgname == "STEERBase.par" ||
3582 pkgname == "ESD.par" ||
3584 pkgname == "AOD.par" ||
3585 pkgname == "ANALYSIS" ||
3586 pkgname == "ANALYSIS.par" ||
3587 pkgname == "OADB" ||
3588 pkgname == "OADB.par" ||
3589 pkgname == "ANALYSISalice" ||
3590 pkgname == "ANALYSISalice.par" ||
3591 pkgname == "CORRFW" ||
3592 pkgname == "CORRFW.par") continue;
3593 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3596 out << "// include path" << endl;
3597 // Get the include path from the interpreter and remove entries pointing to AliRoot
3598 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3599 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3600 out << " TIter nextpath(listpaths);" << endl;
3601 out << " TObjString *pname;" << endl;
3602 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3603 out << " TString current = pname->GetName();" << endl;
3604 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3605 out << " gSystem->AddIncludePath(current);" << endl;
3606 out << " }" << endl;
3607 out << " if (listpaths) delete listpaths;" << endl;
3608 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3609 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3610 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3611 if (fAdditionalLibs.Length()) {
3612 out << "// Add aditional AliRoot libraries" << endl;
3613 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3616 while((str=(TObjString*)next())) {
3617 if (str->GetString().Contains(".so"))
3618 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3620 if (list) delete list;
3623 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3624 if (fAnalysisSource.Length()) {
3625 TObjArray *list = fAnalysisSource.Tokenize(" ");
3628 while((str=(TObjString*)next())) {
3629 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3631 if (list) delete list;
3635 if (fFastReadOption) {
3636 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 !!!");
3637 out << "// fast xrootd reading enabled" << endl;
3638 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3639 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3640 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3641 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3642 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3643 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3645 // Change temp directory to current one
3646 out << "// Set temporary merging directory to current one" << endl;
3647 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3648 out << "// Set temporary compilation directory to current one" << endl;
3649 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3650 out << "// Connect to AliEn" << endl;
3651 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3652 out << " TString outputDir = dir;" << endl;
3653 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3654 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3655 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3656 out << " TIter *iter = new TIter(list);" << endl;
3657 out << " TObjString *str;" << endl;
3658 out << " TString outputFile;" << endl;
3659 out << " Bool_t merged = kTRUE;" << endl;
3660 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3661 out << " outputFile = str->GetString();" << endl;
3662 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3663 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3664 out << " if (index > 0) outputFile.Remove(index);" << endl;
3665 out << " // Skip already merged outputs" << endl;
3666 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3667 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3668 out << " continue;" << endl;
3669 out << " }" << endl;
3670 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3671 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3672 out << " if (!merged) {" << endl;
3673 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3674 out << " return;" << endl;
3675 out << " }" << endl;
3676 out << " }" << endl;
3677 out << " // all outputs merged, validate" << endl;
3678 out << " ofstream out;" << endl;
3679 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3680 out << " out.close();" << endl;
3681 out << " // read the analysis manager from file" << endl;
3682 TString analysisFile = fExecutable;
3683 analysisFile.ReplaceAll(".sh", ".root");
3684 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3685 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3686 out << " if (!file) return;" << endl;
3687 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3688 out << " AliAnalysisManager *mgr = 0;" << endl;
3689 out << " TKey *key;" << endl;
3690 out << " while ((key=(TKey*)nextkey())) {" << endl;
3691 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3692 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3693 out << " };" << endl;
3694 out << " if (!mgr) {" << endl;
3695 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3696 out << " return;" << endl;
3697 out << " }" << endl << endl;
3698 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3699 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3700 out << " mgr->PrintStatus();" << endl;
3701 if (AliAnalysisManager::GetAnalysisManager()) {
3702 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3703 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3705 if (TestBit(AliAnalysisGrid::kTest))
3706 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3708 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3711 out << " TTree *tree = NULL;" << endl;
3712 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3713 out << "}" << endl << endl;
3714 if (hasANALYSISalice) {
3715 out <<"//________________________________________________________________________________" << endl;
3716 out << "Bool_t SetupPar(const char *package) {" << endl;
3717 out << "// Compile the package and set it up." << endl;
3718 out << " TString pkgdir = package;" << endl;
3719 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3720 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3721 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3722 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3723 out << " // Check for BUILD.sh and execute" << endl;
3724 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3725 out << " printf(\"*******************************\\n\");" << endl;
3726 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3727 out << " printf(\"*******************************\\n\");" << endl;
3728 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3729 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3730 out << " gSystem->ChangeDirectory(cdir);" << endl;
3731 out << " return kFALSE;" << endl;
3732 out << " }" << endl;
3733 out << " } else {" << endl;
3734 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3735 out << " gSystem->ChangeDirectory(cdir);" << endl;
3736 out << " return kFALSE;" << endl;
3737 out << " }" << endl;
3738 out << " // Check for SETUP.C and execute" << endl;
3739 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3740 out << " printf(\"*******************************\\n\");" << endl;
3741 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3742 out << " printf(\"*******************************\\n\");" << endl;
3743 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3744 out << " } else {" << endl;
3745 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3746 out << " gSystem->ChangeDirectory(cdir);" << endl;
3747 out << " return kFALSE;" << endl;
3748 out << " }" << endl;
3749 out << " // Restore original workdir" << endl;
3750 out << " gSystem->ChangeDirectory(cdir);" << endl;
3751 out << " return kTRUE;" << endl;
3755 Bool_t copy = kTRUE;
3756 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3759 TString workdir = gGrid->GetHomeDirectory();
3760 workdir += fGridWorkingDir;
3761 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3762 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3763 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3767 //______________________________________________________________________________
3768 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3770 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3771 // Note that for loading the compiled library. The current directory should have precedence in
3773 TString pkgdir = package;
3774 pkgdir.ReplaceAll(".par","");
3775 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3776 TString cdir = gSystem->WorkingDirectory();
3777 gSystem->ChangeDirectory(pkgdir);
3778 // Check for BUILD.sh and execute
3779 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3780 printf("**************************************************\n");
3781 printf("*** Building PAR archive %s\n", package);
3782 printf("**************************************************\n");
3783 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3784 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3785 gSystem->ChangeDirectory(cdir);
3789 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3790 gSystem->ChangeDirectory(cdir);
3793 // Check for SETUP.C and execute
3794 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3795 printf("**************************************************\n");
3796 printf("*** Setup PAR archive %s\n", package);
3797 printf("**************************************************\n");
3798 gROOT->Macro("PROOF-INF/SETUP.C");
3799 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3801 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3802 gSystem->ChangeDirectory(cdir);
3805 // Restore original workdir
3806 gSystem->ChangeDirectory(cdir);
3810 //______________________________________________________________________________
3811 void AliAnalysisAlien::WriteExecutable()
3813 // Generate the alien executable script.
3814 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3816 out.open(fExecutable.Data(), ios::out);
3818 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3821 out << "#!/bin/bash" << endl;
3822 // Make sure we can properly compile par files
3823 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3824 out << "echo \"=========================================\"" << endl;
3825 out << "echo \"############## PATH : ##############\"" << endl;
3826 out << "echo $PATH" << endl;
3827 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3828 out << "echo $LD_LIBRARY_PATH" << endl;
3829 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3830 out << "echo $ROOTSYS" << endl;
3831 out << "echo \"############## which root : ##############\"" << endl;
3832 out << "which root" << endl;
3833 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3834 out << "echo $ALICE_ROOT" << endl;
3835 out << "echo \"############## which aliroot : ##############\"" << endl;
3836 out << "which aliroot" << endl;
3837 out << "echo \"############## system limits : ##############\"" << endl;
3838 out << "ulimit -a" << endl;
3839 out << "echo \"############## memory : ##############\"" << endl;
3840 out << "free -m" << endl;
3841 out << "echo \"=========================================\"" << endl << endl;
3842 out << fExecutableCommand << " ";
3843 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3844 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3845 out << "echo \"############## memory after: ##############\"" << endl;
3846 out << "free -m" << endl;
3848 Bool_t copy = kTRUE;
3849 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3852 TString workdir = gGrid->GetHomeDirectory();
3853 TString bindir = Form("%s/bin", workdir.Data());
3854 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3855 workdir += fGridWorkingDir;
3856 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3857 if (FileExists(executable)) gGrid->Rm(executable);
3858 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3859 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3863 //______________________________________________________________________________
3864 void AliAnalysisAlien::WriteMergeExecutable()
3866 // Generate the alien executable script for the merging job.
3867 if (!fMergeViaJDL) return;
3868 TString mergeExec = fExecutable;
3869 mergeExec.ReplaceAll(".sh", "_merge.sh");
3870 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3872 out.open(mergeExec.Data(), ios::out);
3874 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3877 out << "#!/bin/bash" << endl;
3878 // Make sure we can properly compile par files
3879 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3880 out << "echo \"=========================================\"" << endl;
3881 out << "echo \"############## PATH : ##############\"" << endl;
3882 out << "echo $PATH" << endl;
3883 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3884 out << "echo $LD_LIBRARY_PATH" << endl;
3885 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3886 out << "echo $ROOTSYS" << endl;
3887 out << "echo \"############## which root : ##############\"" << endl;
3888 out << "which root" << endl;
3889 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3890 out << "echo $ALICE_ROOT" << endl;
3891 out << "echo \"############## which aliroot : ##############\"" << endl;
3892 out << "which aliroot" << endl;
3893 out << "echo \"############## system limits : ##############\"" << endl;
3894 out << "ulimit -a" << endl;
3895 out << "echo \"############## memory : ##############\"" << endl;
3896 out << "free -m" << endl;
3897 out << "echo \"=========================================\"" << endl << endl;
3898 TString mergeMacro = fExecutable;
3899 mergeMacro.ReplaceAll(".sh", "_merge.C");
3900 if (IsOneStageMerging())
3901 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3903 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3904 out << fExecutableCommand << " " << "$ARG" << endl;
3905 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3906 out << "echo \"############## memory after: ##############\"" << endl;
3907 out << "free -m" << endl;
3909 Bool_t copy = kTRUE;
3910 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3913 TString workdir = gGrid->GetHomeDirectory();
3914 TString bindir = Form("%s/bin", workdir.Data());
3915 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3916 workdir += fGridWorkingDir;
3917 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3918 if (FileExists(executable)) gGrid->Rm(executable);
3919 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3920 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3924 //______________________________________________________________________________
3925 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3927 // Write the production file to be submitted by LPM manager. The format is:
3928 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3929 // Next lines: full_path_to_dataset XXX (XXX is a string)
3930 // To submit, one has to: submit jdl XXX for all lines
3932 out.open(filename, ios::out);
3934 Error("WriteProductionFile", "Bad file name: %s", filename);
3938 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3939 workdir = gGrid->GetHomeDirectory();
3940 workdir += fGridWorkingDir;
3941 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3942 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3943 out << locjdl << " " << njobspermaster << endl;
3944 Int_t nmasterjobs = fInputFiles->GetEntries();
3945 for (Int_t i=0; i<nmasterjobs; i++) {
3946 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3947 runOutDir.ReplaceAll(".xml", "");
3949 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3951 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3954 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3955 if (FileExists(filename)) gGrid->Rm(filename);
3956 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3960 //______________________________________________________________________________
3961 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3963 // Generate the alien validation script.
3964 // Generate the validation script
3966 if (fValidationScript.IsNull()) {
3967 fValidationScript = fExecutable;
3968 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3970 TString validationScript = fValidationScript;
3971 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3973 Error("WriteValidationScript", "Alien connection required");
3976 if (!fTerminateFiles.IsNull()) {
3977 fTerminateFiles.Strip();
3978 fTerminateFiles.ReplaceAll(" ",",");
3980 TString outStream = "";
3981 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3982 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3984 out.open(validationScript, ios::out);
3985 out << "#!/bin/bash" << endl;
3986 out << "##################################################" << endl;
3987 out << "validateout=`dirname $0`" << endl;
3988 out << "validatetime=`date`" << endl;
3989 out << "validated=\"0\";" << endl;
3990 out << "error=0" << endl;
3991 out << "if [ -z $validateout ]" << endl;
3992 out << "then" << endl;
3993 out << " validateout=\".\"" << endl;
3994 out << "fi" << endl << endl;
3995 out << "cd $validateout;" << endl;
3996 out << "validateworkdir=`pwd`;" << endl << endl;
3997 out << "echo \"*******************************************************\"" << outStream << endl;
3998 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4000 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4001 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4002 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4003 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4004 out << "ls -la ./" << outStream << endl;
4005 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4006 out << "##################################################" << endl;
4009 out << "if [ ! -f stderr ] ; then" << endl;
4010 out << " error=1" << endl;
4011 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4012 out << " echo \"Error = $error\" " << outStream << endl;
4013 out << "fi" << endl;
4015 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4016 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4017 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4018 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4021 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4022 out << " error=1" << endl;
4023 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4024 out << " echo \"$parArch\" " << outStream << endl;
4025 out << " echo \"Error = $error\" " << outStream << endl;
4026 out << "fi" << endl;
4028 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4029 out << " error=1" << endl;
4030 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4031 out << " echo \"$segViol\" " << outStream << endl;
4032 out << " echo \"Error = $error\" " << outStream << endl;
4033 out << "fi" << endl;
4035 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4036 out << " error=1" << endl;
4037 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4038 out << " echo \"$segFault\" " << outStream << endl;
4039 out << " echo \"Error = $error\" " << outStream << endl;
4040 out << "fi" << endl;
4042 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4043 out << " error=1" << endl;
4044 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4045 out << " echo \"$glibcErr\" " << outStream << endl;
4046 out << " echo \"Error = $error\" " << outStream << endl;
4047 out << "fi" << endl;
4049 // Part dedicated to the specific analyses running into the train
4051 TString outputFiles = fOutputFiles;
4052 if (merge && !fTerminateFiles.IsNull()) {
4054 outputFiles += fTerminateFiles;
4056 TObjArray *arr = outputFiles.Tokenize(",");
4059 while (!merge && (os=(TObjString*)next1())) {
4060 // No need to validate outputs produced by merging since the merging macro does this
4061 outputFile = os->GetString();
4062 Int_t index = outputFile.Index("@");
4063 if (index > 0) outputFile.Remove(index);
4064 if (fTerminateFiles.Contains(outputFile)) continue;
4065 if (outputFile.Contains("*")) continue;
4066 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4067 out << " error=1" << endl;
4068 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4069 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4070 out << "fi" << endl;
4073 out << "if ! [ -f outputs_valid ] ; then" << endl;
4074 out << " error=1" << endl;
4075 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4076 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4077 out << "fi" << endl;
4079 out << "if [ $error = 0 ] ; then" << endl;
4080 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4081 if (!IsKeepLogs()) {
4082 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4084 out << " rm -f std*" << endl;
4086 out << "fi" << endl;
4088 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4089 out << "echo \"*******************************************************\"" << outStream << endl;
4090 out << "cd -" << endl;
4091 out << "exit $error" << endl;
4093 Bool_t copy = kTRUE;
4094 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4097 TString workdir = gGrid->GetHomeDirectory();
4098 workdir += fGridWorkingDir;
4099 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4100 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4101 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));