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::AddRunList(const char* runList)
397 // Add several runs into the list of runs; they are expected to be separated by a blank character.
398 TString sList = runList;
399 TObjArray *list = sList.Tokenize(" ");
400 Int_t n = list->GetEntries();
401 for (Int_t i = 0; i < n; i++) {
402 TObjString *os = (TObjString*)list->At(i);
403 AddRunNumber(os->GetString().Atoi());
408 //______________________________________________________________________________
409 void AliAnalysisAlien::AddRunNumber(const char* run)
411 // Add a run number to the list of runs to be processed.
412 if (fRunNumbers.Length()) fRunNumbers += " ";
416 //______________________________________________________________________________
417 void AliAnalysisAlien::AddDataFile(const char *lfn)
419 // Adds a data file to the input to be analysed. The file should be a valid LFN
420 // or point to an existing file in the alien workdir.
421 if (!fInputFiles) fInputFiles = new TObjArray();
422 fInputFiles->Add(new TObjString(lfn));
425 //______________________________________________________________________________
426 void AliAnalysisAlien::AddExternalPackage(const char *package)
428 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
429 if (fExternalPackages) fExternalPackages += " ";
430 fExternalPackages += package;
433 //______________________________________________________________________________
434 Bool_t AliAnalysisAlien::Connect()
436 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
437 if (gGrid && gGrid->IsConnected()) return kTRUE;
438 if (fProductionMode) return kTRUE;
440 Info("Connect", "Trying to connect to AliEn ...");
441 TGrid::Connect("alien://");
443 if (!gGrid || !gGrid->IsConnected()) {
444 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
447 fUser = gGrid->GetUser();
448 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
452 //______________________________________________________________________________
453 void AliAnalysisAlien::CdWork()
455 // Check validity of alien workspace. Create directory if possible.
457 Error("CdWork", "Alien connection required");
460 TString homedir = gGrid->GetHomeDirectory();
461 TString workdir = homedir + fGridWorkingDir;
462 if (DirectoryExists(workdir)) {
466 // Work directory not existing - create it
468 if (gGrid->Mkdir(workdir, "-p")) {
469 gGrid->Cd(fGridWorkingDir);
470 Info("CdWork", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
472 Warning("CdWork", "Working directory %s cannot be created.\n Using %s instead.",
473 workdir.Data(), homedir.Data());
474 fGridWorkingDir = "";
478 //______________________________________________________________________________
479 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
481 // Check if file copying is possible.
482 if (fProductionMode) return kTRUE;
484 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
487 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
488 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
489 // Check if alien_CLOSE_SE is defined
490 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
491 if (!closeSE.IsNull()) {
492 Info("CheckFileCopy", "Your current close storage is pointing to: \
493 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
495 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
497 // Check if grid directory exists.
498 if (!DirectoryExists(alienpath)) {
499 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
502 TFile f("plugin_test_copy", "RECREATE");
503 // User may not have write permissions to current directory
505 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
506 gSystem->WorkingDirectory());
510 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
511 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
512 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
513 \n# 1. Make sure you have write permissions there. If this is the case: \
514 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
515 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
516 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
517 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
518 gSystem->Unlink(f.GetName());
521 gSystem->Unlink(f.GetName());
522 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
523 Info("CheckFileCopy", "### ...SUCCESS ###");
527 //______________________________________________________________________________
528 Bool_t AliAnalysisAlien::CheckInputData()
530 // Check validity of input data. If necessary, create xml files.
531 if (fProductionMode) return kTRUE;
532 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
533 if (!fGridDataDir.Length()) {
534 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
538 Error("CheckInputData", "Merging via jdl works only with run numbers, run range or provided xml");
541 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
542 if (fDataPattern.Contains("tag") && TestBit(AliAnalysisGrid::kTest))
543 TObject::SetBit(AliAnalysisGrid::kUseTags, kTRUE); // ADDED (fix problem in determining the tag usage in test mode)
546 // Process declared files
547 Bool_t isCollection = kFALSE;
548 Bool_t isXml = kFALSE;
549 Bool_t useTags = kFALSE;
550 Bool_t checked = kFALSE;
551 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
553 TString workdir = gGrid->GetHomeDirectory();
554 workdir += fGridWorkingDir;
557 TIter next(fInputFiles);
558 while ((objstr=(TObjString*)next())) {
561 file += objstr->GetString();
562 // Store full lfn path
563 if (FileExists(file)) objstr->SetString(file);
565 file = objstr->GetName();
566 if (!FileExists(objstr->GetName())) {
567 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
568 objstr->GetName(), workdir.Data());
572 Bool_t iscoll, isxml, usetags;
573 CheckDataType(file, iscoll, isxml, usetags);
576 isCollection = iscoll;
579 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
581 if ((iscoll != isCollection) || (isxml != isXml) || (usetags != useTags)) {
582 Error("CheckInputData", "Some conflict was found in the types of inputs");
588 // Process requested run numbers
589 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
590 // Check validity of alien data directory
591 if (!fGridDataDir.Length()) {
592 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
595 if (!DirectoryExists(fGridDataDir)) {
596 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
600 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
604 if (checked && !isXml) {
605 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
608 // Check validity of run number(s)
613 TString schunk, schunk2;
617 useTags = fDataPattern.Contains("tag");
618 TObject::SetBit(AliAnalysisGrid::kUseTags, useTags);
620 if (useTags != fDataPattern.Contains("tag")) {
621 Error("CheckInputData", "Cannot mix input files using/not using tags");
624 if (fRunNumbers.Length()) {
625 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
626 arr = fRunNumbers.Tokenize(" ");
628 while ((os=(TObjString*)next())) {
629 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
630 if (!DirectoryExists(path)) {
631 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
634 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
635 TString msg = "\n##### file: ";
637 msg += " type: xml_collection;";
638 if (useTags) msg += " using_tags: Yes";
639 else msg += " using_tags: No";
640 Info("CheckDataType", "%s", msg.Data());
641 if (fNrunsPerMaster<2) {
642 AddDataFile(Form("%s.xml", os->GetString().Data()));
645 if (((nruns-1)%fNrunsPerMaster) == 0) {
646 schunk = os->GetString();
648 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
649 schunk += Form("_%s.xml", os->GetString().Data());
655 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
656 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
657 format = Form("%%s/%s ", fRunPrefix.Data());
658 path = Form(format.Data(), fGridDataDir.Data(), irun);
659 if (!DirectoryExists(path)) {
662 format = Form("%%s/%s.xml", fRunPrefix.Data());
663 path = Form(format.Data(), workdir.Data(),irun);
664 TString msg = "\n##### file: ";
666 msg += " type: xml_collection;";
667 if (useTags) msg += " using_tags: Yes";
668 else msg += " using_tags: No";
669 Info("CheckDataType", "%s", msg.Data());
670 if (fNrunsPerMaster<2) {
671 format = Form("%s.xml", fRunPrefix.Data());
672 AddDataFile(Form(format.Data(),irun));
675 if (((nruns-1)%fNrunsPerMaster) == 0) {
676 schunk = Form(fRunPrefix.Data(),irun);
678 format = Form("_%s.xml", fRunPrefix.Data());
679 schunk2 = Form(format.Data(), irun);
680 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
693 //______________________________________________________________________________
694 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
696 // Create dataset for the grid data directory + run number.
697 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
699 Error("CreateDataset", "Cannot create dataset with no grid connection");
704 if (!TestBit(AliAnalysisGrid::kTest)) CdWork();
705 TString workdir = gGrid->GetHomeDirectory();
706 workdir += fGridWorkingDir;
708 // Compose the 'find' command arguments
711 TString options = "-x collection ";
712 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
713 TString conditions = "";
718 TString schunk, schunk2;
719 TGridCollection *cbase=0, *cadd=0;
720 if (!fRunNumbers.Length() && !fRunRange[0]) {
721 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
722 // Make a single data collection from data directory.
724 if (!DirectoryExists(path)) {
725 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
729 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
730 else file = Form("%s.xml", gSystem->BaseName(path));
731 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
737 command += conditions;
738 printf("command: %s\n", command.Data());
739 TGridResult *res = gGrid->Command(command);
741 // Write standard output to file
742 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
743 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
744 Bool_t nullFile = kFALSE;
746 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
748 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
750 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
755 Bool_t fileExists = FileExists(file);
756 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
757 // Copy xml file to alien space
758 if (fileExists) gGrid->Rm(file);
759 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
760 if (!FileExists(file)) {
761 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
764 // Update list of files to be processed.
766 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
770 Bool_t nullResult = kTRUE;
771 if (fRunNumbers.Length()) {
772 TObjArray *arr = fRunNumbers.Tokenize(" ");
775 while ((os=(TObjString*)next())) {
776 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
777 if (!DirectoryExists(path)) continue;
779 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
780 else file = Form("%s.xml", os->GetString().Data());
781 // If local collection file does not exist, create it via 'find' command.
782 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
787 command += conditions;
788 TGridResult *res = gGrid->Command(command);
790 // Write standard output to file
791 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
792 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
793 Bool_t nullFile = kFALSE;
795 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
797 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
799 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
800 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
806 if (TestBit(AliAnalysisGrid::kTest)) break;
807 // Check if there is one run per master job.
808 if (fNrunsPerMaster<2) {
809 if (FileExists(file)) {
810 if (fOverwriteMode) gGrid->Rm(file);
812 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
816 // Copy xml file to alien space
817 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
818 if (!FileExists(file)) {
819 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
825 if (((nruns-1)%fNrunsPerMaster) == 0) {
826 schunk = os->GetString();
827 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
829 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
830 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
834 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
837 schunk += Form("_%s.xml", os->GetString().Data());
838 if (FileExists(schunk)) {
839 if (fOverwriteMode) gGrid->Rm(file);
841 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
845 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
846 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
847 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
848 if (!FileExists(schunk)) {
849 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
857 Error("CreateDataset", "No valid dataset corresponding to the query!");
861 // Process a full run range.
862 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
863 format = Form("%%s/%s ", fRunPrefix.Data());
864 path = Form(format.Data(), fGridDataDir.Data(), irun);
865 if (!DirectoryExists(path)) continue;
867 format = Form("%s.xml", fRunPrefix.Data());
868 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
869 else file = Form(format.Data(), irun);
870 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
871 if (fOverwriteMode) gGrid->Rm(file);
873 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
877 // If local collection file does not exist, create it via 'find' command.
878 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
883 command += conditions;
884 TGridResult *res = gGrid->Command(command);
886 // Write standard output to file
887 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
888 Bool_t hasGrep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
889 Bool_t nullFile = kFALSE;
891 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
893 nullFile = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
895 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
901 if (TestBit(AliAnalysisGrid::kTest)) break;
902 // Check if there is one run per master job.
903 if (fNrunsPerMaster<2) {
904 if (FileExists(file)) {
905 if (fOverwriteMode) gGrid->Rm(file);
907 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
911 // Copy xml file to alien space
912 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
913 if (!FileExists(file)) {
914 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
919 // Check if the collection for the chunk exist locally.
920 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
921 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
922 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
925 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
926 if (((nruns-1)%fNrunsPerMaster) == 0) {
927 schunk = Form(fRunPrefix.Data(), irun);
928 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
930 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
934 format = Form("%%s_%s.xml", fRunPrefix.Data());
935 schunk2 = Form(format.Data(), schunk.Data(), irun);
936 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
940 if (FileExists(schunk)) {
941 if (fOverwriteMode) gGrid->Rm(schunk);
943 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
947 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
948 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
949 if (FileExists(schunk)) {
950 if (fOverwriteMode) gGrid->Rm(schunk);
952 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
956 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
957 if (!FileExists(schunk)) {
958 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
964 Error("CreateDataset", "No valid dataset corresponding to the query!");
971 //______________________________________________________________________________
972 Bool_t AliAnalysisAlien::CreateJDL()
974 // Generate a JDL file according to current settings. The name of the file is
975 // specified by fJDLName.
976 Bool_t error = kFALSE;
979 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
980 Bool_t generate = kTRUE;
981 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
983 Error("CreateJDL", "Alien connection required");
986 // Check validity of alien workspace
988 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
989 if (!fProductionMode && !TestBit(AliAnalysisGrid::kTest)) CdWork();
990 workdir += fGridWorkingDir;
994 Error("CreateJDL()", "Define some input files for your analysis.");
997 // Compose list of input files
998 // Check if output files were defined
999 if (!fOutputFiles.Length()) {
1000 Error("CreateJDL", "You must define at least one output file");
1003 // Check if an output directory was defined and valid
1004 if (!fGridOutputDir.Length()) {
1005 Error("CreateJDL", "You must define AliEn output directory");
1008 if (!fProductionMode) {
1009 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1010 if (!DirectoryExists(fGridOutputDir)) {
1011 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1012 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1014 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1018 Warning("CreateJDL", "#### Output directory %s exists! If this contains old data, jobs will fail with ERROR_SV !!! ###", fGridOutputDir.Data());
1023 // Exit if any error up to now
1024 if (error) return kFALSE;
1026 if (!fUser.IsNull()) {
1027 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1028 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
1030 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
1031 TString mergeExec = fExecutable;
1032 mergeExec.ReplaceAll(".sh", "_merge.sh");
1033 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
1034 mergeExec.ReplaceAll(".sh", ".C");
1035 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
1036 if (!fArguments.IsNull())
1037 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
1038 if (IsOneStageMerging()) fMergingJDL->SetArguments(fGridOutputDir);
1040 if (fProductionMode) fMergingJDL->SetArguments("wn.xml $4"); // xml, stage
1041 else fMergingJDL->SetArguments("wn.xml $2"); // xml, stage
1044 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1045 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1046 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
1047 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
1049 if (fMaxInitFailed > 0) {
1050 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
1051 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
1053 if (fSplitMaxInputFileNumber > 0) {
1054 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
1055 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
1057 if (!IsOneStageMerging()) {
1058 fMergingJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"",fMaxMergeFiles));
1059 fMergingJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be merged in one go");
1061 if (fSplitMode.Length()) {
1062 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
1063 fGridJDL->SetDescription("Split", "We split per SE or file");
1065 fMergingJDL->SetValue("Split", "\"se\"");
1066 fMergingJDL->SetDescription("Split", "We split per SE for merging in stages");
1067 if (!fAliROOTVersion.IsNull()) {
1068 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
1069 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
1071 if (!fROOTVersion.IsNull()) {
1072 fGridJDL->AddToPackages("ROOT", fROOTVersion);
1073 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
1075 if (!fAPIVersion.IsNull()) {
1076 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
1077 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
1079 if (!fExternalPackages.IsNull()) {
1080 arr = fExternalPackages.Tokenize(" ");
1082 while ((os=(TObjString*)next())) {
1083 TString pkgname = os->GetString();
1084 Int_t index = pkgname.Index("::");
1085 TString pkgversion = pkgname(index+2, pkgname.Length());
1086 pkgname.Remove(index);
1087 fGridJDL->AddToPackages(pkgname, pkgversion);
1088 fMergingJDL->AddToPackages(pkgname, pkgversion);
1092 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1093 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1094 fMergingJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
1095 fMergingJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
1096 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
1097 TString analysisFile = fExecutable;
1098 analysisFile.ReplaceAll(".sh", ".root");
1099 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1100 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
1101 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
1102 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
1103 if (fAdditionalLibs.Length()) {
1104 arr = fAdditionalLibs.Tokenize(" ");
1106 while ((os=(TObjString*)next())) {
1107 if (os->GetString().Contains(".so")) continue;
1108 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1109 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1114 TIter next(fPackages);
1116 while ((obj=next())) {
1117 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1118 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1121 if (fOutputArchive.Length()) {
1122 arr = fOutputArchive.Tokenize(" ");
1124 Bool_t first = kTRUE;
1125 const char *comment = "Files to be archived";
1126 const char *comment1 = comment;
1127 while ((os=(TObjString*)next())) {
1128 if (!first) comment = NULL;
1129 if (!os->GetString().Contains("@") && fCloseSE.Length())
1130 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1132 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1136 // Output archive for the merging jdl
1137 TString outputArchive;
1138 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1139 outputArchive = "log_archive.zip:std*@disk=1 ";
1140 // Add normal output files, extra files + terminate files
1141 TString files = GetListOfFiles("outextter");
1142 // Do not register merge excludes
1143 if (!fMergeExcludes.IsNull()) {
1144 arr = fMergeExcludes.Tokenize(" ");
1146 while ((os=(TObjString*)next1())) {
1147 files.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1148 files.ReplaceAll(os->GetString(),"");
1152 files.ReplaceAll(".root", "*.root");
1153 outputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",files.Data(),fNreplicas);
1155 TString files = fOutputArchive;
1156 files.ReplaceAll(".root", "*.root"); // nreplicas etc should be already atttached by use
1157 outputArchive = files;
1159 arr = outputArchive.Tokenize(" ");
1163 while ((os=(TObjString*)next2())) {
1164 if (!first) comment = NULL;
1165 TString currentfile = os->GetString();
1166 if (!currentfile.Contains("@") && fCloseSE.Length())
1167 fMergingJDL->AddToOutputArchive(Form("%s@%s",currentfile.Data(), fCloseSE.Data()), comment);
1169 fMergingJDL->AddToOutputArchive(currentfile, comment);
1174 arr = fOutputFiles.Tokenize(",");
1176 Bool_t first = kTRUE;
1177 const char *comment = "Files to be saved";
1178 while ((os=(TObjString*)next())) {
1179 // Ignore ouputs in jdl that are also in outputarchive
1180 TString sout = os->GetString();
1181 sout.ReplaceAll("*", "");
1182 sout.ReplaceAll(".root", "");
1183 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1184 if (fOutputArchive.Contains(sout)) continue;
1185 if (!first) comment = NULL;
1186 if (!os->GetString().Contains("@") && fCloseSE.Length())
1187 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1189 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1191 if (fMergeExcludes.Contains(sout)) continue;
1192 if (!os->GetString().Contains("@") && fCloseSE.Length())
1193 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1195 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1198 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1199 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1200 TString validationScript = fValidationScript;
1201 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1202 validationScript.ReplaceAll(".sh", "_merge.sh");
1203 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1204 if (fMasterResubmitThreshold) {
1205 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1206 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1208 // Write a jdl with 2 input parameters: collection name and output dir name.
1211 // Copy jdl to grid workspace
1213 // Check if an output directory was defined and valid
1214 if (!fGridOutputDir.Length()) {
1215 Error("CreateJDL", "You must define AliEn output directory");
1218 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1219 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1220 if (gGrid->Mkdir(fGridOutputDir,"-p")) {
1221 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1223 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1229 if (TestBit(AliAnalysisGrid::kSubmit)) {
1230 TString mergeJDLName = fExecutable;
1231 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1232 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1233 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1234 if (fProductionMode) {
1235 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1236 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1238 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1239 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1240 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1241 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1243 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1244 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1247 if (fAdditionalLibs.Length()) {
1248 arr = fAdditionalLibs.Tokenize(" ");
1251 while ((os=(TObjString*)next())) {
1252 if (os->GetString().Contains(".so")) continue;
1253 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1254 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1255 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1260 TIter next(fPackages);
1262 while ((obj=next())) {
1263 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1264 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1265 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1272 //______________________________________________________________________________
1273 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1275 // Writes one or more JDL's corresponding to findex. If findex is negative,
1276 // all run numbers are considered in one go (jdl). For non-negative indices
1277 // they correspond to the indices in the array fInputFiles.
1278 if (!fInputFiles) return kFALSE;
1281 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice")) workdir = gGrid->GetHomeDirectory();
1282 workdir += fGridWorkingDir;
1283 TString stageName = "$2";
1284 if (fProductionMode) stageName = "$4";
1285 if (!fMergeDirName.IsNull()) {
1286 fMergingJDL->AddToInputDataCollection(Form("LF:$1/%s/Stage_%s.xml,nodownload",fMergeDirName.Data(),stageName.Data()), "Collection of files to be merged for current stage");
1287 fMergingJDL->SetOutputDirectory(Form("$1/%s/Stage_%s/#alien_counter_03i#",fMergeDirName.Data(),stageName.Data()), "Output directory");
1289 fMergingJDL->AddToInputDataCollection(Form("LF:$1/Stage_%s.xml,nodownload",stageName.Data()), "Collection of files to be merged for current stage");
1290 fMergingJDL->SetOutputDirectory(Form("$1/Stage_%s/#alien_counter_03i#",stageName.Data()), "Output directory");
1292 if (fProductionMode) {
1293 TIter next(fInputFiles);
1294 while ((os=next())) {
1295 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1297 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_04i#", fGridOutputDir.Data()));
1299 if (!fRunNumbers.Length() && !fRunRange[0]) {
1300 // One jdl with no parameters in case input data is specified by name.
1301 TIter next(fInputFiles);
1303 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetName()), "Input xml collections");
1304 if (!fOutputSingle.IsNull())
1305 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1307 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1308 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1311 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1312 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1313 if (!fOutputSingle.IsNull()) {
1314 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1315 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1317 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1322 // Generate the JDL as a string
1323 TString sjdl = fGridJDL->Generate();
1324 TString sjdl1 = fMergingJDL->Generate();
1326 if (!fMergeDirName.IsNull()) {
1327 fMergingJDL->SetOutputDirectory(Form("$1/%s",fMergeDirName.Data()), "Output directory");
1328 fMergingJDL->AddToInputSandbox(Form("LF:$1/%s/Stage_%s.xml",fMergeDirName.Data(),stageName.Data()));
1330 fMergingJDL->SetOutputDirectory("$1", "Output directory");
1331 fMergingJDL->AddToInputSandbox(Form("LF:$1/Stage_%s.xml",stageName.Data()));
1333 TString sjdl2 = fMergingJDL->Generate();
1334 Int_t index, index1;
1335 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1336 sjdl.ReplaceAll("(member", "\n (member");
1337 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1338 sjdl.ReplaceAll("{", "{\n ");
1339 sjdl.ReplaceAll("};", "\n};");
1340 sjdl.ReplaceAll("{\n \n", "{\n");
1341 sjdl.ReplaceAll("\n\n", "\n");
1342 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1343 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1344 sjdl1.ReplaceAll("(member", "\n (member");
1345 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1346 sjdl1.ReplaceAll("{", "{\n ");
1347 sjdl1.ReplaceAll("};", "\n};");
1348 sjdl1.ReplaceAll("{\n \n", "{\n");
1349 sjdl1.ReplaceAll("\n\n", "\n");
1350 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1351 sjdl2.ReplaceAll("\"LF:", "\n \"LF:");
1352 sjdl2.ReplaceAll("(member", "\n (member");
1353 sjdl2.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1354 sjdl2.ReplaceAll("{", "{\n ");
1355 sjdl2.ReplaceAll("};", "\n};");
1356 sjdl2.ReplaceAll("{\n \n", "{\n");
1357 sjdl2.ReplaceAll("\n\n", "\n");
1358 sjdl2.ReplaceAll("OutputDirectory", "OutputDir");
1359 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1360 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1361 index = sjdl.Index("JDLVariables");
1362 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1363 sjdl += "Workdirectorysize = {\"5000MB\"};";
1364 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1365 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1366 index = fJobTag.Index(":");
1367 if (index < 0) index = fJobTag.Length();
1368 TString jobTag = fJobTag;
1369 if (fProductionMode) jobTag.Insert(index,"_Stage$4");
1370 sjdl1.Prepend(Form("Jobtag = {\n \"comment:%s_Merging\"\n};\n", jobTag.Data()));
1371 if (fProductionMode) {
1372 sjdl1.Prepend("# Generated merging jdl (production mode) \
1373 \n# $1 = full alien path to output directory to be merged \
1374 \n# $2 = train number \
1375 \n# $3 = production (like LHC10b) \
1376 \n# $4 = merging stage \
1377 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1378 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1379 sjdl2.Prepend("# Generated merging jdl \
1380 \n# $1 = full alien path to output directory to be merged \
1381 \n# $2 = train number \
1382 \n# $3 = production (like LHC10b) \
1383 \n# $4 = merging stage \
1384 \n# Stage_<n>.xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1386 sjdl1.Prepend("# Generated merging jdl \
1387 \n# $1 = full alien path to output directory to be merged \
1388 \n# $2 = merging stage \
1389 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1390 sjdl2.Prepend(Form("Jobtag = {\n \"comment:%s_FinalMerging\"\n};\n", jobTag.Data()));
1391 sjdl2.Prepend("# Generated merging jdl \
1392 \n# $1 = full alien path to output directory to be merged \
1393 \n# $2 = merging stage \
1394 \n# xml made via: find <OutputDir> *Stage<n-1>/*root_archive.zip\n");
1396 index = sjdl1.Index("JDLVariables");
1397 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1398 index = sjdl2.Index("JDLVariables");
1399 if (index >= 0) sjdl2.Insert(index, "\n# JDL variables\n");
1400 sjdl1 += "Workdirectorysize = {\"5000MB\"};";
1401 sjdl2 += "Workdirectorysize = {\"5000MB\"};";
1402 index = sjdl2.Index("Split =");
1404 index1 = sjdl2.Index("\n", index);
1405 sjdl2.Remove(index, index1-index+1);
1407 index = sjdl2.Index("SplitMaxInputFileNumber");
1409 index1 = sjdl2.Index("\n", index);
1410 sjdl2.Remove(index, index1-index+1);
1412 index = sjdl2.Index("InputDataCollection");
1414 index1 = sjdl2.Index(";", index);
1415 sjdl2.Remove(index, index1-index+1);
1417 index = sjdl2.Index("InputDataListFormat");
1419 index1 = sjdl2.Index("\n", index);
1420 sjdl2.Remove(index, index1-index+1);
1422 index = sjdl2.Index("InputDataList");
1424 index1 = sjdl2.Index("\n", index);
1425 sjdl2.Remove(index, index1-index+1);
1427 sjdl2.ReplaceAll("wn.xml", Form("Stage_%s.xml",stageName.Data()));
1428 // Write jdl to file
1430 out.open(fJDLName.Data(), ios::out);
1432 Error("WriteJDL", "Bad file name: %s", fJDLName.Data());
1435 out << sjdl << endl;
1437 TString mergeJDLName = fExecutable;
1438 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1441 out1.open(mergeJDLName.Data(), ios::out);
1443 Error("WriteJDL", "Bad file name: %s", mergeJDLName.Data());
1446 out1 << sjdl1 << endl;
1449 TString finalJDL = mergeJDLName;
1450 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1451 out2.open(finalJDL.Data(), ios::out);
1453 Error("WriteJDL", "Bad file name: %s", finalJDL.Data());
1456 out2 << sjdl2 << endl;
1460 // Copy jdl to grid workspace
1462 Info("WriteJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1464 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1465 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1466 TString finalJDL = mergeJDLName;
1467 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1468 TString locjdl2 = Form("%s/%s", fGridOutputDir.Data(),finalJDL.Data());
1469 if (fProductionMode) {
1470 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1471 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1472 locjdl2 = Form("%s/%s", workdir.Data(),finalJDL.Data());
1474 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1475 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1476 if (FileExists(locjdl2)) gGrid->Rm(locjdl2);
1477 Info("WriteJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1478 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1480 Info("WriteJDL", "\n##### Copying merging JDL files <%s> to your AliEn output directory", mergeJDLName.Data());
1481 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1482 TFile::Cp(Form("file:%s",finalJDL.Data()), Form("alien://%s", locjdl2.Data()));
1488 //______________________________________________________________________________
1489 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1491 // Returns true if file exists.
1492 if (!gGrid) return kFALSE;
1494 slfn.ReplaceAll("alien://","");
1495 TGridResult *res = gGrid->Ls(slfn);
1496 if (!res) return kFALSE;
1497 TMap *map = dynamic_cast<TMap*>(res->At(0));
1502 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1503 if (!objs || !objs->GetString().Length()) {
1511 //______________________________________________________________________________
1512 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1514 // Returns true if directory exists. Can be also a path.
1515 if (!gGrid) return kFALSE;
1516 // Check if dirname is a path
1517 TString dirstripped = dirname;
1518 dirstripped = dirstripped.Strip();
1519 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1520 TString dir = gSystem->BaseName(dirstripped);
1522 TString path = gSystem->DirName(dirstripped);
1523 TGridResult *res = gGrid->Ls(path, "-F");
1524 if (!res) return kFALSE;
1528 while ((map=dynamic_cast<TMap*>(next()))) {
1529 obj = map->GetValue("name");
1531 if (dir == obj->GetName()) {
1540 //______________________________________________________________________________
1541 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &isCollection, Bool_t &isXml, Bool_t &useTags)
1543 // Check input data type.
1544 isCollection = kFALSE;
1548 Error("CheckDataType", "No connection to grid");
1551 isCollection = IsCollection(lfn);
1552 TString msg = "\n##### file: ";
1555 msg += " type: raw_collection;";
1556 // special treatment for collections
1558 // check for tag files in the collection
1559 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1561 msg += " using_tags: No (unknown)";
1562 Info("CheckDataType", "%s", msg.Data());
1565 const char* typeStr = res->GetKey(0, "origLFN");
1566 if (!typeStr || !strlen(typeStr)) {
1567 msg += " using_tags: No (unknown)";
1568 Info("CheckDataType", "%s", msg.Data());
1571 TString file = typeStr;
1572 useTags = file.Contains(".tag");
1573 if (useTags) msg += " using_tags: Yes";
1574 else msg += " using_tags: No";
1575 Info("CheckDataType", "%s", msg.Data());
1580 isXml = slfn.Contains(".xml");
1582 // Open xml collection and check if there are tag files inside
1583 msg += " type: xml_collection;";
1584 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1586 msg += " using_tags: No (unknown)";
1587 Info("CheckDataType", "%s", msg.Data());
1590 TMap *map = coll->Next();
1592 msg += " using_tags: No (unknown)";
1593 Info("CheckDataType", "%s", msg.Data());
1596 map = (TMap*)map->GetValue("");
1598 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1599 useTags = file.Contains(".tag");
1601 if (useTags) msg += " using_tags: Yes";
1602 else msg += " using_tags: No";
1603 Info("CheckDataType", "%s", msg.Data());
1606 useTags = slfn.Contains(".tag");
1607 if (slfn.Contains(".root")) msg += " type: root file;";
1608 else msg += " type: unknown file;";
1609 if (useTags) msg += " using_tags: Yes";
1610 else msg += " using_tags: No";
1611 Info("CheckDataType", "%s", msg.Data());
1614 //______________________________________________________________________________
1615 void AliAnalysisAlien::EnablePackage(const char *package)
1617 // Enables a par file supposed to exist in the current directory.
1618 TString pkg(package);
1619 pkg.ReplaceAll(".par", "");
1621 if (gSystem->AccessPathName(pkg)) {
1622 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1625 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1626 Info("EnablePackage", "AliEn plugin will use .par packages");
1627 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1629 fPackages = new TObjArray();
1630 fPackages->SetOwner();
1632 fPackages->Add(new TObjString(pkg));
1635 //______________________________________________________________________________
1636 TChain *AliAnalysisAlien::GetChainForTestMode(const char *treeName) const
1638 // Make a tree from files having the location specified in fFileForTestMode.
1639 // Inspired from JF's CreateESDChain.
1640 if (fFileForTestMode.IsNull()) {
1641 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
1644 if (gSystem->AccessPathName(fFileForTestMode)) {
1645 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
1650 in.open(fFileForTestMode);
1652 // Read the input list of files and add them to the chain
1654 TChain *chain = new TChain(treeName);
1658 if (line.IsNull()) continue;
1659 if (count++ == fNtestFiles) break;
1660 TString esdFile(line);
1661 TFile *file = TFile::Open(esdFile);
1663 if (!file->IsZombie()) chain->Add(esdFile);
1666 Error("GetChainforTestMode", "Skipping un-openable file: %s", esdFile.Data());
1670 if (!chain->GetListOfFiles()->GetEntries()) {
1671 Error("GetChainForTestMode", "No file from %s could be opened", fFileForTestMode.Data());
1679 //______________________________________________________________________________
1680 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1682 // Get job status for all jobs with jobid>jobidstart.
1683 static char mstatus[20];
1689 TGridJobStatusList *list = gGrid->Ps("");
1690 if (!list) return mstatus;
1691 Int_t nentries = list->GetSize();
1692 TGridJobStatus *status;
1694 for (Int_t ijob=0; ijob<nentries; ijob++) {
1695 status = (TGridJobStatus *)list->At(ijob);
1696 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)%p)->GetKey(\"queueId\"));", status));
1697 if (pid<jobidstart) continue;
1698 if (pid == lastid) {
1699 gROOT->ProcessLine(Form("sprintf((char*)%p,((TAlienJobStatus*)%p)->GetKey(\"status\"));",mstatus, status));
1701 switch (status->GetStatus()) {
1702 case TGridJobStatus::kWAITING:
1704 case TGridJobStatus::kRUNNING:
1706 case TGridJobStatus::kABORTED:
1707 case TGridJobStatus::kFAIL:
1708 case TGridJobStatus::kUNKNOWN:
1710 case TGridJobStatus::kDONE:
1719 //______________________________________________________________________________
1720 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1722 // Returns true if file is a collection. Functionality duplicated from
1723 // TAlien::Type() because we don't want to directly depend on TAlien.
1725 Error("IsCollection", "No connection to grid");
1728 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1729 if (!res) return kFALSE;
1730 const char* typeStr = res->GetKey(0, "type");
1731 if (!typeStr || !strlen(typeStr)) return kFALSE;
1732 if (!strcmp(typeStr, "collection")) return kTRUE;
1737 //______________________________________________________________________________
1738 Bool_t AliAnalysisAlien::IsSingleOutput() const
1740 // Check if single-ouput option is on.
1741 return (!fOutputSingle.IsNull());
1744 //______________________________________________________________________________
1745 void AliAnalysisAlien::Print(Option_t *) const
1747 // Print current plugin settings.
1748 printf("### AliEn analysis plugin current settings ###\n");
1749 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1750 if (mgr && mgr->IsProofMode()) {
1751 TString proofType = "= PLUGIN IN PROOF MODE ON CLUSTER:_________________";
1752 if (TestBit(AliAnalysisGrid::kTest))
1753 proofType = "= PLUGIN IN PROOF LITE MODE ON CLUSTER:____________";
1754 printf("%s %s\n", proofType.Data(), fProofCluster.Data());
1755 if (!fProofDataSet.IsNull())
1756 printf("= Requested data set:___________________________ %s\n", fProofDataSet.Data());
1758 printf("= Soft reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1760 printf("= Hard reset signal will be send to master______ CHANGE BEHAVIOR AFTER COMPLETION\n");
1761 if (!fRootVersionForProof.IsNull())
1762 printf("= ROOT version requested________________________ %s\n", fRootVersionForProof.Data());
1764 printf("= ROOT version requested________________________ default\n");
1765 printf("= AliRoot version requested_____________________ %s\n", fAliROOTVersion.Data());
1766 if (!fAliRootMode.IsNull())
1767 printf("= Requested AliRoot mode________________________ %s\n", fAliRootMode.Data());
1769 printf("= Number of PROOF workers limited to____________ %d\n", fNproofWorkers);
1770 if (fNproofWorkersPerSlave)
1771 printf("= Maximum number of workers per slave___________ %d\n", fNproofWorkersPerSlave);
1772 if (TestSpecialBit(kClearPackages))
1773 printf("= ClearPackages requested...\n");
1774 if (fIncludePath.Data())
1775 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1776 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1777 if (fPackages && fPackages->GetEntries()) {
1778 TIter next(fPackages);
1781 while ((obj=next())) list += obj->GetName();
1782 printf("= Par files to be used: ________________________ %s\n", list.Data());
1784 if (TestSpecialBit(kProofConnectGrid))
1785 printf("= Requested PROOF connection to grid\n");
1788 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1789 if (fOverwriteMode) {
1790 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1791 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1793 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1794 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1795 printf("= Production mode:______________________________ %d\n", fProductionMode);
1796 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1797 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1798 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1800 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1801 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1802 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1803 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1804 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1805 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1806 if (fRunNumbers.Length())
1807 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1809 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1810 if (!fRunRange[0] && !fRunNumbers.Length()) {
1811 TIter next(fInputFiles);
1814 while ((obj=next())) list += obj->GetName();
1815 printf("= Input files to be processed: _________________ %s\n", list.Data());
1817 if (TestBit(AliAnalysisGrid::kTest))
1818 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1819 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1820 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1821 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1822 printf("= List of outputs produced during Terminate: ___ %s\n", fTerminateFiles.Data());
1823 printf("=====================================================================\n");
1824 printf("= Job price: ___________________________________ %d\n", fPrice);
1825 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1826 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1827 if (fMaxInitFailed>0)
1828 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1829 if (fMasterResubmitThreshold>0)
1830 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1831 printf("= Number of replicas for the output files_______ %d\n", fNreplicas);
1832 if (fNrunsPerMaster>0)
1833 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1834 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1835 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1836 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1837 if (fArguments.Length())
1838 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1839 if (fExecutableArgs.Length())
1840 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1841 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1842 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1843 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1844 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1846 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1847 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1848 if (fIncludePath.Data())
1849 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1850 if (fCloseSE.Length())
1851 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1852 if (fFriendChainName.Length())
1853 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1854 if (fPackages && fPackages->GetEntries()) {
1855 TIter next(fPackages);
1858 while ((obj=next())) list += obj->GetName();
1859 printf("= Par files to be used: ________________________ %s\n", list.Data());
1863 //______________________________________________________________________________
1864 void AliAnalysisAlien::SetDefaults()
1866 // Set default values for everything. What cannot be filled will be left empty.
1867 if (fGridJDL) delete fGridJDL;
1868 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1869 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1872 fSplitMaxInputFileNumber = 100;
1874 fMasterResubmitThreshold = 0;
1880 fNrunsPerMaster = 1;
1881 fMaxMergeFiles = 100;
1883 fExecutable = "analysis.sh";
1884 fExecutableCommand = "root -b -q";
1886 fExecutableArgs = "";
1887 fAnalysisMacro = "myAnalysis.C";
1888 fAnalysisSource = "";
1889 fAdditionalLibs = "";
1893 fAliROOTVersion = "";
1894 fUser = ""; // Your alien user name
1895 fGridWorkingDir = "";
1896 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1897 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1898 fFriendChainName = "";
1899 fGridOutputDir = "output";
1900 fOutputArchive = "log_archive.zip:std*@disk=1 root_archive.zip:*.root@disk=2";
1901 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1902 fInputFormat = "xml-single";
1903 fJDLName = "analysis.jdl";
1904 fJobTag = "Automatically generated analysis JDL";
1905 fMergeExcludes = "";
1908 SetCheckCopy(kTRUE);
1909 SetDefaultOutputs(kTRUE);
1913 //______________________________________________________________________________
1914 Bool_t AliAnalysisAlien::CheckMergedFiles(const char *filename, const char *aliendir, Int_t nperchunk, const char *jdl)
1916 // Checks current merge stage, makes xml for the next stage, counts number of files, submits next stage.
1917 // First check if the result is already in the output directory.
1918 if (FileExists(Form("%s/%s",aliendir,filename))) {
1919 printf("Final merged results found. Not merging again.\n");
1922 // Now check the last stage done.
1925 if (!FileExists(Form("%s/Stage_%d.xml",aliendir, stage+1))) break;
1928 // Next stage of merging
1930 TString pattern = "*root_archive.zip";
1931 if (stage>1) pattern = Form("Stage_%d/*root_archive.zip", stage-1);
1932 TGridResult *res = gGrid->Command(Form("find -x Stage_%d %s %s", stage, aliendir, pattern.Data()));
1933 if (res) delete res;
1934 // Write standard output to file
1935 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", Form("Stage_%d.xml",stage)));
1936 // Count the number of files inside
1938 ifile.open(Form("Stage_%d.xml",stage));
1939 if (!ifile.good()) {
1940 ::Error("CheckMergedFiles", "Could not redirect result of the find command to file %s", Form("Stage_%d.xml",stage));
1945 while (!ifile.eof()) {
1947 if (line.Contains("/event")) nfiles++;
1951 ::Error("CheckMergedFiles", "Cannot start Stage_%d merging since Stage_%d did not produced yet output", stage, stage-1);
1954 printf("=== Stage_%d produced %d files\n", stage-1, nfiles);
1956 // Copy the file in the output directory
1957 printf("===> Copying collection %s in the output directory %s\n", Form("Stage_%d.xml",stage), aliendir);
1958 TFile::Cp(Form("Stage_%d.xml",stage), Form("alien://%s/Stage_%d.xml",aliendir,stage));
1959 // Check if this is the last stage to be done.
1960 Bool_t laststage = (nfiles<nperchunk);
1961 if (fMaxMergeStages && stage>=fMaxMergeStages) laststage = kTRUE;
1963 printf("### Submiting final merging stage %d\n", stage);
1964 TString finalJDL = jdl;
1965 finalJDL.ReplaceAll(".jdl", "_final.jdl");
1966 TString query = Form("submit %s %s %d", finalJDL.Data(), aliendir, stage);
1967 Int_t jobId = SubmitSingleJob(query);
1968 if (!jobId) return kFALSE;
1970 printf("### Submiting merging stage %d\n", stage);
1971 TString query = Form("submit %s %s %d", jdl, aliendir, stage);
1972 Int_t jobId = SubmitSingleJob(query);
1973 if (!jobId) return kFALSE;
1978 //______________________________________________________________________________
1979 Int_t AliAnalysisAlien::SubmitSingleJob(const char *query)
1981 // Submits a single job corresponding to the query and returns job id. If 0 submission failed.
1982 if (!gGrid) return 0;
1983 printf("=> %s ------> ",query);
1984 TGridResult *res = gGrid->Command(query);
1986 TString jobId = res->GetKey(0,"jobId");
1988 if (jobId.IsNull()) {
1989 printf("submission failed. Reason:\n");
1992 ::Error("SubmitSingleJob", "Your query %s could not be submitted", query);
1995 printf(" Job id: %s\n", jobId.Data());
1999 //______________________________________________________________________________
2000 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge, Int_t stage)
2002 // Merge given output files from basedir. Basedir can be an alien output directory
2003 // but also an xml file with root_archive.zip locations. The file merger will merge nmaxmerge
2004 // files in a group (ignored for xml input). Merging can be done in stages:
2005 // stage=0 : will merge all existing files in a single stage, supporting resume if run locally
2006 // stage=1 : works with an xml of all root_archive.zip in the output directory
2007 // stage>1 : works with an xml of all root_archive.zip in the Stage_<n-1> directory
2008 TString outputFile = output;
2010 TString outputChunk;
2011 TString previousChunk = "";
2012 TObjArray *listoffiles = new TObjArray();
2013 // listoffiles->SetOwner();
2014 Int_t countChunk = 0;
2015 Int_t countZero = nmaxmerge;
2016 Bool_t merged = kTRUE;
2017 Int_t index = outputFile.Index("@");
2018 if (index > 0) outputFile.Remove(index);
2019 TString inputFile = outputFile;
2020 TString sbasedir = basedir;
2021 if (sbasedir.Contains(".xml")) {
2022 // Merge files pointed by the xml - ignore nmaxmerge and set ichunk to 0
2023 nmaxmerge = 9999999;
2024 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"%s\");", basedir));
2026 ::Error("MergeOutput", "Input XML collection empty.");
2029 // Iterate grid collection
2030 while (coll->Next()) {
2031 TString fname = gSystem->DirName(coll->GetTURL());
2034 listoffiles->Add(new TNamed(fname.Data(),""));
2037 command = Form("find %s/ *%s", basedir, inputFile.Data());
2038 printf("command: %s\n", command.Data());
2039 TGridResult *res = gGrid->Command(command);
2041 ::Error("MergeOutput","No result for the find command\n");
2047 while ((map=(TMap*)nextmap())) {
2048 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
2049 if (!objs || !objs->GetString().Length()) {
2050 // Nothing found - skip this output
2055 listoffiles->Add(new TNamed(objs->GetName(),""));
2059 if (!listoffiles->GetEntries()) {
2060 ::Error("MergeOutput","No result for the find command\n");
2065 TFileMerger *fm = 0;
2066 TIter next0(listoffiles);
2067 TObjArray *listoffilestmp = new TObjArray();
2068 listoffilestmp->SetOwner();
2071 // Keep only the files at upper level
2072 Int_t countChar = 0;
2073 while ((nextfile=next0())) {
2074 snextfile = nextfile->GetName();
2075 Int_t crtCount = snextfile.CountChar('/');
2076 if (nextfile == listoffiles->First()) countChar = crtCount;
2077 if (crtCount < countChar) countChar = crtCount;
2080 while ((nextfile=next0())) {
2081 snextfile = nextfile->GetName();
2082 Int_t crtCount = snextfile.CountChar('/');
2083 if (crtCount > countChar) {
2087 listoffilestmp->Add(nextfile);
2090 listoffiles = listoffilestmp; // Now contains 'good' files
2091 listoffiles->Print();
2092 TIter next(listoffiles);
2093 // Check if there is a merge operation to resume. Works only for stage 0 or 1.
2094 outputChunk = outputFile;
2095 outputChunk.ReplaceAll(".root", "_*.root");
2096 // Check for existent temporary merge files
2097 // Check overwrite mode and remove previous partial results if needed
2098 // Preserve old merging functionality for stage 0.
2100 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2102 // Skip as many input files as in a chunk
2103 for (Int_t counter=0; counter<nmaxmerge; counter++) {
2106 ::Error("MergeOutput", "Mismatch found. Please remove partial merged files from local dir.");
2110 snextfile = nextfile->GetName();
2112 outputChunk = outputFile;
2113 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2115 if (gSystem->AccessPathName(outputChunk)) continue;
2116 // Merged file with chunks up to <countChunk> found
2117 ::Info("MergeOutput", "Resume merging of <%s> from <%s>\n", outputFile.Data(), outputChunk.Data());
2118 previousChunk = outputChunk;
2122 countZero = nmaxmerge;
2124 while ((nextfile=next())) {
2125 snextfile = nextfile->GetName();
2126 // Loop 'find' results and get next LFN
2127 if (countZero == nmaxmerge) {
2128 // First file in chunk - create file merger and add previous chunk if any.
2129 fm = new TFileMerger(kFALSE);
2130 fm->SetFastMethod(kTRUE);
2131 if (previousChunk.Length()) fm->AddFile(previousChunk.Data());
2132 outputChunk = outputFile;
2133 outputChunk.ReplaceAll(".root", Form("_%04d.root", countChunk));
2135 // If last file found, put merged results in the output file
2136 if (nextfile == listoffiles->Last()) outputChunk = outputFile;
2137 // Add file to be merged and decrement chunk counter.
2138 fm->AddFile(snextfile);
2140 if (countZero==0 || nextfile == listoffiles->Last()) {
2141 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2142 // Nothing found - skip this output
2143 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2147 fm->OutputFile(outputChunk);
2148 // Merge the outputs, then go to next chunk
2150 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2154 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputChunk.Data());
2155 gSystem->Unlink(previousChunk);
2157 if (nextfile == listoffiles->Last()) break;
2159 countZero = nmaxmerge;
2160 previousChunk = outputChunk;
2167 // Merging stage different than 0.
2168 // Move to the begining of the requested chunk.
2169 fm = new TFileMerger(kFALSE);
2170 fm->SetFastMethod(kTRUE);
2171 while ((nextfile=next())) fm->AddFile(nextfile->GetName());
2173 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
2174 // Nothing found - skip this output
2175 ::Warning("MergeOutput", "No <%s> files found.", inputFile.Data());
2179 fm->OutputFile(outputFile);
2180 // Merge the outputs
2182 ::Error("MergeOutput", "Could not merge all <%s> files", outputFile.Data());
2186 ::Info("MergeOutput", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), outputFile.Data());
2192 //______________________________________________________________________________
2193 Bool_t AliAnalysisAlien::MergeOutputs()
2195 // Merge analysis outputs existing in the AliEn space.
2196 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
2197 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2199 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
2203 if (!TestBit(AliAnalysisGrid::kMerge)) {
2204 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
2207 if (fProductionMode) {
2208 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
2211 Info("MergeOutputs", "Submitting merging JDL");
2212 if (!SubmitMerging()) return kFALSE;
2213 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
2214 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
2217 // Get the output path
2218 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2219 if (!DirectoryExists(fGridOutputDir)) {
2220 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
2223 if (!fOutputFiles.Length()) {
2224 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2227 // Check if fast read option was requested
2228 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
2229 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
2230 if (fFastReadOption) {
2231 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
2232 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2233 gEnv->SetValue("XNet.ConnectTimeout",50);
2234 gEnv->SetValue("XNet.RequestTimeout",50);
2235 gEnv->SetValue("XNet.MaxRedirectCount",2);
2236 gEnv->SetValue("XNet.ReconnectTimeout",50);
2237 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
2239 // Make sure we change the temporary directory
2240 gSystem->Setenv("TMPDIR", gSystem->pwd());
2241 TObjArray *list = fOutputFiles.Tokenize(",");
2245 Bool_t merged = kTRUE;
2246 while((str=(TObjString*)next())) {
2247 outputFile = str->GetString();
2248 Int_t index = outputFile.Index("@");
2249 if (index > 0) outputFile.Remove(index);
2250 TString outputChunk = outputFile;
2251 outputChunk.ReplaceAll(".root", "_*.root");
2252 // Skip already merged outputs
2253 if (!gSystem->AccessPathName(outputFile)) {
2254 if (fOverwriteMode) {
2255 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", outputFile.Data());
2256 gSystem->Unlink(outputFile);
2257 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2258 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2259 outputChunk.Data());
2260 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2263 Info("MergeOutputs", "Output file <%s> found. Not merging again.", outputFile.Data());
2267 if (!gSystem->Exec(Form("ls %s 2>/dev/null", outputChunk.Data()))) {
2268 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
2269 outputChunk.Data());
2270 gSystem->Exec(Form("rm -f %s", outputChunk.Data()));
2273 if (fMergeExcludes.Length() &&
2274 fMergeExcludes.Contains(outputFile.Data())) continue;
2275 // Perform a 'find' command in the output directory, looking for registered outputs
2276 merged = MergeOutput(outputFile, fGridOutputDir, fMaxMergeFiles);
2278 Error("MergeOutputs", "Terminate() will NOT be executed");
2281 TFile *fileOpened = (TFile*)gROOT->GetListOfFiles()->FindObject(outputFile);
2282 if (fileOpened) fileOpened->Close();
2287 //______________________________________________________________________________
2288 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
2290 // Use the output files connected to output containers from the analysis manager
2291 // rather than the files defined by SetOutputFiles
2292 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
2293 Info("SetDefaultOutputs", "Plugin will use the output files taken from analysis manager");
2294 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
2297 //______________________________________________________________________________
2298 void AliAnalysisAlien::SetOutputFiles(const char *list)
2300 // Manually set the output files list.
2301 // Removes duplicates. Not allowed if default outputs are not disabled.
2302 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2303 Fatal("SetOutputFiles", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set output files.");
2306 Info("SetOutputFiles", "Output file list is set manually - you are on your own.");
2308 TString slist = list;
2309 if (slist.Contains("@")) Warning("SetOutputFiles","The plugin does not allow explicit SE's. Please use: SetNumberOfReplicas() instead.");
2310 TObjArray *arr = slist.Tokenize(" ");
2314 while ((os=(TObjString*)next())) {
2315 sout = os->GetString();
2316 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
2317 if (fOutputFiles.Contains(sout)) continue;
2318 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2319 fOutputFiles += sout;
2324 //______________________________________________________________________________
2325 void AliAnalysisAlien::SetOutputArchive(const char *list)
2327 // Manually set the output archive list. Free text - you are on your own...
2328 // Not allowed if default outputs are not disabled.
2329 if (TObject::TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2330 Fatal("SetOutputArchive", "You have to explicitly call SetDefaultOutputs(kFALSE) to manually set the output archives.");
2333 Info("SetOutputArchive", "Output archive is set manually - you are on your own.");
2334 fOutputArchive = list;
2337 //______________________________________________________________________________
2338 void AliAnalysisAlien::SetPreferedSE(const char */*se*/)
2340 // Setting a prefered output SE is not allowed anymore.
2341 Warning("SetPreferedSE", "Setting a preferential SE is not allowed anymore via the plugin. Use SetNumberOfReplicas() and SetDefaultOutputs()");
2344 //______________________________________________________________________________
2345 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
2347 // Start remote grid analysis.
2348 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2349 Bool_t testMode = TestBit(AliAnalysisGrid::kTest);
2350 if (!mgr || !mgr->IsInitialized()) {
2351 Error("StartAnalysis", "You need an initialized analysis manager for this");
2354 // Are we in PROOF mode ?
2355 if (mgr->IsProofMode()) {
2356 Info("StartAnalysis", "##### Starting PROOF analysis on cluster <%s> via the plugin #####", fProofCluster.Data());
2357 if (fProofCluster.IsNull()) {
2358 Error("StartAnalysis", "You need to specify the proof cluster name via SetProofCluster");
2361 if (fProofDataSet.IsNull() && !testMode) {
2362 Error("StartAnalysis", "You need to specify a dataset using SetProofDataSet()");
2365 // Set the needed environment
2366 gEnv->SetValue("XSec.GSI.DelegProxy","2");
2367 // Do we need to reset PROOF ? The success of the Reset operation cannot be checked
2368 if (fProofReset && !testMode) {
2369 if (fProofReset==1) {
2370 Info("StartAnalysis", "Sending soft reset signal to proof cluster %s", fProofCluster.Data());
2371 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kFALSE);", fProofCluster.Data()));
2373 Info("StartAnalysis", "Sending hard reset signal to proof cluster %s", fProofCluster.Data());
2374 gROOT->ProcessLine(Form("TProof::Reset(\"%s\", kTRUE);", fProofCluster.Data()));
2376 Info("StartAnalysis", "Stopping the analysis. Please use SetProofReset(0) to resume.");
2379 // Do we need to change the ROOT version ? The success of this cannot be checked.
2380 if (!fRootVersionForProof.IsNull() && !testMode) {
2381 gROOT->ProcessLine(Form("TProof::Mgr(\"%s\")->SetROOTVersion(\"%s\");",
2382 fProofCluster.Data(), fRootVersionForProof.Data()));
2384 // Connect to PROOF and check the status
2387 if (fNproofWorkersPerSlave) sworkers = Form("workers=%dx", fNproofWorkersPerSlave);
2388 else if (fNproofWorkers) sworkers = Form("workers=%d", fNproofWorkers);
2390 if (!sworkers.IsNull())
2391 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\", \"%s\");", fProofCluster.Data(), sworkers.Data()));
2393 proof = gROOT->ProcessLine(Form("TProof::Open(\"%s\");", fProofCluster.Data()));
2395 proof = gROOT->ProcessLine("TProof::Open(\"\");");
2397 Error("StartAnalysis", "Could not start PROOF in test mode");
2402 Error("StartAnalysis", "Could not connect to PROOF cluster <%s>", fProofCluster.Data());
2405 if (fNproofWorkersPerSlave*fNproofWorkers > 0)
2406 gROOT->ProcessLine(Form("gProof->SetParallel(%d);", fNproofWorkers));
2407 // Is dataset existing ?
2409 TString dataset = fProofDataSet;
2410 Int_t index = dataset.Index("#");
2411 if (index>=0) dataset.Remove(index);
2412 // if (!gROOT->ProcessLine(Form("gProof->ExistsDataSet(\"%s\");",fProofDataSet.Data()))) {
2413 // Error("StartAnalysis", "Dataset %s not existing", fProofDataSet.Data());
2416 // Info("StartAnalysis", "Dataset %s found", dataset.Data());
2418 // Is ClearPackages() needed ?
2419 if (TestSpecialBit(kClearPackages)) {
2420 Info("StartAnalysis", "ClearPackages signal sent to PROOF. Use SetClearPackages(kFALSE) to reset this.");
2421 gROOT->ProcessLine("gProof->ClearPackages();");
2423 // Is a given aliroot mode requested ?
2426 if (!fAliRootMode.IsNull()) {
2427 TString alirootMode = fAliRootMode;
2428 if (alirootMode == "default") alirootMode = "";
2429 Info("StartAnalysis", "You are requesting AliRoot mode: %s", fAliRootMode.Data());
2430 optionsList.SetOwner();
2431 optionsList.Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
2432 // Check the additional libs to be loaded
2434 Bool_t parMode = kFALSE;
2435 if (!alirootMode.IsNull()) extraLibs = "ANALYSIS:ANALYSISalice";
2436 // Parse the extra libs for .so
2437 if (fAdditionalLibs.Length()) {
2438 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2441 while((str=(TObjString*)next())) {
2442 if (str->GetString().Contains(".so")) {
2444 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());
2447 TString stmp = str->GetName();
2448 if (stmp.BeginsWith("lib")) stmp.Remove(0,3);
2449 stmp.ReplaceAll(".so","");
2450 if (!extraLibs.IsNull()) extraLibs += ":";
2454 if (str->GetString().Contains(".par")) {
2455 // The first par file found in the list will not allow any further .so
2457 if (!parLibs.IsNull()) parLibs += ":";
2458 parLibs += str->GetName();
2462 if (list) delete list;
2464 if (!extraLibs.IsNull()) optionsList.Add(new TNamed("ALIROOT_EXTRA_LIBS",extraLibs.Data()));
2465 // Check extra includes
2466 if (!fIncludePath.IsNull()) {
2467 TString includePath = fIncludePath;
2468 includePath.ReplaceAll(" ",":");
2469 includePath.ReplaceAll("$ALICE_ROOT","");
2470 includePath.ReplaceAll("${ALICE_ROOT}","");
2471 includePath.ReplaceAll("-I","");
2472 includePath.Strip(TString::kTrailing, ':');
2473 Info("StartAnalysis", "Adding extra includes: %s",includePath.Data());
2474 optionsList.Add(new TNamed("ALIROOT_EXTRA_INCLUDES",includePath.Data()));
2476 // Check if connection to grid is requested
2477 if (TestSpecialBit(kProofConnectGrid))
2478 optionsList.Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
2479 // Enable AliRoot par
2481 // Enable proof lite package
2482 TString alirootLite = gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
2483 for (Int_t i=0; i<optionsList.GetSize(); i++) {
2484 TNamed *obj = (TNamed*)optionsList.At(i);
2485 printf("%s %s\n", obj->GetName(), obj->GetTitle());
2487 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");",alirootLite.Data()))
2488 && !gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\", (TList*)%p);",alirootLite.Data(),&optionsList))) {
2489 Info("StartAnalysis", "AliRootProofLite enabled");
2491 Error("StartAnalysis", "There was an error trying to enable package AliRootProofLite.par");
2495 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"VO_ALICE@AliRoot::%s\", (TList*)%p, kTRUE);",
2496 fAliROOTVersion.Data(), &optionsList))) {
2497 Error("StartAnalysis", "There was an error trying to enable package VO_ALICE@AliRoot::%s", fAliROOTVersion.Data());
2501 // Enable first par files from fAdditionalLibs
2502 if (!parLibs.IsNull()) {
2503 TObjArray *list = parLibs.Tokenize(":");
2505 TObjString *package;
2506 while((package=(TObjString*)next())) {
2507 TString spkg = package->GetName();
2508 spkg.ReplaceAll(".par", "");
2509 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2510 if (!gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2511 TString enablePackage = (testMode)?Form("gProof->EnablePackage(\"%s\",kFALSE);", package->GetName()):Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName());
2512 if (gROOT->ProcessLine(enablePackage)) {
2513 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2517 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2521 if (list) delete list;
2524 if (fAdditionalLibs.Contains(".so") && !testMode) {
2525 Error("StartAnalysis", "You request additional libs to be loaded but did not enabled any AliRoot mode. Please refer to: \
2526 \n http://aaf.cern.ch/node/83 and use a parameter for SetAliRootMode()");
2530 // Enable par files if requested
2531 if (fPackages && fPackages->GetEntries()) {
2532 TIter next(fPackages);
2534 while ((package=next())) {
2535 // Skip packages already enabled
2536 if (parLibs.Contains(package->GetName())) continue;
2537 TString spkg = package->GetName();
2538 spkg.ReplaceAll(".par", "");
2539 gSystem->Exec(TString::Format("rm -rf %s", spkg.Data()));
2540 if (gROOT->ProcessLine(Form("gProof->UploadPackage(\"%s\");", package->GetName()))) {
2541 if (gROOT->ProcessLine(Form("gProof->EnablePackage(\"%s\",kTRUE);", package->GetName()))) {
2542 Error("StartAnalysis", "There was an error trying to enable package %s", package->GetName());
2546 Error("StartAnalysis", "There was an error trying to upload package %s", package->GetName());
2551 // Do we need to load analysis source files ?
2552 // NOTE: don't load on client since this is anyway done by the user to attach his task.
2553 if (fAnalysisSource.Length()) {
2554 TObjArray *list = fAnalysisSource.Tokenize(" ");
2557 while((str=(TObjString*)next())) {
2558 gROOT->ProcessLine(Form("gProof->Load(\"%s+g\", kTRUE);", str->GetName()));
2560 if (list) delete list;
2563 // Register dataset to proof lite.
2564 if (fFileForTestMode.IsNull()) {
2565 Error("GetChainForTestMode", "For proof test mode please use SetFileForTestMode() pointing to a file that contains data file locations.");
2568 if (gSystem->AccessPathName(fFileForTestMode)) {
2569 Error("GetChainForTestMode", "File not found: %s", fFileForTestMode.Data());
2572 TFileCollection *coll = new TFileCollection();
2573 coll->AddFromFile(fFileForTestMode);
2574 gROOT->ProcessLine(Form("gProof->RegisterDataSet(\"test_collection\", (TFileCollection*)%p, \"OV\");", coll));
2575 gROOT->ProcessLine("gProof->ShowDataSets()");
2580 // Check if output files have to be taken from the analysis manager
2581 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
2582 // Add output files and AOD files
2583 fOutputFiles = GetListOfFiles("outaod");
2584 // Add extra files registered to the analysis manager
2585 TString extra = GetListOfFiles("ext");
2586 if (!extra.IsNull()) {
2587 extra.ReplaceAll(".root", "*.root");
2588 if (!fOutputFiles.IsNull()) fOutputFiles += ",";
2589 fOutputFiles += extra;
2591 // Compose the output archive.
2592 fOutputArchive = "log_archive.zip:std*@disk=1 ";
2593 fOutputArchive += Form("root_archive.zip:%s,*.stat@disk=%d",fOutputFiles.Data(),fNreplicas);
2595 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
2596 if (TestBit(AliAnalysisGrid::kOffline)) {
2597 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
2598 \n there nor any job run. You can revise the JDL and analysis \
2599 \n macro then run the same in \"submit\" mode.");
2600 } else if (TestBit(AliAnalysisGrid::kTest)) {
2601 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
2603 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
2604 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
2605 \n space and job submitted.");
2606 } else if (TestBit(AliAnalysisGrid::kMerge)) {
2607 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
2608 if (fMergeViaJDL) CheckInputData();
2611 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
2616 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
2619 if (IsCheckCopy() && gGrid) CheckFileCopy(gGrid->GetHomeDirectory());
2620 if (!CheckInputData()) {
2621 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
2624 if (!CreateDataset(fDataPattern)) {
2626 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
2627 if (fRunNumbers.Length()) serror = "run numbers";
2628 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
2629 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
2630 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
2633 WriteAnalysisFile();
2634 WriteAnalysisMacro();
2636 WriteValidationScript();
2638 WriteMergingMacro();
2639 WriteMergeExecutable();
2640 WriteValidationScript(kTRUE);
2642 if (!CreateJDL()) return kFALSE;
2643 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
2645 // Locally testing the analysis
2646 Info("StartAnalysis", "\n_______________________________________________________________________ \
2647 \n Running analysis script in a daughter shell as on a worker node \
2648 \n_______________________________________________________________________");
2649 TObjArray *list = fOutputFiles.Tokenize(",");
2653 while((str=(TObjString*)next())) {
2654 outputFile = str->GetString();
2655 Int_t index = outputFile.Index("@");
2656 if (index > 0) outputFile.Remove(index);
2657 if (!gSystem->AccessPathName(outputFile)) gSystem->Exec(Form("rm %s", outputFile.Data()));
2660 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
2661 gSystem->Exec(Form("bash %s",fValidationScript.Data()));
2662 // gSystem->Exec("cat stdout");
2665 // Check if submitting is managed by LPM manager
2666 if (fProductionMode) {
2667 TString prodfile = fJDLName;
2668 prodfile.ReplaceAll(".jdl", ".prod");
2669 WriteProductionFile(prodfile);
2670 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
2673 // Submit AliEn job(s)
2674 gGrid->Cd(fGridOutputDir);
2677 if (!fRunNumbers.Length() && !fRunRange[0]) {
2678 // Submit a given xml or a set of runs
2679 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
2680 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
2682 const char *cjobId = res->GetKey(0,"jobId");
2686 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
2689 Info("StartAnalysis", "\n_______________________________________________________________________ \
2690 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2691 \n_______________________________________________________________________",
2692 fJDLName.Data(), cjobId);
2697 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2701 // Submit for a range of enumeration of runs.
2702 if (!Submit()) return kFALSE;
2705 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
2706 \n You may exit at any time and terminate the job later using the option <terminate> \
2707 \n ##################################################################################", jobID.Data());
2708 gSystem->Exec("aliensh");
2712 //______________________________________________________________________________
2713 const char *AliAnalysisAlien::GetListOfFiles(const char *type)
2715 // Get a comma-separated list of output files of the requested type.
2716 // Type can be (case unsensitive):
2717 // aod - list of aod files (std, extensions and filters)
2718 // out - list of output files connected to containers (but not aod's or extras)
2719 // ext - list of extra files registered to the manager
2720 // ter - list of files produced in terminate
2721 static TString files;
2723 TString stype = type;
2725 TString aodfiles, extra;
2726 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2728 ::Error("GetListOfFiles", "Cannot call this without analysis manager");
2729 return files.Data();
2731 if (mgr->GetOutputEventHandler()) {
2732 aodfiles = mgr->GetOutputEventHandler()->GetOutputFileName();
2733 TString extraaod = mgr->GetOutputEventHandler()->GetExtraOutputs();
2734 if (!extraaod.IsNull()) {
2736 aodfiles += extraaod;
2739 if (stype.Contains("aod")) {
2741 if (stype == "aod") return files.Data();
2743 // Add output files that are not in the list of AOD files
2744 TString outputfiles = "";
2745 TIter next(mgr->GetOutputs());
2746 AliAnalysisDataContainer *output;
2747 const char *filename = 0;
2748 while ((output=(AliAnalysisDataContainer*)next())) {
2749 filename = output->GetFileName();
2750 if (!(strcmp(filename, "default"))) continue;
2751 if (outputfiles.Contains(filename)) continue;
2752 if (aodfiles.Contains(filename)) continue;
2753 if (!outputfiles.IsNull()) outputfiles += ",";
2754 outputfiles += filename;
2756 if (stype.Contains("out")) {
2757 if (!files.IsNull()) files += ",";
2758 files += outputfiles;
2759 if (stype == "out") return files.Data();
2761 // Add extra files registered to the analysis manager
2763 extra = mgr->GetExtraFiles();
2764 if (!extra.IsNull()) {
2766 extra.ReplaceAll(" ", ",");
2767 TObjArray *fextra = extra.Tokenize(",");
2768 TIter nextx(fextra);
2770 while ((obj=nextx())) {
2771 if (aodfiles.Contains(obj->GetName())) continue;
2772 if (outputfiles.Contains(obj->GetName())) continue;
2773 if (sextra.Contains(obj->GetName())) continue;
2774 if (!sextra.IsNull()) sextra += ",";
2775 sextra += obj->GetName();
2778 if (stype.Contains("ext")) {
2779 if (!files.IsNull()) files += ",";
2783 if (stype == "ext") return files.Data();
2785 if (!fTerminateFiles.IsNull()) {
2786 fTerminateFiles.Strip();
2787 fTerminateFiles.ReplaceAll(" ",",");
2788 TObjArray *fextra = fTerminateFiles.Tokenize(",");
2789 TIter nextx(fextra);
2791 while ((obj=nextx())) {
2792 if (aodfiles.Contains(obj->GetName())) continue;
2793 if (outputfiles.Contains(obj->GetName())) continue;
2794 if (termfiles.Contains(obj->GetName())) continue;
2795 if (sextra.Contains(obj->GetName())) continue;
2796 if (!termfiles.IsNull()) termfiles += ",";
2797 termfiles += obj->GetName();
2801 if (stype.Contains("ter")) {
2802 if (!files.IsNull() && !termfiles.IsNull()) {
2807 return files.Data();
2810 //______________________________________________________________________________
2811 Bool_t AliAnalysisAlien::Submit()
2813 // Submit all master jobs.
2814 Int_t nmasterjobs = fInputFiles->GetEntries();
2815 Long_t tshoot = gSystem->Now();
2816 if (!fNsubmitted && !SubmitNext()) return kFALSE;
2817 while (fNsubmitted < nmasterjobs) {
2818 Long_t now = gSystem->Now();
2819 if ((now-tshoot)>30000) {
2821 if (!SubmitNext()) return kFALSE;
2827 //______________________________________________________________________________
2828 Bool_t AliAnalysisAlien::SubmitMerging()
2830 // Submit all merging jobs.
2831 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2832 gGrid->Cd(fGridOutputDir);
2833 TString mergeJDLName = fExecutable;
2834 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
2836 Error("SubmitMerging", "You have to use explicit run numbers or run range to merge via JDL!");
2839 Int_t ntosubmit = fInputFiles->GetEntries();
2840 for (Int_t i=0; i<ntosubmit; i++) {
2841 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2842 runOutDir.ReplaceAll(".xml", "");
2843 if (fOutputToRunNo) {
2844 // The output directory is the run number
2845 printf("### Submitting merging job for run <%s>\n", runOutDir.Data());
2846 runOutDir = Form("%s/%s", fGridOutputDir.Data(), runOutDir.Data());
2848 // The output directory is the master number in 3 digits format
2849 printf("### Submitting merging job for master <%03d>\n", i);
2850 runOutDir = Form("%s/%03d",fGridOutputDir.Data(), i);
2852 // Check now the number of merging stages.
2853 TObjArray *list = fOutputFiles.Tokenize(",");
2857 while((str=(TObjString*)next())) {
2858 outputFile = str->GetString();
2859 Int_t index = outputFile.Index("@");
2860 if (index > 0) outputFile.Remove(index);
2861 if (!fMergeExcludes.Contains(outputFile)) break;
2864 Bool_t done = CheckMergedFiles(outputFile, runOutDir, fMaxMergeFiles, mergeJDLName);
2865 if (!done && (i==ntosubmit-1)) return kFALSE;
2867 if (!ntosubmit) return kTRUE;
2868 Info("StartAnalysis", "\n #### STARTING AN ALIEN SHELL FOR YOU. You can exit any time or inspect your jobs in a different shell.##########\
2869 \n Make sure your jobs are in a final state (you can resubmit failed ones via 'masterjob <id> resubmit ERROR_ALL')\
2870 \n Rerun in 'terminate' mode to submit all merging stages, each AFTER the previous one completed. The final merged \
2871 \n output will be written to your alien output directory, while separate stages in <Stage_n>. \
2872 \n ################################################################################################################");
2873 gSystem->Exec("aliensh");
2877 //______________________________________________________________________________
2878 Bool_t AliAnalysisAlien::SubmitNext()
2880 // Submit next bunch of master jobs if the queue is free. The first master job is
2881 // submitted right away, while the next will not be unless the previous was split.
2882 // The plugin will not submit new master jobs if there are more that 500 jobs in
2884 static Bool_t iscalled = kFALSE;
2885 static Int_t firstmaster = 0;
2886 static Int_t lastmaster = 0;
2887 static Int_t npermaster = 0;
2888 if (iscalled) return kTRUE;
2890 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2891 Int_t ntosubmit = 0;
2894 Int_t nmasterjobs = fInputFiles->GetEntries();
2897 if (!IsUseSubmitPolicy()) {
2899 Info("SubmitNext","### Warning submit policy not used ! Submitting too many jobs at a time may be prohibitted. \
2900 \n### You can use SetUseSubmitPolicy() to enable if you have problems.");
2901 ntosubmit = nmasterjobs;
2904 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2905 printf("=== master %d: %s\n", lastmaster, status.Data());
2906 // If last master not split, just return
2907 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2908 // No more than 100 waiting jobs
2909 if (nwaiting>500) {iscalled = kFALSE; return kTRUE;}
2910 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2911 if (npermaster) ntosubmit = (500-nwaiting)/npermaster;
2912 if (!ntosubmit) ntosubmit = 1;
2913 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2914 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2916 for (Int_t i=0; i<ntosubmit; i++) {
2917 // Submit for a range of enumeration of runs.
2918 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2920 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2921 runOutDir.ReplaceAll(".xml", "");
2923 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2925 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2926 printf("********* %s\n",query.Data());
2927 res = gGrid->Command(query);
2929 TString cjobId1 = res->GetKey(0,"jobId");
2930 if (!cjobId1.Length()) {
2934 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2937 Info("StartAnalysis", "\n_______________________________________________________________________ \
2938 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2939 \n_______________________________________________________________________",
2940 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2943 lastmaster = cjobId1.Atoi();
2944 if (!firstmaster) firstmaster = lastmaster;
2949 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2957 //______________________________________________________________________________
2958 void AliAnalysisAlien::WriteAnalysisFile()
2960 // Write current analysis manager into the file <analysisFile>
2961 TString analysisFile = fExecutable;
2962 analysisFile.ReplaceAll(".sh", ".root");
2963 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2964 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2965 if (!mgr || !mgr->IsInitialized()) {
2966 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2969 // Check analysis type
2971 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2972 handler = (TObject*)mgr->GetInputEventHandler();
2974 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2975 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2977 TDirectory *cdir = gDirectory;
2978 TFile *file = TFile::Open(analysisFile, "RECREATE");
2980 // Skip task Terminate calls for the grid job (but not in test mode, where we want to check also the terminate mode
2981 if (!TestBit(AliAnalysisGrid::kTest)) mgr->SetSkipTerminate(kTRUE);
2982 // Unless merging makes no sense
2983 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2986 // Enable termination for local jobs
2987 mgr->SetSkipTerminate(kFALSE);
2989 if (cdir) cdir->cd();
2990 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2992 Bool_t copy = kTRUE;
2993 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2996 TString workdir = gGrid->GetHomeDirectory();
2997 workdir += fGridWorkingDir;
2998 Info("WriteAnalysisFile", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2999 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
3000 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
3004 //______________________________________________________________________________
3005 void AliAnalysisAlien::WriteAnalysisMacro()
3007 // Write the analysis macro that will steer the analysis in grid mode.
3008 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3010 out.open(fAnalysisMacro.Data(), ios::out);
3012 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3015 Bool_t hasSTEERBase = kFALSE;
3016 Bool_t hasESD = kFALSE;
3017 Bool_t hasAOD = kFALSE;
3018 Bool_t hasANALYSIS = kFALSE;
3019 Bool_t hasANALYSISalice = kFALSE;
3020 Bool_t hasCORRFW = kFALSE;
3021 TString func = fAnalysisMacro;
3022 TString type = "ESD";
3023 TString comment = "// Analysis using ";
3024 if (IsUseMCchain()) {
3028 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
3029 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
3034 if (type!="AOD" && fFriendChainName!="") {
3035 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
3038 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
3039 else comment += " data";
3040 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
3041 func.ReplaceAll(".C", "");
3042 out << "void " << func.Data() << "()" << endl;
3044 out << comment.Data() << endl;
3045 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
3046 out << " TStopwatch timer;" << endl;
3047 out << " timer.Start();" << endl << endl;
3048 // Change temp directory to current one
3049 out << "// Set temporary merging directory to current one" << endl;
3050 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3051 // Reset existing include path
3052 out << "// Reset existing include path and add current directory first in the search" << endl;
3053 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3054 if (!fExecutableCommand.Contains("aliroot")) {
3055 out << "// load base root libraries" << endl;
3056 out << " gSystem->Load(\"libTree\");" << endl;
3057 out << " gSystem->Load(\"libGeom\");" << endl;
3058 out << " gSystem->Load(\"libVMC\");" << endl;
3059 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3060 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3062 if (fAdditionalRootLibs.Length()) {
3063 // in principle libtree /lib geom libvmc etc. can go into this list, too
3064 out << "// Add aditional libraries" << endl;
3065 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3068 while((str=(TObjString*)next())) {
3069 if (str->GetString().Contains(".so"))
3070 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3072 if (list) delete list;
3074 out << "// Load analysis framework libraries" << endl;
3075 TString setupPar = "AliAnalysisAlien::SetupPar";
3077 if (!fExecutableCommand.Contains("aliroot")) {
3078 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3079 out << " gSystem->Load(\"libESD\");" << endl;
3080 out << " gSystem->Load(\"libAOD\");" << endl;
3082 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3083 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3084 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3086 TIter next(fPackages);
3089 while ((obj=next())) {
3090 pkgname = obj->GetName();
3091 if (pkgname == "STEERBase" ||
3092 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3093 if (pkgname == "ESD" ||
3094 pkgname == "ESD.par") hasESD = kTRUE;
3095 if (pkgname == "AOD" ||
3096 pkgname == "AOD.par") hasAOD = kTRUE;
3097 if (pkgname == "ANALYSIS" ||
3098 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3099 if (pkgname == "ANALYSISalice" ||
3100 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3101 if (pkgname == "CORRFW" ||
3102 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3104 if (hasANALYSISalice) setupPar = "SetupPar";
3105 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3106 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3107 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3108 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3109 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3110 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3111 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3112 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3113 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3114 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3115 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3116 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3117 out << "// Compile other par packages" << endl;
3119 while ((obj=next())) {
3120 pkgname = obj->GetName();
3121 if (pkgname == "STEERBase" ||
3122 pkgname == "STEERBase.par" ||
3124 pkgname == "ESD.par" ||
3126 pkgname == "AOD.par" ||
3127 pkgname == "ANALYSIS" ||
3128 pkgname == "ANALYSIS.par" ||
3129 pkgname == "ANALYSISalice" ||
3130 pkgname == "ANALYSISalice.par" ||
3131 pkgname == "CORRFW" ||
3132 pkgname == "CORRFW.par") continue;
3133 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3136 out << "// include path" << endl;
3137 // Get the include path from the interpreter and remove entries pointing to AliRoot
3138 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3139 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3140 out << " TIter nextpath(listpaths);" << endl;
3141 out << " TObjString *pname;" << endl;
3142 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3143 out << " TString current = pname->GetName();" << endl;
3144 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3145 out << " gSystem->AddIncludePath(current);" << endl;
3146 out << " }" << endl;
3147 out << " if (listpaths) delete listpaths;" << endl;
3148 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3149 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3150 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3151 if (fAdditionalLibs.Length()) {
3152 out << "// Add aditional AliRoot libraries" << endl;
3153 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3156 while((str=(TObjString*)next())) {
3157 if (str->GetString().Contains(".so"))
3158 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3159 if (str->GetString().Contains(".par"))
3160 out << " if (!" << setupPar << "(\"" << str->GetString() << "\")) return;" << endl;
3162 if (list) delete list;
3165 out << "// analysis source to be compiled at runtime (if any)" << endl;
3166 if (fAnalysisSource.Length()) {
3167 TObjArray *list = fAnalysisSource.Tokenize(" ");
3170 while((str=(TObjString*)next())) {
3171 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3173 if (list) delete list;
3176 // out << " printf(\"Currently load libraries:\\n\");" << endl;
3177 // out << " printf(\"%s\\n\", gSystem->GetLibraries());" << endl;
3178 if (fFastReadOption) {
3179 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 !!! \
3180 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
3181 out << "// fast xrootd reading enabled" << endl;
3182 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3183 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3184 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3185 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3186 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3187 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3189 out << "// connect to AliEn and make the chain" << endl;
3190 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3191 out << "// read the analysis manager from file" << endl;
3192 TString analysisFile = fExecutable;
3193 analysisFile.ReplaceAll(".sh", ".root");
3194 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3195 out << " if (!file) return;" << endl;
3196 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3197 out << " AliAnalysisManager *mgr = 0;" << endl;
3198 out << " TKey *key;" << endl;
3199 out << " while ((key=(TKey*)nextkey())) {" << endl;
3200 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3201 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3202 out << " };" << endl;
3203 out << " if (!mgr) {" << endl;
3204 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file " << analysisFile <<"\");" << endl;
3205 out << " return;" << endl;
3206 out << " }" << endl << endl;
3207 out << " mgr->PrintStatus();" << endl;
3208 if (AliAnalysisManager::GetAnalysisManager()) {
3209 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3210 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3212 if (TestBit(AliAnalysisGrid::kTest))
3213 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3215 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3218 if (IsUsingTags()) {
3219 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
3221 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
3223 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
3224 out << " timer.Stop();" << endl;
3225 out << " timer.Print();" << endl;
3226 out << "}" << endl << endl;
3227 if (IsUsingTags()) {
3228 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
3230 out << "// Create a chain using tags from the xml file." << endl;
3231 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
3232 out << " if (!coll) {" << endl;
3233 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3234 out << " return NULL;" << endl;
3235 out << " }" << endl;
3236 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
3237 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
3238 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
3239 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
3240 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
3241 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
3242 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
3243 out << " // Check if the cuts configuration file was provided" << endl;
3244 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
3245 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
3246 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3247 out << " }" << endl;
3248 if (fFriendChainName=="") {
3249 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
3251 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
3252 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
3253 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
3255 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
3256 out << " chain->ls();" << endl;
3257 out << " return chain;" << endl;
3258 out << "}" << endl << endl;
3259 if (gSystem->AccessPathName("ConfigureCuts.C")) {
3260 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
3261 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
3262 msg += " AliLHCTagCuts *lhcCuts,\n";
3263 msg += " AliDetectorTagCuts *detCuts,\n";
3264 msg += " AliEventTagCuts *evCuts)";
3265 Info("WriteAnalysisMacro", "%s", msg.Data());
3268 if (!IsUsingTags() || fFriendChainName!="") {
3269 out <<"//________________________________________________________________________________" << endl;
3270 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
3272 out << "// Create a chain using url's from xml file" << endl;
3273 out << " TString filename;" << endl;
3274 out << " Int_t run = 0;" << endl;
3275 if (IsUseMCchain()) {
3276 out << " TString treename = \"TE\";" << endl;
3278 out << " TString treename = type;" << endl;
3279 out << " treename.ToLower();" << endl;
3280 out << " treename += \"Tree\";" << endl;
3282 out << " printf(\"***************************************\\n\");" << endl;
3283 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
3284 out << " printf(\"***************************************\\n\");" << endl;
3285 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
3286 out << " if (!coll) {" << endl;
3287 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
3288 out << " return NULL;" << endl;
3289 out << " }" << endl;
3290 out << " AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();" << endl;
3291 out << " TChain *chain = new TChain(treename);" << endl;
3292 if(fFriendChainName!="") {
3293 out << " TChain *chainFriend = new TChain(treename);" << endl;
3295 out << " coll->Reset();" << endl;
3296 out << " while (coll->Next()) {" << endl;
3297 out << " filename = coll->GetTURL("");" << endl;
3298 out << " if (mgr) {" << endl;
3299 out << " Int_t nrun = AliAnalysisManager::GetRunFromAlienPath(filename);" << endl;
3300 out << " if (nrun && nrun != run) {" << endl;
3301 out << " printf(\"### Run number detected from chain: %d\\n\", nrun);" << endl;
3302 out << " mgr->SetRunFromPath(nrun);" << endl;
3303 out << " run = nrun;" << endl;
3304 out << " }" << endl;
3305 out << " }" << endl;
3306 out << " chain->Add(filename);" << endl;
3307 if(fFriendChainName!="") {
3308 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
3309 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3310 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
3311 out << " chainFriend->Add(fileFriend.Data());" << endl;
3313 out << " }" << endl;
3314 out << " if (!chain->GetNtrees()) {" << endl;
3315 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
3316 out << " return NULL;" << endl;
3317 out << " }" << endl;
3318 if(fFriendChainName!="") {
3319 out << " chain->AddFriend(chainFriend);" << endl;
3321 out << " return chain;" << endl;
3322 out << "}" << endl << endl;
3324 if (hasANALYSISalice) {
3325 out <<"//________________________________________________________________________________" << endl;
3326 out << "Bool_t SetupPar(const char *package) {" << endl;
3327 out << "// Compile the package and set it up." << endl;
3328 out << " TString pkgdir = package;" << endl;
3329 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3330 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3331 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3332 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3333 out << " // Check for BUILD.sh and execute" << endl;
3334 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3335 out << " printf(\"*******************************\\n\");" << endl;
3336 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3337 out << " printf(\"*******************************\\n\");" << endl;
3338 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3339 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3340 out << " gSystem->ChangeDirectory(cdir);" << endl;
3341 out << " return kFALSE;" << endl;
3342 out << " }" << endl;
3343 out << " } else {" << endl;
3344 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3345 out << " gSystem->ChangeDirectory(cdir);" << endl;
3346 out << " return kFALSE;" << endl;
3347 out << " }" << endl;
3348 out << " // Check for SETUP.C and execute" << endl;
3349 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3350 out << " printf(\"*******************************\\n\");" << endl;
3351 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3352 out << " printf(\"*******************************\\n\");" << endl;
3353 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3354 out << " } else {" << endl;
3355 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3356 out << " gSystem->ChangeDirectory(cdir);" << endl;
3357 out << " return kFALSE;" << endl;
3358 out << " }" << endl;
3359 out << " // Restore original workdir" << endl;
3360 out << " gSystem->ChangeDirectory(cdir);" << endl;
3361 out << " return kTRUE;" << endl;
3364 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
3366 Bool_t copy = kTRUE;
3367 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3370 TString workdir = gGrid->GetHomeDirectory();
3371 workdir += fGridWorkingDir;
3372 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
3373 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
3374 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
3375 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
3376 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
3378 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
3379 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
3383 //______________________________________________________________________________
3384 void AliAnalysisAlien::WriteMergingMacro()
3386 // Write a macro to merge the outputs per master job.
3387 if (!fMergeViaJDL) return;
3388 if (!fOutputFiles.Length()) {
3389 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
3392 TString mergingMacro = fExecutable;
3393 mergingMacro.ReplaceAll(".sh","_merge.C");
3394 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
3395 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3397 out.open(mergingMacro.Data(), ios::out);
3399 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
3402 Bool_t hasSTEERBase = kFALSE;
3403 Bool_t hasESD = kFALSE;
3404 Bool_t hasAOD = kFALSE;
3405 Bool_t hasANALYSIS = kFALSE;
3406 Bool_t hasANALYSISalice = kFALSE;
3407 Bool_t hasCORRFW = kFALSE;
3408 TString func = mergingMacro;
3410 func.ReplaceAll(".C", "");
3411 out << "void " << func.Data() << "(const char *dir, Int_t stage=0)" << endl;
3413 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
3414 out << " TStopwatch timer;" << endl;
3415 out << " timer.Start();" << endl << endl;
3416 // Reset existing include path
3417 out << "// Reset existing include path and add current directory first in the search" << endl;
3418 out << " gSystem->SetIncludePath(\"-I.\");" << endl;
3419 if (!fExecutableCommand.Contains("aliroot")) {
3420 out << "// load base root libraries" << endl;
3421 out << " gSystem->Load(\"libTree\");" << endl;
3422 out << " gSystem->Load(\"libGeom\");" << endl;
3423 out << " gSystem->Load(\"libVMC\");" << endl;
3424 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
3425 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
3427 if (fAdditionalRootLibs.Length()) {
3428 // in principle libtree /lib geom libvmc etc. can go into this list, too
3429 out << "// Add aditional libraries" << endl;
3430 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
3433 while((str=(TObjString*)next())) {
3434 if (str->GetString().Contains(".so"))
3435 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3437 if (list) delete list;
3439 out << "// Load analysis framework libraries" << endl;
3441 if (!fExecutableCommand.Contains("aliroot")) {
3442 out << " gSystem->Load(\"libSTEERBase\");" << endl;
3443 out << " gSystem->Load(\"libESD\");" << endl;
3444 out << " gSystem->Load(\"libAOD\");" << endl;
3446 out << " gSystem->Load(\"libANALYSIS\");" << endl;
3447 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3448 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3450 TIter next(fPackages);
3453 TString setupPar = "AliAnalysisAlien::SetupPar";
3454 while ((obj=next())) {
3455 pkgname = obj->GetName();
3456 if (pkgname == "STEERBase" ||
3457 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
3458 if (pkgname == "ESD" ||
3459 pkgname == "ESD.par") hasESD = kTRUE;
3460 if (pkgname == "AOD" ||
3461 pkgname == "AOD.par") hasAOD = kTRUE;
3462 if (pkgname == "ANALYSIS" ||
3463 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
3464 if (pkgname == "ANALYSISalice" ||
3465 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
3466 if (pkgname == "CORRFW" ||
3467 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
3469 if (hasANALYSISalice) setupPar = "SetupPar";
3470 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
3471 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
3472 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
3473 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
3474 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
3475 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
3476 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
3477 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
3478 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
3479 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
3480 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
3481 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
3482 out << "// Compile other par packages" << endl;
3484 while ((obj=next())) {
3485 pkgname = obj->GetName();
3486 if (pkgname == "STEERBase" ||
3487 pkgname == "STEERBase.par" ||
3489 pkgname == "ESD.par" ||
3491 pkgname == "AOD.par" ||
3492 pkgname == "ANALYSIS" ||
3493 pkgname == "ANALYSIS.par" ||
3494 pkgname == "ANALYSISalice" ||
3495 pkgname == "ANALYSISalice.par" ||
3496 pkgname == "CORRFW" ||
3497 pkgname == "CORRFW.par") continue;
3498 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
3501 out << "// include path" << endl;
3502 // Get the include path from the interpreter and remove entries pointing to AliRoot
3503 out << " TString intPath = gInterpreter->GetIncludePath();" << endl;
3504 out << " TObjArray *listpaths = intPath.Tokenize(\" \");" << endl;
3505 out << " TIter nextpath(listpaths);" << endl;
3506 out << " TObjString *pname;" << endl;
3507 out << " while ((pname=(TObjString*)nextpath())) {" << endl;
3508 out << " TString current = pname->GetName();" << endl;
3509 out << " if (current.Contains(\"AliRoot\") || current.Contains(\"ALICE_ROOT\")) continue;" << endl;
3510 out << " gSystem->AddIncludePath(current);" << endl;
3511 out << " }" << endl;
3512 out << " if (listpaths) delete listpaths;" << endl;
3513 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
3514 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
3515 out << " printf(\"Include path: %s\\n\", gSystem->GetIncludePath());" << endl << endl;
3516 if (fAdditionalLibs.Length()) {
3517 out << "// Add aditional AliRoot libraries" << endl;
3518 TObjArray *list = fAdditionalLibs.Tokenize(" ");
3521 while((str=(TObjString*)next())) {
3522 if (str->GetString().Contains(".so"))
3523 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
3525 if (list) delete list;
3528 out << "// Analysis source to be compiled at runtime (if any)" << endl;
3529 if (fAnalysisSource.Length()) {
3530 TObjArray *list = fAnalysisSource.Tokenize(" ");
3533 while((str=(TObjString*)next())) {
3534 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
3536 if (list) delete list;
3540 if (fFastReadOption) {
3541 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 !!!");
3542 out << "// fast xrootd reading enabled" << endl;
3543 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
3544 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",50);" << endl;
3545 out << " gEnv->SetValue(\"XNet.RequestTimeout\",50);" << endl;
3546 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
3547 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",50);" << endl;
3548 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
3550 // Change temp directory to current one
3551 out << "// Set temporary merging directory to current one" << endl;
3552 out << " gSystem->Setenv(\"TMPDIR\", gSystem->pwd());" << endl << endl;
3553 out << "// Connect to AliEn" << endl;
3554 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
3555 out << " TString outputDir = dir;" << endl;
3556 out << " TString outputFiles = \"" << GetListOfFiles("out") << "\";" << endl;
3557 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
3558 out << " TObjArray *list = outputFiles.Tokenize(\",\");" << endl;
3559 out << " TIter *iter = new TIter(list);" << endl;
3560 out << " TObjString *str;" << endl;
3561 out << " TString outputFile;" << endl;
3562 out << " Bool_t merged = kTRUE;" << endl;
3563 out << " while((str=(TObjString*)iter->Next())) {" << endl;
3564 out << " outputFile = str->GetString();" << endl;
3565 out << " if (outputFile.Contains(\"*\")) continue;" << endl;
3566 out << " Int_t index = outputFile.Index(\"@\");" << endl;
3567 out << " if (index > 0) outputFile.Remove(index);" << endl;
3568 out << " // Skip already merged outputs" << endl;
3569 out << " if (!gSystem->AccessPathName(outputFile)) {" << endl;
3570 out << " printf(\"Output file <%s> found. Not merging again.\",outputFile.Data());" << endl;
3571 out << " continue;" << endl;
3572 out << " }" << endl;
3573 out << " if (mergeExcludes.Contains(outputFile.Data())) continue;" << endl;
3574 out << " merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, " << fMaxMergeFiles << ", stage);" << endl;
3575 out << " if (!merged) {" << endl;
3576 out << " printf(\"ERROR: Cannot merge %s\\n\", outputFile.Data());" << endl;
3577 out << " return;" << endl;
3578 out << " }" << endl;
3579 out << " }" << endl;
3580 out << " // all outputs merged, validate" << endl;
3581 out << " ofstream out;" << endl;
3582 out << " out.open(\"outputs_valid\", ios::out);" << endl;
3583 out << " out.close();" << endl;
3584 out << " // read the analysis manager from file" << endl;
3585 TString analysisFile = fExecutable;
3586 analysisFile.ReplaceAll(".sh", ".root");
3587 out << " if (!outputDir.Contains(\"Stage\")) return;" << endl;
3588 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
3589 out << " if (!file) return;" << endl;
3590 out << " TIter nextkey(file->GetListOfKeys());" << endl;
3591 out << " AliAnalysisManager *mgr = 0;" << endl;
3592 out << " TKey *key;" << endl;
3593 out << " while ((key=(TKey*)nextkey())) {" << endl;
3594 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
3595 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
3596 out << " };" << endl;
3597 out << " if (!mgr) {" << endl;
3598 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
3599 out << " return;" << endl;
3600 out << " }" << endl << endl;
3601 out << " mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));" << endl;
3602 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
3603 out << " mgr->PrintStatus();" << endl;
3604 if (AliAnalysisManager::GetAnalysisManager()) {
3605 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
3606 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
3608 if (TestBit(AliAnalysisGrid::kTest))
3609 out << " AliLog::SetGlobalLogLevel(AliLog::kWarning);" << endl;
3611 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
3614 out << " TTree *tree = NULL;" << endl;
3615 out << " mgr->StartAnalysis(\"gridterminate\", tree);" << endl;
3616 out << "}" << endl << endl;
3617 if (hasANALYSISalice) {
3618 out <<"//________________________________________________________________________________" << endl;
3619 out << "Bool_t SetupPar(const char *package) {" << endl;
3620 out << "// Compile the package and set it up." << endl;
3621 out << " TString pkgdir = package;" << endl;
3622 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
3623 out << " gSystem->Exec(TString::Format(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
3624 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
3625 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
3626 out << " // Check for BUILD.sh and execute" << endl;
3627 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
3628 out << " printf(\"*******************************\\n\");" << endl;
3629 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
3630 out << " printf(\"*******************************\\n\");" << endl;
3631 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
3632 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
3633 out << " gSystem->ChangeDirectory(cdir);" << endl;
3634 out << " return kFALSE;" << endl;
3635 out << " }" << endl;
3636 out << " } else {" << endl;
3637 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
3638 out << " gSystem->ChangeDirectory(cdir);" << endl;
3639 out << " return kFALSE;" << endl;
3640 out << " }" << endl;
3641 out << " // Check for SETUP.C and execute" << endl;
3642 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
3643 out << " printf(\"*******************************\\n\");" << endl;
3644 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
3645 out << " printf(\"*******************************\\n\");" << endl;
3646 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
3647 out << " } else {" << endl;
3648 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
3649 out << " gSystem->ChangeDirectory(cdir);" << endl;
3650 out << " return kFALSE;" << endl;
3651 out << " }" << endl;
3652 out << " // Restore original workdir" << endl;
3653 out << " gSystem->ChangeDirectory(cdir);" << endl;
3654 out << " return kTRUE;" << endl;
3658 Bool_t copy = kTRUE;
3659 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3662 TString workdir = gGrid->GetHomeDirectory();
3663 workdir += fGridWorkingDir;
3664 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
3665 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
3666 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
3670 //______________________________________________________________________________
3671 Bool_t AliAnalysisAlien::SetupPar(const char *package)
3673 // Compile the par file archive pointed by <package>. This must be present in the current directory.
3674 // Note that for loading the compiled library. The current directory should have precedence in
3676 TString pkgdir = package;
3677 pkgdir.ReplaceAll(".par","");
3678 gSystem->Exec(TString::Format("tar xzf %s.par", pkgdir.Data()));
3679 TString cdir = gSystem->WorkingDirectory();
3680 gSystem->ChangeDirectory(pkgdir);
3681 // Check for BUILD.sh and execute
3682 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
3683 printf("**************************************************\n");
3684 printf("*** Building PAR archive %s\n", package);
3685 printf("**************************************************\n");
3686 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
3687 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
3688 gSystem->ChangeDirectory(cdir);
3692 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
3693 gSystem->ChangeDirectory(cdir);
3696 // Check for SETUP.C and execute
3697 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
3698 printf("**************************************************\n");
3699 printf("*** Setup PAR archive %s\n", package);
3700 printf("**************************************************\n");
3701 gROOT->Macro("PROOF-INF/SETUP.C");
3702 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
3704 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
3705 gSystem->ChangeDirectory(cdir);
3708 // Restore original workdir
3709 gSystem->ChangeDirectory(cdir);
3713 //______________________________________________________________________________
3714 void AliAnalysisAlien::WriteExecutable()
3716 // Generate the alien executable script.
3717 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3719 out.open(fExecutable.Data(), ios::out);
3721 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
3724 out << "#!/bin/bash" << endl;
3725 // Make sure we can properly compile par files
3726 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3727 out << "echo \"=========================================\"" << endl;
3728 out << "echo \"############## PATH : ##############\"" << endl;
3729 out << "echo $PATH" << endl;
3730 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3731 out << "echo $LD_LIBRARY_PATH" << endl;
3732 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3733 out << "echo $ROOTSYS" << endl;
3734 out << "echo \"############## which root : ##############\"" << endl;
3735 out << "which root" << endl;
3736 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3737 out << "echo $ALICE_ROOT" << endl;
3738 out << "echo \"############## which aliroot : ##############\"" << endl;
3739 out << "which aliroot" << endl;
3740 out << "echo \"############## system limits : ##############\"" << endl;
3741 out << "ulimit -a" << endl;
3742 out << "echo \"############## memory : ##############\"" << endl;
3743 out << "free -m" << endl;
3744 out << "echo \"=========================================\"" << endl << endl;
3745 out << fExecutableCommand << " ";
3746 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
3747 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
3748 out << "echo \"############## memory after: ##############\"" << endl;
3749 out << "free -m" << endl;
3751 Bool_t copy = kTRUE;
3752 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3755 TString workdir = gGrid->GetHomeDirectory();
3756 TString bindir = Form("%s/bin", workdir.Data());
3757 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3758 workdir += fGridWorkingDir;
3759 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
3760 if (FileExists(executable)) gGrid->Rm(executable);
3761 Info("WriteExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
3762 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
3766 //______________________________________________________________________________
3767 void AliAnalysisAlien::WriteMergeExecutable()
3769 // Generate the alien executable script for the merging job.
3770 if (!fMergeViaJDL) return;
3771 TString mergeExec = fExecutable;
3772 mergeExec.ReplaceAll(".sh", "_merge.sh");
3773 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3775 out.open(mergeExec.Data(), ios::out);
3777 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
3780 out << "#!/bin/bash" << endl;
3781 // Make sure we can properly compile par files
3782 out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
3783 out << "echo \"=========================================\"" << endl;
3784 out << "echo \"############## PATH : ##############\"" << endl;
3785 out << "echo $PATH" << endl;
3786 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
3787 out << "echo $LD_LIBRARY_PATH" << endl;
3788 out << "echo \"############## ROOTSYS : ##############\"" << endl;
3789 out << "echo $ROOTSYS" << endl;
3790 out << "echo \"############## which root : ##############\"" << endl;
3791 out << "which root" << endl;
3792 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
3793 out << "echo $ALICE_ROOT" << endl;
3794 out << "echo \"############## which aliroot : ##############\"" << endl;
3795 out << "which aliroot" << endl;
3796 out << "echo \"############## system limits : ##############\"" << endl;
3797 out << "ulimit -a" << endl;
3798 out << "echo \"############## memory : ##############\"" << endl;
3799 out << "free -m" << endl;
3800 out << "echo \"=========================================\"" << endl << endl;
3801 TString mergeMacro = fExecutable;
3802 mergeMacro.ReplaceAll(".sh", "_merge.C");
3803 if (IsOneStageMerging())
3804 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
3806 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\",$2)\"" << endl;
3807 out << fExecutableCommand << " " << "$ARG" << endl;
3808 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
3809 out << "echo \"############## memory after: ##############\"" << endl;
3810 out << "free -m" << endl;
3812 Bool_t copy = kTRUE;
3813 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3816 TString workdir = gGrid->GetHomeDirectory();
3817 TString bindir = Form("%s/bin", workdir.Data());
3818 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir,"-p");
3819 workdir += fGridWorkingDir;
3820 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
3821 if (FileExists(executable)) gGrid->Rm(executable);
3822 Info("WriteMergeExecutable", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
3823 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
3827 //______________________________________________________________________________
3828 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
3830 // Write the production file to be submitted by LPM manager. The format is:
3831 // First line: full_path_to_jdl estimated_no_subjobs_per_master
3832 // Next lines: full_path_to_dataset XXX (XXX is a string)
3833 // To submit, one has to: submit jdl XXX for all lines
3835 out.open(filename, ios::out);
3837 Error("WriteProductionFile", "Bad file name: %s", filename);
3841 if (!fProductionMode && !fGridWorkingDir.BeginsWith("/alice"))
3842 workdir = gGrid->GetHomeDirectory();
3843 workdir += fGridWorkingDir;
3844 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
3845 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
3846 out << locjdl << " " << njobspermaster << endl;
3847 Int_t nmasterjobs = fInputFiles->GetEntries();
3848 for (Int_t i=0; i<nmasterjobs; i++) {
3849 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
3850 runOutDir.ReplaceAll(".xml", "");
3852 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
3854 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
3857 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
3858 if (FileExists(filename)) gGrid->Rm(filename);
3859 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
3863 //______________________________________________________________________________
3864 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
3866 // Generate the alien validation script.
3867 // Generate the validation script
3869 if (fValidationScript.IsNull()) {
3870 fValidationScript = fExecutable;
3871 fValidationScript.ReplaceAll(".sh", "_validation.sh");
3873 TString validationScript = fValidationScript;
3874 if (merge) validationScript.ReplaceAll(".sh", "_merge.sh");
3876 Error("WriteValidationScript", "Alien connection required");
3879 if (!fTerminateFiles.IsNull()) {
3880 fTerminateFiles.Strip();
3881 fTerminateFiles.ReplaceAll(" ",",");
3883 TString outStream = "";
3884 if (!TestBit(AliAnalysisGrid::kTest)) outStream = " >> stdout";
3885 if (!TestBit(AliAnalysisGrid::kSubmit)) {
3887 out.open(validationScript, ios::out);
3888 out << "#!/bin/bash" << endl;
3889 out << "##################################################" << endl;
3890 out << "validateout=`dirname $0`" << endl;
3891 out << "validatetime=`date`" << endl;
3892 out << "validated=\"0\";" << endl;
3893 out << "error=0" << endl;
3894 out << "if [ -z $validateout ]" << endl;
3895 out << "then" << endl;
3896 out << " validateout=\".\"" << endl;
3897 out << "fi" << endl << endl;
3898 out << "cd $validateout;" << endl;
3899 out << "validateworkdir=`pwd`;" << endl << endl;
3900 out << "echo \"*******************************************************\"" << outStream << endl;
3901 out << "echo \"* Automatically generated validation script *\"" << outStream << endl;
3903 out << "echo \"* Time: $validatetime \"" << outStream << endl;
3904 out << "echo \"* Dir: $validateout\"" << outStream << endl;
3905 out << "echo \"* Workdir: $validateworkdir\"" << outStream << endl;
3906 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3907 out << "ls -la ./" << outStream << endl;
3908 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl << endl;
3909 out << "##################################################" << endl;
3912 out << "if [ ! -f stderr ] ; then" << endl;
3913 out << " error=1" << endl;
3914 out << " echo \"* ########## Job not validated - no stderr ###\" " << outStream << endl;
3915 out << " echo \"Error = $error\" " << outStream << endl;
3916 out << "fi" << endl;
3918 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
3919 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
3920 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
3921 out << "glibcErr=`grep -Ei \"*** glibc detected ***\" stderr`" << endl;
3924 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
3925 out << " error=1" << endl;
3926 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << outStream << endl;
3927 out << " echo \"$parArch\" " << outStream << endl;
3928 out << " echo \"Error = $error\" " << outStream << endl;
3929 out << "fi" << endl;
3931 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
3932 out << " error=1" << endl;
3933 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << outStream << endl;
3934 out << " echo \"$segViol\" " << outStream << endl;
3935 out << " echo \"Error = $error\" " << outStream << endl;
3936 out << "fi" << endl;
3938 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
3939 out << " error=1" << endl;
3940 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << outStream << endl;
3941 out << " echo \"$segFault\" " << outStream << endl;
3942 out << " echo \"Error = $error\" " << outStream << endl;
3943 out << "fi" << endl;
3945 out << "if [ \"$glibcErr\" != \"\" ] ; then" << endl;
3946 out << " error=1" << endl;
3947 out << " echo \"* ########## Job not validated - *** glibc detected *** ###\" " << outStream << endl;
3948 out << " echo \"$glibcErr\" " << outStream << endl;
3949 out << " echo \"Error = $error\" " << outStream << endl;
3950 out << "fi" << endl;
3952 // Part dedicated to the specific analyses running into the train
3954 TString outputFiles = fOutputFiles;
3955 if (merge && !fTerminateFiles.IsNull()) {
3957 outputFiles += fTerminateFiles;
3959 TObjArray *arr = outputFiles.Tokenize(",");
3962 while (!merge && (os=(TObjString*)next1())) {
3963 // No need to validate outputs produced by merging since the merging macro does this
3964 outputFile = os->GetString();
3965 Int_t index = outputFile.Index("@");
3966 if (index > 0) outputFile.Remove(index);
3967 if (fTerminateFiles.Contains(outputFile)) continue;
3968 if (outputFile.Contains("*")) continue;
3969 out << "if ! [ -f " << outputFile.Data() << " ] ; then" << endl;
3970 out << " error=1" << endl;
3971 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\"" << outStream << endl;
3972 out << " echo \"Output file " << outputFile << " not found. Job FAILED !\" >> stderr" << endl;
3973 out << "fi" << endl;
3976 out << "if ! [ -f outputs_valid ] ; then" << endl;
3977 out << " error=1" << endl;
3978 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3979 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3980 out << "fi" << endl;
3982 out << "if [ $error = 0 ] ; then" << endl;
3983 out << " echo \"* ---------------- Job Validated ------------------*\"" << outStream << endl;
3984 if (!IsKeepLogs()) {
3985 out << " echo \"* === Logs std* will be deleted === \"" << endl;
3987 out << " rm -f std*" << endl;
3989 out << "fi" << endl;
3991 out << "echo \"* ----------------------------------------------------*\"" << outStream << endl;
3992 out << "echo \"*******************************************************\"" << outStream << endl;
3993 out << "cd -" << endl;
3994 out << "exit $error" << endl;
3996 Bool_t copy = kTRUE;
3997 if (fProductionMode || TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
4000 TString workdir = gGrid->GetHomeDirectory();
4001 workdir += fGridWorkingDir;
4002 Info("WriteValidationScript", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
4003 if (FileExists(validationScript)) gGrid->Rm(validationScript);
4004 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));