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 "TGridJobStatusList.h"
34 #include "TGridJobStatus.h"
35 #include "TFileMerger.h"
36 #include "AliAnalysisManager.h"
37 #include "AliVEventHandler.h"
38 #include "AliAnalysisDataContainer.h"
39 #include "AliAnalysisAlien.h"
41 ClassImp(AliAnalysisAlien)
43 //______________________________________________________________________________
44 AliAnalysisAlien::AliAnalysisAlien()
49 fSplitMaxInputFileNumber(0),
51 fMasterResubmitThreshold(0),
93 //______________________________________________________________________________
94 AliAnalysisAlien::AliAnalysisAlien(const char *name)
95 :AliAnalysisGrid(name),
99 fSplitMaxInputFileNumber(0),
101 fMasterResubmitThreshold(0),
109 fExecutableCommand(),
143 //______________________________________________________________________________
144 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
145 :AliAnalysisGrid(other),
147 fPrice(other.fPrice),
149 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
150 fMaxInitFailed(other.fMaxInitFailed),
151 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
152 fNtestFiles(other.fNtestFiles),
153 fNrunsPerMaster(other.fNrunsPerMaster),
154 fMaxMergeFiles(other.fMaxMergeFiles),
155 fNsubmitted(other.fNsubmitted),
156 fProductionMode(other.fProductionMode),
157 fRunNumbers(other.fRunNumbers),
158 fExecutable(other.fExecutable),
159 fExecutableCommand(other.fExecutableCommand),
160 fArguments(other.fArguments),
161 fAnalysisMacro(other.fAnalysisMacro),
162 fAnalysisSource(other.fAnalysisSource),
163 fAdditionalLibs(other.fAdditionalLibs),
164 fSplitMode(other.fSplitMode),
165 fAPIVersion(other.fAPIVersion),
166 fROOTVersion(other.fROOTVersion),
167 fAliROOTVersion(other.fAliROOTVersion),
168 fExternalPackages(other.fExternalPackages),
170 fGridWorkingDir(other.fGridWorkingDir),
171 fGridDataDir(other.fGridDataDir),
172 fDataPattern(other.fDataPattern),
173 fGridOutputDir(other.fGridOutputDir),
174 fOutputArchive(other.fOutputArchive),
175 fOutputFiles(other.fOutputFiles),
176 fInputFormat(other.fInputFormat),
177 fDatasetName(other.fDatasetName),
178 fJDLName(other.fJDLName),
179 fMergeExcludes(other.fMergeExcludes),
180 fIncludePath(other.fIncludePath),
181 fCloseSE(other.fCloseSE),
182 fFriendChainName(other.fFriendChainName),
183 fJobTag(other.fJobTag),
184 fOutputSingle(other.fOutputSingle),
185 fRunPrefix(other.fRunPrefix),
190 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
191 fRunRange[0] = other.fRunRange[0];
192 fRunRange[1] = other.fRunRange[1];
193 if (other.fInputFiles) {
194 fInputFiles = new TObjArray();
195 TIter next(other.fInputFiles);
197 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
198 fInputFiles->SetOwner();
200 if (other.fPackages) {
201 fPackages = new TObjArray();
202 TIter next(other.fPackages);
204 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
205 fPackages->SetOwner();
209 //______________________________________________________________________________
210 AliAnalysisAlien::~AliAnalysisAlien()
213 if (fGridJDL) delete fGridJDL;
214 if (fInputFiles) delete fInputFiles;
215 if (fPackages) delete fPackages;
218 //______________________________________________________________________________
219 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
222 if (this != &other) {
223 AliAnalysisGrid::operator=(other);
224 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
225 fPrice = other.fPrice;
227 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
228 fMaxInitFailed = other.fMaxInitFailed;
229 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
230 fNtestFiles = other.fNtestFiles;
231 fNrunsPerMaster = other.fNrunsPerMaster;
232 fMaxMergeFiles = other.fMaxMergeFiles;
233 fNsubmitted = other.fNsubmitted;
234 fProductionMode = other.fProductionMode;
235 fRunNumbers = other.fRunNumbers;
236 fExecutable = other.fExecutable;
237 fExecutableCommand = other.fExecutableCommand;
238 fArguments = other.fArguments;
239 fAnalysisMacro = other.fAnalysisMacro;
240 fAnalysisSource = other.fAnalysisSource;
241 fAdditionalLibs = other.fAdditionalLibs;
242 fSplitMode = other.fSplitMode;
243 fAPIVersion = other.fAPIVersion;
244 fROOTVersion = other.fROOTVersion;
245 fAliROOTVersion = other.fAliROOTVersion;
246 fExternalPackages = other.fExternalPackages;
248 fGridWorkingDir = other.fGridWorkingDir;
249 fGridDataDir = other.fGridDataDir;
250 fDataPattern = other.fDataPattern;
251 fGridOutputDir = other.fGridOutputDir;
252 fOutputArchive = other.fOutputArchive;
253 fOutputFiles = other.fOutputFiles;
254 fInputFormat = other.fInputFormat;
255 fDatasetName = other.fDatasetName;
256 fJDLName = other.fJDLName;
257 fMergeExcludes = other.fMergeExcludes;
258 fIncludePath = other.fIncludePath;
259 fCloseSE = other.fCloseSE;
260 fFriendChainName = other.fFriendChainName;
261 fJobTag = other.fJobTag;
262 fOutputSingle = other.fOutputSingle;
263 fRunPrefix = other.fRunPrefix;
264 if (other.fInputFiles) {
265 fInputFiles = new TObjArray();
266 TIter next(other.fInputFiles);
268 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
269 fInputFiles->SetOwner();
271 if (other.fPackages) {
272 fPackages = new TObjArray();
273 TIter next(other.fPackages);
275 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
276 fPackages->SetOwner();
282 //______________________________________________________________________________
283 void AliAnalysisAlien::AddIncludePath(const char *path)
285 // Add include path in the remote analysis macro.
287 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
288 else fIncludePath += Form("-I%s ", path);
291 //______________________________________________________________________________
292 void AliAnalysisAlien::AddRunNumber(Int_t run)
294 // Add a run number to the list of runs to be processed.
295 if (fRunNumbers.Length()) fRunNumbers += " ";
296 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
299 //______________________________________________________________________________
300 void AliAnalysisAlien::AddRunNumber(const char* run)
302 // Add a run number to the list of runs to be processed.
303 if (fRunNumbers.Length()) fRunNumbers += " ";
307 //______________________________________________________________________________
308 void AliAnalysisAlien::AddDataFile(const char *lfn)
310 // Adds a data file to the input to be analysed. The file should be a valid LFN
311 // or point to an existing file in the alien workdir.
312 if (!fInputFiles) fInputFiles = new TObjArray();
313 fInputFiles->Add(new TObjString(lfn));
316 //______________________________________________________________________________
317 void AliAnalysisAlien::AddExternalPackage(const char *package)
319 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
320 if (fExternalPackages) fExternalPackages += " ";
321 fExternalPackages += package;
324 //______________________________________________________________________________
325 Bool_t AliAnalysisAlien::Connect()
327 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
328 if (gGrid && gGrid->IsConnected()) return kTRUE;
329 if (!gSystem->Getenv("alien_API_USER")) {
330 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
331 gSystem->Getenv("UID"));
335 Info("Connect", "Trying to connect to AliEn ...");
336 TGrid::Connect("alien://");
338 if (!gGrid || !gGrid->IsConnected()) {
339 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
342 fUser = gGrid->GetUser();
343 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
347 //______________________________________________________________________________
348 void AliAnalysisAlien::CdWork()
350 // Check validity of alien workspace. Create directory if possible.
352 Error("CdWork", "Alien connection required");
355 TString homedir = gGrid->GetHomeDirectory();
356 TString workdir = homedir + fGridWorkingDir;
357 if (DirectoryExists(workdir)) {
361 // Work directory not existing - create it
363 if (gGrid->Mkdir(workdir)) {
364 gGrid->Cd(fGridWorkingDir);
365 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
367 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
368 workdir.Data(), homedir.Data());
369 fGridWorkingDir = "";
373 //______________________________________________________________________________
374 Bool_t AliAnalysisAlien::CheckInputData()
376 // Check validity of input data. If necessary, create xml files.
377 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
378 if (!fGridDataDir.Length()) {
379 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
382 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
385 // Process declared files
386 Bool_t is_collection = kFALSE;
387 Bool_t is_xml = kFALSE;
388 Bool_t use_tags = kFALSE;
389 Bool_t checked = kFALSE;
392 TString workdir = gGrid->GetHomeDirectory();
393 workdir += fGridWorkingDir;
396 TIter next(fInputFiles);
397 while ((objstr=(TObjString*)next())) {
400 file += objstr->GetString();
401 // Store full lfn path
402 if (FileExists(file)) objstr->SetString(file);
404 file = objstr->GetName();
405 if (!FileExists(objstr->GetName())) {
406 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
407 objstr->GetName(), workdir.Data());
411 Bool_t iscoll, isxml, usetags;
412 CheckDataType(file, iscoll, isxml, usetags);
415 is_collection = iscoll;
418 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
420 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
421 Error("CheckInputData", "Some conflict was found in the types of inputs");
427 // Process requested run numbers
428 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
429 // Check validity of alien data directory
430 if (!fGridDataDir.Length()) {
431 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
434 if (!DirectoryExists(fGridDataDir)) {
435 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
439 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
443 if (checked && !is_xml) {
444 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
447 // Check validity of run number(s)
455 use_tags = fDataPattern.Contains("tag");
456 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
458 if (use_tags != fDataPattern.Contains("tag")) {
459 Error("CheckInputData", "Cannot mix input files using/not using tags");
462 if (fRunNumbers.Length()) {
463 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
464 arr = fRunNumbers.Tokenize(" ");
466 while ((os=(TObjString*)next())) {
467 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
468 if (!DirectoryExists(path)) {
469 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
472 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
473 TString msg = "\n##### file: ";
475 msg += " type: xml_collection;";
476 if (use_tags) msg += " using_tags: Yes";
477 else msg += " using_tags: No";
478 Info("CheckDataType", msg.Data());
479 if (fNrunsPerMaster<2) {
480 AddDataFile(Form("%s.xml", os->GetString().Data()));
483 if (((nruns-1)%fNrunsPerMaster) == 0) {
484 schunk = os->GetString();
486 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
487 schunk += Form("_%s.xml", os->GetString().Data());
493 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
494 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
495 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
496 if (!DirectoryExists(path)) {
497 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
500 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
501 TString msg = "\n##### file: ";
503 msg += " type: xml_collection;";
504 if (use_tags) msg += " using_tags: Yes";
505 else msg += " using_tags: No";
506 Info("CheckDataType", msg.Data());
507 if (fNrunsPerMaster<2) {
508 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
511 if (((nruns-1)%fNrunsPerMaster) == 0) {
512 schunk = Form("%s%d", fRunPrefix.Data(),irun);
514 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
515 schunk += Form("_%s%d.xml", fRunPrefix.Data(), irun);
523 //______________________________________________________________________________
524 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
526 // Create dataset for the grid data directory + run number.
527 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
529 Error("CreateDataset", "Cannot create dataset with no grid connection");
535 TString workdir = gGrid->GetHomeDirectory();
536 workdir += fGridWorkingDir;
538 // Compose the 'find' command arguments
540 TString options = "-x collection ";
541 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
542 TString conditions = "";
548 TGridCollection *cbase=0, *cadd=0;
549 if (!fRunNumbers.Length() && !fRunRange[0]) {
550 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
551 // Make a single data collection from data directory.
553 if (!DirectoryExists(path)) {
554 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
558 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
559 else file = Form("%s.xml", gSystem->BaseName(path));
560 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest)) {
566 command += conditions;
567 printf("command: %s\n", command.Data());
568 TGridResult *res = gGrid->Command(command);
570 // Write standard output to file
571 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
573 if (!TestBit(AliAnalysisGrid::kTest) && !FileExists(file)) {
574 // Copy xml file to alien space
575 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
576 if (!FileExists(file)) {
577 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
580 // Update list of files to be processed.
582 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
586 if (fRunNumbers.Length()) {
587 TObjArray *arr = fRunNumbers.Tokenize(" ");
590 while ((os=(TObjString*)next())) {
591 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
592 if (!DirectoryExists(path)) continue;
594 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
595 else file = Form("%s.xml", os->GetString().Data());
596 // If local collection file does not exist, create it via 'find' command.
597 if (gSystem->AccessPathName(file)) {
602 command += conditions;
603 TGridResult *res = gGrid->Command(command);
605 // Write standard output to file
606 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
608 if (TestBit(AliAnalysisGrid::kTest)) break;
609 // Check if there is one run per master job.
610 if (fNrunsPerMaster<2) {
611 if (FileExists(file)) {
612 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
615 // Copy xml file to alien space
616 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
617 if (!FileExists(file)) {
618 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
624 if (((nruns-1)%fNrunsPerMaster) == 0) {
625 schunk = os->GetString();
626 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
628 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
629 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
633 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
636 schunk += Form("_%s.xml", os->GetString().Data());
637 if (FileExists(schunk)) {
638 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
641 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
642 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
643 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
644 if (!FileExists(schunk)) {
645 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
653 // Process a full run range.
654 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
655 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
656 if (!DirectoryExists(path)) continue;
658 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
659 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
660 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
661 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
665 // If local collection file does not exist, create it via 'find' command.
666 if (gSystem->AccessPathName(file)) {
671 command += conditions;
672 TGridResult *res = gGrid->Command(command);
674 // Write standard output to file
675 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
677 if (TestBit(AliAnalysisGrid::kTest)) break;
678 // Check if there is one run per master job.
679 if (fNrunsPerMaster<2) {
680 if (FileExists(file)) {
681 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
684 // Copy xml file to alien space
685 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
686 if (!FileExists(file)) {
687 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
692 // Check if the collection for the chunk exist locally.
693 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
694 if (FileExists(fInputFiles->At(nchunk)->GetName())) continue;
695 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
696 if (((nruns-1)%fNrunsPerMaster) == 0) {
697 schunk = Form("%d", irun);
698 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
700 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
704 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1]) {
707 schunk += Form("_%d.xml", irun);
708 if (FileExists(schunk)) {
709 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
712 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
713 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
714 if (FileExists(schunk)) {
715 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
718 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
719 if (!FileExists(schunk)) {
720 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
729 //______________________________________________________________________________
730 Bool_t AliAnalysisAlien::CreateJDL()
732 // Generate a JDL file according to current settings. The name of the file is
733 // specified by fJDLName.
734 Bool_t error = kFALSE;
737 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
738 Bool_t generate = kTRUE;
739 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
741 Error("CreateJDL", "Alien connection required");
744 // Check validity of alien workspace
746 TString workdir = gGrid->GetHomeDirectory();
747 workdir += fGridWorkingDir;
751 Error("CreateJDL()", "Define some input files for your analysis.");
754 // Compose list of input files
755 // Check if output files were defined
756 if (!fOutputFiles.Length()) {
757 Error("CreateJDL", "You must define at least one output file");
760 // Check if an output directory was defined and valid
761 if (!fGridOutputDir.Length()) {
762 Error("CreateJDL", "You must define AliEn output directory");
765 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
766 if (!DirectoryExists(fGridOutputDir)) {
767 if (gGrid->Mkdir(fGridOutputDir)) {
768 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
770 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
776 // Exit if any error up to now
777 if (error) return kFALSE;
779 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
780 fGridJDL->SetExecutable(fExecutable);
781 // fGridJDL->SetTTL((UInt_t)fTTL);
782 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
783 if (fMaxInitFailed > 0)
784 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
785 if (fSplitMaxInputFileNumber > 0)
786 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
787 if (fSplitMode.Length())
788 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
789 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
790 if (fAliROOTVersion.Length())
791 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
792 if (fROOTVersion.Length())
793 fGridJDL->AddToPackages("ROOT", fROOTVersion);
794 if (fAPIVersion.Length())
795 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
796 if (!fExternalPackages.IsNull()) {
797 arr = fExternalPackages.Tokenize(" ");
799 while ((os=(TObjString*)next())) {
800 TString pkgname = os->GetString();
801 Int_t index = pkgname.Index("::");
802 TString pkgversion = pkgname(index+2, pkgname.Length());
803 pkgname.Remove(index);
804 fGridJDL->AddToPackages(pkgname, pkgversion);
808 fGridJDL->SetInputDataListFormat(fInputFormat);
809 fGridJDL->SetInputDataList("wn.xml");
810 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
811 TString analysisFile = fExecutable;
812 analysisFile.ReplaceAll(".sh", ".root");
813 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
814 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
815 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
816 if (fAdditionalLibs.Length()) {
817 arr = fAdditionalLibs.Tokenize(" ");
819 while ((os=(TObjString*)next())) {
820 if (os->GetString().Contains(".so")) continue;
821 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
826 TIter next(fPackages);
829 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
831 if (fOutputArchive.Length()) {
832 arr = fOutputArchive.Tokenize(" ");
834 while ((os=(TObjString*)next()))
835 if (!os->GetString().Contains("@") && fCloseSE.Length())
836 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
838 fGridJDL->AddToOutputArchive(os->GetString());
841 arr = fOutputFiles.Tokenize(" ");
843 while ((os=(TObjString*)next())) {
844 // Ignore ouputs in jdl that are also in outputarchive
845 TString sout = os->GetString();
846 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
847 if (fOutputArchive.Contains(sout)) continue;
848 if (!os->GetString().Contains("@") && fCloseSE.Length())
849 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
851 fGridJDL->AddToOutputSandbox(os->GetString());
854 // fGridJDL->SetPrice((UInt_t)fPrice);
855 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
856 TString validationScript = fExecutable;
857 validationScript.ReplaceAll(".sh", "_validation.sh");
858 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()));
859 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
860 // Write a jdl with 2 input parameters: collection name and output dir name.
863 // Copy jdl to grid workspace
865 if (TestBit(AliAnalysisGrid::kSubmit)) {
866 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
867 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
869 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
870 if (FileExists(locjdl)) gGrid->Rm(locjdl);
871 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
873 if (fAdditionalLibs.Length()) {
874 arr = fAdditionalLibs.Tokenize(" ");
877 while ((os=(TObjString*)next())) {
878 if (os->GetString().Contains(".so")) continue;
879 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
880 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
881 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
886 TIter next(fPackages);
888 while ((obj=next())) {
889 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
890 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
897 //______________________________________________________________________________
898 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
900 // Writes one or more JDL's corresponding to findex. If findex is negative,
901 // all run numbers are considered in one go (jdl). For non-negative indices
902 // they correspond to the indices in the array fInputFiles.
903 if (!fInputFiles) return kFALSE;
905 TString workdir = gGrid->GetHomeDirectory();
906 workdir += fGridWorkingDir;
908 if (!fRunNumbers.Length() && !fRunRange[0]) {
909 // One jdl with no parameters in case input data is specified by name.
910 TIter next(fInputFiles);
911 while ((os=(TObjString*)next()))
912 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
913 if (!fOutputSingle.IsNull())
914 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
916 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
918 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
919 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
920 if (!fOutputSingle.IsNull())
921 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
922 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()));
926 // Generate the JDL as a string
927 TString sjdl = fGridJDL->Generate();
929 index = sjdl.Index("Executable");
930 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
931 index = sjdl.Index("Split ");
932 if (index >= 0) sjdl.Insert(index, "\n# We split per SE or file\n");
933 index = sjdl.Index("SplitMaxInputFileNumber");
934 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
935 index = sjdl.Index("InputDataCollection");
936 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
937 index = sjdl.Index("InputFile");
938 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
939 index = sjdl.Index("InputDataList ");
940 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
941 index = sjdl.Index("InputDataListFormat");
942 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
943 index = sjdl.Index("Price");
944 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
945 index = sjdl.Index("Requirements");
946 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
947 index = sjdl.Index("Packages");
948 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
949 index = sjdl.Index("User =");
950 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
951 index = sjdl.Index("TTL");
952 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
953 index = sjdl.Index("OutputFile");
954 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
955 index = sjdl.Index("OutputDir");
956 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
957 index = sjdl.Index("OutputArchive");
958 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
959 index = sjdl.Index("MaxInitFailed");
960 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
961 index = sjdl.Index("MasterResubmitThreshold");
962 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
963 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
964 index = sjdl.Index("Validationcommand");
965 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
966 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
967 sjdl.ReplaceAll("(member", "\n (member");
968 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
969 sjdl.ReplaceAll("{", "{\n ");
970 sjdl.ReplaceAll("};", "\n};");
971 sjdl.ReplaceAll("{\n \n", "{\n");
972 sjdl.ReplaceAll("\n\n", "\n");
973 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
974 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
975 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
976 index = sjdl.Index("JDLVariables");
977 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
980 out.open(fJDLName.Data(), ios::out);
982 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
987 // Copy jdl to grid workspace
989 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
991 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
992 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
994 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
995 if (FileExists(locjdl)) gGrid->Rm(locjdl);
996 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1001 //______________________________________________________________________________
1002 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1004 // Returns true if file exists.
1005 if (!gGrid) return kFALSE;
1006 TGridResult *res = gGrid->Ls(lfn);
1007 if (!res) return kFALSE;
1008 TMap *map = dynamic_cast<TMap*>(res->At(0));
1013 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1014 if (!objs || !objs->GetString().Length()) {
1022 //______________________________________________________________________________
1023 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1025 // Returns true if directory exists. Can be also a path.
1026 if (!gGrid) return kFALSE;
1027 // Check if dirname is a path
1028 TString dirstripped = dirname;
1029 dirstripped = dirstripped.Strip();
1030 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1031 TString dir = gSystem->BaseName(dirstripped);
1033 TString path = gSystem->DirName(dirstripped);
1034 TGridResult *res = gGrid->Ls(path, "-F");
1035 if (!res) return kFALSE;
1039 while ((map=dynamic_cast<TMap*>(next()))) {
1040 obj = map->GetValue("name");
1042 if (dir == obj->GetName()) {
1051 //______________________________________________________________________________
1052 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1054 // Check input data type.
1055 is_collection = kFALSE;
1059 Error("CheckDataType", "No connection to grid");
1062 is_collection = IsCollection(lfn);
1063 TString msg = "\n##### file: ";
1065 if (is_collection) {
1066 msg += " type: raw_collection;";
1067 // special treatment for collections
1069 // check for tag files in the collection
1070 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1072 msg += " using_tags: No (unknown)";
1073 Info("CheckDataType", msg.Data());
1076 const char* typeStr = res->GetKey(0, "origLFN");
1077 if (!typeStr || !strlen(typeStr)) {
1078 msg += " using_tags: No (unknown)";
1079 Info("CheckDataType", msg.Data());
1082 TString file = typeStr;
1083 use_tags = file.Contains(".tag");
1084 if (use_tags) msg += " using_tags: Yes";
1085 else msg += " using_tags: No";
1086 Info("CheckDataType", msg.Data());
1091 is_xml = slfn.Contains(".xml");
1093 // Open xml collection and check if there are tag files inside
1094 msg += " type: xml_collection;";
1095 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1097 msg += " using_tags: No (unknown)";
1098 Info("CheckDataType", msg.Data());
1101 TMap *map = coll->Next();
1103 msg += " using_tags: No (unknown)";
1104 Info("CheckDataType", msg.Data());
1107 map = (TMap*)map->GetValue("");
1109 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1110 use_tags = file.Contains(".tag");
1112 if (use_tags) msg += " using_tags: Yes";
1113 else msg += " using_tags: No";
1114 Info("CheckDataType", msg.Data());
1117 use_tags = slfn.Contains(".tag");
1118 if (slfn.Contains(".root")) msg += " type: root file;";
1119 else msg += " type: unhnown file;";
1120 if (use_tags) msg += " using_tags: Yes";
1121 else msg += " using_tags: No";
1122 Info("CheckDataType", msg.Data());
1125 //______________________________________________________________________________
1126 void AliAnalysisAlien::EnablePackage(const char *package)
1128 // Enables a par file supposed to exist in the current directory.
1129 TString pkg(package);
1130 pkg.ReplaceAll(".par", "");
1132 if (gSystem->AccessPathName(pkg)) {
1133 Error("EnablePackage", "Package %s not found", pkg.Data());
1136 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1137 Info("EnablePackage", "AliEn plugin will use .par packages");
1138 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1140 fPackages = new TObjArray();
1141 fPackages->SetOwner();
1143 fPackages->Add(new TObjString(pkg));
1146 //______________________________________________________________________________
1147 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1149 // Get job status for all jobs with jobid>jobidstart.
1150 static char mstatus[20];
1156 TGridJobStatusList *list = gGrid->Ps("");
1157 if (!list) return mstatus;
1158 Int_t nentries = list->GetSize();
1159 TGridJobStatus *status;
1161 for (Int_t ijob=0; ijob<nentries; ijob++) {
1162 status = (TGridJobStatus *)list->At(ijob);
1163 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1164 if (pid<jobidstart) continue;
1165 if (pid == lastid) {
1166 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1168 switch (status->GetStatus()) {
1169 case TGridJobStatus::kWAITING:
1171 case TGridJobStatus::kRUNNING:
1173 case TGridJobStatus::kABORTED:
1174 case TGridJobStatus::kFAIL:
1175 case TGridJobStatus::kUNKNOWN:
1177 case TGridJobStatus::kDONE:
1186 //______________________________________________________________________________
1187 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1189 // Returns true if file is a collection. Functionality duplicated from
1190 // TAlien::Type() because we don't want to directly depend on TAlien.
1192 Error("IsCollection", "No connection to grid");
1195 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1196 if (!res) return kFALSE;
1197 const char* typeStr = res->GetKey(0, "type");
1198 if (!typeStr || !strlen(typeStr)) return kFALSE;
1199 if (!strcmp(typeStr, "collection")) return kTRUE;
1204 //______________________________________________________________________________
1205 void AliAnalysisAlien::Print(Option_t *) const
1207 // Print current plugin settings.
1208 printf("### AliEn analysis plugin current settings ###\n");
1209 printf("= Production mode:______________________________ %d\n", fProductionMode);
1210 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1211 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1212 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1214 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1215 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1216 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1217 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1218 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1219 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1220 if (fRunNumbers.Length())
1221 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1223 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1224 if (!fRunRange[0] && !fRunNumbers.Length()) {
1225 TIter next(fInputFiles);
1228 while ((obj=next())) list += obj->GetName();
1229 printf("= Input files to be processed: _________________ %s\n", list.Data());
1231 if (TestBit(AliAnalysisGrid::kTest))
1232 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1233 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1234 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1235 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1236 printf("=====================================================================\n");
1237 printf("= Job price: ___________________________________ %d\n", fPrice);
1238 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1239 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1240 if (fMaxInitFailed>0)
1241 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1242 if (fMasterResubmitThreshold>0)
1243 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1244 if (fNrunsPerMaster>0)
1245 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1246 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1247 printf("= Name of the generated execution script: ______ %s\n",fExecutable.Data());
1248 if (fArguments.Length())
1249 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1250 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1251 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1252 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1253 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1255 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1256 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1257 if (fIncludePath.Data())
1258 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1259 if (fCloseSE.Length())
1260 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1261 if (fFriendChainName.Length())
1262 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1264 TIter next(fPackages);
1267 while ((obj=next())) list += obj->GetName();
1268 printf("= Par files to be used: ________________________ %s\n", list.Data());
1272 //______________________________________________________________________________
1273 void AliAnalysisAlien::SetDefaults()
1275 // Set default values for everything. What cannot be filled will be left empty.
1276 if (fGridJDL) delete fGridJDL;
1277 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1280 fSplitMaxInputFileNumber = 100;
1282 fMasterResubmitThreshold = 0;
1286 fNrunsPerMaster = 1;
1287 fMaxMergeFiles = 100;
1289 fExecutable = "analysis.sh";
1290 fExecutableCommand = "root -b -q";
1292 fAnalysisMacro = "myAnalysis.C";
1293 fAnalysisSource = "";
1294 fAdditionalLibs = "";
1298 fAliROOTVersion = "";
1299 fUser = ""; // Your alien user name
1300 fGridWorkingDir = "";
1301 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1302 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1303 fFriendChainName = "";
1304 fGridOutputDir = "output";
1305 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1306 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1307 fInputFormat = "xml-single";
1308 fJDLName = "analysis.jdl";
1309 fJobTag = "Automatically generated analysis JDL";
1310 fMergeExcludes = "";
1313 //______________________________________________________________________________
1314 Bool_t AliAnalysisAlien::MergeOutputs()
1316 // Merge analysis outputs existing in the AliEn space.
1317 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1318 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1320 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1323 // Get the output path
1324 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1325 if (!DirectoryExists(fGridOutputDir)) {
1326 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1329 if (!fOutputFiles.Length()) {
1330 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1333 TObjArray *list = fOutputFiles.Tokenize(" ");
1337 TString output_file;
1338 TString output_chunk;
1339 TString previous_chunk;
1340 Int_t count_chunk = 0;
1341 Int_t count_zero = fMaxMergeFiles;
1342 Bool_t merged = kTRUE;
1343 while((str=(TObjString*)next())) {
1344 output_file = str->GetString();
1345 Int_t index = output_file.Index("@");
1346 if (index > 0) output_file.Remove(index);
1347 // Skip already merged outputs
1348 if (!gSystem->AccessPathName(output_file)) {
1349 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1352 if (fMergeExcludes.Length() &&
1353 fMergeExcludes.Contains(output_file.Data())) continue;
1354 // Perform a 'find' command in the output directory, looking for registered outputs
1355 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
1356 printf("command: %s\n", command.Data());
1357 TGridResult *res = gGrid->Command(command);
1359 TFileMerger *fm = 0;
1362 previous_chunk = "";
1364 // Check if there is a merge operation to resume
1365 output_chunk = output_file;
1366 output_chunk.ReplaceAll(".root", "_*.root");
1367 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1369 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1371 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1375 output_chunk = output_file;
1376 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1377 printf("%s\n", output_chunk.Data());
1379 if (gSystem->AccessPathName(output_chunk)) continue;
1380 // Merged file with chunks up to <count_chunk> found
1381 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1382 previous_chunk = output_chunk;
1386 count_zero = fMaxMergeFiles;
1387 while ((map=(TMap*)nextmap())) {
1388 // Loop 'find' results and get next LFN
1389 if (count_zero == fMaxMergeFiles) {
1390 // First file in chunk - create file merger and add previous chunk if any.
1391 fm = new TFileMerger(kFALSE);
1392 fm->SetFastMethod(kTRUE);
1393 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1394 output_chunk = output_file;
1395 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1397 // If last file found, put merged results in the output file
1398 if (map == res->Last()) output_chunk = output_file;
1399 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1400 if (!objs || !objs->GetString().Length()) {
1401 // Nothing found - skip this output
1406 // Add file to be merged and decrement chunk counter.
1407 fm->AddFile(objs->GetString());
1409 if (count_zero==0 || map == res->Last()) {
1410 fm->OutputFile(output_chunk);
1411 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1412 // Nothing found - skip this output
1413 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1418 // Merge the outputs, then go to next chunk
1420 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1426 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1427 gSystem->Unlink(previous_chunk);
1429 if (map == res->Last()) {
1435 count_zero = fMaxMergeFiles;
1436 previous_chunk = output_chunk;
1441 Error("MergeOutputs", "Terminate() will NOT be executed");
1446 //______________________________________________________________________________
1447 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1449 // Use the output files connected to output containers from the analysis manager
1450 // rather than the files defined by SetOutputFiles
1451 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1452 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1454 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1457 //______________________________________________________________________________
1458 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1460 // Start remote grid analysis.
1462 // Check if output files have to be taken from the analysis manager
1463 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1464 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1465 if (!mgr || !mgr->IsInitialized()) {
1466 Error("StartAnalysis", "You need an initialized analysis manager for this");
1470 TIter next(mgr->GetOutputs());
1471 AliAnalysisDataContainer *output;
1472 while ((output=(AliAnalysisDataContainer*)next())) {
1473 const char *filename = output->GetFileName();
1474 if (!(strcmp(filename, "default"))) {
1475 if (!mgr->GetOutputEventHandler()) continue;
1476 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1478 if (fOutputFiles.Contains(filename)) continue;
1479 if (fOutputFiles.Length()) fOutputFiles += " ";
1480 fOutputFiles += filename;
1482 // Add extra files registered to the analysis manager
1483 if (mgr->GetExtraFiles().Length()) {
1484 if (fOutputFiles.Length()) fOutputFiles += " ";
1485 fOutputFiles += mgr->GetExtraFiles();
1488 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1489 if (TestBit(AliAnalysisGrid::kOffline)) {
1490 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1491 \n there nor any job run. You can revise the JDL and analysis \
1492 \n macro then run the same in \"submit\" mode.");
1493 } else if (TestBit(AliAnalysisGrid::kTest)) {
1494 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1496 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1497 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1498 \n space and job submitted.");
1499 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1500 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1503 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1507 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1511 if (!CheckInputData()) {
1512 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1515 CreateDataset(fDataPattern);
1516 WriteAnalysisFile();
1517 WriteAnalysisMacro();
1519 WriteValidationScript();
1520 if (!CreateJDL()) return kFALSE;
1521 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1522 if (TestBit(AliAnalysisGrid::kTest)) {
1523 // Locally testing the analysis
1524 Info("StartAnalysis", "\n_______________________________________________________________________ \
1525 \n Running analysis script in a daughter shell as on a worker node \
1526 \n_______________________________________________________________________");
1527 TObjArray *list = fOutputFiles.Tokenize(" ");
1530 TString output_file;
1531 while((str=(TObjString*)next())) {
1532 output_file = str->GetString();
1533 Int_t index = output_file.Index("@");
1534 if (index > 0) output_file.Remove(index);
1535 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1538 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1539 TString validationScript = fExecutable;
1540 validationScript.ReplaceAll(".sh", "_validation.sh");
1541 gSystem->Exec(Form("bash %s",validationScript.Data()));
1542 // gSystem->Exec("cat stdout");
1545 // Check if submitting is managed by LPM manager
1546 if (fProductionMode) {
1547 TString prodfile = fJDLName;
1548 prodfile.ReplaceAll(".jdl", ".prod");
1549 WriteProductionFile(prodfile);
1550 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1553 // Submit AliEn job(s)
1554 gGrid->Cd(fGridOutputDir);
1557 if (!fRunNumbers.Length() && !fRunRange[0]) {
1558 // Submit a given xml or a set of runs
1559 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1560 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1562 const char *cjobId = res->GetKey(0,"jobId");
1564 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1567 Info("StartAnalysis", "\n_______________________________________________________________________ \
1568 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1569 \n_______________________________________________________________________",
1570 fJDLName.Data(), cjobId);
1576 // Submit for a range of enumeration of runs.
1580 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1581 \n You may exit at any time and terminate the job later using the option <terminate> \
1582 \n ##################################################################################", jobID.Data());
1583 gSystem->Exec("aliensh");
1587 //______________________________________________________________________________
1588 void AliAnalysisAlien::Submit()
1590 // Submit all master jobs.
1591 Int_t nmasterjobs = fInputFiles->GetEntries();
1592 Long_t tshoot = gSystem->Now();
1593 if (!fNsubmitted) SubmitNext();
1594 while (fNsubmitted < nmasterjobs) {
1595 Long_t now = gSystem->Now();
1596 if ((now-tshoot)>30000) {
1603 //______________________________________________________________________________
1604 void AliAnalysisAlien::SubmitNext()
1606 // Submit next bunch of master jobs if the queue is free.
1607 static Bool_t iscalled = kFALSE;
1608 static Int_t firstmaster = 0;
1609 static Int_t lastmaster = 0;
1610 static Int_t npermaster = 0;
1611 if (iscalled) return;
1613 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1614 Int_t ntosubmit = 0;
1617 if (!fNsubmitted) ntosubmit = 1;
1619 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1620 printf("=== master %d: %s\n", lastmaster, status.Data());
1621 // If last master not split, just return
1622 if (status != "SPLIT") {iscalled = kFALSE; return;}
1623 // No more than 100 waiting jobs
1624 if (nwaiting>100) {iscalled = kFALSE; return;}
1625 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1626 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1627 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1628 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1630 Int_t nmasterjobs = fInputFiles->GetEntries();
1631 for (Int_t i=0; i<ntosubmit; i++) {
1632 // Submit for a range of enumeration of runs.
1633 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1635 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1636 printf("********* %s\n",query.Data());
1637 res = gGrid->Command(query);
1639 TString cjobId1 = res->GetKey(0,"jobId");
1640 if (!cjobId1.Length()) {
1641 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1645 Info("StartAnalysis", "\n_______________________________________________________________________ \
1646 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1647 \n_______________________________________________________________________",
1648 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1651 lastmaster = cjobId1.Atoi();
1652 if (!firstmaster) firstmaster = lastmaster;
1661 //______________________________________________________________________________
1662 void AliAnalysisAlien::WriteAnalysisFile()
1664 // Write current analysis manager into the file <analysisFile>
1665 TString analysisFile = fExecutable;
1666 analysisFile.ReplaceAll(".sh", ".root");
1667 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1668 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1669 if (!mgr || !mgr->IsInitialized()) {
1670 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1673 // Check analysis type
1675 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1676 handler = (TObject*)mgr->GetInputEventHandler();
1678 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1679 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1681 TDirectory *cdir = gDirectory;
1682 TFile *file = TFile::Open(analysisFile, "RECREATE");
1687 if (cdir) cdir->cd();
1688 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
1690 Bool_t copy = kTRUE;
1691 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1694 TString workdir = gGrid->GetHomeDirectory();
1695 workdir += fGridWorkingDir;
1696 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1697 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1698 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
1702 //______________________________________________________________________________
1703 void AliAnalysisAlien::WriteAnalysisMacro()
1705 // Write the analysis macro that will steer the analysis in grid mode.
1706 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1708 out.open(fAnalysisMacro.Data(), ios::out);
1710 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1713 TString func = fAnalysisMacro;
1714 TString type = "ESD";
1715 TString comment = "// Analysis using ";
1716 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1717 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1721 if (type!="AOD" && fFriendChainName!="") {
1722 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1725 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1726 else comment += " data";
1727 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1728 func.ReplaceAll(".C", "");
1729 out << "void " << func.Data() << "()" << endl;
1731 out << comment.Data() << endl;
1732 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1733 out << " TStopwatch timer;" << endl;
1734 out << " timer.Start();" << endl << endl;
1735 out << "// load base root libraries" << endl;
1736 out << " gSystem->Load(\"libTree\");" << endl;
1737 out << " gSystem->Load(\"libGeom\");" << endl;
1738 out << " gSystem->Load(\"libVMC\");" << endl;
1739 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1740 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
1741 out << "// Load analysis framework libraries" << endl;
1743 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1744 out << " gSystem->Load(\"libESD\");" << endl;
1745 out << " gSystem->Load(\"libAOD\");" << endl;
1746 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1747 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1748 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1750 TIter next(fPackages);
1753 Bool_t hasSTEERBase = kFALSE;
1754 Bool_t hasESD = kFALSE;
1755 Bool_t hasAOD = kFALSE;
1756 Bool_t hasANALYSIS = kFALSE;
1757 Bool_t hasANALYSISalice = kFALSE;
1758 Bool_t hasCORRFW = kFALSE;
1759 while ((obj=next())) {
1760 pkgname = obj->GetName();
1761 if (pkgname == "STEERBase" ||
1762 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1763 if (pkgname == "ESD" ||
1764 pkgname == "ESD.par") hasESD = kTRUE;
1765 if (pkgname == "AOD" ||
1766 pkgname == "AOD.par") hasAOD = kTRUE;
1767 if (pkgname == "ANALYSIS" ||
1768 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1769 if (pkgname == "ANALYSISalice" ||
1770 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1771 if (pkgname == "CORRFW" ||
1772 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1774 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1775 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1776 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1777 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1778 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1779 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1780 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1781 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1782 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1783 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1784 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1785 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1786 out << "// Compile other par packages" << endl;
1788 while ((obj=next())) {
1789 pkgname = obj->GetName();
1790 if (pkgname == "STEERBase" ||
1791 pkgname == "STEERBase.par" ||
1793 pkgname == "ESD.par" ||
1795 pkgname == "AOD.par" ||
1796 pkgname == "ANALYSIS" ||
1797 pkgname == "ANALYSIS.par" ||
1798 pkgname == "ANALYSISalice" ||
1799 pkgname == "ANALYSISalice.par" ||
1800 pkgname == "CORRFW" ||
1801 pkgname == "CORRFW.par") continue;
1802 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1805 out << "// include path" << endl;
1806 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1807 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1808 if (fAdditionalLibs.Length()) {
1809 out << "// Add aditional AliRoot libraries" << endl;
1810 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1813 while((str=(TObjString*)next())) {
1814 if (str->GetString().Contains(".so"))
1815 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1817 if (list) delete list;
1820 out << "// analysis source to be compiled at runtime (if any)" << endl;
1821 if (fAnalysisSource.Length()) {
1822 TObjArray *list = fAnalysisSource.Tokenize(" ");
1825 while((str=(TObjString*)next())) {
1826 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1828 if (list) delete list;
1831 out << "// connect to AliEn and make the chain" << endl;
1832 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1833 if (IsUsingTags()) {
1834 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1836 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1837 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1839 out << " // Check if the macro to create the chain was provided" << endl;
1840 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1841 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1842 out << " return;" << endl;
1843 out << " }" << endl;
1844 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1845 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1848 out << "// read the analysis manager from file" << endl;
1849 TString analysisFile = fExecutable;
1850 analysisFile.ReplaceAll(".sh", ".root");
1851 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
1852 out << " if (!file) return;" << endl;
1853 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1854 out << " AliAnalysisManager *mgr = 0;" << endl;
1855 out << " TKey *key;" << endl;
1856 out << " while ((key=(TKey*)nextkey())) {" << endl;
1857 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1858 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1859 out << " };" << endl;
1860 out << " if (!mgr) {" << endl;
1861 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
1862 out << " return;" << endl;
1863 out << " }" << endl << endl;
1864 out << " mgr->PrintStatus();" << endl;
1865 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1866 out << " timer.Stop();" << endl;
1867 out << " timer.Print();" << endl;
1868 out << "}" << endl << endl;
1869 if (IsUsingTags()) {
1870 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1872 out << "// Create a chain using tags from the xml file." << endl;
1873 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1874 out << " if (!coll) {" << endl;
1875 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1876 out << " return NULL;" << endl;
1877 out << " }" << endl;
1878 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1879 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1880 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1881 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1882 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1883 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1884 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1885 out << " // Check if the cuts configuration file was provided" << endl;
1886 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1887 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1888 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1889 out << " }" << endl;
1890 if (fFriendChainName=="") {
1891 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1893 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1894 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1895 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1897 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1898 out << " chain->ls();" << endl;
1899 out << " return chain;" << endl;
1900 out << "}" << endl << endl;
1901 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1902 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1903 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1904 msg += " AliLHCTagCuts *lhcCuts,\n";
1905 msg += " AliDetectorTagCuts *detCuts,\n";
1906 msg += " AliEventTagCuts *evCuts)";
1907 Info("WriteAnalysisMacro", msg.Data());
1910 if (!IsUsingTags() || fFriendChainName!="") {
1911 out <<"//________________________________________________________________________________" << endl;
1912 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1914 out << "// Create a chain using url's from xml file" << endl;
1915 out << " TString treename = type;" << endl;
1916 out << " treename.ToLower();" << endl;
1917 out << " treename += \"Tree\";" << endl;
1918 out << " printf(\"***************************************\\n\");" << endl;
1919 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1920 out << " printf(\"***************************************\\n\");" << endl;
1921 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1922 out << " if (!coll) {" << endl;
1923 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1924 out << " return NULL;" << endl;
1925 out << " }" << endl;
1926 out << " TChain *chain = new TChain(treename);" << endl;
1927 if(fFriendChainName!="") {
1928 out << " TChain *chainFriend = new TChain(treename);" << endl;
1930 out << " coll->Reset();" << endl;
1931 out << " while (coll->Next()) {" << endl;
1932 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1933 if(fFriendChainName!="") {
1934 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1935 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1936 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1937 out << " chainFriend->Add(fileFriend.Data());" << endl;
1939 out << " }" << endl;
1940 out << " if (!chain->GetNtrees()) {" << endl;
1941 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1942 out << " return NULL;" << endl;
1943 out << " }" << endl;
1944 if(fFriendChainName!="") {
1945 out << " chain->AddFriend(chainFriend);" << endl;
1947 out << " return chain;" << endl;
1948 out << "}" << endl << endl;
1951 out <<"//________________________________________________________________________________" << endl;
1952 out << "Bool_t SetupPar(const char *package) {" << endl;
1953 out << "// Compile the package and set it up." << endl;
1954 out << " TString pkgdir = package;" << endl;
1955 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1956 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1957 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1958 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1959 out << " // Check for BUILD.sh and execute" << endl;
1960 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1961 out << " printf(\"*******************************\\n\");" << endl;
1962 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1963 out << " printf(\"*******************************\\n\");" << endl;
1964 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1965 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1966 out << " gSystem->ChangeDirectory(cdir);" << endl;
1967 out << " return kFALSE;" << endl;
1968 out << " }" << endl;
1969 out << " } else {" << endl;
1970 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1971 out << " gSystem->ChangeDirectory(cdir);" << endl;
1972 out << " return kFALSE;" << endl;
1973 out << " }" << endl;
1974 out << " // Check for SETUP.C and execute" << endl;
1975 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1976 out << " printf(\"*******************************\\n\");" << endl;
1977 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1978 out << " printf(\"*******************************\\n\");" << endl;
1979 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1980 out << " } else {" << endl;
1981 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
1982 out << " gSystem->ChangeDirectory(cdir);" << endl;
1983 out << " return kFALSE;" << endl;
1984 out << " }" << endl;
1985 out << " // Restore original workdir" << endl;
1986 out << " gSystem->ChangeDirectory(cdir);" << endl;
1987 out << " return kTRUE;" << endl;
1990 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1992 Bool_t copy = kTRUE;
1993 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1996 TString workdir = gGrid->GetHomeDirectory();
1997 workdir += fGridWorkingDir;
1998 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1999 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2000 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2001 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2002 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2004 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2005 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2009 //______________________________________________________________________________
2010 void AliAnalysisAlien::WriteExecutable()
2012 // Generate the alien executable script.
2013 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2015 out.open(fExecutable.Data(), ios::out);
2017 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2020 out << "#!/bin/bash" << endl;
2021 out << "echo \"=========================================\"" << endl;
2022 out << "echo \"############## PATH : ##############\"" << endl;
2023 out << "echo $PATH" << endl;
2024 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2025 out << "echo $LD_LIBRARY_PATH" << endl;
2026 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2027 out << "echo $ROOTSYS" << endl;
2028 out << "echo \"############## which root : ##############\"" << endl;
2029 out << "which root" << endl;
2030 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2031 out << "echo $ALICE_ROOT" << endl;
2032 out << "echo \"############## which aliroot : ##############\"" << endl;
2033 out << "which aliroot" << endl;
2034 out << "echo \"=========================================\"" << endl << endl;
2035 // Make sure we can properly compile par files
2036 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2037 out << fExecutableCommand << " ";
2038 out << fAnalysisMacro.Data() << endl << endl;
2039 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
2041 Bool_t copy = kTRUE;
2042 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2045 TString workdir = gGrid->GetHomeDirectory();
2046 TString bindir = Form("%s/bin", workdir.Data());
2047 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2048 workdir += fGridWorkingDir;
2049 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2050 if (FileExists(executable)) gGrid->Rm(executable);
2051 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2052 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2056 //______________________________________________________________________________
2057 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2059 // Write the production file to be submitted by LPM manager. The format is:
2060 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2061 // Next lines: full_path_to_dataset XXX (XXX is a string)
2062 // To submit, one has to: submit jdl XXX for all lines
2064 out.open(filename, ios::out);
2066 Error("WriteProductionFile", "Bad file name: %s", filename);
2069 TString workdir = gGrid->GetHomeDirectory();
2070 workdir += fGridWorkingDir;
2071 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2072 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2073 out << locjdl << " " << njobspermaster << endl;
2074 Int_t nmasterjobs = fInputFiles->GetEntries();
2075 for (Int_t i=0; i<nmasterjobs; i++) {
2076 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2078 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2079 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2082 //______________________________________________________________________________
2083 void AliAnalysisAlien::WriteValidationScript()
2085 // Generate the alien validation script.
2086 // Generate the validation script
2088 TString validationScript = fExecutable;
2089 validationScript.ReplaceAll(".sh", "_validation.sh");
2091 Error("WriteValidationScript", "Alien connection required");
2094 TString out_stream = "";
2095 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2096 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2098 out.open(validationScript, ios::out);
2099 out << "#!/bin/bash" << endl;
2100 out << "##################################################" << endl;
2101 out << "validateout=`dirname $0`" << endl;
2102 out << "validatetime=`date`" << endl;
2103 out << "validated=\"0\";" << endl;
2104 out << "error=0" << endl;
2105 out << "if [ -z $validateout ]" << endl;
2106 out << "then" << endl;
2107 out << " validateout=\".\"" << endl;
2108 out << "fi" << endl << endl;
2109 out << "cd $validateout;" << endl;
2110 out << "validateworkdir=`pwd`;" << endl << endl;
2111 out << "echo \"*******************************************************\"" << out_stream << endl;
2112 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2114 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2115 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2116 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2117 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2118 out << "ls -la ./" << out_stream << endl;
2119 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2120 out << "##################################################" << endl;
2123 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2124 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2125 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2128 out << "if [ ! -f stderr ] ; then" << endl;
2129 out << " error=1" << endl;
2130 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2131 out << " echo \"Error = $error\" " << out_stream << endl;
2132 out << "fi" << endl;
2134 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2135 out << " error=1" << endl;
2136 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2137 out << " echo \"$parArch\" " << out_stream << endl;
2138 out << " echo \"Error = $error\" " << out_stream << endl;
2139 out << "fi" << endl;
2141 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2142 out << " error=1" << endl;
2143 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2144 out << " echo \"$segViol\" " << out_stream << endl;
2145 out << " echo \"Error = $error\" " << out_stream << endl;
2146 out << "fi" << endl;
2148 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2149 out << " error=1" << endl;
2150 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2151 out << " echo \"$segFault\" " << out_stream << endl;
2152 out << " echo \"Error = $error\" " << out_stream << endl;
2153 out << "fi" << endl;
2155 // Part dedicated to the specific analyses running into the train
2157 TObjArray *arr = fOutputFiles.Tokenize(" ");
2159 TString output_file;
2160 while ((os=(TObjString*)next1())) {
2161 output_file = os->GetString();
2162 Int_t index = output_file.Index("@");
2163 if (index > 0) output_file.Remove(index);
2164 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2165 out << " error=1" << endl;
2166 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2167 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2168 out << "fi" << endl;
2171 out << "if ! [ -f outputs_valid ] ; then" << endl;
2172 out << " error=1" << endl;
2173 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2174 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2175 out << "fi" << endl;
2177 out << "if [ $error = 0 ] ; then" << endl;
2178 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2179 out << "fi" << endl;
2181 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2182 out << "echo \"*******************************************************\"" << out_stream << endl;
2183 out << "cd -" << endl;
2184 out << "exit $error" << endl;
2186 Bool_t copy = kTRUE;
2187 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2190 TString workdir = gGrid->GetHomeDirectory();
2191 workdir += fGridWorkingDir;
2192 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2193 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2194 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));