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"
27 #include "TObjString.h"
28 #include "TObjArray.h"
30 #include "TGridResult.h"
31 #include "TGridCollection.h"
33 #include "TFileMerger.h"
34 #include "AliAnalysisManager.h"
35 #include "AliVEventHandler.h"
36 #include "AliAnalysisDataContainer.h"
37 #include "AliAnalysisAlien.h"
39 ClassImp(AliAnalysisAlien)
41 //______________________________________________________________________________
42 AliAnalysisAlien::AliAnalysisAlien()
47 fSplitMaxInputFileNumber(0),
49 fMasterResubmitThreshold(0),
83 //______________________________________________________________________________
84 AliAnalysisAlien::AliAnalysisAlien(const char *name)
85 :AliAnalysisGrid(name),
89 fSplitMaxInputFileNumber(0),
91 fMasterResubmitThreshold(0),
125 //______________________________________________________________________________
126 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
127 :AliAnalysisGrid(other),
129 fPrice(other.fPrice),
131 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
132 fMaxInitFailed(other.fMaxInitFailed),
133 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
134 fNtestFiles(other.fNtestFiles),
135 fNMasterJobs(other.fNMasterJobs),
136 fRunNumbers(other.fRunNumbers),
137 fExecutable(other.fExecutable),
138 fArguments(other.fArguments),
139 fAnalysisMacro(other.fAnalysisMacro),
140 fAnalysisSource(other.fAnalysisSource),
141 fAdditionalLibs(other.fAdditionalLibs),
142 fSplitMode(other.fSplitMode),
143 fAPIVersion(other.fAPIVersion),
144 fROOTVersion(other.fROOTVersion),
145 fAliROOTVersion(other.fAliROOTVersion),
147 fGridWorkingDir(other.fGridWorkingDir),
148 fGridDataDir(other.fGridDataDir),
149 fDataPattern(other.fDataPattern),
150 fGridOutputDir(other.fGridOutputDir),
151 fOutputArchive(other.fOutputArchive),
152 fOutputFiles(other.fOutputFiles),
153 fInputFormat(other.fInputFormat),
154 fDatasetName(other.fDatasetName),
155 fJDLName(other.fJDLName),
156 fMergeExcludes(other.fMergeExcludes),
157 fIncludePath(other.fIncludePath),
158 fCloseSE(other.fCloseSE),
159 fFriendChainName(other.fFriendChainName),
164 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
165 fRunRange[0] = other.fRunRange[0];
166 fRunRange[1] = other.fRunRange[1];
167 if (other.fInputFiles) {
168 fInputFiles = new TObjArray();
169 TIter next(other.fInputFiles);
171 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
172 fInputFiles->SetOwner();
174 if (other.fPackages) {
175 fPackages = new TObjArray();
176 TIter next(other.fPackages);
178 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
179 fPackages->SetOwner();
183 //______________________________________________________________________________
184 AliAnalysisAlien::~AliAnalysisAlien()
187 if (fGridJDL) delete fGridJDL;
188 if (fInputFiles) delete fInputFiles;
189 if (fPackages) delete fPackages;
192 //______________________________________________________________________________
193 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
196 if (this != &other) {
197 AliAnalysisGrid::operator=(other);
198 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
199 fPrice = other.fPrice;
201 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
202 fMaxInitFailed = other.fMaxInitFailed;
203 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
204 fNtestFiles = other.fNtestFiles;
205 fRunNumbers = other.fRunNumbers;
206 fExecutable = other.fExecutable;
207 fArguments = other.fArguments;
208 fAnalysisMacro = other.fAnalysisMacro;
209 fAnalysisSource = other.fAnalysisSource;
210 fAdditionalLibs = other.fAdditionalLibs;
211 fSplitMode = other.fSplitMode;
212 fAPIVersion = other.fAPIVersion;
213 fROOTVersion = other.fROOTVersion;
214 fAliROOTVersion = other.fAliROOTVersion;
216 fGridWorkingDir = other.fGridWorkingDir;
217 fGridDataDir = other.fGridDataDir;
218 fDataPattern = other.fDataPattern;
219 fGridOutputDir = other.fGridOutputDir;
220 fOutputArchive = other.fOutputArchive;
221 fOutputFiles = other.fOutputFiles;
222 fInputFormat = other.fInputFormat;
223 fDatasetName = other.fDatasetName;
224 fJDLName = other.fJDLName;
225 fMergeExcludes = other.fMergeExcludes;
226 fIncludePath = other.fIncludePath;
227 fCloseSE = other.fCloseSE;
228 fFriendChainName = other.fFriendChainName;
229 if (other.fInputFiles) {
230 fInputFiles = new TObjArray();
231 TIter next(other.fInputFiles);
233 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
234 fInputFiles->SetOwner();
236 if (other.fPackages) {
237 fPackages = new TObjArray();
238 TIter next(other.fPackages);
240 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
241 fPackages->SetOwner();
247 //______________________________________________________________________________
248 void AliAnalysisAlien::AddIncludePath(const char *path)
250 // Add include path in the remote analysis macro.
252 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
253 else fIncludePath += Form("-I%s ", path);
256 //______________________________________________________________________________
257 void AliAnalysisAlien::AddRunNumber(Int_t run)
259 // Add a run number to the list of runs to be processed.
260 if (fRunNumbers.Length()) fRunNumbers += " ";
261 fRunNumbers += Form("%d", run);
264 //______________________________________________________________________________
265 void AliAnalysisAlien::AddDataFile(const char *lfn)
267 // Adds a data file to the input to be analysed. The file should be a valid LFN
268 // or point to an existing file in the alien workdir.
269 if (!fInputFiles) fInputFiles = new TObjArray();
270 fInputFiles->Add(new TObjString(lfn));
273 //______________________________________________________________________________
274 Bool_t AliAnalysisAlien::Connect()
276 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
277 if (gGrid && gGrid->IsConnected()) return kTRUE;
278 if (!gSystem->Getenv("alien_API_USER")) {
279 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
280 gSystem->Getenv("UID"));
284 Info("Connect", "Trying to connect to AliEn ...");
285 TGrid::Connect("alien://");
287 if (!gGrid || !gGrid->IsConnected()) {
288 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
291 fUser = gGrid->GetUser();
292 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
296 //______________________________________________________________________________
297 void AliAnalysisAlien::CdWork()
299 // Check validity of alien workspace. Create directory if possible.
301 Error("CdWork", "Alien connection required");
304 TString homedir = gGrid->GetHomeDirectory();
305 TString workdir = homedir + fGridWorkingDir;
306 if (!gGrid->Cd(workdir)) {
308 if (gGrid->Mkdir(workdir)) {
309 gGrid->Cd(fGridWorkingDir);
310 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
312 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
313 workdir.Data(), homedir.Data());
314 fGridWorkingDir = "";
319 //______________________________________________________________________________
320 Bool_t AliAnalysisAlien::CheckInputData()
322 // Check validity of input data. If necessary, create xml files.
323 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
324 Error("CheckInputData", "You have to specify either a set of run numbers or some existing grid files. Use AddRunNumber()/AddDataFile()/SetRunRange().");
327 // Process declared files
328 Bool_t is_collection = kFALSE;
329 Bool_t is_xml = kFALSE;
330 Bool_t use_tags = kFALSE;
331 Bool_t checked = kFALSE;
334 TString workdir = gGrid->GetHomeDirectory();
335 workdir += fGridWorkingDir;
338 TIter next(fInputFiles);
339 while ((objstr=(TObjString*)next())) {
342 file += objstr->GetString();
343 // Store full lfn path
344 if (FileExists(file)) objstr->SetString(file);
346 file = objstr->GetName();
347 if (!FileExists(objstr->GetName())) {
348 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
349 objstr->GetName(), workdir.Data());
353 Bool_t iscoll, isxml, usetags;
354 CheckDataType(file, iscoll, isxml, usetags);
357 is_collection = iscoll;
360 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
362 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
363 Error("CheckInputData", "Some conflict was found in the types of inputs");
369 // Process requested run numbers
370 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
371 // Check validity of alien data directory
372 if (!fGridDataDir.Length()) {
373 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
376 if (!gGrid->Cd(fGridDataDir)) {
377 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
381 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
385 if (checked && !is_xml) {
386 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
389 // Check validity of run number(s)
395 use_tags = fDataPattern.Contains("tag");
396 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
398 if (use_tags != fDataPattern.Contains("tag")) {
399 Error("CheckInputData", "Cannot mix input files using/not using tags");
402 if (fRunNumbers.Length()) {
403 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
404 arr = fRunNumbers.Tokenize(" ");
406 while ((os=(TObjString*)next())) {
407 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
408 if (!gGrid->Cd(path)) {
409 Warning("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
412 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
413 TString msg = "\n##### file: ";
415 msg += " type: xml_collection;";
416 if (use_tags) msg += " using_tags: Yes";
417 else msg += " using_tags: No";
418 Info("CheckDataType", msg.Data());
423 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
424 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
425 path = Form("%s/%d ", fGridDataDir.Data(), irun);
426 if (!gGrid->Cd(path)) {
427 Warning("CheckInputData", "Run number %d not found in path: %s", irun, path.Data());
430 path = Form("%s/%d.xml", workdir.Data(),irun);
431 TString msg = "\n##### file: ";
433 msg += " type: xml_collection;";
434 if (use_tags) msg += " using_tags: Yes";
435 else msg += " using_tags: No";
436 Info("CheckDataType", msg.Data());
443 //______________________________________________________________________________
444 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
446 // Create dataset for the grid data directory + run number.
447 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
449 Error("CreateDataset", "Cannot create dataset with no grid connection");
455 TString workdir = gGrid->GetHomeDirectory();
456 workdir += fGridWorkingDir;
458 // Compose the 'find' command arguments
460 TString options = "-x collection ";
461 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
462 TString conditions = "";
466 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
468 if (fRunNumbers.Length()) {
469 TObjArray *arr = fRunNumbers.Tokenize(" ");
472 while ((os=(TObjString*)next())) {
473 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
474 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
475 else file = Form("%s.xml", os->GetString().Data());
476 if (FileExists(file) && !TestBit(AliAnalysisGrid::kTest)) {
477 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
485 // conditions = Form(" > %s", file.Data());
486 command += conditions;
487 TGridResult *res = gGrid->Command(command);
489 // Write standard output to file
490 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
491 if (TestBit(AliAnalysisGrid::kTest)) break;
492 // Copy xml file to alien space
493 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
494 if (!FileExists(file)) {
495 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
502 // Process a full run range.
503 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
504 path = Form("%s/%d ", fGridDataDir.Data(), irun);
505 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
506 else file = Form("%d.xml", irun);
507 if (FileExists(file) && !TestBit(AliAnalysisGrid::kTest)) {
508 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
516 // conditions = Form(" > %s", file.Data());
517 command += conditions;
518 TGridResult *res = gGrid->Command(command);
520 // Write standard output to file
521 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
522 if (TestBit(AliAnalysisGrid::kTest)) break;
523 // Copy xml file to alien space
524 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
525 if (!FileExists(file)) {
526 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
534 //______________________________________________________________________________
535 Bool_t AliAnalysisAlien::CreateJDL()
537 // Generate a JDL file according to current settings. The name of the file is
538 // specified by fJDLName.
539 Bool_t error = kFALSE;
542 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
543 Bool_t generate = kTRUE;
544 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
546 Error("CreateJDL", "Alien connection required");
549 // Check validity of alien workspace
551 TString workdir = gGrid->GetHomeDirectory();
552 workdir += fGridWorkingDir;
556 Error("CreateJDL()", "Define some input files for your analysis.");
559 // Compose list of input files
560 // Check if output files were defined
561 if (!fOutputFiles.Length()) {
562 Error("CreateJDL", "You must define at least one output file");
565 // Check if an output directory was defined and valid
566 if (!fGridOutputDir.Length()) {
567 Error("CreateJDL", "You must define AliEn output directory");
570 if (!gGrid->Cd(fGridOutputDir)) {
571 if (gGrid->Mkdir(fGridOutputDir)) {
572 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
574 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
580 // Exit if any error up to now
581 if (error) return kFALSE;
583 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
584 fGridJDL->SetExecutable(fExecutable);
585 // fGridJDL->SetTTL((UInt_t)fTTL);
586 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
587 if (fMaxInitFailed > 0)
588 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
589 if (fSplitMaxInputFileNumber > 0)
590 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
591 if (fSplitMode.Length())
592 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
593 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
594 if (fAliROOTVersion.Length())
595 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
596 if (fROOTVersion.Length())
597 fGridJDL->AddToPackages("ROOT", fROOTVersion);
598 if (fAPIVersion.Length())
599 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
600 fGridJDL->SetInputDataListFormat(fInputFormat);
601 fGridJDL->SetInputDataList("wn.xml");
602 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
603 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
604 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
605 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
606 if (fAdditionalLibs.Length()) {
607 arr = fAdditionalLibs.Tokenize(" ");
609 while ((os=(TObjString*)next())) {
610 if (os->GetString().Contains(".so")) continue;
611 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
616 TIter next(fPackages);
619 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
621 if (fOutputArchive.Length()) {
622 arr = fOutputArchive.Tokenize(" ");
624 while ((os=(TObjString*)next()))
625 if (!os->GetString().Contains("@") && fCloseSE.Length())
626 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
628 fGridJDL->AddToOutputArchive(os->GetString());
631 arr = fOutputFiles.Tokenize(" ");
633 while ((os=(TObjString*)next())) {
634 if (!os->GetString().Contains("@") && fCloseSE.Length())
635 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
637 fGridJDL->AddToOutputSandbox(os->GetString());
640 // fGridJDL->SetPrice((UInt_t)fPrice);
641 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
642 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
643 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
644 // Depending if going through a run range or not, generate one or mode jdl's
645 if (!fRunRange[0]) WriteJDL(-1,copy);
647 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++)
648 if (!WriteJDL(irun-fRunRange[0],copy)) break;
651 // Copy jdl to grid workspace
653 if (fAdditionalLibs.Length()) {
654 arr = fAdditionalLibs.Tokenize(" ");
657 while ((os=(TObjString*)next())) {
658 if (os->GetString().Contains(".so")) continue;
659 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
660 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
661 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
666 TIter next(fPackages);
668 while ((obj=next())) {
669 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
670 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
677 //______________________________________________________________________________
678 Bool_t AliAnalysisAlien::WriteJDL(Int_t findex, Bool_t copy)
680 // Writes one or more JDL's corresponding to findex. If findex is negative,
681 // all run numbers are considered in one go (jdl). For non-negative indices
682 // they correspond to the indices in the array fInputFiles.
683 if (!fInputFiles) return kFALSE;
686 TString workdir = gGrid->GetHomeDirectory();
687 workdir += fGridWorkingDir;
689 TIter next(fInputFiles);
690 while ((os=(TObjString*)next()))
691 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
692 fGridJDL->SetOutputDirectory(Form("%s/%s/#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data()));
694 os = (TObjString*)fInputFiles->At(findex);
695 if (!os) return kFALSE;
696 line = "#Input xml collection\n";
697 line += "InputDataCollection = {";
698 line += Form(" \"LF:%s,nodownload\"", os->GetString().Data());
700 fGridJDL->SetOutputDirectory(Form("%s/%s/%03d#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data(),findex));
704 // Generate the JDL as a string
705 TString sjdl = fGridJDL->Generate();
707 index = sjdl.Index("Executable");
708 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
709 index = sjdl.Index("Split ");
710 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
711 index = sjdl.Index("SplitMaxInputFileNumber");
712 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
713 index = sjdl.Index("InputDataCollection");
714 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
716 index = sjdl.Index("OutputDir");
717 sjdl.Insert(index, line.Data());
719 index = sjdl.Index("InputFile");
720 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
721 index = sjdl.Index("InputDataList ");
722 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
723 index = sjdl.Index("InputDataListFormat");
724 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
725 index = sjdl.Index("Price");
726 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
727 index = sjdl.Index("Requirements");
728 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
729 index = sjdl.Index("Packages");
730 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
731 index = sjdl.Index("User =");
732 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
733 index = sjdl.Index("TTL");
734 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
735 index = sjdl.Index("OutputFile");
736 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
737 index = sjdl.Index("OutputDir");
738 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
739 index = sjdl.Index("OutputArchive");
740 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
741 index = sjdl.Index("MaxInitFailed");
742 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
743 index = sjdl.Index("MasterResubmitThreshold");
744 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
745 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
746 index = sjdl.Index("Validationcommand");
747 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
748 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
749 sjdl.ReplaceAll("(member", "\n (member");
750 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
751 sjdl.ReplaceAll("{", "{\n ");
752 sjdl.ReplaceAll("};", "\n};");
753 sjdl.ReplaceAll("{\n \n", "{\n");
754 sjdl.ReplaceAll("\n\n", "\n");
755 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
756 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
757 sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
758 index = sjdl.Index("JDLVariables");
759 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
761 TString snjdl = fJDLName;
762 if (findex >=0) snjdl.ReplaceAll(".jdl", Form("_%03d.jdl", findex));
764 out.open(snjdl.Data(), ios::out);
766 Error("CreateJDL", "Bad file name: %s", snjdl.Data());
771 // Copy jdl to grid workspace
773 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
775 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn working space", snjdl.Data());
776 if (FileExists(snjdl)) gGrid->Rm(snjdl);
777 TFile::Cp(Form("file:%s",snjdl.Data()), Form("alien://%s/%s", workdir.Data(), snjdl.Data()));
782 //______________________________________________________________________________
783 Bool_t AliAnalysisAlien::FileExists(const char *lfn) const
785 // Returns true if file exists.
787 Error("FileExists", "No connection to grid");
790 TGridResult *res = gGrid->Ls(lfn);
791 if (!res) return kFALSE;
792 TMap *map = dynamic_cast<TMap*>(res->At(0));
797 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
798 if (!objs || !objs->GetString().Length()) {
806 //______________________________________________________________________________
807 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
809 // Check input data type.
810 is_collection = kFALSE;
814 Error("CheckDataType", "No connection to grid");
817 is_collection = IsCollection(lfn);
818 TString msg = "\n##### file: ";
821 msg += " type: raw_collection;";
822 // special treatment for collections
824 // check for tag files in the collection
825 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
827 msg += " using_tags: No (unknown)";
828 Info("CheckDataType", msg.Data());
831 const char* typeStr = res->GetKey(0, "origLFN");
832 if (!typeStr || !strlen(typeStr)) {
833 msg += " using_tags: No (unknown)";
834 Info("CheckDataType", msg.Data());
837 TString file = typeStr;
838 use_tags = file.Contains(".tag");
839 if (use_tags) msg += " using_tags: Yes";
840 else msg += " using_tags: No";
841 Info("CheckDataType", msg.Data());
846 is_xml = slfn.Contains(".xml");
848 // Open xml collection and check if there are tag files inside
849 msg += " type: xml_collection;";
850 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
852 msg += " using_tags: No (unknown)";
853 Info("CheckDataType", msg.Data());
856 TMap *map = coll->Next();
858 msg += " using_tags: No (unknown)";
859 Info("CheckDataType", msg.Data());
862 map = (TMap*)map->GetValue("");
864 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
865 use_tags = file.Contains(".tag");
867 if (use_tags) msg += " using_tags: Yes";
868 else msg += " using_tags: No";
869 Info("CheckDataType", msg.Data());
872 use_tags = slfn.Contains(".tag");
873 if (slfn.Contains(".root")) msg += " type: root file;";
874 else msg += " type: unhnown file;";
875 if (use_tags) msg += " using_tags: Yes";
876 else msg += " using_tags: No";
877 Info("CheckDataType", msg.Data());
880 //______________________________________________________________________________
881 void AliAnalysisAlien::EnablePackage(const char *package)
883 // Enables a par file supposed to exist in the current directory.
884 TString pkg(package);
885 pkg.ReplaceAll(".par", "");
887 if (gSystem->AccessPathName(pkg)) {
888 Error("EnablePackage", "Package %s not found", pkg.Data());
891 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
892 Info("EnablePackage", "AliEn plugin will use .par packages");
893 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
895 fPackages = new TObjArray();
896 fPackages->SetOwner();
898 fPackages->Add(new TObjString(pkg));
901 //______________________________________________________________________________
902 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
904 // Returns true if file is a collection. Functionality duplicated from
905 // TAlien::Type() because we don't want to directly depend on TAlien.
907 Error("IsCollection", "No connection to grid");
910 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
911 if (!res) return kFALSE;
912 const char* typeStr = res->GetKey(0, "type");
913 if (!typeStr || !strlen(typeStr)) return kFALSE;
914 if (!strcmp(typeStr, "collection")) return kTRUE;
919 //______________________________________________________________________________
920 void AliAnalysisAlien::SetDefaults()
922 // Set default values for everything. What cannot be filled will be left empty.
923 if (fGridJDL) delete fGridJDL;
924 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
927 fSplitMaxInputFileNumber = 100;
929 fMasterResubmitThreshold = 0;
935 fExecutable = "analysis.sh";
937 fAnalysisMacro = "myAnalysis.C";
938 fAnalysisSource = "";
939 fAdditionalLibs = "";
943 fAliROOTVersion = "";
944 fUser = ""; // Your alien user name
945 fGridWorkingDir = "";
946 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
947 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
948 fFriendChainName = "";
949 fGridOutputDir = "output";
950 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
951 fOutputFiles = ""; // Like "AliAODs.root histos.root"
952 fInputFormat = "xml-single";
953 fJDLName = "analysis.jdl";
957 //______________________________________________________________________________
958 Bool_t AliAnalysisAlien::MergeOutputs()
960 // Merge analysis outputs existing in the AliEn space.
961 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
962 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
964 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
967 // Get the output path
968 TString output = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
969 if (!gGrid->Cd(output)) output = Form("/%s/%s", gGrid->GetHomeDirectory(), fGridOutputDir.Data());
970 if (!gGrid->Cd(output)) {
971 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
974 if (!fOutputFiles.Length()) {
975 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
978 TObjArray *list = fOutputFiles.Tokenize(" ");
983 Bool_t merged = kTRUE;
984 while((str=(TObjString*)next())) {
985 output_file = str->GetString();
986 Int_t index = output_file.Index("@");
987 if (index > 0) output_file.Remove(index);
988 if (fMergeExcludes.Length() &&
989 fMergeExcludes.Contains(output_file.Data())) continue;
990 command = Form("find %s/ *%s", output.Data(), output_file.Data());
991 printf("command: %s\n", command.Data());
992 TGridResult *res = gGrid->Command(command);
997 while ((map=(TMap*)nextmap())) {
998 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
999 if (!objs || !objs->GetString().Length()) {
1004 fm = new TFileMerger(kFALSE);
1005 fm->SetFastMethod(kTRUE);
1006 fm->OutputFile(output_file);
1008 fm->AddFile(objs->GetString());
1010 if (!fm || !fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1011 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1017 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1020 Info("MergeOutputs", "\n##### Merged %d output files <%s>", fm->GetMergeList()->GetSize(), output_file.Data());
1026 Error("MergeOutputs", "Terminate() will NOT be executed");
1031 //______________________________________________________________________________
1032 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1034 // Use the output files connected to output containers from the analysis manager
1035 // rather than the files defined by SetOutputFiles
1036 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1037 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1039 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1042 //______________________________________________________________________________
1043 void AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1045 // Start remote grid analysis.
1047 // Check if output files have to be taken from the analysis manager
1048 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1049 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1050 if (!mgr || !mgr->IsInitialized()) {
1051 Error("StartAnalysis", "You need an initialized analysis manager for this");
1055 TIter next(mgr->GetOutputs());
1056 AliAnalysisDataContainer *output;
1057 while ((output=(AliAnalysisDataContainer*)next())) {
1058 const char *filename = output->GetFileName();
1059 if (!(strcmp(filename, "default"))) {
1060 if (!mgr->GetOutputEventHandler()) continue;
1061 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1063 if (fOutputFiles.Length()) fOutputFiles += " ";
1064 fOutputFiles += filename;
1066 // Add extra files registered to the analysis manager
1067 if (mgr->GetExtraFiles().Length()) {
1068 if (fOutputFiles.Length()) fOutputFiles += " ";
1069 fOutputFiles += mgr->GetExtraFiles();
1072 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1073 if (TestBit(AliAnalysisGrid::kOffline)) {
1074 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1075 \n there nor any job run. You can revise the JDL and analysis \
1076 \n macro then run the same in \"submit\" mode.");
1077 } else if (TestBit(AliAnalysisGrid::kTest)) {
1078 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1080 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1081 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1082 \n space and job submitted.");
1083 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1084 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1087 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1091 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1094 if (!CheckInputData()) {
1095 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1098 CreateDataset(fDataPattern);
1099 WriteAnalysisFile();
1100 WriteAnalysisMacro();
1102 WriteValidationScript();
1103 if (!CreateJDL()) return;
1104 if (TestBit(AliAnalysisGrid::kOffline)) return;
1105 if (TestBit(AliAnalysisGrid::kTest)) {
1106 // Locally testing the analysis
1107 Info("StartAnalysis", "\n_______________________________________________________________________ \
1108 \n Running analysis script in a daughter shell as on a worker node \
1109 \n_______________________________________________________________________");
1110 TObjArray *list = fOutputFiles.Tokenize(" ");
1113 TString output_file;
1114 while((str=(TObjString*)next())) {
1115 output_file = str->GetString();
1116 Int_t index = output_file.Index("@");
1117 if (index > 0) output_file.Remove(index);
1118 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1121 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1122 gSystem->Exec("bash validate.sh");
1123 // gSystem->Exec("cat stdout");
1126 // Submit AliEn job(s)
1130 if (!fRunRange[0]) {
1131 // Submit a given xml or a set of runs
1132 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1133 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1135 const char *cjobId = res->GetKey(0,"jobId");
1137 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1140 Info("StartAnalysis", "\n_______________________________________________________________________ \
1141 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1142 \n_______________________________________________________________________",
1143 fJDLName.Data(), cjobId);
1149 // Submit for a range of runs.
1151 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
1152 if (!fInputFiles->At(irun-fRunRange[0])) break;
1154 sjdl.ReplaceAll(".jdl", Form("_%03d.jdl", irun-fRunRange[0]));
1155 res = gGrid->Command(Form("submit %s", sjdl.Data()));
1156 printf("*************************** %s\n",Form("submit %s", sjdl.Data()));
1158 const char *cjobId1 = res->GetKey(0,"jobId");
1160 Error("StartAnalysis", "Your JDL %s could not be submitted", sjdl.Data());
1163 Info("StartAnalysis", "\n_______________________________________________________________________ \
1164 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1165 \n_______________________________________________________________________",
1166 sjdl.Data(), cjobId1);
1175 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1176 \n You may exit at any time and terminate the job later using the option <terminate> \
1177 \n ##################################################################################", jobID.Data());
1178 gSystem->Exec("aliensh");
1181 //______________________________________________________________________________
1182 void AliAnalysisAlien::WriteAnalysisFile()
1184 // Write current analysis manager into the file analysis.root
1185 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1186 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1187 if (!mgr || !mgr->IsInitialized()) {
1188 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1191 // Check analysis type
1193 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1194 handler = (TObject*)mgr->GetInputEventHandler();
1196 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1197 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1199 TDirectory *cdir = gDirectory;
1200 TFile *file = TFile::Open("analysis.root", "RECREATE");
1205 if (cdir) cdir->cd();
1206 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1208 Bool_t copy = kTRUE;
1209 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1212 TString workdir = gGrid->GetHomeDirectory();
1213 workdir += fGridWorkingDir;
1214 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1215 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1216 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1220 //______________________________________________________________________________
1221 void AliAnalysisAlien::WriteAnalysisMacro()
1223 // Write the analysis macro that will steer the analysis in grid mode.
1224 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1226 out.open(fAnalysisMacro.Data(), ios::out);
1228 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1231 TString func = fAnalysisMacro;
1232 TString type = "ESD";
1233 TString comment = "// Analysis using ";
1234 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1235 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1239 if (type!="AOD" && fFriendChainName!="") {
1240 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1243 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1244 else comment += " data";
1245 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1246 func.ReplaceAll(".C", "");
1247 out << "void " << func.Data() << "()" << endl;
1249 out << comment.Data() << endl;
1250 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1251 out << " TStopwatch timer;" << endl;
1252 out << " timer.Start();" << endl << endl;
1253 out << "// load base root libraries" << endl;
1254 out << " gSystem->Load(\"libTree\");" << endl;
1255 out << " gSystem->Load(\"libGeom\");" << endl;
1256 out << " gSystem->Load(\"libVMC\");" << endl;
1257 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1258 out << "// Load analysis framework libraries" << endl;
1260 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1261 out << " gSystem->Load(\"libESD\");" << endl;
1262 out << " gSystem->Load(\"libAOD\");" << endl;
1263 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1264 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1265 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1267 TIter next(fPackages);
1270 Bool_t hasSTEERBase = kFALSE;
1271 Bool_t hasESD = kFALSE;
1272 Bool_t hasAOD = kFALSE;
1273 Bool_t hasANALYSIS = kFALSE;
1274 Bool_t hasANALYSISalice = kFALSE;
1275 Bool_t hasCORRFW = kFALSE;
1276 while ((obj=next())) {
1277 pkgname = obj->GetName();
1278 if (pkgname == "STEERBase" ||
1279 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1280 if (pkgname == "ESD" ||
1281 pkgname == "ESD.par") hasESD = kTRUE;
1282 if (pkgname == "AOD" ||
1283 pkgname == "AOD.par") hasAOD = kTRUE;
1284 if (pkgname == "ANALYSIS" ||
1285 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1286 if (pkgname == "ANALYSISalice" ||
1287 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1288 if (pkgname == "CORRFW" ||
1289 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1291 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1292 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1293 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1294 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1295 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1296 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1297 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1298 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1299 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1300 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1301 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1302 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1303 out << "// Compile other par packages" << endl;
1305 while ((obj=next())) {
1306 pkgname = obj->GetName();
1307 if (pkgname == "STEERBase" ||
1308 pkgname == "STEERBase.par" ||
1310 pkgname == "ESD.par" ||
1312 pkgname == "AOD.par" ||
1313 pkgname == "ANALYSIS" ||
1314 pkgname == "ANALYSIS.par" ||
1315 pkgname == "ANALYSISalice" ||
1316 pkgname == "ANALYSISalice.par" ||
1317 pkgname == "CORRFW" ||
1318 pkgname == "CORRFW.par") continue;
1319 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1322 out << "// include path" << endl;
1323 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1324 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1325 if (fAdditionalLibs.Length()) {
1326 out << "// Add aditional AliRoot libraries" << endl;
1327 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1330 while((str=(TObjString*)next())) {
1331 if (str->GetString().Contains(".so"))
1332 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1334 if (list) delete list;
1337 out << "// analysis source to be compiled at runtime (if any)" << endl;
1338 if (fAnalysisSource.Length()) {
1339 TObjArray *list = fAnalysisSource.Tokenize(" ");
1342 while((str=(TObjString*)next())) {
1343 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1345 if (list) delete list;
1348 out << "// connect to AliEn and make the chain" << endl;
1349 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1350 if (IsUsingTags()) {
1351 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1353 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1355 out << "// read the analysis manager from file" << endl;
1356 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1357 out << " if (!file) return;" << endl;
1358 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1359 out << " AliAnalysisManager *mgr = 0;" << endl;
1360 out << " TKey *key;" << endl;
1361 out << " while ((key=(TKey*)nextkey())) {" << endl;
1362 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1363 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1364 out << " };" << endl;
1365 out << " if (!mgr) {" << endl;
1366 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1367 out << " return;" << endl;
1368 out << " }" << endl << endl;
1369 out << " mgr->PrintStatus();" << endl;
1370 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1371 out << " timer.Stop();" << endl;
1372 out << " timer.Print();" << endl;
1373 out << "}" << endl << endl;
1374 if (IsUsingTags()) {
1375 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1377 out << "// Create a chain using tags from the xml file." << endl;
1378 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1379 out << " if (!coll) {" << endl;
1380 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1381 out << " return NULL;" << endl;
1382 out << " }" << endl;
1383 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1384 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1385 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1386 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1387 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1388 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1389 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1390 out << " // Check if the cuts configuration file was provided" << endl;
1391 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1392 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1393 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1394 out << " }" << endl;
1395 if (fFriendChainName=="") {
1396 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1398 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1399 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1400 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1402 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1403 out << " chain->ls();" << endl;
1404 out << " return chain;" << endl;
1405 out << "}" << endl << endl;
1406 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1407 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1408 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1409 msg += " AliLHCTagCuts *lhcCuts,\n";
1410 msg += " AliDetectorTagCuts *detCuts,\n";
1411 msg += " AliEventTagCuts *evCuts)";
1412 Info("WriteAnalysisMacro", msg.Data());
1415 if (!IsUsingTags() || fFriendChainName!="") {
1416 out <<"//________________________________________________________________________________" << endl;
1417 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1419 out << "// Create a chain using url's from xml file" << endl;
1420 out << " TString treename = type;" << endl;
1421 out << " treename.ToLower();" << endl;
1422 out << " treename += \"Tree\";" << endl;
1423 out << " printf(\"***************************************\\n\");" << endl;
1424 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1425 out << " printf(\"***************************************\\n\");" << endl;
1426 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1427 out << " if (!coll) {" << endl;
1428 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1429 out << " return NULL;" << endl;
1430 out << " }" << endl;
1431 out << " TChain *chain = new TChain(treename);" << endl;
1432 if(fFriendChainName!="") {
1433 out << " TChain *chainFriend = new TChain(treename);" << endl;
1435 out << " coll->Reset();" << endl;
1436 out << " while (coll->Next()) {" << endl;
1437 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1438 if(fFriendChainName!="") {
1439 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1440 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1441 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1442 out << " chainFriend->Add(fileFriend.Data());" << endl;
1444 out << " }" << endl;
1445 out << " if (!chain->GetNtrees()) {" << endl;
1446 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1447 out << " return NULL;" << endl;
1448 out << " }" << endl;
1449 if(fFriendChainName!="") {
1450 out << " chain->AddFriend(chainFriend);" << endl;
1452 out << " return chain;" << endl;
1453 out << "}" << endl << endl;
1456 out <<"//________________________________________________________________________________" << endl;
1457 out << "Bool_t SetupPar(const char *package) {" << endl;
1458 out << "// Compile the package and set it up." << endl;
1459 out << " TString pkgdir = package;" << endl;
1460 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1461 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1462 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1463 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1464 out << " // Check for BUILD.sh and execute" << endl;
1465 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1466 out << " printf(\"*******************************\\n\");" << endl;
1467 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1468 out << " printf(\"*******************************\\n\");" << endl;
1469 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1470 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1471 out << " gSystem->ChangeDirectory(cdir);" << endl;
1472 out << " return kFALSE;" << endl;
1473 out << " }" << endl;
1474 out << " } else {" << endl;
1475 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1476 out << " gSystem->ChangeDirectory(cdir);" << endl;
1477 out << " return kFALSE;" << endl;
1478 out << " }" << endl;
1479 out << " // Check for SETUP.C and execute" << endl;
1480 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1481 out << " printf(\"*******************************\\n\");" << endl;
1482 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1483 out << " printf(\"*******************************\\n\");" << endl;
1484 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1485 out << " } else {" << endl;
1486 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
1487 out << " gSystem->ChangeDirectory(cdir);" << endl;
1488 out << " return kFALSE;" << endl;
1489 out << " }" << endl;
1490 out << " // Restore original workdir" << endl;
1491 out << " gSystem->ChangeDirectory(cdir);" << endl;
1492 out << " return kTRUE;" << endl;
1495 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1497 Bool_t copy = kTRUE;
1498 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1501 TString workdir = gGrid->GetHomeDirectory();
1502 workdir += fGridWorkingDir;
1503 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1504 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1505 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1506 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1507 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1509 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1510 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1514 //______________________________________________________________________________
1515 void AliAnalysisAlien::WriteExecutable()
1517 // Generate the alien executable script.
1518 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1520 out.open(fExecutable.Data(), ios::out);
1522 Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1525 out << "#!/bin/bash" << endl;
1526 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1527 out << "echo \"=========================================\"" << endl;
1528 out << "echo \"############## PATH : ##############\"" << endl;
1529 out << "echo $PATH" << endl;
1530 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1531 out << "echo $LD_LIBRARY_PATH" << endl;
1532 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1533 out << "echo $ROOTSYS" << endl;
1534 out << "echo \"############## which root : ##############\"" << endl;
1535 out << "which root" << endl;
1536 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1537 out << "echo $ALICE_ROOT" << endl;
1538 out << "echo \"############## which aliroot : ##############\"" << endl;
1539 out << "which aliroot" << endl;
1540 out << "echo \"=========================================\"" << endl << endl;
1541 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1542 out << "root -b -q ";
1543 out << fAnalysisMacro.Data() << endl << endl;
1544 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1546 Bool_t copy = kTRUE;
1547 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1550 TString workdir = gGrid->GetHomeDirectory();
1551 workdir += fGridWorkingDir;
1552 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1553 if (FileExists(executable)) gGrid->Rm(executable);
1554 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1555 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1559 //______________________________________________________________________________
1560 void AliAnalysisAlien::WriteValidationScript()
1562 // Generate the alien validation script.
1563 // Generate the validation script
1566 Error("WriteValidationScript", "Alien connection required");
1569 TString out_stream = "";
1570 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1571 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1573 out.open("validate.sh", ios::out);
1574 out << "#!/bin/bash" << endl;
1575 out << "##################################################" << endl;
1576 out << "validateout=`dirname $0`" << endl;
1577 out << "validatetime=`date`" << endl;
1578 out << "validated=\"0\";" << endl;
1579 out << "error=0" << endl;
1580 out << "if [ -z $validateout ]" << endl;
1581 out << "then" << endl;
1582 out << " validateout=\".\"" << endl;
1583 out << "fi" << endl << endl;
1584 out << "cd $validateout;" << endl;
1585 out << "validateworkdir=`pwd`;" << endl << endl;
1586 out << "echo \"*******************************************************\"" << out_stream << endl;
1587 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1589 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1590 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1591 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1592 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1593 out << "ls -la ./" << out_stream << endl;
1594 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1595 out << "##################################################" << endl;
1598 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
1599 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
1600 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
1603 out << "if [ ! -f stderr ] ; then" << endl;
1604 out << " error=1" << endl;
1605 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
1606 out << " echo \"Error = $error\" " << out_stream << endl;
1607 out << "fi" << endl;
1609 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
1610 out << " error=1" << endl;
1611 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
1612 out << " echo \"$parArch\" " << out_stream << endl;
1613 out << " echo \"Error = $error\" " << out_stream << endl;
1614 out << "fi" << endl;
1616 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
1617 out << " error=1" << endl;
1618 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
1619 out << " echo \"$segViol\" " << out_stream << endl;
1620 out << " echo \"Error = $error\" " << out_stream << endl;
1621 out << "fi" << endl;
1623 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
1624 out << " error=1" << endl;
1625 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
1626 out << " echo \"$segFault\" " << out_stream << endl;
1627 out << " echo \"Error = $error\" " << out_stream << endl;
1628 out << "fi" << endl;
1630 // Part dedicated to the specific analyses running into the train
1632 TObjArray *arr = fOutputFiles.Tokenize(" ");
1634 TString output_file;
1635 while ((os=(TObjString*)next1())) {
1636 output_file = os->GetString();
1637 Int_t index = output_file.Index("@");
1638 if (index > 0) output_file.Remove(index);
1639 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1640 out << " error=1" << endl;
1641 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
1642 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
1643 out << "fi" << endl;
1646 out << "if [ $error = 0 ] ; then" << endl;
1647 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
1648 out << "fi" << endl;
1650 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1651 out << "echo \"*******************************************************\"" << out_stream << endl;
1652 out << "cd -" << endl;
1653 out << "exit $error" << endl;
1655 Bool_t copy = kTRUE;
1656 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1659 TString workdir = gGrid->GetHomeDirectory();
1660 workdir += fGridWorkingDir;
1661 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
1662 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
1663 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));