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