1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "Riostream.h"
29 #include "TObjString.h"
30 #include "TObjArray.h"
32 #include "TGridResult.h"
33 #include "TGridCollection.h"
35 #include "TGridJobStatusList.h"
36 #include "TGridJobStatus.h"
37 #include "TFileMerger.h"
38 #include "AliAnalysisManager.h"
39 #include "AliVEventHandler.h"
40 #include "AliAnalysisDataContainer.h"
41 #include "AliAnalysisAlien.h"
43 ClassImp(AliAnalysisAlien)
45 //______________________________________________________________________________
46 AliAnalysisAlien::AliAnalysisAlien()
52 fSplitMaxInputFileNumber(0),
54 fMasterResubmitThreshold(0),
71 fAdditionalRootLibs(),
102 //______________________________________________________________________________
103 AliAnalysisAlien::AliAnalysisAlien(const char *name)
104 :AliAnalysisGrid(name),
109 fSplitMaxInputFileNumber(0),
111 fMasterResubmitThreshold(0),
123 fExecutableCommand(),
128 fAdditionalRootLibs(),
159 //______________________________________________________________________________
160 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
161 :AliAnalysisGrid(other),
164 fPrice(other.fPrice),
166 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
167 fMaxInitFailed(other.fMaxInitFailed),
168 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
169 fNtestFiles(other.fNtestFiles),
170 fNrunsPerMaster(other.fNrunsPerMaster),
171 fMaxMergeFiles(other.fMaxMergeFiles),
172 fNsubmitted(other.fNsubmitted),
173 fProductionMode(other.fProductionMode),
174 fOutputToRunNo(other.fOutputToRunNo),
175 fMergeViaJDL(other.fMergeViaJDL),
176 fFastReadOption(other.fFastReadOption),
177 fOverwriteMode(other.fOverwriteMode),
178 fRunNumbers(other.fRunNumbers),
179 fExecutable(other.fExecutable),
180 fExecutableCommand(other.fExecutableCommand),
181 fArguments(other.fArguments),
182 fExecutableArgs(other.fExecutableArgs),
183 fAnalysisMacro(other.fAnalysisMacro),
184 fAnalysisSource(other.fAnalysisSource),
185 fAdditionalRootLibs(other.fAdditionalRootLibs),
186 fAdditionalLibs(other.fAdditionalLibs),
187 fSplitMode(other.fSplitMode),
188 fAPIVersion(other.fAPIVersion),
189 fROOTVersion(other.fROOTVersion),
190 fAliROOTVersion(other.fAliROOTVersion),
191 fExternalPackages(other.fExternalPackages),
193 fGridWorkingDir(other.fGridWorkingDir),
194 fGridDataDir(other.fGridDataDir),
195 fDataPattern(other.fDataPattern),
196 fGridOutputDir(other.fGridOutputDir),
197 fOutputArchive(other.fOutputArchive),
198 fOutputFiles(other.fOutputFiles),
199 fInputFormat(other.fInputFormat),
200 fDatasetName(other.fDatasetName),
201 fJDLName(other.fJDLName),
202 fMergeExcludes(other.fMergeExcludes),
203 fIncludePath(other.fIncludePath),
204 fCloseSE(other.fCloseSE),
205 fFriendChainName(other.fFriendChainName),
206 fJobTag(other.fJobTag),
207 fOutputSingle(other.fOutputSingle),
208 fRunPrefix(other.fRunPrefix),
213 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
214 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
215 fRunRange[0] = other.fRunRange[0];
216 fRunRange[1] = other.fRunRange[1];
217 if (other.fInputFiles) {
218 fInputFiles = new TObjArray();
219 TIter next(other.fInputFiles);
221 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
222 fInputFiles->SetOwner();
224 if (other.fPackages) {
225 fPackages = new TObjArray();
226 TIter next(other.fPackages);
228 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
229 fPackages->SetOwner();
233 //______________________________________________________________________________
234 AliAnalysisAlien::~AliAnalysisAlien()
237 if (fGridJDL) delete fGridJDL;
238 if (fMergingJDL) delete fMergingJDL;
239 if (fInputFiles) delete fInputFiles;
240 if (fPackages) delete fPackages;
243 //______________________________________________________________________________
244 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
247 if (this != &other) {
248 AliAnalysisGrid::operator=(other);
249 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
250 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
251 fPrice = other.fPrice;
253 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
254 fMaxInitFailed = other.fMaxInitFailed;
255 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
256 fNtestFiles = other.fNtestFiles;
257 fNrunsPerMaster = other.fNrunsPerMaster;
258 fMaxMergeFiles = other.fMaxMergeFiles;
259 fNsubmitted = other.fNsubmitted;
260 fProductionMode = other.fProductionMode;
261 fOutputToRunNo = other.fOutputToRunNo;
262 fMergeViaJDL = other.fMergeViaJDL;
263 fFastReadOption = other.fFastReadOption;
264 fOverwriteMode = other.fOverwriteMode;
265 fRunNumbers = other.fRunNumbers;
266 fExecutable = other.fExecutable;
267 fExecutableCommand = other.fExecutableCommand;
268 fArguments = other.fArguments;
269 fExecutableArgs = other.fExecutableArgs;
270 fAnalysisMacro = other.fAnalysisMacro;
271 fAnalysisSource = other.fAnalysisSource;
272 fAdditionalRootLibs = other.fAdditionalRootLibs;
273 fAdditionalLibs = other.fAdditionalLibs;
274 fSplitMode = other.fSplitMode;
275 fAPIVersion = other.fAPIVersion;
276 fROOTVersion = other.fROOTVersion;
277 fAliROOTVersion = other.fAliROOTVersion;
278 fExternalPackages = other.fExternalPackages;
280 fGridWorkingDir = other.fGridWorkingDir;
281 fGridDataDir = other.fGridDataDir;
282 fDataPattern = other.fDataPattern;
283 fGridOutputDir = other.fGridOutputDir;
284 fOutputArchive = other.fOutputArchive;
285 fOutputFiles = other.fOutputFiles;
286 fInputFormat = other.fInputFormat;
287 fDatasetName = other.fDatasetName;
288 fJDLName = other.fJDLName;
289 fMergeExcludes = other.fMergeExcludes;
290 fIncludePath = other.fIncludePath;
291 fCloseSE = other.fCloseSE;
292 fFriendChainName = other.fFriendChainName;
293 fJobTag = other.fJobTag;
294 fOutputSingle = other.fOutputSingle;
295 fRunPrefix = other.fRunPrefix;
296 if (other.fInputFiles) {
297 fInputFiles = new TObjArray();
298 TIter next(other.fInputFiles);
300 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
301 fInputFiles->SetOwner();
303 if (other.fPackages) {
304 fPackages = new TObjArray();
305 TIter next(other.fPackages);
307 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
308 fPackages->SetOwner();
314 //______________________________________________________________________________
315 void AliAnalysisAlien::AddIncludePath(const char *path)
317 // Add include path in the remote analysis macro.
319 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
320 else fIncludePath += Form("-I%s ", path);
323 //______________________________________________________________________________
324 void AliAnalysisAlien::AddRunNumber(Int_t run)
326 // Add a run number to the list of runs to be processed.
327 if (fRunNumbers.Length()) fRunNumbers += " ";
328 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
331 //______________________________________________________________________________
332 void AliAnalysisAlien::AddRunNumber(const char* run)
334 // Add a run number to the list of runs to be processed.
335 if (fRunNumbers.Length()) fRunNumbers += " ";
339 //______________________________________________________________________________
340 void AliAnalysisAlien::AddDataFile(const char *lfn)
342 // Adds a data file to the input to be analysed. The file should be a valid LFN
343 // or point to an existing file in the alien workdir.
344 if (!fInputFiles) fInputFiles = new TObjArray();
345 fInputFiles->Add(new TObjString(lfn));
348 //______________________________________________________________________________
349 void AliAnalysisAlien::AddExternalPackage(const char *package)
351 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
352 if (fExternalPackages) fExternalPackages += " ";
353 fExternalPackages += package;
356 //______________________________________________________________________________
357 Bool_t AliAnalysisAlien::Connect()
359 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
360 if (gGrid && gGrid->IsConnected()) return kTRUE;
361 if (!gSystem->Getenv("alien_API_USER")) {
362 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
363 gSystem->Getenv("UID"));
367 Info("Connect", "Trying to connect to AliEn ...");
368 TGrid::Connect("alien://");
370 if (!gGrid || !gGrid->IsConnected()) {
371 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
374 fUser = gGrid->GetUser();
375 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
379 //______________________________________________________________________________
380 void AliAnalysisAlien::CdWork()
382 // Check validity of alien workspace. Create directory if possible.
384 Error("CdWork", "Alien connection required");
387 TString homedir = gGrid->GetHomeDirectory();
388 TString workdir = homedir + fGridWorkingDir;
389 if (DirectoryExists(workdir)) {
393 // Work directory not existing - create it
395 if (gGrid->Mkdir(workdir)) {
396 gGrid->Cd(fGridWorkingDir);
397 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
399 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
400 workdir.Data(), homedir.Data());
401 fGridWorkingDir = "";
405 //______________________________________________________________________________
406 Bool_t AliAnalysisAlien::CheckInputData()
408 // Check validity of input data. If necessary, create xml files.
409 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
410 if (!fGridDataDir.Length()) {
411 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
414 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
417 // Process declared files
418 Bool_t is_collection = kFALSE;
419 Bool_t is_xml = kFALSE;
420 Bool_t use_tags = kFALSE;
421 Bool_t checked = kFALSE;
424 TString workdir = gGrid->GetHomeDirectory();
425 workdir += fGridWorkingDir;
428 TIter next(fInputFiles);
429 while ((objstr=(TObjString*)next())) {
432 file += objstr->GetString();
433 // Store full lfn path
434 if (FileExists(file)) objstr->SetString(file);
436 file = objstr->GetName();
437 if (!FileExists(objstr->GetName())) {
438 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
439 objstr->GetName(), workdir.Data());
443 Bool_t iscoll, isxml, usetags;
444 CheckDataType(file, iscoll, isxml, usetags);
447 is_collection = iscoll;
450 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
452 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
453 Error("CheckInputData", "Some conflict was found in the types of inputs");
459 // Process requested run numbers
460 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
461 // Check validity of alien data directory
462 if (!fGridDataDir.Length()) {
463 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
466 if (!DirectoryExists(fGridDataDir)) {
467 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
471 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
475 if (checked && !is_xml) {
476 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
479 // Check validity of run number(s)
483 TString schunk, schunk2;
487 use_tags = fDataPattern.Contains("tag");
488 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
490 if (use_tags != fDataPattern.Contains("tag")) {
491 Error("CheckInputData", "Cannot mix input files using/not using tags");
494 if (fRunNumbers.Length()) {
495 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
496 arr = fRunNumbers.Tokenize(" ");
498 while ((os=(TObjString*)next())) {
499 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
500 if (!DirectoryExists(path)) {
501 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
504 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
505 TString msg = "\n##### file: ";
507 msg += " type: xml_collection;";
508 if (use_tags) msg += " using_tags: Yes";
509 else msg += " using_tags: No";
510 Info("CheckDataType", msg.Data());
511 if (fNrunsPerMaster<2) {
512 AddDataFile(Form("%s.xml", os->GetString().Data()));
515 if (((nruns-1)%fNrunsPerMaster) == 0) {
516 schunk = os->GetString();
518 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
519 schunk += Form("_%s.xml", os->GetString().Data());
525 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
526 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
527 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
528 if (!DirectoryExists(path)) {
529 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
532 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
533 TString msg = "\n##### file: ";
535 msg += " type: xml_collection;";
536 if (use_tags) msg += " using_tags: Yes";
537 else msg += " using_tags: No";
538 Info("CheckDataType", msg.Data());
539 if (fNrunsPerMaster<2) {
540 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
543 if (((nruns-1)%fNrunsPerMaster) == 0) {
544 schunk = Form("%s%d", fRunPrefix.Data(),irun);
546 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
547 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
560 //______________________________________________________________________________
561 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
563 // Create dataset for the grid data directory + run number.
564 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
566 Error("CreateDataset", "Cannot create dataset with no grid connection");
572 TString workdir = gGrid->GetHomeDirectory();
573 workdir += fGridWorkingDir;
575 // Compose the 'find' command arguments
577 TString options = "-x collection ";
578 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
579 TString conditions = "";
584 TString schunk, schunk2;
585 TGridCollection *cbase=0, *cadd=0;
586 if (!fRunNumbers.Length() && !fRunRange[0]) {
587 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
588 // Make a single data collection from data directory.
590 if (!DirectoryExists(path)) {
591 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
595 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
596 else file = Form("%s.xml", gSystem->BaseName(path));
597 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
603 command += conditions;
604 printf("command: %s\n", command.Data());
605 TGridResult *res = gGrid->Command(command);
607 // Write standard output to file
608 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
610 Bool_t fileExists = FileExists(file);
611 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
612 // Copy xml file to alien space
613 if (fileExists) gGrid->Rm(file);
614 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
615 if (!FileExists(file)) {
616 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
619 // Update list of files to be processed.
621 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
625 if (fRunNumbers.Length()) {
626 TObjArray *arr = fRunNumbers.Tokenize(" ");
629 while ((os=(TObjString*)next())) {
630 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
631 if (!DirectoryExists(path)) continue;
633 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
634 else file = Form("%s.xml", os->GetString().Data());
635 // If local collection file does not exist, create it via 'find' command.
636 if (gSystem->AccessPathName(file)) {
641 command += conditions;
642 TGridResult *res = gGrid->Command(command);
644 // Write standard output to file
645 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
647 if (TestBit(AliAnalysisGrid::kTest)) break;
648 // Check if there is one run per master job.
649 if (fNrunsPerMaster<2) {
650 if (FileExists(file)) {
651 if (fOverwriteMode) gGrid->Rm(file);
653 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
657 // Copy xml file to alien space
658 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
659 if (!FileExists(file)) {
660 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
666 if (((nruns-1)%fNrunsPerMaster) == 0) {
667 schunk = os->GetString();
668 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
670 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
671 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
675 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
678 schunk += Form("_%s.xml", os->GetString().Data());
679 if (FileExists(schunk)) {
680 if (fOverwriteMode) gGrid->Rm(file);
682 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
686 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
687 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
688 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
689 if (!FileExists(schunk)) {
690 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
698 // Process a full run range.
699 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
700 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
701 if (!DirectoryExists(path)) continue;
703 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
704 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
705 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
706 if (fOverwriteMode) gGrid->Rm(file);
708 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
712 // If local collection file does not exist, create it via 'find' command.
713 if (gSystem->AccessPathName(file) || fOverwriteMode) {
718 command += conditions;
719 TGridResult *res = gGrid->Command(command);
721 // Write standard output to file
722 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
724 if (TestBit(AliAnalysisGrid::kTest)) break;
725 // Check if there is one run per master job.
726 if (fNrunsPerMaster<2) {
727 if (FileExists(file)) {
728 if (fOverwriteMode) gGrid->Rm(file);
730 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
734 // Copy xml file to alien space
735 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
736 if (!FileExists(file)) {
737 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
742 // Check if the collection for the chunk exist locally.
743 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
744 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
745 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
748 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
749 if (((nruns-1)%fNrunsPerMaster) == 0) {
750 schunk = Form("%s%d", fRunPrefix.Data(), irun);
751 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
753 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
757 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
758 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
762 if (FileExists(schunk)) {
763 if (fOverwriteMode) gGrid->Rm(schunk);
765 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
769 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
770 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
771 if (FileExists(schunk)) {
772 if (fOverwriteMode) gGrid->Rm(schunk);
774 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
778 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
779 if (!FileExists(schunk)) {
780 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
789 //______________________________________________________________________________
790 Bool_t AliAnalysisAlien::CreateJDL()
792 // Generate a JDL file according to current settings. The name of the file is
793 // specified by fJDLName.
794 Bool_t error = kFALSE;
797 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
798 Bool_t generate = kTRUE;
799 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
801 Error("CreateJDL", "Alien connection required");
804 // Check validity of alien workspace
806 TString workdir = gGrid->GetHomeDirectory();
807 workdir += fGridWorkingDir;
811 Error("CreateJDL()", "Define some input files for your analysis.");
814 // Compose list of input files
815 // Check if output files were defined
816 if (!fOutputFiles.Length()) {
817 Error("CreateJDL", "You must define at least one output file");
820 // Check if an output directory was defined and valid
821 if (!fGridOutputDir.Length()) {
822 Error("CreateJDL", "You must define AliEn output directory");
825 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
826 if (!DirectoryExists(fGridOutputDir)) {
827 if (gGrid->Mkdir(fGridOutputDir)) {
828 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
830 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
836 // Exit if any error up to now
837 if (error) return kFALSE;
839 if (!fUser.IsNull()) {
840 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
841 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
843 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
844 TString mergeExec = fExecutable;
845 mergeExec.ReplaceAll(".sh", "_merge.sh");
846 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
847 mergeExec.ReplaceAll(".sh", ".C");
848 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
849 if (!fArguments.IsNull())
850 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
851 fMergingJDL->SetArguments("$1");
852 fGridJDL->SetTTL((UInt_t)fTTL);
853 fMergingJDL->SetTTL((UInt_t)fTTL);
854 if (fMaxInitFailed > 0) {
855 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
856 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
858 if (fSplitMaxInputFileNumber > 0) {
859 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
860 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
862 if (fSplitMode.Length()) {
863 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
864 fGridJDL->SetDescription("Split", "We split per SE or file");
866 if (!fAliROOTVersion.IsNull()) {
867 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
868 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
870 if (!fROOTVersion.IsNull()) {
871 fGridJDL->AddToPackages("ROOT", fROOTVersion);
872 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
874 if (!fAPIVersion.IsNull()) {
875 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
876 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
878 if (!fExternalPackages.IsNull()) {
879 arr = fExternalPackages.Tokenize(" ");
881 while ((os=(TObjString*)next())) {
882 TString pkgname = os->GetString();
883 Int_t index = pkgname.Index("::");
884 TString pkgversion = pkgname(index+2, pkgname.Length());
885 pkgname.Remove(index);
886 fGridJDL->AddToPackages(pkgname, pkgversion);
887 fMergingJDL->AddToPackages(pkgname, pkgversion);
891 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
892 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
893 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
894 TString analysisFile = fExecutable;
895 analysisFile.ReplaceAll(".sh", ".root");
896 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
897 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
898 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
899 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
900 if (fAdditionalLibs.Length()) {
901 arr = fAdditionalLibs.Tokenize(" ");
903 while ((os=(TObjString*)next())) {
904 if (os->GetString().Contains(".so")) continue;
905 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
906 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
911 TIter next(fPackages);
913 while ((obj=next())) {
914 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
915 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
918 if (fOutputArchive.Length()) {
919 arr = fOutputArchive.Tokenize(" ");
921 Bool_t first = kTRUE;
922 const char *comment = "Files to be archived";
923 const char *comment1 = comment;
924 while ((os=(TObjString*)next())) {
925 if (!first) comment = NULL;
926 if (!os->GetString().Contains("@") && fCloseSE.Length())
927 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
929 fGridJDL->AddToOutputArchive(os->GetString(), comment);
933 TString outputArchive = fOutputArchive;
934 if (!fMergeExcludes.IsNull()) {
935 arr = fMergeExcludes.Tokenize(" ");
937 while ((os=(TObjString*)next1())) {
938 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
939 outputArchive.ReplaceAll(os->GetString(),"");
943 arr = outputArchive.Tokenize(" ");
947 while ((os=(TObjString*)next2())) {
948 if (!first) comment = NULL;
949 if (!os->GetString().Contains("@") && fCloseSE.Length())
950 fMergingJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
952 fMergingJDL->AddToOutputArchive(os->GetString(), comment);
957 arr = fOutputFiles.Tokenize(" ");
959 Bool_t first = kTRUE;
960 const char *comment = "Files to be archived";
961 const char *comment1 = comment;
962 while ((os=(TObjString*)next())) {
963 // Ignore ouputs in jdl that are also in outputarchive
964 TString sout = os->GetString();
965 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
966 if (fOutputArchive.Contains(sout)) continue;
967 if (!first) comment = NULL;
968 if (!os->GetString().Contains("@") && fCloseSE.Length())
969 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
971 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
975 if (fOutputFiles.Length()) {
976 TString outputFiles = fOutputFiles;
977 if (!fMergeExcludes.IsNull()) {
978 arr = fMergeExcludes.Tokenize(" ");
980 while ((os=(TObjString*)next1())) {
981 outputFiles.ReplaceAll(Form("%s,",os->GetString().Data()),"");
982 outputFiles.ReplaceAll(os->GetString(),"");
986 arr = outputFiles.Tokenize(" ");
990 while ((os=(TObjString*)next2())) {
991 // Ignore ouputs in jdl that are also in outputarchive
992 TString sout = os->GetString();
993 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
994 if (fOutputArchive.Contains(sout)) continue;
995 if (!first) comment = NULL;
996 if (!os->GetString().Contains("@") && fCloseSE.Length())
997 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
999 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1003 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1004 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1005 TString validationScript = fExecutable;
1006 validationScript.ReplaceAll(".sh", "_validation.sh");
1007 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1008 validationScript = fExecutable;
1009 validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
1010 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1011 if (fMasterResubmitThreshold) {
1012 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1013 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1015 // Write a jdl with 2 input parameters: collection name and output dir name.
1018 // Copy jdl to grid workspace
1020 // Check if an output directory was defined and valid
1021 if (!fGridOutputDir.Length()) {
1022 Error("CreateJDL", "You must define AliEn output directory");
1025 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1026 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1027 if (gGrid->Mkdir(fGridOutputDir)) {
1028 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1030 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1036 if (TestBit(AliAnalysisGrid::kSubmit)) {
1037 TString mergeJDLName = fExecutable;
1038 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1039 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1040 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1041 if (fProductionMode) {
1042 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1043 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1045 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1046 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1047 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1048 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1050 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1051 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1054 if (fAdditionalLibs.Length()) {
1055 arr = fAdditionalLibs.Tokenize(" ");
1058 while ((os=(TObjString*)next())) {
1059 if (os->GetString().Contains(".so")) continue;
1060 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1061 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1062 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1067 TIter next(fPackages);
1069 while ((obj=next())) {
1070 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1071 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1072 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1079 //______________________________________________________________________________
1080 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1082 // Writes one or more JDL's corresponding to findex. If findex is negative,
1083 // all run numbers are considered in one go (jdl). For non-negative indices
1084 // they correspond to the indices in the array fInputFiles.
1085 if (!fInputFiles) return kFALSE;
1087 TString workdir = gGrid->GetHomeDirectory();
1088 workdir += fGridWorkingDir;
1090 if (!fRunNumbers.Length() && !fRunRange[0]) {
1091 // One jdl with no parameters in case input data is specified by name.
1092 TIter next(fInputFiles);
1093 while ((os=(TObjString*)next()))
1094 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()), "Input xml collections");
1095 if (!fOutputSingle.IsNull())
1096 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1098 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1099 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1102 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1103 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1104 if (!fOutputSingle.IsNull()) {
1105 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1106 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1108 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1109 fMergingJDL->SetOutputDirectory(Form("%s/$1", fGridOutputDir.Data()), "Output directory");
1114 // Generate the JDL as a string
1115 TString sjdl = fGridJDL->Generate();
1116 TString sjdl1 = fMergingJDL->Generate();
1118 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1119 sjdl.ReplaceAll("(member", "\n (member");
1120 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1121 sjdl.ReplaceAll("{", "{\n ");
1122 sjdl.ReplaceAll("};", "\n};");
1123 sjdl.ReplaceAll("{\n \n", "{\n");
1124 sjdl.ReplaceAll("\n\n", "\n");
1125 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1126 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1127 sjdl1.ReplaceAll("(member", "\n (member");
1128 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1129 sjdl1.ReplaceAll("{", "{\n ");
1130 sjdl1.ReplaceAll("};", "\n};");
1131 sjdl1.ReplaceAll("{\n \n", "{\n");
1132 sjdl1.ReplaceAll("\n\n", "\n");
1133 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1134 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1135 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1136 index = sjdl.Index("JDLVariables");
1137 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1138 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1139 sjdl1.Prepend(Form("Jobtag = {\n \"comment:Merging_%s\"\n};\n", fJobTag.Data()));
1140 index = sjdl1.Index("JDLVariables");
1141 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1142 // Write jdl to file
1144 out.open(fJDLName.Data(), ios::out);
1146 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1149 out << sjdl << endl;
1150 TString mergeJDLName = fExecutable;
1151 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1154 out1.open(mergeJDLName.Data(), ios::out);
1156 Error("CreateJDL", "Bad file name: %s", mergeJDLName.Data());
1159 out1 << sjdl1 << endl;
1162 // Copy jdl to grid workspace
1164 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1166 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1167 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1168 if (fProductionMode) {
1169 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1170 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1172 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1173 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1174 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1175 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1177 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1178 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1184 //______________________________________________________________________________
1185 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1187 // Returns true if file exists.
1188 if (!gGrid) return kFALSE;
1189 TGridResult *res = gGrid->Ls(lfn);
1190 if (!res) return kFALSE;
1191 TMap *map = dynamic_cast<TMap*>(res->At(0));
1196 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1197 if (!objs || !objs->GetString().Length()) {
1205 //______________________________________________________________________________
1206 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1208 // Returns true if directory exists. Can be also a path.
1209 if (!gGrid) return kFALSE;
1210 // Check if dirname is a path
1211 TString dirstripped = dirname;
1212 dirstripped = dirstripped.Strip();
1213 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1214 TString dir = gSystem->BaseName(dirstripped);
1216 TString path = gSystem->DirName(dirstripped);
1217 TGridResult *res = gGrid->Ls(path, "-F");
1218 if (!res) return kFALSE;
1222 while ((map=dynamic_cast<TMap*>(next()))) {
1223 obj = map->GetValue("name");
1225 if (dir == obj->GetName()) {
1234 //______________________________________________________________________________
1235 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1237 // Check input data type.
1238 is_collection = kFALSE;
1242 Error("CheckDataType", "No connection to grid");
1245 is_collection = IsCollection(lfn);
1246 TString msg = "\n##### file: ";
1248 if (is_collection) {
1249 msg += " type: raw_collection;";
1250 // special treatment for collections
1252 // check for tag files in the collection
1253 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1255 msg += " using_tags: No (unknown)";
1256 Info("CheckDataType", msg.Data());
1259 const char* typeStr = res->GetKey(0, "origLFN");
1260 if (!typeStr || !strlen(typeStr)) {
1261 msg += " using_tags: No (unknown)";
1262 Info("CheckDataType", msg.Data());
1265 TString file = typeStr;
1266 use_tags = file.Contains(".tag");
1267 if (use_tags) msg += " using_tags: Yes";
1268 else msg += " using_tags: No";
1269 Info("CheckDataType", msg.Data());
1274 is_xml = slfn.Contains(".xml");
1276 // Open xml collection and check if there are tag files inside
1277 msg += " type: xml_collection;";
1278 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1280 msg += " using_tags: No (unknown)";
1281 Info("CheckDataType", msg.Data());
1284 TMap *map = coll->Next();
1286 msg += " using_tags: No (unknown)";
1287 Info("CheckDataType", msg.Data());
1290 map = (TMap*)map->GetValue("");
1292 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1293 use_tags = file.Contains(".tag");
1295 if (use_tags) msg += " using_tags: Yes";
1296 else msg += " using_tags: No";
1297 Info("CheckDataType", msg.Data());
1300 use_tags = slfn.Contains(".tag");
1301 if (slfn.Contains(".root")) msg += " type: root file;";
1302 else msg += " type: unknown file;";
1303 if (use_tags) msg += " using_tags: Yes";
1304 else msg += " using_tags: No";
1305 Info("CheckDataType", msg.Data());
1308 //______________________________________________________________________________
1309 void AliAnalysisAlien::EnablePackage(const char *package)
1311 // Enables a par file supposed to exist in the current directory.
1312 TString pkg(package);
1313 pkg.ReplaceAll(".par", "");
1315 if (gSystem->AccessPathName(pkg)) {
1316 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1319 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1320 Info("EnablePackage", "AliEn plugin will use .par packages");
1321 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1323 fPackages = new TObjArray();
1324 fPackages->SetOwner();
1326 fPackages->Add(new TObjString(pkg));
1329 //______________________________________________________________________________
1330 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1332 // Get job status for all jobs with jobid>jobidstart.
1333 static char mstatus[20];
1339 TGridJobStatusList *list = gGrid->Ps("");
1340 if (!list) return mstatus;
1341 Int_t nentries = list->GetSize();
1342 TGridJobStatus *status;
1344 for (Int_t ijob=0; ijob<nentries; ijob++) {
1345 status = (TGridJobStatus *)list->At(ijob);
1346 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1347 if (pid<jobidstart) continue;
1348 if (pid == lastid) {
1349 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1351 switch (status->GetStatus()) {
1352 case TGridJobStatus::kWAITING:
1354 case TGridJobStatus::kRUNNING:
1356 case TGridJobStatus::kABORTED:
1357 case TGridJobStatus::kFAIL:
1358 case TGridJobStatus::kUNKNOWN:
1360 case TGridJobStatus::kDONE:
1369 //______________________________________________________________________________
1370 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1372 // Returns true if file is a collection. Functionality duplicated from
1373 // TAlien::Type() because we don't want to directly depend on TAlien.
1375 Error("IsCollection", "No connection to grid");
1378 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1379 if (!res) return kFALSE;
1380 const char* typeStr = res->GetKey(0, "type");
1381 if (!typeStr || !strlen(typeStr)) return kFALSE;
1382 if (!strcmp(typeStr, "collection")) return kTRUE;
1387 //______________________________________________________________________________
1388 Bool_t AliAnalysisAlien::IsSingleOutput() const
1390 // Check if single-ouput option is on.
1391 return (!fOutputSingle.IsNull());
1394 //______________________________________________________________________________
1395 void AliAnalysisAlien::Print(Option_t *) const
1397 // Print current plugin settings.
1398 printf("### AliEn analysis plugin current settings ###\n");
1399 printf("= Production mode:______________________________ %d\n", fProductionMode);
1400 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1401 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1402 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1404 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1405 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1406 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1407 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1408 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1409 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1410 if (fRunNumbers.Length())
1411 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1413 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1414 if (!fRunRange[0] && !fRunNumbers.Length()) {
1415 TIter next(fInputFiles);
1418 while ((obj=next())) list += obj->GetName();
1419 printf("= Input files to be processed: _________________ %s\n", list.Data());
1421 if (TestBit(AliAnalysisGrid::kTest))
1422 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1423 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1424 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1425 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1426 printf("=====================================================================\n");
1427 printf("= Job price: ___________________________________ %d\n", fPrice);
1428 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1429 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1430 if (fMaxInitFailed>0)
1431 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1432 if (fMasterResubmitThreshold>0)
1433 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1434 if (fNrunsPerMaster>0)
1435 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1436 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1437 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1438 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1439 if (fArguments.Length())
1440 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1441 if (fExecutableArgs.Length())
1442 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1443 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1444 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1445 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1446 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1448 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1449 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1450 if (fIncludePath.Data())
1451 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1452 if (fCloseSE.Length())
1453 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1454 if (fFriendChainName.Length())
1455 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1457 TIter next(fPackages);
1460 while ((obj=next())) list += obj->GetName();
1461 printf("= Par files to be used: ________________________ %s\n", list.Data());
1465 //______________________________________________________________________________
1466 void AliAnalysisAlien::SetDefaults()
1468 // Set default values for everything. What cannot be filled will be left empty.
1469 if (fGridJDL) delete fGridJDL;
1470 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1471 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1474 fSplitMaxInputFileNumber = 100;
1476 fMasterResubmitThreshold = 0;
1480 fNrunsPerMaster = 1;
1481 fMaxMergeFiles = 100;
1483 fExecutable = "analysis.sh";
1484 fExecutableCommand = "root -b -q";
1486 fExecutableArgs = "";
1487 fAnalysisMacro = "myAnalysis.C";
1488 fAnalysisSource = "";
1489 fAdditionalLibs = "";
1493 fAliROOTVersion = "";
1494 fUser = ""; // Your alien user name
1495 fGridWorkingDir = "";
1496 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1497 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1498 fFriendChainName = "";
1499 fGridOutputDir = "output";
1500 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1501 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1502 fInputFormat = "xml-single";
1503 fJDLName = "analysis.jdl";
1504 fJobTag = "Automatically generated analysis JDL";
1505 fMergeExcludes = "";
1509 //______________________________________________________________________________
1510 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge)
1512 // Merge all registered outputs from basedir.
1513 TString output_file = output;
1515 TString output_chunk;
1516 TString previous_chunk = "";
1517 Int_t count_chunk = 0;
1518 Int_t count_zero = nmaxmerge;
1519 Bool_t merged = kTRUE;
1520 Int_t index = output_file.Index("@");
1521 if (index > 0) output_file.Remove(index);
1522 command = Form("find %s/ *%s", basedir, output_file.Data());
1523 printf("command: %s\n", command.Data());
1524 TGridResult *res = gGrid->Command(command);
1526 printf("Error: No result for the find command\n");
1530 TFileMerger *fm = 0;
1533 // Check if there is a merge operation to resume
1534 output_chunk = output_file;
1535 output_chunk.ReplaceAll(".root", "_*.root");
1536 // Check for existent temporary merge files
1537 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1539 // Skip as many input files as in a chunk
1540 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1542 ::Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1546 output_chunk = output_file;
1547 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1549 if (gSystem->AccessPathName(output_chunk)) continue;
1550 // Merged file with chunks up to <count_chunk> found
1551 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1552 previous_chunk = output_chunk;
1556 count_zero = nmaxmerge;
1558 while ((map=(TMap*)nextmap())) {
1559 // Loop 'find' results and get next LFN
1560 if (count_zero == nmaxmerge) {
1561 // First file in chunk - create file merger and add previous chunk if any.
1562 fm = new TFileMerger(kFALSE);
1563 fm->SetFastMethod(kTRUE);
1564 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1565 output_chunk = output_file;
1566 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1568 // If last file found, put merged results in the output file
1569 if (map == res->Last()) output_chunk = output_file;
1570 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1571 if (!objs || !objs->GetString().Length()) {
1572 // Nothing found - skip this output
1577 // Add file to be merged and decrement chunk counter.
1578 fm->AddFile(objs->GetString());
1580 if (count_zero==0 || map == res->Last()) {
1581 fm->OutputFile(output_chunk);
1582 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1583 // Nothing found - skip this output
1584 ::Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1589 // Merge the outputs, then go to next chunk
1591 ::Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1597 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1598 gSystem->Unlink(previous_chunk);
1600 if (map == res->Last()) {
1606 count_zero = nmaxmerge;
1607 previous_chunk = output_chunk;
1613 //______________________________________________________________________________
1614 Bool_t AliAnalysisAlien::MergeOutputs()
1616 // Merge analysis outputs existing in the AliEn space.
1617 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1618 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1620 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1624 if (!TestBit(AliAnalysisGrid::kMerge)) {
1625 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
1628 if (fProductionMode) {
1629 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
1632 Info("MergeOutputs", "Submitting merging JDL");
1634 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
1635 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
1638 // Get the output path
1639 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1640 if (!DirectoryExists(fGridOutputDir)) {
1641 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1644 if (!fOutputFiles.Length()) {
1645 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1648 // Check if fast read option was requested
1649 if (fFastReadOption) {
1650 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !");
1651 gEnv->SetValue("XNet.ConnectTimeout",5);
1652 gEnv->SetValue("XNet.RequestTimeout",5);
1653 gEnv->SetValue("XNet.MaxRedirectCount",2);
1654 gEnv->SetValue("XNet.ReconnectTimeout",5);
1655 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
1657 TObjArray *list = fOutputFiles.Tokenize(" ");
1660 TString output_file;
1661 Bool_t merged = kTRUE;
1662 while((str=(TObjString*)next())) {
1663 output_file = str->GetString();
1664 Int_t index = output_file.Index("@");
1665 if (index > 0) output_file.Remove(index);
1666 // Skip already merged outputs
1667 if (!gSystem->AccessPathName(output_file)) {
1668 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1671 if (fMergeExcludes.Length() &&
1672 fMergeExcludes.Contains(output_file.Data())) continue;
1673 // Perform a 'find' command in the output directory, looking for registered outputs
1674 merged = MergeOutput(output_file, fGridOutputDir, fMaxMergeFiles);
1676 Error("MergeOutputs", "Terminate() will NOT be executed");
1683 //______________________________________________________________________________
1684 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1686 // Use the output files connected to output containers from the analysis manager
1687 // rather than the files defined by SetOutputFiles
1688 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1689 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1691 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1694 //______________________________________________________________________________
1695 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1697 // Start remote grid analysis.
1699 // Check if output files have to be taken from the analysis manager
1700 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1701 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1702 if (!mgr || !mgr->IsInitialized()) {
1703 Error("StartAnalysis", "You need an initialized analysis manager for this");
1707 TIter next(mgr->GetOutputs());
1708 AliAnalysisDataContainer *output;
1709 while ((output=(AliAnalysisDataContainer*)next())) {
1710 const char *filename = output->GetFileName();
1711 if (!(strcmp(filename, "default"))) {
1712 if (!mgr->GetOutputEventHandler()) continue;
1713 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1715 if (fOutputFiles.Contains(filename)) continue;
1716 if (fOutputFiles.Length()) fOutputFiles += " ";
1717 fOutputFiles += filename;
1719 // Add extra files registered to the analysis manager
1720 if (mgr->GetExtraFiles().Length()) {
1721 if (fOutputFiles.Length()) fOutputFiles += " ";
1722 fOutputFiles += mgr->GetExtraFiles();
1725 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1726 if (TestBit(AliAnalysisGrid::kOffline)) {
1727 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1728 \n there nor any job run. You can revise the JDL and analysis \
1729 \n macro then run the same in \"submit\" mode.");
1730 } else if (TestBit(AliAnalysisGrid::kTest)) {
1731 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1733 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1734 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1735 \n space and job submitted.");
1736 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1737 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1738 if (fMergeViaJDL) CheckInputData();
1741 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1745 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1749 if (!CheckInputData()) {
1750 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1753 CreateDataset(fDataPattern);
1754 WriteAnalysisFile();
1755 WriteAnalysisMacro();
1757 WriteValidationScript();
1759 WriteMergingMacro();
1760 WriteMergeExecutable();
1761 WriteValidationScript(kTRUE);
1763 if (!CreateJDL()) return kFALSE;
1764 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1765 if (TestBit(AliAnalysisGrid::kTest)) {
1766 // Locally testing the analysis
1767 Info("StartAnalysis", "\n_______________________________________________________________________ \
1768 \n Running analysis script in a daughter shell as on a worker node \
1769 \n_______________________________________________________________________");
1770 TObjArray *list = fOutputFiles.Tokenize(" ");
1773 TString output_file;
1774 while((str=(TObjString*)next())) {
1775 output_file = str->GetString();
1776 Int_t index = output_file.Index("@");
1777 if (index > 0) output_file.Remove(index);
1778 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1781 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1782 TString validationScript = fExecutable;
1783 validationScript.ReplaceAll(".sh", "_validation.sh");
1784 gSystem->Exec(Form("bash %s",validationScript.Data()));
1785 // gSystem->Exec("cat stdout");
1788 // Check if submitting is managed by LPM manager
1789 if (fProductionMode) {
1790 TString prodfile = fJDLName;
1791 prodfile.ReplaceAll(".jdl", ".prod");
1792 WriteProductionFile(prodfile);
1793 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1796 // Submit AliEn job(s)
1797 gGrid->Cd(fGridOutputDir);
1800 if (!fRunNumbers.Length() && !fRunRange[0]) {
1801 // Submit a given xml or a set of runs
1802 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1803 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1805 const char *cjobId = res->GetKey(0,"jobId");
1807 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1810 Info("StartAnalysis", "\n_______________________________________________________________________ \
1811 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1812 \n_______________________________________________________________________",
1813 fJDLName.Data(), cjobId);
1819 // Submit for a range of enumeration of runs.
1823 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1824 \n You may exit at any time and terminate the job later using the option <terminate> \
1825 \n ##################################################################################", jobID.Data());
1826 gSystem->Exec("aliensh");
1830 //______________________________________________________________________________
1831 void AliAnalysisAlien::Submit()
1833 // Submit all master jobs.
1834 Int_t nmasterjobs = fInputFiles->GetEntries();
1835 Long_t tshoot = gSystem->Now();
1836 if (!fNsubmitted) SubmitNext();
1837 while (fNsubmitted < nmasterjobs) {
1838 Long_t now = gSystem->Now();
1839 if ((now-tshoot)>30000) {
1846 //______________________________________________________________________________
1847 void AliAnalysisAlien::SubmitMerging()
1849 // Submit all merging jobs.
1850 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1851 gGrid->Cd(fGridOutputDir);
1852 TString mergeJDLName = fExecutable;
1853 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1854 Int_t ntosubmit = fInputFiles->GetEntries();
1855 printf("### Submitting %d merging jobs...\n", ntosubmit);
1856 for (Int_t i=0; i<ntosubmit; i++) {
1858 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
1859 runOutDir.ReplaceAll(".xml", "");
1861 query = Form("submit %s %s", mergeJDLName.Data(), runOutDir.Data());
1863 query = Form("submit %s %03d", mergeJDLName.Data(), i);
1864 printf("********* %s\n",query.Data());
1865 TGridResult *res = gGrid->Command(query);
1867 const char *cjobId = res->GetKey(0,"jobId");
1869 Error("StartAnalysis", "Your JDL %s could not be submitted", mergeJDLName.Data());
1872 Info("StartAnalysis", "\n_______________________________________________________________________ \
1873 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1874 \n_______________________________________________________________________",
1875 mergeJDLName.Data(), cjobId);
1880 if (!ntosubmit) return;
1881 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
1882 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
1883 \n ##################################################################################");
1884 gSystem->Exec("aliensh");
1887 //______________________________________________________________________________
1888 void AliAnalysisAlien::SubmitNext()
1890 // Submit next bunch of master jobs if the queue is free.
1891 static Bool_t iscalled = kFALSE;
1892 static Int_t firstmaster = 0;
1893 static Int_t lastmaster = 0;
1894 static Int_t npermaster = 0;
1895 if (iscalled) return;
1897 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1898 Int_t ntosubmit = 0;
1901 if (!fNsubmitted) ntosubmit = 1;
1903 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1904 printf("=== master %d: %s\n", lastmaster, status.Data());
1905 // If last master not split, just return
1906 if (status != "SPLIT") {iscalled = kFALSE; return;}
1907 // No more than 100 waiting jobs
1908 if (nwaiting>100) {iscalled = kFALSE; return;}
1909 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1910 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1911 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1912 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1914 Int_t nmasterjobs = fInputFiles->GetEntries();
1915 for (Int_t i=0; i<ntosubmit; i++) {
1916 // Submit for a range of enumeration of runs.
1917 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1919 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
1920 runOutDir.ReplaceAll(".xml", "");
1922 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
1924 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1925 printf("********* %s\n",query.Data());
1926 res = gGrid->Command(query);
1928 TString cjobId1 = res->GetKey(0,"jobId");
1929 if (!cjobId1.Length()) {
1930 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1934 Info("StartAnalysis", "\n_______________________________________________________________________ \
1935 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1936 \n_______________________________________________________________________",
1937 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1940 lastmaster = cjobId1.Atoi();
1941 if (!firstmaster) firstmaster = lastmaster;
1950 //______________________________________________________________________________
1951 void AliAnalysisAlien::WriteAnalysisFile()
1953 // Write current analysis manager into the file <analysisFile>
1954 TString analysisFile = fExecutable;
1955 analysisFile.ReplaceAll(".sh", ".root");
1956 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1957 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1958 if (!mgr || !mgr->IsInitialized()) {
1959 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1962 // Check analysis type
1964 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1965 handler = (TObject*)mgr->GetInputEventHandler();
1967 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1968 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1970 TDirectory *cdir = gDirectory;
1971 TFile *file = TFile::Open(analysisFile, "RECREATE");
1973 // Skip task Terminate calls for the grid job
1974 mgr->SetSkipTerminate(kTRUE);
1975 // Unless merging makes no sense
1976 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
1979 // Enable termination for local jobs
1980 mgr->SetSkipTerminate(kFALSE);
1982 if (cdir) cdir->cd();
1983 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
1985 Bool_t copy = kTRUE;
1986 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1989 TString workdir = gGrid->GetHomeDirectory();
1990 workdir += fGridWorkingDir;
1991 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1992 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1993 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
1997 //______________________________________________________________________________
1998 void AliAnalysisAlien::WriteAnalysisMacro()
2000 // Write the analysis macro that will steer the analysis in grid mode.
2001 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2003 out.open(fAnalysisMacro.Data(), ios::out);
2005 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2008 Bool_t hasSTEERBase = kFALSE;
2009 Bool_t hasESD = kFALSE;
2010 Bool_t hasAOD = kFALSE;
2011 Bool_t hasANALYSIS = kFALSE;
2012 Bool_t hasANALYSISalice = kFALSE;
2013 Bool_t hasCORRFW = kFALSE;
2014 TString func = fAnalysisMacro;
2015 TString type = "ESD";
2016 TString comment = "// Analysis using ";
2017 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2018 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2022 if (type!="AOD" && fFriendChainName!="") {
2023 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2026 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2027 else comment += " data";
2028 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2029 func.ReplaceAll(".C", "");
2030 out << "void " << func.Data() << "()" << endl;
2032 out << comment.Data() << endl;
2033 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
2034 out << " TStopwatch timer;" << endl;
2035 out << " timer.Start();" << endl << endl;
2036 out << "// load base root libraries" << endl;
2037 out << " gSystem->Load(\"libTree\");" << endl;
2038 out << " gSystem->Load(\"libGeom\");" << endl;
2039 out << " gSystem->Load(\"libVMC\");" << endl;
2040 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2041 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2042 if (fAdditionalRootLibs.Length()) {
2043 // in principle libtree /lib geom libvmc etc. can go into this list, too
2044 out << "// Add aditional libraries" << endl;
2045 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2048 while((str=(TObjString*)next())) {
2049 if (str->GetString().Contains(".so"))
2050 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2052 if (list) delete list;
2054 out << "// include path" << endl;
2055 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2056 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2057 out << "// Load analysis framework libraries" << endl;
2059 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2060 out << " gSystem->Load(\"libESD\");" << endl;
2061 out << " gSystem->Load(\"libAOD\");" << endl;
2062 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2063 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2064 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2066 TIter next(fPackages);
2069 TString setupPar = "AliAnalysisAlien::SetupPar";
2070 while ((obj=next())) {
2071 pkgname = obj->GetName();
2072 if (pkgname == "STEERBase" ||
2073 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2074 if (pkgname == "ESD" ||
2075 pkgname == "ESD.par") hasESD = kTRUE;
2076 if (pkgname == "AOD" ||
2077 pkgname == "AOD.par") hasAOD = kTRUE;
2078 if (pkgname == "ANALYSIS" ||
2079 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2080 if (pkgname == "ANALYSISalice" ||
2081 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2082 if (pkgname == "CORRFW" ||
2083 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2085 if (hasANALYSISalice) setupPar = "SetupPar";
2086 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2087 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2088 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2089 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2090 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2091 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2092 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2093 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2094 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2095 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2096 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2097 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2098 out << "// Compile other par packages" << endl;
2100 while ((obj=next())) {
2101 pkgname = obj->GetName();
2102 if (pkgname == "STEERBase" ||
2103 pkgname == "STEERBase.par" ||
2105 pkgname == "ESD.par" ||
2107 pkgname == "AOD.par" ||
2108 pkgname == "ANALYSIS" ||
2109 pkgname == "ANALYSIS.par" ||
2110 pkgname == "ANALYSISalice" ||
2111 pkgname == "ANALYSISalice.par" ||
2112 pkgname == "CORRFW" ||
2113 pkgname == "CORRFW.par") continue;
2114 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2117 if (fAdditionalLibs.Length()) {
2118 out << "// Add aditional AliRoot libraries" << endl;
2119 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2122 while((str=(TObjString*)next())) {
2123 if (str->GetString().Contains(".so"))
2124 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2126 if (list) delete list;
2129 out << "// analysis source to be compiled at runtime (if any)" << endl;
2130 if (fAnalysisSource.Length()) {
2131 TObjArray *list = fAnalysisSource.Tokenize(" ");
2134 while((str=(TObjString*)next())) {
2135 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2137 if (list) delete list;
2140 if (fFastReadOption) {
2141 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. Note that this may skip some files that could be accessed !!!");
2142 out << "// fast xrootd reading enabled" << endl;
2143 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2144 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",5);" << endl;
2145 out << " gEnv->SetValue(\"XNet.RequestTimeout\",5);" << endl;
2146 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2147 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",5);" << endl;
2148 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2150 out << "// connect to AliEn and make the chain" << endl;
2151 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2152 if (IsUsingTags()) {
2153 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
2155 if(fFriendChainName!="AliAOD.VertexingHF.root") {
2156 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
2158 out << " // Check if the macro to create the chain was provided" << endl;
2159 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
2160 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
2161 out << " return;" << endl;
2162 out << " }" << endl;
2163 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
2164 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
2167 out << "// read the analysis manager from file" << endl;
2168 TString analysisFile = fExecutable;
2169 analysisFile.ReplaceAll(".sh", ".root");
2170 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2171 out << " if (!file) return;" << endl;
2172 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2173 out << " AliAnalysisManager *mgr = 0;" << endl;
2174 out << " TKey *key;" << endl;
2175 out << " while ((key=(TKey*)nextkey())) {" << endl;
2176 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2177 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2178 out << " };" << endl;
2179 out << " if (!mgr) {" << endl;
2180 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2181 out << " return;" << endl;
2182 out << " }" << endl << endl;
2183 out << " mgr->PrintStatus();" << endl;
2184 if (AliAnalysisManager::GetAnalysisManager()) {
2185 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2186 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2188 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2191 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
2192 out << " timer.Stop();" << endl;
2193 out << " timer.Print();" << endl;
2194 out << "}" << endl << endl;
2195 if (IsUsingTags()) {
2196 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
2198 out << "// Create a chain using tags from the xml file." << endl;
2199 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
2200 out << " if (!coll) {" << endl;
2201 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2202 out << " return NULL;" << endl;
2203 out << " }" << endl;
2204 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
2205 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
2206 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
2207 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
2208 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
2209 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
2210 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
2211 out << " // Check if the cuts configuration file was provided" << endl;
2212 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
2213 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
2214 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2215 out << " }" << endl;
2216 if (fFriendChainName=="") {
2217 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2219 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
2220 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
2221 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
2223 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
2224 out << " chain->ls();" << endl;
2225 out << " return chain;" << endl;
2226 out << "}" << endl << endl;
2227 if (gSystem->AccessPathName("ConfigureCuts.C")) {
2228 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
2229 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
2230 msg += " AliLHCTagCuts *lhcCuts,\n";
2231 msg += " AliDetectorTagCuts *detCuts,\n";
2232 msg += " AliEventTagCuts *evCuts)";
2233 Info("WriteAnalysisMacro", msg.Data());
2236 if (!IsUsingTags() || fFriendChainName!="") {
2237 out <<"//________________________________________________________________________________" << endl;
2238 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
2240 out << "// Create a chain using url's from xml file" << endl;
2241 out << " TString treename = type;" << endl;
2242 out << " treename.ToLower();" << endl;
2243 out << " treename += \"Tree\";" << endl;
2244 out << " printf(\"***************************************\\n\");" << endl;
2245 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
2246 out << " printf(\"***************************************\\n\");" << endl;
2247 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
2248 out << " if (!coll) {" << endl;
2249 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2250 out << " return NULL;" << endl;
2251 out << " }" << endl;
2252 out << " TChain *chain = new TChain(treename);" << endl;
2253 if(fFriendChainName!="") {
2254 out << " TChain *chainFriend = new TChain(treename);" << endl;
2256 out << " coll->Reset();" << endl;
2257 out << " while (coll->Next()) {" << endl;
2258 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2259 if(fFriendChainName!="") {
2260 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2261 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2262 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2263 out << " chainFriend->Add(fileFriend.Data());" << endl;
2265 out << " }" << endl;
2266 out << " if (!chain->GetNtrees()) {" << endl;
2267 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2268 out << " return NULL;" << endl;
2269 out << " }" << endl;
2270 if(fFriendChainName!="") {
2271 out << " chain->AddFriend(chainFriend);" << endl;
2273 out << " return chain;" << endl;
2274 out << "}" << endl << endl;
2276 if (hasANALYSISalice) {
2277 out <<"//________________________________________________________________________________" << endl;
2278 out << "Bool_t SetupPar(const char *package) {" << endl;
2279 out << "// Compile the package and set it up." << endl;
2280 out << " TString pkgdir = package;" << endl;
2281 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2282 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2283 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2284 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2285 out << " // Check for BUILD.sh and execute" << endl;
2286 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2287 out << " printf(\"*******************************\\n\");" << endl;
2288 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2289 out << " printf(\"*******************************\\n\");" << endl;
2290 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2291 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2292 out << " gSystem->ChangeDirectory(cdir);" << endl;
2293 out << " return kFALSE;" << endl;
2294 out << " }" << endl;
2295 out << " } else {" << endl;
2296 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2297 out << " gSystem->ChangeDirectory(cdir);" << endl;
2298 out << " return kFALSE;" << endl;
2299 out << " }" << endl;
2300 out << " // Check for SETUP.C and execute" << endl;
2301 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2302 out << " printf(\"*******************************\\n\");" << endl;
2303 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2304 out << " printf(\"*******************************\\n\");" << endl;
2305 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2306 out << " } else {" << endl;
2307 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2308 out << " gSystem->ChangeDirectory(cdir);" << endl;
2309 out << " return kFALSE;" << endl;
2310 out << " }" << endl;
2311 out << " // Restore original workdir" << endl;
2312 out << " gSystem->ChangeDirectory(cdir);" << endl;
2313 out << " return kTRUE;" << endl;
2316 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2318 Bool_t copy = kTRUE;
2319 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2322 TString workdir = gGrid->GetHomeDirectory();
2323 workdir += fGridWorkingDir;
2324 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2325 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2326 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2327 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2328 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2330 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2331 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2335 //______________________________________________________________________________
2336 void AliAnalysisAlien::WriteMergingMacro()
2338 // Write a macro to merge the outputs per master job.
2339 if (!fMergeViaJDL) return;
2340 if (!fOutputFiles.Length()) {
2341 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2344 TString mergingMacro = fExecutable;
2345 mergingMacro.ReplaceAll(".sh","_merge.C");
2346 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2347 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2349 out.open(mergingMacro.Data(), ios::out);
2351 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2354 Bool_t hasSTEERBase = kFALSE;
2355 Bool_t hasESD = kFALSE;
2356 Bool_t hasAOD = kFALSE;
2357 Bool_t hasANALYSIS = kFALSE;
2358 Bool_t hasANALYSISalice = kFALSE;
2359 Bool_t hasCORRFW = kFALSE;
2360 TString func = mergingMacro;
2362 func.ReplaceAll(".C", "");
2363 out << "void " << func.Data() << "(const char *dir)" << endl;
2365 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
2366 out << " TStopwatch timer;" << endl;
2367 out << " timer.Start();" << endl << endl;
2368 out << "// load base root libraries" << endl;
2369 out << " gSystem->Load(\"libTree\");" << endl;
2370 out << " gSystem->Load(\"libGeom\");" << endl;
2371 out << " gSystem->Load(\"libVMC\");" << endl;
2372 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2373 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2374 if (fAdditionalRootLibs.Length()) {
2375 // in principle libtree /lib geom libvmc etc. can go into this list, too
2376 out << "// Add aditional libraries" << endl;
2377 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2380 while((str=(TObjString*)next())) {
2381 if (str->GetString().Contains(".so"))
2382 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2384 if (list) delete list;
2386 out << "// include path" << endl;
2387 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2388 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2389 out << "// Load analysis framework libraries" << endl;
2391 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2392 out << " gSystem->Load(\"libESD\");" << endl;
2393 out << " gSystem->Load(\"libAOD\");" << endl;
2394 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2395 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2396 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2398 TIter next(fPackages);
2401 TString setupPar = "AliAnalysisAlien::SetupPar";
2402 while ((obj=next())) {
2403 pkgname = obj->GetName();
2404 if (pkgname == "STEERBase" ||
2405 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2406 if (pkgname == "ESD" ||
2407 pkgname == "ESD.par") hasESD = kTRUE;
2408 if (pkgname == "AOD" ||
2409 pkgname == "AOD.par") hasAOD = kTRUE;
2410 if (pkgname == "ANALYSIS" ||
2411 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2412 if (pkgname == "ANALYSISalice" ||
2413 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2414 if (pkgname == "CORRFW" ||
2415 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2417 if (hasANALYSISalice) setupPar = "SetupPar";
2418 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2419 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2420 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2421 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2422 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2423 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2424 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2425 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2426 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2427 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2428 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2429 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2430 out << "// Compile other par packages" << endl;
2432 while ((obj=next())) {
2433 pkgname = obj->GetName();
2434 if (pkgname == "STEERBase" ||
2435 pkgname == "STEERBase.par" ||
2437 pkgname == "ESD.par" ||
2439 pkgname == "AOD.par" ||
2440 pkgname == "ANALYSIS" ||
2441 pkgname == "ANALYSIS.par" ||
2442 pkgname == "ANALYSISalice" ||
2443 pkgname == "ANALYSISalice.par" ||
2444 pkgname == "CORRFW" ||
2445 pkgname == "CORRFW.par") continue;
2446 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2449 if (fAdditionalLibs.Length()) {
2450 out << "// Add aditional AliRoot libraries" << endl;
2451 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2454 while((str=(TObjString*)next())) {
2455 if (str->GetString().Contains(".so"))
2456 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2458 if (list) delete list;
2461 out << "// Analysis source to be compiled at runtime (if any)" << endl;
2462 if (fAnalysisSource.Length()) {
2463 TObjArray *list = fAnalysisSource.Tokenize(" ");
2466 while((str=(TObjString*)next())) {
2467 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2469 if (list) delete list;
2472 if (fFastReadOption) {
2473 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 !!!");
2474 out << "// fast xrootd reading enabled" << endl;
2475 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2476 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",5);" << endl;
2477 out << " gEnv->SetValue(\"XNet.RequestTimeout\",5);" << endl;
2478 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2479 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",5);" << endl;
2480 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2482 out << "// Connect to AliEn" << endl;
2483 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2484 out << " TString outputDir = \"" << fGridOutputDir << "/\";" << endl;
2485 out << " outputDir += dir;" << endl;
2486 out << " TString outputFiles = \"" << fOutputFiles << "\";" << endl;
2487 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
2488 out << " TObjArray *list = outputFiles.Tokenize(\" \");" << endl;
2489 out << " TIter *iter = new TIter(list);" << endl;
2490 out << " TObjString *str;" << endl;
2491 out << " TString output_file;" << endl;
2492 out << " Bool_t merged = kTRUE;" << endl;
2493 out << " while((str=(TObjString*)iter->Next())) {" << endl;
2494 out << " output_file = str->GetString();" << endl;
2495 out << " Int_t index = output_file.Index(\"@\");" << endl;
2496 out << " if (index > 0) output_file.Remove(index);" << endl;
2497 out << " // Skip already merged outputs" << endl;
2498 out << " if (!gSystem->AccessPathName(output_file)) {" << endl;
2499 out << " printf(\"Output file <%s> found. Not merging again.\",output_file.Data());" << endl;
2500 out << " continue;" << endl;
2501 out << " }" << endl;
2502 out << " if (mergeExcludes.Contains(output_file.Data())) continue;" << endl;
2503 out << " merged = AliAnalysisAlien::MergeOutput(output_file, outputDir, " << fMaxMergeFiles << ");" << endl;
2504 out << " if (!merged) {" << endl;
2505 out << " printf(\"ERROR: Cannot merge %s\\n\", output_file.Data());" << endl;
2506 out << " return;" << endl;
2507 out << " }" << endl;
2508 out << " }" << endl;
2509 out << "// read the analysis manager from file" << endl;
2510 TString analysisFile = fExecutable;
2511 analysisFile.ReplaceAll(".sh", ".root");
2512 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2513 out << " if (!file) return;" << endl;
2514 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2515 out << " AliAnalysisManager *mgr = 0;" << endl;
2516 out << " TKey *key;" << endl;
2517 out << " while ((key=(TKey*)nextkey())) {" << endl;
2518 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2519 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2520 out << " };" << endl;
2521 out << " if (!mgr) {" << endl;
2522 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2523 out << " return;" << endl;
2524 out << " }" << endl << endl;
2525 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
2526 out << " mgr->PrintStatus();" << endl;
2527 if (AliAnalysisManager::GetAnalysisManager()) {
2528 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2529 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2531 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2534 out << " mgr->StartAnalysis(\"gridterminate\");" << endl;
2535 out << "}" << endl << endl;
2536 if (hasANALYSISalice) {
2537 out <<"//________________________________________________________________________________" << endl;
2538 out << "Bool_t SetupPar(const char *package) {" << endl;
2539 out << "// Compile the package and set it up." << endl;
2540 out << " TString pkgdir = package;" << endl;
2541 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2542 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2543 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2544 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2545 out << " // Check for BUILD.sh and execute" << endl;
2546 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2547 out << " printf(\"*******************************\\n\");" << endl;
2548 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2549 out << " printf(\"*******************************\\n\");" << endl;
2550 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2551 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2552 out << " gSystem->ChangeDirectory(cdir);" << endl;
2553 out << " return kFALSE;" << endl;
2554 out << " }" << endl;
2555 out << " } else {" << endl;
2556 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2557 out << " gSystem->ChangeDirectory(cdir);" << endl;
2558 out << " return kFALSE;" << endl;
2559 out << " }" << endl;
2560 out << " // Check for SETUP.C and execute" << endl;
2561 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2562 out << " printf(\"*******************************\\n\");" << endl;
2563 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2564 out << " printf(\"*******************************\\n\");" << endl;
2565 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2566 out << " } else {" << endl;
2567 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2568 out << " gSystem->ChangeDirectory(cdir);" << endl;
2569 out << " return kFALSE;" << endl;
2570 out << " }" << endl;
2571 out << " // Restore original workdir" << endl;
2572 out << " gSystem->ChangeDirectory(cdir);" << endl;
2573 out << " return kTRUE;" << endl;
2577 Bool_t copy = kTRUE;
2578 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2581 TString workdir = gGrid->GetHomeDirectory();
2582 workdir += fGridWorkingDir;
2583 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
2584 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
2585 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
2589 //______________________________________________________________________________
2590 Bool_t AliAnalysisAlien::SetupPar(const char *package)
2592 // Compile the par file archive pointed by <package>. This must be present in the current durectory.
2593 // Note that for loading the compiled library. The current directory should have precedence in
2595 TString pkgdir = package;
2596 pkgdir.ReplaceAll(".par","");
2597 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
2598 TString cdir = gSystem->WorkingDirectory();
2599 gSystem->ChangeDirectory(pkgdir);
2600 // Check for BUILD.sh and execute
2601 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
2602 printf("**************************************************\n");
2603 printf("*** Building PAR archive %s\n", package);
2604 printf("**************************************************\n");
2605 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
2606 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
2607 gSystem->ChangeDirectory(cdir);
2611 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
2612 gSystem->ChangeDirectory(cdir);
2615 // Check for SETUP.C and execute
2616 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
2617 printf("**************************************************\n");
2618 printf("*** Setup PAR archive %s\n", package);
2619 printf("**************************************************\n");
2620 gROOT->Macro("PROOF-INF/SETUP.C");
2621 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
2623 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
2624 gSystem->ChangeDirectory(cdir);
2627 // Restore original workdir
2628 gSystem->ChangeDirectory(cdir);
2632 //______________________________________________________________________________
2633 void AliAnalysisAlien::WriteExecutable()
2635 // Generate the alien executable script.
2636 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2638 out.open(fExecutable.Data(), ios::out);
2640 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2643 out << "#!/bin/bash" << endl;
2644 out << "echo \"=========================================\"" << endl;
2645 out << "echo \"############## PATH : ##############\"" << endl;
2646 out << "echo $PATH" << endl;
2647 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2648 out << "echo $LD_LIBRARY_PATH" << endl;
2649 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2650 out << "echo $ROOTSYS" << endl;
2651 out << "echo \"############## which root : ##############\"" << endl;
2652 out << "which root" << endl;
2653 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2654 out << "echo $ALICE_ROOT" << endl;
2655 out << "echo \"############## which aliroot : ##############\"" << endl;
2656 out << "which aliroot" << endl;
2657 out << "echo \"############## system limits : ##############\"" << endl;
2658 out << "ulimit -a" << endl;
2659 out << "echo \"############## memory : ##############\"" << endl;
2660 out << "free -m" << endl;
2661 out << "echo \"=========================================\"" << endl << endl;
2662 // Make sure we can properly compile par files
2663 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2664 out << fExecutableCommand << " ";
2665 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2666 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2667 out << "echo \"############## memory after: ##############\"" << endl;
2668 out << "free -m" << endl;
2669 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2670 out << "dmesg | tail -n 10" << endl;
2672 Bool_t copy = kTRUE;
2673 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2676 TString workdir = gGrid->GetHomeDirectory();
2677 TString bindir = Form("%s/bin", workdir.Data());
2678 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2679 workdir += fGridWorkingDir;
2680 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2681 if (FileExists(executable)) gGrid->Rm(executable);
2682 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2683 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2687 //______________________________________________________________________________
2688 void AliAnalysisAlien::WriteMergeExecutable()
2690 // Generate the alien executable script for the merging job.
2691 if (!fMergeViaJDL) return;
2692 TString mergeExec = fExecutable;
2693 mergeExec.ReplaceAll(".sh", "_merge.sh");
2694 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2696 out.open(mergeExec.Data(), ios::out);
2698 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
2701 out << "#!/bin/bash" << endl;
2702 out << "echo \"=========================================\"" << endl;
2703 out << "echo \"############## PATH : ##############\"" << endl;
2704 out << "echo $PATH" << endl;
2705 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2706 out << "echo $LD_LIBRARY_PATH" << endl;
2707 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2708 out << "echo $ROOTSYS" << endl;
2709 out << "echo \"############## which root : ##############\"" << endl;
2710 out << "which root" << endl;
2711 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2712 out << "echo $ALICE_ROOT" << endl;
2713 out << "echo \"############## which aliroot : ##############\"" << endl;
2714 out << "which aliroot" << endl;
2715 out << "echo \"############## system limits : ##############\"" << endl;
2716 out << "ulimit -a" << endl;
2717 out << "echo \"############## memory : ##############\"" << endl;
2718 out << "free -m" << endl;
2719 out << "echo \"=========================================\"" << endl << endl;
2720 // Make sure we can properly compile par files
2721 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2722 TString mergeMacro = fExecutable;
2723 mergeMacro.ReplaceAll(".sh", "_merge.C");
2724 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
2725 out << fExecutableCommand << " " << "$ARG" << endl;
2726 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
2727 out << "echo \"############## memory after: ##############\"" << endl;
2728 out << "free -m" << endl;
2729 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2730 out << "dmesg | tail -n 10" << endl;
2732 Bool_t copy = kTRUE;
2733 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2736 TString workdir = gGrid->GetHomeDirectory();
2737 TString bindir = Form("%s/bin", workdir.Data());
2738 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2739 workdir += fGridWorkingDir;
2740 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
2741 if (FileExists(executable)) gGrid->Rm(executable);
2742 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
2743 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
2747 //______________________________________________________________________________
2748 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2750 // Write the production file to be submitted by LPM manager. The format is:
2751 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2752 // Next lines: full_path_to_dataset XXX (XXX is a string)
2753 // To submit, one has to: submit jdl XXX for all lines
2755 out.open(filename, ios::out);
2757 Error("WriteProductionFile", "Bad file name: %s", filename);
2760 TString workdir = gGrid->GetHomeDirectory();
2761 workdir += fGridWorkingDir;
2762 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2763 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2764 out << locjdl << " " << njobspermaster << endl;
2765 Int_t nmasterjobs = fInputFiles->GetEntries();
2766 for (Int_t i=0; i<nmasterjobs; i++) {
2767 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2768 runOutDir.ReplaceAll(".xml", "");
2770 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
2772 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2774 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2775 if (FileExists(filename)) gGrid->Rm(filename);
2776 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2779 //______________________________________________________________________________
2780 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
2782 // Generate the alien validation script.
2783 // Generate the validation script
2785 TString validationScript = fExecutable;
2786 if (merge) validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
2787 else validationScript.ReplaceAll(".sh", "_validation.sh");
2789 Error("WriteValidationScript", "Alien connection required");
2792 TString out_stream = "";
2793 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2794 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2796 out.open(validationScript, ios::out);
2797 out << "#!/bin/bash" << endl;
2798 out << "##################################################" << endl;
2799 out << "validateout=`dirname $0`" << endl;
2800 out << "validatetime=`date`" << endl;
2801 out << "validated=\"0\";" << endl;
2802 out << "error=0" << endl;
2803 out << "if [ -z $validateout ]" << endl;
2804 out << "then" << endl;
2805 out << " validateout=\".\"" << endl;
2806 out << "fi" << endl << endl;
2807 out << "cd $validateout;" << endl;
2808 out << "validateworkdir=`pwd`;" << endl << endl;
2809 out << "echo \"*******************************************************\"" << out_stream << endl;
2810 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2812 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2813 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2814 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2815 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2816 out << "ls -la ./" << out_stream << endl;
2817 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2818 out << "##################################################" << endl;
2821 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2822 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2823 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2826 out << "if [ ! -f stderr ] ; then" << endl;
2827 out << " error=1" << endl;
2828 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2829 out << " echo \"Error = $error\" " << out_stream << endl;
2830 out << "fi" << endl;
2832 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2833 out << " error=1" << endl;
2834 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2835 out << " echo \"$parArch\" " << out_stream << endl;
2836 out << " echo \"Error = $error\" " << out_stream << endl;
2837 out << "fi" << endl;
2839 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2840 out << " error=1" << endl;
2841 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2842 out << " echo \"$segViol\" " << out_stream << endl;
2843 out << " echo \"Error = $error\" " << out_stream << endl;
2844 out << "fi" << endl;
2846 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2847 out << " error=1" << endl;
2848 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2849 out << " echo \"$segFault\" " << out_stream << endl;
2850 out << " echo \"Error = $error\" " << out_stream << endl;
2851 out << "fi" << endl;
2853 // Part dedicated to the specific analyses running into the train
2855 TObjArray *arr = fOutputFiles.Tokenize(" ");
2857 TString output_file;
2858 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2859 TString extra = mgr->GetExtraFiles();
2860 while ((os=(TObjString*)next1())) {
2861 output_file = os->GetString();
2862 Int_t index = output_file.Index("@");
2863 if (index > 0) output_file.Remove(index);
2864 if (merge && fMergeExcludes.Contains(output_file)) continue;
2865 if (extra.Contains(output_file)) continue;
2866 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2867 out << " error=1" << endl;
2868 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2869 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2870 out << "fi" << endl;
2874 out << "if ! [ -f outputs_valid ] ; then" << endl;
2875 out << " error=1" << endl;
2876 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2877 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2878 out << "fi" << endl;
2881 out << "if [ $error = 0 ] ; then" << endl;
2882 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2883 out << "fi" << endl;
2885 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2886 out << "echo \"*******************************************************\"" << out_stream << endl;
2887 out << "cd -" << endl;
2888 out << "exit $error" << endl;
2890 Bool_t copy = kTRUE;
2891 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2894 TString workdir = gGrid->GetHomeDirectory();
2895 workdir += fGridWorkingDir;
2896 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2897 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2898 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));