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;
658 Error("CreateDataset","Dataset %s produced by the previous find command is empty !", file.Data());
662 Bool_t fileExists = FileExists(file);
663 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
664 // Copy xml file to alien space
665 if (fileExists) gGrid->Rm(file);
666 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
667 if (!FileExists(file)) {
668 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
671 // Update list of files to be processed.
673 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
677 Bool_t null_result = kTRUE;
678 if (fRunNumbers.Length()) {
679 TObjArray *arr = fRunNumbers.Tokenize(" ");
682 while ((os=(TObjString*)next())) {
683 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
684 if (!DirectoryExists(path)) continue;
686 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
687 else file = Form("%s.xml", os->GetString().Data());
688 // If local collection file does not exist, create it via 'find' command.
689 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
694 command += conditions;
695 TGridResult *res = gGrid->Command(command);
697 // Write standard output to file
698 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
699 Bool_t has_grep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
700 Bool_t null_file = kFALSE;
702 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
704 null_file = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
705 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
706 fRunNumbers.ReplaceAll(os->GetString().Data(), "");
709 null_result = kFALSE;
711 if (TestBit(AliAnalysisGrid::kTest)) break;
712 // Check if there is one run per master job.
713 if (fNrunsPerMaster<2) {
714 if (FileExists(file)) {
715 if (fOverwriteMode) gGrid->Rm(file);
717 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
721 // Copy xml file to alien space
722 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
723 if (!FileExists(file)) {
724 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
730 if (((nruns-1)%fNrunsPerMaster) == 0) {
731 schunk = os->GetString();
732 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
734 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
735 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
739 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
742 schunk += Form("_%s.xml", os->GetString().Data());
743 if (FileExists(schunk)) {
744 if (fOverwriteMode) gGrid->Rm(file);
746 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
750 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
751 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
752 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
753 if (!FileExists(schunk)) {
754 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
762 Error("CreateDataset", "No valid dataset corresponding to the query!");
766 // Process a full run range.
767 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
768 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
769 if (!DirectoryExists(path)) continue;
771 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
772 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
773 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
774 if (fOverwriteMode) gGrid->Rm(file);
776 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
780 // If local collection file does not exist, create it via 'find' command.
781 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
786 command += conditions;
787 TGridResult *res = gGrid->Command(command);
789 // Write standard output to file
790 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
791 Bool_t has_grep = (gSystem->Exec("grep --version 2>/dev/null > /dev/null")==0)?kTRUE:kFALSE;
792 Bool_t null_file = kFALSE;
794 Warning("CreateDataset", "'grep' command not available on this system - cannot validate the result of the grid 'find' command");
796 null_file = (gSystem->Exec(Form("grep /event %s 2>/dev/null > /dev/null",file.Data()))==0)?kFALSE:kTRUE;
797 Warning("CreateDataset","Dataset %s produced by: <%s> is empty !", file.Data(), command.Data());
800 null_result = kFALSE;
802 if (TestBit(AliAnalysisGrid::kTest)) break;
803 // Check if there is one run per master job.
804 if (fNrunsPerMaster<2) {
805 if (FileExists(file)) {
806 if (fOverwriteMode) gGrid->Rm(file);
808 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
812 // Copy xml file to alien space
813 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
814 if (!FileExists(file)) {
815 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
820 // Check if the collection for the chunk exist locally.
821 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
822 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
823 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
826 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
827 if (((nruns-1)%fNrunsPerMaster) == 0) {
828 schunk = Form("%s%d", fRunPrefix.Data(), irun);
829 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
831 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
835 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
836 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
840 if (FileExists(schunk)) {
841 if (fOverwriteMode) gGrid->Rm(schunk);
843 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
847 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
848 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
849 if (FileExists(schunk)) {
850 if (fOverwriteMode) gGrid->Rm(schunk);
852 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
856 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
857 if (!FileExists(schunk)) {
858 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
864 Error("CreateDataset", "No valid dataset corresponding to the query!");
871 //______________________________________________________________________________
872 Bool_t AliAnalysisAlien::CreateJDL()
874 // Generate a JDL file according to current settings. The name of the file is
875 // specified by fJDLName.
876 Bool_t error = kFALSE;
879 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
880 Bool_t generate = kTRUE;
881 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
883 Error("CreateJDL", "Alien connection required");
886 // Check validity of alien workspace
888 TString workdir = gGrid->GetHomeDirectory();
889 workdir += fGridWorkingDir;
893 Error("CreateJDL()", "Define some input files for your analysis.");
896 // Compose list of input files
897 // Check if output files were defined
898 if (!fOutputFiles.Length()) {
899 Error("CreateJDL", "You must define at least one output file");
902 // Check if an output directory was defined and valid
903 if (!fGridOutputDir.Length()) {
904 Error("CreateJDL", "You must define AliEn output directory");
907 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
908 if (!DirectoryExists(fGridOutputDir)) {
909 if (gGrid->Mkdir(fGridOutputDir)) {
910 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
912 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
918 // Exit if any error up to now
919 if (error) return kFALSE;
921 if (!fUser.IsNull()) {
922 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
923 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
925 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
926 TString mergeExec = fExecutable;
927 mergeExec.ReplaceAll(".sh", "_merge.sh");
928 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
929 mergeExec.ReplaceAll(".sh", ".C");
930 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
931 if (!fArguments.IsNull())
932 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
933 fMergingJDL->SetArguments("$1");
934 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
935 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
936 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
937 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
939 if (fMaxInitFailed > 0) {
940 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
941 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
943 if (fSplitMaxInputFileNumber > 0) {
944 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
945 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
947 if (fSplitMode.Length()) {
948 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
949 fGridJDL->SetDescription("Split", "We split per SE or file");
951 if (!fAliROOTVersion.IsNull()) {
952 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
953 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
955 if (!fROOTVersion.IsNull()) {
956 fGridJDL->AddToPackages("ROOT", fROOTVersion);
957 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
959 if (!fAPIVersion.IsNull()) {
960 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
961 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
963 if (!fExternalPackages.IsNull()) {
964 arr = fExternalPackages.Tokenize(" ");
966 while ((os=(TObjString*)next())) {
967 TString pkgname = os->GetString();
968 Int_t index = pkgname.Index("::");
969 TString pkgversion = pkgname(index+2, pkgname.Length());
970 pkgname.Remove(index);
971 fGridJDL->AddToPackages(pkgname, pkgversion);
972 fMergingJDL->AddToPackages(pkgname, pkgversion);
976 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
977 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
978 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
979 TString analysisFile = fExecutable;
980 analysisFile.ReplaceAll(".sh", ".root");
981 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
982 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
983 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
984 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
985 if (fAdditionalLibs.Length()) {
986 arr = fAdditionalLibs.Tokenize(" ");
988 while ((os=(TObjString*)next())) {
989 if (os->GetString().Contains(".so")) continue;
990 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
991 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
996 TIter next(fPackages);
998 while ((obj=next())) {
999 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1000 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
1003 if (fOutputArchive.Length()) {
1004 arr = fOutputArchive.Tokenize(" ");
1006 Bool_t first = kTRUE;
1007 const char *comment = "Files to be archived";
1008 const char *comment1 = comment;
1009 while ((os=(TObjString*)next())) {
1010 if (!first) comment = NULL;
1011 if (!os->GetString().Contains("@") && fCloseSE.Length())
1012 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1014 fGridJDL->AddToOutputArchive(os->GetString(), comment);
1018 TString outputArchive = fOutputArchive;
1019 if (!fMergeExcludes.IsNull()) {
1020 arr = fMergeExcludes.Tokenize(" ");
1022 while ((os=(TObjString*)next1())) {
1023 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1024 outputArchive.ReplaceAll(os->GetString(),"");
1028 arr = outputArchive.Tokenize(" ");
1032 while ((os=(TObjString*)next2())) {
1033 if (!first) comment = NULL;
1034 if (!os->GetString().Contains("@") && fCloseSE.Length())
1035 fMergingJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1037 fMergingJDL->AddToOutputArchive(os->GetString(), comment);
1042 arr = fOutputFiles.Tokenize(" ");
1044 Bool_t first = kTRUE;
1045 const char *comment = "Files to be archived";
1046 const char *comment1 = comment;
1047 while ((os=(TObjString*)next())) {
1048 // Ignore ouputs in jdl that are also in outputarchive
1049 TString sout = os->GetString();
1050 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1051 if (fOutputArchive.Contains(sout)) continue;
1052 if (!first) comment = NULL;
1053 if (!os->GetString().Contains("@") && fCloseSE.Length())
1054 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1056 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1060 if (fOutputFiles.Length()) {
1061 TString outputFiles = fOutputFiles;
1062 if (!fMergeExcludes.IsNull()) {
1063 arr = fMergeExcludes.Tokenize(" ");
1065 while ((os=(TObjString*)next1())) {
1066 outputFiles.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1067 outputFiles.ReplaceAll(os->GetString(),"");
1071 arr = outputFiles.Tokenize(" ");
1075 while ((os=(TObjString*)next2())) {
1076 // Ignore ouputs in jdl that are also in outputarchive
1077 TString sout = os->GetString();
1078 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1079 if (fOutputArchive.Contains(sout)) continue;
1080 if (!first) comment = NULL;
1081 if (!os->GetString().Contains("@") && fCloseSE.Length())
1082 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1084 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1088 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1089 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1090 TString validationScript = fExecutable;
1091 validationScript.ReplaceAll(".sh", "_validation.sh");
1092 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1093 validationScript = fExecutable;
1094 validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
1095 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1096 if (fMasterResubmitThreshold) {
1097 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1098 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1100 // Write a jdl with 2 input parameters: collection name and output dir name.
1103 // Copy jdl to grid workspace
1105 // Check if an output directory was defined and valid
1106 if (!fGridOutputDir.Length()) {
1107 Error("CreateJDL", "You must define AliEn output directory");
1110 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1111 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1112 if (gGrid->Mkdir(fGridOutputDir)) {
1113 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1115 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1121 if (TestBit(AliAnalysisGrid::kSubmit)) {
1122 TString mergeJDLName = fExecutable;
1123 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1124 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1125 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1126 if (fProductionMode) {
1127 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1128 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1130 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1131 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1132 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1133 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1135 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1136 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1139 if (fAdditionalLibs.Length()) {
1140 arr = fAdditionalLibs.Tokenize(" ");
1143 while ((os=(TObjString*)next())) {
1144 if (os->GetString().Contains(".so")) continue;
1145 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1146 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1147 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1152 TIter next(fPackages);
1154 while ((obj=next())) {
1155 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1156 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1157 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1164 //______________________________________________________________________________
1165 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1167 // Writes one or more JDL's corresponding to findex. If findex is negative,
1168 // all run numbers are considered in one go (jdl). For non-negative indices
1169 // they correspond to the indices in the array fInputFiles.
1170 if (!fInputFiles) return kFALSE;
1172 TString workdir = gGrid->GetHomeDirectory();
1173 workdir += fGridWorkingDir;
1175 if (!fRunNumbers.Length() && !fRunRange[0]) {
1176 // One jdl with no parameters in case input data is specified by name.
1177 TIter next(fInputFiles);
1178 while ((os=(TObjString*)next()))
1179 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()), "Input xml collections");
1180 if (!fOutputSingle.IsNull())
1181 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1183 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1184 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1187 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1188 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1189 if (!fOutputSingle.IsNull()) {
1190 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1191 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1193 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1194 fMergingJDL->SetOutputDirectory(Form("%s/$1", fGridOutputDir.Data()), "Output directory");
1199 // Generate the JDL as a string
1200 TString sjdl = fGridJDL->Generate();
1201 TString sjdl1 = fMergingJDL->Generate();
1203 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1204 sjdl.ReplaceAll("(member", "\n (member");
1205 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1206 sjdl.ReplaceAll("{", "{\n ");
1207 sjdl.ReplaceAll("};", "\n};");
1208 sjdl.ReplaceAll("{\n \n", "{\n");
1209 sjdl.ReplaceAll("\n\n", "\n");
1210 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1211 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1212 sjdl1.ReplaceAll("(member", "\n (member");
1213 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1214 sjdl1.ReplaceAll("{", "{\n ");
1215 sjdl1.ReplaceAll("};", "\n};");
1216 sjdl1.ReplaceAll("{\n \n", "{\n");
1217 sjdl1.ReplaceAll("\n\n", "\n");
1218 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1219 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1220 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1221 index = sjdl.Index("JDLVariables");
1222 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1223 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1224 sjdl1.Prepend(Form("Jobtag = {\n \"comment:Merging_%s\"\n};\n", fJobTag.Data()));
1225 index = sjdl1.Index("JDLVariables");
1226 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1227 // Write jdl to file
1229 out.open(fJDLName.Data(), ios::out);
1231 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1234 out << sjdl << endl;
1235 TString mergeJDLName = fExecutable;
1236 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1239 out1.open(mergeJDLName.Data(), ios::out);
1241 Error("CreateJDL", "Bad file name: %s", mergeJDLName.Data());
1244 out1 << sjdl1 << endl;
1247 // Copy jdl to grid workspace
1249 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1251 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1252 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1253 if (fProductionMode) {
1254 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1255 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1257 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1258 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1259 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1260 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1262 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1263 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1269 //______________________________________________________________________________
1270 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1272 // Returns true if file exists.
1273 if (!gGrid) return kFALSE;
1274 TGridResult *res = gGrid->Ls(lfn);
1275 if (!res) return kFALSE;
1276 TMap *map = dynamic_cast<TMap*>(res->At(0));
1281 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1282 if (!objs || !objs->GetString().Length()) {
1290 //______________________________________________________________________________
1291 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1293 // Returns true if directory exists. Can be also a path.
1294 if (!gGrid) return kFALSE;
1295 // Check if dirname is a path
1296 TString dirstripped = dirname;
1297 dirstripped = dirstripped.Strip();
1298 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1299 TString dir = gSystem->BaseName(dirstripped);
1301 TString path = gSystem->DirName(dirstripped);
1302 TGridResult *res = gGrid->Ls(path, "-F");
1303 if (!res) return kFALSE;
1307 while ((map=dynamic_cast<TMap*>(next()))) {
1308 obj = map->GetValue("name");
1310 if (dir == obj->GetName()) {
1319 //______________________________________________________________________________
1320 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1322 // Check input data type.
1323 is_collection = kFALSE;
1327 Error("CheckDataType", "No connection to grid");
1330 is_collection = IsCollection(lfn);
1331 TString msg = "\n##### file: ";
1333 if (is_collection) {
1334 msg += " type: raw_collection;";
1335 // special treatment for collections
1337 // check for tag files in the collection
1338 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1340 msg += " using_tags: No (unknown)";
1341 Info("CheckDataType", msg.Data());
1344 const char* typeStr = res->GetKey(0, "origLFN");
1345 if (!typeStr || !strlen(typeStr)) {
1346 msg += " using_tags: No (unknown)";
1347 Info("CheckDataType", msg.Data());
1350 TString file = typeStr;
1351 use_tags = file.Contains(".tag");
1352 if (use_tags) msg += " using_tags: Yes";
1353 else msg += " using_tags: No";
1354 Info("CheckDataType", msg.Data());
1359 is_xml = slfn.Contains(".xml");
1361 // Open xml collection and check if there are tag files inside
1362 msg += " type: xml_collection;";
1363 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1365 msg += " using_tags: No (unknown)";
1366 Info("CheckDataType", msg.Data());
1369 TMap *map = coll->Next();
1371 msg += " using_tags: No (unknown)";
1372 Info("CheckDataType", msg.Data());
1375 map = (TMap*)map->GetValue("");
1377 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1378 use_tags = file.Contains(".tag");
1380 if (use_tags) msg += " using_tags: Yes";
1381 else msg += " using_tags: No";
1382 Info("CheckDataType", msg.Data());
1385 use_tags = slfn.Contains(".tag");
1386 if (slfn.Contains(".root")) msg += " type: root file;";
1387 else msg += " type: unknown file;";
1388 if (use_tags) msg += " using_tags: Yes";
1389 else msg += " using_tags: No";
1390 Info("CheckDataType", msg.Data());
1393 //______________________________________________________________________________
1394 void AliAnalysisAlien::EnablePackage(const char *package)
1396 // Enables a par file supposed to exist in the current directory.
1397 TString pkg(package);
1398 pkg.ReplaceAll(".par", "");
1400 if (gSystem->AccessPathName(pkg)) {
1401 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1404 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1405 Info("EnablePackage", "AliEn plugin will use .par packages");
1406 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1408 fPackages = new TObjArray();
1409 fPackages->SetOwner();
1411 fPackages->Add(new TObjString(pkg));
1414 //______________________________________________________________________________
1415 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1417 // Get job status for all jobs with jobid>jobidstart.
1418 static char mstatus[20];
1424 TGridJobStatusList *list = gGrid->Ps("");
1425 if (!list) return mstatus;
1426 Int_t nentries = list->GetSize();
1427 TGridJobStatus *status;
1429 for (Int_t ijob=0; ijob<nentries; ijob++) {
1430 status = (TGridJobStatus *)list->At(ijob);
1431 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1432 if (pid<jobidstart) continue;
1433 if (pid == lastid) {
1434 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1436 switch (status->GetStatus()) {
1437 case TGridJobStatus::kWAITING:
1439 case TGridJobStatus::kRUNNING:
1441 case TGridJobStatus::kABORTED:
1442 case TGridJobStatus::kFAIL:
1443 case TGridJobStatus::kUNKNOWN:
1445 case TGridJobStatus::kDONE:
1454 //______________________________________________________________________________
1455 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1457 // Returns true if file is a collection. Functionality duplicated from
1458 // TAlien::Type() because we don't want to directly depend on TAlien.
1460 Error("IsCollection", "No connection to grid");
1463 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1464 if (!res) return kFALSE;
1465 const char* typeStr = res->GetKey(0, "type");
1466 if (!typeStr || !strlen(typeStr)) return kFALSE;
1467 if (!strcmp(typeStr, "collection")) return kTRUE;
1472 //______________________________________________________________________________
1473 Bool_t AliAnalysisAlien::IsSingleOutput() const
1475 // Check if single-ouput option is on.
1476 return (!fOutputSingle.IsNull());
1479 //______________________________________________________________________________
1480 void AliAnalysisAlien::Print(Option_t *) const
1482 // Print current plugin settings.
1483 printf("### AliEn analysis plugin current settings ###\n");
1484 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1485 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1486 printf("= Production mode:______________________________ %d\n", fProductionMode);
1487 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1488 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1489 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1491 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1492 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1493 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1494 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1495 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1496 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1497 if (fRunNumbers.Length())
1498 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1500 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1501 if (!fRunRange[0] && !fRunNumbers.Length()) {
1502 TIter next(fInputFiles);
1505 while ((obj=next())) list += obj->GetName();
1506 printf("= Input files to be processed: _________________ %s\n", list.Data());
1508 if (TestBit(AliAnalysisGrid::kTest))
1509 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1510 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1511 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1512 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1513 printf("=====================================================================\n");
1514 printf("= Job price: ___________________________________ %d\n", fPrice);
1515 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1516 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1517 if (fMaxInitFailed>0)
1518 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1519 if (fMasterResubmitThreshold>0)
1520 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1521 if (fNrunsPerMaster>0)
1522 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1523 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1524 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1525 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1526 if (fArguments.Length())
1527 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1528 if (fExecutableArgs.Length())
1529 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1530 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1531 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1532 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1533 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1535 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1536 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1537 if (fIncludePath.Data())
1538 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1539 if (fCloseSE.Length())
1540 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1541 if (fFriendChainName.Length())
1542 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1544 TIter next(fPackages);
1547 while ((obj=next())) list += obj->GetName();
1548 printf("= Par files to be used: ________________________ %s\n", list.Data());
1552 //______________________________________________________________________________
1553 void AliAnalysisAlien::SetDefaults()
1555 // Set default values for everything. What cannot be filled will be left empty.
1556 if (fGridJDL) delete fGridJDL;
1557 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1558 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1561 fSplitMaxInputFileNumber = 100;
1563 fMasterResubmitThreshold = 0;
1567 fNrunsPerMaster = 1;
1568 fMaxMergeFiles = 100;
1570 fExecutable = "analysis.sh";
1571 fExecutableCommand = "root -b -q";
1573 fExecutableArgs = "";
1574 fAnalysisMacro = "myAnalysis.C";
1575 fAnalysisSource = "";
1576 fAdditionalLibs = "";
1580 fAliROOTVersion = "";
1581 fUser = ""; // Your alien user name
1582 fGridWorkingDir = "";
1583 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1584 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1585 fFriendChainName = "";
1586 fGridOutputDir = "output";
1587 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1588 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1589 fInputFormat = "xml-single";
1590 fJDLName = "analysis.jdl";
1591 fJobTag = "Automatically generated analysis JDL";
1592 fMergeExcludes = "";
1595 SetCheckCopy(kTRUE);
1598 //______________________________________________________________________________
1599 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge)
1601 // Merge all registered outputs from basedir.
1602 TString output_file = output;
1604 TString output_chunk;
1605 TString previous_chunk = "";
1606 Int_t count_chunk = 0;
1607 Int_t count_zero = nmaxmerge;
1608 Bool_t merged = kTRUE;
1609 Int_t index = output_file.Index("@");
1610 if (index > 0) output_file.Remove(index);
1611 command = Form("find %s/ *%s", basedir, output_file.Data());
1612 printf("command: %s\n", command.Data());
1613 TGridResult *res = gGrid->Command(command);
1615 printf("Error: No result for the find command\n");
1619 TFileMerger *fm = 0;
1622 // Check if there is a merge operation to resume
1623 output_chunk = output_file;
1624 output_chunk.ReplaceAll(".root", "_*.root");
1625 // Check for existent temporary merge files
1626 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1628 // Skip as many input files as in a chunk
1629 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1631 ::Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1635 output_chunk = output_file;
1636 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1638 if (gSystem->AccessPathName(output_chunk)) continue;
1639 // Merged file with chunks up to <count_chunk> found
1640 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1641 previous_chunk = output_chunk;
1645 count_zero = nmaxmerge;
1647 while ((map=(TMap*)nextmap())) {
1648 // Loop 'find' results and get next LFN
1649 if (count_zero == nmaxmerge) {
1650 // First file in chunk - create file merger and add previous chunk if any.
1651 fm = new TFileMerger(kFALSE);
1652 fm->SetFastMethod(kTRUE);
1653 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1654 output_chunk = output_file;
1655 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1657 // If last file found, put merged results in the output file
1658 if (map == res->Last()) output_chunk = output_file;
1659 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1660 if (!objs || !objs->GetString().Length()) {
1661 // Nothing found - skip this output
1666 // Add file to be merged and decrement chunk counter.
1667 fm->AddFile(objs->GetString());
1669 if (count_zero==0 || map == res->Last()) {
1670 fm->OutputFile(output_chunk);
1671 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1672 // Nothing found - skip this output
1673 ::Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1678 // Merge the outputs, then go to next chunk
1680 ::Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1686 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1687 gSystem->Unlink(previous_chunk);
1689 if (map == res->Last()) {
1695 count_zero = nmaxmerge;
1696 previous_chunk = output_chunk;
1702 //______________________________________________________________________________
1703 Bool_t AliAnalysisAlien::MergeOutputs()
1705 // Merge analysis outputs existing in the AliEn space.
1706 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1707 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1709 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1713 if (!TestBit(AliAnalysisGrid::kMerge)) {
1714 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
1717 if (fProductionMode) {
1718 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
1721 Info("MergeOutputs", "Submitting merging JDL");
1722 if (!SubmitMerging()) return kFALSE;
1723 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
1724 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
1727 // Get the output path
1728 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1729 if (!DirectoryExists(fGridOutputDir)) {
1730 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1733 if (!fOutputFiles.Length()) {
1734 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1737 // Check if fast read option was requested
1738 if (fFastReadOption) {
1739 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. This may skip some files that could be accessed ! \
1740 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
1741 gEnv->SetValue("XNet.ConnectTimeout",10);
1742 gEnv->SetValue("XNet.RequestTimeout",10);
1743 gEnv->SetValue("XNet.MaxRedirectCount",2);
1744 gEnv->SetValue("XNet.ReconnectTimeout",10);
1745 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
1747 TObjArray *list = fOutputFiles.Tokenize(" ");
1750 TString output_file;
1751 Bool_t merged = kTRUE;
1752 while((str=(TObjString*)next())) {
1753 output_file = str->GetString();
1754 Int_t index = output_file.Index("@");
1755 if (index > 0) output_file.Remove(index);
1756 // Skip already merged outputs
1757 if (!gSystem->AccessPathName(output_file)) {
1758 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1761 if (fMergeExcludes.Length() &&
1762 fMergeExcludes.Contains(output_file.Data())) continue;
1763 // Perform a 'find' command in the output directory, looking for registered outputs
1764 merged = MergeOutput(output_file, fGridOutputDir, fMaxMergeFiles);
1766 Error("MergeOutputs", "Terminate() will NOT be executed");
1773 //______________________________________________________________________________
1774 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1776 // Use the output files connected to output containers from the analysis manager
1777 // rather than the files defined by SetOutputFiles
1778 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1779 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1781 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1784 //______________________________________________________________________________
1785 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1787 // Start remote grid analysis.
1789 // Check if output files have to be taken from the analysis manager
1790 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1791 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1792 if (!mgr || !mgr->IsInitialized()) {
1793 Error("StartAnalysis", "You need an initialized analysis manager for this");
1797 TIter next(mgr->GetOutputs());
1798 AliAnalysisDataContainer *output;
1799 while ((output=(AliAnalysisDataContainer*)next())) {
1800 const char *filename = output->GetFileName();
1801 if (!(strcmp(filename, "default"))) {
1802 if (!mgr->GetOutputEventHandler()) continue;
1803 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1805 if (fOutputFiles.Contains(filename)) continue;
1806 if (fOutputFiles.Length()) fOutputFiles += " ";
1807 fOutputFiles += filename;
1809 // Add extra files registered to the analysis manager
1810 if (mgr->GetExtraFiles().Length()) {
1811 if (fOutputFiles.Length()) fOutputFiles += " ";
1812 fOutputFiles += mgr->GetExtraFiles();
1815 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1816 if (TestBit(AliAnalysisGrid::kOffline)) {
1817 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1818 \n there nor any job run. You can revise the JDL and analysis \
1819 \n macro then run the same in \"submit\" mode.");
1820 } else if (TestBit(AliAnalysisGrid::kTest)) {
1821 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1823 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1824 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1825 \n space and job submitted.");
1826 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1827 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1828 if (fMergeViaJDL) CheckInputData();
1831 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1836 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1839 if (IsCheckCopy()) CheckFileCopy(gGrid->GetHomeDirectory());
1840 if (!CheckInputData()) {
1841 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1844 if (!CreateDataset(fDataPattern)) {
1846 if (!fRunNumbers.Length() && !fRunRange[0]) serror = Form("path to data directory: <%s>", fGridDataDir.Data());
1847 if (fRunNumbers.Length()) serror = "run numbers";
1848 if (fRunRange[0]) serror = Form("run range [%d, %d]", fRunRange[0], fRunRange[1]);
1849 serror += Form("\n or data pattern <%s>", fDataPattern.Data());
1850 Error("StartAnalysis", "No data to process. Please fix %s in your plugin configuration.", serror.Data());
1853 WriteAnalysisFile();
1854 WriteAnalysisMacro();
1856 WriteValidationScript();
1858 WriteMergingMacro();
1859 WriteMergeExecutable();
1860 WriteValidationScript(kTRUE);
1862 if (!CreateJDL()) return kFALSE;
1863 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1864 if (TestBit(AliAnalysisGrid::kTest)) {
1865 // Locally testing the analysis
1866 Info("StartAnalysis", "\n_______________________________________________________________________ \
1867 \n Running analysis script in a daughter shell as on a worker node \
1868 \n_______________________________________________________________________");
1869 TObjArray *list = fOutputFiles.Tokenize(" ");
1872 TString output_file;
1873 while((str=(TObjString*)next())) {
1874 output_file = str->GetString();
1875 Int_t index = output_file.Index("@");
1876 if (index > 0) output_file.Remove(index);
1877 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1880 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1881 TString validationScript = fExecutable;
1882 validationScript.ReplaceAll(".sh", "_validation.sh");
1883 gSystem->Exec(Form("bash %s",validationScript.Data()));
1884 // gSystem->Exec("cat stdout");
1887 // Check if submitting is managed by LPM manager
1888 if (fProductionMode) {
1889 TString prodfile = fJDLName;
1890 prodfile.ReplaceAll(".jdl", ".prod");
1891 WriteProductionFile(prodfile);
1892 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1895 // Submit AliEn job(s)
1896 gGrid->Cd(fGridOutputDir);
1899 if (!fRunNumbers.Length() && !fRunRange[0]) {
1900 // Submit a given xml or a set of runs
1901 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1902 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1904 const char *cjobId = res->GetKey(0,"jobId");
1908 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1911 Info("StartAnalysis", "\n_______________________________________________________________________ \
1912 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1913 \n_______________________________________________________________________",
1914 fJDLName.Data(), cjobId);
1919 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
1923 // Submit for a range of enumeration of runs.
1924 if (!Submit()) return kFALSE;
1927 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1928 \n You may exit at any time and terminate the job later using the option <terminate> \
1929 \n ##################################################################################", jobID.Data());
1930 gSystem->Exec("aliensh");
1934 //______________________________________________________________________________
1935 Bool_t AliAnalysisAlien::Submit()
1937 // Submit all master jobs.
1938 Int_t nmasterjobs = fInputFiles->GetEntries();
1939 Long_t tshoot = gSystem->Now();
1940 if (!fNsubmitted && !SubmitNext()) return kFALSE;
1941 while (fNsubmitted < nmasterjobs) {
1942 Long_t now = gSystem->Now();
1943 if ((now-tshoot)>30000) {
1945 if (!SubmitNext()) return kFALSE;
1951 //______________________________________________________________________________
1952 Bool_t AliAnalysisAlien::SubmitMerging()
1954 // Submit all merging jobs.
1955 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1956 gGrid->Cd(fGridOutputDir);
1957 TString mergeJDLName = fExecutable;
1958 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1959 Int_t ntosubmit = fInputFiles->GetEntries();
1960 printf("### Submitting %d merging jobs...\n", ntosubmit);
1961 for (Int_t i=0; i<ntosubmit; i++) {
1963 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
1964 runOutDir.ReplaceAll(".xml", "");
1966 query = Form("submit %s %s", mergeJDLName.Data(), runOutDir.Data());
1968 query = Form("submit %s %03d", mergeJDLName.Data(), i);
1969 printf("********* %s\n",query.Data());
1970 TGridResult *res = gGrid->Command(query);
1972 const char *cjobId = res->GetKey(0,"jobId");
1976 Error("StartAnalysis", "Your JDL %s could not be submitted", mergeJDLName.Data());
1979 Info("StartAnalysis", "\n_______________________________________________________________________ \
1980 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1981 \n_______________________________________________________________________",
1982 mergeJDLName.Data(), cjobId);
1986 Error("SubmitMerging", "No grid result after submission !!! Bailing out...");
1990 if (!ntosubmit) return kTRUE;
1991 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
1992 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
1993 \n ##################################################################################");
1994 gSystem->Exec("aliensh");
1998 //______________________________________________________________________________
1999 Bool_t AliAnalysisAlien::SubmitNext()
2001 // Submit next bunch of master jobs if the queue is free.
2002 static Bool_t iscalled = kFALSE;
2003 static Int_t firstmaster = 0;
2004 static Int_t lastmaster = 0;
2005 static Int_t npermaster = 0;
2006 if (iscalled) return kTRUE;
2008 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
2009 Int_t ntosubmit = 0;
2012 if (!fNsubmitted) ntosubmit = 1;
2014 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
2015 printf("=== master %d: %s\n", lastmaster, status.Data());
2016 // If last master not split, just return
2017 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
2018 // No more than 100 waiting jobs
2019 if (nwaiting>100) {iscalled = kFALSE; return kTRUE;}
2020 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
2021 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
2022 if (!ntosubmit) ntosubmit = 1;
2023 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
2024 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
2026 Int_t nmasterjobs = fInputFiles->GetEntries();
2027 for (Int_t i=0; i<ntosubmit; i++) {
2028 // Submit for a range of enumeration of runs.
2029 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
2031 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
2032 runOutDir.ReplaceAll(".xml", "");
2034 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
2036 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
2037 printf("********* %s\n",query.Data());
2038 res = gGrid->Command(query);
2040 TString cjobId1 = res->GetKey(0,"jobId");
2041 if (!cjobId1.Length()) {
2045 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
2048 Info("StartAnalysis", "\n_______________________________________________________________________ \
2049 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2050 \n_______________________________________________________________________",
2051 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2054 lastmaster = cjobId1.Atoi();
2055 if (!firstmaster) firstmaster = lastmaster;
2060 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2068 //______________________________________________________________________________
2069 void AliAnalysisAlien::WriteAnalysisFile()
2071 // Write current analysis manager into the file <analysisFile>
2072 TString analysisFile = fExecutable;
2073 analysisFile.ReplaceAll(".sh", ".root");
2074 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2075 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2076 if (!mgr || !mgr->IsInitialized()) {
2077 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2080 // Check analysis type
2082 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2083 handler = (TObject*)mgr->GetInputEventHandler();
2085 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2086 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2088 TDirectory *cdir = gDirectory;
2089 TFile *file = TFile::Open(analysisFile, "RECREATE");
2091 // Skip task Terminate calls for the grid job
2092 mgr->SetSkipTerminate(kTRUE);
2093 // Unless merging makes no sense
2094 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2097 // Enable termination for local jobs
2098 mgr->SetSkipTerminate(kFALSE);
2100 if (cdir) cdir->cd();
2101 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2103 Bool_t copy = kTRUE;
2104 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2107 TString workdir = gGrid->GetHomeDirectory();
2108 workdir += fGridWorkingDir;
2109 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2110 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2111 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2115 //______________________________________________________________________________
2116 void AliAnalysisAlien::WriteAnalysisMacro()
2118 // Write the analysis macro that will steer the analysis in grid mode.
2119 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2121 out.open(fAnalysisMacro.Data(), ios::out);
2123 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2126 Bool_t hasSTEERBase = kFALSE;
2127 Bool_t hasESD = kFALSE;
2128 Bool_t hasAOD = kFALSE;
2129 Bool_t hasANALYSIS = kFALSE;
2130 Bool_t hasANALYSISalice = kFALSE;
2131 Bool_t hasCORRFW = kFALSE;
2132 TString func = fAnalysisMacro;
2133 TString type = "ESD";
2134 TString comment = "// Analysis using ";
2135 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2136 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2140 if (type!="AOD" && fFriendChainName!="") {
2141 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2144 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2145 else comment += " data";
2146 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2147 func.ReplaceAll(".C", "");
2148 out << "void " << func.Data() << "()" << endl;
2150 out << comment.Data() << endl;
2151 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
2152 out << " TStopwatch timer;" << endl;
2153 out << " timer.Start();" << endl << endl;
2154 out << "// load base root libraries" << endl;
2155 out << " gSystem->Load(\"libTree\");" << endl;
2156 out << " gSystem->Load(\"libGeom\");" << endl;
2157 out << " gSystem->Load(\"libVMC\");" << endl;
2158 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2159 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2160 if (fAdditionalRootLibs.Length()) {
2161 // in principle libtree /lib geom libvmc etc. can go into this list, too
2162 out << "// Add aditional libraries" << endl;
2163 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2166 while((str=(TObjString*)next())) {
2167 if (str->GetString().Contains(".so"))
2168 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2170 if (list) delete list;
2172 out << "// include path" << endl;
2173 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2174 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2175 out << "// Load analysis framework libraries" << endl;
2177 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2178 out << " gSystem->Load(\"libESD\");" << endl;
2179 out << " gSystem->Load(\"libAOD\");" << endl;
2180 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2181 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2182 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2184 TIter next(fPackages);
2187 TString setupPar = "AliAnalysisAlien::SetupPar";
2188 while ((obj=next())) {
2189 pkgname = obj->GetName();
2190 if (pkgname == "STEERBase" ||
2191 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2192 if (pkgname == "ESD" ||
2193 pkgname == "ESD.par") hasESD = kTRUE;
2194 if (pkgname == "AOD" ||
2195 pkgname == "AOD.par") hasAOD = kTRUE;
2196 if (pkgname == "ANALYSIS" ||
2197 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2198 if (pkgname == "ANALYSISalice" ||
2199 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2200 if (pkgname == "CORRFW" ||
2201 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2203 if (hasANALYSISalice) setupPar = "SetupPar";
2204 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2205 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2206 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2207 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2208 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2209 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2210 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2211 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2212 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2213 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2214 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2215 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2216 out << "// Compile other par packages" << endl;
2218 while ((obj=next())) {
2219 pkgname = obj->GetName();
2220 if (pkgname == "STEERBase" ||
2221 pkgname == "STEERBase.par" ||
2223 pkgname == "ESD.par" ||
2225 pkgname == "AOD.par" ||
2226 pkgname == "ANALYSIS" ||
2227 pkgname == "ANALYSIS.par" ||
2228 pkgname == "ANALYSISalice" ||
2229 pkgname == "ANALYSISalice.par" ||
2230 pkgname == "CORRFW" ||
2231 pkgname == "CORRFW.par") continue;
2232 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2235 if (fAdditionalLibs.Length()) {
2236 out << "// Add aditional AliRoot libraries" << endl;
2237 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2240 while((str=(TObjString*)next())) {
2241 if (str->GetString().Contains(".so"))
2242 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2244 if (list) delete list;
2247 out << "// analysis source to be compiled at runtime (if any)" << endl;
2248 if (fAnalysisSource.Length()) {
2249 TObjArray *list = fAnalysisSource.Tokenize(" ");
2252 while((str=(TObjString*)next())) {
2253 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2255 if (list) delete list;
2258 if (fFastReadOption) {
2259 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 !!! \
2260 \n+++ NOTE: To disable this option, use: plugin->SetFastReadOption(kFALSE)");
2261 out << "// fast xrootd reading enabled" << endl;
2262 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2263 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
2264 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
2265 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2266 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
2267 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2269 out << "// connect to AliEn and make the chain" << endl;
2270 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2271 if (IsUsingTags()) {
2272 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
2274 if(fFriendChainName!="AliAOD.VertexingHF.root") {
2275 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
2277 out << " // Check if the macro to create the chain was provided" << endl;
2278 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
2279 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
2280 out << " return;" << endl;
2281 out << " }" << endl;
2282 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
2283 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
2286 out << "// read the analysis manager from file" << endl;
2287 TString analysisFile = fExecutable;
2288 analysisFile.ReplaceAll(".sh", ".root");
2289 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2290 out << " if (!file) return;" << endl;
2291 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2292 out << " AliAnalysisManager *mgr = 0;" << endl;
2293 out << " TKey *key;" << endl;
2294 out << " while ((key=(TKey*)nextkey())) {" << endl;
2295 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2296 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2297 out << " };" << endl;
2298 out << " if (!mgr) {" << endl;
2299 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2300 out << " return;" << endl;
2301 out << " }" << endl << endl;
2302 out << " mgr->PrintStatus();" << endl;
2303 if (AliAnalysisManager::GetAnalysisManager()) {
2304 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2305 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2307 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2310 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
2311 out << " timer.Stop();" << endl;
2312 out << " timer.Print();" << endl;
2313 out << "}" << endl << endl;
2314 if (IsUsingTags()) {
2315 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
2317 out << "// Create a chain using tags from the xml file." << endl;
2318 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
2319 out << " if (!coll) {" << endl;
2320 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2321 out << " return NULL;" << endl;
2322 out << " }" << endl;
2323 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
2324 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
2325 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
2326 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
2327 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
2328 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
2329 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
2330 out << " // Check if the cuts configuration file was provided" << endl;
2331 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
2332 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
2333 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2334 out << " }" << endl;
2335 if (fFriendChainName=="") {
2336 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2338 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
2339 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
2340 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
2342 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
2343 out << " chain->ls();" << endl;
2344 out << " return chain;" << endl;
2345 out << "}" << endl << endl;
2346 if (gSystem->AccessPathName("ConfigureCuts.C")) {
2347 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
2348 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
2349 msg += " AliLHCTagCuts *lhcCuts,\n";
2350 msg += " AliDetectorTagCuts *detCuts,\n";
2351 msg += " AliEventTagCuts *evCuts)";
2352 Info("WriteAnalysisMacro", msg.Data());
2355 if (!IsUsingTags() || fFriendChainName!="") {
2356 out <<"//________________________________________________________________________________" << endl;
2357 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
2359 out << "// Create a chain using url's from xml file" << endl;
2360 out << " TString treename = type;" << endl;
2361 out << " treename.ToLower();" << endl;
2362 out << " treename += \"Tree\";" << endl;
2363 out << " printf(\"***************************************\\n\");" << endl;
2364 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
2365 out << " printf(\"***************************************\\n\");" << endl;
2366 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
2367 out << " if (!coll) {" << endl;
2368 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2369 out << " return NULL;" << endl;
2370 out << " }" << endl;
2371 out << " TChain *chain = new TChain(treename);" << endl;
2372 if(fFriendChainName!="") {
2373 out << " TChain *chainFriend = new TChain(treename);" << endl;
2375 out << " coll->Reset();" << endl;
2376 out << " while (coll->Next()) {" << endl;
2377 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2378 if(fFriendChainName!="") {
2379 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2380 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2381 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2382 out << " chainFriend->Add(fileFriend.Data());" << endl;
2384 out << " }" << endl;
2385 out << " if (!chain->GetNtrees()) {" << endl;
2386 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2387 out << " return NULL;" << endl;
2388 out << " }" << endl;
2389 if(fFriendChainName!="") {
2390 out << " chain->AddFriend(chainFriend);" << endl;
2392 out << " return chain;" << endl;
2393 out << "}" << endl << endl;
2395 if (hasANALYSISalice) {
2396 out <<"//________________________________________________________________________________" << endl;
2397 out << "Bool_t SetupPar(const char *package) {" << endl;
2398 out << "// Compile the package and set it up." << endl;
2399 out << " TString pkgdir = package;" << endl;
2400 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2401 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2402 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2403 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2404 out << " // Check for BUILD.sh and execute" << endl;
2405 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2406 out << " printf(\"*******************************\\n\");" << endl;
2407 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2408 out << " printf(\"*******************************\\n\");" << endl;
2409 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2410 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2411 out << " gSystem->ChangeDirectory(cdir);" << endl;
2412 out << " return kFALSE;" << endl;
2413 out << " }" << endl;
2414 out << " } else {" << endl;
2415 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2416 out << " gSystem->ChangeDirectory(cdir);" << endl;
2417 out << " return kFALSE;" << endl;
2418 out << " }" << endl;
2419 out << " // Check for SETUP.C and execute" << endl;
2420 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2421 out << " printf(\"*******************************\\n\");" << endl;
2422 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2423 out << " printf(\"*******************************\\n\");" << endl;
2424 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2425 out << " } else {" << endl;
2426 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2427 out << " gSystem->ChangeDirectory(cdir);" << endl;
2428 out << " return kFALSE;" << endl;
2429 out << " }" << endl;
2430 out << " // Restore original workdir" << endl;
2431 out << " gSystem->ChangeDirectory(cdir);" << endl;
2432 out << " return kTRUE;" << endl;
2435 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2437 Bool_t copy = kTRUE;
2438 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2441 TString workdir = gGrid->GetHomeDirectory();
2442 workdir += fGridWorkingDir;
2443 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2444 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2445 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2446 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2447 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2449 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2450 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2454 //______________________________________________________________________________
2455 void AliAnalysisAlien::WriteMergingMacro()
2457 // Write a macro to merge the outputs per master job.
2458 if (!fMergeViaJDL) return;
2459 if (!fOutputFiles.Length()) {
2460 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2463 TString mergingMacro = fExecutable;
2464 mergingMacro.ReplaceAll(".sh","_merge.C");
2465 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2466 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2468 out.open(mergingMacro.Data(), ios::out);
2470 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2473 Bool_t hasSTEERBase = kFALSE;
2474 Bool_t hasESD = kFALSE;
2475 Bool_t hasAOD = kFALSE;
2476 Bool_t hasANALYSIS = kFALSE;
2477 Bool_t hasANALYSISalice = kFALSE;
2478 Bool_t hasCORRFW = kFALSE;
2479 TString func = mergingMacro;
2481 func.ReplaceAll(".C", "");
2482 out << "void " << func.Data() << "(const char *dir)" << endl;
2484 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
2485 out << " TStopwatch timer;" << endl;
2486 out << " timer.Start();" << endl << endl;
2487 out << "// load base root libraries" << endl;
2488 out << " gSystem->Load(\"libTree\");" << endl;
2489 out << " gSystem->Load(\"libGeom\");" << endl;
2490 out << " gSystem->Load(\"libVMC\");" << endl;
2491 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2492 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2493 if (fAdditionalRootLibs.Length()) {
2494 // in principle libtree /lib geom libvmc etc. can go into this list, too
2495 out << "// Add aditional libraries" << endl;
2496 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2499 while((str=(TObjString*)next())) {
2500 if (str->GetString().Contains(".so"))
2501 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2503 if (list) delete list;
2505 out << "// include path" << endl;
2506 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2507 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2508 out << "// Load analysis framework libraries" << endl;
2510 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2511 out << " gSystem->Load(\"libESD\");" << endl;
2512 out << " gSystem->Load(\"libAOD\");" << endl;
2513 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2514 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2515 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2517 TIter next(fPackages);
2520 TString setupPar = "AliAnalysisAlien::SetupPar";
2521 while ((obj=next())) {
2522 pkgname = obj->GetName();
2523 if (pkgname == "STEERBase" ||
2524 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2525 if (pkgname == "ESD" ||
2526 pkgname == "ESD.par") hasESD = kTRUE;
2527 if (pkgname == "AOD" ||
2528 pkgname == "AOD.par") hasAOD = kTRUE;
2529 if (pkgname == "ANALYSIS" ||
2530 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2531 if (pkgname == "ANALYSISalice" ||
2532 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2533 if (pkgname == "CORRFW" ||
2534 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2536 if (hasANALYSISalice) setupPar = "SetupPar";
2537 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2538 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2539 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2540 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2541 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2542 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2543 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2544 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2545 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2546 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2547 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2548 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2549 out << "// Compile other par packages" << endl;
2551 while ((obj=next())) {
2552 pkgname = obj->GetName();
2553 if (pkgname == "STEERBase" ||
2554 pkgname == "STEERBase.par" ||
2556 pkgname == "ESD.par" ||
2558 pkgname == "AOD.par" ||
2559 pkgname == "ANALYSIS" ||
2560 pkgname == "ANALYSIS.par" ||
2561 pkgname == "ANALYSISalice" ||
2562 pkgname == "ANALYSISalice.par" ||
2563 pkgname == "CORRFW" ||
2564 pkgname == "CORRFW.par") continue;
2565 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2568 if (fAdditionalLibs.Length()) {
2569 out << "// Add aditional AliRoot libraries" << endl;
2570 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2573 while((str=(TObjString*)next())) {
2574 if (str->GetString().Contains(".so"))
2575 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2577 if (list) delete list;
2580 out << "// Analysis source to be compiled at runtime (if any)" << endl;
2581 if (fAnalysisSource.Length()) {
2582 TObjArray *list = fAnalysisSource.Tokenize(" ");
2585 while((str=(TObjString*)next())) {
2586 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2588 if (list) delete list;
2591 if (fFastReadOption) {
2592 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 !!!");
2593 out << "// fast xrootd reading enabled" << endl;
2594 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2595 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",10);" << endl;
2596 out << " gEnv->SetValue(\"XNet.RequestTimeout\",10);" << endl;
2597 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2598 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",10);" << endl;
2599 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2601 out << "// Connect to AliEn" << endl;
2602 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2603 out << " TString outputDir = \"" << fGridOutputDir << "/\";" << endl;
2604 out << " outputDir += dir;" << endl;
2605 out << " TString outputFiles = \"" << fOutputFiles << "\";" << endl;
2606 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
2607 out << " mergeExcludes += \"" << AliAnalysisManager::GetAnalysisManager()->GetExtraFiles() << "\";" << endl;
2608 out << " TObjArray *list = outputFiles.Tokenize(\" \");" << endl;
2609 out << " TIter *iter = new TIter(list);" << endl;
2610 out << " TObjString *str;" << endl;
2611 out << " TString output_file;" << endl;
2612 out << " Bool_t merged = kTRUE;" << endl;
2613 out << " while((str=(TObjString*)iter->Next())) {" << endl;
2614 out << " output_file = str->GetString();" << endl;
2615 out << " Int_t index = output_file.Index(\"@\");" << endl;
2616 out << " if (index > 0) output_file.Remove(index);" << endl;
2617 out << " // Skip already merged outputs" << endl;
2618 out << " if (!gSystem->AccessPathName(output_file)) {" << endl;
2619 out << " printf(\"Output file <%s> found. Not merging again.\",output_file.Data());" << endl;
2620 out << " continue;" << endl;
2621 out << " }" << endl;
2622 out << " if (mergeExcludes.Contains(output_file.Data())) continue;" << endl;
2623 out << " merged = AliAnalysisAlien::MergeOutput(output_file, outputDir, " << fMaxMergeFiles << ");" << endl;
2624 out << " if (!merged) {" << endl;
2625 out << " printf(\"ERROR: Cannot merge %s\\n\", output_file.Data());" << endl;
2626 out << " }" << endl;
2627 out << " }" << endl;
2628 out << "// read the analysis manager from file" << endl;
2629 TString analysisFile = fExecutable;
2630 analysisFile.ReplaceAll(".sh", ".root");
2631 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2632 out << " if (!file) return;" << endl;
2633 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2634 out << " AliAnalysisManager *mgr = 0;" << endl;
2635 out << " TKey *key;" << endl;
2636 out << " while ((key=(TKey*)nextkey())) {" << endl;
2637 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2638 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2639 out << " };" << endl;
2640 out << " if (!mgr) {" << endl;
2641 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2642 out << " return;" << endl;
2643 out << " }" << endl << endl;
2644 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
2645 out << " mgr->PrintStatus();" << endl;
2646 if (AliAnalysisManager::GetAnalysisManager()) {
2647 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2648 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2650 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2653 out << " mgr->StartAnalysis(\"gridterminate\");" << endl;
2654 out << "}" << endl << endl;
2655 if (hasANALYSISalice) {
2656 out <<"//________________________________________________________________________________" << endl;
2657 out << "Bool_t SetupPar(const char *package) {" << endl;
2658 out << "// Compile the package and set it up." << endl;
2659 out << " TString pkgdir = package;" << endl;
2660 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2661 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2662 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2663 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2664 out << " // Check for BUILD.sh and execute" << endl;
2665 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2666 out << " printf(\"*******************************\\n\");" << endl;
2667 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2668 out << " printf(\"*******************************\\n\");" << endl;
2669 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2670 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2671 out << " gSystem->ChangeDirectory(cdir);" << endl;
2672 out << " return kFALSE;" << endl;
2673 out << " }" << endl;
2674 out << " } else {" << endl;
2675 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2676 out << " gSystem->ChangeDirectory(cdir);" << endl;
2677 out << " return kFALSE;" << endl;
2678 out << " }" << endl;
2679 out << " // Check for SETUP.C and execute" << endl;
2680 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2681 out << " printf(\"*******************************\\n\");" << endl;
2682 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2683 out << " printf(\"*******************************\\n\");" << endl;
2684 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2685 out << " } else {" << endl;
2686 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2687 out << " gSystem->ChangeDirectory(cdir);" << endl;
2688 out << " return kFALSE;" << endl;
2689 out << " }" << endl;
2690 out << " // Restore original workdir" << endl;
2691 out << " gSystem->ChangeDirectory(cdir);" << endl;
2692 out << " return kTRUE;" << endl;
2696 Bool_t copy = kTRUE;
2697 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2700 TString workdir = gGrid->GetHomeDirectory();
2701 workdir += fGridWorkingDir;
2702 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
2703 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
2704 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
2708 //______________________________________________________________________________
2709 Bool_t AliAnalysisAlien::SetupPar(const char *package)
2711 // Compile the par file archive pointed by <package>. This must be present in the current durectory.
2712 // Note that for loading the compiled library. The current directory should have precedence in
2714 TString pkgdir = package;
2715 pkgdir.ReplaceAll(".par","");
2716 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
2717 TString cdir = gSystem->WorkingDirectory();
2718 gSystem->ChangeDirectory(pkgdir);
2719 // Check for BUILD.sh and execute
2720 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
2721 printf("**************************************************\n");
2722 printf("*** Building PAR archive %s\n", package);
2723 printf("**************************************************\n");
2724 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
2725 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
2726 gSystem->ChangeDirectory(cdir);
2730 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
2731 gSystem->ChangeDirectory(cdir);
2734 // Check for SETUP.C and execute
2735 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
2736 printf("**************************************************\n");
2737 printf("*** Setup PAR archive %s\n", package);
2738 printf("**************************************************\n");
2739 gROOT->Macro("PROOF-INF/SETUP.C");
2740 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
2742 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
2743 gSystem->ChangeDirectory(cdir);
2746 // Restore original workdir
2747 gSystem->ChangeDirectory(cdir);
2751 //______________________________________________________________________________
2752 void AliAnalysisAlien::WriteExecutable()
2754 // Generate the alien executable script.
2755 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2757 out.open(fExecutable.Data(), ios::out);
2759 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2762 out << "#!/bin/bash" << endl;
2763 out << "echo \"=========================================\"" << endl;
2764 out << "echo \"############## PATH : ##############\"" << endl;
2765 out << "echo $PATH" << endl;
2766 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2767 out << "echo $LD_LIBRARY_PATH" << endl;
2768 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2769 out << "echo $ROOTSYS" << endl;
2770 out << "echo \"############## which root : ##############\"" << endl;
2771 out << "which root" << endl;
2772 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2773 out << "echo $ALICE_ROOT" << endl;
2774 out << "echo \"############## which aliroot : ##############\"" << endl;
2775 out << "which aliroot" << endl;
2776 out << "echo \"############## system limits : ##############\"" << endl;
2777 out << "ulimit -a" << endl;
2778 out << "echo \"############## memory : ##############\"" << endl;
2779 out << "free -m" << endl;
2780 out << "echo \"=========================================\"" << endl << endl;
2781 // Make sure we can properly compile par files
2782 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2783 out << fExecutableCommand << " ";
2784 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2785 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2786 out << "echo \"############## memory after: ##############\"" << endl;
2787 out << "free -m" << endl;
2788 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2789 out << "dmesg | tail -n 10" << endl;
2791 Bool_t copy = kTRUE;
2792 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2795 TString workdir = gGrid->GetHomeDirectory();
2796 TString bindir = Form("%s/bin", workdir.Data());
2797 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2798 workdir += fGridWorkingDir;
2799 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2800 if (FileExists(executable)) gGrid->Rm(executable);
2801 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2802 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2806 //______________________________________________________________________________
2807 void AliAnalysisAlien::WriteMergeExecutable()
2809 // Generate the alien executable script for the merging job.
2810 if (!fMergeViaJDL) return;
2811 TString mergeExec = fExecutable;
2812 mergeExec.ReplaceAll(".sh", "_merge.sh");
2813 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2815 out.open(mergeExec.Data(), ios::out);
2817 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
2820 out << "#!/bin/bash" << endl;
2821 out << "echo \"=========================================\"" << endl;
2822 out << "echo \"############## PATH : ##############\"" << endl;
2823 out << "echo $PATH" << endl;
2824 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2825 out << "echo $LD_LIBRARY_PATH" << endl;
2826 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2827 out << "echo $ROOTSYS" << endl;
2828 out << "echo \"############## which root : ##############\"" << endl;
2829 out << "which root" << endl;
2830 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2831 out << "echo $ALICE_ROOT" << endl;
2832 out << "echo \"############## which aliroot : ##############\"" << endl;
2833 out << "which aliroot" << endl;
2834 out << "echo \"############## system limits : ##############\"" << endl;
2835 out << "ulimit -a" << endl;
2836 out << "echo \"############## memory : ##############\"" << endl;
2837 out << "free -m" << endl;
2838 out << "echo \"=========================================\"" << endl << endl;
2839 // Make sure we can properly compile par files
2840 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2841 TString mergeMacro = fExecutable;
2842 mergeMacro.ReplaceAll(".sh", "_merge.C");
2843 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
2844 out << fExecutableCommand << " " << "$ARG" << endl;
2845 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
2846 out << "echo \"############## memory after: ##############\"" << endl;
2847 out << "free -m" << endl;
2848 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2849 out << "dmesg | tail -n 10" << endl;
2851 Bool_t copy = kTRUE;
2852 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2855 TString workdir = gGrid->GetHomeDirectory();
2856 TString bindir = Form("%s/bin", workdir.Data());
2857 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2858 workdir += fGridWorkingDir;
2859 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
2860 if (FileExists(executable)) gGrid->Rm(executable);
2861 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
2862 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
2866 //______________________________________________________________________________
2867 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2869 // Write the production file to be submitted by LPM manager. The format is:
2870 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2871 // Next lines: full_path_to_dataset XXX (XXX is a string)
2872 // To submit, one has to: submit jdl XXX for all lines
2874 out.open(filename, ios::out);
2876 Error("WriteProductionFile", "Bad file name: %s", filename);
2879 TString workdir = gGrid->GetHomeDirectory();
2880 workdir += fGridWorkingDir;
2881 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2882 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2883 out << locjdl << " " << njobspermaster << endl;
2884 Int_t nmasterjobs = fInputFiles->GetEntries();
2885 for (Int_t i=0; i<nmasterjobs; i++) {
2886 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2887 runOutDir.ReplaceAll(".xml", "");
2889 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
2891 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2893 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2894 if (FileExists(filename)) gGrid->Rm(filename);
2895 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2898 //______________________________________________________________________________
2899 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
2901 // Generate the alien validation script.
2902 // Generate the validation script
2904 TString validationScript = fExecutable;
2905 if (merge) validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
2906 else validationScript.ReplaceAll(".sh", "_validation.sh");
2908 Error("WriteValidationScript", "Alien connection required");
2911 TString out_stream = "";
2912 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2913 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2915 out.open(validationScript, ios::out);
2916 out << "#!/bin/bash" << endl;
2917 out << "##################################################" << endl;
2918 out << "validateout=`dirname $0`" << endl;
2919 out << "validatetime=`date`" << endl;
2920 out << "validated=\"0\";" << endl;
2921 out << "error=0" << endl;
2922 out << "if [ -z $validateout ]" << endl;
2923 out << "then" << endl;
2924 out << " validateout=\".\"" << endl;
2925 out << "fi" << endl << endl;
2926 out << "cd $validateout;" << endl;
2927 out << "validateworkdir=`pwd`;" << endl << endl;
2928 out << "echo \"*******************************************************\"" << out_stream << endl;
2929 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2931 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2932 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2933 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2934 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2935 out << "ls -la ./" << out_stream << endl;
2936 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2937 out << "##################################################" << endl;
2940 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2941 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2942 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2945 out << "if [ ! -f stderr ] ; then" << endl;
2946 out << " error=1" << endl;
2947 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2948 out << " echo \"Error = $error\" " << out_stream << endl;
2949 out << "fi" << endl;
2951 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2952 out << " error=1" << endl;
2953 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2954 out << " echo \"$parArch\" " << out_stream << endl;
2955 out << " echo \"Error = $error\" " << out_stream << endl;
2956 out << "fi" << endl;
2958 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2959 out << " error=1" << endl;
2960 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2961 out << " echo \"$segViol\" " << out_stream << endl;
2962 out << " echo \"Error = $error\" " << out_stream << endl;
2963 out << "fi" << endl;
2965 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2966 out << " error=1" << endl;
2967 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2968 out << " echo \"$segFault\" " << out_stream << endl;
2969 out << " echo \"Error = $error\" " << out_stream << endl;
2970 out << "fi" << endl;
2972 // Part dedicated to the specific analyses running into the train
2974 TObjArray *arr = fOutputFiles.Tokenize(" ");
2976 TString output_file;
2977 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2978 TString extra = mgr->GetExtraFiles();
2979 while ((os=(TObjString*)next1())) {
2980 output_file = os->GetString();
2981 Int_t index = output_file.Index("@");
2982 if (index > 0) output_file.Remove(index);
2983 if (merge && fMergeExcludes.Contains(output_file)) continue;
2984 if (extra.Contains(output_file)) continue;
2985 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2986 out << " error=1" << endl;
2987 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2988 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2989 out << "fi" << endl;
2993 out << "if ! [ -f outputs_valid ] ; then" << endl;
2994 out << " error=1" << endl;
2995 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2996 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2997 out << "fi" << endl;
3000 out << "if [ $error = 0 ] ; then" << endl;
3001 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
3002 out << "fi" << endl;
3004 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
3005 out << "echo \"*******************************************************\"" << out_stream << endl;
3006 out << "cd -" << endl;
3007 out << "exit $error" << endl;
3009 Bool_t copy = kTRUE;
3010 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
3013 TString workdir = gGrid->GetHomeDirectory();
3014 workdir += fGridWorkingDir;
3015 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
3016 if (FileExists(validationScript)) gGrid->Rm(validationScript);
3017 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));