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 // Check if alien_CLOSE_SE is defined
409 TString closeSE = gSystem->Getenv("alien_CLOSE_SE");
410 if (!closeSE.IsNull()) {
411 Info("CheckFileCopy", "Your current close storage is pointing to: \
412 \n alien_CLOSE_SE = \"%s\"", closeSE.Data());
414 Warning("CheckFileCopy", "Your current close storage is empty ! Depending on your location, file copying may fail.");
416 // Check if grid directory exists.
417 if (!DirectoryExists(alienpath)) {
418 Error("CheckFileCopy", "Alien path %s does not seem to exist", alienpath);
421 TFile f("plugin_test_copy.root", "RECREATE");
422 // User may not have write permissions to current directory
424 Error("CheckFileCopy", "Cannot create local test file. Do you have write access to current directory: <%s> ?",
425 gSystem->WorkingDirectory());
429 TString s = f.GetUUID().AsString();
430 s.ReplaceAll("-",""); // AliEn copy does not like too many '-'
431 if (!TFile::Cp(f.GetName(), Form("alien://%s/%s",alienpath, s.Data()))) {
432 Error("CheckFileCopy", "Cannot copy files to Alien destination: %s \
433 \n# 1. Make sure you have write permissions there. If this is the case: \
434 \n# 2. Check the storage availability at: http://alimonitor.cern.ch/stats?page=SE/table \
435 \n# Do: export alien_CLOSE_SE=\"working_disk_SE\" \
436 \n# To make this permanent put in in your .bashrc (in .alienshrc is not enough) \
437 \n# Redo token: rm /tmp/x509up_u$UID then: alien-token-init <username>", alienpath);
438 gSystem->Unlink(f.GetName());
441 gSystem->Unlink(f.GetName());
442 gGrid->Rm(Form("%s%s",alienpath,s.Data()));
446 //______________________________________________________________________________
447 Bool_t AliAnalysisAlien::CheckInputData()
449 // Check validity of input data. If necessary, create xml files.
450 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
451 if (!fGridDataDir.Length()) {
452 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
455 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
458 // Process declared files
459 Bool_t is_collection = kFALSE;
460 Bool_t is_xml = kFALSE;
461 Bool_t use_tags = kFALSE;
462 Bool_t checked = kFALSE;
465 TString workdir = gGrid->GetHomeDirectory();
466 workdir += fGridWorkingDir;
469 TIter next(fInputFiles);
470 while ((objstr=(TObjString*)next())) {
473 file += objstr->GetString();
474 // Store full lfn path
475 if (FileExists(file)) objstr->SetString(file);
477 file = objstr->GetName();
478 if (!FileExists(objstr->GetName())) {
479 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
480 objstr->GetName(), workdir.Data());
484 Bool_t iscoll, isxml, usetags;
485 CheckDataType(file, iscoll, isxml, usetags);
488 is_collection = iscoll;
491 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
493 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
494 Error("CheckInputData", "Some conflict was found in the types of inputs");
500 // Process requested run numbers
501 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
502 // Check validity of alien data directory
503 if (!fGridDataDir.Length()) {
504 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
507 if (!DirectoryExists(fGridDataDir)) {
508 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
512 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
516 if (checked && !is_xml) {
517 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
520 // Check validity of run number(s)
524 TString schunk, schunk2;
528 use_tags = fDataPattern.Contains("tag");
529 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
531 if (use_tags != fDataPattern.Contains("tag")) {
532 Error("CheckInputData", "Cannot mix input files using/not using tags");
535 if (fRunNumbers.Length()) {
536 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
537 arr = fRunNumbers.Tokenize(" ");
539 while ((os=(TObjString*)next())) {
540 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
541 if (!DirectoryExists(path)) {
542 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
545 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
546 TString msg = "\n##### file: ";
548 msg += " type: xml_collection;";
549 if (use_tags) msg += " using_tags: Yes";
550 else msg += " using_tags: No";
551 Info("CheckDataType", msg.Data());
552 if (fNrunsPerMaster<2) {
553 AddDataFile(Form("%s.xml", os->GetString().Data()));
556 if (((nruns-1)%fNrunsPerMaster) == 0) {
557 schunk = os->GetString();
559 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
560 schunk += Form("_%s.xml", os->GetString().Data());
566 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
567 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
568 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
569 if (!DirectoryExists(path)) {
570 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
573 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
574 TString msg = "\n##### file: ";
576 msg += " type: xml_collection;";
577 if (use_tags) msg += " using_tags: Yes";
578 else msg += " using_tags: No";
579 Info("CheckDataType", msg.Data());
580 if (fNrunsPerMaster<2) {
581 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
584 if (((nruns-1)%fNrunsPerMaster) == 0) {
585 schunk = Form("%s%d", fRunPrefix.Data(),irun);
587 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
588 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
601 //______________________________________________________________________________
602 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
604 // Create dataset for the grid data directory + run number.
605 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
607 Error("CreateDataset", "Cannot create dataset with no grid connection");
613 TString workdir = gGrid->GetHomeDirectory();
614 workdir += fGridWorkingDir;
616 // Compose the 'find' command arguments
618 TString options = "-x collection ";
619 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
620 TString conditions = "";
625 TString schunk, schunk2;
626 TGridCollection *cbase=0, *cadd=0;
627 if (!fRunNumbers.Length() && !fRunRange[0]) {
628 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
629 // Make a single data collection from data directory.
631 if (!DirectoryExists(path)) {
632 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
636 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
637 else file = Form("%s.xml", gSystem->BaseName(path));
638 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest) || fOverwriteMode) {
644 command += conditions;
645 printf("command: %s\n", command.Data());
646 TGridResult *res = gGrid->Command(command);
648 // Write standard output to file
649 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
651 Bool_t fileExists = FileExists(file);
652 if (!TestBit(AliAnalysisGrid::kTest) && (!fileExists || fOverwriteMode)) {
653 // Copy xml file to alien space
654 if (fileExists) gGrid->Rm(file);
655 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
656 if (!FileExists(file)) {
657 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
660 // Update list of files to be processed.
662 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
666 if (fRunNumbers.Length()) {
667 TObjArray *arr = fRunNumbers.Tokenize(" ");
670 while ((os=(TObjString*)next())) {
671 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
672 if (!DirectoryExists(path)) continue;
674 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
675 else file = Form("%s.xml", os->GetString().Data());
676 // If local collection file does not exist, create it via 'find' command.
677 if (gSystem->AccessPathName(file)) {
682 command += conditions;
683 TGridResult *res = gGrid->Command(command);
685 // Write standard output to file
686 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
688 if (TestBit(AliAnalysisGrid::kTest)) break;
689 // Check if there is one run per master job.
690 if (fNrunsPerMaster<2) {
691 if (FileExists(file)) {
692 if (fOverwriteMode) gGrid->Rm(file);
694 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
698 // Copy xml file to alien space
699 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
700 if (!FileExists(file)) {
701 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
707 if (((nruns-1)%fNrunsPerMaster) == 0) {
708 schunk = os->GetString();
709 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
711 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
712 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
716 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
719 schunk += Form("_%s.xml", os->GetString().Data());
720 if (FileExists(schunk)) {
721 if (fOverwriteMode) gGrid->Rm(file);
723 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
727 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
728 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
729 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
730 if (!FileExists(schunk)) {
731 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
739 // Process a full run range.
740 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
741 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
742 if (!DirectoryExists(path)) continue;
744 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
745 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
746 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
747 if (fOverwriteMode) gGrid->Rm(file);
749 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
753 // If local collection file does not exist, create it via 'find' command.
754 if (gSystem->AccessPathName(file) || fOverwriteMode) {
759 command += conditions;
760 TGridResult *res = gGrid->Command(command);
762 // Write standard output to file
763 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
765 if (TestBit(AliAnalysisGrid::kTest)) break;
766 // Check if there is one run per master job.
767 if (fNrunsPerMaster<2) {
768 if (FileExists(file)) {
769 if (fOverwriteMode) gGrid->Rm(file);
771 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
775 // Copy xml file to alien space
776 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
777 if (!FileExists(file)) {
778 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
783 // Check if the collection for the chunk exist locally.
784 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
785 if (FileExists(fInputFiles->At(nchunk)->GetName())) {
786 if (fOverwriteMode) gGrid->Rm(fInputFiles->At(nchunk)->GetName());
789 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
790 if (((nruns-1)%fNrunsPerMaster) == 0) {
791 schunk = Form("%s%d", fRunPrefix.Data(), irun);
792 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
794 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
798 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
799 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
803 if (FileExists(schunk)) {
804 if (fOverwriteMode) gGrid->Rm(schunk);
806 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
810 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
811 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
812 if (FileExists(schunk)) {
813 if (fOverwriteMode) gGrid->Rm(schunk);
815 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
819 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
820 if (!FileExists(schunk)) {
821 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
830 //______________________________________________________________________________
831 Bool_t AliAnalysisAlien::CreateJDL()
833 // Generate a JDL file according to current settings. The name of the file is
834 // specified by fJDLName.
835 Bool_t error = kFALSE;
838 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
839 Bool_t generate = kTRUE;
840 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
842 Error("CreateJDL", "Alien connection required");
845 // Check validity of alien workspace
847 TString workdir = gGrid->GetHomeDirectory();
848 workdir += fGridWorkingDir;
852 Error("CreateJDL()", "Define some input files for your analysis.");
855 // Compose list of input files
856 // Check if output files were defined
857 if (!fOutputFiles.Length()) {
858 Error("CreateJDL", "You must define at least one output file");
861 // Check if an output directory was defined and valid
862 if (!fGridOutputDir.Length()) {
863 Error("CreateJDL", "You must define AliEn output directory");
866 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
867 if (!DirectoryExists(fGridOutputDir)) {
868 if (gGrid->Mkdir(fGridOutputDir)) {
869 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
871 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
877 // Exit if any error up to now
878 if (error) return kFALSE;
880 if (!fUser.IsNull()) {
881 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
882 fMergingJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
884 fGridJDL->SetExecutable(fExecutable, "This is the startup script");
885 TString mergeExec = fExecutable;
886 mergeExec.ReplaceAll(".sh", "_merge.sh");
887 fMergingJDL->SetExecutable(mergeExec, "This is the startup script");
888 mergeExec.ReplaceAll(".sh", ".C");
889 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),mergeExec.Data()), "List of input files to be uploaded to workers");
890 if (!fArguments.IsNull())
891 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
892 fMergingJDL->SetArguments("$1");
893 fGridJDL->SetValue("TTL", Form("\"%d\"",fTTL));
894 fGridJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
895 fMergingJDL->SetValue("TTL", Form("\"%d\"",fTTL));
896 fMergingJDL->SetDescription("TTL", Form("Time after which the job is killed (%d min.)", fTTL/60));
898 if (fMaxInitFailed > 0) {
899 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
900 fGridJDL->SetDescription("MaxInitFailed", "Maximum number of first failing jobs to abort the master job");
902 if (fSplitMaxInputFileNumber > 0) {
903 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
904 fGridJDL->SetDescription("SplitMaxInputFileNumber", "Maximum number of input files to be processed per subjob");
906 if (fSplitMode.Length()) {
907 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
908 fGridJDL->SetDescription("Split", "We split per SE or file");
910 if (!fAliROOTVersion.IsNull()) {
911 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion,"VO_ALICE", "List of requested packages");
912 fMergingJDL->AddToPackages("AliRoot", fAliROOTVersion, "VO_ALICE", "List of requested packages");
914 if (!fROOTVersion.IsNull()) {
915 fGridJDL->AddToPackages("ROOT", fROOTVersion);
916 fMergingJDL->AddToPackages("ROOT", fROOTVersion);
918 if (!fAPIVersion.IsNull()) {
919 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
920 fMergingJDL->AddToPackages("APISCONFIG", fAPIVersion);
922 if (!fExternalPackages.IsNull()) {
923 arr = fExternalPackages.Tokenize(" ");
925 while ((os=(TObjString*)next())) {
926 TString pkgname = os->GetString();
927 Int_t index = pkgname.Index("::");
928 TString pkgversion = pkgname(index+2, pkgname.Length());
929 pkgname.Remove(index);
930 fGridJDL->AddToPackages(pkgname, pkgversion);
931 fMergingJDL->AddToPackages(pkgname, pkgversion);
935 fGridJDL->SetInputDataListFormat(fInputFormat, "Format of input data");
936 fGridJDL->SetInputDataList("wn.xml", "Collection name to be processed on each worker node");
937 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()), "List of input files to be uploaded to workers");
938 TString analysisFile = fExecutable;
939 analysisFile.ReplaceAll(".sh", ".root");
940 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
941 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
942 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
943 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
944 if (fAdditionalLibs.Length()) {
945 arr = fAdditionalLibs.Tokenize(" ");
947 while ((os=(TObjString*)next())) {
948 if (os->GetString().Contains(".so")) continue;
949 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
950 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
955 TIter next(fPackages);
957 while ((obj=next())) {
958 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
959 fMergingJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
962 if (fOutputArchive.Length()) {
963 arr = fOutputArchive.Tokenize(" ");
965 Bool_t first = kTRUE;
966 const char *comment = "Files to be archived";
967 const char *comment1 = comment;
968 while ((os=(TObjString*)next())) {
969 if (!first) comment = NULL;
970 if (!os->GetString().Contains("@") && fCloseSE.Length())
971 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
973 fGridJDL->AddToOutputArchive(os->GetString(), comment);
977 TString outputArchive = fOutputArchive;
978 if (!fMergeExcludes.IsNull()) {
979 arr = fMergeExcludes.Tokenize(" ");
981 while ((os=(TObjString*)next1())) {
982 outputArchive.ReplaceAll(Form("%s,",os->GetString().Data()),"");
983 outputArchive.ReplaceAll(os->GetString(),"");
987 arr = outputArchive.Tokenize(" ");
991 while ((os=(TObjString*)next2())) {
992 if (!first) comment = NULL;
993 if (!os->GetString().Contains("@") && fCloseSE.Length())
994 fMergingJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
996 fMergingJDL->AddToOutputArchive(os->GetString(), comment);
1001 arr = fOutputFiles.Tokenize(" ");
1003 Bool_t first = kTRUE;
1004 const char *comment = "Files to be archived";
1005 const char *comment1 = comment;
1006 while ((os=(TObjString*)next())) {
1007 // Ignore ouputs in jdl that are also in outputarchive
1008 TString sout = os->GetString();
1009 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1010 if (fOutputArchive.Contains(sout)) continue;
1011 if (!first) comment = NULL;
1012 if (!os->GetString().Contains("@") && fCloseSE.Length())
1013 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1015 fGridJDL->AddToOutputSandbox(os->GetString(), comment);
1019 if (fOutputFiles.Length()) {
1020 TString outputFiles = fOutputFiles;
1021 if (!fMergeExcludes.IsNull()) {
1022 arr = fMergeExcludes.Tokenize(" ");
1024 while ((os=(TObjString*)next1())) {
1025 outputFiles.ReplaceAll(Form("%s,",os->GetString().Data()),"");
1026 outputFiles.ReplaceAll(os->GetString(),"");
1030 arr = outputFiles.Tokenize(" ");
1034 while ((os=(TObjString*)next2())) {
1035 // Ignore ouputs in jdl that are also in outputarchive
1036 TString sout = os->GetString();
1037 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
1038 if (fOutputArchive.Contains(sout)) continue;
1039 if (!first) comment = NULL;
1040 if (!os->GetString().Contains("@") && fCloseSE.Length())
1041 fMergingJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()), comment);
1043 fMergingJDL->AddToOutputSandbox(os->GetString(), comment);
1047 fGridJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1048 fMergingJDL->SetPrice((UInt_t)fPrice, "AliEn price for this job");
1049 TString validationScript = fExecutable;
1050 validationScript.ReplaceAll(".sh", "_validation.sh");
1051 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1052 validationScript = fExecutable;
1053 validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
1054 fMergingJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()), "Validation script to be run for each subjob");
1055 if (fMasterResubmitThreshold) {
1056 fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
1057 fGridJDL->SetDescription("MasterResubmitThreshold", "Resubmit failed jobs until DONE rate reaches this percentage");
1059 // Write a jdl with 2 input parameters: collection name and output dir name.
1062 // Copy jdl to grid workspace
1064 // Check if an output directory was defined and valid
1065 if (!fGridOutputDir.Length()) {
1066 Error("CreateJDL", "You must define AliEn output directory");
1069 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
1070 if (!fProductionMode && !DirectoryExists(fGridOutputDir)) {
1071 if (gGrid->Mkdir(fGridOutputDir)) {
1072 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
1074 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
1080 if (TestBit(AliAnalysisGrid::kSubmit)) {
1081 TString mergeJDLName = fExecutable;
1082 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1083 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1084 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1085 if (fProductionMode) {
1086 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1087 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1089 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1090 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1091 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1092 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1094 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1095 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1098 if (fAdditionalLibs.Length()) {
1099 arr = fAdditionalLibs.Tokenize(" ");
1102 while ((os=(TObjString*)next())) {
1103 if (os->GetString().Contains(".so")) continue;
1104 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
1105 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
1106 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
1111 TIter next(fPackages);
1113 while ((obj=next())) {
1114 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
1115 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
1116 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
1123 //______________________________________________________________________________
1124 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
1126 // Writes one or more JDL's corresponding to findex. If findex is negative,
1127 // all run numbers are considered in one go (jdl). For non-negative indices
1128 // they correspond to the indices in the array fInputFiles.
1129 if (!fInputFiles) return kFALSE;
1131 TString workdir = gGrid->GetHomeDirectory();
1132 workdir += fGridWorkingDir;
1134 if (!fRunNumbers.Length() && !fRunRange[0]) {
1135 // One jdl with no parameters in case input data is specified by name.
1136 TIter next(fInputFiles);
1137 while ((os=(TObjString*)next()))
1138 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()), "Input xml collections");
1139 if (!fOutputSingle.IsNull())
1140 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()), "Output directory");
1142 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1143 fMergingJDL->SetOutputDirectory(fGridOutputDir);
1146 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
1147 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()), "Input xml collections");
1148 if (!fOutputSingle.IsNull()) {
1149 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()), "Output directory");
1150 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()), "Output directory");
1152 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()), "Output directory");
1153 fMergingJDL->SetOutputDirectory(Form("%s/$1", fGridOutputDir.Data()), "Output directory");
1158 // Generate the JDL as a string
1159 TString sjdl = fGridJDL->Generate();
1160 TString sjdl1 = fMergingJDL->Generate();
1162 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1163 sjdl.ReplaceAll("(member", "\n (member");
1164 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1165 sjdl.ReplaceAll("{", "{\n ");
1166 sjdl.ReplaceAll("};", "\n};");
1167 sjdl.ReplaceAll("{\n \n", "{\n");
1168 sjdl.ReplaceAll("\n\n", "\n");
1169 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1170 sjdl1.ReplaceAll("\"LF:", "\n \"LF:");
1171 sjdl1.ReplaceAll("(member", "\n (member");
1172 sjdl1.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1173 sjdl1.ReplaceAll("{", "{\n ");
1174 sjdl1.ReplaceAll("};", "\n};");
1175 sjdl1.ReplaceAll("{\n \n", "{\n");
1176 sjdl1.ReplaceAll("\n\n", "\n");
1177 sjdl1.ReplaceAll("OutputDirectory", "OutputDir");
1178 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1179 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1180 index = sjdl.Index("JDLVariables");
1181 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1182 sjdl1 += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1183 sjdl1.Prepend(Form("Jobtag = {\n \"comment:Merging_%s\"\n};\n", fJobTag.Data()));
1184 index = sjdl1.Index("JDLVariables");
1185 if (index >= 0) sjdl1.Insert(index, "\n# JDL variables\n");
1186 // Write jdl to file
1188 out.open(fJDLName.Data(), ios::out);
1190 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1193 out << sjdl << endl;
1194 TString mergeJDLName = fExecutable;
1195 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1198 out1.open(mergeJDLName.Data(), ios::out);
1200 Error("CreateJDL", "Bad file name: %s", mergeJDLName.Data());
1203 out1 << sjdl1 << endl;
1206 // Copy jdl to grid workspace
1208 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1210 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1211 TString locjdl1 = Form("%s/%s", fGridOutputDir.Data(),mergeJDLName.Data());
1212 if (fProductionMode) {
1213 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1214 locjdl1 = Form("%s/%s", workdir.Data(),mergeJDLName.Data());
1216 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1217 if (FileExists(locjdl1)) gGrid->Rm(locjdl1);
1218 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1219 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1221 Info("CreateJDL", "\n##### Copying merging JDL file <%s> to your AliEn output directory", mergeJDLName.Data());
1222 TFile::Cp(Form("file:%s",mergeJDLName.Data()), Form("alien://%s", locjdl1.Data()));
1228 //______________________________________________________________________________
1229 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1231 // Returns true if file exists.
1232 if (!gGrid) return kFALSE;
1233 TGridResult *res = gGrid->Ls(lfn);
1234 if (!res) return kFALSE;
1235 TMap *map = dynamic_cast<TMap*>(res->At(0));
1240 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1241 if (!objs || !objs->GetString().Length()) {
1249 //______________________________________________________________________________
1250 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1252 // Returns true if directory exists. Can be also a path.
1253 if (!gGrid) return kFALSE;
1254 // Check if dirname is a path
1255 TString dirstripped = dirname;
1256 dirstripped = dirstripped.Strip();
1257 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1258 TString dir = gSystem->BaseName(dirstripped);
1260 TString path = gSystem->DirName(dirstripped);
1261 TGridResult *res = gGrid->Ls(path, "-F");
1262 if (!res) return kFALSE;
1266 while ((map=dynamic_cast<TMap*>(next()))) {
1267 obj = map->GetValue("name");
1269 if (dir == obj->GetName()) {
1278 //______________________________________________________________________________
1279 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1281 // Check input data type.
1282 is_collection = kFALSE;
1286 Error("CheckDataType", "No connection to grid");
1289 is_collection = IsCollection(lfn);
1290 TString msg = "\n##### file: ";
1292 if (is_collection) {
1293 msg += " type: raw_collection;";
1294 // special treatment for collections
1296 // check for tag files in the collection
1297 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1299 msg += " using_tags: No (unknown)";
1300 Info("CheckDataType", msg.Data());
1303 const char* typeStr = res->GetKey(0, "origLFN");
1304 if (!typeStr || !strlen(typeStr)) {
1305 msg += " using_tags: No (unknown)";
1306 Info("CheckDataType", msg.Data());
1309 TString file = typeStr;
1310 use_tags = file.Contains(".tag");
1311 if (use_tags) msg += " using_tags: Yes";
1312 else msg += " using_tags: No";
1313 Info("CheckDataType", msg.Data());
1318 is_xml = slfn.Contains(".xml");
1320 // Open xml collection and check if there are tag files inside
1321 msg += " type: xml_collection;";
1322 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1324 msg += " using_tags: No (unknown)";
1325 Info("CheckDataType", msg.Data());
1328 TMap *map = coll->Next();
1330 msg += " using_tags: No (unknown)";
1331 Info("CheckDataType", msg.Data());
1334 map = (TMap*)map->GetValue("");
1336 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1337 use_tags = file.Contains(".tag");
1339 if (use_tags) msg += " using_tags: Yes";
1340 else msg += " using_tags: No";
1341 Info("CheckDataType", msg.Data());
1344 use_tags = slfn.Contains(".tag");
1345 if (slfn.Contains(".root")) msg += " type: root file;";
1346 else msg += " type: unknown file;";
1347 if (use_tags) msg += " using_tags: Yes";
1348 else msg += " using_tags: No";
1349 Info("CheckDataType", msg.Data());
1352 //______________________________________________________________________________
1353 void AliAnalysisAlien::EnablePackage(const char *package)
1355 // Enables a par file supposed to exist in the current directory.
1356 TString pkg(package);
1357 pkg.ReplaceAll(".par", "");
1359 if (gSystem->AccessPathName(pkg)) {
1360 Fatal("EnablePackage", "Package %s not found", pkg.Data());
1363 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1364 Info("EnablePackage", "AliEn plugin will use .par packages");
1365 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1367 fPackages = new TObjArray();
1368 fPackages->SetOwner();
1370 fPackages->Add(new TObjString(pkg));
1373 //______________________________________________________________________________
1374 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1376 // Get job status for all jobs with jobid>jobidstart.
1377 static char mstatus[20];
1383 TGridJobStatusList *list = gGrid->Ps("");
1384 if (!list) return mstatus;
1385 Int_t nentries = list->GetSize();
1386 TGridJobStatus *status;
1388 for (Int_t ijob=0; ijob<nentries; ijob++) {
1389 status = (TGridJobStatus *)list->At(ijob);
1390 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1391 if (pid<jobidstart) continue;
1392 if (pid == lastid) {
1393 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1395 switch (status->GetStatus()) {
1396 case TGridJobStatus::kWAITING:
1398 case TGridJobStatus::kRUNNING:
1400 case TGridJobStatus::kABORTED:
1401 case TGridJobStatus::kFAIL:
1402 case TGridJobStatus::kUNKNOWN:
1404 case TGridJobStatus::kDONE:
1413 //______________________________________________________________________________
1414 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1416 // Returns true if file is a collection. Functionality duplicated from
1417 // TAlien::Type() because we don't want to directly depend on TAlien.
1419 Error("IsCollection", "No connection to grid");
1422 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1423 if (!res) return kFALSE;
1424 const char* typeStr = res->GetKey(0, "type");
1425 if (!typeStr || !strlen(typeStr)) return kFALSE;
1426 if (!strcmp(typeStr, "collection")) return kTRUE;
1431 //______________________________________________________________________________
1432 Bool_t AliAnalysisAlien::IsSingleOutput() const
1434 // Check if single-ouput option is on.
1435 return (!fOutputSingle.IsNull());
1438 //______________________________________________________________________________
1439 void AliAnalysisAlien::Print(Option_t *) const
1441 // Print current plugin settings.
1442 printf("### AliEn analysis plugin current settings ###\n");
1443 printf("= Copy files to grid: __________________________ %s\n", (IsUseCopy())?"YES":"NO");
1444 printf("= Check if files can be copied to grid: ________ %s\n", (IsCheckCopy())?"YES":"NO");
1445 printf("= Production mode:______________________________ %d\n", fProductionMode);
1446 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1447 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1448 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1450 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1451 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1452 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1453 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1454 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1455 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1456 if (fRunNumbers.Length())
1457 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1459 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1460 if (!fRunRange[0] && !fRunNumbers.Length()) {
1461 TIter next(fInputFiles);
1464 while ((obj=next())) list += obj->GetName();
1465 printf("= Input files to be processed: _________________ %s\n", list.Data());
1467 if (TestBit(AliAnalysisGrid::kTest))
1468 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1469 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1470 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1471 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1472 printf("=====================================================================\n");
1473 printf("= Job price: ___________________________________ %d\n", fPrice);
1474 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1475 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1476 if (fMaxInitFailed>0)
1477 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1478 if (fMasterResubmitThreshold>0)
1479 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1480 if (fNrunsPerMaster>0)
1481 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1482 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1483 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1484 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1485 if (fArguments.Length())
1486 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1487 if (fExecutableArgs.Length())
1488 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1489 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1490 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1491 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1492 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1494 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1495 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1496 if (fIncludePath.Data())
1497 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1498 if (fCloseSE.Length())
1499 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1500 if (fFriendChainName.Length())
1501 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1503 TIter next(fPackages);
1506 while ((obj=next())) list += obj->GetName();
1507 printf("= Par files to be used: ________________________ %s\n", list.Data());
1511 //______________________________________________________________________________
1512 void AliAnalysisAlien::SetDefaults()
1514 // Set default values for everything. What cannot be filled will be left empty.
1515 if (fGridJDL) delete fGridJDL;
1516 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1517 fMergingJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1520 fSplitMaxInputFileNumber = 100;
1522 fMasterResubmitThreshold = 0;
1526 fNrunsPerMaster = 1;
1527 fMaxMergeFiles = 100;
1529 fExecutable = "analysis.sh";
1530 fExecutableCommand = "root -b -q";
1532 fExecutableArgs = "";
1533 fAnalysisMacro = "myAnalysis.C";
1534 fAnalysisSource = "";
1535 fAdditionalLibs = "";
1539 fAliROOTVersion = "";
1540 fUser = ""; // Your alien user name
1541 fGridWorkingDir = "";
1542 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1543 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1544 fFriendChainName = "";
1545 fGridOutputDir = "output";
1546 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1547 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1548 fInputFormat = "xml-single";
1549 fJDLName = "analysis.jdl";
1550 fJobTag = "Automatically generated analysis JDL";
1551 fMergeExcludes = "";
1554 SetCheckCopy(kTRUE);
1557 //______________________________________________________________________________
1558 Bool_t AliAnalysisAlien::MergeOutput(const char *output, const char *basedir, Int_t nmaxmerge)
1560 // Merge all registered outputs from basedir.
1561 TString output_file = output;
1563 TString output_chunk;
1564 TString previous_chunk = "";
1565 Int_t count_chunk = 0;
1566 Int_t count_zero = nmaxmerge;
1567 Bool_t merged = kTRUE;
1568 Int_t index = output_file.Index("@");
1569 if (index > 0) output_file.Remove(index);
1570 command = Form("find %s/ *%s", basedir, output_file.Data());
1571 printf("command: %s\n", command.Data());
1572 TGridResult *res = gGrid->Command(command);
1574 printf("Error: No result for the find command\n");
1578 TFileMerger *fm = 0;
1581 // Check if there is a merge operation to resume
1582 output_chunk = output_file;
1583 output_chunk.ReplaceAll(".root", "_*.root");
1584 // Check for existent temporary merge files
1585 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1587 // Skip as many input files as in a chunk
1588 for (Int_t counter=0; counter<nmaxmerge; counter++) map = (TMap*)nextmap();
1590 ::Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1594 output_chunk = output_file;
1595 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1597 if (gSystem->AccessPathName(output_chunk)) continue;
1598 // Merged file with chunks up to <count_chunk> found
1599 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1600 previous_chunk = output_chunk;
1604 count_zero = nmaxmerge;
1606 while ((map=(TMap*)nextmap())) {
1607 // Loop 'find' results and get next LFN
1608 if (count_zero == nmaxmerge) {
1609 // First file in chunk - create file merger and add previous chunk if any.
1610 fm = new TFileMerger(kFALSE);
1611 fm->SetFastMethod(kTRUE);
1612 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1613 output_chunk = output_file;
1614 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1616 // If last file found, put merged results in the output file
1617 if (map == res->Last()) output_chunk = output_file;
1618 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1619 if (!objs || !objs->GetString().Length()) {
1620 // Nothing found - skip this output
1625 // Add file to be merged and decrement chunk counter.
1626 fm->AddFile(objs->GetString());
1628 if (count_zero==0 || map == res->Last()) {
1629 fm->OutputFile(output_chunk);
1630 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1631 // Nothing found - skip this output
1632 ::Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1637 // Merge the outputs, then go to next chunk
1639 ::Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1645 ::Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1646 gSystem->Unlink(previous_chunk);
1648 if (map == res->Last()) {
1654 count_zero = nmaxmerge;
1655 previous_chunk = output_chunk;
1661 //______________________________________________________________________________
1662 Bool_t AliAnalysisAlien::MergeOutputs()
1664 // Merge analysis outputs existing in the AliEn space.
1665 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1666 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1668 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1672 if (!TestBit(AliAnalysisGrid::kMerge)) {
1673 Info("MergeOutputs", "### Re-run with <MergeViaJDL> option in terminate mode of the plugin to submit merging jobs ###");
1676 if (fProductionMode) {
1677 Info("MergeOutputs", "### Merging will be submitted by LPM manager... ###");
1680 Info("MergeOutputs", "Submitting merging JDL");
1681 if (!SubmitMerging()) return kFALSE;
1682 Info("MergeOutputs", "### Re-run with <MergeViaJDL> off to collect results after merging jobs are done ###");
1683 Info("MergeOutputs", "### The Terminate() method is executed by the merging jobs");
1686 // Get the output path
1687 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1688 if (!DirectoryExists(fGridOutputDir)) {
1689 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1692 if (!fOutputFiles.Length()) {
1693 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1696 // Check if fast read option was requested
1697 if (fFastReadOption) {
1698 Warning("MergeOutputs", "You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !");
1699 gEnv->SetValue("XNet.ConnectTimeout",5);
1700 gEnv->SetValue("XNet.RequestTimeout",5);
1701 gEnv->SetValue("XNet.MaxRedirectCount",2);
1702 gEnv->SetValue("XNet.ReconnectTimeout",5);
1703 gEnv->SetValue("XNet.FirstConnectMaxCnt",1);
1705 TObjArray *list = fOutputFiles.Tokenize(" ");
1708 TString output_file;
1709 Bool_t merged = kTRUE;
1710 while((str=(TObjString*)next())) {
1711 output_file = str->GetString();
1712 Int_t index = output_file.Index("@");
1713 if (index > 0) output_file.Remove(index);
1714 // Skip already merged outputs
1715 if (!gSystem->AccessPathName(output_file)) {
1716 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1719 if (fMergeExcludes.Length() &&
1720 fMergeExcludes.Contains(output_file.Data())) continue;
1721 // Perform a 'find' command in the output directory, looking for registered outputs
1722 merged = MergeOutput(output_file, fGridOutputDir, fMaxMergeFiles);
1724 Error("MergeOutputs", "Terminate() will NOT be executed");
1731 //______________________________________________________________________________
1732 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1734 // Use the output files connected to output containers from the analysis manager
1735 // rather than the files defined by SetOutputFiles
1736 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1737 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1739 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1742 //______________________________________________________________________________
1743 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1745 // Start remote grid analysis.
1747 // Check if output files have to be taken from the analysis manager
1748 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1749 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1750 if (!mgr || !mgr->IsInitialized()) {
1751 Error("StartAnalysis", "You need an initialized analysis manager for this");
1755 TIter next(mgr->GetOutputs());
1756 AliAnalysisDataContainer *output;
1757 while ((output=(AliAnalysisDataContainer*)next())) {
1758 const char *filename = output->GetFileName();
1759 if (!(strcmp(filename, "default"))) {
1760 if (!mgr->GetOutputEventHandler()) continue;
1761 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1763 if (fOutputFiles.Contains(filename)) continue;
1764 if (fOutputFiles.Length()) fOutputFiles += " ";
1765 fOutputFiles += filename;
1767 // Add extra files registered to the analysis manager
1768 if (mgr->GetExtraFiles().Length()) {
1769 if (fOutputFiles.Length()) fOutputFiles += " ";
1770 fOutputFiles += mgr->GetExtraFiles();
1773 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1774 if (TestBit(AliAnalysisGrid::kOffline)) {
1775 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1776 \n there nor any job run. You can revise the JDL and analysis \
1777 \n macro then run the same in \"submit\" mode.");
1778 } else if (TestBit(AliAnalysisGrid::kTest)) {
1779 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1781 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1782 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1783 \n space and job submitted.");
1784 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1785 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1786 if (fMergeViaJDL) CheckInputData();
1789 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1794 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1797 if (IsCheckCopy()) CheckFileCopy(gGrid->GetHomeDirectory());
1798 if (!CheckInputData()) {
1799 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1802 CreateDataset(fDataPattern);
1803 WriteAnalysisFile();
1804 WriteAnalysisMacro();
1806 WriteValidationScript();
1808 WriteMergingMacro();
1809 WriteMergeExecutable();
1810 WriteValidationScript(kTRUE);
1812 if (!CreateJDL()) return kFALSE;
1813 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1814 if (TestBit(AliAnalysisGrid::kTest)) {
1815 // Locally testing the analysis
1816 Info("StartAnalysis", "\n_______________________________________________________________________ \
1817 \n Running analysis script in a daughter shell as on a worker node \
1818 \n_______________________________________________________________________");
1819 TObjArray *list = fOutputFiles.Tokenize(" ");
1822 TString output_file;
1823 while((str=(TObjString*)next())) {
1824 output_file = str->GetString();
1825 Int_t index = output_file.Index("@");
1826 if (index > 0) output_file.Remove(index);
1827 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1830 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1831 TString validationScript = fExecutable;
1832 validationScript.ReplaceAll(".sh", "_validation.sh");
1833 gSystem->Exec(Form("bash %s",validationScript.Data()));
1834 // gSystem->Exec("cat stdout");
1837 // Check if submitting is managed by LPM manager
1838 if (fProductionMode) {
1839 TString prodfile = fJDLName;
1840 prodfile.ReplaceAll(".jdl", ".prod");
1841 WriteProductionFile(prodfile);
1842 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1845 // Submit AliEn job(s)
1846 gGrid->Cd(fGridOutputDir);
1849 if (!fRunNumbers.Length() && !fRunRange[0]) {
1850 // Submit a given xml or a set of runs
1851 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1852 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1854 const char *cjobId = res->GetKey(0,"jobId");
1858 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1861 Info("StartAnalysis", "\n_______________________________________________________________________ \
1862 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1863 \n_______________________________________________________________________",
1864 fJDLName.Data(), cjobId);
1869 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
1873 // Submit for a range of enumeration of runs.
1874 if (!Submit()) return kFALSE;
1877 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1878 \n You may exit at any time and terminate the job later using the option <terminate> \
1879 \n ##################################################################################", jobID.Data());
1880 gSystem->Exec("aliensh");
1884 //______________________________________________________________________________
1885 Bool_t AliAnalysisAlien::Submit()
1887 // Submit all master jobs.
1888 Int_t nmasterjobs = fInputFiles->GetEntries();
1889 Long_t tshoot = gSystem->Now();
1890 if (!fNsubmitted && !SubmitNext()) return kFALSE;
1891 while (fNsubmitted < nmasterjobs) {
1892 Long_t now = gSystem->Now();
1893 if ((now-tshoot)>30000) {
1895 if (!SubmitNext()) return kFALSE;
1901 //______________________________________________________________________________
1902 Bool_t AliAnalysisAlien::SubmitMerging()
1904 // Submit all merging jobs.
1905 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1906 gGrid->Cd(fGridOutputDir);
1907 TString mergeJDLName = fExecutable;
1908 mergeJDLName.ReplaceAll(".sh", "_merge.jdl");
1909 Int_t ntosubmit = fInputFiles->GetEntries();
1910 printf("### Submitting %d merging jobs...\n", ntosubmit);
1911 for (Int_t i=0; i<ntosubmit; i++) {
1913 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
1914 runOutDir.ReplaceAll(".xml", "");
1916 query = Form("submit %s %s", mergeJDLName.Data(), runOutDir.Data());
1918 query = Form("submit %s %03d", mergeJDLName.Data(), i);
1919 printf("********* %s\n",query.Data());
1920 TGridResult *res = gGrid->Command(query);
1922 const char *cjobId = res->GetKey(0,"jobId");
1926 Error("StartAnalysis", "Your JDL %s could not be submitted", mergeJDLName.Data());
1929 Info("StartAnalysis", "\n_______________________________________________________________________ \
1930 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1931 \n_______________________________________________________________________",
1932 mergeJDLName.Data(), cjobId);
1936 Error("SubmitMerging", "No grid result after submission !!! Bailing out...");
1940 if (!ntosubmit) return kTRUE;
1941 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR MERGING JOBS HAVE FINISHED. #### \
1942 \n You may exit at any time and terminate the job later using the option <terminate> but disabling SetMergeViaJDL\
1943 \n ##################################################################################");
1944 gSystem->Exec("aliensh");
1948 //______________________________________________________________________________
1949 Bool_t AliAnalysisAlien::SubmitNext()
1951 // Submit next bunch of master jobs if the queue is free.
1952 static Bool_t iscalled = kFALSE;
1953 static Int_t firstmaster = 0;
1954 static Int_t lastmaster = 0;
1955 static Int_t npermaster = 0;
1956 if (iscalled) return kTRUE;
1958 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1959 Int_t ntosubmit = 0;
1962 if (!fNsubmitted) ntosubmit = 1;
1964 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1965 printf("=== master %d: %s\n", lastmaster, status.Data());
1966 // If last master not split, just return
1967 if (status != "SPLIT") {iscalled = kFALSE; return kTRUE;}
1968 // No more than 100 waiting jobs
1969 if (nwaiting>100) {iscalled = kFALSE; return kTRUE;}
1970 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1971 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1972 if (!ntosubmit) ntosubmit = 1;
1973 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1974 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1976 Int_t nmasterjobs = fInputFiles->GetEntries();
1977 for (Int_t i=0; i<ntosubmit; i++) {
1978 // Submit for a range of enumeration of runs.
1979 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return kTRUE;}
1981 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
1982 runOutDir.ReplaceAll(".xml", "");
1984 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
1986 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1987 printf("********* %s\n",query.Data());
1988 res = gGrid->Command(query);
1990 TString cjobId1 = res->GetKey(0,"jobId");
1991 if (!cjobId1.Length()) {
1995 Error("StartAnalysis", "Your JDL %s could not be submitted. The message was:", fJDLName.Data());
1998 Info("StartAnalysis", "\n_______________________________________________________________________ \
1999 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
2000 \n_______________________________________________________________________",
2001 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
2004 lastmaster = cjobId1.Atoi();
2005 if (!firstmaster) firstmaster = lastmaster;
2010 Error("StartAnalysis", "No grid result after submission !!! Bailing out...");
2018 //______________________________________________________________________________
2019 void AliAnalysisAlien::WriteAnalysisFile()
2021 // Write current analysis manager into the file <analysisFile>
2022 TString analysisFile = fExecutable;
2023 analysisFile.ReplaceAll(".sh", ".root");
2024 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2025 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2026 if (!mgr || !mgr->IsInitialized()) {
2027 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
2030 // Check analysis type
2032 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
2033 handler = (TObject*)mgr->GetInputEventHandler();
2035 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
2036 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
2038 TDirectory *cdir = gDirectory;
2039 TFile *file = TFile::Open(analysisFile, "RECREATE");
2041 // Skip task Terminate calls for the grid job
2042 mgr->SetSkipTerminate(kTRUE);
2043 // Unless merging makes no sense
2044 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
2047 // Enable termination for local jobs
2048 mgr->SetSkipTerminate(kFALSE);
2050 if (cdir) cdir->cd();
2051 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
2053 Bool_t copy = kTRUE;
2054 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2057 TString workdir = gGrid->GetHomeDirectory();
2058 workdir += fGridWorkingDir;
2059 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
2060 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
2061 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
2065 //______________________________________________________________________________
2066 void AliAnalysisAlien::WriteAnalysisMacro()
2068 // Write the analysis macro that will steer the analysis in grid mode.
2069 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2071 out.open(fAnalysisMacro.Data(), ios::out);
2073 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2076 Bool_t hasSTEERBase = kFALSE;
2077 Bool_t hasESD = kFALSE;
2078 Bool_t hasAOD = kFALSE;
2079 Bool_t hasANALYSIS = kFALSE;
2080 Bool_t hasANALYSISalice = kFALSE;
2081 Bool_t hasCORRFW = kFALSE;
2082 TString func = fAnalysisMacro;
2083 TString type = "ESD";
2084 TString comment = "// Analysis using ";
2085 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
2086 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
2090 if (type!="AOD" && fFriendChainName!="") {
2091 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
2094 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
2095 else comment += " data";
2096 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
2097 func.ReplaceAll(".C", "");
2098 out << "void " << func.Data() << "()" << endl;
2100 out << comment.Data() << endl;
2101 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
2102 out << " TStopwatch timer;" << endl;
2103 out << " timer.Start();" << endl << endl;
2104 out << "// load base root libraries" << endl;
2105 out << " gSystem->Load(\"libTree\");" << endl;
2106 out << " gSystem->Load(\"libGeom\");" << endl;
2107 out << " gSystem->Load(\"libVMC\");" << endl;
2108 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2109 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2110 if (fAdditionalRootLibs.Length()) {
2111 // in principle libtree /lib geom libvmc etc. can go into this list, too
2112 out << "// Add aditional libraries" << endl;
2113 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2116 while((str=(TObjString*)next())) {
2117 if (str->GetString().Contains(".so"))
2118 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2120 if (list) delete list;
2122 out << "// include path" << endl;
2123 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2124 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2125 out << "// Load analysis framework libraries" << endl;
2127 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2128 out << " gSystem->Load(\"libESD\");" << endl;
2129 out << " gSystem->Load(\"libAOD\");" << endl;
2130 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2131 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2132 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2134 TIter next(fPackages);
2137 TString setupPar = "AliAnalysisAlien::SetupPar";
2138 while ((obj=next())) {
2139 pkgname = obj->GetName();
2140 if (pkgname == "STEERBase" ||
2141 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2142 if (pkgname == "ESD" ||
2143 pkgname == "ESD.par") hasESD = kTRUE;
2144 if (pkgname == "AOD" ||
2145 pkgname == "AOD.par") hasAOD = kTRUE;
2146 if (pkgname == "ANALYSIS" ||
2147 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2148 if (pkgname == "ANALYSISalice" ||
2149 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2150 if (pkgname == "CORRFW" ||
2151 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2153 if (hasANALYSISalice) setupPar = "SetupPar";
2154 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2155 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2156 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2157 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2158 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2159 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2160 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2161 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2162 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2163 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2164 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2165 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2166 out << "// Compile other par packages" << endl;
2168 while ((obj=next())) {
2169 pkgname = obj->GetName();
2170 if (pkgname == "STEERBase" ||
2171 pkgname == "STEERBase.par" ||
2173 pkgname == "ESD.par" ||
2175 pkgname == "AOD.par" ||
2176 pkgname == "ANALYSIS" ||
2177 pkgname == "ANALYSIS.par" ||
2178 pkgname == "ANALYSISalice" ||
2179 pkgname == "ANALYSISalice.par" ||
2180 pkgname == "CORRFW" ||
2181 pkgname == "CORRFW.par") continue;
2182 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2185 if (fAdditionalLibs.Length()) {
2186 out << "// Add aditional AliRoot libraries" << endl;
2187 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2190 while((str=(TObjString*)next())) {
2191 if (str->GetString().Contains(".so"))
2192 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2194 if (list) delete list;
2197 out << "// analysis source to be compiled at runtime (if any)" << endl;
2198 if (fAnalysisSource.Length()) {
2199 TObjArray *list = fAnalysisSource.Tokenize(" ");
2202 while((str=(TObjString*)next())) {
2203 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2205 if (list) delete list;
2208 if (fFastReadOption) {
2209 Warning("WriteAnalysisMacro", "!!! You requested FastRead option. Using xrootd flags to reduce timeouts in the grid jobs. Note that this may skip some files that could be accessed !!!");
2210 out << "// fast xrootd reading enabled" << endl;
2211 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2212 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",5);" << endl;
2213 out << " gEnv->SetValue(\"XNet.RequestTimeout\",5);" << endl;
2214 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2215 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",5);" << endl;
2216 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2218 out << "// connect to AliEn and make the chain" << endl;
2219 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2220 if (IsUsingTags()) {
2221 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
2223 if(fFriendChainName!="AliAOD.VertexingHF.root") {
2224 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
2226 out << " // Check if the macro to create the chain was provided" << endl;
2227 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
2228 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
2229 out << " return;" << endl;
2230 out << " }" << endl;
2231 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
2232 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
2235 out << "// read the analysis manager from file" << endl;
2236 TString analysisFile = fExecutable;
2237 analysisFile.ReplaceAll(".sh", ".root");
2238 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2239 out << " if (!file) return;" << endl;
2240 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2241 out << " AliAnalysisManager *mgr = 0;" << endl;
2242 out << " TKey *key;" << endl;
2243 out << " while ((key=(TKey*)nextkey())) {" << endl;
2244 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2245 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2246 out << " };" << endl;
2247 out << " if (!mgr) {" << endl;
2248 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2249 out << " return;" << endl;
2250 out << " }" << endl << endl;
2251 out << " mgr->PrintStatus();" << endl;
2252 if (AliAnalysisManager::GetAnalysisManager()) {
2253 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2254 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2256 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2259 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
2260 out << " timer.Stop();" << endl;
2261 out << " timer.Print();" << endl;
2262 out << "}" << endl << endl;
2263 if (IsUsingTags()) {
2264 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
2266 out << "// Create a chain using tags from the xml file." << endl;
2267 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
2268 out << " if (!coll) {" << endl;
2269 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2270 out << " return NULL;" << endl;
2271 out << " }" << endl;
2272 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
2273 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
2274 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
2275 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
2276 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
2277 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
2278 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
2279 out << " // Check if the cuts configuration file was provided" << endl;
2280 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
2281 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
2282 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2283 out << " }" << endl;
2284 if (fFriendChainName=="") {
2285 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
2287 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
2288 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
2289 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
2291 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
2292 out << " chain->ls();" << endl;
2293 out << " return chain;" << endl;
2294 out << "}" << endl << endl;
2295 if (gSystem->AccessPathName("ConfigureCuts.C")) {
2296 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
2297 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
2298 msg += " AliLHCTagCuts *lhcCuts,\n";
2299 msg += " AliDetectorTagCuts *detCuts,\n";
2300 msg += " AliEventTagCuts *evCuts)";
2301 Info("WriteAnalysisMacro", msg.Data());
2304 if (!IsUsingTags() || fFriendChainName!="") {
2305 out <<"//________________________________________________________________________________" << endl;
2306 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
2308 out << "// Create a chain using url's from xml file" << endl;
2309 out << " TString treename = type;" << endl;
2310 out << " treename.ToLower();" << endl;
2311 out << " treename += \"Tree\";" << endl;
2312 out << " printf(\"***************************************\\n\");" << endl;
2313 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
2314 out << " printf(\"***************************************\\n\");" << endl;
2315 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
2316 out << " if (!coll) {" << endl;
2317 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2318 out << " return NULL;" << endl;
2319 out << " }" << endl;
2320 out << " TChain *chain = new TChain(treename);" << endl;
2321 if(fFriendChainName!="") {
2322 out << " TChain *chainFriend = new TChain(treename);" << endl;
2324 out << " coll->Reset();" << endl;
2325 out << " while (coll->Next()) {" << endl;
2326 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2327 if(fFriendChainName!="") {
2328 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2329 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2330 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2331 out << " chainFriend->Add(fileFriend.Data());" << endl;
2333 out << " }" << endl;
2334 out << " if (!chain->GetNtrees()) {" << endl;
2335 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2336 out << " return NULL;" << endl;
2337 out << " }" << endl;
2338 if(fFriendChainName!="") {
2339 out << " chain->AddFriend(chainFriend);" << endl;
2341 out << " return chain;" << endl;
2342 out << "}" << endl << endl;
2344 if (hasANALYSISalice) {
2345 out <<"//________________________________________________________________________________" << endl;
2346 out << "Bool_t SetupPar(const char *package) {" << endl;
2347 out << "// Compile the package and set it up." << endl;
2348 out << " TString pkgdir = package;" << endl;
2349 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2350 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2351 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2352 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2353 out << " // Check for BUILD.sh and execute" << endl;
2354 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2355 out << " printf(\"*******************************\\n\");" << endl;
2356 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2357 out << " printf(\"*******************************\\n\");" << endl;
2358 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2359 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2360 out << " gSystem->ChangeDirectory(cdir);" << endl;
2361 out << " return kFALSE;" << endl;
2362 out << " }" << endl;
2363 out << " } else {" << endl;
2364 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2365 out << " gSystem->ChangeDirectory(cdir);" << endl;
2366 out << " return kFALSE;" << endl;
2367 out << " }" << endl;
2368 out << " // Check for SETUP.C and execute" << endl;
2369 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2370 out << " printf(\"*******************************\\n\");" << endl;
2371 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2372 out << " printf(\"*******************************\\n\");" << endl;
2373 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2374 out << " } else {" << endl;
2375 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2376 out << " gSystem->ChangeDirectory(cdir);" << endl;
2377 out << " return kFALSE;" << endl;
2378 out << " }" << endl;
2379 out << " // Restore original workdir" << endl;
2380 out << " gSystem->ChangeDirectory(cdir);" << endl;
2381 out << " return kTRUE;" << endl;
2384 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2386 Bool_t copy = kTRUE;
2387 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2390 TString workdir = gGrid->GetHomeDirectory();
2391 workdir += fGridWorkingDir;
2392 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2393 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2394 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2395 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2396 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2398 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2399 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2403 //______________________________________________________________________________
2404 void AliAnalysisAlien::WriteMergingMacro()
2406 // Write a macro to merge the outputs per master job.
2407 if (!fMergeViaJDL) return;
2408 if (!fOutputFiles.Length()) {
2409 Error("WriteMergingMacro", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
2412 TString mergingMacro = fExecutable;
2413 mergingMacro.ReplaceAll(".sh","_merge.C");
2414 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
2415 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2417 out.open(mergingMacro.Data(), ios::out);
2419 Error("WriteMergingMacro", "could not open file %s for writing", fAnalysisMacro.Data());
2422 Bool_t hasSTEERBase = kFALSE;
2423 Bool_t hasESD = kFALSE;
2424 Bool_t hasAOD = kFALSE;
2425 Bool_t hasANALYSIS = kFALSE;
2426 Bool_t hasANALYSISalice = kFALSE;
2427 Bool_t hasCORRFW = kFALSE;
2428 TString func = mergingMacro;
2430 func.ReplaceAll(".C", "");
2431 out << "void " << func.Data() << "(const char *dir)" << endl;
2433 out << "// Automatically generated merging macro executed in grid subjobs" << endl << endl;
2434 out << " TStopwatch timer;" << endl;
2435 out << " timer.Start();" << endl << endl;
2436 out << "// load base root libraries" << endl;
2437 out << " gSystem->Load(\"libTree\");" << endl;
2438 out << " gSystem->Load(\"libGeom\");" << endl;
2439 out << " gSystem->Load(\"libVMC\");" << endl;
2440 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
2441 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
2442 if (fAdditionalRootLibs.Length()) {
2443 // in principle libtree /lib geom libvmc etc. can go into this list, too
2444 out << "// Add aditional libraries" << endl;
2445 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
2448 while((str=(TObjString*)next())) {
2449 if (str->GetString().Contains(".so"))
2450 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2452 if (list) delete list;
2454 out << "// include path" << endl;
2455 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
2456 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
2457 out << "// Load analysis framework libraries" << endl;
2459 out << " gSystem->Load(\"libSTEERBase\");" << endl;
2460 out << " gSystem->Load(\"libESD\");" << endl;
2461 out << " gSystem->Load(\"libAOD\");" << endl;
2462 out << " gSystem->Load(\"libANALYSIS\");" << endl;
2463 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2464 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2466 TIter next(fPackages);
2469 TString setupPar = "AliAnalysisAlien::SetupPar";
2470 while ((obj=next())) {
2471 pkgname = obj->GetName();
2472 if (pkgname == "STEERBase" ||
2473 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
2474 if (pkgname == "ESD" ||
2475 pkgname == "ESD.par") hasESD = kTRUE;
2476 if (pkgname == "AOD" ||
2477 pkgname == "AOD.par") hasAOD = kTRUE;
2478 if (pkgname == "ANALYSIS" ||
2479 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
2480 if (pkgname == "ANALYSISalice" ||
2481 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
2482 if (pkgname == "CORRFW" ||
2483 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
2485 if (hasANALYSISalice) setupPar = "SetupPar";
2486 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
2487 else out << " if (!" << setupPar << "(\"STEERBase\")) return;" << endl;
2488 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
2489 else out << " if (!" << setupPar << "(\"ESD\")) return;" << endl;
2490 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
2491 else out << " if (!" << setupPar << "(\"AOD\")) return;" << endl;
2492 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
2493 else out << " if (!" << setupPar << "(\"ANALYSIS\")) return;" << endl;
2494 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
2495 else out << " if (!" << setupPar << "(\"ANALYSISalice\")) return;" << endl;
2496 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
2497 else out << " if (!" << setupPar << "(\"CORRFW\")) return;" << endl << endl;
2498 out << "// Compile other par packages" << endl;
2500 while ((obj=next())) {
2501 pkgname = obj->GetName();
2502 if (pkgname == "STEERBase" ||
2503 pkgname == "STEERBase.par" ||
2505 pkgname == "ESD.par" ||
2507 pkgname == "AOD.par" ||
2508 pkgname == "ANALYSIS" ||
2509 pkgname == "ANALYSIS.par" ||
2510 pkgname == "ANALYSISalice" ||
2511 pkgname == "ANALYSISalice.par" ||
2512 pkgname == "CORRFW" ||
2513 pkgname == "CORRFW.par") continue;
2514 out << " if (!" << setupPar << "(\"" << obj->GetName() << "\")) return;" << endl;
2517 if (fAdditionalLibs.Length()) {
2518 out << "// Add aditional AliRoot libraries" << endl;
2519 TObjArray *list = fAdditionalLibs.Tokenize(" ");
2522 while((str=(TObjString*)next())) {
2523 if (str->GetString().Contains(".so"))
2524 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
2526 if (list) delete list;
2529 out << "// Analysis source to be compiled at runtime (if any)" << endl;
2530 if (fAnalysisSource.Length()) {
2531 TObjArray *list = fAnalysisSource.Tokenize(" ");
2534 while((str=(TObjString*)next())) {
2535 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
2537 if (list) delete list;
2540 if (fFastReadOption) {
2541 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 !!!");
2542 out << "// fast xrootd reading enabled" << endl;
2543 out << " printf(\"!!! You requested FastRead option. Using xrootd flags to reduce timeouts. Note that this may skip some files that could be accessed !!!\");" << endl;
2544 out << " gEnv->SetValue(\"XNet.ConnectTimeout\",5);" << endl;
2545 out << " gEnv->SetValue(\"XNet.RequestTimeout\",5);" << endl;
2546 out << " gEnv->SetValue(\"XNet.MaxRedirectCount\",2);" << endl;
2547 out << " gEnv->SetValue(\"XNet.ReconnectTimeout\",5);" << endl;
2548 out << " gEnv->SetValue(\"XNet.FirstConnectMaxCnt\",1);" << endl << endl;
2550 out << "// Connect to AliEn" << endl;
2551 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
2552 out << " TString outputDir = \"" << fGridOutputDir << "/\";" << endl;
2553 out << " outputDir += dir;" << endl;
2554 out << " TString outputFiles = \"" << fOutputFiles << "\";" << endl;
2555 out << " TString mergeExcludes = \"" << fMergeExcludes << "\";" << endl;
2556 out << " mergeExcludes += \"" << AliAnalysisManager::GetAnalysisManager()->GetExtraFiles() << "\";" << endl;
2557 out << " TObjArray *list = outputFiles.Tokenize(\" \");" << endl;
2558 out << " TIter *iter = new TIter(list);" << endl;
2559 out << " TObjString *str;" << endl;
2560 out << " TString output_file;" << endl;
2561 out << " Bool_t merged = kTRUE;" << endl;
2562 out << " while((str=(TObjString*)iter->Next())) {" << endl;
2563 out << " output_file = str->GetString();" << endl;
2564 out << " Int_t index = output_file.Index(\"@\");" << endl;
2565 out << " if (index > 0) output_file.Remove(index);" << endl;
2566 out << " // Skip already merged outputs" << endl;
2567 out << " if (!gSystem->AccessPathName(output_file)) {" << endl;
2568 out << " printf(\"Output file <%s> found. Not merging again.\",output_file.Data());" << endl;
2569 out << " continue;" << endl;
2570 out << " }" << endl;
2571 out << " if (mergeExcludes.Contains(output_file.Data())) continue;" << endl;
2572 out << " merged = AliAnalysisAlien::MergeOutput(output_file, outputDir, " << fMaxMergeFiles << ");" << endl;
2573 out << " if (!merged) {" << endl;
2574 out << " printf(\"ERROR: Cannot merge %s\\n\", output_file.Data());" << endl;
2575 out << " }" << endl;
2576 out << " }" << endl;
2577 out << "// read the analysis manager from file" << endl;
2578 TString analysisFile = fExecutable;
2579 analysisFile.ReplaceAll(".sh", ".root");
2580 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
2581 out << " if (!file) return;" << endl;
2582 out << " TIter nextkey(file->GetListOfKeys());" << endl;
2583 out << " AliAnalysisManager *mgr = 0;" << endl;
2584 out << " TKey *key;" << endl;
2585 out << " while ((key=(TKey*)nextkey())) {" << endl;
2586 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
2587 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
2588 out << " };" << endl;
2589 out << " if (!mgr) {" << endl;
2590 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
2591 out << " return;" << endl;
2592 out << " }" << endl << endl;
2593 out << " mgr->SetSkipTerminate(kFALSE);" << endl;
2594 out << " mgr->PrintStatus();" << endl;
2595 if (AliAnalysisManager::GetAnalysisManager()) {
2596 if (AliAnalysisManager::GetAnalysisManager()->GetDebugLevel()>3) {
2597 out << " gEnv->SetValue(\"XNet.Debug\", \"1\");" << endl;
2599 out << " AliLog::SetGlobalLogLevel(AliLog::kError);" << endl;
2602 out << " mgr->StartAnalysis(\"gridterminate\");" << endl;
2603 out << "}" << endl << endl;
2604 if (hasANALYSISalice) {
2605 out <<"//________________________________________________________________________________" << endl;
2606 out << "Bool_t SetupPar(const char *package) {" << endl;
2607 out << "// Compile the package and set it up." << endl;
2608 out << " TString pkgdir = package;" << endl;
2609 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2610 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2611 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2612 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2613 out << " // Check for BUILD.sh and execute" << endl;
2614 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2615 out << " printf(\"*******************************\\n\");" << endl;
2616 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2617 out << " printf(\"*******************************\\n\");" << endl;
2618 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2619 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2620 out << " gSystem->ChangeDirectory(cdir);" << endl;
2621 out << " return kFALSE;" << endl;
2622 out << " }" << endl;
2623 out << " } else {" << endl;
2624 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2625 out << " gSystem->ChangeDirectory(cdir);" << endl;
2626 out << " return kFALSE;" << endl;
2627 out << " }" << endl;
2628 out << " // Check for SETUP.C and execute" << endl;
2629 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2630 out << " printf(\"*******************************\\n\");" << endl;
2631 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2632 out << " printf(\"*******************************\\n\");" << endl;
2633 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2634 out << " } else {" << endl;
2635 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2636 out << " gSystem->ChangeDirectory(cdir);" << endl;
2637 out << " return kFALSE;" << endl;
2638 out << " }" << endl;
2639 out << " // Restore original workdir" << endl;
2640 out << " gSystem->ChangeDirectory(cdir);" << endl;
2641 out << " return kTRUE;" << endl;
2645 Bool_t copy = kTRUE;
2646 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2649 TString workdir = gGrid->GetHomeDirectory();
2650 workdir += fGridWorkingDir;
2651 if (FileExists(mergingMacro)) gGrid->Rm(mergingMacro);
2652 Info("WriteMergingMacro", "\n##### Copying merging macro: <%s> to your alien workspace", mergingMacro.Data());
2653 TFile::Cp(Form("file:%s",mergingMacro.Data()), Form("alien://%s/%s", workdir.Data(), mergingMacro.Data()));
2657 //______________________________________________________________________________
2658 Bool_t AliAnalysisAlien::SetupPar(const char *package)
2660 // Compile the par file archive pointed by <package>. This must be present in the current durectory.
2661 // Note that for loading the compiled library. The current directory should have precedence in
2663 TString pkgdir = package;
2664 pkgdir.ReplaceAll(".par","");
2665 gSystem->Exec(Form("tar xvzf %s.par", pkgdir.Data()));
2666 TString cdir = gSystem->WorkingDirectory();
2667 gSystem->ChangeDirectory(pkgdir);
2668 // Check for BUILD.sh and execute
2669 if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
2670 printf("**************************************************\n");
2671 printf("*** Building PAR archive %s\n", package);
2672 printf("**************************************************\n");
2673 if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
2674 ::Error("SetupPar", "Cannot build par archive %s", pkgdir.Data());
2675 gSystem->ChangeDirectory(cdir);
2679 ::Error("SetupPar","Cannot access PROOF-INF/BUILD.sh for package %s", pkgdir.Data());
2680 gSystem->ChangeDirectory(cdir);
2683 // Check for SETUP.C and execute
2684 if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
2685 printf("**************************************************\n");
2686 printf("*** Setup PAR archive %s\n", package);
2687 printf("**************************************************\n");
2688 gROOT->Macro("PROOF-INF/SETUP.C");
2689 printf("*** Loaded library: %s\n", gSystem->GetLibraries(pkgdir,"",kFALSE));
2691 ::Error("SetupPar","Cannot access PROOF-INF/SETUP.C for package %s", pkgdir.Data());
2692 gSystem->ChangeDirectory(cdir);
2695 // Restore original workdir
2696 gSystem->ChangeDirectory(cdir);
2700 //______________________________________________________________________________
2701 void AliAnalysisAlien::WriteExecutable()
2703 // Generate the alien executable script.
2704 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2706 out.open(fExecutable.Data(), ios::out);
2708 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2711 out << "#!/bin/bash" << endl;
2712 out << "echo \"=========================================\"" << endl;
2713 out << "echo \"############## PATH : ##############\"" << endl;
2714 out << "echo $PATH" << endl;
2715 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2716 out << "echo $LD_LIBRARY_PATH" << endl;
2717 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2718 out << "echo $ROOTSYS" << endl;
2719 out << "echo \"############## which root : ##############\"" << endl;
2720 out << "which root" << endl;
2721 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2722 out << "echo $ALICE_ROOT" << endl;
2723 out << "echo \"############## which aliroot : ##############\"" << endl;
2724 out << "which aliroot" << endl;
2725 out << "echo \"############## system limits : ##############\"" << endl;
2726 out << "ulimit -a" << endl;
2727 out << "echo \"############## memory : ##############\"" << endl;
2728 out << "free -m" << endl;
2729 out << "echo \"=========================================\"" << endl << endl;
2730 // Make sure we can properly compile par files
2731 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2732 out << fExecutableCommand << " ";
2733 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2734 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2735 out << "echo \"############## memory after: ##############\"" << endl;
2736 out << "free -m" << endl;
2737 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2738 out << "dmesg | tail -n 10" << endl;
2740 Bool_t copy = kTRUE;
2741 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2744 TString workdir = gGrid->GetHomeDirectory();
2745 TString bindir = Form("%s/bin", workdir.Data());
2746 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2747 workdir += fGridWorkingDir;
2748 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2749 if (FileExists(executable)) gGrid->Rm(executable);
2750 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2751 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2755 //______________________________________________________________________________
2756 void AliAnalysisAlien::WriteMergeExecutable()
2758 // Generate the alien executable script for the merging job.
2759 if (!fMergeViaJDL) return;
2760 TString mergeExec = fExecutable;
2761 mergeExec.ReplaceAll(".sh", "_merge.sh");
2762 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2764 out.open(mergeExec.Data(), ios::out);
2766 Error("WriteMergingExecutable", "Bad file name for executable: %s", mergeExec.Data());
2769 out << "#!/bin/bash" << endl;
2770 out << "echo \"=========================================\"" << endl;
2771 out << "echo \"############## PATH : ##############\"" << endl;
2772 out << "echo $PATH" << endl;
2773 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2774 out << "echo $LD_LIBRARY_PATH" << endl;
2775 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2776 out << "echo $ROOTSYS" << endl;
2777 out << "echo \"############## which root : ##############\"" << endl;
2778 out << "which root" << endl;
2779 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2780 out << "echo $ALICE_ROOT" << endl;
2781 out << "echo \"############## which aliroot : ##############\"" << endl;
2782 out << "which aliroot" << endl;
2783 out << "echo \"############## system limits : ##############\"" << endl;
2784 out << "ulimit -a" << endl;
2785 out << "echo \"############## memory : ##############\"" << endl;
2786 out << "free -m" << endl;
2787 out << "echo \"=========================================\"" << endl << endl;
2788 // Make sure we can properly compile par files
2789 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2790 TString mergeMacro = fExecutable;
2791 mergeMacro.ReplaceAll(".sh", "_merge.C");
2792 out << "export ARG=\"" << mergeMacro << "(\\\"$1\\\")\"" << endl;
2793 out << fExecutableCommand << " " << "$ARG" << endl;
2794 out << "echo \"======== " << mergeMacro.Data() << " finished with exit code: $? ========\"" << endl;
2795 out << "echo \"############## memory after: ##############\"" << endl;
2796 out << "free -m" << endl;
2797 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2798 out << "dmesg | tail -n 10" << endl;
2800 Bool_t copy = kTRUE;
2801 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2804 TString workdir = gGrid->GetHomeDirectory();
2805 TString bindir = Form("%s/bin", workdir.Data());
2806 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2807 workdir += fGridWorkingDir;
2808 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), mergeExec.Data());
2809 if (FileExists(executable)) gGrid->Rm(executable);
2810 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", mergeExec.Data());
2811 TFile::Cp(Form("file:%s",mergeExec.Data()), Form("alien://%s", executable.Data()));
2815 //______________________________________________________________________________
2816 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2818 // Write the production file to be submitted by LPM manager. The format is:
2819 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2820 // Next lines: full_path_to_dataset XXX (XXX is a string)
2821 // To submit, one has to: submit jdl XXX for all lines
2823 out.open(filename, ios::out);
2825 Error("WriteProductionFile", "Bad file name: %s", filename);
2828 TString workdir = gGrid->GetHomeDirectory();
2829 workdir += fGridWorkingDir;
2830 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2831 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2832 out << locjdl << " " << njobspermaster << endl;
2833 Int_t nmasterjobs = fInputFiles->GetEntries();
2834 for (Int_t i=0; i<nmasterjobs; i++) {
2835 TString runOutDir = gSystem->BaseName(fInputFiles->At(i)->GetName());
2836 runOutDir.ReplaceAll(".xml", "");
2838 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << runOutDir << endl;
2840 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2842 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2843 if (FileExists(filename)) gGrid->Rm(filename);
2844 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2847 //______________________________________________________________________________
2848 void AliAnalysisAlien::WriteValidationScript(Bool_t merge)
2850 // Generate the alien validation script.
2851 // Generate the validation script
2853 TString validationScript = fExecutable;
2854 if (merge) validationScript.ReplaceAll(".sh", "_mergevalidation.sh");
2855 else validationScript.ReplaceAll(".sh", "_validation.sh");
2857 Error("WriteValidationScript", "Alien connection required");
2860 TString out_stream = "";
2861 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2862 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2864 out.open(validationScript, ios::out);
2865 out << "#!/bin/bash" << endl;
2866 out << "##################################################" << endl;
2867 out << "validateout=`dirname $0`" << endl;
2868 out << "validatetime=`date`" << endl;
2869 out << "validated=\"0\";" << endl;
2870 out << "error=0" << endl;
2871 out << "if [ -z $validateout ]" << endl;
2872 out << "then" << endl;
2873 out << " validateout=\".\"" << endl;
2874 out << "fi" << endl << endl;
2875 out << "cd $validateout;" << endl;
2876 out << "validateworkdir=`pwd`;" << endl << endl;
2877 out << "echo \"*******************************************************\"" << out_stream << endl;
2878 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2880 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2881 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2882 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2883 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2884 out << "ls -la ./" << out_stream << endl;
2885 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2886 out << "##################################################" << endl;
2889 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2890 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2891 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2894 out << "if [ ! -f stderr ] ; then" << endl;
2895 out << " error=1" << endl;
2896 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2897 out << " echo \"Error = $error\" " << out_stream << endl;
2898 out << "fi" << endl;
2900 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2901 out << " error=1" << endl;
2902 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2903 out << " echo \"$parArch\" " << out_stream << endl;
2904 out << " echo \"Error = $error\" " << out_stream << endl;
2905 out << "fi" << endl;
2907 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2908 out << " error=1" << endl;
2909 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2910 out << " echo \"$segViol\" " << out_stream << endl;
2911 out << " echo \"Error = $error\" " << out_stream << endl;
2912 out << "fi" << endl;
2914 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2915 out << " error=1" << endl;
2916 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2917 out << " echo \"$segFault\" " << out_stream << endl;
2918 out << " echo \"Error = $error\" " << out_stream << endl;
2919 out << "fi" << endl;
2921 // Part dedicated to the specific analyses running into the train
2923 TObjArray *arr = fOutputFiles.Tokenize(" ");
2925 TString output_file;
2926 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2927 TString extra = mgr->GetExtraFiles();
2928 while ((os=(TObjString*)next1())) {
2929 output_file = os->GetString();
2930 Int_t index = output_file.Index("@");
2931 if (index > 0) output_file.Remove(index);
2932 if (merge && fMergeExcludes.Contains(output_file)) continue;
2933 if (extra.Contains(output_file)) continue;
2934 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2935 out << " error=1" << endl;
2936 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2937 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2938 out << "fi" << endl;
2942 out << "if ! [ -f outputs_valid ] ; then" << endl;
2943 out << " error=1" << endl;
2944 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2945 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2946 out << "fi" << endl;
2949 out << "if [ $error = 0 ] ; then" << endl;
2950 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2951 out << "fi" << endl;
2953 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2954 out << "echo \"*******************************************************\"" << out_stream << endl;
2955 out << "cd -" << endl;
2956 out << "exit $error" << endl;
2958 Bool_t copy = kTRUE;
2959 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2962 TString workdir = gGrid->GetHomeDirectory();
2963 workdir += fGridWorkingDir;
2964 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2965 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2966 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));