1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "Riostream.h"
30 #include "TFileCollection.h"
32 #include "TObjString.h"
33 #include "TObjArray.h"
35 #include "TGridResult.h"
36 #include "TGridCollection.h"
38 #include "TGridJobStatusList.h"
39 #include "TGridJobStatus.h"
40 #include "TFileMerger.h"
41 #include "AliAnalysisManager.h"
42 #include "AliVEventHandler.h"
43 #include "AliAnalysisDataContainer.h"
44 #include "AliAnalysisAlien.h"
46 ClassImp(AliAnalysisAlien)
48 //______________________________________________________________________________
49 AliAnalysisAlien::AliAnalysisAlien()
55 fSplitMaxInputFileNumber(0),
57 fMasterResubmitThreshold(0),
70 fNproofWorkersPerSlave(0),
80 fAdditionalRootLibs(),
108 fRootVersionForProof(),
118 //______________________________________________________________________________
119 AliAnalysisAlien::AliAnalysisAlien(const char *name)
120 :AliAnalysisGrid(name),
125 fSplitMaxInputFileNumber(0),
127 fMasterResubmitThreshold(0),
140 fNproofWorkersPerSlave(0),
144 fExecutableCommand(),
150 fAdditionalRootLibs(),
178 fRootVersionForProof(),
188 //______________________________________________________________________________
189 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
190 :AliAnalysisGrid(other),
193 fPrice(other.fPrice),
195 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
196 fMaxInitFailed(other.fMaxInitFailed),
197 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
198 fNtestFiles(other.fNtestFiles),
199 fNrunsPerMaster(other.fNrunsPerMaster),
200 fMaxMergeFiles(other.fMaxMergeFiles),
201 fMaxMergeStages(other.fMaxMergeStages),
202 fNsubmitted(other.fNsubmitted),
203 fProductionMode(other.fProductionMode),
204 fOutputToRunNo(other.fOutputToRunNo),
205 fMergeViaJDL(other.fMergeViaJDL),
206 fFastReadOption(other.fFastReadOption),
207 fOverwriteMode(other.fOverwriteMode),
208 fNreplicas(other.fNreplicas),
209 fNproofWorkers(other.fNproofWorkers),
210 fNproofWorkersPerSlave(other.fNproofWorkersPerSlave),
211 fProofReset(other.fProofReset),
212 fRunNumbers(other.fRunNumbers),
213 fExecutable(other.fExecutable),
214 fExecutableCommand(other.fExecutableCommand),
215 fArguments(other.fArguments),
216 fExecutableArgs(other.fExecutableArgs),
217 fAnalysisMacro(other.fAnalysisMacro),
218 fAnalysisSource(other.fAnalysisSource),
219 fValidationScript(other.fValidationScript),
220 fAdditionalRootLibs(other.fAdditionalRootLibs),
221 fAdditionalLibs(other.fAdditionalLibs),
222 fSplitMode(other.fSplitMode),
223 fAPIVersion(other.fAPIVersion),
224 fROOTVersion(other.fROOTVersion),
225 fAliROOTVersion(other.fAliROOTVersion),
226 fExternalPackages(other.fExternalPackages),
228 fGridWorkingDir(other.fGridWorkingDir),
229 fGridDataDir(other.fGridDataDir),
230 fDataPattern(other.fDataPattern),
231 fGridOutputDir(other.fGridOutputDir),
232 fOutputArchive(other.fOutputArchive),
233 fOutputFiles(other.fOutputFiles),
234 fInputFormat(other.fInputFormat),
235 fDatasetName(other.fDatasetName),
236 fJDLName(other.fJDLName),
237 fTerminateFiles(other.fTerminateFiles),
238 fMergeExcludes(other.fMergeExcludes),
239 fIncludePath(other.fIncludePath),
240 fCloseSE(other.fCloseSE),
241 fFriendChainName(other.fFriendChainName),
242 fJobTag(other.fJobTag),
243 fOutputSingle(other.fOutputSingle),
244 fRunPrefix(other.fRunPrefix),
245 fProofCluster(other.fProofCluster),
246 fProofDataSet(other.fProofDataSet),
247 fFileForTestMode(other.fFileForTestMode),
248 fRootVersionForProof(other.fRootVersionForProof),
249 fAliRootMode(other.fAliRootMode),
250 fMergeDirName(other.fMergeDirName),
255 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
256 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
257 fRunRange[0] = other.fRunRange[0];
258 fRunRange[1] = other.fRunRange[1];
259 if (other.fInputFiles) {
260 fInputFiles = new TObjArray();
261 TIter next(other.fInputFiles);
263 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
264 fInputFiles->SetOwner();
266 if (other.fPackages) {
267 fPackages = new TObjArray();
268 TIter next(other.fPackages);
270 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
271 fPackages->SetOwner();
275 //______________________________________________________________________________
276 AliAnalysisAlien::~AliAnalysisAlien()
279 if (fGridJDL) delete fGridJDL;
280 if (fMergingJDL) delete fMergingJDL;
281 if (fInputFiles) delete fInputFiles;
282 if (fPackages) delete fPackages;
285 //______________________________________________________________________________
286 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
289 if (this != &other) {
290 AliAnalysisGrid::operator=(other);
291 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
292 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
293 fPrice = other.fPrice;
295 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
296 fMaxInitFailed = other.fMaxInitFailed;
297 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
298 fNtestFiles = other.fNtestFiles;
299 fNrunsPerMaster = other.fNrunsPerMaster;
300 fMaxMergeFiles = other.fMaxMergeFiles;
301 fMaxMergeStages = other.fMaxMergeStages;
302 fNsubmitted = other.fNsubmitted;
303 fProductionMode = other.fProductionMode;
304 fOutputToRunNo = other.fOutputToRunNo;
305 fMergeViaJDL = other.fMergeViaJDL;
306 fFastReadOption = other.fFastReadOption;
307 fOverwriteMode = other.fOverwriteMode;
308 fNreplicas = other.fNreplicas;
309 fNproofWorkers = other.fNproofWorkers;
310 fNproofWorkersPerSlave = other.fNproofWorkersPerSlave;
311 fProofReset = other.fProofReset;
312 fRunNumbers = other.fRunNumbers;
313 fExecutable = other.fExecutable;
314 fExecutableCommand = other.fExecutableCommand;
315 fArguments = other.fArguments;
316 fExecutableArgs = other.fExecutableArgs;
317 fAnalysisMacro = other.fAnalysisMacro;
318 fAnalysisSource = other.fAnalysisSource;
319 fValidationScript = other.fValidationScript;
320 fAdditionalRootLibs = other.fAdditionalRootLibs;
321 fAdditionalLibs = other.fAdditionalLibs;
322 fSplitMode = other.fSplitMode;
323 fAPIVersion = other.fAPIVersion;
324 fROOTVersion = other.fROOTVersion;
325 fAliROOTVersion = other.fAliROOTVersion;
326 fExternalPackages = other.fExternalPackages;
328 fGridWorkingDir = other.fGridWorkingDir;
329 fGridDataDir = other.fGridDataDir;
330 fDataPattern = other.fDataPattern;
331 fGridOutputDir = other.fGridOutputDir;
332 fOutputArchive = other.fOutputArchive;
333 fOutputFiles = other.fOutputFiles;
334 fInputFormat = other.fInputFormat;
335 fDatasetName = other.fDatasetName;
336 fJDLName = other.fJDLName;
337 fTerminateFiles = other.fTerminateFiles;
338 fMergeExcludes = other.fMergeExcludes;
339 fIncludePath = other.fIncludePath;
340 fCloseSE = other.fCloseSE;
341 fFriendChainName = other.fFriendChainName;
342 fJobTag = other.fJobTag;
343 fOutputSingle = other.fOutputSingle;
344 fRunPrefix = other.fRunPrefix;
345 fProofCluster = other.fProofCluster;
346 fProofDataSet = other.fProofDataSet;
347 fFileForTestMode = other.fFileForTestMode;
348 fRootVersionForProof = other.fRootVersionForProof;
349 fAliRootMode = other.fAliRootMode;
350 fMergeDirName = other.fMergeDirName;
351 if (other.fInputFiles) {
352 fInputFiles = new TObjArray();
353 TIter next(other.fInputFiles);
355 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
356 fInputFiles->SetOwner();
358 if (other.fPackages) {
359 fPackages = new TObjArray();
360 TIter next(other.fPackages);
362 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
363 fPackages->SetOwner();
369 //______________________________________________________________________________
370 void AliAnalysisAlien::SetRunPrefix(const char *prefix)
372 // Set the run number format. Can be a prefix or a format like "%09d"
374 if (!fRunPrefix.Contains("%")) fRunPrefix += "%d";
377 //______________________________________________________________________________
378 void AliAnalysisAlien::AddIncludePath(const char *path)
380 // Add include path in the remote analysis macro.
382 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
383 else fIncludePath += Form("-I%s ", path);
386 //______________________________________________________________________________
387 void AliAnalysisAlien::AddRunNumber(Int_t run)
389 // Add a run number to the list of runs to be processed.
390 if (fRunNumbers.Length()) fRunNumbers += " ";
391 fRunNumbers += Form(fRunPrefix.Data(), run);
394 //______________________________________________________________________________
395 void AliAnalysisAlien::AddRunNumber(const char* run)
397 // Add a run number to the list of runs to be processed.
398 if (fRunNumbers.Length()) fRunNumbers += " ";
402 //______________________________________________________________________________
403 void AliAnalysisAlien::AddDataFile(const char *lfn)
405 // Adds a data file to the input to be analysed. The file should be a valid LFN
406 // or point to an existing file in the alien workdir.
407 if (!fInputFiles) fInputFiles = new TObjArray();
408 fInputFiles->Add(new TObjString(lfn));
411 //______________________________________________________________________________
412 void AliAnalysisAlien::AddExternalPackage(const char *package)
414 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
415 if (fExternalPackages) fExternalPackages += " ";
416 fExternalPackages += package;
419 //______________________________________________________________________________
420 Bool_t AliAnalysisAlien::Connect()
422 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
423 if (gGrid && gGrid->IsConnected()) return kTRUE;
424 if (fProductionMode) return kTRUE;
426 Info("Connect", "Trying to connect to AliEn ...");
427 TGrid::Connect("alien://");
429 if (!gGrid || !gGrid->IsConnected()) {
430 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
433 fUser = gGrid->GetUser();
434 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
438 //______________________________________________________________________________
439 void AliAnalysisAlien::CdWork()
441 // Check validity of alien workspace. Create directory if possible.
443 Error("CdWork", "Alien connection required");
446 TString homedir = gGrid->GetHomeDirectory();
447 TString workdir = homedir + fGridWorkingDir;
448 if (DirectoryExists(workdir)) {
452 // Work directory not existing - create it
454 if (gGrid->Mkdir(workdir, "-p")) {
455 gGrid->Cd(fGridWorkingDir);
456 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
458 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
459 workdir.Data(), homedir.Data());
460 fGridWorkingDir = "";
464 //______________________________________________________________________________
465 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
467 // Check if file copying is possible.
468 if (fProductionMode) return kTRUE;
470 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
473 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
474 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
475 // Check if alien_CLOSE_SE is defined
476 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
477 if (!closeSE.IsNull()) {
478 Info("CheckFileCopy", "Your current close storage is pointing to: \
479 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
481 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
483 // Check if grid directory exists.
484 if (!DirectoryExists(alienpath)) {
485 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
488 TFile f("plugin_test_copy", "RECREATE");
489 // User may not have write permissions to current directory
491 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
492 gSystem->WorkingDirectory());
496 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
497 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
498 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
499 \n# 1. Make sure you have write permissions there. If this is the case: \
500 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
501 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
502 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
503 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
504 gSystem->Unlink(f.GetName());
507 gSystem->Unlink(f.GetName());
508 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
509 Info("CheckFileCopy", "### ...SUCCESS ###");
513 //______________________________________________________________________________
514 Bool_t AliAnalysisAlien::CheckInputData()
516 // Check validity of input data. If necessary, create xml files.
517 if (fProductionMode) return kTRUE;
518 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
519 if (!fGridDataDir.Length()) {
520 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
524 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
527 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
528 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
529 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
532 // Process declared files
533 Bool_t isCollection = kFALSE;
534 Bool_t isXml = kFALSE;
535 Bool_t useTags = kFALSE;
536 Bool_t checked = kFALSE;
537 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
539 TString workdir = gGrid->GetHomeDirectory();
540 workdir += fGridWorkingDir;
543 TIter next(fInputFiles);
544 while ((objstr=(TObjString*)next())) {
547 file += objstr->GetString();
548 // Store full lfn path
549 if (FileExists(file)) objstr->SetString(file);
551 file = objstr->GetName();
552 if (!FileExists(objstr->GetName())) {
553 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
554 objstr->GetName(), workdir.Data());
558 Bool_t iscoll, isxml, usetags;
559 CheckDataType(file, iscoll, isxml, usetags);
562 isCollection = iscoll;
565 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
567 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
568 Error("CheckInputData", "Some conflict was found in the types of inputs");
574 // Process requested run numbers
575 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
576 // Check validity of alien data directory
577 if (!fGridDataDir.Length()) {
578 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
581 if (!DirectoryExists(fGridDataDir)) {
582 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
586 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
590 if (checked && !isXml) {
591 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
594 // Check validity of run number(s)
599 TString schunk, schunk2;
603 useTags = fDataPattern.Contains("tag");
604 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
606 if (useTags != fDataPattern.Contains("tag")) {
607 Error("CheckInputData", "Cannot mix input files using/not using tags");
610 if (fRunNumbers.Length()) {
611 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
612 arr = fRunNumbers.Tokenize(" ");
614 while ((os=(TObjString*)next())) {
615 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
616 if (!DirectoryExists(path)) {
617 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
620 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
621 TString msg = "\n##### file: ";
623 msg += " type: xml_collection;";
624 if (useTags) msg += " using_tags: Yes";
625 else msg += " using_tags: No";
626 Info("CheckDataType", "%s", msg.Data());
627 if (fNrunsPerMaster<2) {
628 AddDataFile(Form("%s.xml", os->GetString().Data()));
631 if (((nruns-1)%fNrunsPerMaster) == 0) {
632 schunk = os->GetString();
634 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
635 schunk += Form("_%s.xml", os->GetString().Data());
641 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
642 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
643 format = Form("%%s/%s ", fRunPrefix.Data());
644 path = Form(format.Data(), fGridDataDir.Data(), irun);
645 if (!DirectoryExists(path)) {
648 format = Form("%%s/%s.xml", fRunPrefix.Data());
649 path = Form(format.Data(), workdir.Data(),irun);
650 TString msg = "\n##### file: ";
652 msg += " type: xml_collection;";
653 if (useTags) msg += " using_tags: Yes";
654 else msg += " using_tags: No";
655 Info("CheckDataType", "%s", msg.Data());
656 if (fNrunsPerMaster<2) {
657 format = Form("%s.xml", fRunPrefix.Data());
658 AddDataFile(Form(format.Data(),irun));
661 if (((nruns-1)%fNrunsPerMaster) == 0) {
662 schunk = Form(fRunPrefix.Data(),irun);
664 format = Form("_%s.xml", fRunPrefix.Data());
665 schunk2 = Form(format.Data(), irun);
666 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
679 //______________________________________________________________________________
680 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
682 // Create dataset for the grid data directory + run number.
683 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
685 Error("CreateDataset", "Cannot create dataset with no grid connection");
690 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
691 TString workdir = gGrid->GetHomeDirectory();
692 workdir += fGridWorkingDir;
694 // Compose the 'find' command arguments
697 TString options = "-x collection ";
698 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
699 TString conditions = "";
704 TString schunk, schunk2;
705 TGridCollection *cbase=0, *cadd=0;
706 if (!fRunNumbers.Length() && !fRunRange[0]) {
707 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
708 // Make a single data collection from data directory.
710 if (!DirectoryExists(path)) {
711 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
715 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
716 else file = Form("%s.xml", gSystem->BaseName(path));
717 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
723 command += conditions;
724 printf("command: %s\n", command.Data());
725 TGridResult *res = gGrid->Command(command);
727 // Write standard output to file
728 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
729 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
730 Bool_t nullFile = kFALSE;
732 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
734 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
736 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
741 Bool_t fileExists = FileExists(file);
742 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
743 // Copy xml file to alien space
744 if (fileExists) gGrid->Rm(file);
745 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
746 if (!FileExists(file)) {
747 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
750 // Update list of files to be processed.
752 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
756 Bool_t nullResult = kTRUE;
757 if (fRunNumbers.Length()) {
758 TObjArray *arr = fRunNumbers.Tokenize(" ");
761 while ((os=(TObjString*)next())) {
762 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
763 if (!DirectoryExists(path)) continue;
765 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
766 else file = Form("%s.xml", os->GetString().Data());
767 // If local collection file does not exist, create it via 'find' command.
768 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
773 command += conditions;
774 TGridResult *res = gGrid->Command(command);
776 // Write standard output to file
777 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
778 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
779 Bool_t nullFile = kFALSE;
781 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
783 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
785 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
786 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
792 if (TestBit(AliAnalysisGrid::kTest)) break;
793 // Check if there is one run per master job.
794 if (fNrunsPerMaster<2) {
795 if (FileExists(file)) {
796 if (fOverwriteMode) gGrid->Rm(file);
798 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
802 // Copy xml file to alien space
803 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
804 if (!FileExists(file)) {
805 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
811 if (((nruns-1)%fNrunsPerMaster) == 0) {
812 schunk = os->GetString();
813 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
815 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
816 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
820 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
823 schunk += Form("_%s.xml", os->GetString().Data());
824 if (FileExists(schunk)) {
825 if (fOverwriteMode) gGrid->Rm(file);
827 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
831 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
832 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
833 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
834 if (!FileExists(schunk)) {
835 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
843 Error("CreateDataset", "No valid dataset corresponding to the query!");
847 // Process a full run range.
848 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
849 format = Form("%%s/%s ", fRunPrefix.Data());
850 path = Form(format.Data(), fGridDataDir.Data(), irun);
851 if (!DirectoryExists(path)) continue;
853 format = Form("%s.xml", fRunPrefix.Data());
854 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
855 else file = Form(format.Data(), irun);
856 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
857 if (fOverwriteMode) gGrid->Rm(file);
859 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
863 // If local collection file does not exist, create it via 'find' command.
864 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
869 command += conditions;
870 TGridResult *res = gGrid->Command(command);
872 // Write standard output to file
873 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
874 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
875 Bool_t nullFile = kFALSE;
877 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
879 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
881 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
887 if (TestBit(AliAnalysisGrid::kTest)) break;
888 // Check if there is one run per master job.
889 if (fNrunsPerMaster<2) {
890 if (FileExists(file)) {
891 if (fOverwriteMode) gGrid->Rm(file);
893 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
897 // Copy xml file to alien space
898 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
899 if (!FileExists(file)) {
900 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
905 // Check if the collection for the chunk exist locally.
906 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
907 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
908 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
911 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
912 if (((nruns-1)%fNrunsPerMaster) == 0) {
913 schunk = Form(fRunPrefix.Data(), irun);
914 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
916 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
920 format = Form("%%s_%s.xml", fRunPrefix.Data());
921 schunk2 = Form(format.Data(), schunk.Data(), irun);
922 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
926 if (FileExists(schunk)) {
927 if (fOverwriteMode) gGrid->Rm(schunk);
929 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
933 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
934 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
935 if (FileExists(schunk)) {
936 if (fOverwriteMode) gGrid->Rm(schunk);
938 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
942 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
943 if (!FileExists(schunk)) {
944 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
950 Error("CreateDataset", "No valid dataset corresponding to the query!");
957 //______________________________________________________________________________
958 Bool_t AliAnalysisAlien::CreateJDL()
960 // Generate a JDL file according to current settings. The name of the file is
961 // specified by fJDLName.
962 Bool_t error = kFALSE;
965 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
966 Bool_t generate = kTRUE;
967 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
969 Error("CreateJDL", "Alien connection required");
972 // Check validity of alien workspace
974 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
975 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
976 workdir += fGridWorkingDir;
980 Error("CreateJDL()", "Define some input files for your analysis.");
983 // Compose list of input files
984 // Check if output files were defined
985 if (!fOutputFiles.Length()) {
986 Error("CreateJDL", "You must define at least one output file");
989 // Check if an output directory was defined and valid
990 if (!fGridOutputDir.Length()) {
991 Error("CreateJDL", "You must define AliEn output directory");
994 if (!fProductionMode) {
995 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
996 if (!DirectoryExists(fGridOutputDir)) {
997 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
998 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1000 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1004 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1009 // Exit if any error up to now
1010 if (error) return kFALSE;
1012 if (!fUser.IsNull()) {
1013 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1014 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1016 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1017 TString mergeExec = fExecutable;
1018 mergeExec.ReplaceAll(".sh", "_merge.sh");
1019 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1020 mergeExec.ReplaceAll(".sh", ".C");
1021 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1022 if (!fArguments.IsNull())
1023 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1024 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1026 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1027 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1030 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1031 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1032 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1033 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1035 if (fMaxInitFailed > 0) {
1036 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1037 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1039 if (fSplitMaxInputFileNumber > 0) {
1040 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1041 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1043 if (!IsOneStageMerging()) {
1044 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1045 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1047 if (fSplitMode.Length()) {
1048 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1049 fGridJDL->SetDescription("Split", "We split per SE or file");
1051 fMergingJDL->SetValue("Split", "\"se\"");
1052 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1053 if (!fAliROOTVersion.IsNull()) {
1054 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1055 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1057 if (!fROOTVersion.IsNull()) {
1058 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1059 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1061 if (!fAPIVersion.IsNull()) {
1062 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1063 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1065 if (!fExternalPackages.IsNull()) {
1066 arr = fExternalPackages.Tokenize(" ");
1068 while ((os=(TObjString*)next())) {
1069 TString pkgname = os->GetString();
1070 Int_t index = pkgname.Index("::");
1071 TString pkgversion = pkgname(index+2, pkgname.Length());
1072 pkgname.Remove(index);
1073 fGridJDL->AddToPackages(pkgname, pkgversion);
1074 fMergingJDL->AddToPackages(pkgname, pkgversion);
1078 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1079 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1080 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1081 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1082 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1083 TString analysisFile = fExecutable;
1084 analysisFile.ReplaceAll(".sh", ".root");
1085 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1086 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1087 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1088 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1089 if (fAdditionalLibs.Length()) {
1090 arr = fAdditionalLibs.Tokenize(" ");
1092 while ((os=(TObjString*)next())) {
1093 if (os->GetString().Contains(".so")) continue;
1094 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1095 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1100 TIter next(fPackages);
1102 while ((obj=next())) {
1103 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1104 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1107 if (fOutputArchive.Length()) {
1108 arr = fOutputArchive.Tokenize(" ");
1110 Bool_t first = kTRUE;
1111 const char *comment = "Files to be archived";
1112 const char *comment1 = comment;
1113 while ((os=(TObjString*)next())) {
1114 if (!first) comment = NULL;
1115 if (!os->GetString().Contains("@") && fCloseSE.Length())
1116 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1118 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1122 // Output archive for the merging jdl
1123 TString outputArchive;
1124 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1125 outputArchive = "log_archive.zip:std*@disk=1 ";
1126 // Add normal output files, extra files + terminate files
1127 TString files = GetListOfFiles("outextter");
1128 // Do not register merge excludes
1129 if (!fMergeExcludes.IsNull()) {
1130 arr = fMergeExcludes.Tokenize(" ");
1132 while ((os=(TObjString*)next1())) {
1133 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1134 files.ReplaceAll(os->GetString(),"");
1138 files.ReplaceAll(".root", "*.root");
1139 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1141 TString files = fOutputArchive;
1142 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1143 outputArchive = files;
1145 arr = outputArchive.Tokenize(" ");
1149 while ((os=(TObjString*)next2())) {
1150 if (!first) comment = NULL;
1151 TString currentfile = os->GetString();
1152 if (!currentfile.Contains("@") && fCloseSE.Length())
1153 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1155 fMergingJDL->AddToOutputArchive(currentfile, comment);
1160 arr = fOutputFiles.Tokenize(",");
1162 Bool_t first = kTRUE;
1163 const char *comment = "Files to be saved";
1164 while ((os=(TObjString*)next())) {
1165 // Ignore ouputs in jdl that are also in outputarchive
1166 TString sout = os->GetString();
1167 sout.ReplaceAll("*", "");
1168 sout.ReplaceAll(".root", "");
1169 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1170 if (fOutputArchive.Contains(sout)) continue;
1171 if (!first) comment = NULL;
1172 if (!os->GetString().Contains("@") && fCloseSE.Length())
1173 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1175 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1177 if (fMergeExcludes.Contains(sout)) continue;
1178 if (!os->GetString().Contains("@") && fCloseSE.Length())
1179 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1181 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1184 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1185 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1186 TString validationScript = fValidationScript;
1187 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1188 validationScript.ReplaceAll(".sh", "_merge.sh");
1189 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1190 if (fMasterResubmitThreshold) {
1191 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1192 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1194 // Write a jdl with 2 input parameters: collection name and output dir name.
1197 // Copy jdl to grid workspace
1199 // Check if an output directory was defined and valid
1200 if (!fGridOutputDir.Length()) {
1201 Error("CreateJDL", "You must define AliEn output directory");
1204 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1205 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1206 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1207 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1209 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1215 if (TestBit(AliAnalysisGrid::kSubmit)) {
1216 TString mergeJDLName = fExecutable;
1217 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1218 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1219 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1220 if (fProductionMode) {
1221 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1222 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1224 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1225 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1226 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1227 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1229 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1230 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1233 if (fAdditionalLibs.Length()) {
1234 arr = fAdditionalLibs.Tokenize(" ");
1237 while ((os=(TObjString*)next())) {
1238 if (os->GetString().Contains(".so")) continue;
1239 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1240 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1241 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1246 TIter next(fPackages);
1248 while ((obj=next())) {
1249 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1250 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1251 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1258 //______________________________________________________________________________
1259 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1261 // Writes one or more JDL's corresponding to findex. If findex is negative,
1262 // all run numbers are considered in one go (jdl). For non-negative indices
1263 // they correspond to the indices in the array fInputFiles.
1264 if (!fInputFiles) return kFALSE;
1267 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1268 workdir += fGridWorkingDir;
1269 TString stageName = "$2";
1270 if (fProductionMode) stageName = "$4";
1271 if (!fMergeDirName.IsNull()) {
1272 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1273 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1275 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1276 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1278 if (fProductionMode) {
1279 TIter next(fInputFiles);
1280 while ((os=next())) {
1281 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1283 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1285 if (!fRunNumbers.Length() && !fRunRange[0]) {
1286 // One jdl with no parameters in case input data is specified by name.
1287 TIter next(fInputFiles);
1289 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1290 if (!fOutputSingle.IsNull())
1291 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1293 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1294 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1297 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1298 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1299 if (!fOutputSingle.IsNull()) {
1300 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1301 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1303 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1308 // Generate the JDL as a string
1309 TString sjdl = fGridJDL->Generate();
1310 TString sjdl1 = fMergingJDL->Generate();
1312 if (!fMergeDirName.IsNull()) {
1313 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1314 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1316 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1317 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1319 TString sjdl2 = fMergingJDL->Generate();
1320 Int_t index, index1;
1321 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1322 sjdl.ReplaceAll("(member", "\n (member");
1323 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1324 sjdl.ReplaceAll("{", "{\n ");
1325 sjdl.ReplaceAll("};", "\n};");
1326 sjdl.ReplaceAll("{\n \n", "{\n");
1327 sjdl.ReplaceAll("\n\n", "\n");
1328 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1329 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1330 sjdl1.ReplaceAll("(member", "\n (member");
1331 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1332 sjdl1.ReplaceAll("{", "{\n ");
1333 sjdl1.ReplaceAll("};", "\n};");
1334 sjdl1.ReplaceAll("{\n \n", "{\n");
1335 sjdl1.ReplaceAll("\n\n", "\n");
1336 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1337 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1338 sjdl2.ReplaceAll("(member", "\n (member");
1339 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1340 sjdl2.ReplaceAll("{", "{\n ");
1341 sjdl2.ReplaceAll("};", "\n};");
1342 sjdl2.ReplaceAll("{\n \n", "{\n");
1343 sjdl2.ReplaceAll("\n\n", "\n");
1344 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1345 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1346 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1347 index = sjdl.Index("JDLVariables");
1348 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1349 sjdl += "Workdirectorysize = {\"5000MB\"};";
1350 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1351 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1352 index = fJobTag.Index(":");
1353 if (index < 0) index = fJobTag.Length();
1354 TString jobTag = fJobTag;
1355 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1356 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1357 if (fProductionMode) {
1358 sjdl1.Prepend("# Generated merging jdl (production mode) \
1359 \n# $1 = full alien path to output directory to be merged \
1360 \n# $2 = train number \
1361 \n# $3 = production (like LHC10b) \
1362 \n# $4 = merging stage \
1363 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1364 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1365 sjdl2.Prepend("# Generated merging jdl \
1366 \n# $1 = full alien path to output directory to be merged \
1367 \n# $2 = train number \
1368 \n# $3 = production (like LHC10b) \
1369 \n# $4 = merging stage \
1370 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1372 sjdl1.Prepend("# Generated merging jdl \
1373 \n# $1 = full alien path to output directory to be merged \
1374 \n# $2 = merging stage \
1375 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1376 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1377 sjdl2.Prepend("# Generated merging jdl \
1378 \n# $1 = full alien path to output directory to be merged \
1379 \n# $2 = merging stage \
1380 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1382 index = sjdl1.Index("JDLVariables");
1383 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1384 index = sjdl2.Index("JDLVariables");
1385 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1386 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1387 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1388 index = sjdl2.Index("Split =");
1390 index1 = sjdl2.Index("\n", index);
1391 sjdl2.Remove(index, index1-index+1);
1393 index = sjdl2.Index("SplitMaxInputFileNumber");
1395 index1 = sjdl2.Index("\n", index);
1396 sjdl2.Remove(index, index1-index+1);
1398 index = sjdl2.Index("InputDataCollection");
1400 index1 = sjdl2.Index(";", index);
1401 sjdl2.Remove(index, index1-index+1);
1403 index = sjdl2.Index("InputDataListFormat");
1405 index1 = sjdl2.Index("\n", index);
1406 sjdl2.Remove(index, index1-index+1);
1408 index = sjdl2.Index("InputDataList");
1410 index1 = sjdl2.Index("\n", index);
1411 sjdl2.Remove(index, index1-index+1);
1413 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1414 // Write jdl to file
1416 out.open(fJDLName.Data(), ios::out);
1418 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1421 out << sjdl << endl;
1423 TString mergeJDLName = fExecutable;
1424 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1427 out1.open(mergeJDLName.Data(), ios::out);
1429 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1432 out1 << sjdl1 << endl;
1435 TString finalJDL = mergeJDLName;
1436 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1437 out2.open(finalJDL.Data(), ios::out);
1439 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1442 out2 << sjdl2 << endl;
1446 // Copy jdl to grid workspace
1448 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1450 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1451 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1452 TString finalJDL = mergeJDLName;
1453 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1454 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1455 if (fProductionMode) {
1456 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1457 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1458 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1460 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1461 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1462 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1463 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1464 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1466 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1467 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1468 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1474 //______________________________________________________________________________
1475 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1477 // Returns true if file exists.
1478 if (!gGrid) return kFALSE;
1480 slfn.ReplaceAll("alien://","");
1481 TGridResult *res = gGrid->Ls(slfn);
1482 if (!res) return kFALSE;
1483 TMap *map = dynamic_cast<TMap*>(res->At(0));
1488 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1489 if (!objs || !objs->GetString().Length()) {
1497 //______________________________________________________________________________
1498 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1500 // Returns true if directory exists. Can be also a path.
1501 if (!gGrid) return kFALSE;
1502 // Check if dirname is a path
1503 TString dirstripped = dirname;
1504 dirstripped = dirstripped.Strip();
1505 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1506 TString dir = gSystem->BaseName(dirstripped);
1508 TString path = gSystem->DirName(dirstripped);
1509 TGridResult *res = gGrid->Ls(path, "-F");
1510 if (!res) return kFALSE;
1514 while ((map=dynamic_cast<TMap*>(next()))) {
1515 obj = map->GetValue("name");
1517 if (dir == obj->GetName()) {
1526 //______________________________________________________________________________
1527 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1529 // Check input data type.
1530 isCollection = kFALSE;
1534 Error("CheckDataType", "No connection to grid");
1537 isCollection = IsCollection(lfn);
1538 TString msg = "\n##### file: ";
1541 msg += " type: raw_collection;";
1542 // special treatment for collections
1544 // check for tag files in the collection
1545 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1547 msg += " using_tags: No (unknown)";
1548 Info("CheckDataType", "%s", msg.Data());
1551 const char* typeStr = res->GetKey(0, "origLFN");
1552 if (!typeStr || !strlen(typeStr)) {
1553 msg += " using_tags: No (unknown)";
1554 Info("CheckDataType", "%s", msg.Data());
1557 TString file = typeStr;
1558 useTags = file.Contains(".tag");
1559 if (useTags) msg += " using_tags: Yes";
1560 else msg += " using_tags: No";
1561 Info("CheckDataType", "%s", msg.Data());
1566 isXml = slfn.Contains(".xml");
1568 // Open xml collection and check if there are tag files inside
1569 msg += " type: xml_collection;";
1570 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1572 msg += " using_tags: No (unknown)";
1573 Info("CheckDataType", "%s", msg.Data());
1576 TMap *map = coll->Next();
1578 msg += " using_tags: No (unknown)";
1579 Info("CheckDataType", "%s", msg.Data());
1582 map = (TMap*)map->GetValue("");
1584 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1585 useTags = file.Contains(".tag");
1587 if (useTags) msg += " using_tags: Yes";
1588 else msg += " using_tags: No";
1589 Info("CheckDataType", "%s", msg.Data());
1592 useTags = slfn.Contains(".tag");
1593 if (slfn.Contains(".root")) msg += " type: root file;";
1594 else msg += " type: unknown file;";
1595 if (useTags) msg += " using_tags: Yes";
1596 else msg += " using_tags: No";
1597 Info("CheckDataType", "%s", msg.Data());
1600 //______________________________________________________________________________
1601 void AliAnalysisAlien::EnablePackage(const char *package)
1603 // Enables a par file supposed to exist in the current directory.
1604 TString pkg(package);
1605 pkg.ReplaceAll(".par", "");
1607 if (gSystem->AccessPathName(pkg)) {
1608 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1611 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1612 Info("EnablePackage", "AliEn plugin will use .par packages");
1613 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1615 fPackages = new TObjArray();
1616 fPackages->SetOwner();
1618 fPackages->Add(new TObjString(pkg));
1621 //______________________________________________________________________________
1622 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1624 // Make a tree from files having the location specified in fFileForTestMode.
1625 // Inspired from JF's CreateESDChain.
1626 if (fFileForTestMode.IsNull()) {
1627 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1630 if (gSystem->AccessPathName(fFileForTestMode)) {
1631 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1636 in.open(fFileForTestMode);
1638 // Read the input list of files and add them to the chain
1640 TChain *chain = new TChain(treeName);
1644 if (line.IsNull()) continue;
1645 if (count++ == fNtestFiles) break;
1646 TString esdFile(line);
1647 TFile *file = TFile::Open(esdFile);
1649 if (!file->IsZombie()) chain->Add(esdFile);
1652 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1656 if (!chain->GetListOfFiles()->GetEntries()) {
1657 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1665 //______________________________________________________________________________
1666 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1668 // Get job status for all jobs with jobid>jobidstart.
1669 static char mstatus[20];
1675 TGridJobStatusList *list = gGrid->Ps("");
1676 if (!list) return mstatus;
1677 Int_t nentries = list->GetSize();
1678 TGridJobStatus *status;
1680 for (Int_t ijob=0; ijob<nentries; ijob++) {
1681 status = (TGridJobStatus *)list->At(ijob);
1682 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1683 if (pid<jobidstart) continue;
1684 if (pid == lastid) {
1685 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1687 switch (status->GetStatus()) {
1688 case TGridJobStatus::kWAITING:
1690 case TGridJobStatus::kRUNNING:
1692 case TGridJobStatus::kABORTED:
1693 case TGridJobStatus::kFAIL:
1694 case TGridJobStatus::kUNKNOWN:
1696 case TGridJobStatus::kDONE:
1705 //______________________________________________________________________________
1706 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1708 // Returns true if file is a collection. Functionality duplicated from
1709 // TAlien::Type() because we don't want to directly depend on TAlien.
1711 Error("IsCollection", "No connection to grid");
1714 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1715 if (!res) return kFALSE;
1716 const char* typeStr = res->GetKey(0, "type");
1717 if (!typeStr || !strlen(typeStr)) return kFALSE;
1718 if (!strcmp(typeStr, "collection")) return kTRUE;
1723 //______________________________________________________________________________
1724 Bool_t AliAnalysisAlien::IsSingleOutput() const
1726 // Check if single-ouput option is on.
1727 return (!fOutputSingle.IsNull());
1730 //______________________________________________________________________________
1731 void AliAnalysisAlien::Print(Option_t *) const
1733 // Print current plugin settings.
1734 printf("### AliEn analysis plugin current settings ###\n");
1735 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1736 if (mgr && mgr->IsProofMode()) {
1737 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1738 if (TestBit(AliAnalysisGrid::kTest))
1739 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1740 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1741 if (!fProofDataSet.IsNull())
1742 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1744 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1746 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1747 if (!fRootVersionForProof.IsNull())
1748 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1750 printf("= ROOT version requested________________________ default\n");
1751 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1752 if (!fAliRootMode.IsNull())
1753 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1755 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1756 if (fNproofWorkersPerSlave)
1757 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1758 if (TestSpecialBit(kClearPackages))
1759 printf("= ClearPackages requested...\n");
1760 if (fIncludePath.Data())
1761 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1762 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1763 if (fPackages && fPackages->GetEntries()) {
1764 TIter next(fPackages);
1767 while ((obj=next())) list += obj->GetName();
1768 printf("= Par files to be used: ________________________ %s\n", list.Data());
1770 if (TestSpecialBit(kProofConnectGrid))
1771 printf("= Requested PROOF connection to grid\n");
1774 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1775 if (fOverwriteMode) {
1776 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1777 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1779 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1780 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1781 printf("= Production mode:______________________________ %d\n", fProductionMode);
1782 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1783 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1784 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1786 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1787 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1788 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1789 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1790 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1791 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1792 if (fRunNumbers.Length())
1793 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1795 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1796 if (!fRunRange[0] && !fRunNumbers.Length()) {
1797 TIter next(fInputFiles);
1800 while ((obj=next())) list += obj->GetName();
1801 printf("= Input files to be processed: _________________ %s\n", list.Data());
1803 if (TestBit(AliAnalysisGrid::kTest))
1804 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1805 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1806 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1807 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1808 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1809 printf("=====================================================================\n");
1810 printf("= Job price: ___________________________________ %d\n", fPrice);
1811 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1812 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1813 if (fMaxInitFailed>0)
1814 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1815 if (fMasterResubmitThreshold>0)
1816 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1817 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1818 if (fNrunsPerMaster>0)
1819 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1820 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1821 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1822 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1823 if (fArguments.Length())
1824 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1825 if (fExecutableArgs.Length())
1826 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1827 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1828 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1829 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1830 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1832 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1833 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1834 if (fIncludePath.Data())
1835 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1836 if (fCloseSE.Length())
1837 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1838 if (fFriendChainName.Length())
1839 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1840 if (fPackages && fPackages->GetEntries()) {
1841 TIter next(fPackages);
1844 while ((obj=next())) list += obj->GetName();
1845 printf("= Par files to be used: ________________________ %s\n", list.Data());
1849 //______________________________________________________________________________
1850 void AliAnalysisAlien::SetDefaults()
1852 // Set default values for everything. What cannot be filled will be left empty.
1853 if (fGridJDL) delete fGridJDL;
1854 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1855 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1858 fSplitMaxInputFileNumber = 100;
1860 fMasterResubmitThreshold = 0;
1866 fNrunsPerMaster = 1;
1867 fMaxMergeFiles = 100;
1869 fExecutable = "analysis.sh";
1870 fExecutableCommand = "root -b -q";
1872 fExecutableArgs = "";
1873 fAnalysisMacro = "myAnalysis.C";
1874 fAnalysisSource = "";
1875 fAdditionalLibs = "";
1879 fAliROOTVersion = "";
1880 fUser = ""; // Your alien user name
1881 fGridWorkingDir = "";
1882 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1883 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1884 fFriendChainName = "";
1885 fGridOutputDir = "output";
1886 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1887 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1888 fInputFormat = "xml-single";
1889 fJDLName = "analysis.jdl";
1890 fJobTag = "Automatically generated analysis JDL";
1891 fMergeExcludes = "";
1894 SetCheckCopy(kTRUE);
1895 SetDefaultOutputs(kTRUE);
1899 //______________________________________________________________________________
1900 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
1902 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1903 // First check if the result is already in the output directory.
1904 if (FileExists(Form("%s/%s",aliendir,filename))) {
1905 printf("Final merged results found. Not merging again.\n");
1908 // Now check the last stage done.
1911 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1914 // Next stage of merging
1916 TString pattern = "*root_archive.zip";
1917 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1918 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1919 if (res) delete res;
1920 // Write standard output to file
1921 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1922 // Count the number of files inside
1924 ifile.open(Form("Stage_%d.xml",stage));
1925 if (!ifile.good()) {
1926 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
1931 while (!ifile.eof()) {
1933 if (line.Contains("/event")) nfiles++;
1937 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1940 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
1942 // Copy the file in the output directory
1943 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1944 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1945 // Check if this is the last stage to be done.
1946 Bool_t laststage = (nfiles<nperchunk);
1947 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1949 printf("### Submiting final merging stage %d\n", stage);
1950 TString finalJDL = jdl;
1951 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1952 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
1953 Int_t jobId = SubmitSingleJob(query);
1954 if (!jobId) return kFALSE;
1956 printf("### Submiting merging stage %d\n", stage);
1957 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
1958 Int_t jobId = SubmitSingleJob(query);
1959 if (!jobId) return kFALSE;
1964 //______________________________________________________________________________
1965 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1967 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1968 if (!gGrid) return 0;
1969 printf("=> %s ------> ",query);
1970 TGridResult *res = gGrid->Command(query);
1972 TString jobId = res->GetKey(0,"jobId");
1974 if (jobId.IsNull()) {
1975 printf("submission failed. Reason:\n");
1978 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
1981 printf(" Job id: %s\n", jobId.Data());
1985 //______________________________________________________________________________
1986 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
1988 // Merge given output files from basedir. Basedir can be an alien output directory
1989 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
1990 // files in a group (ignored for xml input). Merging can be done in stages:
1991 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
1992 // stage=1 : works with an xml of all root_archive.zip in the output directory
1993 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
1994 TString outputFile = output;
1996 TString outputChunk;
1997 TString previousChunk = "";
1998 TObjArray *listoffiles = new TObjArray();
1999 // listoffiles->SetOwner();
2000 Int_t countChunk = 0;
2001 Int_t countZero = nmaxmerge;
2002 Bool_t merged = kTRUE;
2003 Int_t index = outputFile.Index("@");
2004 if (index > 0) outputFile.Remove(index);
2005 TString inputFile = outputFile;
2006 TString sbasedir = basedir;
2007 if (sbasedir.Contains(".xml")) {
2008 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2009 nmaxmerge = 9999999;
2010 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2012 ::Error("MergeOutput", "Input XML collection empty.");
2015 // Iterate grid collection
2016 while (coll->Next()) {
2017 TString fname = gSystem->DirName(coll->GetTURL());
2020 listoffiles->Add(new TNamed(fname.Data(),""));
2023 command = Form("find %s/ *%s", basedir, inputFile.Data());
2024 printf("command: %s\n", command.Data());
2025 TGridResult *res = gGrid->Command(command);
2027 ::Error("MergeOutput","No result for the find command\n");
2033 while ((map=(TMap*)nextmap())) {
2034 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2035 if (!objs || !objs->GetString().Length()) {
2036 // Nothing found - skip this output
2041 listoffiles->Add(new TNamed(objs->GetName(),""));
2045 if (!listoffiles->GetEntries()) {
2046 ::Error("MergeOutput","No result for the find command\n");
2051 TFileMerger *fm = 0;
2052 TIter next0(listoffiles);
2053 TObjArray *listoffilestmp = new TObjArray();
2054 listoffilestmp->SetOwner();
2057 // Keep only the files at upper level
2058 Int_t countChar = 0;
2059 while ((nextfile=next0())) {
2060 snextfile = nextfile->GetName();
2061 Int_t crtCount = snextfile.CountChar('/');
2062 if (nextfile == listoffiles->First()) countChar = crtCount;
2063 if (crtCount < countChar) countChar = crtCount;
2066 while ((nextfile=next0())) {
2067 snextfile = nextfile->GetName();
2068 Int_t crtCount = snextfile.CountChar('/');
2069 if (crtCount > countChar) {
2073 listoffilestmp->Add(nextfile);
2076 listoffiles = listoffilestmp; // Now contains 'good' files
2077 listoffiles->Print();
2078 TIter next(listoffiles);
2079 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2080 outputChunk = outputFile;
2081 outputChunk.ReplaceAll(".root", "_*.root");
2082 // Check for existent temporary merge files
2083 // Check overwrite mode and remove previous partial results if needed
2084 // Preserve old merging functionality for stage 0.
2086 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2088 // Skip as many input files as in a chunk
2089 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2092 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2096 snextfile = nextfile->GetName();
2098 outputChunk = outputFile;
2099 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2101 if (gSystem->AccessPathName(outputChunk)) continue;
2102 // Merged file with chunks up to <countChunk> found
2103 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2104 previousChunk = outputChunk;
2108 countZero = nmaxmerge;
2110 while ((nextfile=next())) {
2111 snextfile = nextfile->GetName();
2112 // Loop 'find' results and get next LFN
2113 if (countZero == nmaxmerge) {
2114 // First file in chunk - create file merger and add previous chunk if any.
2115 fm = new TFileMerger(kFALSE);
2116 fm->SetFastMethod(kTRUE);
2117 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2118 outputChunk = outputFile;
2119 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2121 // If last file found, put merged results in the output file
2122 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2123 // Add file to be merged and decrement chunk counter.
2124 fm->AddFile(snextfile);
2126 if (countZero==0 || nextfile == listoffiles->Last()) {
2127 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2128 // Nothing found - skip this output
2129 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2133 fm->OutputFile(outputChunk);
2134 // Merge the outputs, then go to next chunk
2136 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2140 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2141 gSystem->Unlink(previousChunk);
2143 if (nextfile == listoffiles->Last()) break;
2145 countZero = nmaxmerge;
2146 previousChunk = outputChunk;
2153 // Merging stage different than 0.
2154 // Move to the begining of the requested chunk.
2155 fm = new TFileMerger(kFALSE);
2156 fm->SetFastMethod(kTRUE);
2157 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2159 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2160 // Nothing found - skip this output
2161 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2165 fm->OutputFile(outputFile);
2166 // Merge the outputs
2168 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2172 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2178 //______________________________________________________________________________
2179 Bool_t AliAnalysisAlien::MergeOutputs()
2181 // Merge analysis outputs existing in the AliEn space.
2182 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2183 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2185 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2189 if (!TestBit(AliAnalysisGrid::kMerge)) {
2190 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2193 if (fProductionMode) {
2194 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2197 Info("MergeOutputs", "Submitting merging JDL");
2198 if (!SubmitMerging()) return kFALSE;
2199 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2200 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2203 // Get the output path
2204 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2205 if (!DirectoryExists(fGridOutputDir)) {
2206 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2209 if (!fOutputFiles.Length()) {
2210 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2213 // Check if fast read option was requested
2214 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2215 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2216 if (fFastReadOption) {
2217 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2218 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2219 gEnv->SetValue("XNet.ConnectTimeout",50);
2220 gEnv->SetValue("XNet.RequestTimeout",50);
2221 gEnv->SetValue("XNet.MaxRedirectCount",2);
2222 gEnv->SetValue("XNet.ReconnectTimeout",50);
2223 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2225 // Make sure we change the temporary directory
2226 gSystem->Setenv("TMPDIR", gSystem->pwd());
2227 TObjArray *list = fOutputFiles.Tokenize(",");
2231 Bool_t merged = kTRUE;
2232 while((str=(TObjString*)next())) {
2233 outputFile = str->GetString();
2234 Int_t index = outputFile.Index("@");
2235 if (index > 0) outputFile.Remove(index);
2236 TString outputChunk = outputFile;
2237 outputChunk.ReplaceAll(".root", "_*.root");
2238 // Skip already merged outputs
2239 if (!gSystem->AccessPathName(outputFile)) {
2240 if (fOverwriteMode) {
2241 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2242 gSystem->Unlink(outputFile);
2243 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2244 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2245 outputChunk.Data());
2246 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2249 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2253 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2254 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2255 outputChunk.Data());
2256 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2259 if (fMergeExcludes.Length() &&
2260 fMergeExcludes.Contains(outputFile.Data())) continue;
2261 // Perform a 'find' command in the output directory, looking for registered outputs
2262 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2264 Error("MergeOutputs", "Terminate() will NOT be executed");
2267 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2268 if (fileOpened) fileOpened->Close();
2273 //______________________________________________________________________________
2274 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2276 // Use the output files connected to output containers from the analysis manager
2277 // rather than the files defined by SetOutputFiles
2278 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2279 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2280 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2283 //______________________________________________________________________________
2284 void AliAnalysisAlien::SetOutputFiles(const char *list)
2286 // Manually set the output files list.
2287 // Removes duplicates. Not allowed if default outputs are not disabled.
2288 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2289 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2292 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2294 TString slist = list;
2295 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2296 TObjArray *arr = slist.Tokenize(" ");
2300 while ((os=(TObjString*)next())) {
2301 sout = os->GetString();
2302 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2303 if (fOutputFiles.Contains(sout)) continue;
2304 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2305 fOutputFiles += sout;
2310 //______________________________________________________________________________
2311 void AliAnalysisAlien::SetOutputArchive(const char *list)
2313 // Manually set the output archive list. Free text - you are on your own...
2314 // Not allowed if default outputs are not disabled.
2315 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2316 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2319 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2320 fOutputArchive = list;
2323 //______________________________________________________________________________
2324 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2326 // Setting a prefered output SE is not allowed anymore.
2327 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2330 //______________________________________________________________________________
2331 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2333 // Start remote grid analysis.
2334 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2335 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2336 if (!mgr || !mgr->IsInitialized()) {
2337 Error("StartAnalysis", "You need an initialized analysis manager for this");
2340 // Are we in PROOF mode ?
2341 if (mgr->IsProofMode()) {
2342 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2343 if (fProofCluster.IsNull()) {
2344 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2347 if (fProofDataSet.IsNull() && !testMode) {
2348 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2351 // Set the needed environment
2352 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2353 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2354 if (fProofReset && !testMode) {
2355 if (fProofReset==1) {
2356 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2357 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2359 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2360 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2362 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2365 // Do we need to change the ROOT version ? The success of this cannot be checked.
2366 if (!fRootVersionForProof.IsNull() && !testMode) {
2367 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2368 fProofCluster.Data(), fRootVersionForProof.Data()));
2370 // Connect to PROOF and check the status
2373 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2374 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2376 if (!sworkers.IsNull())
2377 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2379 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2381 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2383 Error("StartAnalysis", "Could not start PROOF in test mode");
2388 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2391 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2392 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2393 // Is dataset existing ?
2395 TString dataset = fProofDataSet;
2396 Int_t index = dataset.Index("#");
2397 if (index>=0) dataset.Remove(index);
2398 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2399 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2402 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2404 // Is ClearPackages() needed ?
2405 if (TestSpecialBit(kClearPackages)) {
2406 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2407 gROOT->ProcessLine("gProof->ClearPackages();");
2409 // Is a given aliroot mode requested ?
2412 if (!fAliRootMode.IsNull()) {
2413 TString alirootMode = fAliRootMode;
2414 if (alirootMode == "default") alirootMode = "";
2415 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2416 optionsList.SetOwner();
2417 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2418 // Check the additional libs to be loaded
2420 Bool_t parMode = kFALSE;
2421 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2422 // Parse the extra libs for .so
2423 if (fAdditionalLibs.Length()) {
2424 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2427 while((str=(TObjString*)next())) {
2428 if (str->GetString().Contains(".so")) {
2430 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());
2433 TString stmp = str->GetName();
2434 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2435 stmp.ReplaceAll(".so","");
2436 if (!extraLibs.IsNull()) extraLibs += ":";
2440 if (str->GetString().Contains(".par")) {
2441 // The first par file found in the list will not allow any further .so
2443 if (!parLibs.IsNull()) parLibs += ":";
2444 parLibs += str->GetName();
2448 if (list) delete list;
2450 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2451 // Check extra includes
2452 if (!fIncludePath.IsNull()) {
2453 TString includePath = fIncludePath;
2454 includePath.ReplaceAll(" ",":");
2455 includePath.ReplaceAll("$ALICE_ROOT","");
2456 includePath.ReplaceAll("${ALICE_ROOT}","");
2457 includePath.ReplaceAll("-I","");
2458 includePath.Strip(TString::kTrailing, ':');
2459 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2460 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2462 // Check if connection to grid is requested
2463 if (TestSpecialBit(kProofConnectGrid))
2464 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2465 // Enable AliRoot par
2467 // Enable proof lite package
2468 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2469 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2470 TNamed *obj = (TNamed*)optionsList.At(i);
2471 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2473 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2474 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2475 Info("StartAnalysis", "AliRootProofLite enabled");
2477 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2481 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2482 fAliROOTVersion.Data(), &optionsList))) {
2483 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2487 // Enable first par files from fAdditionalLibs
2488 if (!parLibs.IsNull()) {
2489 TObjArray *list = parLibs.Tokenize(":");
2491 TObjString *package;
2492 while((package=(TObjString*)next())) {
2493 TString spkg = package->GetName();
2494 spkg.ReplaceAll(".par", "");
2495 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2496 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2497 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2498 if (gROOT->ProcessLine(enablePackage)) {
2499 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2503 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2507 if (list) delete list;
2510 if (fAdditionalLibs.Contains(".so") && !testMode) {
2511 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2512 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2516 // Enable par files if requested
2517 if (fPackages && fPackages->GetEntries()) {
2518 TIter next(fPackages);
2520 while ((package=next())) {
2521 // Skip packages already enabled
2522 if (parLibs.Contains(package->GetName())) continue;
2523 TString spkg = package->GetName();
2524 spkg.ReplaceAll(".par", "");
2525 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2526 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2527 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2528 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2532 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2537 // Do we need to load analysis source files ?
2538 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2539 if (fAnalysisSource.Length()) {
2540 TObjArray *list = fAnalysisSource.Tokenize(" ");
2543 while((str=(TObjString*)next())) {
2544 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2546 if (list) delete list;
2549 // Register dataset to proof lite.
2550 if (fFileForTestMode.IsNull()) {
2551 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2554 if (gSystem->AccessPathName(fFileForTestMode)) {
2555 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2558 TFileCollection *coll = new TFileCollection();
2559 coll->AddFromFile(fFileForTestMode);
2560 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2561 gROOT->ProcessLine("gProof->ShowDataSets()");
2566 // Check if output files have to be taken from the analysis manager
2567 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2568 // Add output files and AOD files
2569 fOutputFiles = GetListOfFiles("outaod");
2570 // Add extra files registered to the analysis manager
2571 TString extra = GetListOfFiles("ext");
2572 if (!extra.IsNull()) {
2573 extra.ReplaceAll(".root", "*.root");
2574 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2575 fOutputFiles += extra;
2577 // Compose the output archive.
2578 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2579 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2581 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2582 if (TestBit(AliAnalysisGrid::kOffline)) {
2583 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2584 \n there nor any job run. You can revise the JDL and analysis \
2585 \n macro then run the same in \"submit\" mode.");
2586 } else if (TestBit(AliAnalysisGrid::kTest)) {
2587 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2589 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2590 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2591 \n space and job submitted.");
2592 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2593 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2594 if (fMergeViaJDL) CheckInputData();
2597 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2602 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2605 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2606 if (!CheckInputData()) {
2607 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2610 if (!CreateDataset(fDataPattern)) {
2612 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2613 if (fRunNumbers.Length()) serror = "run numbers";
2614 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2615 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2616 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2619 WriteAnalysisFile();
2620 WriteAnalysisMacro();
2622 WriteValidationScript();
2624 WriteMergingMacro();
2625 WriteMergeExecutable();
2626 WriteValidationScript(kTRUE);
2628 if (!CreateJDL()) return kFALSE;
2629 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2631 // Locally testing the analysis
2632 Info("StartAnalysis", "\n_______________________________________________________________________ \
2633 \n Running analysis script in a daughter shell as on a worker node \
2634 \n_______________________________________________________________________");
2635 TObjArray *list = fOutputFiles.Tokenize(",");
2639 while((str=(TObjString*)next())) {
2640 outputFile = str->GetString();
2641 Int_t index = outputFile.Index("@");
2642 if (index > 0) outputFile.Remove(index);
2643 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2646 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2647 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2648 // gSystem->Exec("cat stdout");
2651 // Check if submitting is managed by LPM manager
2652 if (fProductionMode) {
2653 TString prodfile = fJDLName;
2654 prodfile.ReplaceAll(".jdl", ".prod");
2655 WriteProductionFile(prodfile);
2656 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2659 // Submit AliEn job(s)
2660 gGrid->Cd(fGridOutputDir);
2663 if (!fRunNumbers.Length() && !fRunRange[0]) {
2664 // Submit a given xml or a set of runs
2665 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2666 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2668 const char *cjobId = res->GetKey(0,"jobId");
2672 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2675 Info("StartAnalysis", "\n_______________________________________________________________________ \
2676 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2677 \n_______________________________________________________________________",
2678 fJDLName.Data(), cjobId);
2683 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2687 // Submit for a range of enumeration of runs.
2688 if (!Submit()) return kFALSE;
2691 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2692 \n You may exit at any time and terminate the job later using the option <terminate> \
2693 \n ##################################################################################", jobID.Data());
2694 gSystem->Exec("aliensh");
2698 //______________________________________________________________________________
2699 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2701 // Get a comma-separated list of output files of the requested type.
2702 // Type can be (case unsensitive):
2703 // aod - list of aod files (std, extensions and filters)
2704 // out - list of output files connected to containers (but not aod's or extras)
2705 // ext - list of extra files registered to the manager
2706 // ter - list of files produced in terminate
2707 static TString files;
2709 TString stype = type;
2711 TString aodfiles, extra;
2712 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2714 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2715 return files.Data();
2717 if (mgr->GetOutputEventHandler()) {
2718 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2719 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2720 if (!extraaod.IsNull()) {
2722 aodfiles += extraaod;
2725 if (stype.Contains("aod")) {
2727 if (stype == "aod") return files.Data();
2729 // Add output files that are not in the list of AOD files
2730 TString outputfiles = "";
2731 TIter next(mgr->GetOutputs());
2732 AliAnalysisDataContainer *output;
2733 const char *filename = 0;
2734 while ((output=(AliAnalysisDataContainer*)next())) {
2735 filename = output->GetFileName();
2736 if (!(strcmp(filename, "default"))) continue;
2737 if (outputfiles.Contains(filename)) continue;
2738 if (aodfiles.Contains(filename)) continue;
2739 if (!outputfiles.IsNull()) outputfiles += ",";
2740 outputfiles += filename;
2742 if (stype.Contains("out")) {
2743 if (!files.IsNull()) files += ",";
2744 files += outputfiles;
2745 if (stype == "out") return files.Data();
2747 // Add extra files registered to the analysis manager
2749 extra = mgr->GetExtraFiles();
2750 if (!extra.IsNull()) {
2752 extra.ReplaceAll(" ", ",");
2753 TObjArray *fextra = extra.Tokenize(",");
2754 TIter nextx(fextra);
2756 while ((obj=nextx())) {
2757 if (aodfiles.Contains(obj->GetName())) continue;
2758 if (outputfiles.Contains(obj->GetName())) continue;
2759 if (sextra.Contains(obj->GetName())) continue;
2760 if (!sextra.IsNull()) sextra += ",";
2761 sextra += obj->GetName();
2764 if (stype.Contains("ext")) {
2765 if (!files.IsNull()) files += ",";
2769 if (stype == "ext") return files.Data();
2771 if (!fTerminateFiles.IsNull()) {
2772 fTerminateFiles.Strip();
2773 fTerminateFiles.ReplaceAll(" ",",");
2774 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2775 TIter nextx(fextra);
2777 while ((obj=nextx())) {
2778 if (aodfiles.Contains(obj->GetName())) continue;
2779 if (outputfiles.Contains(obj->GetName())) continue;
2780 if (termfiles.Contains(obj->GetName())) continue;
2781 if (sextra.Contains(obj->GetName())) continue;
2782 if (!termfiles.IsNull()) termfiles += ",";
2783 termfiles += obj->GetName();
2787 if (stype.Contains("ter")) {
2788 if (!files.IsNull() && !termfiles.IsNull()) {
2793 return files.Data();
2796 //______________________________________________________________________________
2797 Bool_t AliAnalysisAlien::Submit()
2799 // Submit all master jobs.
2800 Int_t nmasterjobs = fInputFiles->GetEntries();
2801 Long_t tshoot = gSystem->Now();
2802 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2803 while (fNsubmitted < nmasterjobs) {
2804 Long_t now = gSystem->Now();
2805 if ((now-tshoot)>30000) {
2807 if (!SubmitNext()) return kFALSE;
2813 //______________________________________________________________________________
2814 Bool_t AliAnalysisAlien::SubmitMerging()
2816 // Submit all merging jobs.
2817 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2818 gGrid->Cd(fGridOutputDir);
2819 TString mergeJDLName = fExecutable;
2820 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2822 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
2825 Int_t ntosubmit = fInputFiles->GetEntries();
2826 for (Int_t i=0; i<ntosubmit; i++) {
2827 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2828 runOutDir.ReplaceAll(".xml", "");
2829 if (fOutputToRunNo) {
2830 // The output directory is the run number
2831 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2832 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2834 // The output directory is the master number in 3 digits format
2835 printf("### Submitting merging job for master <%03d>\n", i);
2836 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2838 // Check now the number of merging stages.
2839 TObjArray *list = fOutputFiles.Tokenize(",");
2843 while((str=(TObjString*)next())) {
2844 outputFile = str->GetString();
2845 Int_t index = outputFile.Index("@");
2846 if (index > 0) outputFile.Remove(index);
2847 if (!fMergeExcludes.Contains(outputFile)) break;
2850 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2851 if (!done && (i==ntosubmit-1)) return kFALSE;
2853 if (!ntosubmit) return kTRUE;
2854 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
2855 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
2856 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
2857 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
2858 \n ################################################################################################################");
2859 gSystem->Exec("aliensh");
2863 //______________________________________________________________________________
2864 Bool_t AliAnalysisAlien::SubmitNext()
2866 // Submit next bunch of master jobs if the queue is free. The first master job is
2867 // submitted right away, while the next will not be unless the previous was split.
2868 // The plugin will not submit new master jobs if there are more that 500 jobs in
2870 static Bool_t iscalled = kFALSE;
2871 static Int_t firstmaster = 0;
2872 static Int_t lastmaster = 0;
2873 static Int_t npermaster = 0;
2874 if (iscalled) return kTRUE;
2876 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2877 Int_t ntosubmit = 0;
2880 Int_t nmasterjobs = fInputFiles->GetEntries();
2883 if (!IsUseSubmitPolicy()) {
2885 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2886 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2887 ntosubmit = nmasterjobs;
2890 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2891 printf("=== master %d: %s\n", lastmaster, status.Data());
2892 // If last master not split, just return
2893 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2894 // No more than 100 waiting jobs
2895 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2896 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2897 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2898 if (!ntosubmit) ntosubmit = 1;
2899 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2900 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2902 for (Int_t i=0; i<ntosubmit; i++) {
2903 // Submit for a range of enumeration of runs.
2904 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2906 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2907 runOutDir.ReplaceAll(".xml", "");
2909 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2911 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2912 printf("********* %s\n",query.Data());
2913 res = gGrid->Command(query);
2915 TString cjobId1 = res->GetKey(0,"jobId");
2916 if (!cjobId1.Length()) {
2920 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2923 Info("StartAnalysis", "\n_______________________________________________________________________ \
2924 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2925 \n_______________________________________________________________________",
2926 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2929 lastmaster = cjobId1.Atoi();
2930 if (!firstmaster) firstmaster = lastmaster;
2935 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2943 //______________________________________________________________________________
2944 void AliAnalysisAlien::WriteAnalysisFile()
2946 // Write current analysis manager into the file <analysisFile>
2947 TString analysisFile = fExecutable;
2948 analysisFile.ReplaceAll(".sh", ".root");
2949 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2950 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2951 if (!mgr || !mgr->IsInitialized()) {
2952 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2955 // Check analysis type
2957 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2958 handler = (TObject*)mgr->GetInputEventHandler();
2960 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2961 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2963 TDirectory *cdir = gDirectory;
2964 TFile *file = TFile::Open(analysisFile, "RECREATE");
2966 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2967 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
2968 // Unless merging makes no sense
2969 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2972 // Enable termination for local jobs
2973 mgr->SetSkipTerminate(kFALSE);
2975 if (cdir) cdir->cd();
2976 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2978 Bool_t copy = kTRUE;
2979 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2982 TString workdir = gGrid->GetHomeDirectory();
2983 workdir += fGridWorkingDir;
2984 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2985 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2986 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2990 //______________________________________________________________________________
2991 void AliAnalysisAlien::WriteAnalysisMacro()
2993 // Write the analysis macro that will steer the analysis in grid mode.
2994 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2996 out.open(fAnalysisMacro.Data(), ios::out);
2998 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3001 Bool_t hasSTEERBase = kFALSE;
3002 Bool_t hasESD = kFALSE;
3003 Bool_t hasAOD = kFALSE;
3004 Bool_t hasANALYSIS = kFALSE;
3005 Bool_t hasANALYSISalice = kFALSE;
3006 Bool_t hasCORRFW = kFALSE;
3007 TString func = fAnalysisMacro;
3008 TString type = "ESD";
3009 TString comment = "// Analysis using ";
3010 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3011 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3015 if (type!="AOD" && fFriendChainName!="") {
3016 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3019 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3020 else comment += " data";
3021 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3022 func.ReplaceAll(".C", "");
3023 out << "void " << func.Data() << "()" << endl;
3025 out << comment.Data() << endl;
3026 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3027 out << " TStopwatch timer;" << endl;
3028 out << " timer.Start();" << endl << endl;
3029 // Change temp directory to current one
3030 out << "// Set temporary merging directory to current one" << endl;
3031 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3032 // Reset existing include path
3033 out << "// Reset existing include path and add current directory first in the search" << endl;
3034 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3035 if (!fExecutableCommand.Contains("aliroot")) {
3036 out << "// load base root libraries" << endl;
3037 out << " gSystem->Load(\"libTree\");" << endl;
3038 out << " gSystem->Load(\"libGeom\");" << endl;
3039 out << " gSystem->Load(\"libVMC\");" << endl;
3040 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3041 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3043 if (fAdditionalRootLibs.Length()) {
3044 // in principle libtree /lib geom libvmc etc. can go into this list, too
3045 out << "// Add aditional libraries" << endl;
3046 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3049 while((str=(TObjString*)next())) {
3050 if (str->GetString().Contains(".so"))
3051 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3053 if (list) delete list;
3055 out << "// Load analysis framework libraries" << endl;
3056 TString setupPar = "AliAnalysisAlien::SetupPar";
3058 if (!fExecutableCommand.Contains("aliroot")) {
3059 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3060 out << " gSystem->Load(\"libESD\");" << endl;
3061 out << " gSystem->Load(\"libAOD\");" << endl;
3063 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3064 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3065 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3067 TIter next(fPackages);
3070 while ((obj=next())) {
3071 pkgname = obj->GetName();
3072 if (pkgname == "STEERBase" ||
3073 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3074 if (pkgname == "ESD" ||
3075 pkgname == "ESD.par") hasESD = kTRUE;
3076 if (pkgname == "AOD" ||
3077 pkgname == "AOD.par") hasAOD = kTRUE;
3078 if (pkgname == "ANALYSIS" ||
3079 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3080 if (pkgname == "ANALYSISalice" ||
3081 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3082 if (pkgname == "CORRFW" ||
3083 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3085 if (hasANALYSISalice) setupPar = "SetupPar";
3086 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3087 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3088 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3089 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3090 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3091 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3092 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3093 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3094 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3095 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3096 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3097 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3098 out << "// Compile other par packages" << endl;
3100 while ((obj=next())) {
3101 pkgname = obj->GetName();
3102 if (pkgname == "STEERBase" ||
3103 pkgname == "STEERBase.par" ||
3105 pkgname == "ESD.par" ||
3107 pkgname == "AOD.par" ||
3108 pkgname == "ANALYSIS" ||
3109 pkgname == "ANALYSIS.par" ||
3110 pkgname == "ANALYSISalice" ||
3111 pkgname == "ANALYSISalice.par" ||
3112 pkgname == "CORRFW" ||
3113 pkgname == "CORRFW.par") continue;
3114 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3117 out << "// include path" << endl;
3118 // Get the include path from the interpreter and remove entries pointing to AliRoot
3119 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3120 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3121 out << " TIter nextpath(listpaths);" << endl;
3122 out << " TObjString *pname;" << endl;
3123 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3124 out << " TString current = pname->GetName();" << endl;
3125 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3126 out << " gSystem->AddIncludePath(current);" << endl;
3127 out << " }" << endl;
3128 out << " if (listpaths) delete listpaths;" << endl;
3129 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3130 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3131 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3132 if (fAdditionalLibs.Length()) {
3133 out << "// Add aditional AliRoot libraries" << endl;
3134 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3137 while((str=(TObjString*)next())) {
3138 if (str->GetString().Contains(".so"))
3139 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3140 if (str->GetString().Contains(".par"))
3141 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3143 if (list) delete list;
3146 out << "// analysis source to be compiled at runtime (if any)" << endl;
3147 if (fAnalysisSource.Length()) {
3148 TObjArray *list = fAnalysisSource.Tokenize(" ");
3151 while((str=(TObjString*)next())) {
3152 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3154 if (list) delete list;
3157 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3158 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3159 if (fFastReadOption) {
3160 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 !!! \
3161 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3162 out << "// fast xrootd reading enabled" << endl;
3163 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3164 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3165 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3166 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3167 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3168 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3170 out << "// connect to AliEn and make the chain" << endl;
3171 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3172 out << "// read the analysis manager from file" << endl;
3173 TString analysisFile = fExecutable;
3174 analysisFile.ReplaceAll(".sh", ".root");
3175 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3176 out << " if (!file) return;" << endl;
3177 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3178 out << " AliAnalysisManager *mgr = 0;" << endl;
3179 out << " TKey *key;" << endl;
3180 out << " while ((key=(TKey*)nextkey())) {" << endl;
3181 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3182 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3183 out << " };" << endl;
3184 out << " if (!mgr) {" << endl;
3185 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3186 out << " return;" << endl;
3187 out << " }" << endl << endl;
3188 out << " mgr->PrintStatus();" << endl;
3189 if (AliAnalysisManager::GetAnalysisManager()) {
3190 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3191 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3193 if (TestBit(AliAnalysisGrid::kTest))
3194 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3196 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3199 if (IsUsingTags()) {
3200 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3202 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3204 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3205 out << " timer.Stop();" << endl;
3206 out << " timer.Print();" << endl;
3207 out << "}" << endl << endl;
3208 if (IsUsingTags()) {
3209 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3211 out << "// Create a chain using tags from the xml file." << endl;
3212 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3213 out << " if (!coll) {" << endl;
3214 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3215 out << " return NULL;" << endl;
3216 out << " }" << endl;
3217 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3218 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3219 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3220 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3221 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3222 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3223 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3224 out << " // Check if the cuts configuration file was provided" << endl;
3225 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3226 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3227 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3228 out << " }" << endl;
3229 if (fFriendChainName=="") {
3230 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3232 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3233 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3234 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3236 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3237 out << " chain->ls();" << endl;
3238 out << " return chain;" << endl;
3239 out << "}" << endl << endl;
3240 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3241 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3242 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3243 msg += " AliLHCTagCuts *lhcCuts,\n";
3244 msg += " AliDetectorTagCuts *detCuts,\n";
3245 msg += " AliEventTagCuts *evCuts)";
3246 Info("WriteAnalysisMacro", "%s", msg.Data());
3249 if (!IsUsingTags() || fFriendChainName!="") {
3250 out <<"//________________________________________________________________________________" << endl;
3251 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3253 out << "// Create a chain using url's from xml file" << endl;
3254 out << " TString filename;" << endl;
3255 out << " Int_t run = 0;" << endl;
3256 out << " TString treename = type;" << endl;
3257 out << " treename.ToLower();" << endl;
3258 out << " treename += \"Tree\";" << endl;
3259 out << " printf(\"***************************************\\n\");" << endl;
3260 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3261 out << " printf(\"***************************************\\n\");" << endl;
3262 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3263 out << " if (!coll) {" << endl;
3264 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3265 out << " return NULL;" << endl;
3266 out << " }" << endl;
3267 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3268 out << " TChain *chain = new TChain(treename);" << endl;
3269 if(fFriendChainName!="") {
3270 out << " TChain *chainFriend = new TChain(treename);" << endl;
3272 out << " coll->Reset();" << endl;
3273 out << " while (coll->Next()) {" << endl;
3274 out << " filename = coll->GetTURL("");" << endl;
3275 out << " if (mgr) {" << endl;
3276 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3277 out << " if (nrun && nrun != run) {" << endl;
3278 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3279 out << " mgr->SetRunFromPath(nrun);" << endl;
3280 out << " run = nrun;" << endl;
3281 out << " }" << endl;
3282 out << " }" << endl;
3283 out << " chain->Add(filename);" << endl;
3284 if(fFriendChainName!="") {
3285 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3286 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3287 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3288 out << " chainFriend->Add(fileFriend.Data());" << endl;
3290 out << " }" << endl;
3291 out << " if (!chain->GetNtrees()) {" << endl;
3292 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3293 out << " return NULL;" << endl;
3294 out << " }" << endl;
3295 if(fFriendChainName!="") {
3296 out << " chain->AddFriend(chainFriend);" << endl;
3298 out << " return chain;" << endl;
3299 out << "}" << endl << endl;
3301 if (hasANALYSISalice) {
3302 out <<"//________________________________________________________________________________" << endl;
3303 out << "Bool_t SetupPar(const char *package) {" << endl;
3304 out << "// Compile the package and set it up." << endl;
3305 out << " TString pkgdir = package;" << endl;
3306 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3307 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3308 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3309 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3310 out << " // Check for BUILD.sh and execute" << endl;
3311 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3312 out << " printf(\"*******************************\\n\");" << endl;
3313 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3314 out << " printf(\"*******************************\\n\");" << endl;
3315 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3316 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3317 out << " gSystem->ChangeDirectory(cdir);" << endl;
3318 out << " return kFALSE;" << endl;
3319 out << " }" << endl;
3320 out << " } else {" << endl;
3321 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3322 out << " gSystem->ChangeDirectory(cdir);" << endl;
3323 out << " return kFALSE;" << endl;
3324 out << " }" << endl;
3325 out << " // Check for SETUP.C and execute" << endl;
3326 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3327 out << " printf(\"*******************************\\n\");" << endl;
3328 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3329 out << " printf(\"*******************************\\n\");" << endl;
3330 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3331 out << " } else {" << endl;
3332 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3333 out << " gSystem->ChangeDirectory(cdir);" << endl;
3334 out << " return kFALSE;" << endl;
3335 out << " }" << endl;
3336 out << " // Restore original workdir" << endl;
3337 out << " gSystem->ChangeDirectory(cdir);" << endl;
3338 out << " return kTRUE;" << endl;
3341 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3343 Bool_t copy = kTRUE;
3344 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3347 TString workdir = gGrid->GetHomeDirectory();
3348 workdir += fGridWorkingDir;
3349 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3350 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3351 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3352 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3353 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3355 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3356 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3360 //______________________________________________________________________________
3361 void AliAnalysisAlien::WriteMergingMacro()
3363 // Write a macro to merge the outputs per master job.
3364 if (!fMergeViaJDL) return;
3365 if (!fOutputFiles.Length()) {
3366 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3369 TString mergingMacro = fExecutable;
3370 mergingMacro.ReplaceAll(".sh","_merge.C");
3371 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3372 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3374 out.open(mergingMacro.Data(), ios::out);
3376 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3379 Bool_t hasSTEERBase = kFALSE;
3380 Bool_t hasESD = kFALSE;
3381 Bool_t hasAOD = kFALSE;
3382 Bool_t hasANALYSIS = kFALSE;
3383 Bool_t hasANALYSISalice = kFALSE;
3384 Bool_t hasCORRFW = kFALSE;
3385 TString func = mergingMacro;
3387 func.ReplaceAll(".C", "");
3388 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3390 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3391 out << " TStopwatch timer;" << endl;
3392 out << " timer.Start();" << endl << endl;
3393 // Reset existing include path
3394 out << "// Reset existing include path and add current directory first in the search" << endl;
3395 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3396 if (!fExecutableCommand.Contains("aliroot")) {
3397 out << "// load base root libraries" << endl;
3398 out << " gSystem->Load(\"libTree\");" << endl;
3399 out << " gSystem->Load(\"libGeom\");" << endl;
3400 out << " gSystem->Load(\"libVMC\");" << endl;
3401 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3402 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3404 if (fAdditionalRootLibs.Length()) {
3405 // in principle libtree /lib geom libvmc etc. can go into this list, too
3406 out << "// Add aditional libraries" << endl;
3407 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3410 while((str=(TObjString*)next())) {
3411 if (str->GetString().Contains(".so"))
3412 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3414 if (list) delete list;
3416 out << "// Load analysis framework libraries" << endl;
3418 if (!fExecutableCommand.Contains("aliroot")) {
3419 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3420 out << " gSystem->Load(\"libESD\");" << endl;
3421 out << " gSystem->Load(\"libAOD\");" << endl;
3423 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3424 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3425 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3427 TIter next(fPackages);
3430 TString setupPar = "AliAnalysisAlien::SetupPar";
3431 while ((obj=next())) {
3432 pkgname = obj->GetName();
3433 if (pkgname == "STEERBase" ||
3434 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3435 if (pkgname == "ESD" ||
3436 pkgname == "ESD.par") hasESD = kTRUE;
3437 if (pkgname == "AOD" ||
3438 pkgname == "AOD.par") hasAOD = kTRUE;
3439 if (pkgname == "ANALYSIS" ||
3440 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3441 if (pkgname == "ANALYSISalice" ||
3442 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3443 if (pkgname == "CORRFW" ||
3444 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3446 if (hasANALYSISalice) setupPar = "SetupPar";
3447 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3448 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3449 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3450 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3451 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3452 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3453 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3454 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3455 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3456 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3457 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3458 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3459 out << "// Compile other par packages" << endl;
3461 while ((obj=next())) {
3462 pkgname = obj->GetName();
3463 if (pkgname == "STEERBase" ||
3464 pkgname == "STEERBase.par" ||
3466 pkgname == "ESD.par" ||
3468 pkgname == "AOD.par" ||
3469 pkgname == "ANALYSIS" ||
3470 pkgname == "ANALYSIS.par" ||
3471 pkgname == "ANALYSISalice" ||
3472 pkgname == "ANALYSISalice.par" ||
3473 pkgname == "CORRFW" ||
3474 pkgname == "CORRFW.par") continue;
3475 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3478 out << "// include path" << endl;
3479 // Get the include path from the interpreter and remove entries pointing to AliRoot
3480 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3481 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3482 out << " TIter nextpath(listpaths);" << endl;
3483 out << " TObjString *pname;" << endl;
3484 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3485 out << " TString current = pname->GetName();" << endl;
3486 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3487 out << " gSystem->AddIncludePath(current);" << endl;
3488 out << " }" << endl;
3489 out << " if (listpaths) delete listpaths;" << endl;
3490 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3491 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3492 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3493 if (fAdditionalLibs.Length()) {
3494 out << "// Add aditional AliRoot libraries" << endl;
3495 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3498 while((str=(TObjString*)next())) {
3499 if (str->GetString().Contains(".so"))
3500 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3502 if (list) delete list;
3505 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3506 if (fAnalysisSource.Length()) {
3507 TObjArray *list = fAnalysisSource.Tokenize(" ");
3510 while((str=(TObjString*)next())) {
3511 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3513 if (list) delete list;
3517 if (fFastReadOption) {
3518 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 !!!");
3519 out << "// fast xrootd reading enabled" << endl;
3520 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3521 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3522 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3523 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3524 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3525 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3527 // Change temp directory to current one
3528 out << "// Set temporary merging directory to current one" << endl;
3529 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3530 out << "// Connect to AliEn" << endl;
3531 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3532 out << " TString outputDir = dir;" << endl;
3533 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3534 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3535 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3536 out << " TIter *iter = new TIter(list);" << endl;
3537 out << " TObjString *str;" << endl;
3538 out << " TString outputFile;" << endl;
3539 out << " Bool_t merged = kTRUE;" << endl;
3540 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3541 out << " outputFile = str->GetString();" << endl;
3542 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3543 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3544 out << " if (index > 0) outputFile.Remove(index);" << endl;
3545 out << " // Skip already merged outputs" << endl;
3546 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3547 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3548 out << " continue;" << endl;
3549 out << " }" << endl;
3550 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3551 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3552 out << " if (!merged) {" << endl;
3553 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3554 out << " return;" << endl;
3555 out << " }" << endl;
3556 out << " }" << endl;
3557 out << " // all outputs merged, validate" << endl;
3558 out << " ofstream out;" << endl;
3559 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3560 out << " out.close();" << endl;
3561 out << " // read the analysis manager from file" << endl;
3562 TString analysisFile = fExecutable;
3563 analysisFile.ReplaceAll(".sh", ".root");
3564 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3565 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3566 out << " if (!file) return;" << endl;
3567 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3568 out << " AliAnalysisManager *mgr = 0;" << endl;
3569 out << " TKey *key;" << endl;
3570 out << " while ((key=(TKey*)nextkey())) {" << endl;
3571 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3572 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3573 out << " };" << endl;
3574 out << " if (!mgr) {" << endl;
3575 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3576 out << " return;" << endl;
3577 out << " }" << endl << endl;
3578 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3579 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3580 out << " mgr->PrintStatus();" << endl;
3581 if (AliAnalysisManager::GetAnalysisManager()) {
3582 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3583 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3585 if (TestBit(AliAnalysisGrid::kTest))
3586 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3588 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3591 out << " TTree *tree = NULL;" << endl;
3592 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3593 out << "}" << endl << endl;
3594 if (hasANALYSISalice) {
3595 out <<"//________________________________________________________________________________" << endl;
3596 out << "Bool_t SetupPar(const char *package) {" << endl;
3597 out << "// Compile the package and set it up." << endl;
3598 out << " TString pkgdir = package;" << endl;
3599 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3600 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3601 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3602 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3603 out << " // Check for BUILD.sh and execute" << endl;
3604 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3605 out << " printf(\"*******************************\\n\");" << endl;
3606 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3607 out << " printf(\"*******************************\\n\");" << endl;
3608 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3609 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3610 out << " gSystem->ChangeDirectory(cdir);" << endl;
3611 out << " return kFALSE;" << endl;
3612 out << " }" << endl;
3613 out << " } else {" << endl;
3614 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3615 out << " gSystem->ChangeDirectory(cdir);" << endl;
3616 out << " return kFALSE;" << endl;
3617 out << " }" << endl;
3618 out << " // Check for SETUP.C and execute" << endl;
3619 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3620 out << " printf(\"*******************************\\n\");" << endl;
3621 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3622 out << " printf(\"*******************************\\n\");" << endl;
3623 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3624 out << " } else {" << endl;
3625 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3626 out << " gSystem->ChangeDirectory(cdir);" << endl;
3627 out << " return kFALSE;" << endl;
3628 out << " }" << endl;
3629 out << " // Restore original workdir" << endl;
3630 out << " gSystem->ChangeDirectory(cdir);" << endl;
3631 out << " return kTRUE;" << endl;
3635 Bool_t copy = kTRUE;
3636 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3639 TString workdir = gGrid->GetHomeDirectory();
3640 workdir += fGridWorkingDir;
3641 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3642 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3643 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3647 //______________________________________________________________________________
3648 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3650 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3651 // Note that for loading the compiled library. The current directory should have precedence in
3653 TString pkgdir = package;
3654 pkgdir.ReplaceAll(".par","");
3655 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3656 TString cdir = gSystem->WorkingDirectory();
3657 gSystem->ChangeDirectory(pkgdir);
3658 // Check for BUILD.sh and execute
3659 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3660 printf("**************************************************\n");
3661 printf("*** Building PAR archive %s\n", package);
3662 printf("**************************************************\n");
3663 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3664 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3665 gSystem->ChangeDirectory(cdir);
3669 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3670 gSystem->ChangeDirectory(cdir);
3673 // Check for SETUP.C and execute
3674 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3675 printf("**************************************************\n");
3676 printf("*** Setup PAR archive %s\n", package);
3677 printf("**************************************************\n");
3678 gROOT->Macro("PROOF-INF/SETUP.C");
3679 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3681 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3682 gSystem->ChangeDirectory(cdir);
3685 // Restore original workdir
3686 gSystem->ChangeDirectory(cdir);
3690 //______________________________________________________________________________
3691 void AliAnalysisAlien::WriteExecutable()
3693 // Generate the alien executable script.
3694 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3696 out.open(fExecutable.Data(), ios::out);
3698 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3701 out << "#!/bin/bash" << endl;
3702 // Make sure we can properly compile par files
3703 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3704 out << "echo \"=========================================\"" << endl;
3705 out << "echo \"############## PATH : ##############\"" << endl;
3706 out << "echo $PATH" << endl;
3707 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3708 out << "echo $LD_LIBRARY_PATH" << endl;
3709 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3710 out << "echo $ROOTSYS" << endl;
3711 out << "echo \"############## which root : ##############\"" << endl;
3712 out << "which root" << endl;
3713 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3714 out << "echo $ALICE_ROOT" << endl;
3715 out << "echo \"############## which aliroot : ##############\"" << endl;
3716 out << "which aliroot" << endl;
3717 out << "echo \"############## system limits : ##############\"" << endl;
3718 out << "ulimit -a" << endl;
3719 out << "echo \"############## memory : ##############\"" << endl;
3720 out << "free -m" << endl;
3721 out << "echo \"=========================================\"" << endl << endl;
3722 out << fExecutableCommand << " ";
3723 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3724 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3725 out << "echo \"############## memory after: ##############\"" << endl;
3726 out << "free -m" << endl;
3728 Bool_t copy = kTRUE;
3729 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3732 TString workdir = gGrid->GetHomeDirectory();
3733 TString bindir = Form("%s/bin", workdir.Data());
3734 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3735 workdir += fGridWorkingDir;
3736 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3737 if (FileExists(executable)) gGrid->Rm(executable);
3738 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3739 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3743 //______________________________________________________________________________
3744 void AliAnalysisAlien::WriteMergeExecutable()
3746 // Generate the alien executable script for the merging job.
3747 if (!fMergeViaJDL) return;
3748 TString mergeExec = fExecutable;
3749 mergeExec.ReplaceAll(".sh", "_merge.sh");
3750 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3752 out.open(mergeExec.Data(), ios::out);
3754 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3757 out << "#!/bin/bash" << endl;
3758 // Make sure we can properly compile par files
3759 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3760 out << "echo \"=========================================\"" << endl;
3761 out << "echo \"############## PATH : ##############\"" << endl;
3762 out << "echo $PATH" << endl;
3763 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3764 out << "echo $LD_LIBRARY_PATH" << endl;
3765 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3766 out << "echo $ROOTSYS" << endl;
3767 out << "echo \"############## which root : ##############\"" << endl;
3768 out << "which root" << endl;
3769 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3770 out << "echo $ALICE_ROOT" << endl;
3771 out << "echo \"############## which aliroot : ##############\"" << endl;
3772 out << "which aliroot" << endl;
3773 out << "echo \"############## system limits : ##############\"" << endl;
3774 out << "ulimit -a" << endl;
3775 out << "echo \"############## memory : ##############\"" << endl;
3776 out << "free -m" << endl;
3777 out << "echo \"=========================================\"" << endl << endl;
3778 TString mergeMacro = fExecutable;
3779 mergeMacro.ReplaceAll(".sh", "_merge.C");
3780 if (IsOneStageMerging())
3781 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3783 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3784 out << fExecutableCommand << " " << "$ARG" << endl;
3785 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3786 out << "echo \"############## memory after: ##############\"" << endl;
3787 out << "free -m" << endl;
3789 Bool_t copy = kTRUE;
3790 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3793 TString workdir = gGrid->GetHomeDirectory();
3794 TString bindir = Form("%s/bin", workdir.Data());
3795 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3796 workdir += fGridWorkingDir;
3797 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3798 if (FileExists(executable)) gGrid->Rm(executable);
3799 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3800 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3804 //______________________________________________________________________________
3805 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3807 // Write the production file to be submitted by LPM manager. The format is:
3808 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3809 // Next lines: full_path_to_dataset XXX (XXX is a string)
3810 // To submit, one has to: submit jdl XXX for all lines
3812 out.open(filename, ios::out);
3814 Error("WriteProductionFile", "Bad file name: %s", filename);
3818 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3819 workdir = gGrid->GetHomeDirectory();
3820 workdir += fGridWorkingDir;
3821 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3822 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3823 out << locjdl << " " << njobspermaster << endl;
3824 Int_t nmasterjobs = fInputFiles->GetEntries();
3825 for (Int_t i=0; i<nmasterjobs; i++) {
3826 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3827 runOutDir.ReplaceAll(".xml", "");
3829 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3831 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3834 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3835 if (FileExists(filename)) gGrid->Rm(filename);
3836 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3840 //______________________________________________________________________________
3841 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3843 // Generate the alien validation script.
3844 // Generate the validation script
3846 if (fValidationScript.IsNull()) {
3847 fValidationScript = fExecutable;
3848 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3850 TString validationScript = fValidationScript;
3851 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3853 Error("WriteValidationScript", "Alien connection required");
3856 if (!fTerminateFiles.IsNull()) {
3857 fTerminateFiles.Strip();
3858 fTerminateFiles.ReplaceAll(" ",",");
3860 TString outStream = "";
3861 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3862 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3864 out.open(validationScript, ios::out);
3865 out << "#!/bin/bash" << endl;
3866 out << "##################################################" << endl;
3867 out << "validateout=`dirname $0`" << endl;
3868 out << "validatetime=`date`" << endl;
3869 out << "validated=\"0\";" << endl;
3870 out << "error=0" << endl;
3871 out << "if [ -z $validateout ]" << endl;
3872 out << "then" << endl;
3873 out << " validateout=\".\"" << endl;
3874 out << "fi" << endl << endl;
3875 out << "cd $validateout;" << endl;
3876 out << "validateworkdir=`pwd`;" << endl << endl;
3877 out << "echo \"*******************************************************\"" << outStream << endl;
3878 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3880 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3881 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3882 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3883 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3884 out << "ls -la ./" << outStream << endl;
3885 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3886 out << "##################################################" << endl;
3889 out << "if [ ! -f stderr ] ; then" << endl;
3890 out << " error=1" << endl;
3891 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3892 out << " echo \"Error = $error\" " << outStream << endl;
3893 out << "fi" << endl;
3895 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3896 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3897 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3898 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3901 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3902 out << " error=1" << endl;
3903 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3904 out << " echo \"$parArch\" " << outStream << endl;
3905 out << " echo \"Error = $error\" " << outStream << endl;
3906 out << "fi" << endl;
3908 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3909 out << " error=1" << endl;
3910 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3911 out << " echo \"$segViol\" " << outStream << endl;
3912 out << " echo \"Error = $error\" " << outStream << endl;
3913 out << "fi" << endl;
3915 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3916 out << " error=1" << endl;
3917 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3918 out << " echo \"$segFault\" " << outStream << endl;
3919 out << " echo \"Error = $error\" " << outStream << endl;
3920 out << "fi" << endl;
3922 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3923 out << " error=1" << endl;
3924 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3925 out << " echo \"$glibcErr\" " << outStream << endl;
3926 out << " echo \"Error = $error\" " << outStream << endl;
3927 out << "fi" << endl;
3929 // Part dedicated to the specific analyses running into the train
3931 TString outputFiles = fOutputFiles;
3932 if (merge && !fTerminateFiles.IsNull()) {
3934 outputFiles += fTerminateFiles;
3936 TObjArray *arr = outputFiles.Tokenize(",");
3939 while (!merge && (os=(TObjString*)next1())) {
3940 // No need to validate outputs produced by merging since the merging macro does this
3941 outputFile = os->GetString();
3942 Int_t index = outputFile.Index("@");
3943 if (index > 0) outputFile.Remove(index);
3944 if (fTerminateFiles.Contains(outputFile)) continue;
3945 if (outputFile.Contains("*")) continue;
3946 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
3947 out << " error=1" << endl;
3948 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
3949 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
3950 out << "fi" << endl;
3953 out << "if ! [ -f outputs_valid ] ; then" << endl;
3954 out << " error=1" << endl;
3955 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3956 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3957 out << "fi" << endl;
3959 out << "if [ $error = 0 ] ; then" << endl;
3960 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
3961 if (!IsKeepLogs()) {
3962 out << " echo \"* === Logs std* will be deleted === \"" << endl;
3964 out << " rm -f std*" << endl;
3966 out << "fi" << endl;
3968 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3969 out << "echo \"*******************************************************\"" << outStream << endl;
3970 out << "cd -" << endl;
3971 out << "exit $error" << endl;
3973 Bool_t copy = kTRUE;
3974 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3977 TString workdir = gGrid->GetHomeDirectory();
3978 workdir += fGridWorkingDir;
3979 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
3980 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3981 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));