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),
81 //______________________________________________________________________________
82 AliAnalysisAlien::AliAnalysisAlien(const char *name)
83 :AliAnalysisGrid(name),
87 fSplitMaxInputFileNumber(0),
89 fMasterResubmitThreshold(0),
121 //______________________________________________________________________________
122 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
123 :AliAnalysisGrid(other),
125 fPrice(other.fPrice),
127 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
128 fMaxInitFailed(other.fMaxInitFailed),
129 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
130 fNtestFiles(other.fNtestFiles),
131 fRunNumbers(other.fRunNumbers),
132 fExecutable(other.fExecutable),
133 fArguments(other.fArguments),
134 fAnalysisMacro(other.fAnalysisMacro),
135 fAnalysisSource(other.fAnalysisSource),
136 fAdditionalLibs(other.fAdditionalLibs),
137 fSplitMode(other.fSplitMode),
138 fAPIVersion(other.fAPIVersion),
139 fROOTVersion(other.fROOTVersion),
140 fAliROOTVersion(other.fAliROOTVersion),
142 fGridWorkingDir(other.fGridWorkingDir),
143 fGridDataDir(other.fGridDataDir),
144 fDataPattern(other.fDataPattern),
145 fGridOutputDir(other.fGridOutputDir),
146 fOutputArchive(other.fOutputArchive),
147 fOutputFiles(other.fOutputFiles),
148 fInputFormat(other.fInputFormat),
149 fDatasetName(other.fDatasetName),
150 fJDLName(other.fJDLName),
151 fMergeExcludes(other.fMergeExcludes),
152 fIncludePath(other.fIncludePath),
153 fCloseSE(other.fCloseSE),
158 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
159 if (other.fInputFiles) {
160 fInputFiles = new TObjArray();
161 TIter next(other.fInputFiles);
163 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
164 fInputFiles->SetOwner();
166 if (other.fPackages) {
167 fPackages = new TObjArray();
168 TIter next(other.fPackages);
170 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
171 fPackages->SetOwner();
175 //______________________________________________________________________________
176 AliAnalysisAlien::~AliAnalysisAlien()
179 if (fGridJDL) delete fGridJDL;
180 if (fInputFiles) delete fInputFiles;
181 if (fPackages) delete fPackages;
184 //______________________________________________________________________________
185 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
188 if (this != &other) {
189 AliAnalysisGrid::operator=(other);
190 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
191 fPrice = other.fPrice;
193 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
194 fMaxInitFailed = other.fMaxInitFailed;
195 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
196 fNtestFiles = other.fNtestFiles;
197 fRunNumbers = other.fRunNumbers;
198 fExecutable = other.fExecutable;
199 fArguments = other.fArguments;
200 fAnalysisMacro = other.fAnalysisMacro;
201 fAnalysisSource = other.fAnalysisSource;
202 fAdditionalLibs = other.fAdditionalLibs;
203 fSplitMode = other.fSplitMode;
204 fAPIVersion = other.fAPIVersion;
205 fROOTVersion = other.fROOTVersion;
206 fAliROOTVersion = other.fAliROOTVersion;
208 fGridWorkingDir = other.fGridWorkingDir;
209 fGridDataDir = other.fGridDataDir;
210 fDataPattern = other.fDataPattern;
211 fGridOutputDir = other.fGridOutputDir;
212 fOutputArchive = other.fOutputArchive;
213 fOutputFiles = other.fOutputFiles;
214 fInputFormat = other.fInputFormat;
215 fDatasetName = other.fDatasetName;
216 fJDLName = other.fJDLName;
217 fMergeExcludes = other.fMergeExcludes;
218 fIncludePath = other.fIncludePath;
219 fCloseSE = other.fCloseSE;
220 if (other.fInputFiles) {
221 fInputFiles = new TObjArray();
222 TIter next(other.fInputFiles);
224 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
225 fInputFiles->SetOwner();
227 if (other.fPackages) {
228 fPackages = new TObjArray();
229 TIter next(other.fPackages);
231 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
232 fPackages->SetOwner();
238 //______________________________________________________________________________
239 void AliAnalysisAlien::AddIncludePath(const char *path)
241 // Add include path in the remote analysis macro.
243 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
244 else fIncludePath += Form("-I%s ", path);
247 //______________________________________________________________________________
248 void AliAnalysisAlien::AddRunNumber(Int_t run)
250 // Add a run number to the list of runs to be processed.
251 if (fRunNumbers.Length()) fRunNumbers += " ";
252 fRunNumbers += Form("%d", run);
255 //______________________________________________________________________________
256 void AliAnalysisAlien::AddDataFile(const char *lfn)
258 // Adds a data file to the input to be analysed. The file should be a valid LFN
259 // or point to an existing file in the alien workdir.
260 if (!fInputFiles) fInputFiles = new TObjArray();
261 fInputFiles->Add(new TObjString(lfn));
264 //______________________________________________________________________________
265 Bool_t AliAnalysisAlien::Connect()
267 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
268 if (gGrid && gGrid->IsConnected()) return kTRUE;
269 if (!gSystem->Getenv("alien_API_USER")) {
270 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
271 gSystem->Getenv("UID"));
275 Info("Connect", "Trying to connect to AliEn ...");
276 TGrid::Connect("alien://");
278 if (!gGrid || !gGrid->IsConnected()) {
279 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
282 fUser = gGrid->GetUser();
283 fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
284 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
288 //______________________________________________________________________________
289 void AliAnalysisAlien::CdWork()
291 // Check validity of alien workspace. Create directory if possible.
293 Error("CdWork", "Alien connection required");
296 TString homedir = gGrid->GetHomeDirectory();
297 TString workdir = homedir + fGridWorkingDir;
298 if (!gGrid->Cd(workdir)) {
300 if (gGrid->Mkdir(workdir)) {
301 gGrid->Cd(fGridWorkingDir);
302 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
304 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
305 workdir.Data(), homedir.Data());
306 fGridWorkingDir = "";
311 //______________________________________________________________________________
312 Bool_t AliAnalysisAlien::CheckInputData()
314 // Check validity of input data. If necessary, create xml files.
315 if (!fInputFiles && !fRunNumbers.Length()) {
316 Error("CheckInputData", "You have to specify either a set of run numbers or some existing grid files. Use AddRunNumber()/AddDataFile().");
319 // Process declared files
320 Bool_t is_collection = kFALSE;
321 Bool_t is_xml = kFALSE;
322 Bool_t use_tags = kFALSE;
323 Bool_t checked = kFALSE;
326 TString workdir = gGrid->GetHomeDirectory();
327 workdir += fGridWorkingDir;
330 TIter next(fInputFiles);
331 while ((objstr=(TObjString*)next())) {
334 file += objstr->GetString();
335 // Store full lfn path
336 if (FileExists(file)) objstr->SetString(file);
338 file = objstr->GetName();
339 if (!FileExists(objstr->GetName())) {
340 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
341 objstr->GetName(), workdir.Data());
345 Bool_t iscoll, isxml, usetags;
346 CheckDataType(file, iscoll, isxml, usetags);
349 is_collection = iscoll;
352 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
354 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
355 Error("CheckInputData", "Some conflict was found in the types of inputs");
361 // Process requested run numbers
362 if (!fRunNumbers.Length()) return kTRUE;
363 // Check validity of alien data directory
364 if (!fGridDataDir.Length()) {
365 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
368 if (!gGrid->Cd(fGridDataDir)) {
369 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
373 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
377 if (checked && !is_xml) {
378 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
381 // Check validity of run number(s)
387 use_tags = fDataPattern.Contains("tag");
388 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
390 if (use_tags != fDataPattern.Contains("tag")) {
391 Error("CheckInputData", "Cannot mix input files using/not using tags");
394 if (fRunNumbers.Length()) {
395 arr = fRunNumbers.Tokenize(" ");
397 while ((os=(TObjString*)next())) {
398 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
399 if (!gGrid->Cd(path)) {
400 Error("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
403 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
404 TString msg = "\n##### file: ";
406 msg += " type: xml_collection;";
407 if (use_tags) msg += " using_tags: Yes";
408 else msg += " using_tags: No";
409 Info("CheckDataType", msg.Data());
417 //______________________________________________________________________________
418 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
420 // Create dataset for the grid data directory + run number.
421 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
423 Error("CreateDataset", "Cannot create dataset with no grid connection");
429 TString workdir = gGrid->GetHomeDirectory();
430 workdir += fGridWorkingDir;
432 // Compose the 'find' command arguments
434 TString options = "-x collection ";
435 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
436 TString conditions = "";
440 if (!fRunNumbers.Length()) return kTRUE;
442 TObjArray *arr = fRunNumbers.Tokenize(" ");
445 while ((os=(TObjString*)next())) {
446 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
447 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
448 else file = Form("%s.xml", os->GetString().Data());
449 if (FileExists(file) && !TestBit(AliAnalysisGrid::kTest)) {
450 Info("CreateDataset", "\n##### Removing previous dataset %s", file.Data());
457 // conditions = Form(" > %s", file.Data());
458 command += conditions;
459 TGridResult *res = gGrid->Command(command);
461 // Write standard output to file
462 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
463 if (TestBit(AliAnalysisGrid::kTest)) break;
464 // Copy xml file to alien space
465 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
466 if (!FileExists(file)) {
467 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
476 //______________________________________________________________________________
477 Bool_t AliAnalysisAlien::CreateJDL()
479 // Generate a JDL file according to current settings. The name of the file is
480 // specified by fJDLName.
481 Bool_t error = kFALSE;
484 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
485 Bool_t generate = kTRUE;
486 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
488 Error("CreateJDL", "Alien connection required");
491 // Check validity of alien workspace
493 TString workdir = gGrid->GetHomeDirectory();
494 workdir += fGridWorkingDir;
498 Error("CreateJDL()", "Define some input files for your analysis.");
501 // Compose list of input files
502 // Check if output files were defined
503 if (!fOutputFiles.Length()) {
504 Error("CreateJDL", "You must define at least one output file");
507 // Check if an output directory was defined and valid
508 if (!fGridOutputDir.Length()) {
509 Error("CreateJDL", "You must define AliEn output directory");
512 if (!gGrid->Cd(fGridOutputDir)) {
513 if (gGrid->Mkdir(fGridOutputDir)) {
514 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
516 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
522 // Exit if any error up to now
523 if (error) return kFALSE;
525 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
526 fGridJDL->SetExecutable(fExecutable);
527 // fGridJDL->SetTTL((UInt_t)fTTL);
528 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
529 if (fMaxInitFailed > 0)
530 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
531 if (fSplitMaxInputFileNumber > 0)
532 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
533 if (fSplitMode.Length())
534 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
535 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
536 if (fAliROOTVersion.Length())
537 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
538 if (fROOTVersion.Length())
539 fGridJDL->AddToPackages("ROOT", fROOTVersion);
540 if (fAPIVersion.Length())
541 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
542 fGridJDL->SetInputDataListFormat(fInputFormat);
543 fGridJDL->SetInputDataList("wn.xml");
545 TIter next(fInputFiles);
546 while ((os=(TObjString*)next()))
547 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
549 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
550 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
551 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
552 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
553 if (fAdditionalLibs.Length()) {
554 arr = fAdditionalLibs.Tokenize(" ");
556 while ((os=(TObjString*)next())) {
557 if (os->GetString().Contains(".so")) continue;
558 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
563 TIter next(fPackages);
566 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
568 if (fOutputArchive.Length()) {
569 arr = fOutputArchive.Tokenize(" ");
571 while ((os=(TObjString*)next()))
572 fGridJDL->AddToOutputArchive(os->GetString().Data());
575 fGridJDL->SetOutputDirectory(Form("%s/%s/#alien_counter_03i#", workdir.Data(), fGridOutputDir.Data()));
576 arr = fOutputFiles.Tokenize(" ");
578 while ((os=(TObjString*)next())) fGridJDL->AddToOutputSandbox(os->GetString());
580 // fGridJDL->SetPrice((UInt_t)fPrice);
581 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
582 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
583 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
584 // Generate the JDL as a string
585 TString sjdl = fGridJDL->Generate();
587 index = sjdl.Index("Executable");
588 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
589 index = sjdl.Index("Split ");
590 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
591 index = sjdl.Index("SplitMaxInputFileNumber");
592 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
593 index = sjdl.Index("InputDataCollection");
594 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
595 index = sjdl.Index("InputFile");
596 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
597 index = sjdl.Index("InputDataList ");
598 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
599 index = sjdl.Index("InputDataListFormat");
600 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
601 index = sjdl.Index("Price");
602 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
603 index = sjdl.Index("Requirements");
604 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
605 index = sjdl.Index("Packages");
606 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
607 index = sjdl.Index("User");
608 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
609 index = sjdl.Index("TTL");
610 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
611 index = sjdl.Index("OutputFile");
612 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
613 index = sjdl.Index("OutputDir");
614 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
615 index = sjdl.Index("OutputArchive");
616 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
617 index = sjdl.Index("MaxInitFailed");
618 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
619 index = sjdl.Index("MasterResubmitThreshold");
620 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
621 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
622 index = sjdl.Index("Validationcommand");
623 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
624 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
625 sjdl.ReplaceAll("(member", "\n (member");
626 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
627 sjdl.ReplaceAll("{", "{\n ");
628 sjdl.ReplaceAll("};", "\n};");
629 sjdl.ReplaceAll("{\n \n", "{\n");
630 sjdl.ReplaceAll("\n\n", "\n");
631 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
632 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
633 sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
634 index = sjdl.Index("JDLVariables");
635 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
638 out.open(fJDLName.Data(), ios::out);
640 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
645 // Copy jdl to grid workspace
647 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
649 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn working space", fJDLName.Data());
650 if (FileExists(fJDLName)) gGrid->Rm(fJDLName);
651 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s/%s", workdir.Data(), fJDLName.Data()));
652 if (fAdditionalLibs.Length()) {
653 arr = fAdditionalLibs.Tokenize(" ");
656 while ((os=(TObjString*)next())) {
657 if (os->GetString().Contains(".so")) continue;
658 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
659 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
660 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
665 TIter next(fPackages);
667 while ((obj=next())) {
668 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
669 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
676 //______________________________________________________________________________
677 Bool_t AliAnalysisAlien::FileExists(const char *lfn) const
679 // Returns true if file exists.
681 Error("FileExists", "No connection to grid");
684 TGridResult *res = gGrid->Ls(lfn);
685 if (!res) return kFALSE;
686 TMap *map = dynamic_cast<TMap*>(res->At(0));
691 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
692 if (!objs || !objs->GetString().Length()) {
700 //______________________________________________________________________________
701 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
703 // Check input data type.
704 is_collection = kFALSE;
708 Error("CheckDataType", "No connection to grid");
711 is_collection = IsCollection(lfn);
712 TString msg = "\n##### file: ";
715 msg += " type: raw_collection;";
716 // special treatment for collections
718 // check for tag files in the collection
719 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
721 msg += " using_tags: No (unknown)";
722 Info("CheckDataType", msg.Data());
725 const char* typeStr = res->GetKey(0, "origLFN");
726 if (!typeStr || !strlen(typeStr)) {
727 msg += " using_tags: No (unknown)";
728 Info("CheckDataType", msg.Data());
731 TString file = typeStr;
732 use_tags = file.Contains(".tag");
733 if (use_tags) msg += " using_tags: Yes";
734 else msg += " using_tags: No";
735 Info("CheckDataType", msg.Data());
740 is_xml = slfn.Contains(".xml");
742 // Open xml collection and check if there are tag files inside
743 msg += " type: xml_collection;";
744 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
746 msg += " using_tags: No (unknown)";
747 Info("CheckDataType", msg.Data());
750 TMap *map = coll->Next();
752 msg += " using_tags: No (unknown)";
753 Info("CheckDataType", msg.Data());
756 map = (TMap*)map->GetValue("");
758 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
759 use_tags = file.Contains(".tag");
761 if (use_tags) msg += " using_tags: Yes";
762 else msg += " using_tags: No";
763 Info("CheckDataType", msg.Data());
766 use_tags = slfn.Contains(".tag");
767 if (slfn.Contains(".root")) msg += " type: root file;";
768 else msg += " type: unhnown file;";
769 if (use_tags) msg += " using_tags: Yes";
770 else msg += " using_tags: No";
771 Info("CheckDataType", msg.Data());
774 //______________________________________________________________________________
775 void AliAnalysisAlien::EnablePackage(const char *package)
777 // Enables a par file supposed to exist in the current directory.
778 TString pkg(package);
779 pkg.ReplaceAll(".par", "");
781 if (gSystem->AccessPathName(pkg)) {
782 Error("EnablePackage", "Package %s not found", pkg.Data());
785 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
786 Info("EnablePackage", "AliEn plugin will use .par packages");
787 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
789 fPackages = new TObjArray();
790 fPackages->SetOwner();
792 fPackages->Add(new TObjString(pkg));
795 //______________________________________________________________________________
796 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
798 // Returns true if file is a collection. Functionality duplicated from
799 // TAlien::Type() because we don't want to directly depend on TAlien.
801 Error("IsCollection", "No connection to grid");
804 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
805 if (!res) return kFALSE;
806 const char* typeStr = res->GetKey(0, "type");
807 if (!typeStr || !strlen(typeStr)) return kFALSE;
808 if (!strcmp(typeStr, "collection")) return kTRUE;
813 //______________________________________________________________________________
814 void AliAnalysisAlien::SetDefaults()
816 // Set default values for everything. What cannot be filled will be left empty.
817 if (fGridJDL) delete fGridJDL;
818 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
821 fSplitMaxInputFileNumber = 100;
823 fMasterResubmitThreshold = 0;
826 fExecutable = "analysis.sh";
828 fAnalysisMacro = "myAnalysis.C";
829 fAnalysisSource = "";
830 fAdditionalLibs = "";
834 fAliROOTVersion = "";
835 fUser = ""; // Your alien user name
836 fGridWorkingDir = "";
837 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
838 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
839 fGridOutputDir = "output";
840 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
841 fOutputFiles = ""; // Like "AliAODs.root histos.root"
842 fInputFormat = "xml-single";
843 fJDLName = "analysis.jdl";
847 //______________________________________________________________________________
848 Bool_t AliAnalysisAlien::MergeOutputs()
850 // Merge analysis outputs existing in the AliEn space.
851 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
852 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
854 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
857 // Get the output path
858 TString output = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
859 if (!gGrid->Cd(output)) output = Form("/%s/%s", gGrid->GetHomeDirectory(), fGridOutputDir.Data());
860 if (!gGrid->Cd(output)) {
861 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
864 if (!fOutputFiles.Length()) {
865 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
868 TObjArray *list = fOutputFiles.Tokenize(" ");
873 Bool_t merged = kTRUE;
874 while((str=(TObjString*)next())) {
875 output_file = str->GetString();
876 Int_t index = output_file.Index("@");
877 if (index > 0) output_file.Remove(index);
878 if (fMergeExcludes.Length() &&
879 fMergeExcludes.Contains(output_file.Data())) continue;
880 command = Form("find %s/ *%s", output.Data(), output_file.Data());
881 printf("command: %s\n", command.Data());
882 TGridResult *res = gGrid->Command(command);
887 while ((map=(TMap*)nextmap())) {
888 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
889 if (!objs || !objs->GetString().Length()) {
894 fm = new TFileMerger(kFALSE);
895 fm->SetFastMethod(kTRUE);
896 fm->OutputFile(output_file);
898 fm->AddFile(objs->GetString());
900 if (!fm || !fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
901 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
907 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
910 Info("MergeOutputs", "\n##### Merged %d output files <%s>", fm->GetMergeList()->GetSize(), output_file.Data());
916 Error("MergeOutputs", "Terminate() will NOT be executed");
921 //______________________________________________________________________________
922 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
924 // Use the output files connected to output containers from the analysis manager
925 // rather than the files defined by SetOutputFiles
926 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
927 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
929 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
932 //______________________________________________________________________________
933 void AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
935 // Start remote grid analysis.
937 if (TestBit(AliAnalysisGrid::kOffline)) {
938 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
939 \n there nor any job run. You can revise the JDL and analysis \
940 \n macro then run the same in \"submit\" mode.");
941 } else if (TestBit(AliAnalysisGrid::kTest)) {
942 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
944 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
945 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
946 \n space and job submitted.");
947 } else if (TestBit(AliAnalysisGrid::kMerge)) {
948 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
951 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
955 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
958 if (!CheckInputData()) {
959 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
962 CreateDataset(fDataPattern);
963 // Check if output files have to be taken from the analysis manager
964 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
965 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
966 if (!mgr || !mgr->IsInitialized()) {
967 Error("StartAnalysis", "You need an initialized analysis manager for this");
971 TIter next(mgr->GetOutputs());
972 AliAnalysisDataContainer *output;
973 while ((output=(AliAnalysisDataContainer*)next())) {
974 const char *filename = output->GetFileName();
975 if (!(strcmp(filename, "default"))) {
976 if (!mgr->GetOutputEventHandler()) continue;
977 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
979 if (fOutputFiles.Length()) fOutputFiles += " ";
980 fOutputFiles += filename;
984 WriteAnalysisMacro();
986 WriteValidationScript();
987 if (!CreateJDL()) return;
988 if (TestBit(AliAnalysisGrid::kOffline)) return;
989 if (TestBit(AliAnalysisGrid::kTest)) {
990 // Locally testing the analysis
991 Info("StartAnalysis", "\n_______________________________________________________________________ \
992 \n Running analysis script in a daughter shell as on a worker node \
993 \n_______________________________________________________________________");
994 TObjArray *list = fOutputFiles.Tokenize(" ");
998 while((str=(TObjString*)next())) {
999 output_file = str->GetString();
1000 Int_t index = output_file.Index("@");
1001 if (index > 0) output_file.Remove(index);
1002 gSystem->Exec(Form("rm %s", output_file.Data()));
1005 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1006 gSystem->Exec("bash validate.sh");
1007 // gSystem->Exec("cat stdout");
1012 TGridResult *res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1015 const char *cjobId = res->GetKey(0,"jobId");
1017 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1020 Info("StartAnalysis", "\n_______________________________________________________________________ \
1021 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1022 \n_______________________________________________________________________",
1023 fJDLName.Data(), cjobId);
1028 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1029 \n You may exit at any time and terminate the job later using the option <terminate> \
1030 \n ##################################################################################", jobID.Data());
1032 gSystem->Exec("aliensh");
1035 //______________________________________________________________________________
1036 void AliAnalysisAlien::WriteAnalysisFile()
1038 // Write current analysis manager into the file analysis.root
1039 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1040 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1041 if (!mgr || !mgr->IsInitialized()) {
1042 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1045 // Check analysis type
1047 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1048 handler = (TObject*)mgr->GetInputEventHandler();
1050 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1051 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1053 TDirectory *cdir = gDirectory;
1054 TFile *file = TFile::Open("analysis.root", "RECREATE");
1059 if (cdir) cdir->cd();
1060 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1062 Bool_t copy = kTRUE;
1063 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1066 TString workdir = gGrid->GetHomeDirectory();
1067 workdir += fGridWorkingDir;
1068 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1069 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1070 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1074 //______________________________________________________________________________
1075 void AliAnalysisAlien::WriteAnalysisMacro()
1077 // Write the analysis macro that will steer the analysis in grid mode.
1078 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1080 out.open(fAnalysisMacro.Data(), ios::out);
1082 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1085 TString func = fAnalysisMacro;
1086 TString type = "ESD";
1087 TString comment = "// Analysis using ";
1088 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1089 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1093 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1094 else comment += " data";
1095 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1096 func.ReplaceAll(".C", "");
1097 out << "void " << func.Data() << "()" << endl;
1099 out << comment.Data() << endl;
1100 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1101 out << "// load base root libraries" << endl;
1102 out << " gSystem->Load(\"libTree\");" << endl;
1103 out << " gSystem->Load(\"libGeom\");" << endl;
1104 out << " gSystem->Load(\"libVMC\");" << endl;
1105 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1107 out << "// Load analysis framework libraries" << endl;
1108 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1109 out << " gSystem->Load(\"libESD\");" << endl;
1110 out << " gSystem->Load(\"libAOD\");" << endl;
1111 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1112 out << " gSystem->Load(\"libANALYSISalice\");" << endl << endl;
1113 out << "// include path (remove if using par files)" << endl;
1114 out << " gROOT->ProcessLine(\".include $ALICE_ROOT/include\");" << endl;
1115 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl << endl;
1117 out << "// Compile all par packages" << endl;
1118 TIter next(fPackages);
1120 while ((obj=next()))
1121 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1123 if (fAdditionalLibs.Length()) {
1124 out << "// Add aditional AliRoot libraries" << endl;
1125 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1128 while((str=(TObjString*)next())) {
1129 if (str->GetString().Contains(".so"))
1130 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1132 if (list) delete list;
1135 out << "// analysis source to be compiled at runtime (if any)" << endl;
1136 if (fAnalysisSource.Length()) {
1137 TObjArray *list = fAnalysisSource.Tokenize(" ");
1140 while((str=(TObjString*)next())) {
1141 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1143 if (list) delete list;
1146 out << "// connect to AliEn and make the chain" << endl;
1147 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1148 if (IsUsingTags()) {
1149 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1151 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1153 out << "// read the analysis manager from file" << endl;
1154 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1155 out << " if (!file) return;" << endl;
1156 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1157 out << " AliAnalysisManager *mgr = 0;" << endl;
1158 out << " TKey *key;" << endl;
1159 out << " while ((key=(TKey*)nextkey())) {" << endl;
1160 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1161 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1162 out << " };" << endl;
1163 out << " if (!mgr) {" << endl;
1164 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1165 out << " return;" << endl;
1166 out << " }" << endl << endl;
1167 out << " mgr->PrintStatus();" << endl;
1168 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1169 out << "}" << endl << endl;
1170 if (IsUsingTags()) {
1171 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1173 out << "// Create a chain using tags from the xml file." << endl;
1174 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1175 out << " if (!coll) {" << endl;
1176 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1177 out << " return NULL;" << endl;
1178 out << " }" << endl;
1179 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1180 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1181 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1182 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1183 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1184 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1185 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1186 out << " // Check if the cuts configuration file was provided" << endl;
1187 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1188 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1189 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1190 out << " }" << endl;
1191 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1192 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1193 out << " chain->ls();" << endl;
1194 out << " return chain;" << endl;
1196 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1197 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1198 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1199 msg += " AliLHCTagCuts *lhcCuts,\n";
1200 msg += " AliDetectorTagCuts *detCuts,\n";
1201 msg += " AliEventTagCuts *evCuts)";
1202 Info("WriteAnalysisMacro", msg.Data());
1205 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1207 out << "// Create a chain using url's from xml file" << endl;
1208 out << " TString treename = type;" << endl;
1209 out << " treename.ToLower();" << endl;
1210 out << " treename += \"Tree\";" << endl;
1211 out << " printf(\"***************************************\\n\");" << endl;
1212 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1213 out << " printf(\"***************************************\\n\");" << endl;
1214 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1215 out << " if (!coll) {" << endl;
1216 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1217 out << " return NULL;" << endl;
1218 out << " }" << endl;
1219 out << " TChain *chain = new TChain(treename);" << endl;
1220 out << " coll->Reset();" << endl;
1221 out << " while (coll->Next()) chain->Add(coll->GetTURL(\"\"));" << endl;
1222 out << " if (!chain->GetNtrees()) {" << endl;
1223 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1224 out << " return NULL;" << endl;
1225 out << " }" << endl;
1226 out << " return chain;" << endl;
1230 out << "Bool_t SetupPar(const char *package) {" << endl;
1231 out << "// Compile the package and set it up." << endl;
1232 out << " TString pkgdir = package;" << endl;
1233 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1234 out << " gSystem->Exec(Form(\"tar xvzf %s\", package));" << endl;
1235 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1236 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1237 out << " // Check for BUILD.sh and execute" << endl;
1238 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1239 out << " printf(\"*******************************\\n\");" << endl;
1240 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1241 out << " printf(\"*******************************\\n\");" << endl;
1242 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1243 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", package);" << endl;
1244 out << " gSystem->ChangeDirectory(cdir);" << endl;
1245 out << " return kFALSE;" << endl;
1246 out << " }" << endl;
1247 out << " } else {" << endl;
1248 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", package);" << endl;
1249 out << " gSystem->ChangeDirectory(cdir);" << endl;
1250 out << " return kFALSE;" << endl;
1251 out << " }" << endl;
1252 out << " // Check for SETUP.C and execute" << endl;
1253 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1254 out << " printf(\"*******************************\\n\");" << endl;
1255 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1256 out << " printf(\"*******************************\\n\");" << endl;
1257 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1258 out << " } else {" << endl;
1259 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", package);" << endl;
1260 out << " gSystem->ChangeDirectory(cdir);" << endl;
1261 out << " return kFALSE;" << endl;
1262 out << " }" << endl;
1263 out << " // Restore original workdir" << endl;
1264 out << " gSystem->ChangeDirectory(cdir);" << endl;
1265 out << " return kTRUE;" << endl;
1268 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1270 Bool_t copy = kTRUE;
1271 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1274 TString workdir = gGrid->GetHomeDirectory();
1275 workdir += fGridWorkingDir;
1276 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1277 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1278 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1279 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1280 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1282 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1283 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1287 //______________________________________________________________________________
1288 void AliAnalysisAlien::WriteExecutable()
1290 // Generate the alien executable script.
1291 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1293 out.open(fExecutable.Data(), ios::out);
1295 Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1298 out << "#!/bin/bash" << endl;
1299 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1300 out << "echo \"=========================================\"" << endl;
1301 out << "echo \"############## PATH : ##############\"" << endl;
1302 out << "echo $PATH" << endl;
1303 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1304 out << "echo $LD_LIBRARY_PATH" << endl;
1305 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1306 out << "echo $ROOTSYS" << endl;
1307 out << "echo \"############## which root : ##############\"" << endl;
1308 out << "which root" << endl;
1309 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1310 out << "echo $ALICE_ROOT" << endl;
1311 out << "echo \"############## which aliroot : ##############\"" << endl;
1312 out << "which aliroot" << endl;
1313 out << "echo \"=========================================\"" << endl << endl;
1314 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1315 out << "root -b -q ";
1316 out << fAnalysisMacro.Data() << endl << endl;
1317 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1319 Bool_t copy = kTRUE;
1320 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1323 TString workdir = gGrid->GetHomeDirectory();
1324 workdir += fGridWorkingDir;
1325 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1326 if (FileExists(executable)) gGrid->Rm(executable);
1327 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1328 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1332 //______________________________________________________________________________
1333 void AliAnalysisAlien::WriteValidationScript()
1335 // Generate the alien validation script.
1336 // Generate the validation script
1339 Error("WriteValidationScript", "Alien connection required");
1342 TString out_stream = "";
1343 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1344 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1346 out.open("validate.sh", ios::out);
1347 out << "#!/bin/bash" << endl;
1348 out << "##################################################" << endl;
1349 out << "validateout=`dirname $0`" << endl;
1350 out << "validatetime=`date`" << endl;
1351 out << "validated=\"0\";" << endl;
1352 out << "error=0" << endl;
1353 out << "if [ -z $validateout ]" << endl;
1354 out << "then" << endl;
1355 out << " validateout=\".\"" << endl;
1356 out << "fi" << endl << endl;
1357 out << "cd $validateout;" << endl;
1358 out << "validateworkdir=`pwd`;" << endl << endl;
1359 out << "echo \"*******************************************************\"" << out_stream << endl;
1360 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1362 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1363 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1364 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1365 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1366 out << "ls -la ./" << out_stream << endl;
1367 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1368 out << "##################################################" << endl;
1369 TObjArray *arr = fOutputFiles.Tokenize(" ");
1371 TString output_file;
1372 while ((os=(TObjString*)next1())) {
1373 output_file = os->GetString();
1374 Int_t index = output_file.Index("@");
1375 if (index > 0) output_file.Remove(index);
1376 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1377 out << " error=1" << endl;
1378 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
1379 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
1380 out << "fi" << endl;
1383 out << "if [ $error = 0 ] ; then" << endl;
1384 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
1385 out << "fi" << endl;
1387 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1388 out << "echo \"*******************************************************\"" << out_stream << endl;
1389 out << "cd -" << endl;
1390 out << "exit $error" << endl;
1392 Bool_t copy = kTRUE;
1393 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1396 TString workdir = gGrid->GetHomeDirectory();
1397 workdir += fGridWorkingDir;
1398 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
1399 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
1400 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));