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;
362 Info("Connect", "Trying to connect to AliEn ...");
363 TGrid::Connect("alien://");
365 if (!gGrid || !gGrid->IsConnected()) {
366 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
369 fUser = gGrid->GetUser();
370 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
374 //______________________________________________________________________________
375 void AliAnalysisAlien::CdWork()
377 // Check validity of alien workspace. Create directory if possible.
379 Error("CdWork", "Alien connection required");
382 TString homedir = gGrid->GetHomeDirectory();
383 TString workdir = homedir + fGridWorkingDir;
384 if (DirectoryExists(workdir)) {
388 // Work directory not existing - create it
390 if (gGrid->Mkdir(workdir)) {
391 gGrid->Cd(fGridWorkingDir);
392 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
394 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
395 workdir.Data(), homedir.Data());
396 fGridWorkingDir = "";
400 //______________________________________________________________________________
401 Bool_t AliAnalysisAlien::CheckFileCopy(const char *alienpath)
403 // Check if file copying is possible.
405 Error("CheckFileCopy", "Not connected to AliEn. File copying cannot be tested.");
408 Info("CheckFileCopy", "Checking possibility to copy files to your AliEn home directory... \
409 \n +++ NOTE: You can disable this via: plugin->SetCheckCopy(kFALSE);");
410 // Check if alien_CLOSE_SE is defined
411 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
412 if (!closeSE.IsNull()) {
413 Info("CheckFileCopy", "Your current close storage is pointing to: \
414 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
416 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
418 // Check if grid directory exists.
419 if (!DirectoryExists(alienpath)) {
420 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
423 TFile f("plugin_test_copy", "RECREATE");
424 // User may not have write permissions to current directory
426 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
427 gSystem->WorkingDirectory());
431 if (FileExists(Form("alien://%s/%s",alienpath, f.GetName()))) gGrid->Rm(Form("alien://%s/%s",alienpath, f.GetName()));
432 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, f.GetName()))) {
433 Error("CheckFileCopy", "Cannot copy files to Alien destination: <%s> This may be temporary, or: \
434 \n# 1. Make sure you have write permissions there. If this is the case: \
435 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
436 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
437 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
438 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
439 gSystem->Unlink(f.GetName());
442 gSystem->Unlink(f.GetName());
443 gGrid->Rm(Form("%s%s",alienpath,f.GetName()));
444 Info("CheckFileCopy", "### ...SUCCESS ###");
448 //______________________________________________________________________________
449 Bool_t AliAnalysisAlien::CheckInputData()
451 // Check validity of input data. If necessary, create xml files.
452 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
453 if (!fGridDataDir.Length()) {
454 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
457 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
460 // Process declared files
461 Bool_t is_collection = kFALSE;
462 Bool_t is_xml = kFALSE;
463 Bool_t use_tags = kFALSE;
464 Bool_t checked = kFALSE;
467 TString workdir = gGrid->GetHomeDirectory();
468 workdir += fGridWorkingDir;
471 TIter next(fInputFiles);
472 while ((objstr=(TObjString*)next())) {
475 file += objstr->GetString();
476 // Store full lfn path
477 if (FileExists(file)) objstr->SetString(file);
479 file = objstr->GetName();
480 if (!FileExists(objstr->GetName())) {
481 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
482 objstr->GetName(), workdir.Data());
486 Bool_t iscoll, isxml, usetags;
487 CheckDataType(file, iscoll, isxml, usetags);
490 is_collection = iscoll;
493 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
495 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
496 Error("CheckInputData", "Some conflict was found in the types of inputs");
502 // Process requested run numbers
503 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
504 // Check validity of alien data directory
505 if (!fGridDataDir.Length()) {
506 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
509 if (!DirectoryExists(fGridDataDir)) {
510 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
514 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
518 if (checked && !is_xml) {
519 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
522 // Check validity of run number(s)
526 TString schunk, schunk2;
530 use_tags = fDataPattern.Contains("tag");
531 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
533 if (use_tags != fDataPattern.Contains("tag")) {
534 Error("CheckInputData", "Cannot mix input files using/not using tags");
537 if (fRunNumbers.Length()) {
538 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
539 arr = fRunNumbers.Tokenize(" ");
541 while ((os=(TObjString*)next())) {
542 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
543 if (!DirectoryExists(path)) {
544 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
547 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
548 TString msg = "\n##### file: ";
550 msg += " type: xml_collection;";
551 if (use_tags) msg += " using_tags: Yes";
552 else msg += " using_tags: No";
553 Info("CheckDataType", msg.Data());
554 if (fNrunsPerMaster<2) {
555 AddDataFile(Form("%s.xml", os->GetString().Data()));
558 if (((nruns-1)%fNrunsPerMaster) == 0) {
559 schunk = os->GetString();
561 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
562 schunk += Form("_%s.xml", os->GetString().Data());
568 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
569 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
570 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
571 if (!DirectoryExists(path)) {
572 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
575 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
576 TString msg = "\n##### file: ";
578 msg += " type: xml_collection;";
579 if (use_tags) msg += " using_tags: Yes";
580 else msg += " using_tags: No";
581 Info("CheckDataType", msg.Data());
582 if (fNrunsPerMaster<2) {
583 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
586 if (((nruns-1)%fNrunsPerMaster) == 0) {
587 schunk = Form("%s%d", fRunPrefix.Data(),irun);
589 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
590 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
603 //______________________________________________________________________________
604 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
606 // Create dataset for the grid data directory + run number.
607 if (TestBit(AliAnalysisGrid::kOffline)) return kTRUE;
609 Error("CreateDataset", "Cannot create dataset with no grid connection");
615 TString workdir = gGrid->GetHomeDirectory();
616 workdir += fGridWorkingDir;
618 // Compose the 'find' command arguments
620 TString options = "-x collection ";
621 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
622 TString conditions = "";
627 TString schunk, schunk2;
628 TGridCollection *cbase=0, *cadd=0;
629 if (!fRunNumbers.Length() && !fRunRange[0]) {
630 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
631 // Make a single data collection from data directory.
633 if (!DirectoryExists(path)) {
634 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
638 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
639 else file = Form("%s.xml", gSystem->BaseName(path));
640 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
646 command += conditions;
647 printf("command: %s\n", command.Data());
648 TGridResult *res = gGrid->Command(command);
650 // Write standard output to file
651 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
652 Bool_t has_grep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
653 Bool_t null_file = kFALSE;
655 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
657 null_file = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
659 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
664 Bool_t fileExists = FileExists(file);
665 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
666 // Copy xml file to alien space
667 if (fileExists) gGrid->Rm(file);
668 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
669 if (!FileExists(file)) {
670 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
673 // Update list of files to be processed.
675 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
679 Bool_t null_result = kTRUE;
680 if (fRunNumbers.Length()) {
681 TObjArray *arr = fRunNumbers.Tokenize(" ");
684 while ((os=(TObjString*)next())) {
685 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
686 if (!DirectoryExists(path)) continue;
688 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
689 else file = Form("%s.xml", os->GetString().Data());
690 // If local collection file does not exist, create it via 'find' command.
691 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
696 command += conditions;
697 TGridResult *res = gGrid->Command(command);
699 // Write standard output to file
700 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
701 Bool_t has_grep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
702 Bool_t null_file = kFALSE;
704 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
706 null_file = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
708 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
709 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
713 null_result = kFALSE;
715 if (TestBit(AliAnalysisGrid::kTest)) break;
716 // Check if there is one run per master job.
717 if (fNrunsPerMaster<2) {
718 if (FileExists(file)) {
719 if (fOverwriteMode) gGrid->Rm(file);
721 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
725 // Copy xml file to alien space
726 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
727 if (!FileExists(file)) {
728 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
734 if (((nruns-1)%fNrunsPerMaster) == 0) {
735 schunk = os->GetString();
736 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
738 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
739 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
743 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
746 schunk += Form("_%s.xml", os->GetString().Data());
747 if (FileExists(schunk)) {
748 if (fOverwriteMode) gGrid->Rm(file);
750 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
754 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
755 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
756 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
757 if (!FileExists(schunk)) {
758 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
766 Error("CreateDataset", "No valid dataset corresponding to the query!");
770 // Process a full run range.
771 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
772 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
773 if (!DirectoryExists(path)) continue;
775 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
776 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
777 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
778 if (fOverwriteMode) gGrid->Rm(file);
780 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
784 // If local collection file does not exist, create it via 'find' command.
785 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
790 command += conditions;
791 TGridResult *res = gGrid->Command(command);
793 // Write standard output to file
794 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
795 Bool_t has_grep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
796 Bool_t null_file = kFALSE;
798 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
800 null_file = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
802 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
806 null_result = kFALSE;
808 if (TestBit(AliAnalysisGrid::kTest)) break;
809 // Check if there is one run per master job.
810 if (fNrunsPerMaster<2) {
811 if (FileExists(file)) {
812 if (fOverwriteMode) gGrid->Rm(file);
814 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
818 // Copy xml file to alien space
819 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
820 if (!FileExists(file)) {
821 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
826 // Check if the collection for the chunk exist locally.
827 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
828 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
829 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
832 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
833 if (((nruns-1)%fNrunsPerMaster) == 0) {
834 schunk = Form("%s%d", fRunPrefix.Data(), irun);
835 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
837 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
841 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
842 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
846 if (FileExists(schunk)) {
847 if (fOverwriteMode) gGrid->Rm(schunk);
849 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
853 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
854 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
855 if (FileExists(schunk)) {
856 if (fOverwriteMode) gGrid->Rm(schunk);
858 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
862 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
863 if (!FileExists(schunk)) {
864 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
870 Error("CreateDataset", "No valid dataset corresponding to the query!");
877 //______________________________________________________________________________
878 Bool_t AliAnalysisAlien::CreateJDL()
880 // Generate a JDL file according to current settings. The name of the file is
881 // specified by fJDLName.
882 Bool_t error = kFALSE;
885 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
886 Bool_t generate = kTRUE;
887 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
889 Error("CreateJDL", "Alien connection required");
892 // Check validity of alien workspace
894 TString workdir = gGrid->GetHomeDirectory();
895 workdir += fGridWorkingDir;
899 Error("CreateJDL()", "Define some input files for your analysis.");
902 // Compose list of input files
903 // Check if output files were defined
904 if (!fOutputFiles.Length()) {
905 Error("CreateJDL", "You must define at least one output file");
908 // Check if an output directory was defined and valid
909 if (!fGridOutputDir.Length()) {
910 Error("CreateJDL", "You must define AliEn output directory");
913 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
914 if (!DirectoryExists(fGridOutputDir)) {
915 if (gGrid->Mkdir(fGridOutputDir)) {
916 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
918 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
924 // Exit if any error up to now
925 if (error) return kFALSE;
927 if (!fUser.IsNull()) {
928 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
929 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
931 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
932 TString mergeExec = fExecutable;
933 mergeExec.ReplaceAll(".sh", "_merge.sh");
934 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
935 mergeExec.ReplaceAll(".sh", ".C");
936 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
937 if (!fArguments.IsNull())
938 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
939 fMergingJDL->SetArguments("$1");
940 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
941 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
942 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
943 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
945 if (fMaxInitFailed > 0) {
946 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
947 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
949 if (fSplitMaxInputFileNumber > 0) {
950 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
951 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
953 if (fSplitMode.Length()) {
954 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
955 fGridJDL->SetDescription("Split", "We split per SE or file");
957 if (!fAliROOTVersion.IsNull()) {
958 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
959 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
961 if (!fROOTVersion.IsNull()) {
962 fGridJDL->AddToPackages("ROOT", fROOTVersion);
963 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
965 if (!fAPIVersion.IsNull()) {
966 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
967 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
969 if (!fExternalPackages.IsNull()) {
970 arr = fExternalPackages.Tokenize(" ");
972 while ((os=(TObjString*)next())) {
973 TString pkgname = os->GetString();
974 Int_t index = pkgname.Index("::");
975 TString pkgversion = pkgname(index+2, pkgname.Length());
976 pkgname.Remove(index);
977 fGridJDL->AddToPackages(pkgname, pkgversion);
978 fMergingJDL->AddToPackages(pkgname, pkgversion);
982 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
983 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
984 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
985 TString analysisFile = fExecutable;
986 analysisFile.ReplaceAll(".sh", ".root");
987 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
988 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
989 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
990 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
991 if (fAdditionalLibs.Length()) {
992 arr = fAdditionalLibs.Tokenize(" ");
994 while ((os=(TObjString*)next())) {
995 if (os->GetString().Contains(".so")) continue;
996 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
997 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
1002 TIter next(fPackages);
1004 while ((obj=next())) {
1005 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1006 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1009 if (fOutputArchive.Length()) {
1010 arr = fOutputArchive.Tokenize(" ");
1012 Bool_t first = kTRUE;
1013 const char *comment = "Files to be archived";
1014 const char *comment1 = comment;
1015 while ((os=(TObjString*)next())) {
1016 if (!first) comment = NULL;
1017 if (!os->GetString().Contains("@") && fCloseSE.Length())
1018 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1020 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1024 TString outputArchive = fOutputArchive;
1025 if (!fMergeExcludes.IsNull()) {
1026 arr = fMergeExcludes.Tokenize(" ");
1028 while ((os=(TObjString*)next1())) {
1029 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1030 outputArchive.ReplaceAll(os->GetString(),"");
1034 arr = outputArchive.Tokenize(" ");
1038 while ((os=(TObjString*)next2())) {
1039 if (!first) comment = NULL;
1040 if (!os->GetString().Contains("@") && fCloseSE.Length())
1041 fMergingJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1043 fMergingJDL->AddToOutputArchive(os->GetString(), comment);
1048 arr = fOutputFiles.Tokenize(" ");
1050 Bool_t first = kTRUE;
1051 const char *comment = "Files to be archived";
1052 const char *comment1 = comment;
1053 while ((os=(TObjString*)next())) {
1054 // Ignore ouputs in jdl that are also in outputarchive
1055 TString sout = os->GetString();
1056 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1057 if (fOutputArchive.Contains(sout)) continue;
1058 if (!first) comment = NULL;
1059 if (!os->GetString().Contains("@") && fCloseSE.Length())
1060 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1062 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1066 if (fOutputFiles.Length()) {
1067 TString outputFiles = fOutputFiles;
1068 if (!fMergeExcludes.IsNull()) {
1069 arr = fMergeExcludes.Tokenize(" ");
1071 while ((os=(TObjString*)next1())) {
1072 outputFiles.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1073 outputFiles.ReplaceAll(os->GetString(),"");
1077 arr = outputFiles.Tokenize(" ");
1081 while ((os=(TObjString*)next2())) {
1082 // Ignore ouputs in jdl that are also in outputarchive
1083 TString sout = os->GetString();
1084 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1085 if (fOutputArchive.Contains(sout)) continue;
1086 if (!first) comment = NULL;
1087 if (!os->GetString().Contains("@") && fCloseSE.Length())
1088 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1090 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1094 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1095 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1096 TString validationScript = fExecutable;
1097 validationScript.ReplaceAll(".sh", "_validation.sh");
1098 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1099 validationScript = fExecutable;
1100 validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
1101 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1102 if (fMasterResubmitThreshold) {
1103 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1104 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1106 // Write a jdl with 2 input parameters: collection name and output dir name.
1109 // Copy jdl to grid workspace
1111 // Check if an output directory was defined and valid
1112 if (!fGridOutputDir.Length()) {
1113 Error("CreateJDL", "You must define AliEn output directory");
1116 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1117 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1118 if (gGrid->Mkdir(fGridOutputDir)) {
1119 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1121 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1127 if (TestBit(AliAnalysisGrid::kSubmit)) {
1128 TString mergeJDLName = fExecutable;
1129 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1130 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1131 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1132 if (fProductionMode) {
1133 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1134 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1136 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1137 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1138 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1139 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1141 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1142 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1145 if (fAdditionalLibs.Length()) {
1146 arr = fAdditionalLibs.Tokenize(" ");
1149 while ((os=(TObjString*)next())) {
1150 if (os->GetString().Contains(".so")) continue;
1151 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1152 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1153 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1158 TIter next(fPackages);
1160 while ((obj=next())) {
1161 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1162 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1163 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1170 //______________________________________________________________________________
1171 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1173 // Writes one or more JDL's corresponding to findex. If findex is negative,
1174 // all run numbers are considered in one go (jdl). For non-negative indices
1175 // they correspond to the indices in the array fInputFiles.
1176 if (!fInputFiles) return kFALSE;
1178 TString workdir = gGrid->GetHomeDirectory();
1179 workdir += fGridWorkingDir;
1181 if (!fRunNumbers.Length() && !fRunRange[0]) {
1182 // One jdl with no parameters in case input data is specified by name.
1183 TIter next(fInputFiles);
1184 while ((os=(TObjString*)next()))
1185 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()), "Input xml collections");
1186 if (!fOutputSingle.IsNull())
1187 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1189 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1190 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1193 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1194 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1195 if (!fOutputSingle.IsNull()) {
1196 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1197 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1199 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1200 fMergingJDL->SetOutputDirectory(Form("%s/$1", fGridOutputDir.Data()), "Output directory");
1205 // Generate the JDL as a string
1206 TString sjdl = fGridJDL->Generate();
1207 TString sjdl1 = fMergingJDL->Generate();
1209 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1210 sjdl.ReplaceAll("(member", "\n (member");
1211 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1212 sjdl.ReplaceAll("{", "{\n ");
1213 sjdl.ReplaceAll("};", "\n};");
1214 sjdl.ReplaceAll("{\n \n", "{\n");
1215 sjdl.ReplaceAll("\n\n", "\n");
1216 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1217 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1218 sjdl1.ReplaceAll("(member", "\n (member");
1219 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1220 sjdl1.ReplaceAll("{", "{\n ");
1221 sjdl1.ReplaceAll("};", "\n};");
1222 sjdl1.ReplaceAll("{\n \n", "{\n");
1223 sjdl1.ReplaceAll("\n\n", "\n");
1224 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1225 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1226 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1227 index = sjdl.Index("JDLVariables");
1228 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1229 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1230 sjdl1.Prepend(Form("Jobtag = {\n \"comment:Merging_%s\"\n};\n", fJobTag.Data()));
1231 index = sjdl1.Index("JDLVariables");
1232 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1233 // Write jdl to file
1235 out.open(fJDLName.Data(), ios::out);
1237 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1240 out << sjdl << endl;
1241 TString mergeJDLName = fExecutable;
1242 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1245 out1.open(mergeJDLName.Data(), ios::out);
1247 Error("CreateJDL", "Bad file name: %s", mergeJDLName.Data());
1250 out1 << sjdl1 << endl;
1253 // Copy jdl to grid workspace
1255 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1257 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1258 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1259 if (fProductionMode) {
1260 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1261 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1263 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1264 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1265 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1266 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1268 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1269 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1275 //______________________________________________________________________________
1276 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1278 // Returns true if file exists.
1279 if (!gGrid) return kFALSE;
1280 TGridResult *res = gGrid->Ls(lfn);
1281 if (!res) return kFALSE;
1282 TMap *map = dynamic_cast<TMap*>(res->At(0));
1287 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1288 if (!objs || !objs->GetString().Length()) {
1296 //______________________________________________________________________________
1297 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1299 // Returns true if directory exists. Can be also a path.
1300 if (!gGrid) return kFALSE;
1301 // Check if dirname is a path
1302 TString dirstripped = dirname;
1303 dirstripped = dirstripped.Strip();
1304 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1305 TString dir = gSystem->BaseName(dirstripped);
1307 TString path = gSystem->DirName(dirstripped);
1308 TGridResult *res = gGrid->Ls(path, "-F");
1309 if (!res) return kFALSE;
1313 while ((map=dynamic_cast<TMap*>(next()))) {
1314 obj = map->GetValue("name");
1316 if (dir == obj->GetName()) {
1325 //______________________________________________________________________________
1326 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1328 // Check input data type.
1329 is_collection = kFALSE;
1333 Error("CheckDataType", "No connection to grid");
1336 is_collection = IsCollection(lfn);
1337 TString msg = "\n##### file: ";
1339 if (is_collection) {
1340 msg += " type: raw_collection;";
1341 // special treatment for collections
1343 // check for tag files in the collection
1344 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1346 msg += " using_tags: No (unknown)";
1347 Info("CheckDataType", msg.Data());
1350 const char* typeStr = res->GetKey(0, "origLFN");
1351 if (!typeStr || !strlen(typeStr)) {
1352 msg += " using_tags: No (unknown)";
1353 Info("CheckDataType", msg.Data());
1356 TString file = typeStr;
1357 use_tags = file.Contains(".tag");
1358 if (use_tags) msg += " using_tags: Yes";
1359 else msg += " using_tags: No";
1360 Info("CheckDataType", msg.Data());
1365 is_xml = slfn.Contains(".xml");
1367 // Open xml collection and check if there are tag files inside
1368 msg += " type: xml_collection;";
1369 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1371 msg += " using_tags: No (unknown)";
1372 Info("CheckDataType", msg.Data());
1375 TMap *map = coll->Next();
1377 msg += " using_tags: No (unknown)";
1378 Info("CheckDataType", msg.Data());
1381 map = (TMap*)map->GetValue("");
1383 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1384 use_tags = file.Contains(".tag");
1386 if (use_tags) msg += " using_tags: Yes";
1387 else msg += " using_tags: No";
1388 Info("CheckDataType", msg.Data());
1391 use_tags = slfn.Contains(".tag");
1392 if (slfn.Contains(".root")) msg += " type: root file;";
1393 else msg += " type: unknown file;";
1394 if (use_tags) msg += " using_tags: Yes";
1395 else msg += " using_tags: No";
1396 Info("CheckDataType", msg.Data());
1399 //______________________________________________________________________________
1400 void AliAnalysisAlien::EnablePackage(const char *package)
1402 // Enables a par file supposed to exist in the current directory.
1403 TString pkg(package);
1404 pkg.ReplaceAll(".par", "");
1406 if (gSystem->AccessPathName(pkg)) {
1407 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1410 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1411 Info("EnablePackage", "AliEn plugin will use .par packages");
1412 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1414 fPackages = new TObjArray();
1415 fPackages->SetOwner();
1417 fPackages->Add(new TObjString(pkg));
1420 //______________________________________________________________________________
1421 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1423 // Get job status for all jobs with jobid>jobidstart.
1424 static char mstatus[20];
1430 TGridJobStatusList *list = gGrid->Ps("");
1431 if (!list) return mstatus;
1432 Int_t nentries = list->GetSize();
1433 TGridJobStatus *status;
1435 for (Int_t ijob=0; ijob<nentries; ijob++) {
1436 status = (TGridJobStatus *)list->At(ijob);
1437 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1438 if (pid<jobidstart) continue;
1439 if (pid == lastid) {
1440 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1442 switch (status->GetStatus()) {
1443 case TGridJobStatus::kWAITING:
1445 case TGridJobStatus::kRUNNING:
1447 case TGridJobStatus::kABORTED:
1448 case TGridJobStatus::kFAIL:
1449 case TGridJobStatus::kUNKNOWN:
1451 case TGridJobStatus::kDONE:
1460 //______________________________________________________________________________
1461 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1463 // Returns true if file is a collection. Functionality duplicated from
1464 // TAlien::Type() because we don't want to directly depend on TAlien.
1466 Error("IsCollection", "No connection to grid");
1469 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1470 if (!res) return kFALSE;
1471 const char* typeStr = res->GetKey(0, "type");
1472 if (!typeStr || !strlen(typeStr)) return kFALSE;
1473 if (!strcmp(typeStr, "collection")) return kTRUE;
1478 //______________________________________________________________________________
1479 Bool_t AliAnalysisAlien::IsSingleOutput() const
1481 // Check if single-ouput option is on.
1482 return (!fOutputSingle.IsNull());
1485 //______________________________________________________________________________
1486 void AliAnalysisAlien::Print(Option_t *) const
1488 // Print current plugin settings.
1489 printf("### AliEn analysis plugin current settings ###\n");
1490 printf("= OverwriteMode:________________________________ %d\n", fOverwriteMode);
1491 if (fOverwriteMode) {
1492 printf("***** NOTE: Overwrite mode will overwrite the input generated datasets and partial results from previous analysis. \
1493 \n***** To disable, use: plugin->SetOverwriteMode(kFALSE);\n");
1495 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1496 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1497 printf("= Production mode:______________________________ %d\n", fProductionMode);
1498 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1499 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1500 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1502 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1503 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1504 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1505 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1506 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1507 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1508 if (fRunNumbers.Length())
1509 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1511 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1512 if (!fRunRange[0] && !fRunNumbers.Length()) {
1513 TIter next(fInputFiles);
1516 while ((obj=next())) list += obj->GetName();
1517 printf("= Input files to be processed: _________________ %s\n", list.Data());
1519 if (TestBit(AliAnalysisGrid::kTest))
1520 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1521 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1522 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1523 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1524 printf("=====================================================================\n");
1525 printf("= Job price: ___________________________________ %d\n", fPrice);
1526 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1527 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1528 if (fMaxInitFailed>0)
1529 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1530 if (fMasterResubmitThreshold>0)
1531 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1532 if (fNrunsPerMaster>0)
1533 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1534 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1535 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1536 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1537 if (fArguments.Length())
1538 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1539 if (fExecutableArgs.Length())
1540 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1541 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1542 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1543 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1544 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1546 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1547 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1548 if (fIncludePath.Data())
1549 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1550 if (fCloseSE.Length())
1551 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1552 if (fFriendChainName.Length())
1553 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1555 TIter next(fPackages);
1558 while ((obj=next())) list += obj->GetName();
1559 printf("= Par files to be used: ________________________ %s\n", list.Data());
1563 //______________________________________________________________________________
1564 void AliAnalysisAlien::SetDefaults()
1566 // Set default values for everything. What cannot be filled will be left empty.
1567 if (fGridJDL) delete fGridJDL;
1568 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1569 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1572 fSplitMaxInputFileNumber = 100;
1574 fMasterResubmitThreshold = 0;
1578 fNrunsPerMaster = 1;
1579 fMaxMergeFiles = 100;
1581 fExecutable = "analysis.sh";
1582 fExecutableCommand = "root -b -q";
1584 fExecutableArgs = "";
1585 fAnalysisMacro = "myAnalysis.C";
1586 fAnalysisSource = "";
1587 fAdditionalLibs = "";
1591 fAliROOTVersion = "";
1592 fUser = ""; // Your alien user name
1593 fGridWorkingDir = "";
1594 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1595 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1596 fFriendChainName = "";
1597 fGridOutputDir = "output";
1598 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1599 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1600 fInputFormat = "xml-single";
1601 fJDLName = "analysis.jdl";
1602 fJobTag = "Automatically generated analysis JDL";
1603 fMergeExcludes = "";
1606 SetCheckCopy(kTRUE);
1610 //______________________________________________________________________________
1611 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge)
1613 // Merge all registered outputs from basedir.
1614 TString output_file = output;
1616 TString output_chunk;
1617 TString previous_chunk = "";
1618 Int_t count_chunk = 0;
1619 Int_t count_zero = nmaxmerge;
1620 Bool_t merged = kTRUE;
1621 Int_t index = output_file.Index("@");
1622 if (index > 0) output_file.Remove(index);
1623 command = Form("find %s/ *%s", basedir, output_file.Data());
1624 printf("command: %s\n", command.Data());
1625 TGridResult *res = gGrid->Command(command);
1627 printf("Error: No result for the find command\n");
1631 TFileMerger *fm = 0;
1634 // Check if there is a merge operation to resume
1635 output_chunk = output_file;
1636 output_chunk.ReplaceAll(".root", "_*.root");
1637 // Check for existent temporary merge files
1638 // Check overwrite mode and remove previous partial results if needed
1639 if (!gSystem->Exec(Form("ls %s 2>/dev/null", output_chunk.Data()))) {
1641 // Skip as many input files as in a chunk
1642 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1644 ::Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1648 output_chunk = output_file;
1649 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1651 if (gSystem->AccessPathName(output_chunk)) continue;
1652 // Merged file with chunks up to <count_chunk> found
1653 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1654 previous_chunk = output_chunk;
1658 count_zero = nmaxmerge;
1660 while ((map=(TMap*)nextmap())) {
1661 // Loop 'find' results and get next LFN
1662 if (count_zero == nmaxmerge) {
1663 // First file in chunk - create file merger and add previous chunk if any.
1664 fm = new TFileMerger(kFALSE);
1665 fm->SetFastMethod(kTRUE);
1666 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1667 output_chunk = output_file;
1668 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1670 // If last file found, put merged results in the output file
1671 if (map == res->Last()) output_chunk = output_file;
1672 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1673 if (!objs || !objs->GetString().Length()) {
1674 // Nothing found - skip this output
1679 // Add file to be merged and decrement chunk counter.
1680 fm->AddFile(objs->GetString());
1682 if (count_zero==0 || map == res->Last()) {
1683 fm->OutputFile(output_chunk);
1684 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1685 // Nothing found - skip this output
1686 ::Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1691 // Merge the outputs, then go to next chunk
1693 ::Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1699 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1700 gSystem->Unlink(previous_chunk);
1702 if (map == res->Last()) {
1708 count_zero = nmaxmerge;
1709 previous_chunk = output_chunk;
1715 //______________________________________________________________________________
1716 Bool_t AliAnalysisAlien::MergeOutputs()
1718 // Merge analysis outputs existing in the AliEn space.
1719 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1720 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1722 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1726 if (!TestBit(AliAnalysisGrid::kMerge)) {
1727 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
1730 if (fProductionMode) {
1731 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
1734 Info("MergeOutputs", "Submitting merging JDL");
1735 if (!SubmitMerging()) return kFALSE;
1736 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
1737 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
1740 // Get the output path
1741 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1742 if (!DirectoryExists(fGridOutputDir)) {
1743 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1746 if (!fOutputFiles.Length()) {
1747 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1750 // Check if fast read option was requested
1751 Info("MergeOutputs", "Started local merging of output files from: alien://%s \
1752 \n======= overwrite mode = %d", fGridOutputDir.Data(), (Int_t)fOverwriteMode);
1753 if (fFastReadOption) {
1754 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
1755 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
1756 gEnv->SetValue("XNet.ConnectTimeout",10);
1757 gEnv->SetValue("XNet.RequestTimeout",10);
1758 gEnv->SetValue("XNet.MaxRedirectCount",2);
1759 gEnv->SetValue("XNet.ReconnectTimeout",10);
1760 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
1762 TObjArray *list = fOutputFiles.Tokenize(" ");
1765 TString output_file;
1766 Bool_t merged = kTRUE;
1767 while((str=(TObjString*)next())) {
1768 output_file = str->GetString();
1769 Int_t index = output_file.Index("@");
1770 if (index > 0) output_file.Remove(index);
1771 TString output_chunk = output_file;
1772 output_chunk.ReplaceAll(".root", "_*.root");
1773 // Skip already merged outputs
1774 if (!gSystem->AccessPathName(output_file)) {
1775 if (fOverwriteMode) {
1776 Info("MergeOutputs", "Overwrite mode. Existing file %s was deleted.", output_file.Data());
1777 gSystem->Unlink(output_file);
1778 if (!gSystem->Exec(Form("ls %s 2>/dev/null", output_chunk.Data()))) {
1779 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
1780 output_chunk.Data());
1781 gSystem->Exec(Form("rm -f %s", output_chunk.Data()));
1784 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1788 if (!gSystem->Exec(Form("ls %s 2>/dev/null", output_chunk.Data()))) {
1789 Info("MergeOutput", "Overwrite mode: partial merged files %s will removed",
1790 output_chunk.Data());
1791 gSystem->Exec(Form("rm -f %s", output_chunk.Data()));
1794 if (fMergeExcludes.Length() &&
1795 fMergeExcludes.Contains(output_file.Data())) continue;
1796 // Perform a 'find' command in the output directory, looking for registered outputs
1797 merged = MergeOutput(output_file, fGridOutputDir, fMaxMergeFiles);
1799 Error("MergeOutputs", "Terminate() will NOT be executed");
1806 //______________________________________________________________________________
1807 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1809 // Use the output files connected to output containers from the analysis manager
1810 // rather than the files defined by SetOutputFiles
1811 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1812 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1814 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1817 //______________________________________________________________________________
1818 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1820 // Start remote grid analysis.
1822 // Check if output files have to be taken from the analysis manager
1823 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1824 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1825 if (!mgr || !mgr->IsInitialized()) {
1826 Error("StartAnalysis", "You need an initialized analysis manager for this");
1830 TIter next(mgr->GetOutputs());
1831 AliAnalysisDataContainer *output;
1832 while ((output=(AliAnalysisDataContainer*)next())) {
1833 const char *filename = output->GetFileName();
1834 if (!(strcmp(filename, "default"))) {
1835 if (!mgr->GetOutputEventHandler()) continue;
1836 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1838 if (fOutputFiles.Contains(filename)) continue;
1839 if (fOutputFiles.Length()) fOutputFiles += " ";
1840 fOutputFiles += filename;
1842 // Add extra files registered to the analysis manager
1843 if (mgr->GetExtraFiles().Length()) {
1844 if (fOutputFiles.Length()) fOutputFiles += " ";
1845 fOutputFiles += mgr->GetExtraFiles();
1848 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1849 if (TestBit(AliAnalysisGrid::kOffline)) {
1850 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1851 \n there nor any job run. You can revise the JDL and analysis \
1852 \n macro then run the same in \"submit\" mode.");
1853 } else if (TestBit(AliAnalysisGrid::kTest)) {
1854 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1856 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1857 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1858 \n space and job submitted.");
1859 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1860 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1861 if (fMergeViaJDL) CheckInputData();
1864 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1869 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1872 if (IsCheckCopy()) CheckFileCopy(gGrid->GetHomeDirectory());
1873 if (!CheckInputData()) {
1874 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1877 if (!CreateDataset(fDataPattern)) {
1879 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
1880 if (fRunNumbers.Length()) serror = "run numbers";
1881 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
1882 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
1883 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
1886 WriteAnalysisFile();
1887 WriteAnalysisMacro();
1889 WriteValidationScript();
1891 WriteMergingMacro();
1892 WriteMergeExecutable();
1893 WriteValidationScript(kTRUE);
1895 if (!CreateJDL()) return kFALSE;
1896 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1897 if (TestBit(AliAnalysisGrid::kTest)) {
1898 // Locally testing the analysis
1899 Info("StartAnalysis", "\n_______________________________________________________________________ \
1900 \n Running analysis script in a daughter shell as on a worker node \
1901 \n_______________________________________________________________________");
1902 TObjArray *list = fOutputFiles.Tokenize(" ");
1905 TString output_file;
1906 while((str=(TObjString*)next())) {
1907 output_file = str->GetString();
1908 Int_t index = output_file.Index("@");
1909 if (index > 0) output_file.Remove(index);
1910 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1913 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1914 TString validationScript = fExecutable;
1915 validationScript.ReplaceAll(".sh", "_validation.sh");
1916 gSystem->Exec(Form("bash %s",validationScript.Data()));
1917 // gSystem->Exec("cat stdout");
1920 // Check if submitting is managed by LPM manager
1921 if (fProductionMode) {
1922 TString prodfile = fJDLName;
1923 prodfile.ReplaceAll(".jdl", ".prod");
1924 WriteProductionFile(prodfile);
1925 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1928 // Submit AliEn job(s)
1929 gGrid->Cd(fGridOutputDir);
1932 if (!fRunNumbers.Length() && !fRunRange[0]) {
1933 // Submit a given xml or a set of runs
1934 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1935 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1937 const char *cjobId = res->GetKey(0,"jobId");
1941 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1944 Info("StartAnalysis", "\n_______________________________________________________________________ \
1945 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1946 \n_______________________________________________________________________",
1947 fJDLName.Data(), cjobId);
1952 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
1956 // Submit for a range of enumeration of runs.
1957 if (!Submit()) return kFALSE;
1960 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1961 \n You may exit at any time and terminate the job later using the option <terminate> \
1962 \n ##################################################################################", jobID.Data());
1963 gSystem->Exec("aliensh");
1967 //______________________________________________________________________________
1968 Bool_t AliAnalysisAlien::Submit()
1970 // Submit all master jobs.
1971 Int_t nmasterjobs = fInputFiles->GetEntries();
1972 Long_t tshoot = gSystem->Now();
1973 if (!fNsubmitted && !SubmitNext()) return kFALSE;
1974 while (fNsubmitted < nmasterjobs) {
1975 Long_t now = gSystem->Now();
1976 if ((now-tshoot)>30000) {
1978 if (!SubmitNext()) return kFALSE;
1984 //______________________________________________________________________________
1985 Bool_t AliAnalysisAlien::SubmitMerging()
1987 // Submit all merging jobs.
1988 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1989 gGrid->Cd(fGridOutputDir);
1990 TString mergeJDLName = fExecutable;
1991 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1992 Int_t ntosubmit = fInputFiles->GetEntries();
1993 printf("### Submitting %d merging jobs...\n", ntosubmit);
1994 for (Int_t i=0; i<ntosubmit; i++) {
1996 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
1997 runOutDir.ReplaceAll(".xml", "");
1999 query = Form("submit %s %s", mergeJDLName.Data(), runOutDir.Data());
2001 query = Form("submit %s %03d", mergeJDLName.Data(), i);
2002 printf("********* %s\n",query.Data());
2003 TGridResult *res = gGrid->Command(query);
2005 const char *cjobId = res->GetKey(0,"jobId");
2009 Error("StartAnalysis", "Your JDL %s could not be submitted", mergeJDLName.Data());
2012 Info("StartAnalysis", "\n_______________________________________________________________________ \
2013 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
2014 \n_______________________________________________________________________",
2015 mergeJDLName.Data(), cjobId);
2019 Error("SubmitMerging", "No grid result after submission !!! Bailing out...");
2023 if (!ntosubmit) return kTRUE;
2024 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
2025 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
2026 \n ##################################################################################");
2027 gSystem->Exec("aliensh");
2031 //______________________________________________________________________________
2032 Bool_t AliAnalysisAlien::SubmitNext()
2034 // Submit next bunch of master jobs if the queue is free.
2035 static Bool_t iscalled = kFALSE;
2036 static Int_t firstmaster = 0;
2037 static Int_t lastmaster = 0;
2038 static Int_t npermaster = 0;
2039 if (iscalled) return kTRUE;
2041 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2042 Int_t ntosubmit = 0;
2045 if (!fNsubmitted) ntosubmit = 1;
2047 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2048 printf("=== master %d: %s\n", lastmaster, status.Data());
2049 // If last master not split, just return
2050 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2051 // No more than 100 waiting jobs
2052 if (nwaiting>100) {iscalled = kFALSE; return kTRUE;}
2053 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2054 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
2055 if (!ntosubmit) ntosubmit = 1;
2056 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2057 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2059 Int_t nmasterjobs = fInputFiles->GetEntries();
2060 for (Int_t i=0; i<ntosubmit; i++) {
2061 // Submit for a range of enumeration of runs.
2062 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2064 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2065 runOutDir.ReplaceAll(".xml", "");
2067 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2069 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2070 printf("********* %s\n",query.Data());
2071 res = gGrid->Command(query);
2073 TString cjobId1 = res->GetKey(0,"jobId");
2074 if (!cjobId1.Length()) {
2078 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2081 Info("StartAnalysis", "\n_______________________________________________________________________ \
2082 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2083 \n_______________________________________________________________________",
2084 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2087 lastmaster = cjobId1.Atoi();
2088 if (!firstmaster) firstmaster = lastmaster;
2093 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2101 //______________________________________________________________________________
2102 void AliAnalysisAlien::WriteAnalysisFile()
2104 // Write current analysis manager into the file <analysisFile>
2105 TString analysisFile = fExecutable;
2106 analysisFile.ReplaceAll(".sh", ".root");
2107 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2108 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2109 if (!mgr || !mgr->IsInitialized()) {
2110 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2113 // Check analysis type
2115 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2116 handler = (TObject*)mgr->GetInputEventHandler();
2118 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2119 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2121 TDirectory *cdir = gDirectory;
2122 TFile *file = TFile::Open(analysisFile, "RECREATE");
2124 // Skip task Terminate calls for the grid job
2125 mgr->SetSkipTerminate(kTRUE);
2126 // Unless merging makes no sense
2127 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2130 // Enable termination for local jobs
2131 mgr->SetSkipTerminate(kFALSE);
2133 if (cdir) cdir->cd();
2134 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2136 Bool_t copy = kTRUE;
2137 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2140 TString workdir = gGrid->GetHomeDirectory();
2141 workdir += fGridWorkingDir;
2142 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2143 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2144 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2148 //______________________________________________________________________________
2149 void AliAnalysisAlien::WriteAnalysisMacro()
2151 // Write the analysis macro that will steer the analysis in grid mode.
2152 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2154 out.open(fAnalysisMacro.Data(), ios::out);
2156 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2159 Bool_t hasSTEERBase = kFALSE;
2160 Bool_t hasESD = kFALSE;
2161 Bool_t hasAOD = kFALSE;
2162 Bool_t hasANALYSIS = kFALSE;
2163 Bool_t hasANALYSISalice = kFALSE;
2164 Bool_t hasCORRFW = kFALSE;
2165 TString func = fAnalysisMacro;
2166 TString type = "ESD";
2167 TString comment = "// Analysis using ";
2168 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2169 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2173 if (type!="AOD" && fFriendChainName!="") {
2174 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2177 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2178 else comment += " data";
2179 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2180 func.ReplaceAll(".C", "");
2181 out << "void " << func.Data() << "()" << endl;
2183 out << comment.Data() << endl;
2184 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
2185 out << " TStopwatch timer;" << endl;
2186 out << " timer.Start();" << endl << endl;
2187 out << "// load base root libraries" << endl;
2188 out << " gSystem->Load(\"libTree\");" << endl;
2189 out << " gSystem->Load(\"libGeom\");" << endl;
2190 out << " gSystem->Load(\"libVMC\");" << endl;
2191 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2192 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2193 if (fAdditionalRootLibs.Length()) {
2194 // in principle libtree /lib geom libvmc etc. can go into this list, too
2195 out << "// Add aditional libraries" << endl;
2196 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2199 while((str=(TObjString*)next())) {
2200 if (str->GetString().Contains(".so"))
2201 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2203 if (list) delete list;
2205 out << "// include path" << endl;
2206 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2207 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2208 out << "// Load analysis framework libraries" << endl;
2210 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2211 out << " gSystem->Load(\"libESD\");" << endl;
2212 out << " gSystem->Load(\"libAOD\");" << endl;
2213 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2214 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2215 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2217 TIter next(fPackages);
2220 TString setupPar = "AliAnalysisAlien::SetupPar";
2221 while ((obj=next())) {
2222 pkgname = obj->GetName();
2223 if (pkgname == "STEERBase" ||
2224 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2225 if (pkgname == "ESD" ||
2226 pkgname == "ESD.par") hasESD = kTRUE;
2227 if (pkgname == "AOD" ||
2228 pkgname == "AOD.par") hasAOD = kTRUE;
2229 if (pkgname == "ANALYSIS" ||
2230 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2231 if (pkgname == "ANALYSISalice" ||
2232 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2233 if (pkgname == "CORRFW" ||
2234 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2236 if (hasANALYSISalice) setupPar = "SetupPar";
2237 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2238 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2239 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2240 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2241 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2242 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2243 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2244 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2245 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2246 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2247 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2248 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2249 out << "// Compile other par packages" << endl;
2251 while ((obj=next())) {
2252 pkgname = obj->GetName();
2253 if (pkgname == "STEERBase" ||
2254 pkgname == "STEERBase.par" ||
2256 pkgname == "ESD.par" ||
2258 pkgname == "AOD.par" ||
2259 pkgname == "ANALYSIS" ||
2260 pkgname == "ANALYSIS.par" ||
2261 pkgname == "ANALYSISalice" ||
2262 pkgname == "ANALYSISalice.par" ||
2263 pkgname == "CORRFW" ||
2264 pkgname == "CORRFW.par") continue;
2265 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2268 if (fAdditionalLibs.Length()) {
2269 out << "// Add aditional AliRoot libraries" << endl;
2270 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2273 while((str=(TObjString*)next())) {
2274 if (str->GetString().Contains(".so"))
2275 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2277 if (list) delete list;
2280 out << "// analysis source to be compiled at runtime (if any)" << endl;
2281 if (fAnalysisSource.Length()) {
2282 TObjArray *list = fAnalysisSource.Tokenize(" ");
2285 while((str=(TObjString*)next())) {
2286 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2288 if (list) delete list;
2291 if (fFastReadOption) {
2292 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. This may skip some files that could be accessed !!! \
2293 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2294 out << "// fast xrootd reading enabled" << endl;
2295 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2296 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
2297 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
2298 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2299 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
2300 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2302 out << "// connect to AliEn and make the chain" << endl;
2303 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2304 if (IsUsingTags()) {
2305 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
2307 if(fFriendChainName!="AliAOD.VertexingHF.root") {
2308 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
2310 out << " // Check if the macro to create the chain was provided" << endl;
2311 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
2312 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
2313 out << " return;" << endl;
2314 out << " }" << endl;
2315 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
2316 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
2319 out << "// read the analysis manager from file" << endl;
2320 TString analysisFile = fExecutable;
2321 analysisFile.ReplaceAll(".sh", ".root");
2322 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2323 out << " if (!file) return;" << endl;
2324 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2325 out << " AliAnalysisManager *mgr = 0;" << endl;
2326 out << " TKey *key;" << endl;
2327 out << " while ((key=(TKey*)nextkey())) {" << endl;
2328 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2329 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2330 out << " };" << endl;
2331 out << " if (!mgr) {" << endl;
2332 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2333 out << " return;" << endl;
2334 out << " }" << endl << endl;
2335 out << " mgr->PrintStatus();" << endl;
2336 if (AliAnalysisManager::GetAnalysisManager()) {
2337 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2338 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2340 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2343 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
2344 out << " timer.Stop();" << endl;
2345 out << " timer.Print();" << endl;
2346 out << "}" << endl << endl;
2347 if (IsUsingTags()) {
2348 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
2350 out << "// Create a chain using tags from the xml file." << endl;
2351 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
2352 out << " if (!coll) {" << endl;
2353 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2354 out << " return NULL;" << endl;
2355 out << " }" << endl;
2356 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
2357 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
2358 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
2359 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
2360 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
2361 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
2362 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
2363 out << " // Check if the cuts configuration file was provided" << endl;
2364 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
2365 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
2366 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2367 out << " }" << endl;
2368 if (fFriendChainName=="") {
2369 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2371 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
2372 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
2373 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
2375 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
2376 out << " chain->ls();" << endl;
2377 out << " return chain;" << endl;
2378 out << "}" << endl << endl;
2379 if (gSystem->AccessPathName("ConfigureCuts.C")) {
2380 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
2381 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
2382 msg += " AliLHCTagCuts *lhcCuts,\n";
2383 msg += " AliDetectorTagCuts *detCuts,\n";
2384 msg += " AliEventTagCuts *evCuts)";
2385 Info("WriteAnalysisMacro", msg.Data());
2388 if (!IsUsingTags() || fFriendChainName!="") {
2389 out <<"//________________________________________________________________________________" << endl;
2390 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
2392 out << "// Create a chain using url's from xml file" << endl;
2393 out << " TString treename = type;" << endl;
2394 out << " treename.ToLower();" << endl;
2395 out << " treename += \"Tree\";" << endl;
2396 out << " printf(\"***************************************\\n\");" << endl;
2397 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
2398 out << " printf(\"***************************************\\n\");" << endl;
2399 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
2400 out << " if (!coll) {" << endl;
2401 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2402 out << " return NULL;" << endl;
2403 out << " }" << endl;
2404 out << " TChain *chain = new TChain(treename);" << endl;
2405 if(fFriendChainName!="") {
2406 out << " TChain *chainFriend = new TChain(treename);" << endl;
2408 out << " coll->Reset();" << endl;
2409 out << " while (coll->Next()) {" << endl;
2410 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2411 if(fFriendChainName!="") {
2412 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2413 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2414 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2415 out << " chainFriend->Add(fileFriend.Data());" << endl;
2417 out << " }" << endl;
2418 out << " if (!chain->GetNtrees()) {" << endl;
2419 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2420 out << " return NULL;" << endl;
2421 out << " }" << endl;
2422 if(fFriendChainName!="") {
2423 out << " chain->AddFriend(chainFriend);" << endl;
2425 out << " return chain;" << endl;
2426 out << "}" << endl << endl;
2428 if (hasANALYSISalice) {
2429 out <<"//________________________________________________________________________________" << endl;
2430 out << "Bool_t SetupPar(const char *package) {" << endl;
2431 out << "// Compile the package and set it up." << endl;
2432 out << " TString pkgdir = package;" << endl;
2433 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2434 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2435 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2436 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2437 out << " // Check for BUILD.sh and execute" << endl;
2438 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2439 out << " printf(\"*******************************\\n\");" << endl;
2440 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2441 out << " printf(\"*******************************\\n\");" << endl;
2442 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2443 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2444 out << " gSystem->ChangeDirectory(cdir);" << endl;
2445 out << " return kFALSE;" << endl;
2446 out << " }" << endl;
2447 out << " } else {" << endl;
2448 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2449 out << " gSystem->ChangeDirectory(cdir);" << endl;
2450 out << " return kFALSE;" << endl;
2451 out << " }" << endl;
2452 out << " // Check for SETUP.C and execute" << endl;
2453 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2454 out << " printf(\"*******************************\\n\");" << endl;
2455 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2456 out << " printf(\"*******************************\\n\");" << endl;
2457 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2458 out << " } else {" << endl;
2459 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2460 out << " gSystem->ChangeDirectory(cdir);" << endl;
2461 out << " return kFALSE;" << endl;
2462 out << " }" << endl;
2463 out << " // Restore original workdir" << endl;
2464 out << " gSystem->ChangeDirectory(cdir);" << endl;
2465 out << " return kTRUE;" << endl;
2468 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2470 Bool_t copy = kTRUE;
2471 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2474 TString workdir = gGrid->GetHomeDirectory();
2475 workdir += fGridWorkingDir;
2476 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2477 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2478 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2479 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2480 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2482 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2483 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2487 //______________________________________________________________________________
2488 void AliAnalysisAlien::WriteMergingMacro()
2490 // Write a macro to merge the outputs per master job.
2491 if (!fMergeViaJDL) return;
2492 if (!fOutputFiles.Length()) {
2493 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2496 TString mergingMacro = fExecutable;
2497 mergingMacro.ReplaceAll(".sh","_merge.C");
2498 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2499 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2501 out.open(mergingMacro.Data(), ios::out);
2503 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2506 Bool_t hasSTEERBase = kFALSE;
2507 Bool_t hasESD = kFALSE;
2508 Bool_t hasAOD = kFALSE;
2509 Bool_t hasANALYSIS = kFALSE;
2510 Bool_t hasANALYSISalice = kFALSE;
2511 Bool_t hasCORRFW = kFALSE;
2512 TString func = mergingMacro;
2514 func.ReplaceAll(".C", "");
2515 out << "void " << func.Data() << "(const char *dir)" << endl;
2517 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
2518 out << " TStopwatch timer;" << endl;
2519 out << " timer.Start();" << endl << endl;
2520 out << "// load base root libraries" << endl;
2521 out << " gSystem->Load(\"libTree\");" << endl;
2522 out << " gSystem->Load(\"libGeom\");" << endl;
2523 out << " gSystem->Load(\"libVMC\");" << endl;
2524 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2525 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2526 if (fAdditionalRootLibs.Length()) {
2527 // in principle libtree /lib geom libvmc etc. can go into this list, too
2528 out << "// Add aditional libraries" << endl;
2529 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2532 while((str=(TObjString*)next())) {
2533 if (str->GetString().Contains(".so"))
2534 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2536 if (list) delete list;
2538 out << "// include path" << endl;
2539 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2540 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2541 out << "// Load analysis framework libraries" << endl;
2543 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2544 out << " gSystem->Load(\"libESD\");" << endl;
2545 out << " gSystem->Load(\"libAOD\");" << endl;
2546 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2547 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2548 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2550 TIter next(fPackages);
2553 TString setupPar = "AliAnalysisAlien::SetupPar";
2554 while ((obj=next())) {
2555 pkgname = obj->GetName();
2556 if (pkgname == "STEERBase" ||
2557 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2558 if (pkgname == "ESD" ||
2559 pkgname == "ESD.par") hasESD = kTRUE;
2560 if (pkgname == "AOD" ||
2561 pkgname == "AOD.par") hasAOD = kTRUE;
2562 if (pkgname == "ANALYSIS" ||
2563 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2564 if (pkgname == "ANALYSISalice" ||
2565 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2566 if (pkgname == "CORRFW" ||
2567 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2569 if (hasANALYSISalice) setupPar = "SetupPar";
2570 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2571 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2572 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2573 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2574 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2575 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2576 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2577 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2578 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2579 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2580 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2581 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2582 out << "// Compile other par packages" << endl;
2584 while ((obj=next())) {
2585 pkgname = obj->GetName();
2586 if (pkgname == "STEERBase" ||
2587 pkgname == "STEERBase.par" ||
2589 pkgname == "ESD.par" ||
2591 pkgname == "AOD.par" ||
2592 pkgname == "ANALYSIS" ||
2593 pkgname == "ANALYSIS.par" ||
2594 pkgname == "ANALYSISalice" ||
2595 pkgname == "ANALYSISalice.par" ||
2596 pkgname == "CORRFW" ||
2597 pkgname == "CORRFW.par") continue;
2598 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2601 if (fAdditionalLibs.Length()) {
2602 out << "// Add aditional AliRoot libraries" << endl;
2603 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2606 while((str=(TObjString*)next())) {
2607 if (str->GetString().Contains(".so"))
2608 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2610 if (list) delete list;
2613 out << "// Analysis source to be compiled at runtime (if any)" << endl;
2614 if (fAnalysisSource.Length()) {
2615 TObjArray *list = fAnalysisSource.Tokenize(" ");
2618 while((str=(TObjString*)next())) {
2619 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2621 if (list) delete list;
2624 if (fFastReadOption) {
2625 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 !!!");
2626 out << "// fast xrootd reading enabled" << endl;
2627 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2628 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
2629 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
2630 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2631 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
2632 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2634 out << "// Connect to AliEn" << endl;
2635 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2636 out << " TString outputDir = \"" << fGridOutputDir << "/\";" << endl;
2637 out << " outputDir += dir;" << endl;
2638 out << " TString outputFiles = \"" << fOutputFiles << "\";" << endl;
2639 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
2640 out << " mergeExcludes += \"" << AliAnalysisManager::GetAnalysisManager()->GetExtraFiles() << "\";" << endl;
2641 out << " TObjArray *list = outputFiles.Tokenize(\" \");" << endl;
2642 out << " TIter *iter = new TIter(list);" << endl;
2643 out << " TObjString *str;" << endl;
2644 out << " TString output_file;" << endl;
2645 out << " Bool_t merged = kTRUE;" << endl;
2646 out << " while((str=(TObjString*)iter->Next())) {" << endl;
2647 out << " output_file = str->GetString();" << endl;
2648 out << " Int_t index = output_file.Index(\"@\");" << endl;
2649 out << " if (index > 0) output_file.Remove(index);" << endl;
2650 out << " // Skip already merged outputs" << endl;
2651 out << " if (!gSystem->AccessPathName(output_file)) {" << endl;
2652 out << " printf(\"Output file <%s> found. Not merging again.\",output_file.Data());" << endl;
2653 out << " continue;" << endl;
2654 out << " }" << endl;
2655 out << " if (mergeExcludes.Contains(output_file.Data())) continue;" << endl;
2656 out << " merged = AliAnalysisAlien::MergeOutput(output_file, outputDir, " << fMaxMergeFiles << ");" << endl;
2657 out << " if (!merged) {" << endl;
2658 out << " printf(\"ERROR: Cannot merge %s\\n\", output_file.Data());" << endl;
2659 out << " }" << endl;
2660 out << " }" << endl;
2661 out << "// read the analysis manager from file" << endl;
2662 TString analysisFile = fExecutable;
2663 analysisFile.ReplaceAll(".sh", ".root");
2664 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2665 out << " if (!file) return;" << endl;
2666 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2667 out << " AliAnalysisManager *mgr = 0;" << endl;
2668 out << " TKey *key;" << endl;
2669 out << " while ((key=(TKey*)nextkey())) {" << endl;
2670 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2671 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2672 out << " };" << endl;
2673 out << " if (!mgr) {" << endl;
2674 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2675 out << " return;" << endl;
2676 out << " }" << endl << endl;
2677 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
2678 out << " mgr->PrintStatus();" << endl;
2679 if (AliAnalysisManager::GetAnalysisManager()) {
2680 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2681 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2683 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2686 out << " mgr->StartAnalysis(\"gridterminate\");" << endl;
2687 out << "}" << endl << endl;
2688 if (hasANALYSISalice) {
2689 out <<"//________________________________________________________________________________" << endl;
2690 out << "Bool_t SetupPar(const char *package) {" << endl;
2691 out << "// Compile the package and set it up." << endl;
2692 out << " TString pkgdir = package;" << endl;
2693 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2694 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2695 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2696 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2697 out << " // Check for BUILD.sh and execute" << endl;
2698 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2699 out << " printf(\"*******************************\\n\");" << endl;
2700 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2701 out << " printf(\"*******************************\\n\");" << endl;
2702 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2703 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2704 out << " gSystem->ChangeDirectory(cdir);" << endl;
2705 out << " return kFALSE;" << endl;
2706 out << " }" << endl;
2707 out << " } else {" << endl;
2708 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2709 out << " gSystem->ChangeDirectory(cdir);" << endl;
2710 out << " return kFALSE;" << endl;
2711 out << " }" << endl;
2712 out << " // Check for SETUP.C and execute" << endl;
2713 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2714 out << " printf(\"*******************************\\n\");" << endl;
2715 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2716 out << " printf(\"*******************************\\n\");" << endl;
2717 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2718 out << " } else {" << endl;
2719 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2720 out << " gSystem->ChangeDirectory(cdir);" << endl;
2721 out << " return kFALSE;" << endl;
2722 out << " }" << endl;
2723 out << " // Restore original workdir" << endl;
2724 out << " gSystem->ChangeDirectory(cdir);" << endl;
2725 out << " return kTRUE;" << endl;
2729 Bool_t copy = kTRUE;
2730 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2733 TString workdir = gGrid->GetHomeDirectory();
2734 workdir += fGridWorkingDir;
2735 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
2736 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
2737 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
2741 //______________________________________________________________________________
2742 Bool_t AliAnalysisAlien::SetupPar(const char *package)
2744 // Compile the par file archive pointed by <package>. This must be present in the current durectory.
2745 // Note that for loading the compiled library. The current directory should have precedence in
2747 TString pkgdir = package;
2748 pkgdir.ReplaceAll(".par","");
2749 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
2750 TString cdir = gSystem->WorkingDirectory();
2751 gSystem->ChangeDirectory(pkgdir);
2752 // Check for BUILD.sh and execute
2753 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
2754 printf("**************************************************\n");
2755 printf("*** Building PAR archive %s\n", package);
2756 printf("**************************************************\n");
2757 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
2758 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
2759 gSystem->ChangeDirectory(cdir);
2763 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
2764 gSystem->ChangeDirectory(cdir);
2767 // Check for SETUP.C and execute
2768 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
2769 printf("**************************************************\n");
2770 printf("*** Setup PAR archive %s\n", package);
2771 printf("**************************************************\n");
2772 gROOT->Macro("PROOF-INF/SETUP.C");
2773 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
2775 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
2776 gSystem->ChangeDirectory(cdir);
2779 // Restore original workdir
2780 gSystem->ChangeDirectory(cdir);
2784 //______________________________________________________________________________
2785 void AliAnalysisAlien::WriteExecutable()
2787 // Generate the alien executable script.
2788 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2790 out.open(fExecutable.Data(), ios::out);
2792 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2795 out << "#!/bin/bash" << endl;
2796 out << "echo \"=========================================\"" << endl;
2797 out << "echo \"############## PATH : ##############\"" << endl;
2798 out << "echo $PATH" << endl;
2799 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2800 out << "echo $LD_LIBRARY_PATH" << endl;
2801 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2802 out << "echo $ROOTSYS" << endl;
2803 out << "echo \"############## which root : ##############\"" << endl;
2804 out << "which root" << endl;
2805 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2806 out << "echo $ALICE_ROOT" << endl;
2807 out << "echo \"############## which aliroot : ##############\"" << endl;
2808 out << "which aliroot" << endl;
2809 out << "echo \"############## system limits : ##############\"" << endl;
2810 out << "ulimit -a" << endl;
2811 out << "echo \"############## memory : ##############\"" << endl;
2812 out << "free -m" << endl;
2813 out << "echo \"=========================================\"" << endl << endl;
2814 // Make sure we can properly compile par files
2815 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2816 out << fExecutableCommand << " ";
2817 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2818 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2819 out << "echo \"############## memory after: ##############\"" << endl;
2820 out << "free -m" << endl;
2821 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2822 out << "dmesg | tail -n 10" << endl;
2824 Bool_t copy = kTRUE;
2825 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2828 TString workdir = gGrid->GetHomeDirectory();
2829 TString bindir = Form("%s/bin", workdir.Data());
2830 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2831 workdir += fGridWorkingDir;
2832 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2833 if (FileExists(executable)) gGrid->Rm(executable);
2834 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2835 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2839 //______________________________________________________________________________
2840 void AliAnalysisAlien::WriteMergeExecutable()
2842 // Generate the alien executable script for the merging job.
2843 if (!fMergeViaJDL) return;
2844 TString mergeExec = fExecutable;
2845 mergeExec.ReplaceAll(".sh", "_merge.sh");
2846 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2848 out.open(mergeExec.Data(), ios::out);
2850 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
2853 out << "#!/bin/bash" << endl;
2854 out << "echo \"=========================================\"" << endl;
2855 out << "echo \"############## PATH : ##############\"" << endl;
2856 out << "echo $PATH" << endl;
2857 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2858 out << "echo $LD_LIBRARY_PATH" << endl;
2859 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2860 out << "echo $ROOTSYS" << endl;
2861 out << "echo \"############## which root : ##############\"" << endl;
2862 out << "which root" << endl;
2863 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2864 out << "echo $ALICE_ROOT" << endl;
2865 out << "echo \"############## which aliroot : ##############\"" << endl;
2866 out << "which aliroot" << endl;
2867 out << "echo \"############## system limits : ##############\"" << endl;
2868 out << "ulimit -a" << endl;
2869 out << "echo \"############## memory : ##############\"" << endl;
2870 out << "free -m" << endl;
2871 out << "echo \"=========================================\"" << endl << endl;
2872 // Make sure we can properly compile par files
2873 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2874 TString mergeMacro = fExecutable;
2875 mergeMacro.ReplaceAll(".sh", "_merge.C");
2876 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
2877 out << fExecutableCommand << " " << "$ARG" << endl;
2878 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
2879 out << "echo \"############## memory after: ##############\"" << endl;
2880 out << "free -m" << endl;
2881 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2882 out << "dmesg | tail -n 10" << endl;
2884 Bool_t copy = kTRUE;
2885 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2888 TString workdir = gGrid->GetHomeDirectory();
2889 TString bindir = Form("%s/bin", workdir.Data());
2890 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2891 workdir += fGridWorkingDir;
2892 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
2893 if (FileExists(executable)) gGrid->Rm(executable);
2894 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
2895 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
2899 //______________________________________________________________________________
2900 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2902 // Write the production file to be submitted by LPM manager. The format is:
2903 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2904 // Next lines: full_path_to_dataset XXX (XXX is a string)
2905 // To submit, one has to: submit jdl XXX for all lines
2907 out.open(filename, ios::out);
2909 Error("WriteProductionFile", "Bad file name: %s", filename);
2912 TString workdir = gGrid->GetHomeDirectory();
2913 workdir += fGridWorkingDir;
2914 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2915 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2916 out << locjdl << " " << njobspermaster << endl;
2917 Int_t nmasterjobs = fInputFiles->GetEntries();
2918 for (Int_t i=0; i<nmasterjobs; i++) {
2919 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2920 runOutDir.ReplaceAll(".xml", "");
2922 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
2924 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2926 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2927 if (FileExists(filename)) gGrid->Rm(filename);
2928 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2931 //______________________________________________________________________________
2932 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
2934 // Generate the alien validation script.
2935 // Generate the validation script
2937 TString validationScript = fExecutable;
2938 if (merge) validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
2939 else validationScript.ReplaceAll(".sh", "_validation.sh");
2941 Error("WriteValidationScript", "Alien connection required");
2944 TString out_stream = "";
2945 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2946 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2948 out.open(validationScript, ios::out);
2949 out << "#!/bin/bash" << endl;
2950 out << "##################################################" << endl;
2951 out << "validateout=`dirname $0`" << endl;
2952 out << "validatetime=`date`" << endl;
2953 out << "validated=\"0\";" << endl;
2954 out << "error=0" << endl;
2955 out << "if [ -z $validateout ]" << endl;
2956 out << "then" << endl;
2957 out << " validateout=\".\"" << endl;
2958 out << "fi" << endl << endl;
2959 out << "cd $validateout;" << endl;
2960 out << "validateworkdir=`pwd`;" << endl << endl;
2961 out << "echo \"*******************************************************\"" << out_stream << endl;
2962 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2964 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2965 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2966 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2967 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2968 out << "ls -la ./" << out_stream << endl;
2969 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2970 out << "##################################################" << endl;
2973 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2974 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2975 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2978 out << "if [ ! -f stderr ] ; then" << endl;
2979 out << " error=1" << endl;
2980 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2981 out << " echo \"Error = $error\" " << out_stream << endl;
2982 out << "fi" << endl;
2984 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2985 out << " error=1" << endl;
2986 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2987 out << " echo \"$parArch\" " << out_stream << endl;
2988 out << " echo \"Error = $error\" " << out_stream << endl;
2989 out << "fi" << endl;
2991 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2992 out << " error=1" << endl;
2993 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2994 out << " echo \"$segViol\" " << out_stream << endl;
2995 out << " echo \"Error = $error\" " << out_stream << endl;
2996 out << "fi" << endl;
2998 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2999 out << " error=1" << endl;
3000 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
3001 out << " echo \"$segFault\" " << out_stream << endl;
3002 out << " echo \"Error = $error\" " << out_stream << endl;
3003 out << "fi" << endl;
3005 // Part dedicated to the specific analyses running into the train
3007 TObjArray *arr = fOutputFiles.Tokenize(" ");
3009 TString output_file;
3010 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
3011 TString extra = mgr->GetExtraFiles();
3012 while ((os=(TObjString*)next1())) {
3013 output_file = os->GetString();
3014 Int_t index = output_file.Index("@");
3015 if (index > 0) output_file.Remove(index);
3016 if (merge && fMergeExcludes.Contains(output_file)) continue;
3017 if (extra.Contains(output_file)) continue;
3018 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
3019 out << " error=1" << endl;
3020 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
3021 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
3022 out << "fi" << endl;
3026 out << "if ! [ -f outputs_valid ] ; then" << endl;
3027 out << " error=1" << endl;
3028 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
3029 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
3030 out << "fi" << endl;
3033 out << "if [ $error = 0 ] ; then" << endl;
3034 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
3035 out << "fi" << endl;
3037 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
3038 out << "echo \"*******************************************************\"" << out_stream << endl;
3039 out << "cd -" << endl;
3040 out << "exit $error" << endl;
3042 Bool_t copy = kTRUE;
3043 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3046 TString workdir = gGrid->GetHomeDirectory();
3047 workdir += fGridWorkingDir;
3048 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
3049 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3050 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));