1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "AliAnalysisAlien.h"
25 #include "Riostream.h"
33 #include "TFileCollection.h"
35 #include "TObjString.h"
36 #include "TObjArray.h"
38 #include "TGridResult.h"
39 #include "TGridCollection.h"
41 #include "TGridJobStatusList.h"
42 #include "TGridJobStatus.h"
43 #include "TFileMerger.h"
44 #include "AliAnalysisManager.h"
45 #include "AliVEventHandler.h"
46 #include "AliAnalysisDataContainer.h"
47 #include "AliMultiInputEventHandler.h"
49 ClassImp(AliAnalysisAlien)
55 Bool_t copyLocal2Alien(const char* where, const char* loc, const char* rem)
57 TString sl(Form("file:%s", loc));
58 TString sr(Form("alien://%s", rem));
59 Bool_t ret = TFile::Cp(sl, sr);
61 Warning(where, "Failed to copy %s to %s", sl.Data(), sr.Data());
67 //______________________________________________________________________________
68 AliAnalysisAlien::AliAnalysisAlien()
74 fSplitMaxInputFileNumber(0),
76 fMasterResubmitThreshold(0),
89 fNproofWorkersPerSlave(0),
99 fAdditionalRootLibs(),
127 fRootVersionForProof(),
138 //______________________________________________________________________________
139 AliAnalysisAlien::AliAnalysisAlien(const char *name)
140 :AliAnalysisGrid(name),
145 fSplitMaxInputFileNumber(0),
147 fMasterResubmitThreshold(0),
160 fNproofWorkersPerSlave(0),
164 fExecutableCommand(),
170 fAdditionalRootLibs(),
198 fRootVersionForProof(),
209 //______________________________________________________________________________
210 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
211 :AliAnalysisGrid(other),
214 fPrice(other.fPrice),
216 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
217 fMaxInitFailed(other.fMaxInitFailed),
218 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
219 fNtestFiles(other.fNtestFiles),
220 fNrunsPerMaster(other.fNrunsPerMaster),
221 fMaxMergeFiles(other.fMaxMergeFiles),
222 fMaxMergeStages(other.fMaxMergeStages),
223 fNsubmitted(other.fNsubmitted),
224 fProductionMode(other.fProductionMode),
225 fOutputToRunNo(other.fOutputToRunNo),
226 fMergeViaJDL(other.fMergeViaJDL),
227 fFastReadOption(other.fFastReadOption),
228 fOverwriteMode(other.fOverwriteMode),
229 fNreplicas(other.fNreplicas),
230 fNproofWorkers(other.fNproofWorkers),
231 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
232 fProofReset(other.fProofReset),
233 fRunNumbers(other.fRunNumbers),
234 fExecutable(other.fExecutable),
235 fExecutableCommand(other.fExecutableCommand),
236 fArguments(other.fArguments),
237 fExecutableArgs(other.fExecutableArgs),
238 fAnalysisMacro(other.fAnalysisMacro),
239 fAnalysisSource(other.fAnalysisSource),
240 fValidationScript(other.fValidationScript),
241 fAdditionalRootLibs(other.fAdditionalRootLibs),
242 fAdditionalLibs(other.fAdditionalLibs),
243 fSplitMode(other.fSplitMode),
244 fAPIVersion(other.fAPIVersion),
245 fROOTVersion(other.fROOTVersion),
246 fAliROOTVersion(other.fAliROOTVersion),
247 fExternalPackages(other.fExternalPackages),
249 fGridWorkingDir(other.fGridWorkingDir),
250 fGridDataDir(other.fGridDataDir),
251 fDataPattern(other.fDataPattern),
252 fGridOutputDir(other.fGridOutputDir),
253 fOutputArchive(other.fOutputArchive),
254 fOutputFiles(other.fOutputFiles),
255 fInputFormat(other.fInputFormat),
256 fDatasetName(other.fDatasetName),
257 fJDLName(other.fJDLName),
258 fTerminateFiles(other.fTerminateFiles),
259 fMergeExcludes(other.fMergeExcludes),
260 fIncludePath(other.fIncludePath),
261 fCloseSE(other.fCloseSE),
262 fFriendChainName(other.fFriendChainName),
263 fJobTag(other.fJobTag),
264 fOutputSingle(other.fOutputSingle),
265 fRunPrefix(other.fRunPrefix),
266 fProofCluster(other.fProofCluster),
267 fProofDataSet(other.fProofDataSet),
268 fFileForTestMode(other.fFileForTestMode),
269 fRootVersionForProof(other.fRootVersionForProof),
270 fAliRootMode(other.fAliRootMode),
271 fMergeDirName(other.fMergeDirName),
277 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
278 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
279 fRunRange[0] = other.fRunRange[0];
280 fRunRange[1] = other.fRunRange[1];
281 if (other.fInputFiles) {
282 fInputFiles = new TObjArray();
283 TIter next(other.fInputFiles);
285 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
286 fInputFiles->SetOwner();
288 if (other.fPackages) {
289 fPackages = new TObjArray();
290 TIter next(other.fPackages);
292 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
293 fPackages->SetOwner();
297 //______________________________________________________________________________
298 AliAnalysisAlien::~AliAnalysisAlien()
301 if (fGridJDL) delete fGridJDL;
302 if (fMergingJDL) delete fMergingJDL;
303 if (fInputFiles) delete fInputFiles;
304 if (fPackages) delete fPackages;
305 fProofParam.DeleteAll();
308 //______________________________________________________________________________
309 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
312 if (this != &other) {
313 AliAnalysisGrid::operator=(other);
314 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
315 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
316 fPrice = other.fPrice;
318 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
319 fMaxInitFailed = other.fMaxInitFailed;
320 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
321 fNtestFiles = other.fNtestFiles;
322 fNrunsPerMaster = other.fNrunsPerMaster;
323 fMaxMergeFiles = other.fMaxMergeFiles;
324 fMaxMergeStages = other.fMaxMergeStages;
325 fNsubmitted = other.fNsubmitted;
326 fProductionMode = other.fProductionMode;
327 fOutputToRunNo = other.fOutputToRunNo;
328 fMergeViaJDL = other.fMergeViaJDL;
329 fFastReadOption = other.fFastReadOption;
330 fOverwriteMode = other.fOverwriteMode;
331 fNreplicas = other.fNreplicas;
332 fNproofWorkers = other.fNproofWorkers;
333 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
334 fProofReset = other.fProofReset;
335 fRunNumbers = other.fRunNumbers;
336 fExecutable = other.fExecutable;
337 fExecutableCommand = other.fExecutableCommand;
338 fArguments = other.fArguments;
339 fExecutableArgs = other.fExecutableArgs;
340 fAnalysisMacro = other.fAnalysisMacro;
341 fAnalysisSource = other.fAnalysisSource;
342 fValidationScript = other.fValidationScript;
343 fAdditionalRootLibs = other.fAdditionalRootLibs;
344 fAdditionalLibs = other.fAdditionalLibs;
345 fSplitMode = other.fSplitMode;
346 fAPIVersion = other.fAPIVersion;
347 fROOTVersion = other.fROOTVersion;
348 fAliROOTVersion = other.fAliROOTVersion;
349 fExternalPackages = other.fExternalPackages;
351 fGridWorkingDir = other.fGridWorkingDir;
352 fGridDataDir = other.fGridDataDir;
353 fDataPattern = other.fDataPattern;
354 fGridOutputDir = other.fGridOutputDir;
355 fOutputArchive = other.fOutputArchive;
356 fOutputFiles = other.fOutputFiles;
357 fInputFormat = other.fInputFormat;
358 fDatasetName = other.fDatasetName;
359 fJDLName = other.fJDLName;
360 fTerminateFiles = other.fTerminateFiles;
361 fMergeExcludes = other.fMergeExcludes;
362 fIncludePath = other.fIncludePath;
363 fCloseSE = other.fCloseSE;
364 fFriendChainName = other.fFriendChainName;
365 fJobTag = other.fJobTag;
366 fOutputSingle = other.fOutputSingle;
367 fRunPrefix = other.fRunPrefix;
368 fProofCluster = other.fProofCluster;
369 fProofDataSet = other.fProofDataSet;
370 fFileForTestMode = other.fFileForTestMode;
371 fRootVersionForProof = other.fRootVersionForProof;
372 fAliRootMode = other.fAliRootMode;
373 fMergeDirName = other.fMergeDirName;
374 if (other.fInputFiles) {
375 fInputFiles = new TObjArray();
376 TIter next(other.fInputFiles);
378 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
379 fInputFiles->SetOwner();
381 if (other.fPackages) {
382 fPackages = new TObjArray();
383 TIter next(other.fPackages);
385 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
386 fPackages->SetOwner();
392 //______________________________________________________________________________
393 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
395 // Set the run number format. Can be a prefix or a format like "%09d"
397 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
400 //______________________________________________________________________________
401 void AliAnalysisAlien::AddIncludePath(const char *path)
403 // Add include path in the remote analysis macro.
405 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
406 else fIncludePath += Form("-I%s ", path);
409 //______________________________________________________________________________
410 void AliAnalysisAlien::AddRunNumber(Int_t run)
412 // Add a run number to the list of runs to be processed.
413 if (fRunNumbers.Length()) fRunNumbers += " ";
414 fRunNumbers += Form(fRunPrefix.Data(), run);
417 //______________________________________________________________________________
418 void AliAnalysisAlien::AddRunList(const char* runList)
420 // Add several runs into the list of runs; they are expected to be separated by a blank character.
421 TString sList = runList;
422 TObjArray *list = sList.Tokenize(" ");
423 Int_t n = list->GetEntries();
424 for (Int_t i = 0; i < n; i++) {
425 TObjString *os = (TObjString*)list->At(i);
426 AddRunNumber(os->GetString().Atoi());
431 //______________________________________________________________________________
432 void AliAnalysisAlien::AddRunNumber(const char* run)
434 // Add a run number to the list of runs to be processed.
437 TObjArray *arr = runs.Tokenize(" ");
440 prefix.Append(fRunPrefix, fRunPrefix.Index("%d"));
441 while ((os=(TObjString*)next())){
442 if (fRunNumbers.Length()) fRunNumbers += " ";
443 fRunNumbers += Form("%s%s", prefix.Data(), os->GetString().Data());
448 //______________________________________________________________________________
449 void AliAnalysisAlien::AddDataFile(const char *lfn)
451 // Adds a data file to the input to be analysed. The file should be a valid LFN
452 // or point to an existing file in the alien workdir.
453 if (!fInputFiles) fInputFiles = new TObjArray();
454 fInputFiles->Add(new TObjString(lfn));
457 //______________________________________________________________________________
458 void AliAnalysisAlien::AddExternalPackage(const char *package)
460 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
461 if (fExternalPackages) fExternalPackages += " ";
462 fExternalPackages += package;
465 //______________________________________________________________________________
466 Bool_t AliAnalysisAlien::Connect()
468 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
469 if (gGrid && gGrid->IsConnected()) return kTRUE;
470 if (fProductionMode) return kTRUE;
472 Info("Connect", "Trying to connect to AliEn ...");
473 TGrid::Connect("alien://");
475 if (!gGrid || !gGrid->IsConnected()) {
476 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
479 fUser = gGrid->GetUser();
480 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
484 //______________________________________________________________________________
485 void AliAnalysisAlien::CdWork()
487 // Check validity of alien workspace. Create directory if possible.
489 Error("CdWork", "Alien connection required");
492 TString homedir = gGrid->GetHomeDirectory();
493 TString workdir = homedir + fGridWorkingDir;
494 if (DirectoryExists(workdir)) {
498 // Work directory not existing - create it
500 if (gGrid->Mkdir(workdir, "-p")) {
501 gGrid->Cd(fGridWorkingDir);
502 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
504 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
505 workdir.Data(), homedir.Data());
506 fGridWorkingDir = "";
510 //______________________________________________________________________________
511 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
513 // Check if file copying is possible.
514 if (fProductionMode) return kTRUE;
516 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
519 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
520 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
521 // Check if alien_CLOSE_SE is defined
522 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
523 if (!closeSE.IsNull()) {
524 Info("CheckFileCopy", "Your current close storage is pointing to: \
525 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
527 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
529 // Check if grid directory exists.
530 if (!DirectoryExists(alienpath)) {
531 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
534 TFile f("plugin_test_copy", "RECREATE");
535 // User may not have write permissions to current directory
537 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
538 gSystem->WorkingDirectory());
542 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
543 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
544 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
545 \n# 1. Make sure you have write permissions there. If this is the case: \
546 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
547 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
548 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
549 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
550 gSystem->Unlink(f.GetName());
553 gSystem->Unlink(f.GetName());
554 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
555 Info("CheckFileCopy", "### ...SUCCESS ###");
559 //______________________________________________________________________________
560 Bool_t AliAnalysisAlien::CheckInputData()
562 // Check validity of input data. If necessary, create xml files.
563 if (fProductionMode) return kTRUE;
564 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
565 if (!fGridDataDir.Length()) {
566 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
570 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
573 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
574 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
575 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
578 // Process declared files
579 Bool_t isCollection = kFALSE;
580 Bool_t isXml = kFALSE;
581 Bool_t useTags = kFALSE;
582 Bool_t checked = kFALSE;
583 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
585 TString workdir = gGrid->GetHomeDirectory();
586 workdir += fGridWorkingDir;
589 TIter next(fInputFiles);
590 while ((objstr=(TObjString*)next())) {
593 file += objstr->GetString();
594 // Store full lfn path
595 if (FileExists(file)) objstr->SetString(file);
597 file = objstr->GetName();
598 if (!FileExists(objstr->GetName())) {
599 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
600 objstr->GetName(), workdir.Data());
604 Bool_t iscoll, isxml, usetags;
605 CheckDataType(file, iscoll, isxml, usetags);
608 isCollection = iscoll;
611 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
613 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
614 Error("CheckInputData", "Some conflict was found in the types of inputs");
620 // Process requested run numbers
621 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
622 // Check validity of alien data directory
623 if (!fGridDataDir.Length()) {
624 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
627 if (!DirectoryExists(fGridDataDir)) {
628 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
632 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
636 if (checked && !isXml) {
637 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
640 // Check validity of run number(s)
645 TString schunk, schunk2;
649 useTags = fDataPattern.Contains("tag");
650 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
652 if (useTags != fDataPattern.Contains("tag")) {
653 Error("CheckInputData", "Cannot mix input files using/not using tags");
656 if (fRunNumbers.Length()) {
657 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
658 arr = fRunNumbers.Tokenize(" ");
660 while ((os=(TObjString*)next())) {
661 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
662 if (!DirectoryExists(path)) {
663 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
666 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
667 TString msg = "\n##### file: ";
669 msg += " type: xml_collection;";
670 if (useTags) msg += " using_tags: Yes";
671 else msg += " using_tags: No";
672 Info("CheckDataType", "%s", msg.Data());
673 if (fNrunsPerMaster<2) {
674 AddDataFile(Form("%s.xml", os->GetString().Data()));
677 if (((nruns-1)%fNrunsPerMaster) == 0) {
678 schunk = os->GetString();
680 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
681 schunk += Form("_%s.xml", os->GetString().Data());
687 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
688 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
689 format = Form("%%s/%s ", fRunPrefix.Data());
690 path = Form(format.Data(), fGridDataDir.Data(), irun);
691 if (!DirectoryExists(path)) {
694 format = Form("%%s/%s.xml", fRunPrefix.Data());
695 path = Form(format.Data(), workdir.Data(),irun);
696 TString msg = "\n##### file: ";
698 msg += " type: xml_collection;";
699 if (useTags) msg += " using_tags: Yes";
700 else msg += " using_tags: No";
701 Info("CheckDataType", "%s", msg.Data());
702 if (fNrunsPerMaster<2) {
703 format = Form("%s.xml", fRunPrefix.Data());
704 AddDataFile(Form(format.Data(),irun));
707 if (((nruns-1)%fNrunsPerMaster) == 0) {
708 schunk = Form(fRunPrefix.Data(),irun);
710 format = Form("_%s.xml", fRunPrefix.Data());
711 schunk2 = Form(format.Data(), irun);
712 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
725 //______________________________________________________________________________
726 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
728 // Create dataset for the grid data directory + run number.
729 const Int_t gMaxEntries = 15000;
730 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
732 Error("CreateDataset", "Cannot create dataset with no grid connection");
737 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
738 TString workdir = gGrid->GetHomeDirectory();
739 workdir += fGridWorkingDir;
741 // Compose the 'find' command arguments
744 TString options = "-x collection ";
745 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
746 else options += Form("-l %d ", gMaxEntries); // Protection for the find command
747 TString conditions = "";
754 TString schunk, schunk2;
755 TGridCollection *cbase=0, *cadd=0;
756 if (!fRunNumbers.Length() && !fRunRange[0]) {
757 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
758 // Make a single data collection from data directory.
760 if (!DirectoryExists(path)) {
761 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
765 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
766 else file = Form("%s.xml", gSystem->BaseName(path));
770 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
772 command += Form("%s -o %d ",options.Data(), nstart);
776 command += conditions;
777 printf("command: %s\n", command.Data());
778 TGridResult *res = gGrid->Command(command);
780 // Write standard output to file
781 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage, file.Data()));
782 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
783 Bool_t nullFile = kFALSE;
785 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
787 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
789 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
790 gSystem->Exec("rm -f __tmp*");
798 gSystem->Exec("rm -f __tmp__");
799 ncount = line.Atoi();
802 if (ncount == gMaxEntries) {
803 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
804 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
805 if (!cbase) cbase = cadd;
813 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
814 printf("... please wait - TAlienCollection::Add() scales badly...\n");
817 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
818 delete cbase; cbase = 0;
820 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
822 gSystem->Exec("rm -f __tmp*");
823 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
827 Bool_t fileExists = FileExists(file);
828 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
829 // Copy xml file to alien space
830 if (fileExists) gGrid->Rm(file);
831 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
832 if (!FileExists(file)) {
833 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
836 // Update list of files to be processed.
838 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
842 Bool_t nullResult = kTRUE;
843 if (fRunNumbers.Length()) {
844 TObjArray *arr = fRunNumbers.Tokenize(" ");
847 while ((os=(TObjString*)next())) {
850 path = Form("%s/%s/ ", fGridDataDir.Data(), os->GetString().Data());
851 if (!DirectoryExists(path)) continue;
853 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
854 else file = Form("%s.xml", os->GetString().Data());
855 // If local collection file does not exist, create it via 'find' command.
859 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
861 command += Form("%s -o %d ",options.Data(), nstart);
864 command += conditions;
865 TGridResult *res = gGrid->Command(command);
867 // Write standard output to file
868 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
869 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
870 Bool_t nullFile = kFALSE;
872 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
874 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
876 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
877 gSystem->Exec("rm -f __tmp*");
878 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
886 gSystem->Exec("rm -f __tmp__");
887 ncount = line.Atoi();
891 if (ncount == gMaxEntries) {
892 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
893 if (fNrunsPerMaster > 1) {
894 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
895 file.Data(),gMaxEntries);
898 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
899 if (!cbase) cbase = cadd;
906 if (cbase && fNrunsPerMaster<2) {
907 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
908 printf("... please wait - TAlienCollection::Add() scales badly...\n");
911 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
912 delete cbase; cbase = 0;
914 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
916 gSystem->Exec("rm -f __tmp*");
917 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
921 if (TestBit(AliAnalysisGrid::kTest)) break;
922 // Check if there is one run per master job.
923 if (fNrunsPerMaster<2) {
924 if (FileExists(file)) {
925 if (fOverwriteMode) gGrid->Rm(file);
927 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
931 // Copy xml file to alien space
932 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
933 if (!FileExists(file)) {
934 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
940 if (((nruns-1)%fNrunsPerMaster) == 0) {
941 schunk = os->GetString();
942 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
944 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
945 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
949 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
952 schunk += Form("_%s.xml", os->GetString().Data());
953 if (FileExists(schunk)) {
954 if (fOverwriteMode) gGrid->Rm(file);
956 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
960 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
961 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
962 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
963 if (!FileExists(schunk)) {
964 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
972 Error("CreateDataset", "No valid dataset corresponding to the query!");
976 // Process a full run range.
977 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
978 format = Form("%%s/%s ", fRunPrefix.Data());
981 path = Form(format.Data(), fGridDataDir.Data(), irun);
982 if (!DirectoryExists(path)) continue;
984 format = Form("%s.xml", fRunPrefix.Data());
985 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
986 else file = Form(format.Data(), irun);
987 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
988 if (fOverwriteMode) gGrid->Rm(file);
990 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
994 // If local collection file does not exist, create it via 'find' command.
998 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
1000 command += Form("%s -o %d ",options.Data(), nstart);
1003 command += conditions;
1004 TGridResult *res = gGrid->Command(command);
1005 if (res) delete res;
1006 // Write standard output to file
1007 gROOT->ProcessLine(Form("gGrid->Stdout(); > __tmp%d__%s", stage,file.Data()));
1008 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
1009 Bool_t nullFile = kFALSE;
1011 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
1013 nullFile = (gSystem->Exec(Form("grep -c /event __tmp%d__%s 2>/dev/null > __tmp__",stage,file.Data()))==0)?kFALSE:kTRUE;
1015 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
1016 gSystem->Exec("rm -f __tmp*");
1024 gSystem->Exec("rm -f __tmp__");
1025 ncount = line.Atoi();
1027 nullResult = kFALSE;
1029 if (ncount == gMaxEntries) {
1030 Info("CreateDataset", "Dataset %s has more than 15K entries. Trying to merge...", file.Data());
1031 if (fNrunsPerMaster > 1) {
1032 Error("CreateDataset", "File %s has more than %d entries. Please set the number of runs per master to 1 !",
1033 file.Data(),gMaxEntries);
1036 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1037 if (!cbase) cbase = cadd;
1044 if (cbase && fNrunsPerMaster<2) {
1045 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"__tmp%d__%s\", 1000000);",stage,file.Data()));
1046 printf("... please wait - TAlienCollection::Add() scales badly...\n");
1049 cbase->ExportXML(Form("file://%s", file.Data()),kFALSE,kFALSE, file, "Merged entries for a run");
1050 delete cbase; cbase = 0;
1052 TFile::Cp(Form("__tmp%d__%s",stage, file.Data()), file.Data());
1054 Info("CreateDataset", "Created dataset %s with %d files", file.Data(), nstart+ncount);
1058 if (TestBit(AliAnalysisGrid::kTest)) break;
1059 // Check if there is one run per master job.
1060 if (fNrunsPerMaster<2) {
1061 if (FileExists(file)) {
1062 if (fOverwriteMode) gGrid->Rm(file);
1064 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
1068 // Copy xml file to alien space
1069 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
1070 if (!FileExists(file)) {
1071 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
1076 // Check if the collection for the chunk exist locally.
1077 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
1078 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
1079 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
1082 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
1083 if (((nruns-1)%fNrunsPerMaster) == 0) {
1084 schunk = Form(fRunPrefix.Data(), irun);
1085 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1087 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
1091 format = Form("%%s_%s.xml", fRunPrefix.Data());
1092 schunk2 = Form(format.Data(), schunk.Data(), irun);
1093 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
1097 if (FileExists(schunk)) {
1098 if (fOverwriteMode) gGrid->Rm(schunk);
1100 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
1104 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
1105 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
1106 if (FileExists(schunk)) {
1107 if (fOverwriteMode) gGrid->Rm(schunk);
1109 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
1113 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
1114 if (!FileExists(schunk)) {
1115 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
1121 Error("CreateDataset", "No valid dataset corresponding to the query!");
1128 //______________________________________________________________________________
1129 Bool_t AliAnalysisAlien::CreateJDL()
1131 // Generate a JDL file according to current settings. The name of the file is
1132 // specified by fJDLName.
1133 Bool_t error = kFALSE;
1135 Bool_t copy = kTRUE;
1136 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1137 Bool_t generate = kTRUE;
1138 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
1140 Error("CreateJDL", "Alien connection required");
1143 // Check validity of alien workspace
1145 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1146 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
1147 workdir += fGridWorkingDir;
1151 Error("CreateJDL()", "Define some input files for your analysis.");
1154 // Compose list of input files
1155 // Check if output files were defined
1156 if (!fOutputFiles.Length()) {
1157 Error("CreateJDL", "You must define at least one output file");
1160 // Check if an output directory was defined and valid
1161 if (!fGridOutputDir.Length()) {
1162 Error("CreateJDL", "You must define AliEn output directory");
1165 if (!fProductionMode) {
1166 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1167 if (!DirectoryExists(fGridOutputDir)) {
1168 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1169 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1171 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1175 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1180 // Exit if any error up to now
1181 if (error) return kFALSE;
1183 if (!fUser.IsNull()) {
1184 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1185 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1187 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1188 TString mergeExec = fExecutable;
1189 mergeExec.ReplaceAll(".sh", "_merge.sh");
1190 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1191 mergeExec.ReplaceAll(".sh", ".C");
1192 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1193 if (!fArguments.IsNull())
1194 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1195 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1197 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1198 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1201 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1202 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1203 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1204 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1206 if (fMaxInitFailed > 0) {
1207 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1208 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1210 if (fSplitMaxInputFileNumber > 0) {
1211 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1212 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1214 if (!IsOneStageMerging()) {
1215 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1216 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1218 if (fSplitMode.Length()) {
1219 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1220 fGridJDL->SetDescription("Split", "We split per SE or file");
1222 fMergingJDL->SetValue("Split", "\"se\"");
1223 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1224 if (!fAliROOTVersion.IsNull()) {
1225 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1226 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1228 if (!fROOTVersion.IsNull()) {
1229 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1230 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1232 if (!fAPIVersion.IsNull()) {
1233 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1234 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1236 if (!fExternalPackages.IsNull()) {
1237 arr = fExternalPackages.Tokenize(" ");
1239 while ((os=(TObjString*)next())) {
1240 TString pkgname = os->GetString();
1241 Int_t index = pkgname.Index("::");
1242 TString pkgversion = pkgname(index+2, pkgname.Length());
1243 pkgname.Remove(index);
1244 fGridJDL->AddToPackages(pkgname, pkgversion);
1245 fMergingJDL->AddToPackages(pkgname, pkgversion);
1249 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1250 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1251 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1252 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1253 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1254 TString analysisFile = fExecutable;
1255 analysisFile.ReplaceAll(".sh", ".root");
1256 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1257 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1258 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1259 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1260 if (fAdditionalLibs.Length()) {
1261 arr = fAdditionalLibs.Tokenize(" ");
1263 while ((os=(TObjString*)next())) {
1264 if (os->GetString().Contains(".so")) continue;
1265 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1266 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1271 TIter next(fPackages);
1273 while ((obj=next())) {
1274 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1275 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1278 if (fOutputArchive.Length()) {
1279 arr = fOutputArchive.Tokenize(" ");
1281 Bool_t first = kTRUE;
1282 const char *comment = "Files to be archived";
1283 const char *comment1 = comment;
1284 while ((os=(TObjString*)next())) {
1285 if (!first) comment = NULL;
1286 if (!os->GetString().Contains("@") && fCloseSE.Length())
1287 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1289 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1293 // Output archive for the merging jdl
1294 TString outputArchive;
1295 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1296 outputArchive = "log_archive.zip:std*@disk=1 ";
1297 // Add normal output files, extra files + terminate files
1298 TString files = GetListOfFiles("outextter");
1299 // Do not register merge excludes
1300 if (!fMergeExcludes.IsNull()) {
1301 arr = fMergeExcludes.Tokenize(" ");
1303 while ((os=(TObjString*)next1())) {
1304 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1305 files.ReplaceAll(os->GetString(),"");
1309 files.ReplaceAll(".root", "*.root");
1310 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1312 TString files = fOutputArchive;
1313 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1314 outputArchive = files;
1316 arr = outputArchive.Tokenize(" ");
1320 while ((os=(TObjString*)next2())) {
1321 if (!first) comment = NULL;
1322 TString currentfile = os->GetString();
1323 if (!currentfile.Contains("@") && fCloseSE.Length())
1324 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1326 fMergingJDL->AddToOutputArchive(currentfile, comment);
1331 arr = fOutputFiles.Tokenize(",");
1333 Bool_t first = kTRUE;
1334 const char *comment = "Files to be saved";
1335 while ((os=(TObjString*)next())) {
1336 // Ignore ouputs in jdl that are also in outputarchive
1337 TString sout = os->GetString();
1338 sout.ReplaceAll("*", "");
1339 sout.ReplaceAll(".root", "");
1340 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1341 if (fOutputArchive.Contains(sout)) continue;
1342 if (!first) comment = NULL;
1343 if (!os->GetString().Contains("@") && fCloseSE.Length())
1344 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1346 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1348 if (fMergeExcludes.Contains(sout)) continue;
1349 if (!os->GetString().Contains("@") && fCloseSE.Length())
1350 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1352 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1355 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1356 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1357 TString validationScript = fValidationScript;
1358 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1359 validationScript.ReplaceAll(".sh", "_merge.sh");
1360 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1361 if (fMasterResubmitThreshold) {
1362 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1363 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1365 // Write a jdl with 2 input parameters: collection name and output dir name.
1368 // Copy jdl to grid workspace
1370 // Check if an output directory was defined and valid
1371 if (!fGridOutputDir.Length()) {
1372 Error("CreateJDL", "You must define AliEn output directory");
1375 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1376 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1377 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1378 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1380 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1386 if (TestBit(AliAnalysisGrid::kSubmit)) {
1387 TString mergeJDLName = fExecutable;
1388 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1389 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1390 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1391 if (fProductionMode) {
1392 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1393 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1395 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1396 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1397 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1398 if (!copyLocal2Alien("CreateJDL", fJDLName, locjdl))
1399 Fatal("","Terminating");
1400 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1402 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1403 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1404 if (!copyLocal2Alien("CreateJDL", mergeJDLName.Data(), locjdl1))
1405 Fatal("","Terminating");
1408 if (fAdditionalLibs.Length()) {
1409 arr = fAdditionalLibs.Tokenize(" ");
1412 while ((os=(TObjString*)next())) {
1413 if (os->GetString().Contains(".so")) continue;
1414 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1415 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1416 // TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1417 if (!copyLocal2Alien("CreateJDL", os->GetString().Data(),
1418 Form("%s/%s", workdir.Data(), os->GetString().Data())))
1419 Fatal("","Terminating");
1424 TIter next(fPackages);
1426 while ((obj=next())) {
1427 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1428 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1429 // TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1430 if (!copyLocal2Alien("CreateJDL",obj->GetName(),
1431 Form("%s/%s", workdir.Data(), obj->GetName())))
1432 Fatal("","Terminating");
1439 //______________________________________________________________________________
1440 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1442 // Writes one or more JDL's corresponding to findex. If findex is negative,
1443 // all run numbers are considered in one go (jdl). For non-negative indices
1444 // they correspond to the indices in the array fInputFiles.
1445 if (!fInputFiles) return kFALSE;
1448 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1449 workdir += fGridWorkingDir;
1450 TString stageName = "$2";
1451 if (fProductionMode) stageName = "$4";
1452 if (!fMergeDirName.IsNull()) {
1453 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1454 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1456 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1457 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1459 if (fProductionMode) {
1460 TIter next(fInputFiles);
1461 while ((os=next())) {
1462 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1464 if (!fOutputToRunNo)
1465 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1467 fGridJDL->SetOutputDirectory(fGridOutputDir);
1469 if (!fRunNumbers.Length() && !fRunRange[0]) {
1470 // One jdl with no parameters in case input data is specified by name.
1471 TIter next(fInputFiles);
1473 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1474 if (!fOutputSingle.IsNull())
1475 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1477 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1478 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1481 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1482 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1483 if (!fOutputSingle.IsNull()) {
1484 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1485 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1487 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1492 // Generate the JDL as a string
1493 TString sjdl = fGridJDL->Generate();
1494 TString sjdl1 = fMergingJDL->Generate();
1496 if (!fMergeDirName.IsNull()) {
1497 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1498 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1500 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1501 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1503 TString sjdl2 = fMergingJDL->Generate();
1504 Int_t index, index1;
1505 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1506 sjdl.ReplaceAll("(member", "\n (member");
1507 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1508 sjdl.ReplaceAll("{", "{\n ");
1509 sjdl.ReplaceAll("};", "\n};");
1510 sjdl.ReplaceAll("{\n \n", "{\n");
1511 sjdl.ReplaceAll("\n\n", "\n");
1512 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1513 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1514 sjdl1.ReplaceAll("(member", "\n (member");
1515 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1516 sjdl1.ReplaceAll("{", "{\n ");
1517 sjdl1.ReplaceAll("};", "\n};");
1518 sjdl1.ReplaceAll("{\n \n", "{\n");
1519 sjdl1.ReplaceAll("\n\n", "\n");
1520 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1521 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1522 sjdl2.ReplaceAll("(member", "\n (member");
1523 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1524 sjdl2.ReplaceAll("{", "{\n ");
1525 sjdl2.ReplaceAll("};", "\n};");
1526 sjdl2.ReplaceAll("{\n \n", "{\n");
1527 sjdl2.ReplaceAll("\n\n", "\n");
1528 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1529 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1530 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1531 index = sjdl.Index("JDLVariables");
1532 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1533 sjdl += "Workdirectorysize = {\"5000MB\"};";
1534 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1535 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1536 index = fJobTag.Index(":");
1537 if (index < 0) index = fJobTag.Length();
1538 TString jobTag = fJobTag;
1539 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1540 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1541 if (fProductionMode) {
1542 sjdl1.Prepend("# Generated merging jdl (production mode) \
1543 \n# $1 = full alien path to output directory to be merged \
1544 \n# $2 = train number \
1545 \n# $3 = production (like LHC10b) \
1546 \n# $4 = merging stage \
1547 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1548 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1549 sjdl2.Prepend("# Generated merging jdl \
1550 \n# $1 = full alien path to output directory to be merged \
1551 \n# $2 = train number \
1552 \n# $3 = production (like LHC10b) \
1553 \n# $4 = merging stage \
1554 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1556 sjdl1.Prepend("# Generated merging jdl \
1557 \n# $1 = full alien path to output directory to be merged \
1558 \n# $2 = merging stage \
1559 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1560 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1561 sjdl2.Prepend("# Generated merging jdl \
1562 \n# $1 = full alien path to output directory to be merged \
1563 \n# $2 = merging stage \
1564 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1566 index = sjdl1.Index("JDLVariables");
1567 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1568 index = sjdl2.Index("JDLVariables");
1569 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1570 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1571 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1572 index = sjdl2.Index("Split =");
1574 index1 = sjdl2.Index("\n", index);
1575 sjdl2.Remove(index, index1-index+1);
1577 index = sjdl2.Index("SplitMaxInputFileNumber");
1579 index1 = sjdl2.Index("\n", index);
1580 sjdl2.Remove(index, index1-index+1);
1582 index = sjdl2.Index("InputDataCollection");
1584 index1 = sjdl2.Index(";", index);
1585 sjdl2.Remove(index, index1-index+1);
1587 index = sjdl2.Index("InputDataListFormat");
1589 index1 = sjdl2.Index("\n", index);
1590 sjdl2.Remove(index, index1-index+1);
1592 index = sjdl2.Index("InputDataList");
1594 index1 = sjdl2.Index("\n", index);
1595 sjdl2.Remove(index, index1-index+1);
1597 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1598 // Write jdl to file
1600 out.open(fJDLName.Data(), ios::out);
1602 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1605 out << sjdl << endl;
1607 TString mergeJDLName = fExecutable;
1608 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1611 out1.open(mergeJDLName.Data(), ios::out);
1613 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1616 out1 << sjdl1 << endl;
1619 TString finalJDL = mergeJDLName;
1620 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1621 out2.open(finalJDL.Data(), ios::out);
1623 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1626 out2 << sjdl2 << endl;
1630 // Copy jdl to grid workspace
1632 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1634 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1635 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1636 TString finalJDL = mergeJDLName;
1637 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1638 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1639 if (fProductionMode) {
1640 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1641 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1642 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1644 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1645 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1646 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1647 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1648 // TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1649 if (!copyLocal2Alien("WriteJDL",fJDLName.Data(),locjdl.Data()))
1650 Fatal("","Terminating");
1652 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1653 // TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1654 // TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1655 if (!copyLocal2Alien("WriteJDL",mergeJDLName.Data(),locjdl1.Data()))
1656 Fatal("","Terminating");
1657 if (!copyLocal2Alien("WriteJDL",finalJDL.Data(),locjdl2.Data()))
1658 Fatal("","Terminating");
1664 //______________________________________________________________________________
1665 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1667 // Returns true if file exists.
1668 if (!gGrid) return kFALSE;
1670 slfn.ReplaceAll("alien://","");
1671 TGridResult *res = gGrid->Ls(slfn);
1672 if (!res) return kFALSE;
1673 TMap *map = dynamic_cast<TMap*>(res->At(0));
1678 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1679 if (!objs || !objs->GetString().Length()) {
1687 //______________________________________________________________________________
1688 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1690 // Returns true if directory exists. Can be also a path.
1691 if (!gGrid) return kFALSE;
1692 // Check if dirname is a path
1693 TString dirstripped = dirname;
1694 dirstripped = dirstripped.Strip();
1695 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1696 TString dir = gSystem->BaseName(dirstripped);
1698 TString path = gSystem->DirName(dirstripped);
1699 TGridResult *res = gGrid->Ls(path, "-F");
1700 if (!res) return kFALSE;
1704 while ((map=dynamic_cast<TMap*>(next()))) {
1705 obj = map->GetValue("name");
1707 if (dir == obj->GetName()) {
1716 //______________________________________________________________________________
1717 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1719 // Check input data type.
1720 isCollection = kFALSE;
1724 Error("CheckDataType", "No connection to grid");
1727 isCollection = IsCollection(lfn);
1728 TString msg = "\n##### file: ";
1731 msg += " type: raw_collection;";
1732 // special treatment for collections
1734 // check for tag files in the collection
1735 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1737 msg += " using_tags: No (unknown)";
1738 Info("CheckDataType", "%s", msg.Data());
1741 const char* typeStr = res->GetKey(0, "origLFN");
1742 if (!typeStr || !strlen(typeStr)) {
1743 msg += " using_tags: No (unknown)";
1744 Info("CheckDataType", "%s", msg.Data());
1747 TString file = typeStr;
1748 useTags = file.Contains(".tag");
1749 if (useTags) msg += " using_tags: Yes";
1750 else msg += " using_tags: No";
1751 Info("CheckDataType", "%s", msg.Data());
1756 isXml = slfn.Contains(".xml");
1758 // Open xml collection and check if there are tag files inside
1759 msg += " type: xml_collection;";
1760 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1762 msg += " using_tags: No (unknown)";
1763 Info("CheckDataType", "%s", msg.Data());
1766 TMap *map = coll->Next();
1768 msg += " using_tags: No (unknown)";
1769 Info("CheckDataType", "%s", msg.Data());
1772 map = (TMap*)map->GetValue("");
1774 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1775 useTags = file.Contains(".tag");
1777 if (useTags) msg += " using_tags: Yes";
1778 else msg += " using_tags: No";
1779 Info("CheckDataType", "%s", msg.Data());
1782 useTags = slfn.Contains(".tag");
1783 if (slfn.Contains(".root")) msg += " type: root file;";
1784 else msg += " type: unknown file;";
1785 if (useTags) msg += " using_tags: Yes";
1786 else msg += " using_tags: No";
1787 Info("CheckDataType", "%s", msg.Data());
1790 //______________________________________________________________________________
1791 void AliAnalysisAlien::EnablePackage(const char *package)
1793 // Enables a par file supposed to exist in the current directory.
1794 TString pkg(package);
1795 pkg.ReplaceAll(".par", "");
1797 if (gSystem->AccessPathName(pkg)) {
1798 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1801 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1802 Info("EnablePackage", "AliEn plugin will use .par packages");
1803 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1805 fPackages = new TObjArray();
1806 fPackages->SetOwner();
1808 fPackages->Add(new TObjString(pkg));
1811 //______________________________________________________________________________
1812 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1814 // Make a tree from files having the location specified in fFileForTestMode.
1815 // Inspired from JF's CreateESDChain.
1816 if (fFileForTestMode.IsNull()) {
1817 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1820 if (gSystem->AccessPathName(fFileForTestMode)) {
1821 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1826 in.open(fFileForTestMode);
1828 // Read the input list of files and add them to the chain
1830 TChain *chain = new TChain(treeName);
1834 if (line.IsNull()) continue;
1835 if (count++ == fNtestFiles) break;
1836 TString esdFile(line);
1837 TFile *file = TFile::Open(esdFile);
1839 if (!file->IsZombie()) chain->Add(esdFile);
1842 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1846 if (!chain->GetListOfFiles()->GetEntries()) {
1847 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1855 //______________________________________________________________________________
1856 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1858 // Get job status for all jobs with jobid>jobidstart.
1859 static char mstatus[20];
1865 TGridJobStatusList *list = gGrid->Ps("");
1866 if (!list) return mstatus;
1867 Int_t nentries = list->GetSize();
1868 TGridJobStatus *status;
1870 for (Int_t ijob=0; ijob<nentries; ijob++) {
1871 status = (TGridJobStatus *)list->At(ijob);
1872 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1873 if (pid<jobidstart) continue;
1874 if (pid == lastid) {
1875 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1877 switch (status->GetStatus()) {
1878 case TGridJobStatus::kWAITING:
1880 case TGridJobStatus::kRUNNING:
1882 case TGridJobStatus::kABORTED:
1883 case TGridJobStatus::kFAIL:
1884 case TGridJobStatus::kUNKNOWN:
1886 case TGridJobStatus::kDONE:
1895 //______________________________________________________________________________
1896 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1898 // Returns true if file is a collection. Functionality duplicated from
1899 // TAlien::Type() because we don't want to directly depend on TAlien.
1901 Error("IsCollection", "No connection to grid");
1904 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1905 if (!res) return kFALSE;
1906 const char* typeStr = res->GetKey(0, "type");
1907 if (!typeStr || !strlen(typeStr)) return kFALSE;
1908 if (!strcmp(typeStr, "collection")) return kTRUE;
1913 //______________________________________________________________________________
1914 Bool_t AliAnalysisAlien::IsSingleOutput() const
1916 // Check if single-ouput option is on.
1917 return (!fOutputSingle.IsNull());
1920 //______________________________________________________________________________
1921 void AliAnalysisAlien::Print(Option_t *) const
1923 // Print current plugin settings.
1924 printf("### AliEn analysis plugin current settings ###\n");
1925 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1926 if (mgr && mgr->IsProofMode()) {
1927 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1928 if (TestBit(AliAnalysisGrid::kTest))
1929 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1930 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1931 if (!fProofDataSet.IsNull())
1932 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1934 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1936 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1937 if (!fRootVersionForProof.IsNull())
1938 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1940 printf("= ROOT version requested________________________ default\n");
1941 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1942 if (!fAliRootMode.IsNull())
1943 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1945 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1946 if (fNproofWorkersPerSlave)
1947 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1948 if (TestSpecialBit(kClearPackages))
1949 printf("= ClearPackages requested...\n");
1950 if (fIncludePath.Data())
1951 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1952 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1953 if (fPackages && fPackages->GetEntries()) {
1954 TIter next(fPackages);
1957 while ((obj=next())) list += obj->GetName();
1958 printf("= Par files to be used: ________________________ %s\n", list.Data());
1960 if (TestSpecialBit(kProofConnectGrid))
1961 printf("= Requested PROOF connection to grid\n");
1964 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1965 if (fOverwriteMode) {
1966 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1967 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1969 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1970 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1971 printf("= Production mode:______________________________ %d\n", fProductionMode);
1972 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1973 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1974 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1976 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1977 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1978 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1979 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1980 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1981 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1982 if (fRunNumbers.Length())
1983 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1985 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1986 if (!fRunRange[0] && !fRunNumbers.Length()) {
1987 TIter next(fInputFiles);
1990 while ((obj=next())) list += obj->GetName();
1991 printf("= Input files to be processed: _________________ %s\n", list.Data());
1993 if (TestBit(AliAnalysisGrid::kTest))
1994 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1995 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1996 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1997 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1998 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1999 printf("=====================================================================\n");
2000 printf("= Job price: ___________________________________ %d\n", fPrice);
2001 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
2002 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
2003 if (fMaxInitFailed>0)
2004 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
2005 if (fMasterResubmitThreshold>0)
2006 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
2007 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
2008 if (fNrunsPerMaster>0)
2009 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
2010 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
2011 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
2012 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
2013 if (fArguments.Length())
2014 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
2015 if (fExecutableArgs.Length())
2016 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
2017 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
2018 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
2019 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
2020 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
2022 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
2023 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
2024 if (fIncludePath.Data())
2025 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
2026 if (fCloseSE.Length())
2027 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
2028 if (fFriendChainName.Length())
2029 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
2030 if (fPackages && fPackages->GetEntries()) {
2031 TIter next(fPackages);
2034 while ((obj=next())) list += obj->GetName();
2035 printf("= Par files to be used: ________________________ %s\n", list.Data());
2039 //______________________________________________________________________________
2040 void AliAnalysisAlien::SetDefaults()
2042 // Set default values for everything. What cannot be filled will be left empty.
2043 if (fGridJDL) delete fGridJDL;
2044 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2045 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
2048 fSplitMaxInputFileNumber = 100;
2050 fMasterResubmitThreshold = 0;
2056 fNrunsPerMaster = 1;
2057 fMaxMergeFiles = 100;
2059 fExecutable = "analysis.sh";
2060 fExecutableCommand = "root -b -q";
2062 fExecutableArgs = "";
2063 fAnalysisMacro = "myAnalysis.C";
2064 fAnalysisSource = "";
2065 fAdditionalLibs = "";
2069 fAliROOTVersion = "";
2070 fUser = ""; // Your alien user name
2071 fGridWorkingDir = "";
2072 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
2073 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
2074 fFriendChainName = "";
2075 fGridOutputDir = "output";
2076 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
2077 fOutputFiles = ""; // Like "AliAODs.root histos.root"
2078 fInputFormat = "xml-single";
2079 fJDLName = "analysis.jdl";
2080 fJobTag = "Automatically generated analysis JDL";
2081 fMergeExcludes = "";
2084 SetCheckCopy(kTRUE);
2085 SetDefaultOutputs(kTRUE);
2089 //______________________________________________________________________________
2090 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
2092 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
2093 // First check if the result is already in the output directory.
2094 if (FileExists(Form("%s/%s",aliendir,filename))) {
2095 printf("Final merged results found. Not merging again.\n");
2098 // Now check the last stage done.
2101 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
2104 // Next stage of merging
2106 TString pattern = "*root_archive.zip";
2107 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
2108 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
2109 if (res) delete res;
2110 // Write standard output to file
2111 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
2112 // Count the number of files inside
2114 ifile.open(Form("Stage_%d.xml",stage));
2115 if (!ifile.good()) {
2116 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
2121 while (!ifile.eof()) {
2123 if (line.Contains("/event")) nfiles++;
2127 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
2130 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
2132 // Copy the file in the output directory
2133 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
2134 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
2135 if (!copyLocal2Alien("CheckMergedFiles", Form("Stage_%d.xml",stage),
2136 Form("%s/Stage_%d.xml",aliendir,stage))) Fatal("","Terminating");
2137 // Check if this is the last stage to be done.
2138 Bool_t laststage = (nfiles<nperchunk);
2139 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
2141 printf("### Submiting final merging stage %d\n", stage);
2142 TString finalJDL = jdl;
2143 finalJDL.ReplaceAll(".jdl", "_final.jdl");
2144 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
2145 Int_t jobId = SubmitSingleJob(query);
2146 if (!jobId) return kFALSE;
2148 printf("### Submiting merging stage %d\n", stage);
2149 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
2150 Int_t jobId = SubmitSingleJob(query);
2151 if (!jobId) return kFALSE;
2156 //______________________________________________________________________________
2157 AliAnalysisManager *AliAnalysisAlien::LoadAnalysisManager(const char *fname)
2159 // Loat the analysis manager from a file.
2160 TFile *file = TFile::Open(fname);
2162 ::Error("LoadAnalysisManager", "Cannot open file %s", fname);
2165 TIter nextkey(file->GetListOfKeys());
2166 AliAnalysisManager *mgr = 0;
2168 while ((key=(TKey*)nextkey())) {
2169 if (!strcmp(key->GetClassName(), "AliAnalysisManager"))
2170 mgr = (AliAnalysisManager*)file->Get(key->GetName());
2173 ::Error("LoadAnalysisManager", "No analysis manager found in file %s", fname);
2177 //______________________________________________________________________________
2178 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
2180 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
2181 if (!gGrid) return 0;
2182 printf("=> %s ------> ",query);
2183 TGridResult *res = gGrid->Command(query);
2185 TString jobId = res->GetKey(0,"jobId");
2187 if (jobId.IsNull()) {
2188 printf("submission failed. Reason:\n");
2191 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
2194 printf(" Job id: %s\n", jobId.Data());
2198 //______________________________________________________________________________
2199 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2201 // Merge given output files from basedir. Basedir can be an alien output directory
2202 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2203 // files in a group (ignored for xml input). Merging can be done in stages:
2204 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2205 // stage=1 : works with an xml of all root_archive.zip in the output directory
2206 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2207 TString outputFile = output;
2209 TString outputChunk;
2210 TString previousChunk = "";
2211 TObjArray *listoffiles = new TObjArray();
2212 // listoffiles->SetOwner();
2213 Int_t countChunk = 0;
2214 Int_t countZero = nmaxmerge;
2215 Bool_t merged = kTRUE;
2216 Int_t index = outputFile.Index("@");
2217 if (index > 0) outputFile.Remove(index);
2218 TString inputFile = outputFile;
2219 TString sbasedir = basedir;
2220 if (sbasedir.Contains(".xml")) {
2221 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2222 nmaxmerge = 9999999;
2223 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2225 ::Error("MergeOutput", "Input XML collection empty.");
2228 // Iterate grid collection
2229 while (coll->Next()) {
2230 TString fname = gSystem->DirName(coll->GetTURL());
2233 listoffiles->Add(new TNamed(fname.Data(),""));
2236 command = Form("find %s/ *%s", basedir, inputFile.Data());
2237 printf("command: %s\n", command.Data());
2238 TGridResult *res = gGrid->Command(command);
2240 ::Error("MergeOutput","No result for the find command\n");
2246 while ((map=(TMap*)nextmap())) {
2247 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2248 if (!objs || !objs->GetString().Length()) {
2249 // Nothing found - skip this output
2254 listoffiles->Add(new TNamed(objs->GetName(),""));
2258 if (!listoffiles->GetEntries()) {
2259 ::Error("MergeOutput","No result for the find command\n");
2264 TFileMerger *fm = 0;
2265 TIter next0(listoffiles);
2266 TObjArray *listoffilestmp = new TObjArray();
2267 listoffilestmp->SetOwner();
2270 // Keep only the files at upper level
2271 Int_t countChar = 0;
2272 while ((nextfile=next0())) {
2273 snextfile = nextfile->GetName();
2274 Int_t crtCount = snextfile.CountChar('/');
2275 if (nextfile == listoffiles->First()) countChar = crtCount;
2276 if (crtCount < countChar) countChar = crtCount;
2279 while ((nextfile=next0())) {
2280 snextfile = nextfile->GetName();
2281 Int_t crtCount = snextfile.CountChar('/');
2282 if (crtCount > countChar) {
2286 listoffilestmp->Add(nextfile);
2289 listoffiles = listoffilestmp; // Now contains 'good' files
2290 listoffiles->Print();
2291 TIter next(listoffiles);
2292 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2293 outputChunk = outputFile;
2294 outputChunk.ReplaceAll(".root", "_*.root");
2295 // Check for existent temporary merge files
2296 // Check overwrite mode and remove previous partial results if needed
2297 // Preserve old merging functionality for stage 0.
2299 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2301 // Skip as many input files as in a chunk
2302 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2305 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2309 snextfile = nextfile->GetName();
2311 outputChunk = outputFile;
2312 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2314 if (gSystem->AccessPathName(outputChunk)) continue;
2315 // Merged file with chunks up to <countChunk> found
2316 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2317 previousChunk = outputChunk;
2321 countZero = nmaxmerge;
2323 while ((nextfile=next())) {
2324 snextfile = nextfile->GetName();
2325 // Loop 'find' results and get next LFN
2326 if (countZero == nmaxmerge) {
2327 // First file in chunk - create file merger and add previous chunk if any.
2328 fm = new TFileMerger(kFALSE);
2329 fm->SetFastMethod(kTRUE);
2330 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2331 outputChunk = outputFile;
2332 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2334 // If last file found, put merged results in the output file
2335 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2336 // Add file to be merged and decrement chunk counter.
2337 fm->AddFile(snextfile);
2339 if (countZero==0 || nextfile == listoffiles->Last()) {
2340 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2341 // Nothing found - skip this output
2342 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2346 fm->OutputFile(outputChunk);
2347 // Merge the outputs, then go to next chunk
2349 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2353 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2354 gSystem->Unlink(previousChunk);
2356 if (nextfile == listoffiles->Last()) break;
2358 countZero = nmaxmerge;
2359 previousChunk = outputChunk;
2366 // Merging stage different than 0.
2367 // Move to the begining of the requested chunk.
2368 fm = new TFileMerger(kFALSE);
2369 fm->SetFastMethod(kTRUE);
2370 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2372 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2373 // Nothing found - skip this output
2374 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2378 fm->OutputFile(outputFile);
2379 // Merge the outputs
2381 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2385 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2391 //______________________________________________________________________________
2392 Bool_t AliAnalysisAlien::MergeOutputs()
2394 // Merge analysis outputs existing in the AliEn space.
2395 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2396 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2398 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2402 if (!TestBit(AliAnalysisGrid::kMerge)) {
2403 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2406 if (fProductionMode) {
2407 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2410 Info("MergeOutputs", "Submitting merging JDL");
2411 if (!SubmitMerging()) return kFALSE;
2412 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2413 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2416 // Get the output path
2417 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2418 if (!DirectoryExists(fGridOutputDir)) {
2419 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2422 if (!fOutputFiles.Length()) {
2423 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2426 // Check if fast read option was requested
2427 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2428 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2429 if (fFastReadOption) {
2430 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2431 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2432 gEnv->SetValue("XNet.ConnectTimeout",50);
2433 gEnv->SetValue("XNet.RequestTimeout",50);
2434 gEnv->SetValue("XNet.MaxRedirectCount",2);
2435 gEnv->SetValue("XNet.ReconnectTimeout",50);
2436 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2438 // Make sure we change the temporary directory
2439 gSystem->Setenv("TMPDIR", gSystem->pwd());
2440 // Set temporary compilation directory to current one
2441 gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
2442 TObjArray *list = fOutputFiles.Tokenize(",");
2446 Bool_t merged = kTRUE;
2447 while((str=(TObjString*)next())) {
2448 outputFile = str->GetString();
2449 Int_t index = outputFile.Index("@");
2450 if (index > 0) outputFile.Remove(index);
2451 TString outputChunk = outputFile;
2452 outputChunk.ReplaceAll(".root", "_*.root");
2453 // Skip already merged outputs
2454 if (!gSystem->AccessPathName(outputFile)) {
2455 if (fOverwriteMode) {
2456 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2457 gSystem->Unlink(outputFile);
2458 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2459 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2460 outputChunk.Data());
2461 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2464 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2468 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2469 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2470 outputChunk.Data());
2471 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2474 if (fMergeExcludes.Length() &&
2475 fMergeExcludes.Contains(outputFile.Data())) continue;
2476 // Perform a 'find' command in the output directory, looking for registered outputs
2477 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2479 Error("MergeOutputs", "Terminate() will NOT be executed");
2482 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2483 if (fileOpened) fileOpened->Close();
2488 //______________________________________________________________________________
2489 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2491 // Use the output files connected to output containers from the analysis manager
2492 // rather than the files defined by SetOutputFiles
2493 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2494 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2495 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2498 //______________________________________________________________________________
2499 void AliAnalysisAlien::SetOutputFiles(const char *list)
2501 // Manually set the output files list.
2502 // Removes duplicates. Not allowed if default outputs are not disabled.
2503 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2504 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2507 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2509 TString slist = list;
2510 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2511 TObjArray *arr = slist.Tokenize(" ");
2515 while ((os=(TObjString*)next())) {
2516 sout = os->GetString();
2517 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2518 if (fOutputFiles.Contains(sout)) continue;
2519 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2520 fOutputFiles += sout;
2525 //______________________________________________________________________________
2526 void AliAnalysisAlien::SetOutputArchive(const char *list)
2528 // Manually set the output archive list. Free text - you are on your own...
2529 // Not allowed if default outputs are not disabled.
2530 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2531 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2534 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2535 fOutputArchive = list;
2538 //______________________________________________________________________________
2539 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2541 // Setting a prefered output SE is not allowed anymore.
2542 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2545 //______________________________________________________________________________
2546 void AliAnalysisAlien::SetProofParameter(const char *pname, const char *value)
2548 // Set some PROOF special parameter.
2549 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2551 TObject *old = pair->Key();
2552 TObject *val = pair->Value();
2553 fProofParam.Remove(old);
2557 fProofParam.Add(new TObjString(pname), new TObjString(value));
2560 //______________________________________________________________________________
2561 const char *AliAnalysisAlien::GetProofParameter(const char *pname) const
2563 // Returns a special PROOF parameter.
2564 TPair *pair = dynamic_cast<TPair*>(fProofParam.FindObject(pname));
2565 if (!pair) return 0;
2566 return pair->Value()->GetName();
2569 //______________________________________________________________________________
2570 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2572 // Start remote grid analysis.
2573 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2574 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2575 if (!mgr || !mgr->IsInitialized()) {
2576 Error("StartAnalysis", "You need an initialized analysis manager for this");
2579 // Are we in PROOF mode ?
2580 if (mgr->IsProofMode()) {
2581 if (testMode) Info("StartAnalysis", "##### Starting PROOF analysis with Proof Lite via the plugin #####");
2582 else Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2583 if (fProofCluster.IsNull()) {
2584 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2587 if (fProofDataSet.IsNull() && !testMode) {
2588 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2591 // Set the needed environment
2592 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2593 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2594 if (fProofReset && !testMode) {
2595 if (fProofReset==1) {
2596 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2597 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2599 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2600 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2602 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2607 // Check if there is an old active session
2608 Long_t nsessions = gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->QuerySessions(\"\")->GetEntries();", fProofCluster.Data()));
2610 Error("StartAnalysis","You have to reset your old session first\n");
2614 // Do we need to change the ROOT version ? The success of this cannot be checked.
2615 if (!fRootVersionForProof.IsNull() && !testMode) {
2616 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2617 fProofCluster.Data(), fRootVersionForProof.Data()));
2619 // Connect to PROOF and check the status
2622 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2623 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2625 if (!sworkers.IsNull())
2626 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2628 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2630 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2632 Error("StartAnalysis", "Could not start PROOF in test mode");
2637 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2640 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2641 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2642 // Set proof special parameters if any
2643 TIter nextpp(&fProofParam);
2644 TObject *proofparam;
2645 while ((proofparam=nextpp())) {
2646 TString svalue = GetProofParameter(proofparam->GetName());
2647 gROOT->ProcessLine(Form("gProof->SetParameter(\"%s\",%s);", proofparam->GetName(), svalue.Data()));
2649 // Is dataset existing ?
2651 TString dataset = fProofDataSet;
2652 Int_t index = dataset.Index("#");
2653 if (index>=0) dataset.Remove(index);
2654 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2655 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2658 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2660 // Is ClearPackages() needed ?
2661 if (TestSpecialBit(kClearPackages)) {
2662 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2663 gROOT->ProcessLine("gProof->ClearPackages();");
2665 // Is a given aliroot mode requested ?
2668 if (!fAliRootMode.IsNull()) {
2669 TString alirootMode = fAliRootMode;
2670 if (alirootMode == "default") alirootMode = "";
2671 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2672 optionsList.SetOwner();
2673 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2674 // Check the additional libs to be loaded
2676 Bool_t parMode = kFALSE;
2677 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:OADB:ANALYSISalice";
2678 // Parse the extra libs for .so
2679 if (fAdditionalLibs.Length()) {
2680 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2683 while((str=(TObjString*)next())) {
2684 if (str->GetString().Contains(".so")) {
2686 Warning("StartAnalysis", "Plugin does not support loading libs after par files in PROOF mode. Library %s and following will not load on workers", str->GetName());
2689 TString stmp = str->GetName();
2690 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2691 stmp.ReplaceAll(".so","");
2692 if (!extraLibs.IsNull()) extraLibs += ":";
2696 if (str->GetString().Contains(".par")) {
2697 // The first par file found in the list will not allow any further .so
2699 if (!parLibs.IsNull()) parLibs += ":";
2700 parLibs += str->GetName();
2704 if (list) delete list;
2706 if (!extraLibs.IsNull()) {
2707 Info("StartAnalysis", "Adding extra libs: %s",extraLibs.Data());
2708 optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2710 // Check extra includes
2711 if (!fIncludePath.IsNull()) {
2712 TString includePath = fIncludePath;
2713 includePath.ReplaceAll(" ",":");
2714 includePath.ReplaceAll("$ALICE_ROOT/","");
2715 includePath.ReplaceAll("${ALICE_ROOT}/","");
2716 includePath.ReplaceAll("-I","");
2717 includePath.Remove(TString::kTrailing, ':');
2718 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2719 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2721 // Check if connection to grid is requested
2722 if (TestSpecialBit(kProofConnectGrid))
2723 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2724 // Enable AliRoot par
2726 // Enable proof lite package
2727 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2728 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2729 TNamed *obj = (TNamed*)optionsList.At(i);
2730 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2732 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2733 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2734 Info("StartAnalysis", "AliRootProofLite enabled");
2736 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2740 if ( ! fAliROOTVersion.IsNull() ) {
2741 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2742 fAliROOTVersion.Data(), &optionsList))) {
2743 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2748 // Enable first par files from fAdditionalLibs
2749 if (!parLibs.IsNull()) {
2750 TObjArray *list = parLibs.Tokenize(":");
2752 TObjString *package;
2753 while((package=(TObjString*)next())) {
2754 TString spkg = package->GetName();
2755 spkg.ReplaceAll(".par", "");
2756 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2757 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2758 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2759 if (gROOT->ProcessLine(enablePackage)) {
2760 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2764 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2768 if (list) delete list;
2771 if (fAdditionalLibs.Contains(".so") && !testMode) {
2772 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2773 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2777 // Enable par files if requested
2778 if (fPackages && fPackages->GetEntries()) {
2779 TIter next(fPackages);
2781 while ((package=next())) {
2782 // Skip packages already enabled
2783 if (parLibs.Contains(package->GetName())) continue;
2784 TString spkg = package->GetName();
2785 spkg.ReplaceAll(".par", "");
2786 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2787 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2788 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2789 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2793 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2798 // Do we need to load analysis source files ?
2799 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2800 if (fAnalysisSource.Length()) {
2801 TObjArray *list = fAnalysisSource.Tokenize(" ");
2804 while((str=(TObjString*)next())) {
2805 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2807 if (list) delete list;
2810 // Register dataset to proof lite.
2811 if (fFileForTestMode.IsNull()) {
2812 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2815 if (gSystem->AccessPathName(fFileForTestMode)) {
2816 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2819 TFileCollection *coll = new TFileCollection();
2820 coll->AddFromFile(fFileForTestMode);
2821 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2822 gROOT->ProcessLine("gProof->ShowDataSets()");
2827 // Check if output files have to be taken from the analysis manager
2828 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2829 // Add output files and AOD files
2830 fOutputFiles = GetListOfFiles("outaod");
2831 // Add extra files registered to the analysis manager
2832 TString extra = GetListOfFiles("ext");
2833 if (!extra.IsNull()) {
2834 extra.ReplaceAll(".root", "*.root");
2835 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2836 fOutputFiles += extra;
2838 // Compose the output archive.
2839 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2840 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2842 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2843 if (TestBit(AliAnalysisGrid::kOffline)) {
2844 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2845 \n there nor any job run. You can revise the JDL and analysis \
2846 \n macro then run the same in \"submit\" mode.");
2847 } else if (TestBit(AliAnalysisGrid::kTest)) {
2848 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2850 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2851 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2852 \n space and job submitted.");
2853 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2854 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2855 if (fMergeViaJDL) CheckInputData();
2858 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2863 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2866 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2867 if (!CheckInputData()) {
2868 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2871 if (!CreateDataset(fDataPattern)) {
2873 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2874 if (fRunNumbers.Length()) serror = "run numbers";
2875 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2876 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2877 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2880 WriteAnalysisFile();
2881 WriteAnalysisMacro();
2883 WriteValidationScript();
2885 WriteMergingMacro();
2886 WriteMergeExecutable();
2887 WriteValidationScript(kTRUE);
2889 if (!CreateJDL()) return kFALSE;
2890 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2892 // Locally testing the analysis
2893 Info("StartAnalysis", "\n_______________________________________________________________________ \
2894 \n Running analysis script in a daughter shell as on a worker node \
2895 \n_______________________________________________________________________");
2896 TObjArray *list = fOutputFiles.Tokenize(",");
2900 while((str=(TObjString*)next())) {
2901 outputFile = str->GetString();
2902 Int_t index = outputFile.Index("@");
2903 if (index > 0) outputFile.Remove(index);
2904 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2907 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2908 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2909 // gSystem->Exec("cat stdout");
2912 // Check if submitting is managed by LPM manager
2913 if (fProductionMode) {
2914 TString prodfile = fJDLName;
2915 prodfile.ReplaceAll(".jdl", ".prod");
2916 WriteProductionFile(prodfile);
2917 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2920 // Submit AliEn job(s)
2921 gGrid->Cd(fGridOutputDir);
2924 if (!fRunNumbers.Length() && !fRunRange[0]) {
2925 // Submit a given xml or a set of runs
2926 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2927 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2929 const char *cjobId = res->GetKey(0,"jobId");
2933 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2936 Info("StartAnalysis", "\n_______________________________________________________________________ \
2937 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2938 \n_______________________________________________________________________",
2939 fJDLName.Data(), cjobId);
2944 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2948 // Submit for a range of enumeration of runs.
2949 if (!Submit()) return kFALSE;
2952 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2953 \n You may exit at any time and terminate the job later using the option <terminate> \
2954 \n ##################################################################################", jobID.Data());
2955 gSystem->Exec("aliensh");
2959 //______________________________________________________________________________
2960 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2962 // Get a comma-separated list of output files of the requested type.
2963 // Type can be (case unsensitive):
2964 // aod - list of aod files (std, extensions and filters)
2965 // out - list of output files connected to containers (but not aod's or extras)
2966 // ext - list of extra files registered to the manager
2967 // ter - list of files produced in terminate
2968 static TString files;
2970 TString stype = type;
2972 TString aodfiles, extra;
2973 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2975 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2976 return files.Data();
2978 if (mgr->GetOutputEventHandler()) {
2979 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2980 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2981 if (!extraaod.IsNull()) {
2983 aodfiles += extraaod;
2986 if (stype.Contains("aod")) {
2988 if (stype == "aod") return files.Data();
2990 // Add output files that are not in the list of AOD files
2991 TString outputfiles = "";
2992 TIter next(mgr->GetOutputs());
2993 AliAnalysisDataContainer *output;
2994 const char *filename = 0;
2995 while ((output=(AliAnalysisDataContainer*)next())) {
2996 filename = output->GetFileName();
2997 if (!(strcmp(filename, "default"))) continue;
2998 if (outputfiles.Contains(filename)) continue;
2999 if (aodfiles.Contains(filename)) continue;
3000 if (!outputfiles.IsNull()) outputfiles += ",";
3001 outputfiles += filename;
3003 if (stype.Contains("out")) {
3004 if (!files.IsNull()) files += ",";
3005 files += outputfiles;
3006 if (stype == "out") return files.Data();
3008 // Add extra files registered to the analysis manager
3010 extra = mgr->GetExtraFiles();
3011 if (!extra.IsNull()) {
3013 extra.ReplaceAll(" ", ",");
3014 TObjArray *fextra = extra.Tokenize(",");
3015 TIter nextx(fextra);
3017 while ((obj=nextx())) {
3018 if (aodfiles.Contains(obj->GetName())) continue;
3019 if (outputfiles.Contains(obj->GetName())) continue;
3020 if (sextra.Contains(obj->GetName())) continue;
3021 if (!sextra.IsNull()) sextra += ",";
3022 sextra += obj->GetName();
3025 if (stype.Contains("ext")) {
3026 if (!files.IsNull()) files += ",";
3030 if (stype == "ext") return files.Data();
3032 if (!fTerminateFiles.IsNull()) {
3033 fTerminateFiles.Strip();
3034 fTerminateFiles.ReplaceAll(" ",",");
3035 TObjArray *fextra = fTerminateFiles.Tokenize(",");
3036 TIter nextx(fextra);
3038 while ((obj=nextx())) {
3039 if (aodfiles.Contains(obj->GetName())) continue;
3040 if (outputfiles.Contains(obj->GetName())) continue;
3041 if (termfiles.Contains(obj->GetName())) continue;
3042 if (sextra.Contains(obj->GetName())) continue;
3043 if (!termfiles.IsNull()) termfiles += ",";
3044 termfiles += obj->GetName();
3048 if (stype.Contains("ter")) {
3049 if (!files.IsNull() && !termfiles.IsNull()) {
3054 return files.Data();
3057 //______________________________________________________________________________
3058 Bool_t AliAnalysisAlien::Submit()
3060 // Submit all master jobs.
3061 Int_t nmasterjobs = fInputFiles->GetEntries();
3062 Long_t tshoot = gSystem->Now();
3063 if (!fNsubmitted && !SubmitNext()) return kFALSE;
3064 while (fNsubmitted < nmasterjobs) {
3065 Long_t now = gSystem->Now();
3066 if ((now-tshoot)>30000) {
3068 if (!SubmitNext()) return kFALSE;
3074 //______________________________________________________________________________
3075 Bool_t AliAnalysisAlien::SubmitMerging()
3077 // Submit all merging jobs.
3078 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3079 gGrid->Cd(fGridOutputDir);
3080 TString mergeJDLName = fExecutable;
3081 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
3083 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
3086 Int_t ntosubmit = fInputFiles->GetEntries();
3087 for (Int_t i=0; i<ntosubmit; i++) {
3088 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3089 runOutDir.ReplaceAll(".xml", "");
3090 if (fOutputToRunNo) {
3091 // The output directory is the run number
3092 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
3093 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
3095 if (!fRunNumbers.Length() && !fRunRange[0]) {
3096 // The output directory is the grid outdir
3097 printf("### Submitting merging job for the full output directory %s.\n", fGridOutputDir.Data());
3098 runOutDir = fGridOutputDir;
3100 // The output directory is the master number in 3 digits format
3101 printf("### Submitting merging job for master <%03d>\n", i);
3102 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
3105 // Check now the number of merging stages.
3106 TObjArray *list = fOutputFiles.Tokenize(",");
3110 while((str=(TObjString*)next())) {
3111 outputFile = str->GetString();
3112 Int_t index = outputFile.Index("@");
3113 if (index > 0) outputFile.Remove(index);
3114 if (!fMergeExcludes.Contains(outputFile)) break;
3117 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
3118 if (!done && (i==ntosubmit-1)) return kFALSE;
3119 if (!fRunNumbers.Length() && !fRunRange[0]) break;
3121 if (!ntosubmit) return kTRUE;
3122 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
3123 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
3124 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
3125 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
3126 \n ################################################################################################################");
3127 gSystem->Exec("aliensh");
3131 //______________________________________________________________________________
3132 Bool_t AliAnalysisAlien::SubmitNext()
3134 // Submit next bunch of master jobs if the queue is free. The first master job is
3135 // submitted right away, while the next will not be unless the previous was split.
3136 // The plugin will not submit new master jobs if there are more that 500 jobs in
3138 static Bool_t iscalled = kFALSE;
3139 static Int_t firstmaster = 0;
3140 static Int_t lastmaster = 0;
3141 static Int_t npermaster = 0;
3142 if (iscalled) return kTRUE;
3144 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
3145 Int_t ntosubmit = 0;
3148 Int_t nmasterjobs = fInputFiles->GetEntries();
3151 if (!IsUseSubmitPolicy()) {
3153 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
3154 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
3155 ntosubmit = nmasterjobs;
3158 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
3159 printf("=== master %d: %s\n", lastmaster, status.Data());
3160 // If last master not split, just return
3161 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
3162 // No more than 100 waiting jobs
3163 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
3164 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
3165 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
3166 if (!ntosubmit) ntosubmit = 1;
3167 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
3168 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
3170 for (Int_t i=0; i<ntosubmit; i++) {
3171 // Submit for a range of enumeration of runs.
3172 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
3174 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
3175 runOutDir.ReplaceAll(".xml", "");
3177 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
3179 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
3180 printf("********* %s\n",query.Data());
3181 res = gGrid->Command(query);
3183 TString cjobId1 = res->GetKey(0,"jobId");
3184 if (!cjobId1.Length()) {
3188 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
3191 Info("StartAnalysis", "\n_______________________________________________________________________ \
3192 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
3193 \n_______________________________________________________________________",
3194 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
3197 lastmaster = cjobId1.Atoi();
3198 if (!firstmaster) firstmaster = lastmaster;
3203 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
3211 //______________________________________________________________________________
3212 void AliAnalysisAlien::WriteAnalysisFile()
3214 // Write current analysis manager into the file <analysisFile>
3215 TString analysisFile = fExecutable;
3216 analysisFile.ReplaceAll(".sh", ".root");
3217 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3218 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3219 if (!mgr || !mgr->IsInitialized()) {
3220 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
3223 // Check analysis type
3225 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
3226 handler = (TObject*)mgr->GetInputEventHandler();
3228 if (handler->InheritsFrom("AliMultiInputEventHandler")) {
3229 AliMultiInputEventHandler *multiIH = (AliMultiInputEventHandler*)handler;
3230 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3231 if (multiIH->GetFirstInputEventHandler()->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3233 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
3234 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
3237 TDirectory *cdir = gDirectory;
3238 TFile *file = TFile::Open(analysisFile, "RECREATE");
3240 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
3241 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
3242 // Unless merging makes no sense
3243 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
3246 // Enable termination for local jobs
3247 mgr->SetSkipTerminate(kFALSE);
3249 if (cdir) cdir->cd();
3250 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
3252 Bool_t copy = kTRUE;
3253 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3256 TString workdir = gGrid->GetHomeDirectory();
3257 workdir += fGridWorkingDir;
3258 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
3259 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3260 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
3261 if (!copyLocal2Alien("WriteAnalysisFile",analysisFile.Data(),
3262 Form("%s/%s", workdir.Data(),analysisFile.Data()))) Fatal("","Terminating");
3266 //______________________________________________________________________________
3267 void AliAnalysisAlien::WriteAnalysisMacro()
3269 // Write the analysis macro that will steer the analysis in grid mode.
3270 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3272 out.open(fAnalysisMacro.Data(), ios::out);
3274 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3277 Bool_t hasSTEERBase = kFALSE;
3278 Bool_t hasESD = kFALSE;
3279 Bool_t hasAOD = kFALSE;
3280 Bool_t hasANALYSIS = kFALSE;
3281 Bool_t hasOADB = kFALSE;
3282 Bool_t hasANALYSISalice = kFALSE;
3283 Bool_t hasCORRFW = kFALSE;
3284 TString func = fAnalysisMacro;
3285 TString type = "ESD";
3286 TString comment = "// Analysis using ";
3287 if (IsUseMCchain()) {
3291 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3292 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3297 if (type!="AOD" && fFriendChainName!="") {
3298 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3301 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3302 else comment += " data";
3303 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3304 func.ReplaceAll(".C", "");
3305 out << "void " << func.Data() << "()" << endl;
3307 out << comment.Data() << endl;
3308 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3309 out << " TStopwatch timer;" << endl;
3310 out << " timer.Start();" << endl << endl;
3311 // Change temp directory to current one
3312 out << "// Set temporary merging directory to current one" << endl;
3313 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3314 out << "// Set temporary compilation directory to current one" << endl;
3315 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3316 // Reset existing include path
3317 out << "// Reset existing include path and add current directory first in the search" << endl;
3318 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3319 if (!fExecutableCommand.Contains("aliroot")) {
3320 out << "// load base root libraries" << endl;
3321 out << " gSystem->Load(\"libTree\");" << endl;
3322 out << " gSystem->Load(\"libGeom\");" << endl;
3323 out << " gSystem->Load(\"libVMC\");" << endl;
3324 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3325 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3327 if (fAdditionalRootLibs.Length()) {
3328 // in principle libtree /lib geom libvmc etc. can go into this list, too
3329 out << "// Add aditional libraries" << endl;
3330 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3333 while((str=(TObjString*)next())) {
3334 if (str->GetString().Contains(".so"))
3335 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3337 if (list) delete list;
3339 out << "// Load analysis framework libraries" << endl;
3340 TString setupPar = "AliAnalysisAlien::SetupPar";
3342 if (!fExecutableCommand.Contains("aliroot")) {
3343 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3344 out << " gSystem->Load(\"libESD\");" << endl;
3345 out << " gSystem->Load(\"libAOD\");" << endl;
3347 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3348 out << " gSystem->Load(\"libOADB\");" << endl;
3349 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3350 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3352 TIter next(fPackages);
3355 while ((obj=next())) {
3356 pkgname = obj->GetName();
3357 if (pkgname == "STEERBase" ||
3358 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3359 if (pkgname == "ESD" ||
3360 pkgname == "ESD.par") hasESD = kTRUE;
3361 if (pkgname == "AOD" ||
3362 pkgname == "AOD.par") hasAOD = kTRUE;
3363 if (pkgname == "ANALYSIS" ||
3364 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3365 if (pkgname == "OADB" ||
3366 pkgname == "OADB.par") hasOADB = kTRUE;
3367 if (pkgname == "ANALYSISalice" ||
3368 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3369 if (pkgname == "CORRFW" ||
3370 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3372 if (hasANALYSISalice) setupPar = "SetupPar";
3373 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3374 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3375 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3376 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3377 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3378 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3379 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3380 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3381 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3382 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3383 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3384 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3385 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3386 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3387 out << "// Compile other par packages" << endl;
3389 while ((obj=next())) {
3390 pkgname = obj->GetName();
3391 if (pkgname == "STEERBase" ||
3392 pkgname == "STEERBase.par" ||
3394 pkgname == "ESD.par" ||
3396 pkgname == "AOD.par" ||
3397 pkgname == "ANALYSIS" ||
3398 pkgname == "ANALYSIS.par" ||
3399 pkgname == "OADB" ||
3400 pkgname == "OADB.par" ||
3401 pkgname == "ANALYSISalice" ||
3402 pkgname == "ANALYSISalice.par" ||
3403 pkgname == "CORRFW" ||
3404 pkgname == "CORRFW.par") continue;
3405 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3408 out << "// include path" << endl;
3409 // Get the include path from the interpreter and remove entries pointing to AliRoot
3410 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3411 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3412 out << " TIter nextpath(listpaths);" << endl;
3413 out << " TObjString *pname;" << endl;
3414 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3415 out << " TString current = pname->GetName();" << endl;
3416 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3417 out << " gSystem->AddIncludePath(current);" << endl;
3418 out << " }" << endl;
3419 out << " if (listpaths) delete listpaths;" << endl;
3420 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3421 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3422 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3423 if (fAdditionalLibs.Length()) {
3424 out << "// Add aditional AliRoot libraries" << endl;
3425 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3428 while((str=(TObjString*)next())) {
3429 if (str->GetString().Contains(".so"))
3430 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3431 if (str->GetString().Contains(".par"))
3432 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3434 if (list) delete list;
3437 out << "// analysis source to be compiled at runtime (if any)" << endl;
3438 if (fAnalysisSource.Length()) {
3439 TObjArray *list = fAnalysisSource.Tokenize(" ");
3442 while((str=(TObjString*)next())) {
3443 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3445 if (list) delete list;
3448 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3449 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3450 if (fFastReadOption) {
3451 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 !!! \
3452 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3453 out << "// fast xrootd reading enabled" << endl;
3454 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3455 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3456 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3457 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3458 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3459 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3461 out << "// connect to AliEn and make the chain" << endl;
3462 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3463 out << "// read the analysis manager from file" << endl;
3464 TString analysisFile = fExecutable;
3465 analysisFile.ReplaceAll(".sh", ".root");
3466 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3467 << analysisFile << "\");" << endl;
3468 out << " if (!mgr) return;" << endl;
3469 out << " mgr->PrintStatus();" << endl;
3470 if (AliAnalysisManager::GetAnalysisManager()) {
3471 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3472 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3474 if (TestBit(AliAnalysisGrid::kTest))
3475 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3477 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3480 if (IsUsingTags()) {
3481 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3483 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3485 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3486 out << " timer.Stop();" << endl;
3487 out << " timer.Print();" << endl;
3488 out << "}" << endl << endl;
3489 if (IsUsingTags()) {
3490 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3492 out << "// Create a chain using tags from the xml file." << endl;
3493 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3494 out << " if (!coll) {" << endl;
3495 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3496 out << " return NULL;" << endl;
3497 out << " }" << endl;
3498 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3499 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3500 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3501 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3502 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3503 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3504 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3505 out << " // Check if the cuts configuration file was provided" << endl;
3506 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3507 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3508 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3509 out << " }" << endl;
3510 if (fFriendChainName=="") {
3511 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3513 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3514 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3515 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3517 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3518 out << " chain->ls();" << endl;
3519 out << " return chain;" << endl;
3520 out << "}" << endl << endl;
3521 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3522 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3523 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3524 msg += " AliLHCTagCuts *lhcCuts,\n";
3525 msg += " AliDetectorTagCuts *detCuts,\n";
3526 msg += " AliEventTagCuts *evCuts)";
3527 Info("WriteAnalysisMacro", "%s", msg.Data());
3530 if (!IsUsingTags() || fFriendChainName!="") {
3531 out <<"//________________________________________________________________________________" << endl;
3532 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3534 out << "// Create a chain using url's from xml file" << endl;
3535 out << " TString filename;" << endl;
3536 out << " Int_t run = 0;" << endl;
3537 if (IsUseMCchain()) {
3538 out << " TString treename = \"TE\";" << endl;
3540 out << " TString treename = type;" << endl;
3541 out << " treename.ToLower();" << endl;
3542 out << " treename += \"Tree\";" << endl;
3544 out << " printf(\"***************************************\\n\");" << endl;
3545 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3546 out << " printf(\"***************************************\\n\");" << endl;
3547 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3548 out << " if (!coll) {" << endl;
3549 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3550 out << " return NULL;" << endl;
3551 out << " }" << endl;
3552 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3553 out << " TChain *chain = new TChain(treename);" << endl;
3554 if(fFriendChainName!="") {
3555 out << " TChain *chainFriend = new TChain(treename);" << endl;
3557 out << " coll->Reset();" << endl;
3558 out << " while (coll->Next()) {" << endl;
3559 out << " filename = coll->GetTURL("");" << endl;
3560 out << " if (mgr) {" << endl;
3561 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3562 out << " if (nrun && nrun != run) {" << endl;
3563 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3564 out << " mgr->SetRunFromPath(nrun);" << endl;
3565 out << " run = nrun;" << endl;
3566 out << " }" << endl;
3567 out << " }" << endl;
3568 out << " chain->Add(filename);" << endl;
3569 if(fFriendChainName!="") {
3570 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3571 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3572 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3573 out << " chainFriend->Add(fileFriend.Data());" << endl;
3575 out << " }" << endl;
3576 out << " if (!chain->GetNtrees()) {" << endl;
3577 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3578 out << " return NULL;" << endl;
3579 out << " }" << endl;
3580 if(fFriendChainName!="") {
3581 out << " chain->AddFriend(chainFriend);" << endl;
3583 out << " return chain;" << endl;
3584 out << "}" << endl << endl;
3586 if (hasANALYSISalice) {
3587 out <<"//________________________________________________________________________________" << endl;
3588 out << "Bool_t SetupPar(const char *package) {" << endl;
3589 out << "// Compile the package and set it up." << endl;
3590 out << " TString pkgdir = package;" << endl;
3591 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3592 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3593 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3594 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3595 out << " // Check for BUILD.sh and execute" << endl;
3596 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3597 out << " printf(\"*******************************\\n\");" << endl;
3598 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3599 out << " printf(\"*******************************\\n\");" << endl;
3600 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3601 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3602 out << " gSystem->ChangeDirectory(cdir);" << endl;
3603 out << " return kFALSE;" << endl;
3604 out << " }" << endl;
3605 out << " } else {" << endl;
3606 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3607 out << " gSystem->ChangeDirectory(cdir);" << endl;
3608 out << " return kFALSE;" << endl;
3609 out << " }" << endl;
3610 out << " // Check for SETUP.C and execute" << endl;
3611 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3612 out << " printf(\"*******************************\\n\");" << endl;
3613 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3614 out << " printf(\"*******************************\\n\");" << endl;
3615 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3616 out << " } else {" << endl;
3617 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3618 out << " gSystem->ChangeDirectory(cdir);" << endl;
3619 out << " return kFALSE;" << endl;
3620 out << " }" << endl;
3621 out << " // Restore original workdir" << endl;
3622 out << " gSystem->ChangeDirectory(cdir);" << endl;
3623 out << " return kTRUE;" << endl;
3626 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3628 Bool_t copy = kTRUE;
3629 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3632 TString workdir = gGrid->GetHomeDirectory();
3633 workdir += fGridWorkingDir;
3634 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3635 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3636 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3637 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3638 if (!copyLocal2Alien("WriteAnalysisMacro","ConfigureCuts.C",
3639 Form("%s/ConfigureCuts.C", workdir.Data()))) Fatal("","Terminating");
3640 // TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3642 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3643 // TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3644 if (!copyLocal2Alien("WriteAnalysisMacro",fAnalysisMacro.Data(),
3645 Form("alien://%s/%s", workdir.Data(),
3646 fAnalysisMacro.Data()))) Fatal("","Terminating");
3650 //______________________________________________________________________________
3651 void AliAnalysisAlien::WriteMergingMacro()
3653 // Write a macro to merge the outputs per master job.
3654 if (!fMergeViaJDL) return;
3655 if (!fOutputFiles.Length()) {
3656 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3659 TString mergingMacro = fExecutable;
3660 mergingMacro.ReplaceAll(".sh","_merge.C");
3661 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3662 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3664 out.open(mergingMacro.Data(), ios::out);
3666 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3669 Bool_t hasSTEERBase = kFALSE;
3670 Bool_t hasESD = kFALSE;
3671 Bool_t hasAOD = kFALSE;
3672 Bool_t hasANALYSIS = kFALSE;
3673 Bool_t hasOADB = kFALSE;
3674 Bool_t hasANALYSISalice = kFALSE;
3675 Bool_t hasCORRFW = kFALSE;
3676 TString func = mergingMacro;
3678 func.ReplaceAll(".C", "");
3679 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3681 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3682 out << " TStopwatch timer;" << endl;
3683 out << " timer.Start();" << endl << endl;
3684 // Reset existing include path
3685 out << "// Reset existing include path and add current directory first in the search" << endl;
3686 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3687 if (!fExecutableCommand.Contains("aliroot")) {
3688 out << "// load base root libraries" << endl;
3689 out << " gSystem->Load(\"libTree\");" << endl;
3690 out << " gSystem->Load(\"libGeom\");" << endl;
3691 out << " gSystem->Load(\"libVMC\");" << endl;
3692 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3693 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3695 if (fAdditionalRootLibs.Length()) {
3696 // in principle libtree /lib geom libvmc etc. can go into this list, too
3697 out << "// Add aditional libraries" << endl;
3698 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3701 while((str=(TObjString*)next())) {
3702 if (str->GetString().Contains(".so"))
3703 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3705 if (list) delete list;
3707 out << "// Load analysis framework libraries" << endl;
3709 if (!fExecutableCommand.Contains("aliroot")) {
3710 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3711 out << " gSystem->Load(\"libESD\");" << endl;
3712 out << " gSystem->Load(\"libAOD\");" << endl;
3714 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3715 out << " gSystem->Load(\"libOADB\");" << endl;
3716 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3717 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3719 TIter next(fPackages);
3722 TString setupPar = "AliAnalysisAlien::SetupPar";
3723 while ((obj=next())) {
3724 pkgname = obj->GetName();
3725 if (pkgname == "STEERBase" ||
3726 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3727 if (pkgname == "ESD" ||
3728 pkgname == "ESD.par") hasESD = kTRUE;
3729 if (pkgname == "AOD" ||
3730 pkgname == "AOD.par") hasAOD = kTRUE;
3731 if (pkgname == "ANALYSIS" ||
3732 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3733 if (pkgname == "OADB" ||
3734 pkgname == "OADB.par") hasOADB = kTRUE;
3735 if (pkgname == "ANALYSISalice" ||
3736 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3737 if (pkgname == "CORRFW" ||
3738 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3740 if (hasANALYSISalice) setupPar = "SetupPar";
3741 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3742 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3743 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3744 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3745 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3746 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3747 out << " gSystem->Load(\"libOADB\");" << endl;
3748 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3749 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3750 if (!hasOADB) out << " gSystem->Load(\"libOADB\");" << endl;
3751 else out << " if (!" << setupPar << "(\"OADB\")) return;" << endl;
3752 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3753 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3754 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3755 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3756 out << "// Compile other par packages" << endl;
3758 while ((obj=next())) {
3759 pkgname = obj->GetName();
3760 if (pkgname == "STEERBase" ||
3761 pkgname == "STEERBase.par" ||
3763 pkgname == "ESD.par" ||
3765 pkgname == "AOD.par" ||
3766 pkgname == "ANALYSIS" ||
3767 pkgname == "ANALYSIS.par" ||
3768 pkgname == "OADB" ||
3769 pkgname == "OADB.par" ||
3770 pkgname == "ANALYSISalice" ||
3771 pkgname == "ANALYSISalice.par" ||
3772 pkgname == "CORRFW" ||
3773 pkgname == "CORRFW.par") continue;
3774 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3777 out << "// include path" << endl;
3778 // Get the include path from the interpreter and remove entries pointing to AliRoot
3779 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3780 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3781 out << " TIter nextpath(listpaths);" << endl;
3782 out << " TObjString *pname;" << endl;
3783 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3784 out << " TString current = pname->GetName();" << endl;
3785 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3786 out << " gSystem->AddIncludePath(current);" << endl;
3787 out << " }" << endl;
3788 out << " if (listpaths) delete listpaths;" << endl;
3789 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3790 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3791 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3792 if (fAdditionalLibs.Length()) {
3793 out << "// Add aditional AliRoot libraries" << endl;
3794 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3797 while((str=(TObjString*)next())) {
3798 if (str->GetString().Contains(".so"))
3799 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3801 if (list) delete list;
3804 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3805 if (fAnalysisSource.Length()) {
3806 TObjArray *list = fAnalysisSource.Tokenize(" ");
3809 while((str=(TObjString*)next())) {
3810 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3812 if (list) delete list;
3816 if (fFastReadOption) {
3817 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 !!!");
3818 out << "// fast xrootd reading enabled" << endl;
3819 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3820 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3821 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3822 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3823 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3824 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3826 // Change temp directory to current one
3827 out << "// Set temporary merging directory to current one" << endl;
3828 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3829 out << "// Set temporary compilation directory to current one" << endl;
3830 out << " gSystem->SetBuildDir(gSystem->pwd(), kTRUE);" << endl << endl;
3831 out << "// Connect to AliEn" << endl;
3832 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3833 out << " TString outputDir = dir;" << endl;
3834 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3835 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3836 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3837 out << " TIter *iter = new TIter(list);" << endl;
3838 out << " TObjString *str;" << endl;
3839 out << " TString outputFile;" << endl;
3840 out << " Bool_t merged = kTRUE;" << endl;
3841 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3842 out << " outputFile = str->GetString();" << endl;
3843 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3844 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3845 out << " if (index > 0) outputFile.Remove(index);" << endl;
3846 out << " // Skip already merged outputs" << endl;
3847 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3848 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3849 out << " continue;" << endl;
3850 out << " }" << endl;
3851 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3852 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3853 out << " if (!merged) {" << endl;
3854 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3855 out << " return;" << endl;
3856 out << " }" << endl;
3857 out << " }" << endl;
3858 out << " // all outputs merged, validate" << endl;
3859 out << " ofstream out;" << endl;
3860 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3861 out << " out.close();" << endl;
3862 out << " // read the analysis manager from file" << endl;
3863 TString analysisFile = fExecutable;
3864 analysisFile.ReplaceAll(".sh", ".root");
3865 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3866 out << " AliAnalysisManager *mgr = AliAnalysisAlien::LoadAnalysisManager(\""
3867 << analysisFile << "\");" << endl;
3868 out << " if (!mgr) return;" << endl;
3869 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3870 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3871 out << " mgr->PrintStatus();" << endl;
3872 if (AliAnalysisManager::GetAnalysisManager()) {
3873 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3874 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3876 if (TestBit(AliAnalysisGrid::kTest))
3877 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3879 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3882 out << " TTree *tree = NULL;" << endl;
3883 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3884 out << "}" << endl << endl;
3885 if (hasANALYSISalice) {
3886 out <<"//________________________________________________________________________________" << endl;
3887 out << "Bool_t SetupPar(const char *package) {" << endl;
3888 out << "// Compile the package and set it up." << endl;
3889 out << " TString pkgdir = package;" << endl;
3890 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3891 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3892 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3893 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3894 out << " // Check for BUILD.sh and execute" << endl;
3895 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3896 out << " printf(\"*******************************\\n\");" << endl;
3897 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3898 out << " printf(\"*******************************\\n\");" << endl;
3899 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3900 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3901 out << " gSystem->ChangeDirectory(cdir);" << endl;
3902 out << " return kFALSE;" << endl;
3903 out << " }" << endl;
3904 out << " } else {" << endl;
3905 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3906 out << " gSystem->ChangeDirectory(cdir);" << endl;
3907 out << " return kFALSE;" << endl;
3908 out << " }" << endl;
3909 out << " // Check for SETUP.C and execute" << endl;
3910 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3911 out << " printf(\"*******************************\\n\");" << endl;
3912 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3913 out << " printf(\"*******************************\\n\");" << endl;
3914 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3915 out << " } else {" << endl;
3916 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3917 out << " gSystem->ChangeDirectory(cdir);" << endl;
3918 out << " return kFALSE;" << endl;
3919 out << " }" << endl;
3920 out << " // Restore original workdir" << endl;
3921 out << " gSystem->ChangeDirectory(cdir);" << endl;
3922 out << " return kTRUE;" << endl;
3926 Bool_t copy = kTRUE;
3927 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3930 TString workdir = gGrid->GetHomeDirectory();
3931 workdir += fGridWorkingDir;
3932 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3933 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3934 // TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3935 if (!copyLocal2Alien("WriteMergeMacro",mergingMacro.Data(),
3936 Form("%s/%s", workdir.Data(), mergingMacro.Data()))) Fatal("","Terminating");
3940 //______________________________________________________________________________
3941 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3943 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3944 // Note that for loading the compiled library. The current directory should have precedence in
3946 TString pkgdir = package;
3947 pkgdir.ReplaceAll(".par","");
3948 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3949 TString cdir = gSystem->WorkingDirectory();
3950 gSystem->ChangeDirectory(pkgdir);
3951 // Check for BUILD.sh and execute
3952 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3953 printf("**************************************************\n");
3954 printf("*** Building PAR archive %s\n", package);
3955 printf("**************************************************\n");
3956 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3957 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3958 gSystem->ChangeDirectory(cdir);
3962 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3963 gSystem->ChangeDirectory(cdir);
3966 // Check for SETUP.C and execute
3967 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3968 printf("**************************************************\n");
3969 printf("*** Setup PAR archive %s\n", package);
3970 printf("**************************************************\n");
3971 gROOT->Macro("PROOF-INF/SETUP.C");
3972 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3974 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3975 gSystem->ChangeDirectory(cdir);
3978 // Restore original workdir
3979 gSystem->ChangeDirectory(cdir);
3983 //______________________________________________________________________________
3984 void AliAnalysisAlien::WriteExecutable()
3986 // Generate the alien executable script.
3987 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3989 out.open(fExecutable.Data(), ios::out);
3991 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3994 out << "#!/bin/bash" << endl;
3995 // Make sure we can properly compile par files
3996 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3997 out << "echo \"=========================================\"" << endl;
3998 out << "echo \"############## PATH : ##############\"" << endl;
3999 out << "echo $PATH" << endl;
4000 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4001 out << "echo $LD_LIBRARY_PATH" << endl;
4002 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4003 out << "echo $ROOTSYS" << endl;
4004 out << "echo \"############## which root : ##############\"" << endl;
4005 out << "which root" << endl;
4006 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4007 out << "echo $ALICE_ROOT" << endl;
4008 out << "echo \"############## which aliroot : ##############\"" << endl;
4009 out << "which aliroot" << endl;
4010 out << "echo \"############## system limits : ##############\"" << endl;
4011 out << "ulimit -a" << endl;
4012 out << "echo \"############## memory : ##############\"" << endl;
4013 out << "free -m" << endl;
4014 out << "echo \"=========================================\"" << endl << endl;
4015 out << fExecutableCommand << " ";
4016 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
4017 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
4018 out << "echo \"############## memory after: ##############\"" << endl;
4019 out << "free -m" << endl;
4021 Bool_t copy = kTRUE;
4022 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4025 TString workdir = gGrid->GetHomeDirectory();
4026 TString bindir = Form("%s/bin", workdir.Data());
4027 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4028 workdir += fGridWorkingDir;
4029 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
4030 if (FileExists(executable)) gGrid->Rm(executable);
4031 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
4032 // TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
4033 if (!copyLocal2Alien("WriteExecutable",fExecutable.Data(),
4034 executable.Data())) Fatal("","Terminating");
4038 //______________________________________________________________________________
4039 void AliAnalysisAlien::WriteMergeExecutable()
4041 // Generate the alien executable script for the merging job.
4042 if (!fMergeViaJDL) return;
4043 TString mergeExec = fExecutable;
4044 mergeExec.ReplaceAll(".sh", "_merge.sh");
4045 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4047 out.open(mergeExec.Data(), ios::out);
4049 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
4052 out << "#!/bin/bash" << endl;
4053 // Make sure we can properly compile par files
4054 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
4055 out << "echo \"=========================================\"" << endl;
4056 out << "echo \"############## PATH : ##############\"" << endl;
4057 out << "echo $PATH" << endl;
4058 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
4059 out << "echo $LD_LIBRARY_PATH" << endl;
4060 out << "echo \"############## ROOTSYS : ##############\"" << endl;
4061 out << "echo $ROOTSYS" << endl;
4062 out << "echo \"############## which root : ##############\"" << endl;
4063 out << "which root" << endl;
4064 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
4065 out << "echo $ALICE_ROOT" << endl;
4066 out << "echo \"############## which aliroot : ##############\"" << endl;
4067 out << "which aliroot" << endl;
4068 out << "echo \"############## system limits : ##############\"" << endl;
4069 out << "ulimit -a" << endl;
4070 out << "echo \"############## memory : ##############\"" << endl;
4071 out << "free -m" << endl;
4072 out << "echo \"=========================================\"" << endl << endl;
4073 TString mergeMacro = fExecutable;
4074 mergeMacro.ReplaceAll(".sh", "_merge.C");
4075 if (IsOneStageMerging())
4076 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
4078 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
4079 out << fExecutableCommand << " " << "$ARG" << endl;
4080 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
4081 out << "echo \"############## memory after: ##############\"" << endl;
4082 out << "free -m" << endl;
4084 Bool_t copy = kTRUE;
4085 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4088 TString workdir = gGrid->GetHomeDirectory();
4089 TString bindir = Form("%s/bin", workdir.Data());
4090 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
4091 workdir += fGridWorkingDir;
4092 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
4093 if (FileExists(executable)) gGrid->Rm(executable);
4094 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
4095 // TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
4096 if (!copyLocal2Alien("WriteMergeExecutable",
4097 mergeExec.Data(), executable.Data())) Fatal("","Terminating");
4101 //______________________________________________________________________________
4102 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
4104 // Write the production file to be submitted by LPM manager. The format is:
4105 // First line: full_path_to_jdl estimated_no_subjobs_per_master
4106 // Next lines: full_path_to_dataset XXX (XXX is a string)
4107 // To submit, one has to: submit jdl XXX for all lines
4109 out.open(filename, ios::out);
4111 Error("WriteProductionFile", "Bad file name: %s", filename);
4115 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
4116 workdir = gGrid->GetHomeDirectory();
4117 workdir += fGridWorkingDir;
4118 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
4119 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
4120 out << locjdl << " " << njobspermaster << endl;
4121 Int_t nmasterjobs = fInputFiles->GetEntries();
4122 for (Int_t i=0; i<nmasterjobs; i++) {
4123 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
4124 runOutDir.ReplaceAll(".xml", "");
4126 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
4128 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
4131 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
4132 if (FileExists(filename)) gGrid->Rm(filename);
4133 // TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
4134 if (!copyLocal2Alien("WriteProductionFile", filename,
4135 Form("%s/%s", workdir.Data(),filename))) Fatal("","Terminating");
4139 //______________________________________________________________________________
4140 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
4142 // Generate the alien validation script.
4143 // Generate the validation script
4145 if (fValidationScript.IsNull()) {
4146 fValidationScript = fExecutable;
4147 fValidationScript.ReplaceAll(".sh", "_validation.sh");
4149 TString validationScript = fValidationScript;
4150 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
4152 Error("WriteValidationScript", "Alien connection required");
4155 if (!fTerminateFiles.IsNull()) {
4156 fTerminateFiles.Strip();
4157 fTerminateFiles.ReplaceAll(" ",",");
4159 TString outStream = "";
4160 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
4161 if (!TestBit(AliAnalysisGrid::kSubmit)) {
4163 out.open(validationScript, ios::out);
4164 out << "#!/bin/bash" << endl;
4165 out << "##################################################" << endl;
4166 out << "validateout=`dirname $0`" << endl;
4167 out << "validatetime=`date`" << endl;
4168 out << "validated=\"0\";" << endl;
4169 out << "error=0" << endl;
4170 out << "if [ -z $validateout ]" << endl;
4171 out << "then" << endl;
4172 out << " validateout=\".\"" << endl;
4173 out << "fi" << endl << endl;
4174 out << "cd $validateout;" << endl;
4175 out << "validateworkdir=`pwd`;" << endl << endl;
4176 out << "echo \"*******************************************************\"" << outStream << endl;
4177 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
4179 out << "echo \"* Time: $validatetime \"" << outStream << endl;
4180 out << "echo \"* Dir: $validateout\"" << outStream << endl;
4181 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
4182 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4183 out << "ls -la ./" << outStream << endl;
4184 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
4185 out << "##################################################" << endl;
4188 out << "if [ ! -f stderr ] ; then" << endl;
4189 out << " error=1" << endl;
4190 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
4191 out << " echo \"Error = $error\" " << outStream << endl;
4192 out << "fi" << endl;
4194 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
4195 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
4196 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
4197 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
4200 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
4201 out << " error=1" << endl;
4202 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
4203 out << " echo \"$parArch\" " << outStream << endl;
4204 out << " echo \"Error = $error\" " << outStream << endl;
4205 out << "fi" << endl;
4207 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
4208 out << " error=1" << endl;
4209 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
4210 out << " echo \"$segViol\" " << outStream << endl;
4211 out << " echo \"Error = $error\" " << outStream << endl;
4212 out << "fi" << endl;
4214 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
4215 out << " error=1" << endl;
4216 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
4217 out << " echo \"$segFault\" " << outStream << endl;
4218 out << " echo \"Error = $error\" " << outStream << endl;
4219 out << "fi" << endl;
4221 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
4222 out << " error=1" << endl;
4223 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
4224 out << " echo \"$glibcErr\" " << outStream << endl;
4225 out << " echo \"Error = $error\" " << outStream << endl;
4226 out << "fi" << endl;
4228 // Part dedicated to the specific analyses running into the train
4230 TString outputFiles = fOutputFiles;
4231 if (merge && !fTerminateFiles.IsNull()) {
4233 outputFiles += fTerminateFiles;
4235 TObjArray *arr = outputFiles.Tokenize(",");
4238 while (!merge && (os=(TObjString*)next1())) {
4239 // No need to validate outputs produced by merging since the merging macro does this
4240 outputFile = os->GetString();
4241 Int_t index = outputFile.Index("@");
4242 if (index > 0) outputFile.Remove(index);
4243 if (fTerminateFiles.Contains(outputFile)) continue;
4244 if (outputFile.Contains("*")) continue;
4245 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
4246 out << " error=1" << endl;
4247 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
4248 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
4249 out << "fi" << endl;
4252 out << "if ! [ -f outputs_valid ] ; then" << endl;
4253 out << " error=1" << endl;
4254 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
4255 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
4256 out << "fi" << endl;
4258 out << "if [ $error = 0 ] ; then" << endl;
4259 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
4260 if (!IsKeepLogs()) {
4261 out << " echo \"* === Logs std* will be deleted === \"" << endl;
4263 out << " rm -f std*" << endl;
4265 out << "fi" << endl;
4267 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
4268 out << "echo \"*******************************************************\"" << outStream << endl;
4269 out << "cd -" << endl;
4270 out << "exit $error" << endl;
4272 Bool_t copy = kTRUE;
4273 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4276 TString workdir = gGrid->GetHomeDirectory();
4277 workdir += fGridWorkingDir;
4278 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4279 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4280 // TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));
4281 if (!copyLocal2Alien("WriteValidationScript", validationScript.Data(),
4282 Form("%s/%s",workdir.Data(), validationScript.Data()))) Fatal("","Terminating");