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 "AliAnalysisAlien.h"
37 ClassImp(AliAnalysisAlien)
39 //______________________________________________________________________________
40 AliAnalysisAlien::AliAnalysisAlien()
45 fSplitMaxInputFileNumber(0),
47 fMasterResubmitThreshold(0),
75 //______________________________________________________________________________
76 AliAnalysisAlien::AliAnalysisAlien(const char *name)
77 :AliAnalysisGrid(name),
81 fSplitMaxInputFileNumber(0),
83 fMasterResubmitThreshold(0),
111 //______________________________________________________________________________
112 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
113 :AliAnalysisGrid(other),
115 fPrice(other.fPrice),
117 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
118 fMaxInitFailed(other.fMaxInitFailed),
119 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
120 fRunNumbers(other.fRunNumbers),
121 fExecutable(other.fExecutable),
122 fArguments(other.fArguments),
123 fAnalysisMacro(other.fAnalysisMacro),
124 fAnalysisSource(other.fAnalysisSource),
125 fAdditionalLibs(other.fAdditionalLibs),
126 fSplitMode(other.fSplitMode),
127 fAPIVersion(other.fAPIVersion),
128 fROOTVersion(other.fROOTVersion),
129 fAliROOTVersion(other.fAliROOTVersion),
131 fGridWorkingDir(other.fGridWorkingDir),
132 fGridDataDir(other.fGridDataDir),
133 fDataPattern(other.fDataPattern),
134 fGridOutputDir(other.fGridOutputDir),
135 fOutputArchive(other.fOutputArchive),
136 fOutputFiles(other.fOutputFiles),
137 fInputFormat(other.fInputFormat),
138 fDatasetName(other.fDatasetName),
139 fJDLName(other.fJDLName),
144 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
145 if (other.fInputFiles) {
146 fInputFiles = new TObjArray();
147 TIter next(other.fInputFiles);
149 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
150 fInputFiles->SetOwner();
152 if (other.fPackages) {
153 fPackages = new TObjArray();
154 TIter next(other.fPackages);
156 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
157 fPackages->SetOwner();
161 //______________________________________________________________________________
162 AliAnalysisAlien::~AliAnalysisAlien()
165 if (fGridJDL) delete fGridJDL;
166 if (fInputFiles) delete fInputFiles;
167 if (fPackages) delete fPackages;
170 //______________________________________________________________________________
171 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
174 if (this != &other) {
175 AliAnalysisGrid::operator=(other);
176 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
177 fPrice = other.fPrice;
179 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
180 fMaxInitFailed = other.fMaxInitFailed;
181 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
182 fRunNumbers = other.fRunNumbers;
183 fExecutable = other.fExecutable;
184 fArguments = other.fArguments;
185 fAnalysisMacro = other.fAnalysisMacro;
186 fAnalysisSource = other.fAnalysisSource;
187 fAdditionalLibs = other.fAdditionalLibs;
188 fSplitMode = other.fSplitMode;
189 fAPIVersion = other.fAPIVersion;
190 fROOTVersion = other.fROOTVersion;
191 fAliROOTVersion = other.fAliROOTVersion;
193 fGridWorkingDir = other.fGridWorkingDir;
194 fGridDataDir = other.fGridDataDir;
195 fDataPattern = other.fDataPattern;
196 fGridOutputDir = other.fGridOutputDir;
197 fOutputArchive = other.fOutputArchive;
198 fOutputFiles = other.fOutputFiles;
199 fInputFormat = other.fInputFormat;
200 fDatasetName = other.fDatasetName;
201 fJDLName = other.fJDLName;
202 if (other.fInputFiles) {
203 fInputFiles = new TObjArray();
204 TIter next(other.fInputFiles);
206 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
207 fInputFiles->SetOwner();
209 if (other.fPackages) {
210 fPackages = new TObjArray();
211 TIter next(other.fPackages);
213 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
214 fPackages->SetOwner();
220 //______________________________________________________________________________
221 void AliAnalysisAlien::AddRunNumber(Int_t run)
223 // Add a run number to the list of runs to be processed.
224 if (fRunNumbers.Length()) fRunNumbers += " ";
225 fRunNumbers += Form("%d", run);
228 //______________________________________________________________________________
229 void AliAnalysisAlien::AddDataFile(const char *lfn)
231 // Adds a data file to the input to be analysed. The file should be a valid LFN
232 // or point to an existing file in the alien workdir.
233 if (!fInputFiles) fInputFiles = new TObjArray();
234 fInputFiles->Add(new TObjString(lfn));
237 //______________________________________________________________________________
238 Bool_t AliAnalysisAlien::Connect()
240 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
241 if (gGrid && gGrid->IsConnected()) return kTRUE;
242 if (!gSystem->Getenv("alien_API_USER")) {
243 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
244 gSystem->Getenv("UID"));
248 Info("Connect", "Trying to connect to AliEn ...");
249 TGrid::Connect("alien://");
251 if (!gGrid || !gGrid->IsConnected()) {
252 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
255 fUser = gGrid->GetUser();
256 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
260 //______________________________________________________________________________
261 void AliAnalysisAlien::CdWork()
263 // Check validity of alien workspace. Create directory if possible.
265 Error("CdWork", "Alien connection required");
268 TString homedir = gGrid->GetHomeDirectory();
269 TString workdir = homedir + fGridWorkingDir;
270 if (!gGrid->Cd(workdir)) {
272 if (gGrid->Mkdir(workdir)) {
273 gGrid->Cd(fGridWorkingDir);
274 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
276 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
277 workdir.Data(), homedir.Data());
278 fGridWorkingDir = "";
283 //______________________________________________________________________________
284 Bool_t AliAnalysisAlien::CheckInputData()
286 // Check validity of input data. If necessary, create xml files.
287 if (!fInputFiles && !fRunNumbers.Length()) {
288 Error("CheckInputData", "You have to specify either a set of run numbers or some existing grid files. Use AddRunNumber()/AddDataFile().");
291 // Process declared files
292 Bool_t is_collection = kFALSE;
293 Bool_t is_xml = kFALSE;
294 Bool_t use_tags = kFALSE;
295 Bool_t checked = kFALSE;
298 TString workdir = gGrid->GetHomeDirectory();
299 workdir += fGridWorkingDir;
302 TIter next(fInputFiles);
303 while ((objstr=(TObjString*)next())) {
306 file += objstr->GetString();
307 // Store full lfn path
308 if (FileExists(file)) objstr->SetString(file);
310 file = objstr->GetName();
311 if (!FileExists(objstr->GetName())) {
312 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
313 objstr->GetName(), workdir.Data());
317 Bool_t iscoll, isxml, usetags;
318 CheckDataType(file, iscoll, isxml, usetags);
321 is_collection = iscoll;
324 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
326 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
327 Error("CheckInputData", "Some conflict was found in the types of inputs");
333 // Process requested run numbers
334 if (!fRunNumbers.Length()) return kTRUE;
335 // Check validity of alien data directory
336 if (!fGridDataDir.Length()) {
337 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
340 if (!gGrid->Cd(fGridDataDir)) {
341 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
345 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
349 if (checked && !is_xml) {
350 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
353 // Check validity of run number(s)
359 use_tags = fDataPattern.Contains("tag");
360 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
362 if (use_tags != fDataPattern.Contains("tag")) {
363 Error("CheckInputData", "Cannot mix input files using/not using tags");
366 if (fRunNumbers.Length()) {
367 arr = fRunNumbers.Tokenize(" ");
369 while ((os=(TObjString*)next())) {
370 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
371 if (!gGrid->Cd(path)) {
372 Error("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
375 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
376 TString msg = "\n##### file: ";
378 msg += " type: xml_collection;";
379 if (use_tags) msg += " using_tags: Yes";
380 else msg += " using_tags: No";
381 Info("CheckDataType", msg.Data());
389 //______________________________________________________________________________
390 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
392 // Create dataset for the grid data directory + run number.
393 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
395 Error("CreateDataset", "Cannot create dataset with no grid connection");
401 TString workdir = gGrid->GetHomeDirectory();
402 workdir += fGridWorkingDir;
404 // Compose the 'find' command arguments
406 TString options = "-x collection ";
407 if (TestBit(AliAnalysisGrid::kTest)) options += "-l 100 ";
408 TString conditions = "";
412 if (!fRunNumbers.Length()) return kTRUE;
414 TObjArray *arr = fRunNumbers.Tokenize(" ");
417 while ((os=(TObjString*)next())) {
418 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
419 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
420 else file = Form("%s.xml", os->GetString().Data());
421 if (FileExists(file) && !TestBit(AliAnalysisGrid::kTest)) {
422 Info("CreateDataset", "\n##### Removing previous dataset %s", file.Data());
429 // conditions = Form(" > %s", file.Data());
430 command += conditions;
431 TGridResult *res = gGrid->Command(command);
433 // Write standard output to file
434 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
435 if (TestBit(AliAnalysisGrid::kTest)) break;
436 // Copy xml file to alien space
437 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
438 if (!FileExists(file)) {
439 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
448 //______________________________________________________________________________
449 Bool_t AliAnalysisAlien::CreateJDL()
451 // Generate a JDL file according to current settings. The name of the file is
452 // specified by fJDLName.
453 Bool_t error = kFALSE;
456 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
457 Bool_t generate = kTRUE;
458 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
460 Error("CreateJDL", "Alien connection required");
463 // Check validity of alien workspace
465 TString workdir = gGrid->GetHomeDirectory();
466 workdir += fGridWorkingDir;
470 Error("CreateJDL()", "Define some input files for your analysis.");
473 // Compose list of input files
474 // Check if output files were defined
475 if (!fOutputFiles.Length()) {
476 Error("CreateJDL", "You must define at least one output file");
479 // Check if an output directory was defined and valid
480 if (!fGridOutputDir.Length()) {
481 Error("CreateJDL", "You must define AliEn output directory");
484 if (!gGrid->Cd(fGridOutputDir)) {
485 if (gGrid->Mkdir(fGridOutputDir)) {
486 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
488 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
494 // Exit if any error up to now
495 if (error) return kFALSE;
497 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
498 fGridJDL->SetExecutable(fExecutable);
499 // fGridJDL->SetTTL((UInt_t)fTTL);
500 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
501 if (fMaxInitFailed > 0)
502 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
503 if (fSplitMaxInputFileNumber > 0)
504 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
505 if (fSplitMode.Length())
506 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
507 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
508 if (fAliROOTVersion.Length())
509 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
510 if (fROOTVersion.Length())
511 fGridJDL->AddToPackages("ROOT", fROOTVersion);
512 if (fAPIVersion.Length())
513 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
514 fGridJDL->SetInputDataListFormat(fInputFormat);
515 fGridJDL->SetInputDataList("wn.xml");
517 TIter next(fInputFiles);
518 while ((os=(TObjString*)next()))
519 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
521 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
522 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
523 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
524 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
525 if (fAdditionalLibs.Length()) {
526 arr = fAdditionalLibs.Tokenize(" ");
528 while ((os=(TObjString*)next())) {
529 if (os->GetString().Contains(".so")) continue;
530 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
535 TIter next(fPackages);
538 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
540 if (fOutputArchive.Length()) {
541 arr = fOutputArchive.Tokenize(" ");
543 while ((os=(TObjString*)next()))
544 fGridJDL->AddToOutputArchive(os->GetString().Data());
547 fGridJDL->SetOutputDirectory(Form("%s/%s/#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data()));
548 arr = fOutputFiles.Tokenize(" ");
550 while ((os=(TObjString*)next())) fGridJDL->AddToOutputSandbox(os->GetString());
552 // fGridJDL->SetPrice((UInt_t)fPrice);
553 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
554 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
555 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
556 // Generate the JDL as a string
557 TString sjdl = fGridJDL->Generate();
559 index = sjdl.Index("Executable");
560 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
561 index = sjdl.Index("Split ");
562 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
563 index = sjdl.Index("SplitMaxInputFileNumber");
564 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
565 index = sjdl.Index("InputDataCollection");
566 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
567 index = sjdl.Index("InputFile");
568 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
569 index = sjdl.Index("InputDataList ");
570 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
571 index = sjdl.Index("InputDataListFormat");
572 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
573 index = sjdl.Index("Price");
574 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
575 index = sjdl.Index("Requirements");
576 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
577 index = sjdl.Index("Packages");
578 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
579 index = sjdl.Index("User");
580 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
581 index = sjdl.Index("TTL");
582 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
583 index = sjdl.Index("OutputFile");
584 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
585 index = sjdl.Index("OutputDir");
586 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
587 index = sjdl.Index("OutputArchive");
588 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
589 index = sjdl.Index("MaxInitFailed");
590 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
591 index = sjdl.Index("MasterResubmitThreshold");
592 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
593 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
594 index = sjdl.Index("Validationcommand");
595 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
596 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
597 sjdl.ReplaceAll("(member", "\n (member");
598 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
599 sjdl.ReplaceAll("{", "{\n ");
600 sjdl.ReplaceAll("};", "\n};");
601 sjdl.ReplaceAll("{\n \n", "{\n");
602 sjdl.ReplaceAll("\n\n", "\n");
603 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
604 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
605 sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
606 index = sjdl.Index("JDLVariables");
607 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
610 out.open(fJDLName.Data(), ios::out);
612 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
617 // Copy jdl to grid workspace
619 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
621 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn working space", fJDLName.Data());
622 if (FileExists(fJDLName)) gGrid->Rm(fJDLName);
623 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s/%s", workdir.Data(), fJDLName.Data()));
624 if (fAdditionalLibs.Length()) {
625 arr = fAdditionalLibs.Tokenize(" ");
628 while ((os=(TObjString*)next())) {
629 if (os->GetString().Contains(".so")) continue;
630 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
631 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
632 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
637 TIter next(fPackages);
639 while ((obj=next())) {
640 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
641 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
648 //______________________________________________________________________________
649 Bool_t AliAnalysisAlien::FileExists(const char *lfn) const
651 // Returns true if file exists.
653 Error("FileExists", "No connection to grid");
656 TGridResult *res = gGrid->Ls(lfn);
657 if (!res) return kFALSE;
658 TMap *map = dynamic_cast<TMap*>(res->At(0));
663 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
664 if (!objs || !objs->GetString().Length()) {
672 //______________________________________________________________________________
673 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
675 // Check input data type.
676 is_collection = kFALSE;
680 Error("CheckDataType", "No connection to grid");
683 is_collection = IsCollection(lfn);
684 TString msg = "\n##### file: ";
687 msg += " type: raw_collection;";
688 // special treatment for collections
690 // check for tag files in the collection
691 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
693 msg += " using_tags: No (unknown)";
694 Info("CheckDataType", msg.Data());
697 const char* typeStr = res->GetKey(0, "origLFN");
698 if (!typeStr || !strlen(typeStr)) {
699 msg += " using_tags: No (unknown)";
700 Info("CheckDataType", msg.Data());
703 TString file = typeStr;
704 use_tags = file.Contains(".tag");
705 if (use_tags) msg += " using_tags: Yes";
706 else msg += " using_tags: No";
707 Info("CheckDataType", msg.Data());
712 is_xml = slfn.Contains(".xml");
714 // Open xml collection and check if there are tag files inside
715 msg += " type: xml_collection;";
716 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
718 msg += " using_tags: No (unknown)";
719 Info("CheckDataType", msg.Data());
722 TMap *map = coll->Next();
724 msg += " using_tags: No (unknown)";
725 Info("CheckDataType", msg.Data());
728 map = (TMap*)map->GetValue("");
730 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
731 use_tags = file.Contains(".tag");
733 if (use_tags) msg += " using_tags: Yes";
734 else msg += " using_tags: No";
735 Info("CheckDataType", msg.Data());
738 use_tags = slfn.Contains(".tag");
739 if (slfn.Contains(".root")) msg += " type: root file;";
740 else msg += " type: unhnown file;";
741 if (use_tags) msg += " using_tags: Yes";
742 else msg += " using_tags: No";
743 Info("CheckDataType", msg.Data());
746 //______________________________________________________________________________
747 void AliAnalysisAlien::EnablePackage(const char *package)
749 // Enables a par file supposed to exist in the current directory.
750 TString pkg(package);
751 pkg.ReplaceAll(".par", "");
753 if (gSystem->AccessPathName(pkg)) {
754 Error("EnablePackage", "Package %s not found", pkg.Data());
757 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
758 Info("EnablePackage", "AliEn plugin will use .par packages");
759 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
761 fPackages = new TObjArray();
762 fPackages->SetOwner();
764 fPackages->Add(new TObjString(pkg));
767 //______________________________________________________________________________
768 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
770 // Returns true if file is a collection. Functionality duplicated from
771 // TAlien::Type() because we don't want to directly depend on TAlien.
773 Error("IsCollection", "No connection to grid");
776 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
777 if (!res) return kFALSE;
778 const char* typeStr = res->GetKey(0, "type");
779 if (!typeStr || !strlen(typeStr)) return kFALSE;
780 if (!strcmp(typeStr, "collection")) return kTRUE;
785 //______________________________________________________________________________
786 void AliAnalysisAlien::SetDefaults()
788 // Set default values for everything. What cannot be filled will be left empty.
789 if (fGridJDL) delete fGridJDL;
790 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
793 fSplitMaxInputFileNumber = 100;
795 fMasterResubmitThreshold = 0;
797 fExecutable = "analysis.sh";
799 fAnalysisMacro = "myAnalysis.C";
800 fAnalysisSource = "";
801 fAdditionalLibs = "";
805 fAliROOTVersion = "";
806 fUser = ""; // Your alien user name
807 fGridWorkingDir = "";
808 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
809 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
810 fGridOutputDir = "output";
811 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
812 fOutputFiles = ""; // Like "AliAODs.root histos.root"
813 fInputFormat = "xml-single";
814 fJDLName = "analysis.jdl";
817 //______________________________________________________________________________
818 Bool_t AliAnalysisAlien::MergeOutputs()
820 // Merge analysis outputs existing in the AliEn space.
821 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
822 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
824 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
827 // Get the output path
828 TString output = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
829 if (!gGrid->Cd(output)) output = Form("/%s/%s", gGrid->GetHomeDirectory(), fGridOutputDir.Data());
830 if (!gGrid->Cd(output)) {
831 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
834 if (!fOutputFiles.Length()) {
835 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
838 TObjArray *list = fOutputFiles.Tokenize(" ");
843 Bool_t merged = kTRUE;
844 while((str=(TObjString*)next())) {
845 output_file = str->GetString();
846 Int_t index = output_file.Index("@");
847 if (index > 0) output_file.Remove(index);
848 command = Form("find %s/ *%s", output.Data(), output_file.Data());
849 printf("command: %s\n", command.Data());
850 TGridResult *res = gGrid->Command(command);
855 while ((map=(TMap*)nextmap())) {
856 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
857 if (!objs || !objs->GetString().Length()) {
862 fm = new TFileMerger(kFALSE);
863 fm->SetFastMethod(kTRUE);
864 fm->OutputFile(output_file);
866 fm->AddFile(objs->GetString());
868 if (!fm || !fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
869 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
875 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
878 Info("MergeOutputs", "\n##### Merged %d output files <%s>", fm->GetMergeList()->GetSize(), output_file.Data());
884 Error("MergeOutputs", "Terminate() will NOT be executed");
889 //______________________________________________________________________________
890 void AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
892 // Start remote grid analysis.
894 if (TestBit(AliAnalysisGrid::kOffline)) {
895 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
896 \n there nor any job run. You can revise the JDL and analysis \
897 \n macro then run the same in \"submit\" mode.");
898 } else if (TestBit(AliAnalysisGrid::kTest)) {
899 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
901 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
902 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
903 \n space and job submitted.");
904 } else if (TestBit(AliAnalysisGrid::kMerge)) {
905 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
908 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
912 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
915 if (!CheckInputData()) {
916 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
919 CreateDataset(fDataPattern);
921 WriteAnalysisMacro();
923 WriteValidationScript();
924 if (!CreateJDL()) return;
925 if (TestBit(AliAnalysisGrid::kOffline)) return;
926 if (TestBit(AliAnalysisGrid::kTest)) {
927 // Locally testing the analysis
928 Info("StartAnalysis", "\n_______________________________________________________________________ \
929 \n Running analysis script in a daughter shell as on a worker node \
930 \n_______________________________________________________________________");
931 TObjArray *list = fOutputFiles.Tokenize(" ");
935 while((str=(TObjString*)next())) {
936 output_file = str->GetString();
937 Int_t index = output_file.Index("@");
938 if (index > 0) output_file.Remove(index);
939 gSystem->Exec(Form("rm %s", output_file.Data()));
942 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
943 gSystem->Exec("bash validate.sh");
944 // gSystem->Exec("cat stdout");
949 TGridResult *res = gGrid->Command(Form("submit %s", fJDLName.Data()));
952 const char *cjobId = res->GetKey(0,"jobId");
954 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
957 Info("StartAnalysis", "\n_______________________________________________________________________ \
958 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
959 \n_______________________________________________________________________",
960 fJDLName.Data(), cjobId);
965 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
966 \n You may exit at any time and terminate the job later using the option <terminate> \
967 \n ##################################################################################", jobID.Data());
971 //______________________________________________________________________________
972 void AliAnalysisAlien::WriteAnalysisFile()
974 // Write current analysis manager into the file analysis.root
975 if (!TestBit(AliAnalysisGrid::kSubmit)) {
976 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
977 if (!mgr || !mgr->IsInitialized()) {
978 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
981 // Check analysis type
983 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
984 handler = (TObject*)mgr->GetInputEventHandler();
986 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
987 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
989 TDirectory *cdir = gDirectory;
990 TFile *file = TFile::Open("analysis.root", "RECREATE");
995 if (cdir) cdir->cd();
996 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
999 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1002 TString workdir = gGrid->GetHomeDirectory();
1003 workdir += fGridWorkingDir;
1004 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1005 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1006 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1010 //______________________________________________________________________________
1011 void AliAnalysisAlien::WriteAnalysisMacro()
1013 // Write the analysis macro that will steer the analysis in grid mode.
1014 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1016 out.open(fAnalysisMacro.Data(), ios::out);
1018 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1021 TString func = fAnalysisMacro;
1022 TString type = "ESD";
1023 TString comment = "// Analysis using ";
1024 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1025 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1029 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1030 else comment += " data";
1031 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1032 func.ReplaceAll(".C", "");
1033 out << "void " << func.Data() << "()" << endl;
1035 out << comment.Data() << endl;
1036 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1037 out << "// load base root libraries" << endl;
1038 out << " gSystem->Load(\"libTree\");" << endl;
1039 out << " gSystem->Load(\"libGeom\");" << endl;
1040 out << " gSystem->Load(\"libVMC\");" << endl;
1041 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1043 out << "// Load analysis framework libraries" << endl;
1044 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1045 out << " gSystem->Load(\"libESD\");" << endl;
1046 out << " gSystem->Load(\"libAOD\");" << endl;
1047 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1048 out << " gSystem->Load(\"libANALYSISalice\");" << endl << endl;
1049 out << "// include path (remove if using par files)" << endl;
1050 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl << endl;
1052 out << "// Compile all par packages" << endl;
1053 TIter next(fPackages);
1055 while ((obj=next()))
1056 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1058 if (fAdditionalLibs.Length()) {
1059 out << "// Add aditional AliRoot libraries" << endl;
1060 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1063 while((str=(TObjString*)next())) {
1064 if (str->GetString().Contains(".so"))
1065 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1067 if (list) delete list;
1070 out << "// analysis source to be compiled at runtime (if any)" << endl;
1071 if (fAnalysisSource.Length()) {
1072 TObjArray *list = fAnalysisSource.Tokenize(" ");
1075 while((str=(TObjString*)next())) {
1076 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1078 if (list) delete list;
1081 out << "// connect to AliEn and make the chain" << endl;
1082 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1083 if (IsUsingTags()) {
1084 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1086 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1088 out << "// read the analysis manager from file" << endl;
1089 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1090 out << " if (!file) return;" << endl;
1091 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1092 out << " AliAnalysisManager *mgr = 0;" << endl;
1093 out << " TKey *key;" << endl;
1094 out << " while ((key=(TKey*)nextkey())) {" << endl;
1095 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1096 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1097 out << " };" << endl;
1098 out << " if (!mgr) {" << endl;
1099 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1100 out << " return;" << endl;
1101 out << " }" << endl << endl;
1102 out << " mgr->PrintStatus();" << endl;
1103 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1104 out << "}" << endl << endl;
1105 if (IsUsingTags()) {
1106 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1108 out << "// Create a chain using tags from the xml file." << endl;
1109 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1110 out << " if (!coll) {" << endl;
1111 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1112 out << " return NULL;" << endl;
1113 out << " }" << endl;
1114 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1115 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1116 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1117 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1118 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1119 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1120 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1121 out << " // Check if the cuts configuration file was provided" << endl;
1122 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1123 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1124 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1125 out << " }" << endl;
1126 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1127 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1128 out << " chain->ls();" << endl;
1129 out << " return chain;" << endl;
1131 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1132 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1133 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1134 msg += " AliLHCTagCuts *lhcCuts,\n";
1135 msg += " AliDetectorTagCuts *detCuts,\n";
1136 msg += " AliEventTagCuts *evCuts)";
1137 Info("WriteAnalysisMacro", msg.Data());
1140 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1142 out << "// Create a chain using url's from xml file" << endl;
1143 out << " TString treename = type;" << endl;
1144 out << " treename.ToLower();" << endl;
1145 out << " treename += \"Tree\";" << endl;
1146 out << " printf(\"***************************************\");" << endl;
1147 out << " printf(\" Getting chain of trees %s\\n\", treename);" << endl;
1148 out << " printf(\"***************************************\");" << endl;
1149 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1150 out << " if (!coll) {" << endl;
1151 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1152 out << " return NULL;" << endl;
1153 out << " }" << endl;
1154 out << " TChain *chain = new TChain(treename);" << endl;
1155 out << " coll->Reset();" << endl;
1156 out << " while (coll->Next()) chain->Add(coll->GetTURL(\"\"));" << endl;
1157 out << " if (!chain->GetNtrees()) {" << endl;
1158 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1159 out << " return NULL;" << endl;
1160 out << " }" << endl;
1161 out << " return chain;" << endl;
1165 out << "Bool_t SetupPar(const char *package) {" << endl;
1166 out << "// Compile the package and set it up." << endl;
1167 out << " TString pkgdir = package;" << endl;
1168 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1169 out << " gSystem->Exec(Form(\"tar xvzf %s\", package));" << endl;
1170 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1171 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1172 out << " // Check for BUILD.sh and execute" << endl;
1173 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1174 out << " printf(\"*******************************\\n\");" << endl;
1175 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1176 out << " printf(\"*******************************\\n\");" << endl;
1177 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1178 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", package);" << endl;
1179 out << " gSystem->ChangeDirectory(cdir);" << endl;
1180 out << " return kFALSE;" << endl;
1181 out << " }" << endl;
1182 out << " } else {" << endl;
1183 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", package);" << endl;
1184 out << " gSystem->ChangeDirectory(cdir);" << endl;
1185 out << " return kFALSE;" << endl;
1186 out << " }" << endl;
1187 out << " // Check for SETUP.C and execute" << endl;
1188 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1189 out << " printf(\"*******************************\\n\");" << endl;
1190 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1191 out << " printf(\"*******************************\\n\");" << endl;
1192 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1193 out << " } else {" << endl;
1194 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", package);" << endl;
1195 out << " gSystem->ChangeDirectory(cdir);" << endl;
1196 out << " return kFALSE;" << endl;
1197 out << " }" << endl;
1198 out << " // Restore original workdir" << endl;
1199 out << " gSystem->ChangeDirectory(cdir);" << endl;
1200 out << " return kTRUE;" << endl;
1203 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1205 Bool_t copy = kTRUE;
1206 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1209 TString workdir = gGrid->GetHomeDirectory();
1210 workdir += fGridWorkingDir;
1211 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1212 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1213 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1214 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1215 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1217 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1218 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1222 //______________________________________________________________________________
1223 void AliAnalysisAlien::WriteExecutable()
1225 // Generate the alien executable script.
1226 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1228 out.open(fExecutable.Data(), ios::out);
1230 Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1233 out << "#!/bin/bash" << endl;
1234 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1235 out << "echo \"=========================================\"" << endl;
1236 out << "echo \"############## PATH : ##############\"" << endl;
1237 out << "echo $PATH" << endl;
1238 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1239 out << "echo $LD_LIBRARY_PATH" << endl;
1240 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1241 out << "echo $ROOTSYS" << endl;
1242 out << "echo \"############## which root : ##############\"" << endl;
1243 out << "which root" << endl;
1244 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1245 out << "echo $ALICE_ROOT" << endl;
1246 out << "echo \"############## which aliroot : ##############\"" << endl;
1247 out << "which aliroot" << endl;
1248 out << "echo \"=========================================\"" << endl << endl;
1249 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1250 out << "root -b -q ";
1251 out << fAnalysisMacro.Data() << endl << endl;
1252 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1254 Bool_t copy = kTRUE;
1255 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1258 TString workdir = gGrid->GetHomeDirectory();
1259 workdir += fGridWorkingDir;
1260 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1261 if (FileExists(executable)) gGrid->Rm(executable);
1262 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1263 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1267 //______________________________________________________________________________
1268 void AliAnalysisAlien::WriteValidationScript()
1270 // Generate the alien validation script.
1271 // Generate the validation script
1274 Error("WriteValidationScript", "Alien connection required");
1277 TString out_stream = "";
1278 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1279 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1281 out.open("validate.sh", ios::out);
1282 out << "#!/bin/bash" << endl;
1283 out << "##################################################" << endl;
1284 out << "validateout=`dirname $0`" << endl;
1285 out << "validatetime=`date`" << endl;
1286 out << "validated=\"0\";" << endl;
1287 out << "error=0" << endl;
1288 out << "if [ -z $validateout ]" << endl;
1289 out << "then" << endl;
1290 out << " validateout=\".\"" << endl;
1291 out << "fi" << endl << endl;
1292 out << "cd $validateout;" << endl;
1293 out << "validateworkdir=`pwd`;" << endl << endl;
1294 out << "echo \"*******************************************************\"" << out_stream << endl;
1295 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1297 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1298 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1299 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1300 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1301 out << "ls -la ./" << out_stream << endl;
1302 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1303 out << "##################################################" << endl;
1304 TObjArray *arr = fOutputFiles.Tokenize(" ");
1306 TString output_file;
1307 while ((os=(TObjString*)next1())) {
1308 output_file = os->GetString();
1309 Int_t index = output_file.Index("@");
1310 if (index > 0) output_file.Remove(index);
1311 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1312 out << " error=1" << endl;
1313 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
1314 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
1315 out << "fi" << endl;
1318 out << "if [ $error = 0 ] ; then" << endl;
1319 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
1320 out << "fi" << endl;
1322 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1323 out << "echo \"*******************************************************\"" << out_stream << endl;
1324 out << "cd -" << endl;
1325 out << "exit $error" << endl;
1327 Bool_t copy = kTRUE;
1328 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1331 TString workdir = gGrid->GetHomeDirectory();
1332 workdir += fGridWorkingDir;
1333 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
1334 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
1335 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));