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),
80 //______________________________________________________________________________
81 AliAnalysisAlien::AliAnalysisAlien(const char *name)
82 :AliAnalysisGrid(name),
86 fSplitMaxInputFileNumber(0),
88 fMasterResubmitThreshold(0),
119 //______________________________________________________________________________
120 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
121 :AliAnalysisGrid(other),
123 fPrice(other.fPrice),
125 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
126 fMaxInitFailed(other.fMaxInitFailed),
127 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
128 fNtestFiles(other.fNtestFiles),
129 fRunNumbers(other.fRunNumbers),
130 fExecutable(other.fExecutable),
131 fArguments(other.fArguments),
132 fAnalysisMacro(other.fAnalysisMacro),
133 fAnalysisSource(other.fAnalysisSource),
134 fAdditionalLibs(other.fAdditionalLibs),
135 fSplitMode(other.fSplitMode),
136 fAPIVersion(other.fAPIVersion),
137 fROOTVersion(other.fROOTVersion),
138 fAliROOTVersion(other.fAliROOTVersion),
140 fGridWorkingDir(other.fGridWorkingDir),
141 fGridDataDir(other.fGridDataDir),
142 fDataPattern(other.fDataPattern),
143 fGridOutputDir(other.fGridOutputDir),
144 fOutputArchive(other.fOutputArchive),
145 fOutputFiles(other.fOutputFiles),
146 fInputFormat(other.fInputFormat),
147 fDatasetName(other.fDatasetName),
148 fJDLName(other.fJDLName),
149 fMergeExcludes(other.fMergeExcludes),
150 fCloseSE(other.fCloseSE),
155 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
156 if (other.fInputFiles) {
157 fInputFiles = new TObjArray();
158 TIter next(other.fInputFiles);
160 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
161 fInputFiles->SetOwner();
163 if (other.fPackages) {
164 fPackages = new TObjArray();
165 TIter next(other.fPackages);
167 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
168 fPackages->SetOwner();
172 //______________________________________________________________________________
173 AliAnalysisAlien::~AliAnalysisAlien()
176 if (fGridJDL) delete fGridJDL;
177 if (fInputFiles) delete fInputFiles;
178 if (fPackages) delete fPackages;
181 //______________________________________________________________________________
182 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
185 if (this != &other) {
186 AliAnalysisGrid::operator=(other);
187 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
188 fPrice = other.fPrice;
190 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
191 fMaxInitFailed = other.fMaxInitFailed;
192 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
193 fNtestFiles = other.fNtestFiles;
194 fRunNumbers = other.fRunNumbers;
195 fExecutable = other.fExecutable;
196 fArguments = other.fArguments;
197 fAnalysisMacro = other.fAnalysisMacro;
198 fAnalysisSource = other.fAnalysisSource;
199 fAdditionalLibs = other.fAdditionalLibs;
200 fSplitMode = other.fSplitMode;
201 fAPIVersion = other.fAPIVersion;
202 fROOTVersion = other.fROOTVersion;
203 fAliROOTVersion = other.fAliROOTVersion;
205 fGridWorkingDir = other.fGridWorkingDir;
206 fGridDataDir = other.fGridDataDir;
207 fDataPattern = other.fDataPattern;
208 fGridOutputDir = other.fGridOutputDir;
209 fOutputArchive = other.fOutputArchive;
210 fOutputFiles = other.fOutputFiles;
211 fInputFormat = other.fInputFormat;
212 fDatasetName = other.fDatasetName;
213 fJDLName = other.fJDLName;
214 fMergeExcludes = other.fMergeExcludes;
215 fCloseSE = other.fCloseSE;
216 if (other.fInputFiles) {
217 fInputFiles = new TObjArray();
218 TIter next(other.fInputFiles);
220 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
221 fInputFiles->SetOwner();
223 if (other.fPackages) {
224 fPackages = new TObjArray();
225 TIter next(other.fPackages);
227 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
228 fPackages->SetOwner();
234 //______________________________________________________________________________
235 void AliAnalysisAlien::AddRunNumber(Int_t run)
237 // Add a run number to the list of runs to be processed.
238 if (fRunNumbers.Length()) fRunNumbers += " ";
239 fRunNumbers += Form("%d", run);
242 //______________________________________________________________________________
243 void AliAnalysisAlien::AddDataFile(const char *lfn)
245 // Adds a data file to the input to be analysed. The file should be a valid LFN
246 // or point to an existing file in the alien workdir.
247 if (!fInputFiles) fInputFiles = new TObjArray();
248 fInputFiles->Add(new TObjString(lfn));
251 //______________________________________________________________________________
252 Bool_t AliAnalysisAlien::Connect()
254 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
255 if (gGrid && gGrid->IsConnected()) return kTRUE;
256 if (!gSystem->Getenv("alien_API_USER")) {
257 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
258 gSystem->Getenv("UID"));
262 Info("Connect", "Trying to connect to AliEn ...");
263 TGrid::Connect("alien://");
265 if (!gGrid || !gGrid->IsConnected()) {
266 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
269 fUser = gGrid->GetUser();
270 fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
271 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
275 //______________________________________________________________________________
276 void AliAnalysisAlien::CdWork()
278 // Check validity of alien workspace. Create directory if possible.
280 Error("CdWork", "Alien connection required");
283 TString homedir = gGrid->GetHomeDirectory();
284 TString workdir = homedir + fGridWorkingDir;
285 if (!gGrid->Cd(workdir)) {
287 if (gGrid->Mkdir(workdir)) {
288 gGrid->Cd(fGridWorkingDir);
289 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
291 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
292 workdir.Data(), homedir.Data());
293 fGridWorkingDir = "";
298 //______________________________________________________________________________
299 Bool_t AliAnalysisAlien::CheckInputData()
301 // Check validity of input data. If necessary, create xml files.
302 if (!fInputFiles && !fRunNumbers.Length()) {
303 Error("CheckInputData", "You have to specify either a set of run numbers or some existing grid files. Use AddRunNumber()/AddDataFile().");
306 // Process declared files
307 Bool_t is_collection = kFALSE;
308 Bool_t is_xml = kFALSE;
309 Bool_t use_tags = kFALSE;
310 Bool_t checked = kFALSE;
313 TString workdir = gGrid->GetHomeDirectory();
314 workdir += fGridWorkingDir;
317 TIter next(fInputFiles);
318 while ((objstr=(TObjString*)next())) {
321 file += objstr->GetString();
322 // Store full lfn path
323 if (FileExists(file)) objstr->SetString(file);
325 file = objstr->GetName();
326 if (!FileExists(objstr->GetName())) {
327 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
328 objstr->GetName(), workdir.Data());
332 Bool_t iscoll, isxml, usetags;
333 CheckDataType(file, iscoll, isxml, usetags);
336 is_collection = iscoll;
339 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
341 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
342 Error("CheckInputData", "Some conflict was found in the types of inputs");
348 // Process requested run numbers
349 if (!fRunNumbers.Length()) return kTRUE;
350 // Check validity of alien data directory
351 if (!fGridDataDir.Length()) {
352 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
355 if (!gGrid->Cd(fGridDataDir)) {
356 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
360 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
364 if (checked && !is_xml) {
365 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
368 // Check validity of run number(s)
374 use_tags = fDataPattern.Contains("tag");
375 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
377 if (use_tags != fDataPattern.Contains("tag")) {
378 Error("CheckInputData", "Cannot mix input files using/not using tags");
381 if (fRunNumbers.Length()) {
382 arr = fRunNumbers.Tokenize(" ");
384 while ((os=(TObjString*)next())) {
385 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
386 if (!gGrid->Cd(path)) {
387 Error("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
390 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
391 TString msg = "\n##### file: ";
393 msg += " type: xml_collection;";
394 if (use_tags) msg += " using_tags: Yes";
395 else msg += " using_tags: No";
396 Info("CheckDataType", msg.Data());
404 //______________________________________________________________________________
405 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
407 // Create dataset for the grid data directory + run number.
408 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
410 Error("CreateDataset", "Cannot create dataset with no grid connection");
416 TString workdir = gGrid->GetHomeDirectory();
417 workdir += fGridWorkingDir;
419 // Compose the 'find' command arguments
421 TString options = "-x collection ";
422 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
423 TString conditions = "";
427 if (!fRunNumbers.Length()) return kTRUE;
429 TObjArray *arr = fRunNumbers.Tokenize(" ");
432 while ((os=(TObjString*)next())) {
433 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
434 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
435 else file = Form("%s.xml", os->GetString().Data());
436 if (FileExists(file) && !TestBit(AliAnalysisGrid::kTest)) {
437 Info("CreateDataset", "\n##### Removing previous dataset %s", file.Data());
444 // conditions = Form(" > %s", file.Data());
445 command += conditions;
446 TGridResult *res = gGrid->Command(command);
448 // Write standard output to file
449 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
450 if (TestBit(AliAnalysisGrid::kTest)) break;
451 // Copy xml file to alien space
452 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
453 if (!FileExists(file)) {
454 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
463 //______________________________________________________________________________
464 Bool_t AliAnalysisAlien::CreateJDL()
466 // Generate a JDL file according to current settings. The name of the file is
467 // specified by fJDLName.
468 Bool_t error = kFALSE;
471 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
472 Bool_t generate = kTRUE;
473 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
475 Error("CreateJDL", "Alien connection required");
478 // Check validity of alien workspace
480 TString workdir = gGrid->GetHomeDirectory();
481 workdir += fGridWorkingDir;
485 Error("CreateJDL()", "Define some input files for your analysis.");
488 // Compose list of input files
489 // Check if output files were defined
490 if (!fOutputFiles.Length()) {
491 Error("CreateJDL", "You must define at least one output file");
494 // Check if an output directory was defined and valid
495 if (!fGridOutputDir.Length()) {
496 Error("CreateJDL", "You must define AliEn output directory");
499 if (!gGrid->Cd(fGridOutputDir)) {
500 if (gGrid->Mkdir(fGridOutputDir)) {
501 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
503 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
509 // Exit if any error up to now
510 if (error) return kFALSE;
512 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
513 fGridJDL->SetExecutable(fExecutable);
514 // fGridJDL->SetTTL((UInt_t)fTTL);
515 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
516 if (fMaxInitFailed > 0)
517 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
518 if (fSplitMaxInputFileNumber > 0)
519 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
520 if (fSplitMode.Length())
521 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
522 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
523 if (fAliROOTVersion.Length())
524 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
525 if (fROOTVersion.Length())
526 fGridJDL->AddToPackages("ROOT", fROOTVersion);
527 if (fAPIVersion.Length())
528 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
529 fGridJDL->SetInputDataListFormat(fInputFormat);
530 fGridJDL->SetInputDataList("wn.xml");
532 TIter next(fInputFiles);
533 while ((os=(TObjString*)next()))
534 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
536 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
537 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
538 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
539 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
540 if (fAdditionalLibs.Length()) {
541 arr = fAdditionalLibs.Tokenize(" ");
543 while ((os=(TObjString*)next())) {
544 if (os->GetString().Contains(".so")) continue;
545 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
550 TIter next(fPackages);
553 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
555 if (fOutputArchive.Length()) {
556 arr = fOutputArchive.Tokenize(" ");
558 while ((os=(TObjString*)next()))
559 fGridJDL->AddToOutputArchive(os->GetString().Data());
562 fGridJDL->SetOutputDirectory(Form("%s/%s/#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data()));
563 arr = fOutputFiles.Tokenize(" ");
565 while ((os=(TObjString*)next())) fGridJDL->AddToOutputSandbox(os->GetString());
567 // fGridJDL->SetPrice((UInt_t)fPrice);
568 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
569 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
570 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
571 // Generate the JDL as a string
572 TString sjdl = fGridJDL->Generate();
574 index = sjdl.Index("Executable");
575 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
576 index = sjdl.Index("Split ");
577 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
578 index = sjdl.Index("SplitMaxInputFileNumber");
579 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
580 index = sjdl.Index("InputDataCollection");
581 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
582 index = sjdl.Index("InputFile");
583 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
584 index = sjdl.Index("InputDataList ");
585 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
586 index = sjdl.Index("InputDataListFormat");
587 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
588 index = sjdl.Index("Price");
589 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
590 index = sjdl.Index("Requirements");
591 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
592 index = sjdl.Index("Packages");
593 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
594 index = sjdl.Index("User");
595 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
596 index = sjdl.Index("TTL");
597 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
598 index = sjdl.Index("OutputFile");
599 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
600 index = sjdl.Index("OutputDir");
601 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
602 index = sjdl.Index("OutputArchive");
603 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
604 index = sjdl.Index("MaxInitFailed");
605 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
606 index = sjdl.Index("MasterResubmitThreshold");
607 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
608 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
609 index = sjdl.Index("Validationcommand");
610 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
611 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
612 sjdl.ReplaceAll("(member", "\n (member");
613 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
614 sjdl.ReplaceAll("{", "{\n ");
615 sjdl.ReplaceAll("};", "\n};");
616 sjdl.ReplaceAll("{\n \n", "{\n");
617 sjdl.ReplaceAll("\n\n", "\n");
618 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
619 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
620 sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
621 index = sjdl.Index("JDLVariables");
622 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
625 out.open(fJDLName.Data(), ios::out);
627 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
632 // Copy jdl to grid workspace
634 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
636 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn working space", fJDLName.Data());
637 if (FileExists(fJDLName)) gGrid->Rm(fJDLName);
638 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s/%s", workdir.Data(), fJDLName.Data()));
639 if (fAdditionalLibs.Length()) {
640 arr = fAdditionalLibs.Tokenize(" ");
643 while ((os=(TObjString*)next())) {
644 if (os->GetString().Contains(".so")) continue;
645 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
646 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
647 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
652 TIter next(fPackages);
654 while ((obj=next())) {
655 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
656 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
663 //______________________________________________________________________________
664 Bool_t AliAnalysisAlien::FileExists(const char *lfn) const
666 // Returns true if file exists.
668 Error("FileExists", "No connection to grid");
671 TGridResult *res = gGrid->Ls(lfn);
672 if (!res) return kFALSE;
673 TMap *map = dynamic_cast<TMap*>(res->At(0));
678 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
679 if (!objs || !objs->GetString().Length()) {
687 //______________________________________________________________________________
688 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
690 // Check input data type.
691 is_collection = kFALSE;
695 Error("CheckDataType", "No connection to grid");
698 is_collection = IsCollection(lfn);
699 TString msg = "\n##### file: ";
702 msg += " type: raw_collection;";
703 // special treatment for collections
705 // check for tag files in the collection
706 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
708 msg += " using_tags: No (unknown)";
709 Info("CheckDataType", msg.Data());
712 const char* typeStr = res->GetKey(0, "origLFN");
713 if (!typeStr || !strlen(typeStr)) {
714 msg += " using_tags: No (unknown)";
715 Info("CheckDataType", msg.Data());
718 TString file = typeStr;
719 use_tags = file.Contains(".tag");
720 if (use_tags) msg += " using_tags: Yes";
721 else msg += " using_tags: No";
722 Info("CheckDataType", msg.Data());
727 is_xml = slfn.Contains(".xml");
729 // Open xml collection and check if there are tag files inside
730 msg += " type: xml_collection;";
731 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
733 msg += " using_tags: No (unknown)";
734 Info("CheckDataType", msg.Data());
737 TMap *map = coll->Next();
739 msg += " using_tags: No (unknown)";
740 Info("CheckDataType", msg.Data());
743 map = (TMap*)map->GetValue("");
745 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
746 use_tags = file.Contains(".tag");
748 if (use_tags) msg += " using_tags: Yes";
749 else msg += " using_tags: No";
750 Info("CheckDataType", msg.Data());
753 use_tags = slfn.Contains(".tag");
754 if (slfn.Contains(".root")) msg += " type: root file;";
755 else msg += " type: unhnown file;";
756 if (use_tags) msg += " using_tags: Yes";
757 else msg += " using_tags: No";
758 Info("CheckDataType", msg.Data());
761 //______________________________________________________________________________
762 void AliAnalysisAlien::EnablePackage(const char *package)
764 // Enables a par file supposed to exist in the current directory.
765 TString pkg(package);
766 pkg.ReplaceAll(".par", "");
768 if (gSystem->AccessPathName(pkg)) {
769 Error("EnablePackage", "Package %s not found", pkg.Data());
772 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
773 Info("EnablePackage", "AliEn plugin will use .par packages");
774 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
776 fPackages = new TObjArray();
777 fPackages->SetOwner();
779 fPackages->Add(new TObjString(pkg));
782 //______________________________________________________________________________
783 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
785 // Returns true if file is a collection. Functionality duplicated from
786 // TAlien::Type() because we don't want to directly depend on TAlien.
788 Error("IsCollection", "No connection to grid");
791 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
792 if (!res) return kFALSE;
793 const char* typeStr = res->GetKey(0, "type");
794 if (!typeStr || !strlen(typeStr)) return kFALSE;
795 if (!strcmp(typeStr, "collection")) return kTRUE;
800 //______________________________________________________________________________
801 void AliAnalysisAlien::SetDefaults()
803 // Set default values for everything. What cannot be filled will be left empty.
804 if (fGridJDL) delete fGridJDL;
805 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
808 fSplitMaxInputFileNumber = 100;
810 fMasterResubmitThreshold = 0;
813 fExecutable = "analysis.sh";
815 fAnalysisMacro = "myAnalysis.C";
816 fAnalysisSource = "";
817 fAdditionalLibs = "";
821 fAliROOTVersion = "";
822 fUser = ""; // Your alien user name
823 fGridWorkingDir = "";
824 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
825 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
826 fGridOutputDir = "output";
827 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
828 fOutputFiles = ""; // Like "AliAODs.root histos.root"
829 fInputFormat = "xml-single";
830 fJDLName = "analysis.jdl";
834 //______________________________________________________________________________
835 Bool_t AliAnalysisAlien::MergeOutputs()
837 // Merge analysis outputs existing in the AliEn space.
838 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
839 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
841 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
844 // Get the output path
845 TString output = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
846 if (!gGrid->Cd(output)) output = Form("/%s/%s", gGrid->GetHomeDirectory(), fGridOutputDir.Data());
847 if (!gGrid->Cd(output)) {
848 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
851 if (!fOutputFiles.Length()) {
852 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
855 TObjArray *list = fOutputFiles.Tokenize(" ");
860 Bool_t merged = kTRUE;
861 while((str=(TObjString*)next())) {
862 output_file = str->GetString();
863 Int_t index = output_file.Index("@");
864 if (index > 0) output_file.Remove(index);
865 if (fMergeExcludes.Length() &&
866 fMergeExcludes.Contains(output_file.Data())) continue;
867 command = Form("find %s/ *%s", output.Data(), output_file.Data());
868 printf("command: %s\n", command.Data());
869 TGridResult *res = gGrid->Command(command);
874 while ((map=(TMap*)nextmap())) {
875 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
876 if (!objs || !objs->GetString().Length()) {
881 fm = new TFileMerger(kFALSE);
882 fm->SetFastMethod(kTRUE);
883 fm->OutputFile(output_file);
885 fm->AddFile(objs->GetString());
887 if (!fm || !fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
888 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
894 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
897 Info("MergeOutputs", "\n##### Merged %d output files <%s>", fm->GetMergeList()->GetSize(), output_file.Data());
903 Error("MergeOutputs", "Terminate() will NOT be executed");
908 //______________________________________________________________________________
909 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
911 // Use the output files connected to output containers from the analysis manager
912 // rather than the files defined by SetOutputFiles
913 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
914 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
916 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
919 //______________________________________________________________________________
920 void AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
922 // Start remote grid analysis.
924 if (TestBit(AliAnalysisGrid::kOffline)) {
925 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
926 \n there nor any job run. You can revise the JDL and analysis \
927 \n macro then run the same in \"submit\" mode.");
928 } else if (TestBit(AliAnalysisGrid::kTest)) {
929 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
931 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
932 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
933 \n space and job submitted.");
934 } else if (TestBit(AliAnalysisGrid::kMerge)) {
935 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
938 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
942 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
945 if (!CheckInputData()) {
946 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
949 CreateDataset(fDataPattern);
950 // Check if output files have to be taken from the analysis manager
951 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
952 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
953 if (!mgr || !mgr->IsInitialized()) {
954 Error("StartAnalysis", "You need an initialized analysis manager for this");
958 TIter next(mgr->GetOutputs());
959 AliAnalysisDataContainer *output;
960 while ((output=(AliAnalysisDataContainer*)next())) {
961 const char *filename = output->GetFileName();
962 if (!(strcmp(filename, "default"))) {
963 if (!mgr->GetOutputEventHandler()) continue;
964 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
966 if (fOutputFiles.Length()) fOutputFiles += " ";
967 fOutputFiles += filename;
971 WriteAnalysisMacro();
973 WriteValidationScript();
974 if (!CreateJDL()) return;
975 if (TestBit(AliAnalysisGrid::kOffline)) return;
976 if (TestBit(AliAnalysisGrid::kTest)) {
977 // Locally testing the analysis
978 Info("StartAnalysis", "\n_______________________________________________________________________ \
979 \n Running analysis script in a daughter shell as on a worker node \
980 \n_______________________________________________________________________");
981 TObjArray *list = fOutputFiles.Tokenize(" ");
985 while((str=(TObjString*)next())) {
986 output_file = str->GetString();
987 Int_t index = output_file.Index("@");
988 if (index > 0) output_file.Remove(index);
989 gSystem->Exec(Form("rm %s", output_file.Data()));
992 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
993 gSystem->Exec("bash validate.sh");
994 // gSystem->Exec("cat stdout");
999 TGridResult *res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1002 const char *cjobId = res->GetKey(0,"jobId");
1004 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1007 Info("StartAnalysis", "\n_______________________________________________________________________ \
1008 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1009 \n_______________________________________________________________________",
1010 fJDLName.Data(), cjobId);
1015 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1016 \n You may exit at any time and terminate the job later using the option <terminate> \
1017 \n ##################################################################################", jobID.Data());
1019 gSystem->Exec("aliensh");
1022 //______________________________________________________________________________
1023 void AliAnalysisAlien::WriteAnalysisFile()
1025 // Write current analysis manager into the file analysis.root
1026 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1027 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1028 if (!mgr || !mgr->IsInitialized()) {
1029 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1032 // Check analysis type
1034 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1035 handler = (TObject*)mgr->GetInputEventHandler();
1037 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1038 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1040 TDirectory *cdir = gDirectory;
1041 TFile *file = TFile::Open("analysis.root", "RECREATE");
1046 if (cdir) cdir->cd();
1047 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1049 Bool_t copy = kTRUE;
1050 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1053 TString workdir = gGrid->GetHomeDirectory();
1054 workdir += fGridWorkingDir;
1055 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1056 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1057 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1061 //______________________________________________________________________________
1062 void AliAnalysisAlien::WriteAnalysisMacro()
1064 // Write the analysis macro that will steer the analysis in grid mode.
1065 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1067 out.open(fAnalysisMacro.Data(), ios::out);
1069 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1072 TString func = fAnalysisMacro;
1073 TString type = "ESD";
1074 TString comment = "// Analysis using ";
1075 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1076 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1080 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1081 else comment += " data";
1082 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1083 func.ReplaceAll(".C", "");
1084 out << "void " << func.Data() << "()" << endl;
1086 out << comment.Data() << endl;
1087 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1088 out << "// load base root libraries" << endl;
1089 out << " gSystem->Load(\"libTree\");" << endl;
1090 out << " gSystem->Load(\"libGeom\");" << endl;
1091 out << " gSystem->Load(\"libVMC\");" << endl;
1092 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1094 out << "// Load analysis framework libraries" << endl;
1095 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1096 out << " gSystem->Load(\"libESD\");" << endl;
1097 out << " gSystem->Load(\"libAOD\");" << endl;
1098 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1099 out << " gSystem->Load(\"libANALYSISalice\");" << endl << endl;
1100 out << "// include path (remove if using par files)" << endl;
1101 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl << endl;
1103 out << "// Compile all par packages" << endl;
1104 TIter next(fPackages);
1106 while ((obj=next()))
1107 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1109 if (fAdditionalLibs.Length()) {
1110 out << "// Add aditional AliRoot libraries" << endl;
1111 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1114 while((str=(TObjString*)next())) {
1115 if (str->GetString().Contains(".so"))
1116 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1118 if (list) delete list;
1121 out << "// analysis source to be compiled at runtime (if any)" << endl;
1122 if (fAnalysisSource.Length()) {
1123 TObjArray *list = fAnalysisSource.Tokenize(" ");
1126 while((str=(TObjString*)next())) {
1127 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1129 if (list) delete list;
1132 out << "// connect to AliEn and make the chain" << endl;
1133 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1134 if (IsUsingTags()) {
1135 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1137 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1139 out << "// read the analysis manager from file" << endl;
1140 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1141 out << " if (!file) return;" << endl;
1142 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1143 out << " AliAnalysisManager *mgr = 0;" << endl;
1144 out << " TKey *key;" << endl;
1145 out << " while ((key=(TKey*)nextkey())) {" << endl;
1146 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1147 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1148 out << " };" << endl;
1149 out << " if (!mgr) {" << endl;
1150 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1151 out << " return;" << endl;
1152 out << " }" << endl << endl;
1153 out << " mgr->PrintStatus();" << endl;
1154 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1155 out << "}" << endl << endl;
1156 if (IsUsingTags()) {
1157 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1159 out << "// Create a chain using tags from the xml file." << endl;
1160 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1161 out << " if (!coll) {" << endl;
1162 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1163 out << " return NULL;" << endl;
1164 out << " }" << endl;
1165 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1166 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1167 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1168 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1169 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1170 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1171 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1172 out << " // Check if the cuts configuration file was provided" << endl;
1173 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1174 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1175 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1176 out << " }" << endl;
1177 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1178 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1179 out << " chain->ls();" << endl;
1180 out << " return chain;" << endl;
1182 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1183 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1184 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1185 msg += " AliLHCTagCuts *lhcCuts,\n";
1186 msg += " AliDetectorTagCuts *detCuts,\n";
1187 msg += " AliEventTagCuts *evCuts)";
1188 Info("WriteAnalysisMacro", msg.Data());
1191 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1193 out << "// Create a chain using url's from xml file" << endl;
1194 out << " TString treename = type;" << endl;
1195 out << " treename.ToLower();" << endl;
1196 out << " treename += \"Tree\";" << endl;
1197 out << " printf(\"***************************************\\n\");" << endl;
1198 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1199 out << " printf(\"***************************************\\n\");" << endl;
1200 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1201 out << " if (!coll) {" << endl;
1202 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1203 out << " return NULL;" << endl;
1204 out << " }" << endl;
1205 out << " TChain *chain = new TChain(treename);" << endl;
1206 out << " coll->Reset();" << endl;
1207 out << " while (coll->Next()) chain->Add(coll->GetTURL(\"\"));" << endl;
1208 out << " if (!chain->GetNtrees()) {" << endl;
1209 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1210 out << " return NULL;" << endl;
1211 out << " }" << endl;
1212 out << " return chain;" << endl;
1216 out << "Bool_t SetupPar(const char *package) {" << endl;
1217 out << "// Compile the package and set it up." << endl;
1218 out << " TString pkgdir = package;" << endl;
1219 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1220 out << " gSystem->Exec(Form(\"tar xvzf %s\", package));" << endl;
1221 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1222 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1223 out << " // Check for BUILD.sh and execute" << endl;
1224 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1225 out << " printf(\"*******************************\\n\");" << endl;
1226 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1227 out << " printf(\"*******************************\\n\");" << endl;
1228 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1229 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", package);" << endl;
1230 out << " gSystem->ChangeDirectory(cdir);" << endl;
1231 out << " return kFALSE;" << endl;
1232 out << " }" << endl;
1233 out << " } else {" << endl;
1234 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", package);" << endl;
1235 out << " gSystem->ChangeDirectory(cdir);" << endl;
1236 out << " return kFALSE;" << endl;
1237 out << " }" << endl;
1238 out << " // Check for SETUP.C and execute" << endl;
1239 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1240 out << " printf(\"*******************************\\n\");" << endl;
1241 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1242 out << " printf(\"*******************************\\n\");" << endl;
1243 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1244 out << " } else {" << endl;
1245 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", package);" << endl;
1246 out << " gSystem->ChangeDirectory(cdir);" << endl;
1247 out << " return kFALSE;" << endl;
1248 out << " }" << endl;
1249 out << " // Restore original workdir" << endl;
1250 out << " gSystem->ChangeDirectory(cdir);" << endl;
1251 out << " return kTRUE;" << endl;
1254 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1256 Bool_t copy = kTRUE;
1257 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1260 TString workdir = gGrid->GetHomeDirectory();
1261 workdir += fGridWorkingDir;
1262 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1263 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1264 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1265 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1266 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1268 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1269 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1273 //______________________________________________________________________________
1274 void AliAnalysisAlien::WriteExecutable()
1276 // Generate the alien executable script.
1277 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1279 out.open(fExecutable.Data(), ios::out);
1281 Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1284 out << "#!/bin/bash" << endl;
1285 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1286 out << "echo \"=========================================\"" << endl;
1287 out << "echo \"############## PATH : ##############\"" << endl;
1288 out << "echo $PATH" << endl;
1289 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1290 out << "echo $LD_LIBRARY_PATH" << endl;
1291 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1292 out << "echo $ROOTSYS" << endl;
1293 out << "echo \"############## which root : ##############\"" << endl;
1294 out << "which root" << endl;
1295 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1296 out << "echo $ALICE_ROOT" << endl;
1297 out << "echo \"############## which aliroot : ##############\"" << endl;
1298 out << "which aliroot" << endl;
1299 out << "echo \"=========================================\"" << endl << endl;
1300 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1301 out << "root -b -q ";
1302 out << fAnalysisMacro.Data() << endl << endl;
1303 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1305 Bool_t copy = kTRUE;
1306 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1309 TString workdir = gGrid->GetHomeDirectory();
1310 workdir += fGridWorkingDir;
1311 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1312 if (FileExists(executable)) gGrid->Rm(executable);
1313 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1314 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1318 //______________________________________________________________________________
1319 void AliAnalysisAlien::WriteValidationScript()
1321 // Generate the alien validation script.
1322 // Generate the validation script
1325 Error("WriteValidationScript", "Alien connection required");
1328 TString out_stream = "";
1329 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1330 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1332 out.open("validate.sh", ios::out);
1333 out << "#!/bin/bash" << endl;
1334 out << "##################################################" << endl;
1335 out << "validateout=`dirname $0`" << endl;
1336 out << "validatetime=`date`" << endl;
1337 out << "validated=\"0\";" << endl;
1338 out << "error=0" << endl;
1339 out << "if [ -z $validateout ]" << endl;
1340 out << "then" << endl;
1341 out << " validateout=\".\"" << endl;
1342 out << "fi" << endl << endl;
1343 out << "cd $validateout;" << endl;
1344 out << "validateworkdir=`pwd`;" << endl << endl;
1345 out << "echo \"*******************************************************\"" << out_stream << endl;
1346 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1348 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1349 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1350 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1351 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1352 out << "ls -la ./" << out_stream << endl;
1353 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1354 out << "##################################################" << endl;
1355 TObjArray *arr = fOutputFiles.Tokenize(" ");
1357 TString output_file;
1358 while ((os=(TObjString*)next1())) {
1359 output_file = os->GetString();
1360 Int_t index = output_file.Index("@");
1361 if (index > 0) output_file.Remove(index);
1362 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1363 out << " error=1" << endl;
1364 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
1365 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
1366 out << "fi" << endl;
1369 out << "if [ $error = 0 ] ; then" << endl;
1370 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
1371 out << "fi" << endl;
1373 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1374 out << "echo \"*******************************************************\"" << out_stream << endl;
1375 out << "cd -" << endl;
1376 out << "exit $error" << endl;
1378 Bool_t copy = kTRUE;
1379 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1382 TString workdir = gGrid->GetHomeDirectory();
1383 workdir += fGridWorkingDir;
1384 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
1385 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
1386 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));