1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "Riostream.h"
29 #include "TObjString.h"
30 #include "TObjArray.h"
32 #include "TGridResult.h"
33 #include "TGridCollection.h"
35 #include "TGridJobStatusList.h"
36 #include "TGridJobStatus.h"
37 #include "TFileMerger.h"
38 #include "AliAnalysisManager.h"
39 #include "AliVEventHandler.h"
40 #include "AliAnalysisDataContainer.h"
41 #include "AliAnalysisAlien.h"
43 ClassImp(AliAnalysisAlien)
45 //______________________________________________________________________________
46 AliAnalysisAlien::AliAnalysisAlien()
52 fSplitMaxInputFileNumber(0),
54 fMasterResubmitThreshold(0),
72 fAdditionalRootLibs(),
103 //______________________________________________________________________________
104 AliAnalysisAlien::AliAnalysisAlien(const char *name)
105 :AliAnalysisGrid(name),
110 fSplitMaxInputFileNumber(0),
112 fMasterResubmitThreshold(0),
125 fExecutableCommand(),
130 fAdditionalRootLibs(),
161 //______________________________________________________________________________
162 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
163 :AliAnalysisGrid(other),
166 fPrice(other.fPrice),
168 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
169 fMaxInitFailed(other.fMaxInitFailed),
170 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
171 fNtestFiles(other.fNtestFiles),
172 fNrunsPerMaster(other.fNrunsPerMaster),
173 fMaxMergeFiles(other.fMaxMergeFiles),
174 fNsubmitted(other.fNsubmitted),
175 fProductionMode(other.fProductionMode),
176 fOutputToRunNo(other.fOutputToRunNo),
177 fMergeViaJDL(other.fMergeViaJDL),
178 fFastReadOption(other.fFastReadOption),
179 fOverwriteMode(other.fOverwriteMode),
180 fNreplicas(other.fNreplicas),
181 fRunNumbers(other.fRunNumbers),
182 fExecutable(other.fExecutable),
183 fExecutableCommand(other.fExecutableCommand),
184 fArguments(other.fArguments),
185 fExecutableArgs(other.fExecutableArgs),
186 fAnalysisMacro(other.fAnalysisMacro),
187 fAnalysisSource(other.fAnalysisSource),
188 fAdditionalRootLibs(other.fAdditionalRootLibs),
189 fAdditionalLibs(other.fAdditionalLibs),
190 fSplitMode(other.fSplitMode),
191 fAPIVersion(other.fAPIVersion),
192 fROOTVersion(other.fROOTVersion),
193 fAliROOTVersion(other.fAliROOTVersion),
194 fExternalPackages(other.fExternalPackages),
196 fGridWorkingDir(other.fGridWorkingDir),
197 fGridDataDir(other.fGridDataDir),
198 fDataPattern(other.fDataPattern),
199 fGridOutputDir(other.fGridOutputDir),
200 fOutputArchive(other.fOutputArchive),
201 fOutputFiles(other.fOutputFiles),
202 fInputFormat(other.fInputFormat),
203 fDatasetName(other.fDatasetName),
204 fJDLName(other.fJDLName),
205 fMergeExcludes(other.fMergeExcludes),
206 fIncludePath(other.fIncludePath),
207 fCloseSE(other.fCloseSE),
208 fFriendChainName(other.fFriendChainName),
209 fJobTag(other.fJobTag),
210 fOutputSingle(other.fOutputSingle),
211 fRunPrefix(other.fRunPrefix),
216 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
217 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
218 fRunRange[0] = other.fRunRange[0];
219 fRunRange[1] = other.fRunRange[1];
220 if (other.fInputFiles) {
221 fInputFiles = new TObjArray();
222 TIter next(other.fInputFiles);
224 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
225 fInputFiles->SetOwner();
227 if (other.fPackages) {
228 fPackages = new TObjArray();
229 TIter next(other.fPackages);
231 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
232 fPackages->SetOwner();
236 //______________________________________________________________________________
237 AliAnalysisAlien::~AliAnalysisAlien()
240 if (fGridJDL) delete fGridJDL;
241 if (fMergingJDL) delete fMergingJDL;
242 if (fInputFiles) delete fInputFiles;
243 if (fPackages) delete fPackages;
246 //______________________________________________________________________________
247 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
250 if (this != &other) {
251 AliAnalysisGrid::operator=(other);
252 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
253 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
254 fPrice = other.fPrice;
256 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
257 fMaxInitFailed = other.fMaxInitFailed;
258 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
259 fNtestFiles = other.fNtestFiles;
260 fNrunsPerMaster = other.fNrunsPerMaster;
261 fMaxMergeFiles = other.fMaxMergeFiles;
262 fNsubmitted = other.fNsubmitted;
263 fProductionMode = other.fProductionMode;
264 fOutputToRunNo = other.fOutputToRunNo;
265 fMergeViaJDL = other.fMergeViaJDL;
266 fFastReadOption = other.fFastReadOption;
267 fOverwriteMode = other.fOverwriteMode;
268 fNreplicas = other.fNreplicas;
269 fRunNumbers = other.fRunNumbers;
270 fExecutable = other.fExecutable;
271 fExecutableCommand = other.fExecutableCommand;
272 fArguments = other.fArguments;
273 fExecutableArgs = other.fExecutableArgs;
274 fAnalysisMacro = other.fAnalysisMacro;
275 fAnalysisSource = other.fAnalysisSource;
276 fAdditionalRootLibs = other.fAdditionalRootLibs;
277 fAdditionalLibs = other.fAdditionalLibs;
278 fSplitMode = other.fSplitMode;
279 fAPIVersion = other.fAPIVersion;
280 fROOTVersion = other.fROOTVersion;
281 fAliROOTVersion = other.fAliROOTVersion;
282 fExternalPackages = other.fExternalPackages;
284 fGridWorkingDir = other.fGridWorkingDir;
285 fGridDataDir = other.fGridDataDir;
286 fDataPattern = other.fDataPattern;
287 fGridOutputDir = other.fGridOutputDir;
288 fOutputArchive = other.fOutputArchive;
289 fOutputFiles = other.fOutputFiles;
290 fInputFormat = other.fInputFormat;
291 fDatasetName = other.fDatasetName;
292 fJDLName = other.fJDLName;
293 fMergeExcludes = other.fMergeExcludes;
294 fIncludePath = other.fIncludePath;
295 fCloseSE = other.fCloseSE;
296 fFriendChainName = other.fFriendChainName;
297 fJobTag = other.fJobTag;
298 fOutputSingle = other.fOutputSingle;
299 fRunPrefix = other.fRunPrefix;
300 if (other.fInputFiles) {
301 fInputFiles = new TObjArray();
302 TIter next(other.fInputFiles);
304 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
305 fInputFiles->SetOwner();
307 if (other.fPackages) {
308 fPackages = new TObjArray();
309 TIter next(other.fPackages);
311 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
312 fPackages->SetOwner();
318 //______________________________________________________________________________
319 void AliAnalysisAlien::AddIncludePath(const char *path)
321 // Add include path in the remote analysis macro.
323 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
324 else fIncludePath += Form("-I%s ", path);
327 //______________________________________________________________________________
328 void AliAnalysisAlien::AddRunNumber(Int_t run)
330 // Add a run number to the list of runs to be processed.
331 if (fRunNumbers.Length()) fRunNumbers += " ";
332 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
335 //______________________________________________________________________________
336 void AliAnalysisAlien::AddRunNumber(const char* run)
338 // Add a run number to the list of runs to be processed.
339 if (fRunNumbers.Length()) fRunNumbers += " ";
343 //______________________________________________________________________________
344 void AliAnalysisAlien::AddDataFile(const char *lfn)
346 // Adds a data file to the input to be analysed. The file should be a valid LFN
347 // or point to an existing file in the alien workdir.
348 if (!fInputFiles) fInputFiles = new TObjArray();
349 fInputFiles->Add(new TObjString(lfn));
352 //______________________________________________________________________________
353 void AliAnalysisAlien::AddExternalPackage(const char *package)
355 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
356 if (fExternalPackages) fExternalPackages += " ";
357 fExternalPackages += package;
360 //______________________________________________________________________________
361 Bool_t AliAnalysisAlien::Connect()
363 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
364 if (gGrid && gGrid->IsConnected()) return kTRUE;
366 Info("Connect", "Trying to connect to AliEn ...");
367 TGrid::Connect("alien://");
369 if (!gGrid || !gGrid->IsConnected()) {
370 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
373 fUser = gGrid->GetUser();
374 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
378 //______________________________________________________________________________
379 void AliAnalysisAlien::CdWork()
381 // Check validity of alien workspace. Create directory if possible.
383 Error("CdWork", "Alien connection required");
386 TString homedir = gGrid->GetHomeDirectory();
387 TString workdir = homedir + fGridWorkingDir;
388 if (DirectoryExists(workdir)) {
392 // Work directory not existing - create it
394 if (gGrid->Mkdir(workdir)) {
395 gGrid->Cd(fGridWorkingDir);
396 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
398 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
399 workdir.Data(), homedir.Data());
400 fGridWorkingDir = "";
404 //______________________________________________________________________________
405 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
407 // Check if file copying is possible.
409 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
412 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
413 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
414 // Check if alien_CLOSE_SE is defined
415 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
416 if (!closeSE.IsNull()) {
417 Info("CheckFileCopy", "Your current close storage is pointing to: \
418 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
420 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
422 // Check if grid directory exists.
423 if (!DirectoryExists(alienpath)) {
424 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
427 TFile f("plugin_test_copy", "RECREATE");
428 // User may not have write permissions to current directory
430 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
431 gSystem->WorkingDirectory());
435 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
436 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
437 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
438 \n# 1. Make sure you have write permissions there. If this is the case: \
439 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
440 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
441 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
442 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
443 gSystem->Unlink(f.GetName());
446 gSystem->Unlink(f.GetName());
447 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
448 Info("CheckFileCopy", "### ...SUCCESS ###");
452 //______________________________________________________________________________
453 Bool_t AliAnalysisAlien::CheckInputData()
455 // Check validity of input data. If necessary, create xml files.
456 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
457 if (!fGridDataDir.Length()) {
458 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
461 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
464 // Process declared files
465 Bool_t isCollection = kFALSE;
466 Bool_t isXml = kFALSE;
467 Bool_t useTags = kFALSE;
468 Bool_t checked = kFALSE;
471 TString workdir = gGrid->GetHomeDirectory();
472 workdir += fGridWorkingDir;
475 TIter next(fInputFiles);
476 while ((objstr=(TObjString*)next())) {
479 file += objstr->GetString();
480 // Store full lfn path
481 if (FileExists(file)) objstr->SetString(file);
483 file = objstr->GetName();
484 if (!FileExists(objstr->GetName())) {
485 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
486 objstr->GetName(), workdir.Data());
490 Bool_t iscoll, isxml, usetags;
491 CheckDataType(file, iscoll, isxml, usetags);
494 isCollection = iscoll;
497 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
499 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
500 Error("CheckInputData", "Some conflict was found in the types of inputs");
506 // Process requested run numbers
507 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
508 // Check validity of alien data directory
509 if (!fGridDataDir.Length()) {
510 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
513 if (!DirectoryExists(fGridDataDir)) {
514 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
518 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
522 if (checked && !isXml) {
523 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
526 // Check validity of run number(s)
530 TString schunk, schunk2;
534 useTags = fDataPattern.Contains("tag");
535 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
537 if (useTags != fDataPattern.Contains("tag")) {
538 Error("CheckInputData", "Cannot mix input files using/not using tags");
541 if (fRunNumbers.Length()) {
542 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
543 arr = fRunNumbers.Tokenize(" ");
545 while ((os=(TObjString*)next())) {
546 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
547 if (!DirectoryExists(path)) {
548 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
551 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
552 TString msg = "\n##### file: ";
554 msg += " type: xml_collection;";
555 if (useTags) msg += " using_tags: Yes";
556 else msg += " using_tags: No";
557 Info("CheckDataType", msg.Data());
558 if (fNrunsPerMaster<2) {
559 AddDataFile(Form("%s.xml", os->GetString().Data()));
562 if (((nruns-1)%fNrunsPerMaster) == 0) {
563 schunk = os->GetString();
565 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
566 schunk += Form("_%s.xml", os->GetString().Data());
572 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
573 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
574 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
575 if (!DirectoryExists(path)) {
576 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
579 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
580 TString msg = "\n##### file: ";
582 msg += " type: xml_collection;";
583 if (useTags) msg += " using_tags: Yes";
584 else msg += " using_tags: No";
585 Info("CheckDataType", msg.Data());
586 if (fNrunsPerMaster<2) {
587 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
590 if (((nruns-1)%fNrunsPerMaster) == 0) {
591 schunk = Form("%s%d", fRunPrefix.Data(),irun);
593 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
594 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
607 //______________________________________________________________________________
608 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
610 // Create dataset for the grid data directory + run number.
611 if (TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
613 Error("CreateDataset", "Cannot create dataset with no grid connection");
619 TString workdir = gGrid->GetHomeDirectory();
620 workdir += fGridWorkingDir;
622 // Compose the 'find' command arguments
624 TString options = "-x collection ";
625 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
626 TString conditions = "";
631 TString schunk, schunk2;
632 TGridCollection *cbase=0, *cadd=0;
633 if (!fRunNumbers.Length() && !fRunRange[0]) {
634 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
635 // Make a single data collection from data directory.
637 if (!DirectoryExists(path)) {
638 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
642 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
643 else file = Form("%s.xml", gSystem->BaseName(path));
644 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
650 command += conditions;
651 printf("command: %s\n", command.Data());
652 TGridResult *res = gGrid->Command(command);
654 // Write standard output to file
655 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
656 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
657 Bool_t nullFile = kFALSE;
659 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
661 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
663 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
668 Bool_t fileExists = FileExists(file);
669 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
670 // Copy xml file to alien space
671 if (fileExists) gGrid->Rm(file);
672 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
673 if (!FileExists(file)) {
674 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
677 // Update list of files to be processed.
679 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
683 Bool_t nullResult = kTRUE;
684 if (fRunNumbers.Length()) {
685 TObjArray *arr = fRunNumbers.Tokenize(" ");
688 while ((os=(TObjString*)next())) {
689 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
690 if (!DirectoryExists(path)) continue;
692 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
693 else file = Form("%s.xml", os->GetString().Data());
694 // If local collection file does not exist, create it via 'find' command.
695 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
700 command += conditions;
701 TGridResult *res = gGrid->Command(command);
703 // Write standard output to file
704 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
705 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
706 Bool_t nullFile = kFALSE;
708 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
710 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
712 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
713 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
719 if (TestBit(AliAnalysisGrid::kTest)) break;
720 // Check if there is one run per master job.
721 if (fNrunsPerMaster<2) {
722 if (FileExists(file)) {
723 if (fOverwriteMode) gGrid->Rm(file);
725 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
729 // Copy xml file to alien space
730 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
731 if (!FileExists(file)) {
732 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
738 if (((nruns-1)%fNrunsPerMaster) == 0) {
739 schunk = os->GetString();
740 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
742 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
743 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
747 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
750 schunk += Form("_%s.xml", os->GetString().Data());
751 if (FileExists(schunk)) {
752 if (fOverwriteMode) gGrid->Rm(file);
754 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
758 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
759 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
760 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
761 if (!FileExists(schunk)) {
762 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
770 Error("CreateDataset", "No valid dataset corresponding to the query!");
774 // Process a full run range.
775 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
776 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
777 if (!DirectoryExists(path)) continue;
779 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
780 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
781 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
782 if (fOverwriteMode) gGrid->Rm(file);
784 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
788 // If local collection file does not exist, create it via 'find' command.
789 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
794 command += conditions;
795 TGridResult *res = gGrid->Command(command);
797 // Write standard output to file
798 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
799 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
800 Bool_t nullFile = kFALSE;
802 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
804 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
806 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
812 if (TestBit(AliAnalysisGrid::kTest)) break;
813 // Check if there is one run per master job.
814 if (fNrunsPerMaster<2) {
815 if (FileExists(file)) {
816 if (fOverwriteMode) gGrid->Rm(file);
818 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
822 // Copy xml file to alien space
823 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
824 if (!FileExists(file)) {
825 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
830 // Check if the collection for the chunk exist locally.
831 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
832 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
833 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
836 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
837 if (((nruns-1)%fNrunsPerMaster) == 0) {
838 schunk = Form("%s%d", fRunPrefix.Data(), irun);
839 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
841 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
845 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
846 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
850 if (FileExists(schunk)) {
851 if (fOverwriteMode) gGrid->Rm(schunk);
853 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
857 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
858 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
859 if (FileExists(schunk)) {
860 if (fOverwriteMode) gGrid->Rm(schunk);
862 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
866 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
867 if (!FileExists(schunk)) {
868 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
874 Error("CreateDataset", "No valid dataset corresponding to the query!");
881 //______________________________________________________________________________
882 Bool_t AliAnalysisAlien::CreateJDL()
884 // Generate a JDL file according to current settings. The name of the file is
885 // specified by fJDLName.
886 Bool_t error = kFALSE;
889 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
890 Bool_t generate = kTRUE;
891 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
893 Error("CreateJDL", "Alien connection required");
896 // Check validity of alien workspace
898 TString workdir = gGrid->GetHomeDirectory();
899 workdir += fGridWorkingDir;
903 Error("CreateJDL()", "Define some input files for your analysis.");
906 // Compose list of input files
907 // Check if output files were defined
908 if (!fOutputFiles.Length()) {
909 Error("CreateJDL", "You must define at least one output file");
912 // Check if an output directory was defined and valid
913 if (!fGridOutputDir.Length()) {
914 Error("CreateJDL", "You must define AliEn output directory");
917 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
918 if (!DirectoryExists(fGridOutputDir)) {
919 if (gGrid->Mkdir(fGridOutputDir)) {
920 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
922 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
928 // Exit if any error up to now
929 if (error) return kFALSE;
931 if (!fUser.IsNull()) {
932 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
933 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
935 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
936 TString mergeExec = fExecutable;
937 mergeExec.ReplaceAll(".sh", "_merge.sh");
938 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
939 mergeExec.ReplaceAll(".sh", ".C");
940 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
941 if (!fArguments.IsNull())
942 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
943 fMergingJDL->SetArguments("$1");
944 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
945 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
946 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
947 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
949 if (fMaxInitFailed > 0) {
950 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
951 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
953 if (fSplitMaxInputFileNumber > 0) {
954 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
955 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
957 if (fSplitMode.Length()) {
958 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
959 fGridJDL->SetDescription("Split", "We split per SE or file");
961 if (!fAliROOTVersion.IsNull()) {
962 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
963 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
965 if (!fROOTVersion.IsNull()) {
966 fGridJDL->AddToPackages("ROOT", fROOTVersion);
967 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
969 if (!fAPIVersion.IsNull()) {
970 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
971 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
973 if (!fExternalPackages.IsNull()) {
974 arr = fExternalPackages.Tokenize(" ");
976 while ((os=(TObjString*)next())) {
977 TString pkgname = os->GetString();
978 Int_t index = pkgname.Index("::");
979 TString pkgversion = pkgname(index+2, pkgname.Length());
980 pkgname.Remove(index);
981 fGridJDL->AddToPackages(pkgname, pkgversion);
982 fMergingJDL->AddToPackages(pkgname, pkgversion);
986 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
987 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
988 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
989 TString analysisFile = fExecutable;
990 analysisFile.ReplaceAll(".sh", ".root");
991 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
992 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
993 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
994 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
995 if (fAdditionalLibs.Length()) {
996 arr = fAdditionalLibs.Tokenize(" ");
998 while ((os=(TObjString*)next())) {
999 if (os->GetString().Contains(".so")) continue;
1000 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1001 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1006 TIter next(fPackages);
1008 while ((obj=next())) {
1009 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1010 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1013 if (fOutputArchive.Length()) {
1014 arr = fOutputArchive.Tokenize(" ");
1016 Bool_t first = kTRUE;
1017 const char *comment = "Files to be archived";
1018 const char *comment1 = comment;
1019 while ((os=(TObjString*)next())) {
1020 if (!first) comment = NULL;
1021 if (!os->GetString().Contains("@") && fCloseSE.Length())
1022 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1024 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1028 TString outputArchive = fOutputArchive;
1029 if (!fMergeExcludes.IsNull()) {
1030 arr = fMergeExcludes.Tokenize(" ");
1032 while ((os=(TObjString*)next1())) {
1033 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1034 outputArchive.ReplaceAll(os->GetString(),"");
1038 arr = outputArchive.Tokenize(" ");
1042 while ((os=(TObjString*)next2())) {
1043 if (!first) comment = NULL;
1044 if (!os->GetString().Contains("@") && fCloseSE.Length())
1045 fMergingJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1047 fMergingJDL->AddToOutputArchive(os->GetString(), comment);
1052 arr = fOutputFiles.Tokenize(",");
1054 Bool_t first = kTRUE;
1055 const char *comment = "Files to be archived";
1056 const char *comment1 = comment;
1057 while ((os=(TObjString*)next())) {
1058 // Ignore ouputs in jdl that are also in outputarchive
1059 TString sout = os->GetString();
1060 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1061 if (fOutputArchive.Contains(sout)) continue;
1062 if (!first) comment = NULL;
1063 if (!os->GetString().Contains("@") && fCloseSE.Length())
1064 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1066 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1070 if (fOutputFiles.Length()) {
1071 TString outputFiles = fOutputFiles;
1072 if (!fMergeExcludes.IsNull()) {
1073 arr = fMergeExcludes.Tokenize(" ");
1075 while ((os=(TObjString*)next1())) {
1076 outputFiles.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1077 outputFiles.ReplaceAll(os->GetString(),"");
1081 arr = outputFiles.Tokenize(" ");
1085 while ((os=(TObjString*)next2())) {
1086 // Ignore ouputs in jdl that are also in outputarchive
1087 TString sout = os->GetString();
1088 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1089 if (fOutputArchive.Contains(sout)) continue;
1090 if (!first) comment = NULL;
1091 if (!os->GetString().Contains("@") && fCloseSE.Length())
1092 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1094 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1098 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1099 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1100 TString validationScript = fExecutable;
1101 validationScript.ReplaceAll(".sh", "_validation.sh");
1102 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1103 validationScript = fExecutable;
1104 validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
1105 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1106 if (fMasterResubmitThreshold) {
1107 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1108 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1110 // Write a jdl with 2 input parameters: collection name and output dir name.
1113 // Copy jdl to grid workspace
1115 // Check if an output directory was defined and valid
1116 if (!fGridOutputDir.Length()) {
1117 Error("CreateJDL", "You must define AliEn output directory");
1120 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1121 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1122 if (gGrid->Mkdir(fGridOutputDir)) {
1123 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1125 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1131 if (TestBit(AliAnalysisGrid::kSubmit)) {
1132 TString mergeJDLName = fExecutable;
1133 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1134 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1135 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1136 if (fProductionMode) {
1137 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1138 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1140 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1141 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1142 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1143 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1145 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1146 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1149 if (fAdditionalLibs.Length()) {
1150 arr = fAdditionalLibs.Tokenize(" ");
1153 while ((os=(TObjString*)next())) {
1154 if (os->GetString().Contains(".so")) continue;
1155 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1156 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1157 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1162 TIter next(fPackages);
1164 while ((obj=next())) {
1165 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1166 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1167 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1174 //______________________________________________________________________________
1175 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1177 // Writes one or more JDL's corresponding to findex. If findex is negative,
1178 // all run numbers are considered in one go (jdl). For non-negative indices
1179 // they correspond to the indices in the array fInputFiles.
1180 if (!fInputFiles) return kFALSE;
1182 TString workdir = gGrid->GetHomeDirectory();
1183 workdir += fGridWorkingDir;
1185 if (!fRunNumbers.Length() && !fRunRange[0]) {
1186 // One jdl with no parameters in case input data is specified by name.
1187 TIter next(fInputFiles);
1188 while ((os=(TObjString*)next()))
1189 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()), "Input xml collections");
1190 if (!fOutputSingle.IsNull())
1191 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1193 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1194 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1197 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1198 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1199 if (!fOutputSingle.IsNull()) {
1200 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1201 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1203 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1204 fMergingJDL->SetOutputDirectory(Form("%s/$1", fGridOutputDir.Data()), "Output directory");
1209 // Generate the JDL as a string
1210 TString sjdl = fGridJDL->Generate();
1211 TString sjdl1 = fMergingJDL->Generate();
1213 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1214 sjdl.ReplaceAll("(member", "\n (member");
1215 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1216 sjdl.ReplaceAll("{", "{\n ");
1217 sjdl.ReplaceAll("};", "\n};");
1218 sjdl.ReplaceAll("{\n \n", "{\n");
1219 sjdl.ReplaceAll("\n\n", "\n");
1220 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1221 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1222 sjdl1.ReplaceAll("(member", "\n (member");
1223 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1224 sjdl1.ReplaceAll("{", "{\n ");
1225 sjdl1.ReplaceAll("};", "\n};");
1226 sjdl1.ReplaceAll("{\n \n", "{\n");
1227 sjdl1.ReplaceAll("\n\n", "\n");
1228 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1229 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1230 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1231 index = sjdl.Index("JDLVariables");
1232 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1233 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1234 sjdl1.Prepend(Form("Jobtag = {\n \"comment:Merging_%s\"\n};\n", fJobTag.Data()));
1235 index = sjdl1.Index("JDLVariables");
1236 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1237 // Write jdl to file
1239 out.open(fJDLName.Data(), ios::out);
1241 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1244 out << sjdl << endl;
1245 TString mergeJDLName = fExecutable;
1246 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1249 out1.open(mergeJDLName.Data(), ios::out);
1251 Error("CreateJDL", "Bad file name: %s", mergeJDLName.Data());
1254 out1 << sjdl1 << endl;
1257 // Copy jdl to grid workspace
1259 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1261 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1262 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1263 if (fProductionMode) {
1264 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1265 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1267 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1268 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1269 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1270 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1272 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1273 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1279 //______________________________________________________________________________
1280 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1282 // Returns true if file exists.
1283 if (!gGrid) return kFALSE;
1284 TGridResult *res = gGrid->Ls(lfn);
1285 if (!res) return kFALSE;
1286 TMap *map = dynamic_cast<TMap*>(res->At(0));
1291 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1292 if (!objs || !objs->GetString().Length()) {
1300 //______________________________________________________________________________
1301 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1303 // Returns true if directory exists. Can be also a path.
1304 if (!gGrid) return kFALSE;
1305 // Check if dirname is a path
1306 TString dirstripped = dirname;
1307 dirstripped = dirstripped.Strip();
1308 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1309 TString dir = gSystem->BaseName(dirstripped);
1311 TString path = gSystem->DirName(dirstripped);
1312 TGridResult *res = gGrid->Ls(path, "-F");
1313 if (!res) return kFALSE;
1317 while ((map=dynamic_cast<TMap*>(next()))) {
1318 obj = map->GetValue("name");
1320 if (dir == obj->GetName()) {
1329 //______________________________________________________________________________
1330 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1332 // Check input data type.
1333 isCollection = kFALSE;
1337 Error("CheckDataType", "No connection to grid");
1340 isCollection = IsCollection(lfn);
1341 TString msg = "\n##### file: ";
1344 msg += " type: raw_collection;";
1345 // special treatment for collections
1347 // check for tag files in the collection
1348 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1350 msg += " using_tags: No (unknown)";
1351 Info("CheckDataType", msg.Data());
1354 const char* typeStr = res->GetKey(0, "origLFN");
1355 if (!typeStr || !strlen(typeStr)) {
1356 msg += " using_tags: No (unknown)";
1357 Info("CheckDataType", msg.Data());
1360 TString file = typeStr;
1361 useTags = file.Contains(".tag");
1362 if (useTags) msg += " using_tags: Yes";
1363 else msg += " using_tags: No";
1364 Info("CheckDataType", msg.Data());
1369 isXml = slfn.Contains(".xml");
1371 // Open xml collection and check if there are tag files inside
1372 msg += " type: xml_collection;";
1373 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1375 msg += " using_tags: No (unknown)";
1376 Info("CheckDataType", msg.Data());
1379 TMap *map = coll->Next();
1381 msg += " using_tags: No (unknown)";
1382 Info("CheckDataType", msg.Data());
1385 map = (TMap*)map->GetValue("");
1387 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1388 useTags = file.Contains(".tag");
1390 if (useTags) msg += " using_tags: Yes";
1391 else msg += " using_tags: No";
1392 Info("CheckDataType", msg.Data());
1395 useTags = slfn.Contains(".tag");
1396 if (slfn.Contains(".root")) msg += " type: root file;";
1397 else msg += " type: unknown file;";
1398 if (useTags) msg += " using_tags: Yes";
1399 else msg += " using_tags: No";
1400 Info("CheckDataType", msg.Data());
1403 //______________________________________________________________________________
1404 void AliAnalysisAlien::EnablePackage(const char *package)
1406 // Enables a par file supposed to exist in the current directory.
1407 TString pkg(package);
1408 pkg.ReplaceAll(".par", "");
1410 if (gSystem->AccessPathName(pkg)) {
1411 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1414 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1415 Info("EnablePackage", "AliEn plugin will use .par packages");
1416 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1418 fPackages = new TObjArray();
1419 fPackages->SetOwner();
1421 fPackages->Add(new TObjString(pkg));
1424 //______________________________________________________________________________
1425 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1427 // Get job status for all jobs with jobid>jobidstart.
1428 static char mstatus[20];
1434 TGridJobStatusList *list = gGrid->Ps("");
1435 if (!list) return mstatus;
1436 Int_t nentries = list->GetSize();
1437 TGridJobStatus *status;
1439 for (Int_t ijob=0; ijob<nentries; ijob++) {
1440 status = (TGridJobStatus *)list->At(ijob);
1441 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1442 if (pid<jobidstart) continue;
1443 if (pid == lastid) {
1444 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1446 switch (status->GetStatus()) {
1447 case TGridJobStatus::kWAITING:
1449 case TGridJobStatus::kRUNNING:
1451 case TGridJobStatus::kABORTED:
1452 case TGridJobStatus::kFAIL:
1453 case TGridJobStatus::kUNKNOWN:
1455 case TGridJobStatus::kDONE:
1464 //______________________________________________________________________________
1465 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1467 // Returns true if file is a collection. Functionality duplicated from
1468 // TAlien::Type() because we don't want to directly depend on TAlien.
1470 Error("IsCollection", "No connection to grid");
1473 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1474 if (!res) return kFALSE;
1475 const char* typeStr = res->GetKey(0, "type");
1476 if (!typeStr || !strlen(typeStr)) return kFALSE;
1477 if (!strcmp(typeStr, "collection")) return kTRUE;
1482 //______________________________________________________________________________
1483 Bool_t AliAnalysisAlien::IsSingleOutput() const
1485 // Check if single-ouput option is on.
1486 return (!fOutputSingle.IsNull());
1489 //______________________________________________________________________________
1490 void AliAnalysisAlien::Print(Option_t *) const
1492 // Print current plugin settings.
1493 printf("### AliEn analysis plugin current settings ###\n");
1494 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1495 if (fOverwriteMode) {
1496 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1497 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1499 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1500 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1501 printf("= Production mode:______________________________ %d\n", fProductionMode);
1502 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1503 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1504 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1506 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1507 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1508 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1509 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1510 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1511 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1512 if (fRunNumbers.Length())
1513 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1515 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1516 if (!fRunRange[0] && !fRunNumbers.Length()) {
1517 TIter next(fInputFiles);
1520 while ((obj=next())) list += obj->GetName();
1521 printf("= Input files to be processed: _________________ %s\n", list.Data());
1523 if (TestBit(AliAnalysisGrid::kTest))
1524 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1525 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1526 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1527 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1528 printf("=====================================================================\n");
1529 printf("= Job price: ___________________________________ %d\n", fPrice);
1530 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1531 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1532 if (fMaxInitFailed>0)
1533 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1534 if (fMasterResubmitThreshold>0)
1535 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1536 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1537 if (fNrunsPerMaster>0)
1538 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1539 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1540 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1541 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1542 if (fArguments.Length())
1543 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1544 if (fExecutableArgs.Length())
1545 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1546 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1547 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1548 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1549 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1551 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1552 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1553 if (fIncludePath.Data())
1554 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1555 if (fCloseSE.Length())
1556 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1557 if (fFriendChainName.Length())
1558 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1560 TIter next(fPackages);
1563 while ((obj=next())) list += obj->GetName();
1564 printf("= Par files to be used: ________________________ %s\n", list.Data());
1568 //______________________________________________________________________________
1569 void AliAnalysisAlien::SetDefaults()
1571 // Set default values for everything. What cannot be filled will be left empty.
1572 if (fGridJDL) delete fGridJDL;
1573 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1574 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1577 fSplitMaxInputFileNumber = 100;
1579 fMasterResubmitThreshold = 0;
1584 fNrunsPerMaster = 1;
1585 fMaxMergeFiles = 100;
1587 fExecutable = "analysis.sh";
1588 fExecutableCommand = "root -b -q";
1590 fExecutableArgs = "";
1591 fAnalysisMacro = "myAnalysis.C";
1592 fAnalysisSource = "";
1593 fAdditionalLibs = "";
1597 fAliROOTVersion = "";
1598 fUser = ""; // Your alien user name
1599 fGridWorkingDir = "";
1600 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1601 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1602 fFriendChainName = "";
1603 fGridOutputDir = "output";
1604 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1605 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1606 fInputFormat = "xml-single";
1607 fJDLName = "analysis.jdl";
1608 fJobTag = "Automatically generated analysis JDL";
1609 fMergeExcludes = "";
1612 SetCheckCopy(kTRUE);
1613 SetDefaultOutputs(kTRUE);
1617 //______________________________________________________________________________
1618 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge)
1620 // Merge all registered outputs from basedir.
1621 TString outputFile = output;
1623 TString outputChunk;
1624 TString previousChunk = "";
1625 Int_t countChunk = 0;
1626 Int_t countZero = nmaxmerge;
1627 Bool_t merged = kTRUE;
1628 Int_t index = outputFile.Index("@");
1629 if (index > 0) outputFile.Remove(index);
1630 command = Form("find %s/ *%s", basedir, outputFile.Data());
1631 printf("command: %s\n", command.Data());
1632 TGridResult *res = gGrid->Command(command);
1634 printf("Error: No result for the find command\n");
1638 TFileMerger *fm = 0;
1641 // Check if there is a merge operation to resume
1642 outputChunk = outputFile;
1643 outputChunk.ReplaceAll(".root", "_*.root");
1644 // Check for existent temporary merge files
1645 // Check overwrite mode and remove previous partial results if needed
1646 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
1648 // Skip as many input files as in a chunk
1649 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1651 ::Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", outputFile.Data(), res->GetSize());
1655 outputChunk = outputFile;
1656 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
1658 if (gSystem->AccessPathName(outputChunk)) continue;
1659 // Merged file with chunks up to <countChunk> found
1660 printf("Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
1661 previousChunk = outputChunk;
1665 countZero = nmaxmerge;
1667 while ((map=(TMap*)nextmap())) {
1668 // Loop 'find' results and get next LFN
1669 if (countZero == nmaxmerge) {
1670 // First file in chunk - create file merger and add previous chunk if any.
1671 fm = new TFileMerger(kFALSE);
1672 fm->SetFastMethod(kTRUE);
1673 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
1674 outputChunk = outputFile;
1675 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
1677 // If last file found, put merged results in the output file
1678 if (map == res->Last()) outputChunk = outputFile;
1679 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1680 if (!objs || !objs->GetString().Length()) {
1681 // Nothing found - skip this output
1686 // Add file to be merged and decrement chunk counter.
1687 fm->AddFile(objs->GetString());
1689 if (countZero==0 || map == res->Last()) {
1690 fm->OutputFile(outputChunk);
1691 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1692 // Nothing found - skip this output
1693 ::Warning("MergeOutputs", "No <%s> files found.", outputFile.Data());
1698 // Merge the outputs, then go to next chunk
1700 ::Error("MergeOutputs", "Could not merge all <%s> files", outputFile.Data());
1706 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
1707 gSystem->Unlink(previousChunk);
1709 if (map == res->Last()) {
1715 countZero = nmaxmerge;
1716 previousChunk = outputChunk;
1722 //______________________________________________________________________________
1723 Bool_t AliAnalysisAlien::MergeOutputs()
1725 // Merge analysis outputs existing in the AliEn space.
1726 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1727 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1729 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1733 if (!TestBit(AliAnalysisGrid::kMerge)) {
1734 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
1737 if (fProductionMode) {
1738 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
1741 Info("MergeOutputs", "Submitting merging JDL");
1742 if (!SubmitMerging()) return kFALSE;
1743 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
1744 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
1747 // Get the output path
1748 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1749 if (!DirectoryExists(fGridOutputDir)) {
1750 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1753 if (!fOutputFiles.Length()) {
1754 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1757 // Check if fast read option was requested
1758 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
1759 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
1760 if (fFastReadOption) {
1761 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
1762 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
1763 gEnv->SetValue("XNet.ConnectTimeout",10);
1764 gEnv->SetValue("XNet.RequestTimeout",10);
1765 gEnv->SetValue("XNet.MaxRedirectCount",2);
1766 gEnv->SetValue("XNet.ReconnectTimeout",10);
1767 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
1769 // Make sure we change the temporary directory
1770 gSystem->Setenv("TMPDIR", gSystem->pwd());
1771 TObjArray *list = fOutputFiles.Tokenize(",");
1775 Bool_t merged = kTRUE;
1776 while((str=(TObjString*)next())) {
1777 outputFile = str->GetString();
1778 Int_t index = outputFile.Index("@");
1779 if (index > 0) outputFile.Remove(index);
1780 TString outputChunk = outputFile;
1781 outputChunk.ReplaceAll(".root", "_*.root");
1782 // Skip already merged outputs
1783 if (!gSystem->AccessPathName(outputFile)) {
1784 if (fOverwriteMode) {
1785 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
1786 gSystem->Unlink(outputFile);
1787 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
1788 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
1789 outputChunk.Data());
1790 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
1793 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
1797 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
1798 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
1799 outputChunk.Data());
1800 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
1803 if (fMergeExcludes.Length() &&
1804 fMergeExcludes.Contains(outputFile.Data())) continue;
1805 // Perform a 'find' command in the output directory, looking for registered outputs
1806 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
1808 Error("MergeOutputs", "Terminate() will NOT be executed");
1811 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
1812 if (fileOpened) fileOpened->Close();
1817 //______________________________________________________________________________
1818 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1820 // Use the output files connected to output containers from the analysis manager
1821 // rather than the files defined by SetOutputFiles
1822 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1823 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
1824 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1827 //______________________________________________________________________________
1828 void AliAnalysisAlien::SetOutputFiles(const char *list)
1830 // Manually set the output files list.
1831 // Removes duplicates. Not allowed if default outputs are not disabled.
1832 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1833 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
1836 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
1838 TString slist = list;
1839 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
1840 TObjArray *arr = slist.Tokenize(" ");
1844 while ((os=(TObjString*)next())) {
1845 sout = os->GetString();
1846 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1847 if (fOutputFiles.Contains(sout)) continue;
1848 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
1849 fOutputFiles += sout;
1854 //______________________________________________________________________________
1855 void AliAnalysisAlien::SetOutputArchive(const char *list)
1857 // Manually set the output archive list. Free text - you are on your own...
1858 // Not allowed if default outputs are not disabled.
1859 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1860 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
1863 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
1864 fOutputArchive = list;
1867 //______________________________________________________________________________
1868 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
1870 // Setting a prefered output SE is not allowed anymore.
1871 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
1874 //______________________________________________________________________________
1875 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1877 // Start remote grid analysis.
1879 // Check if output files have to be taken from the analysis manager
1880 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1881 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1882 if (!mgr || !mgr->IsInitialized()) {
1883 Error("StartAnalysis", "You need an initialized analysis manager for this");
1887 TIter next(mgr->GetOutputs());
1888 AliAnalysisDataContainer *output;
1889 while ((output=(AliAnalysisDataContainer*)next())) {
1890 const char *filename = output->GetFileName();
1891 if (!(strcmp(filename, "default"))) {
1892 if (!mgr->GetOutputEventHandler()) continue;
1893 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1895 if (fOutputFiles.Contains(filename)) continue;
1896 if (fOutputFiles.Length()) fOutputFiles += ",";
1897 fOutputFiles += filename;
1899 // Add extra files registered to the analysis manager
1900 if (mgr->GetExtraFiles().Length()) {
1901 if (fOutputFiles.Length()) fOutputFiles += ",";
1902 TString extra = mgr->GetExtraFiles();
1903 extra.ReplaceAll(" ", ",");
1904 // Protection in case extra files do not exist (will it work?)
1905 extra.ReplaceAll(".root", "*.root");
1906 fOutputFiles += extra;
1908 // Compose the output archive.
1909 fOutputArchive = "log_archive.zip:std*@disk=1 ";
1910 fOutputArchive += Form("root_archive.zip:%s@disk=%d",fOutputFiles.Data(),fNreplicas);
1912 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1913 if (TestBit(AliAnalysisGrid::kOffline)) {
1914 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1915 \n there nor any job run. You can revise the JDL and analysis \
1916 \n macro then run the same in \"submit\" mode.");
1917 } else if (TestBit(AliAnalysisGrid::kTest)) {
1918 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1920 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1921 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1922 \n space and job submitted.");
1923 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1924 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1925 if (fMergeViaJDL) CheckInputData();
1928 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1933 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1936 if (IsCheckCopy()) CheckFileCopy(gGrid->GetHomeDirectory());
1937 if (!CheckInputData()) {
1938 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1941 if (!CreateDataset(fDataPattern)) {
1943 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
1944 if (fRunNumbers.Length()) serror = "run numbers";
1945 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
1946 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
1947 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
1950 WriteAnalysisFile();
1951 WriteAnalysisMacro();
1953 WriteValidationScript();
1955 WriteMergingMacro();
1956 WriteMergeExecutable();
1957 WriteValidationScript(kTRUE);
1959 if (!CreateJDL()) return kFALSE;
1960 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1961 if (TestBit(AliAnalysisGrid::kTest)) {
1962 // Locally testing the analysis
1963 Info("StartAnalysis", "\n_______________________________________________________________________ \
1964 \n Running analysis script in a daughter shell as on a worker node \
1965 \n_______________________________________________________________________");
1966 TObjArray *list = fOutputFiles.Tokenize(",");
1970 while((str=(TObjString*)next())) {
1971 outputFile = str->GetString();
1972 Int_t index = outputFile.Index("@");
1973 if (index > 0) outputFile.Remove(index);
1974 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
1977 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1978 TString validationScript = fExecutable;
1979 validationScript.ReplaceAll(".sh", "_validation.sh");
1980 gSystem->Exec(Form("bash %s",validationScript.Data()));
1981 // gSystem->Exec("cat stdout");
1984 // Check if submitting is managed by LPM manager
1985 if (fProductionMode) {
1986 TString prodfile = fJDLName;
1987 prodfile.ReplaceAll(".jdl", ".prod");
1988 WriteProductionFile(prodfile);
1989 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1992 // Submit AliEn job(s)
1993 gGrid->Cd(fGridOutputDir);
1996 if (!fRunNumbers.Length() && !fRunRange[0]) {
1997 // Submit a given xml or a set of runs
1998 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1999 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2001 const char *cjobId = res->GetKey(0,"jobId");
2005 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2008 Info("StartAnalysis", "\n_______________________________________________________________________ \
2009 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2010 \n_______________________________________________________________________",
2011 fJDLName.Data(), cjobId);
2016 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2020 // Submit for a range of enumeration of runs.
2021 if (!Submit()) return kFALSE;
2024 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2025 \n You may exit at any time and terminate the job later using the option <terminate> \
2026 \n ##################################################################################", jobID.Data());
2027 gSystem->Exec("aliensh");
2031 //______________________________________________________________________________
2032 Bool_t AliAnalysisAlien::Submit()
2034 // Submit all master jobs.
2035 Int_t nmasterjobs = fInputFiles->GetEntries();
2036 Long_t tshoot = gSystem->Now();
2037 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2038 while (fNsubmitted < nmasterjobs) {
2039 Long_t now = gSystem->Now();
2040 if ((now-tshoot)>30000) {
2042 if (!SubmitNext()) return kFALSE;
2048 //______________________________________________________________________________
2049 Bool_t AliAnalysisAlien::SubmitMerging()
2051 // Submit all merging jobs.
2052 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2053 gGrid->Cd(fGridOutputDir);
2054 TString mergeJDLName = fExecutable;
2055 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2056 Int_t ntosubmit = fInputFiles->GetEntries();
2057 printf("### Submitting %d merging jobs...\n", ntosubmit);
2058 for (Int_t i=0; i<ntosubmit; i++) {
2060 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2061 runOutDir.ReplaceAll(".xml", "");
2063 query = Form("submit %s %s", mergeJDLName.Data(), runOutDir.Data());
2065 query = Form("submit %s %03d", mergeJDLName.Data(), i);
2066 printf("********* %s\n",query.Data());
2067 TGridResult *res = gGrid->Command(query);
2069 const char *cjobId = res->GetKey(0,"jobId");
2073 Error("StartAnalysis", "Your JDL %s could not be submitted", mergeJDLName.Data());
2076 Info("StartAnalysis", "\n_______________________________________________________________________ \
2077 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2078 \n_______________________________________________________________________",
2079 mergeJDLName.Data(), cjobId);
2083 Error("SubmitMerging", "No grid result after submission !!! Bailing out...");
2087 if (!ntosubmit) return kTRUE;
2088 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
2089 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
2090 \n ##################################################################################");
2091 gSystem->Exec("aliensh");
2095 //______________________________________________________________________________
2096 Bool_t AliAnalysisAlien::SubmitNext()
2098 // Submit next bunch of master jobs if the queue is free.
2099 static Bool_t iscalled = kFALSE;
2100 static Int_t firstmaster = 0;
2101 static Int_t lastmaster = 0;
2102 static Int_t npermaster = 0;
2103 if (iscalled) return kTRUE;
2105 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2106 Int_t ntosubmit = 0;
2109 if (!fNsubmitted) ntosubmit = 1;
2111 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2112 printf("=== master %d: %s\n", lastmaster, status.Data());
2113 // If last master not split, just return
2114 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2115 // No more than 100 waiting jobs
2116 if (nwaiting>100) {iscalled = kFALSE; return kTRUE;}
2117 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2118 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
2119 if (!ntosubmit) ntosubmit = 1;
2120 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2121 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2123 Int_t nmasterjobs = fInputFiles->GetEntries();
2124 for (Int_t i=0; i<ntosubmit; i++) {
2125 // Submit for a range of enumeration of runs.
2126 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2128 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2129 runOutDir.ReplaceAll(".xml", "");
2131 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2133 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2134 printf("********* %s\n",query.Data());
2135 res = gGrid->Command(query);
2137 TString cjobId1 = res->GetKey(0,"jobId");
2138 if (!cjobId1.Length()) {
2142 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2145 Info("StartAnalysis", "\n_______________________________________________________________________ \
2146 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2147 \n_______________________________________________________________________",
2148 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2151 lastmaster = cjobId1.Atoi();
2152 if (!firstmaster) firstmaster = lastmaster;
2157 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2165 //______________________________________________________________________________
2166 void AliAnalysisAlien::WriteAnalysisFile()
2168 // Write current analysis manager into the file <analysisFile>
2169 TString analysisFile = fExecutable;
2170 analysisFile.ReplaceAll(".sh", ".root");
2171 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2172 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2173 if (!mgr || !mgr->IsInitialized()) {
2174 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2177 // Check analysis type
2179 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2180 handler = (TObject*)mgr->GetInputEventHandler();
2182 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2183 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2185 TDirectory *cdir = gDirectory;
2186 TFile *file = TFile::Open(analysisFile, "RECREATE");
2188 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2189 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
2190 // Unless merging makes no sense
2191 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2194 // Enable termination for local jobs
2195 mgr->SetSkipTerminate(kFALSE);
2197 if (cdir) cdir->cd();
2198 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2200 Bool_t copy = kTRUE;
2201 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2204 TString workdir = gGrid->GetHomeDirectory();
2205 workdir += fGridWorkingDir;
2206 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2207 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2208 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2212 //______________________________________________________________________________
2213 void AliAnalysisAlien::WriteAnalysisMacro()
2215 // Write the analysis macro that will steer the analysis in grid mode.
2216 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2218 out.open(fAnalysisMacro.Data(), ios::out);
2220 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2223 Bool_t hasSTEERBase = kFALSE;
2224 Bool_t hasESD = kFALSE;
2225 Bool_t hasAOD = kFALSE;
2226 Bool_t hasANALYSIS = kFALSE;
2227 Bool_t hasANALYSISalice = kFALSE;
2228 Bool_t hasCORRFW = kFALSE;
2229 TString func = fAnalysisMacro;
2230 TString type = "ESD";
2231 TString comment = "// Analysis using ";
2232 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2233 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2237 if (type!="AOD" && fFriendChainName!="") {
2238 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2241 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2242 else comment += " data";
2243 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2244 func.ReplaceAll(".C", "");
2245 out << "void " << func.Data() << "()" << endl;
2247 out << comment.Data() << endl;
2248 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
2249 out << " TStopwatch timer;" << endl;
2250 out << " timer.Start();" << endl << endl;
2251 out << "// load base root libraries" << endl;
2252 out << " gSystem->Load(\"libTree\");" << endl;
2253 out << " gSystem->Load(\"libGeom\");" << endl;
2254 out << " gSystem->Load(\"libVMC\");" << endl;
2255 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2256 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2257 if (fAdditionalRootLibs.Length()) {
2258 // in principle libtree /lib geom libvmc etc. can go into this list, too
2259 out << "// Add aditional libraries" << endl;
2260 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2263 while((str=(TObjString*)next())) {
2264 if (str->GetString().Contains(".so"))
2265 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2267 if (list) delete list;
2269 out << "// include path" << endl;
2270 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2271 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2272 out << "// Load analysis framework libraries" << endl;
2274 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2275 out << " gSystem->Load(\"libESD\");" << endl;
2276 out << " gSystem->Load(\"libAOD\");" << endl;
2277 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2278 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2279 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2281 TIter next(fPackages);
2284 TString setupPar = "AliAnalysisAlien::SetupPar";
2285 while ((obj=next())) {
2286 pkgname = obj->GetName();
2287 if (pkgname == "STEERBase" ||
2288 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2289 if (pkgname == "ESD" ||
2290 pkgname == "ESD.par") hasESD = kTRUE;
2291 if (pkgname == "AOD" ||
2292 pkgname == "AOD.par") hasAOD = kTRUE;
2293 if (pkgname == "ANALYSIS" ||
2294 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2295 if (pkgname == "ANALYSISalice" ||
2296 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2297 if (pkgname == "CORRFW" ||
2298 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2300 if (hasANALYSISalice) setupPar = "SetupPar";
2301 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2302 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2303 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2304 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2305 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2306 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2307 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2308 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2309 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2310 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2311 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2312 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2313 out << "// Compile other par packages" << endl;
2315 while ((obj=next())) {
2316 pkgname = obj->GetName();
2317 if (pkgname == "STEERBase" ||
2318 pkgname == "STEERBase.par" ||
2320 pkgname == "ESD.par" ||
2322 pkgname == "AOD.par" ||
2323 pkgname == "ANALYSIS" ||
2324 pkgname == "ANALYSIS.par" ||
2325 pkgname == "ANALYSISalice" ||
2326 pkgname == "ANALYSISalice.par" ||
2327 pkgname == "CORRFW" ||
2328 pkgname == "CORRFW.par") continue;
2329 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2332 if (fAdditionalLibs.Length()) {
2333 out << "// Add aditional AliRoot libraries" << endl;
2334 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2337 while((str=(TObjString*)next())) {
2338 if (str->GetString().Contains(".so"))
2339 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2341 if (list) delete list;
2344 out << "// analysis source to be compiled at runtime (if any)" << endl;
2345 if (fAnalysisSource.Length()) {
2346 TObjArray *list = fAnalysisSource.Tokenize(" ");
2349 while((str=(TObjString*)next())) {
2350 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2352 if (list) delete list;
2355 if (fFastReadOption) {
2356 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 !!! \
2357 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2358 out << "// fast xrootd reading enabled" << endl;
2359 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2360 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
2361 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
2362 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2363 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
2364 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2366 // Change temp directory to current one
2367 out << "// Set temporary merging directory to current one" << endl;
2368 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
2369 out << "// connect to AliEn and make the chain" << endl;
2370 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2371 if (IsUsingTags()) {
2372 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
2374 if(fFriendChainName!="AliAOD.VertexingHF.root") {
2375 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
2377 out << " // Check if the macro to create the chain was provided" << endl;
2378 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
2379 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
2380 out << " return;" << endl;
2381 out << " }" << endl;
2382 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
2383 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
2386 out << "// read the analysis manager from file" << endl;
2387 TString analysisFile = fExecutable;
2388 analysisFile.ReplaceAll(".sh", ".root");
2389 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2390 out << " if (!file) return;" << endl;
2391 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2392 out << " AliAnalysisManager *mgr = 0;" << endl;
2393 out << " TKey *key;" << endl;
2394 out << " while ((key=(TKey*)nextkey())) {" << endl;
2395 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2396 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2397 out << " };" << endl;
2398 out << " if (!mgr) {" << endl;
2399 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
2400 out << " return;" << endl;
2401 out << " }" << endl << endl;
2402 out << " mgr->PrintStatus();" << endl;
2403 if (AliAnalysisManager::GetAnalysisManager()) {
2404 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2405 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2407 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2410 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
2411 out << " timer.Stop();" << endl;
2412 out << " timer.Print();" << endl;
2413 out << "}" << endl << endl;
2414 if (IsUsingTags()) {
2415 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
2417 out << "// Create a chain using tags from the xml file." << endl;
2418 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
2419 out << " if (!coll) {" << endl;
2420 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2421 out << " return NULL;" << endl;
2422 out << " }" << endl;
2423 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
2424 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
2425 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
2426 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
2427 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
2428 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
2429 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
2430 out << " // Check if the cuts configuration file was provided" << endl;
2431 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
2432 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
2433 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2434 out << " }" << endl;
2435 if (fFriendChainName=="") {
2436 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2438 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
2439 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
2440 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
2442 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
2443 out << " chain->ls();" << endl;
2444 out << " return chain;" << endl;
2445 out << "}" << endl << endl;
2446 if (gSystem->AccessPathName("ConfigureCuts.C")) {
2447 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
2448 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
2449 msg += " AliLHCTagCuts *lhcCuts,\n";
2450 msg += " AliDetectorTagCuts *detCuts,\n";
2451 msg += " AliEventTagCuts *evCuts)";
2452 Info("WriteAnalysisMacro", msg.Data());
2455 if (!IsUsingTags() || fFriendChainName!="") {
2456 out <<"//________________________________________________________________________________" << endl;
2457 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
2459 out << "// Create a chain using url's from xml file" << endl;
2460 out << " TString treename = type;" << endl;
2461 out << " treename.ToLower();" << endl;
2462 out << " treename += \"Tree\";" << endl;
2463 out << " printf(\"***************************************\\n\");" << endl;
2464 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
2465 out << " printf(\"***************************************\\n\");" << endl;
2466 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
2467 out << " if (!coll) {" << endl;
2468 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2469 out << " return NULL;" << endl;
2470 out << " }" << endl;
2471 out << " TChain *chain = new TChain(treename);" << endl;
2472 if(fFriendChainName!="") {
2473 out << " TChain *chainFriend = new TChain(treename);" << endl;
2475 out << " coll->Reset();" << endl;
2476 out << " while (coll->Next()) {" << endl;
2477 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2478 if(fFriendChainName!="") {
2479 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2480 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2481 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2482 out << " chainFriend->Add(fileFriend.Data());" << endl;
2484 out << " }" << endl;
2485 out << " if (!chain->GetNtrees()) {" << endl;
2486 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2487 out << " return NULL;" << endl;
2488 out << " }" << endl;
2489 if(fFriendChainName!="") {
2490 out << " chain->AddFriend(chainFriend);" << endl;
2492 out << " return chain;" << endl;
2493 out << "}" << endl << endl;
2495 if (hasANALYSISalice) {
2496 out <<"//________________________________________________________________________________" << endl;
2497 out << "Bool_t SetupPar(const char *package) {" << endl;
2498 out << "// Compile the package and set it up." << endl;
2499 out << " TString pkgdir = package;" << endl;
2500 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2501 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2502 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2503 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2504 out << " // Check for BUILD.sh and execute" << endl;
2505 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2506 out << " printf(\"*******************************\\n\");" << endl;
2507 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2508 out << " printf(\"*******************************\\n\");" << endl;
2509 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2510 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2511 out << " gSystem->ChangeDirectory(cdir);" << endl;
2512 out << " return kFALSE;" << endl;
2513 out << " }" << endl;
2514 out << " } else {" << endl;
2515 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2516 out << " gSystem->ChangeDirectory(cdir);" << endl;
2517 out << " return kFALSE;" << endl;
2518 out << " }" << endl;
2519 out << " // Check for SETUP.C and execute" << endl;
2520 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2521 out << " printf(\"*******************************\\n\");" << endl;
2522 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2523 out << " printf(\"*******************************\\n\");" << endl;
2524 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2525 out << " } else {" << endl;
2526 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2527 out << " gSystem->ChangeDirectory(cdir);" << endl;
2528 out << " return kFALSE;" << endl;
2529 out << " }" << endl;
2530 out << " // Restore original workdir" << endl;
2531 out << " gSystem->ChangeDirectory(cdir);" << endl;
2532 out << " return kTRUE;" << endl;
2535 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2537 Bool_t copy = kTRUE;
2538 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2541 TString workdir = gGrid->GetHomeDirectory();
2542 workdir += fGridWorkingDir;
2543 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2544 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2545 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2546 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2547 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2549 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2550 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2554 //______________________________________________________________________________
2555 void AliAnalysisAlien::WriteMergingMacro()
2557 // Write a macro to merge the outputs per master job.
2558 if (!fMergeViaJDL) return;
2559 if (!fOutputFiles.Length()) {
2560 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2563 TString mergingMacro = fExecutable;
2564 mergingMacro.ReplaceAll(".sh","_merge.C");
2565 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2566 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2568 out.open(mergingMacro.Data(), ios::out);
2570 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2573 Bool_t hasSTEERBase = kFALSE;
2574 Bool_t hasESD = kFALSE;
2575 Bool_t hasAOD = kFALSE;
2576 Bool_t hasANALYSIS = kFALSE;
2577 Bool_t hasANALYSISalice = kFALSE;
2578 Bool_t hasCORRFW = kFALSE;
2579 TString func = mergingMacro;
2581 func.ReplaceAll(".C", "");
2582 out << "void " << func.Data() << "(const char *dir)" << endl;
2584 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
2585 out << " TStopwatch timer;" << endl;
2586 out << " timer.Start();" << endl << endl;
2587 out << "// load base root libraries" << endl;
2588 out << " gSystem->Load(\"libTree\");" << endl;
2589 out << " gSystem->Load(\"libGeom\");" << endl;
2590 out << " gSystem->Load(\"libVMC\");" << endl;
2591 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2592 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2593 if (fAdditionalRootLibs.Length()) {
2594 // in principle libtree /lib geom libvmc etc. can go into this list, too
2595 out << "// Add aditional libraries" << endl;
2596 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2599 while((str=(TObjString*)next())) {
2600 if (str->GetString().Contains(".so"))
2601 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2603 if (list) delete list;
2605 out << "// include path" << endl;
2606 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2607 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2608 out << "// Load analysis framework libraries" << endl;
2610 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2611 out << " gSystem->Load(\"libESD\");" << endl;
2612 out << " gSystem->Load(\"libAOD\");" << endl;
2613 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2614 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2615 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2617 TIter next(fPackages);
2620 TString setupPar = "AliAnalysisAlien::SetupPar";
2621 while ((obj=next())) {
2622 pkgname = obj->GetName();
2623 if (pkgname == "STEERBase" ||
2624 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2625 if (pkgname == "ESD" ||
2626 pkgname == "ESD.par") hasESD = kTRUE;
2627 if (pkgname == "AOD" ||
2628 pkgname == "AOD.par") hasAOD = kTRUE;
2629 if (pkgname == "ANALYSIS" ||
2630 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2631 if (pkgname == "ANALYSISalice" ||
2632 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2633 if (pkgname == "CORRFW" ||
2634 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2636 if (hasANALYSISalice) setupPar = "SetupPar";
2637 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2638 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2639 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2640 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2641 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2642 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2643 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2644 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2645 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2646 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2647 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2648 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2649 out << "// Compile other par packages" << endl;
2651 while ((obj=next())) {
2652 pkgname = obj->GetName();
2653 if (pkgname == "STEERBase" ||
2654 pkgname == "STEERBase.par" ||
2656 pkgname == "ESD.par" ||
2658 pkgname == "AOD.par" ||
2659 pkgname == "ANALYSIS" ||
2660 pkgname == "ANALYSIS.par" ||
2661 pkgname == "ANALYSISalice" ||
2662 pkgname == "ANALYSISalice.par" ||
2663 pkgname == "CORRFW" ||
2664 pkgname == "CORRFW.par") continue;
2665 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2668 if (fAdditionalLibs.Length()) {
2669 out << "// Add aditional AliRoot libraries" << endl;
2670 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2673 while((str=(TObjString*)next())) {
2674 if (str->GetString().Contains(".so"))
2675 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2677 if (list) delete list;
2680 out << "// Analysis source to be compiled at runtime (if any)" << endl;
2681 if (fAnalysisSource.Length()) {
2682 TObjArray *list = fAnalysisSource.Tokenize(" ");
2685 while((str=(TObjString*)next())) {
2686 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2688 if (list) delete list;
2692 if (fFastReadOption) {
2693 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 !!!");
2694 out << "// fast xrootd reading enabled" << endl;
2695 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2696 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
2697 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
2698 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2699 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
2700 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2702 // Change temp directory to current one
2703 out << "// Set temporary merging directory to current one" << endl;
2704 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
2705 out << "// Connect to AliEn" << endl;
2706 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2707 out << " TString outputDir = \"" << fGridOutputDir << "/\";" << endl;
2708 out << " outputDir += dir;" << endl;
2709 out << " TString outputFiles = \"" << fOutputFiles << "\";" << endl;
2710 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
2711 out << " mergeExcludes += \"" << AliAnalysisManager::GetAnalysisManager()->GetExtraFiles() << "\";" << endl;
2712 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
2713 out << " TIter *iter = new TIter(list);" << endl;
2714 out << " TObjString *str;" << endl;
2715 out << " TString outputFile;" << endl;
2716 out << " Bool_t merged = kTRUE;" << endl;
2717 out << " while((str=(TObjString*)iter->Next())) {" << endl;
2718 out << " outputFile = str->GetString();" << endl;
2719 out << " Int_t index = outputFile.Index(\"@\");" << endl;
2720 out << " if (index > 0) outputFile.Remove(index);" << endl;
2721 out << " // Skip already merged outputs" << endl;
2722 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
2723 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
2724 out << " continue;" << endl;
2725 out << " }" << endl;
2726 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
2727 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ");" << endl;
2728 out << " if (!merged) {" << endl;
2729 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
2730 out << " }" << endl;
2731 out << " }" << endl;
2732 out << "// read the analysis manager from file" << endl;
2733 TString analysisFile = fExecutable;
2734 analysisFile.ReplaceAll(".sh", ".root");
2735 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2736 out << " if (!file) return;" << endl;
2737 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2738 out << " AliAnalysisManager *mgr = 0;" << endl;
2739 out << " TKey *key;" << endl;
2740 out << " while ((key=(TKey*)nextkey())) {" << endl;
2741 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2742 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2743 out << " };" << endl;
2744 out << " if (!mgr) {" << endl;
2745 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2746 out << " return;" << endl;
2747 out << " }" << endl << endl;
2748 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
2749 out << " mgr->PrintStatus();" << endl;
2750 if (AliAnalysisManager::GetAnalysisManager()) {
2751 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2752 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2754 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2757 out << " mgr->StartAnalysis(\"gridterminate\");" << endl;
2758 out << "}" << endl << endl;
2759 if (hasANALYSISalice) {
2760 out <<"//________________________________________________________________________________" << endl;
2761 out << "Bool_t SetupPar(const char *package) {" << endl;
2762 out << "// Compile the package and set it up." << endl;
2763 out << " TString pkgdir = package;" << endl;
2764 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2765 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2766 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2767 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2768 out << " // Check for BUILD.sh and execute" << endl;
2769 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2770 out << " printf(\"*******************************\\n\");" << endl;
2771 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2772 out << " printf(\"*******************************\\n\");" << endl;
2773 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2774 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2775 out << " gSystem->ChangeDirectory(cdir);" << endl;
2776 out << " return kFALSE;" << endl;
2777 out << " }" << endl;
2778 out << " } else {" << endl;
2779 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2780 out << " gSystem->ChangeDirectory(cdir);" << endl;
2781 out << " return kFALSE;" << endl;
2782 out << " }" << endl;
2783 out << " // Check for SETUP.C and execute" << endl;
2784 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2785 out << " printf(\"*******************************\\n\");" << endl;
2786 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2787 out << " printf(\"*******************************\\n\");" << endl;
2788 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2789 out << " } else {" << endl;
2790 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2791 out << " gSystem->ChangeDirectory(cdir);" << endl;
2792 out << " return kFALSE;" << endl;
2793 out << " }" << endl;
2794 out << " // Restore original workdir" << endl;
2795 out << " gSystem->ChangeDirectory(cdir);" << endl;
2796 out << " return kTRUE;" << endl;
2800 Bool_t copy = kTRUE;
2801 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2804 TString workdir = gGrid->GetHomeDirectory();
2805 workdir += fGridWorkingDir;
2806 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
2807 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
2808 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
2812 //______________________________________________________________________________
2813 Bool_t AliAnalysisAlien::SetupPar(const char *package)
2815 // Compile the par file archive pointed by <package>. This must be present in the current directory.
2816 // Note that for loading the compiled library. The current directory should have precedence in
2818 TString pkgdir = package;
2819 pkgdir.ReplaceAll(".par","");
2820 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
2821 TString cdir = gSystem->WorkingDirectory();
2822 gSystem->ChangeDirectory(pkgdir);
2823 // Check for BUILD.sh and execute
2824 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
2825 printf("**************************************************\n");
2826 printf("*** Building PAR archive %s\n", package);
2827 printf("**************************************************\n");
2828 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
2829 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
2830 gSystem->ChangeDirectory(cdir);
2834 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
2835 gSystem->ChangeDirectory(cdir);
2838 // Check for SETUP.C and execute
2839 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
2840 printf("**************************************************\n");
2841 printf("*** Setup PAR archive %s\n", package);
2842 printf("**************************************************\n");
2843 gROOT->Macro("PROOF-INF/SETUP.C");
2844 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
2846 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
2847 gSystem->ChangeDirectory(cdir);
2850 // Restore original workdir
2851 gSystem->ChangeDirectory(cdir);
2855 //______________________________________________________________________________
2856 void AliAnalysisAlien::WriteExecutable()
2858 // Generate the alien executable script.
2859 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2861 out.open(fExecutable.Data(), ios::out);
2863 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2866 out << "#!/bin/bash" << endl;
2867 out << "echo \"=========================================\"" << endl;
2868 out << "echo \"############## PATH : ##############\"" << endl;
2869 out << "echo $PATH" << endl;
2870 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2871 out << "echo $LD_LIBRARY_PATH" << endl;
2872 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2873 out << "echo $ROOTSYS" << endl;
2874 out << "echo \"############## which root : ##############\"" << endl;
2875 out << "which root" << endl;
2876 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2877 out << "echo $ALICE_ROOT" << endl;
2878 out << "echo \"############## which aliroot : ##############\"" << endl;
2879 out << "which aliroot" << endl;
2880 out << "echo \"############## system limits : ##############\"" << endl;
2881 out << "ulimit -a" << endl;
2882 out << "echo \"############## memory : ##############\"" << endl;
2883 out << "free -m" << endl;
2884 out << "echo \"=========================================\"" << endl << endl;
2885 // Make sure we can properly compile par files
2886 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2887 out << fExecutableCommand << " ";
2888 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2889 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2890 out << "echo \"############## memory after: ##############\"" << endl;
2891 out << "free -m" << endl;
2893 Bool_t copy = kTRUE;
2894 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2897 TString workdir = gGrid->GetHomeDirectory();
2898 TString bindir = Form("%s/bin", workdir.Data());
2899 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2900 workdir += fGridWorkingDir;
2901 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2902 if (FileExists(executable)) gGrid->Rm(executable);
2903 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2904 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2908 //______________________________________________________________________________
2909 void AliAnalysisAlien::WriteMergeExecutable()
2911 // Generate the alien executable script for the merging job.
2912 if (!fMergeViaJDL) return;
2913 TString mergeExec = fExecutable;
2914 mergeExec.ReplaceAll(".sh", "_merge.sh");
2915 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2917 out.open(mergeExec.Data(), ios::out);
2919 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
2922 out << "#!/bin/bash" << endl;
2923 out << "echo \"=========================================\"" << endl;
2924 out << "echo \"############## PATH : ##############\"" << endl;
2925 out << "echo $PATH" << endl;
2926 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2927 out << "echo $LD_LIBRARY_PATH" << endl;
2928 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2929 out << "echo $ROOTSYS" << endl;
2930 out << "echo \"############## which root : ##############\"" << endl;
2931 out << "which root" << endl;
2932 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2933 out << "echo $ALICE_ROOT" << endl;
2934 out << "echo \"############## which aliroot : ##############\"" << endl;
2935 out << "which aliroot" << endl;
2936 out << "echo \"############## system limits : ##############\"" << endl;
2937 out << "ulimit -a" << endl;
2938 out << "echo \"############## memory : ##############\"" << endl;
2939 out << "free -m" << endl;
2940 out << "echo \"=========================================\"" << endl << endl;
2941 // Make sure we can properly compile par files
2942 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2943 TString mergeMacro = fExecutable;
2944 mergeMacro.ReplaceAll(".sh", "_merge.C");
2945 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
2946 out << fExecutableCommand << " " << "$ARG" << endl;
2947 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
2948 out << "echo \"############## memory after: ##############\"" << endl;
2949 out << "free -m" << endl;
2951 Bool_t copy = kTRUE;
2952 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2955 TString workdir = gGrid->GetHomeDirectory();
2956 TString bindir = Form("%s/bin", workdir.Data());
2957 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2958 workdir += fGridWorkingDir;
2959 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
2960 if (FileExists(executable)) gGrid->Rm(executable);
2961 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
2962 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
2966 //______________________________________________________________________________
2967 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2969 // Write the production file to be submitted by LPM manager. The format is:
2970 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2971 // Next lines: full_path_to_dataset XXX (XXX is a string)
2972 // To submit, one has to: submit jdl XXX for all lines
2974 out.open(filename, ios::out);
2976 Error("WriteProductionFile", "Bad file name: %s", filename);
2979 TString workdir = gGrid->GetHomeDirectory();
2980 workdir += fGridWorkingDir;
2981 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2982 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2983 out << locjdl << " " << njobspermaster << endl;
2984 Int_t nmasterjobs = fInputFiles->GetEntries();
2985 for (Int_t i=0; i<nmasterjobs; i++) {
2986 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2987 runOutDir.ReplaceAll(".xml", "");
2989 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
2991 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2993 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2994 if (FileExists(filename)) gGrid->Rm(filename);
2995 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2998 //______________________________________________________________________________
2999 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3001 // Generate the alien validation script.
3002 // Generate the validation script
3004 TString validationScript = fExecutable;
3005 if (merge) validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
3006 else validationScript.ReplaceAll(".sh", "_validation.sh");
3008 Error("WriteValidationScript", "Alien connection required");
3011 TString outStream = "";
3012 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3013 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3015 out.open(validationScript, ios::out);
3016 out << "#!/bin/bash" << endl;
3017 out << "##################################################" << endl;
3018 out << "validateout=`dirname $0`" << endl;
3019 out << "validatetime=`date`" << endl;
3020 out << "validated=\"0\";" << endl;
3021 out << "error=0" << endl;
3022 out << "if [ -z $validateout ]" << endl;
3023 out << "then" << endl;
3024 out << " validateout=\".\"" << endl;
3025 out << "fi" << endl << endl;
3026 out << "cd $validateout;" << endl;
3027 out << "validateworkdir=`pwd`;" << endl << endl;
3028 out << "echo \"*******************************************************\"" << outStream << endl;
3029 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3031 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3032 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3033 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3034 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3035 out << "ls -la ./" << outStream << endl;
3036 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3037 out << "##################################################" << endl;
3040 out << "if [ ! -f stderr ] ; then" << endl;
3041 out << " error=1" << endl;
3042 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3043 out << " echo \"Error = $error\" " << outStream << endl;
3044 out << "fi" << endl;
3046 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3047 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3048 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3049 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3052 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3053 out << " error=1" << endl;
3054 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3055 out << " echo \"$parArch\" " << outStream << endl;
3056 out << " echo \"Error = $error\" " << outStream << endl;
3057 out << "fi" << endl;
3059 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3060 out << " error=1" << endl;
3061 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3062 out << " echo \"$segViol\" " << outStream << endl;
3063 out << " echo \"Error = $error\" " << outStream << endl;
3064 out << "fi" << endl;
3066 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3067 out << " error=1" << endl;
3068 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3069 out << " echo \"$segFault\" " << outStream << endl;
3070 out << " echo \"Error = $error\" " << outStream << endl;
3071 out << "fi" << endl;
3073 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3074 out << " error=1" << endl;
3075 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3076 out << " echo \"$glibcErr\" " << outStream << endl;
3077 out << " echo \"Error = $error\" " << outStream << endl;
3078 out << "fi" << endl;
3080 // Part dedicated to the specific analyses running into the train
3082 TObjArray *arr = fOutputFiles.Tokenize(",");
3085 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3086 TString extra = mgr->GetExtraFiles();
3087 while ((os=(TObjString*)next1())) {
3088 outputFile = os->GetString();
3089 Int_t index = outputFile.Index("@");
3090 if (index > 0) outputFile.Remove(index);
3091 if (merge && fMergeExcludes.Contains(outputFile)) continue;
3092 if (extra.Contains(outputFile)) continue;
3093 if (outputFile.Contains("*")) continue;
3094 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
3095 out << " error=1" << endl;
3096 out << " echo \"Output file(s) not found. Job FAILED !\"" << outStream << endl;
3097 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
3098 out << "fi" << endl;
3102 out << "if ! [ -f outputs_valid ] ; then" << endl;
3103 out << " error=1" << endl;
3104 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3105 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3106 out << "fi" << endl;
3109 out << "if [ $error = 0 ] ; then" << endl;
3110 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
3111 if (!IsKeepLogs()) {
3112 out << " echo \"* === Logs std* will be deleted === \"" << endl;
3114 out << " rm -f std*" << endl;
3116 out << "fi" << endl;
3118 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3119 out << "echo \"*******************************************************\"" << outStream << endl;
3120 out << "cd -" << endl;
3121 out << "exit $error" << endl;
3123 Bool_t copy = kTRUE;
3124 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3127 TString workdir = gGrid->GetHomeDirectory();
3128 workdir += fGridWorkingDir;
3129 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
3130 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3131 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));