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),
89 //______________________________________________________________________________
90 AliAnalysisAlien::AliAnalysisAlien(const char *name)
91 :AliAnalysisGrid(name),
95 fSplitMaxInputFileNumber(0),
97 fMasterResubmitThreshold(0),
135 //______________________________________________________________________________
136 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
137 :AliAnalysisGrid(other),
139 fPrice(other.fPrice),
141 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
142 fMaxInitFailed(other.fMaxInitFailed),
143 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
144 fNtestFiles(other.fNtestFiles),
145 fNrunsPerMaster(other.fNrunsPerMaster),
146 fMaxMergeFiles(other.fMaxMergeFiles),
147 fNsubmitted(other.fNsubmitted),
148 fProductionMode(other.fProductionMode),
149 fRunNumbers(other.fRunNumbers),
150 fExecutable(other.fExecutable),
151 fArguments(other.fArguments),
152 fAnalysisMacro(other.fAnalysisMacro),
153 fAnalysisSource(other.fAnalysisSource),
154 fAdditionalLibs(other.fAdditionalLibs),
155 fSplitMode(other.fSplitMode),
156 fAPIVersion(other.fAPIVersion),
157 fROOTVersion(other.fROOTVersion),
158 fAliROOTVersion(other.fAliROOTVersion),
160 fGridWorkingDir(other.fGridWorkingDir),
161 fGridDataDir(other.fGridDataDir),
162 fDataPattern(other.fDataPattern),
163 fGridOutputDir(other.fGridOutputDir),
164 fOutputArchive(other.fOutputArchive),
165 fOutputFiles(other.fOutputFiles),
166 fInputFormat(other.fInputFormat),
167 fDatasetName(other.fDatasetName),
168 fJDLName(other.fJDLName),
169 fMergeExcludes(other.fMergeExcludes),
170 fIncludePath(other.fIncludePath),
171 fCloseSE(other.fCloseSE),
172 fFriendChainName(other.fFriendChainName),
173 fJobTag(other.fJobTag),
178 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
179 fRunRange[0] = other.fRunRange[0];
180 fRunRange[1] = other.fRunRange[1];
181 if (other.fInputFiles) {
182 fInputFiles = new TObjArray();
183 TIter next(other.fInputFiles);
185 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
186 fInputFiles->SetOwner();
188 if (other.fPackages) {
189 fPackages = new TObjArray();
190 TIter next(other.fPackages);
192 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
193 fPackages->SetOwner();
197 //______________________________________________________________________________
198 AliAnalysisAlien::~AliAnalysisAlien()
201 if (fGridJDL) delete fGridJDL;
202 if (fInputFiles) delete fInputFiles;
203 if (fPackages) delete fPackages;
206 //______________________________________________________________________________
207 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
210 if (this != &other) {
211 AliAnalysisGrid::operator=(other);
212 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
213 fPrice = other.fPrice;
215 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
216 fMaxInitFailed = other.fMaxInitFailed;
217 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
218 fNtestFiles = other.fNtestFiles;
219 fNrunsPerMaster = other.fNrunsPerMaster;
220 fMaxMergeFiles = other.fMaxMergeFiles;
221 fNsubmitted = other.fNsubmitted;
222 fProductionMode = other.fProductionMode;
223 fRunNumbers = other.fRunNumbers;
224 fExecutable = other.fExecutable;
225 fArguments = other.fArguments;
226 fAnalysisMacro = other.fAnalysisMacro;
227 fAnalysisSource = other.fAnalysisSource;
228 fAdditionalLibs = other.fAdditionalLibs;
229 fSplitMode = other.fSplitMode;
230 fAPIVersion = other.fAPIVersion;
231 fROOTVersion = other.fROOTVersion;
232 fAliROOTVersion = other.fAliROOTVersion;
234 fGridWorkingDir = other.fGridWorkingDir;
235 fGridDataDir = other.fGridDataDir;
236 fDataPattern = other.fDataPattern;
237 fGridOutputDir = other.fGridOutputDir;
238 fOutputArchive = other.fOutputArchive;
239 fOutputFiles = other.fOutputFiles;
240 fInputFormat = other.fInputFormat;
241 fDatasetName = other.fDatasetName;
242 fJDLName = other.fJDLName;
243 fMergeExcludes = other.fMergeExcludes;
244 fIncludePath = other.fIncludePath;
245 fCloseSE = other.fCloseSE;
246 fFriendChainName = other.fFriendChainName;
247 fJobTag = other.fJobTag;
248 if (other.fInputFiles) {
249 fInputFiles = new TObjArray();
250 TIter next(other.fInputFiles);
252 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
253 fInputFiles->SetOwner();
255 if (other.fPackages) {
256 fPackages = new TObjArray();
257 TIter next(other.fPackages);
259 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
260 fPackages->SetOwner();
266 //______________________________________________________________________________
267 void AliAnalysisAlien::AddIncludePath(const char *path)
269 // Add include path in the remote analysis macro.
271 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
272 else fIncludePath += Form("-I%s ", path);
275 //______________________________________________________________________________
276 void AliAnalysisAlien::AddRunNumber(Int_t run)
278 // Add a run number to the list of runs to be processed.
279 if (fRunNumbers.Length()) fRunNumbers += " ";
280 fRunNumbers += Form("%d", run);
283 //______________________________________________________________________________
284 void AliAnalysisAlien::AddDataFile(const char *lfn)
286 // Adds a data file to the input to be analysed. The file should be a valid LFN
287 // or point to an existing file in the alien workdir.
288 if (!fInputFiles) fInputFiles = new TObjArray();
289 fInputFiles->Add(new TObjString(lfn));
292 //______________________________________________________________________________
293 Bool_t AliAnalysisAlien::Connect()
295 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
296 if (gGrid && gGrid->IsConnected()) return kTRUE;
297 if (!gSystem->Getenv("alien_API_USER")) {
298 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
299 gSystem->Getenv("UID"));
303 Info("Connect", "Trying to connect to AliEn ...");
304 TGrid::Connect("alien://");
306 if (!gGrid || !gGrid->IsConnected()) {
307 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
310 fUser = gGrid->GetUser();
311 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
315 //______________________________________________________________________________
316 void AliAnalysisAlien::CdWork()
318 // Check validity of alien workspace. Create directory if possible.
320 Error("CdWork", "Alien connection required");
323 TString homedir = gGrid->GetHomeDirectory();
324 TString workdir = homedir + fGridWorkingDir;
325 if (!gGrid->Cd(workdir)) {
327 if (gGrid->Mkdir(workdir)) {
328 gGrid->Cd(fGridWorkingDir);
329 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
331 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
332 workdir.Data(), homedir.Data());
333 fGridWorkingDir = "";
338 //______________________________________________________________________________
339 Bool_t AliAnalysisAlien::CheckInputData()
341 // Check validity of input data. If necessary, create xml files.
342 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
343 if (!fGridDataDir.Length()) {
344 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
347 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
350 // Process declared files
351 Bool_t is_collection = kFALSE;
352 Bool_t is_xml = kFALSE;
353 Bool_t use_tags = kFALSE;
354 Bool_t checked = kFALSE;
357 TString workdir = gGrid->GetHomeDirectory();
358 workdir += fGridWorkingDir;
361 TIter next(fInputFiles);
362 while ((objstr=(TObjString*)next())) {
365 file += objstr->GetString();
366 // Store full lfn path
367 if (FileExists(file)) objstr->SetString(file);
369 file = objstr->GetName();
370 if (!FileExists(objstr->GetName())) {
371 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
372 objstr->GetName(), workdir.Data());
376 Bool_t iscoll, isxml, usetags;
377 CheckDataType(file, iscoll, isxml, usetags);
380 is_collection = iscoll;
383 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
385 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
386 Error("CheckInputData", "Some conflict was found in the types of inputs");
392 // Process requested run numbers
393 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
394 // Check validity of alien data directory
395 if (!fGridDataDir.Length()) {
396 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
399 if (!gGrid->Cd(fGridDataDir)) {
400 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
404 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
408 if (checked && !is_xml) {
409 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
412 // Check validity of run number(s)
420 use_tags = fDataPattern.Contains("tag");
421 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
423 if (use_tags != fDataPattern.Contains("tag")) {
424 Error("CheckInputData", "Cannot mix input files using/not using tags");
427 if (fRunNumbers.Length()) {
428 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
429 arr = fRunNumbers.Tokenize(" ");
431 while ((os=(TObjString*)next())) {
432 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
433 if (!gGrid->Cd(path)) {
434 Warning("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
437 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
438 TString msg = "\n##### file: ";
440 msg += " type: xml_collection;";
441 if (use_tags) msg += " using_tags: Yes";
442 else msg += " using_tags: No";
443 Info("CheckDataType", msg.Data());
444 if (fNrunsPerMaster<2) {
445 AddDataFile(Form("%s.xml", os->GetString().Data()));
448 if (((nruns-1)%fNrunsPerMaster) == 0) {
449 schunk = os->GetString();
451 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
452 schunk += Form("_%s.xml", os->GetString().Data());
458 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
459 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
460 path = Form("%s/%d ", fGridDataDir.Data(), irun);
461 if (!gGrid->Cd(path)) {
462 Warning("CheckInputData", "Run number %d not found in path: %s", irun, path.Data());
465 path = Form("%s/%d.xml", workdir.Data(),irun);
466 TString msg = "\n##### file: ";
468 msg += " type: xml_collection;";
469 if (use_tags) msg += " using_tags: Yes";
470 else msg += " using_tags: No";
471 Info("CheckDataType", msg.Data());
472 if (fNrunsPerMaster<2) {
473 AddDataFile(Form("%d.xml",irun));
476 if (((nruns-1)%fNrunsPerMaster) == 0) {
477 schunk = Form("%d", irun);
479 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
480 schunk += Form("_%d.xml", irun);
488 //______________________________________________________________________________
489 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
491 // Create dataset for the grid data directory + run number.
492 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
494 Error("CreateDataset", "Cannot create dataset with no grid connection");
500 TString workdir = gGrid->GetHomeDirectory();
501 workdir += fGridWorkingDir;
503 // Compose the 'find' command arguments
505 TString options = "-x collection ";
506 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
507 TString conditions = "";
513 TGridCollection *cbase=0, *cadd=0;
514 if (!fRunNumbers.Length() && !fRunRange[0]) {
515 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
516 // Make a single data collection from data directory.
518 if (!gGrid->Cd(path)) {
519 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
523 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
524 else file = Form("%s.xml", gSystem->BaseName(path));
525 if (gSystem->AccessPathName(file)) {
531 command += conditions;
532 printf("command: %s\n", command.Data());
533 TGridResult *res = gGrid->Command(command);
535 // Write standard output to file
536 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
538 if (!TestBit(AliAnalysisGrid::kTest) && !FileExists(file)) {
539 // Copy xml file to alien space
540 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
541 if (!FileExists(file)) {
542 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
545 // Update list of files to be processed.
547 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
551 if (fRunNumbers.Length()) {
552 TObjArray *arr = fRunNumbers.Tokenize(" ");
555 while ((os=(TObjString*)next())) {
556 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
557 if (!gGrid->Cd(path)) continue;
559 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
560 else file = Form("%s.xml", os->GetString().Data());
561 // If local collection file does not exist, create it via 'find' command.
562 if (gSystem->AccessPathName(file)) {
567 command += conditions;
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)) break;
574 // Check if there is one run per master job.
575 if (fNrunsPerMaster<2) {
576 if (FileExists(file)) {
577 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
580 // Copy xml file to alien space
581 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
582 if (!FileExists(file)) {
583 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
589 if (((nruns-1)%fNrunsPerMaster) == 0) {
590 schunk = os->GetString();
591 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
593 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
594 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
598 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
601 schunk += Form("_%s.xml", os->GetString().Data());
602 if (FileExists(schunk)) {
603 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
606 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
607 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
608 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
609 if (!FileExists(schunk)) {
610 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
618 // Process a full run range.
619 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
620 path = Form("%s/%d ", fGridDataDir.Data(), irun);
621 if (!gGrid->Cd(path)) continue;
623 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
624 else file = Form("%d.xml", irun);
625 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
626 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
630 // If local collection file does not exist, create it via 'find' command.
631 if (gSystem->AccessPathName(file)) {
636 command += conditions;
637 TGridResult *res = gGrid->Command(command);
639 // Write standard output to file
640 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
642 if (TestBit(AliAnalysisGrid::kTest)) break;
643 // Check if there is one run per master job.
644 if (fNrunsPerMaster<2) {
645 if (FileExists(file)) {
646 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
649 // Copy xml file to alien space
650 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
651 if (!FileExists(file)) {
652 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
657 // Check if the collection for the chunk exist locally.
658 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
659 if (FileExists(fInputFiles->At(nchunk)->GetName())) continue;
660 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
661 if (((nruns-1)%fNrunsPerMaster) == 0) {
662 schunk = Form("%d", irun);
663 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
665 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
669 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1]) {
672 schunk += Form("_%d.xml", irun);
673 if (FileExists(schunk)) {
674 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
677 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
678 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
679 if (FileExists(schunk)) {
680 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
683 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
684 if (!FileExists(schunk)) {
685 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
694 //______________________________________________________________________________
695 Bool_t AliAnalysisAlien::CreateJDL()
697 // Generate a JDL file according to current settings. The name of the file is
698 // specified by fJDLName.
699 Bool_t error = kFALSE;
702 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
703 Bool_t generate = kTRUE;
704 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
706 Error("CreateJDL", "Alien connection required");
709 // Check validity of alien workspace
711 TString workdir = gGrid->GetHomeDirectory();
712 workdir += fGridWorkingDir;
716 Error("CreateJDL()", "Define some input files for your analysis.");
719 // Compose list of input files
720 // Check if output files were defined
721 if (!fOutputFiles.Length()) {
722 Error("CreateJDL", "You must define at least one output file");
725 // Check if an output directory was defined and valid
726 if (!fGridOutputDir.Length()) {
727 Error("CreateJDL", "You must define AliEn output directory");
730 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
731 if (!gGrid->Cd(fGridOutputDir)) {
732 if (gGrid->Mkdir(fGridOutputDir)) {
733 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
735 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
741 // Exit if any error up to now
742 if (error) return kFALSE;
744 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
745 fGridJDL->SetExecutable(fExecutable);
746 // fGridJDL->SetTTL((UInt_t)fTTL);
747 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
748 if (fMaxInitFailed > 0)
749 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
750 if (fSplitMaxInputFileNumber > 0)
751 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
752 if (fSplitMode.Length())
753 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
754 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
755 if (fAliROOTVersion.Length())
756 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
757 if (fROOTVersion.Length())
758 fGridJDL->AddToPackages("ROOT", fROOTVersion);
759 if (fAPIVersion.Length())
760 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
761 fGridJDL->SetInputDataListFormat(fInputFormat);
762 fGridJDL->SetInputDataList("wn.xml");
763 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
764 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
765 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
766 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
767 if (fAdditionalLibs.Length()) {
768 arr = fAdditionalLibs.Tokenize(" ");
770 while ((os=(TObjString*)next())) {
771 if (os->GetString().Contains(".so")) continue;
772 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
777 TIter next(fPackages);
780 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
782 if (fOutputArchive.Length()) {
783 arr = fOutputArchive.Tokenize(" ");
785 while ((os=(TObjString*)next()))
786 if (!os->GetString().Contains("@") && fCloseSE.Length())
787 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
789 fGridJDL->AddToOutputArchive(os->GetString());
792 arr = fOutputFiles.Tokenize(" ");
794 while ((os=(TObjString*)next())) {
795 if (!os->GetString().Contains("@") && fCloseSE.Length())
796 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
798 fGridJDL->AddToOutputSandbox(os->GetString());
801 // fGridJDL->SetPrice((UInt_t)fPrice);
802 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
803 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
804 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
805 // Write a jdl with 2 input parameters: collection name and output dir name.
808 // Copy jdl to grid workspace
810 if (fAdditionalLibs.Length()) {
811 arr = fAdditionalLibs.Tokenize(" ");
814 while ((os=(TObjString*)next())) {
815 if (os->GetString().Contains(".so")) continue;
816 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
817 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
818 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
823 TIter next(fPackages);
825 while ((obj=next())) {
826 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
827 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
834 //______________________________________________________________________________
835 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
837 // Writes one or more JDL's corresponding to findex. If findex is negative,
838 // all run numbers are considered in one go (jdl). For non-negative indices
839 // they correspond to the indices in the array fInputFiles.
840 if (!fInputFiles) return kFALSE;
842 TString workdir = gGrid->GetHomeDirectory();
843 workdir += fGridWorkingDir;
845 if (!fRunNumbers.Length() && !fRunRange[0]) {
846 // One jdl with no parameters in case input data is specified by name.
847 TIter next(fInputFiles);
848 while ((os=(TObjString*)next()))
849 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
850 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
852 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
853 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
854 fGridJDL->SetOutputDirectory(Form("%s/$2#alien_counter_03i#", fGridOutputDir.Data()));
858 // Generate the JDL as a string
859 TString sjdl = fGridJDL->Generate();
861 index = sjdl.Index("Executable");
862 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
863 index = sjdl.Index("Split ");
864 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
865 index = sjdl.Index("SplitMaxInputFileNumber");
866 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
867 index = sjdl.Index("InputDataCollection");
868 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
869 index = sjdl.Index("InputFile");
870 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
871 index = sjdl.Index("InputDataList ");
872 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
873 index = sjdl.Index("InputDataListFormat");
874 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
875 index = sjdl.Index("Price");
876 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
877 index = sjdl.Index("Requirements");
878 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
879 index = sjdl.Index("Packages");
880 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
881 index = sjdl.Index("User =");
882 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
883 index = sjdl.Index("TTL");
884 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
885 index = sjdl.Index("OutputFile");
886 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
887 index = sjdl.Index("OutputDir");
888 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
889 index = sjdl.Index("OutputArchive");
890 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
891 index = sjdl.Index("MaxInitFailed");
892 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
893 index = sjdl.Index("MasterResubmitThreshold");
894 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
895 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
896 index = sjdl.Index("Validationcommand");
897 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
898 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
899 sjdl.ReplaceAll("(member", "\n (member");
900 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
901 sjdl.ReplaceAll("{", "{\n ");
902 sjdl.ReplaceAll("};", "\n};");
903 sjdl.ReplaceAll("{\n \n", "{\n");
904 sjdl.ReplaceAll("\n\n", "\n");
905 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
906 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
907 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\";\n}\n", fJobTag.Data()));
908 index = sjdl.Index("JDLVariables");
909 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
912 out.open(fJDLName.Data(), ios::out);
914 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
919 // Copy jdl to grid workspace
921 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
923 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
924 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
926 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
927 if (FileExists(locjdl)) gGrid->Rm(locjdl);
928 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
933 //______________________________________________________________________________
934 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
936 // Returns true if file exists.
937 if (!gGrid) return kFALSE;
938 TGridResult *res = gGrid->Ls(lfn);
939 if (!res) return kFALSE;
940 TMap *map = dynamic_cast<TMap*>(res->At(0));
945 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
946 if (!objs || !objs->GetString().Length()) {
954 //______________________________________________________________________________
955 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
957 // Check input data type.
958 is_collection = kFALSE;
962 Error("CheckDataType", "No connection to grid");
965 is_collection = IsCollection(lfn);
966 TString msg = "\n##### file: ";
969 msg += " type: raw_collection;";
970 // special treatment for collections
972 // check for tag files in the collection
973 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
975 msg += " using_tags: No (unknown)";
976 Info("CheckDataType", msg.Data());
979 const char* typeStr = res->GetKey(0, "origLFN");
980 if (!typeStr || !strlen(typeStr)) {
981 msg += " using_tags: No (unknown)";
982 Info("CheckDataType", msg.Data());
985 TString file = typeStr;
986 use_tags = file.Contains(".tag");
987 if (use_tags) msg += " using_tags: Yes";
988 else msg += " using_tags: No";
989 Info("CheckDataType", msg.Data());
994 is_xml = slfn.Contains(".xml");
996 // Open xml collection and check if there are tag files inside
997 msg += " type: xml_collection;";
998 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1000 msg += " using_tags: No (unknown)";
1001 Info("CheckDataType", msg.Data());
1004 TMap *map = coll->Next();
1006 msg += " using_tags: No (unknown)";
1007 Info("CheckDataType", msg.Data());
1010 map = (TMap*)map->GetValue("");
1012 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1013 use_tags = file.Contains(".tag");
1015 if (use_tags) msg += " using_tags: Yes";
1016 else msg += " using_tags: No";
1017 Info("CheckDataType", msg.Data());
1020 use_tags = slfn.Contains(".tag");
1021 if (slfn.Contains(".root")) msg += " type: root file;";
1022 else msg += " type: unhnown file;";
1023 if (use_tags) msg += " using_tags: Yes";
1024 else msg += " using_tags: No";
1025 Info("CheckDataType", msg.Data());
1028 //______________________________________________________________________________
1029 void AliAnalysisAlien::EnablePackage(const char *package)
1031 // Enables a par file supposed to exist in the current directory.
1032 TString pkg(package);
1033 pkg.ReplaceAll(".par", "");
1035 if (gSystem->AccessPathName(pkg)) {
1036 Error("EnablePackage", "Package %s not found", pkg.Data());
1039 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1040 Info("EnablePackage", "AliEn plugin will use .par packages");
1041 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1043 fPackages = new TObjArray();
1044 fPackages->SetOwner();
1046 fPackages->Add(new TObjString(pkg));
1049 //______________________________________________________________________________
1050 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1052 // Get job status for all jobs with jobid>jobidstart.
1053 static char mstatus[20];
1059 TGridJobStatusList *list = gGrid->Ps("");
1060 if (!list) return mstatus;
1061 Int_t nentries = list->GetSize();
1062 TGridJobStatus *status;
1064 for (Int_t ijob=0; ijob<nentries; ijob++) {
1065 status = (TGridJobStatus *)list->At(ijob);
1066 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1067 if (pid<jobidstart) continue;
1068 if (pid == lastid) {
1069 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1071 switch (status->GetStatus()) {
1072 case TGridJobStatus::kWAITING:
1074 case TGridJobStatus::kRUNNING:
1076 case TGridJobStatus::kABORTED:
1077 case TGridJobStatus::kFAIL:
1078 case TGridJobStatus::kUNKNOWN:
1080 case TGridJobStatus::kDONE:
1089 //______________________________________________________________________________
1090 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1092 // Returns true if file is a collection. Functionality duplicated from
1093 // TAlien::Type() because we don't want to directly depend on TAlien.
1095 Error("IsCollection", "No connection to grid");
1098 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1099 if (!res) return kFALSE;
1100 const char* typeStr = res->GetKey(0, "type");
1101 if (!typeStr || !strlen(typeStr)) return kFALSE;
1102 if (!strcmp(typeStr, "collection")) return kTRUE;
1107 //______________________________________________________________________________
1108 void AliAnalysisAlien::Print(Option_t *) const
1110 // Print current plugin settings.
1111 printf("### AliEn analysis plugin current settings ###\n");
1112 printf("= Production mode:______________________________ %d\n", fProductionMode);
1113 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1114 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1115 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1117 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1118 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1119 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1120 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1121 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1122 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1123 if (fRunNumbers.Length())
1124 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1126 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1127 if (!fRunRange[0] && !fRunNumbers.Length()) {
1128 TIter next(fInputFiles);
1131 while ((obj=next())) list += obj->GetName();
1132 printf("= Input files to be processed: _________________ %s\n", list.Data());
1134 if (TestBit(AliAnalysisGrid::kTest))
1135 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1136 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1137 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1138 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1139 printf("=====================================================================\n");
1140 printf("= Job price: ___________________________________ %d\n", fPrice);
1141 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1142 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1143 if (fMaxInitFailed>0)
1144 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1145 if (fMasterResubmitThreshold>0)
1146 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1147 if (fNrunsPerMaster>0)
1148 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1149 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1150 printf("= Name of the generated execution script: ______ %s\n",fExecutable.Data());
1151 if (fArguments.Length())
1152 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1153 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1154 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1155 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1156 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1158 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1159 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1160 if (fIncludePath.Data())
1161 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1162 if (fCloseSE.Length())
1163 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1164 if (fFriendChainName.Length())
1165 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1167 TIter next(fPackages);
1170 while ((obj=next())) list += obj->GetName();
1171 printf("= Par files to be used: ________________________ %s\n", list.Data());
1175 //______________________________________________________________________________
1176 void AliAnalysisAlien::SetDefaults()
1178 // Set default values for everything. What cannot be filled will be left empty.
1179 if (fGridJDL) delete fGridJDL;
1180 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1183 fSplitMaxInputFileNumber = 100;
1185 fMasterResubmitThreshold = 0;
1189 fNrunsPerMaster = 1;
1190 fMaxMergeFiles = 100;
1192 fExecutable = "analysis.sh";
1194 fAnalysisMacro = "myAnalysis.C";
1195 fAnalysisSource = "";
1196 fAdditionalLibs = "";
1200 fAliROOTVersion = "";
1201 fUser = ""; // Your alien user name
1202 fGridWorkingDir = "";
1203 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1204 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1205 fFriendChainName = "";
1206 fGridOutputDir = "output";
1207 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1208 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1209 fInputFormat = "xml-single";
1210 fJDLName = "analysis.jdl";
1211 fJobTag = "Automatically generated analysis JDL";
1212 fMergeExcludes = "";
1215 //______________________________________________________________________________
1216 Bool_t AliAnalysisAlien::MergeOutputs()
1218 // Merge analysis outputs existing in the AliEn space.
1219 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1220 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1222 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1225 // Get the output path
1226 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1227 if (!gGrid->Cd(fGridOutputDir)) {
1228 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1231 if (!fOutputFiles.Length()) {
1232 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1235 TObjArray *list = fOutputFiles.Tokenize(" ");
1239 TString output_file;
1240 TString output_chunk;
1241 TString previous_chunk;
1242 Int_t count_chunk = 0;
1243 Int_t count_zero = fMaxMergeFiles;
1244 Bool_t merged = kTRUE;
1245 while((str=(TObjString*)next())) {
1246 output_file = str->GetString();
1247 Int_t index = output_file.Index("@");
1248 if (index > 0) output_file.Remove(index);
1249 // Skip already merged outputs
1250 if (!gSystem->AccessPathName(output_file)) {
1251 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1254 if (fMergeExcludes.Length() &&
1255 fMergeExcludes.Contains(output_file.Data())) continue;
1256 // Perform a 'find' command in the output directory, looking for registered outputs
1257 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
1258 printf("command: %s\n", command.Data());
1259 TGridResult *res = gGrid->Command(command);
1261 TFileMerger *fm = 0;
1264 previous_chunk = "";
1266 // Check if there is a merge operation to resume
1267 output_chunk = output_file;
1268 output_chunk.ReplaceAll(".root", "_*.root");
1269 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1271 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1273 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1277 output_chunk = output_file;
1278 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1279 printf("%s\n", output_chunk.Data());
1281 if (gSystem->AccessPathName(output_chunk)) continue;
1282 // Merged file with chunks up to <count_chunk> found
1283 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1284 previous_chunk = output_chunk;
1288 count_zero = fMaxMergeFiles;
1289 while ((map=(TMap*)nextmap())) {
1290 // Loop 'find' results and get next LFN
1291 if (count_zero == fMaxMergeFiles) {
1292 // First file in chunk - create file merger and add previous chunk if any.
1293 fm = new TFileMerger(kFALSE);
1294 fm->SetFastMethod(kTRUE);
1295 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1296 output_chunk = output_file;
1297 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1299 // If last file found, put merged results in the output file
1300 if (map == res->Last()) output_chunk = output_file;
1301 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1302 if (!objs || !objs->GetString().Length()) {
1303 // Nothing found - skip this output
1308 // Add file to be merged and decrement chunk counter.
1309 fm->AddFile(objs->GetString());
1311 if (count_zero==0 || map == res->Last()) {
1312 fm->OutputFile(output_chunk);
1313 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1314 // Nothing found - skip this output
1315 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1320 // Merge the outputs, then go to next chunk
1322 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1328 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1329 gSystem->Unlink(previous_chunk);
1331 if (map == res->Last()) {
1337 count_zero = fMaxMergeFiles;
1338 previous_chunk = output_chunk;
1343 Error("MergeOutputs", "Terminate() will NOT be executed");
1348 //______________________________________________________________________________
1349 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1351 // Use the output files connected to output containers from the analysis manager
1352 // rather than the files defined by SetOutputFiles
1353 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1354 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1356 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1359 //______________________________________________________________________________
1360 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1362 // Start remote grid analysis.
1364 // Check if output files have to be taken from the analysis manager
1365 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1366 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1367 if (!mgr || !mgr->IsInitialized()) {
1368 Error("StartAnalysis", "You need an initialized analysis manager for this");
1372 TIter next(mgr->GetOutputs());
1373 AliAnalysisDataContainer *output;
1374 while ((output=(AliAnalysisDataContainer*)next())) {
1375 const char *filename = output->GetFileName();
1376 if (!(strcmp(filename, "default"))) {
1377 if (!mgr->GetOutputEventHandler()) continue;
1378 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1380 if (fOutputFiles.Length()) fOutputFiles += " ";
1381 fOutputFiles += filename;
1383 // Add extra files registered to the analysis manager
1384 if (mgr->GetExtraFiles().Length()) {
1385 if (fOutputFiles.Length()) fOutputFiles += " ";
1386 fOutputFiles += mgr->GetExtraFiles();
1389 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1390 if (TestBit(AliAnalysisGrid::kOffline)) {
1391 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1392 \n there nor any job run. You can revise the JDL and analysis \
1393 \n macro then run the same in \"submit\" mode.");
1394 } else if (TestBit(AliAnalysisGrid::kTest)) {
1395 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1397 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1398 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1399 \n space and job submitted.");
1400 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1401 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1404 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1408 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1412 if (!CheckInputData()) {
1413 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1416 CreateDataset(fDataPattern);
1417 WriteAnalysisFile();
1418 WriteAnalysisMacro();
1420 WriteValidationScript();
1421 if (!CreateJDL()) return kFALSE;
1422 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1423 if (TestBit(AliAnalysisGrid::kTest)) {
1424 // Locally testing the analysis
1425 Info("StartAnalysis", "\n_______________________________________________________________________ \
1426 \n Running analysis script in a daughter shell as on a worker node \
1427 \n_______________________________________________________________________");
1428 TObjArray *list = fOutputFiles.Tokenize(" ");
1431 TString output_file;
1432 while((str=(TObjString*)next())) {
1433 output_file = str->GetString();
1434 Int_t index = output_file.Index("@");
1435 if (index > 0) output_file.Remove(index);
1436 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1439 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1440 gSystem->Exec("bash validate.sh");
1441 // gSystem->Exec("cat stdout");
1444 // Check if submitting is managed by LPM manager
1445 if (fProductionMode) {
1446 TString prodfile = fJDLName;
1447 prodfile.ReplaceAll(".jdl", ".prod");
1448 WriteProductionFile(prodfile);
1449 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1452 // Submit AliEn job(s)
1453 gGrid->Cd(fGridOutputDir);
1456 if (!fRunNumbers.Length() && !fRunRange[0]) {
1457 // Submit a given xml or a set of runs
1458 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1459 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1461 const char *cjobId = res->GetKey(0,"jobId");
1463 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1466 Info("StartAnalysis", "\n_______________________________________________________________________ \
1467 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1468 \n_______________________________________________________________________",
1469 fJDLName.Data(), cjobId);
1475 // Submit for a range of enumeration of runs.
1479 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1480 \n You may exit at any time and terminate the job later using the option <terminate> \
1481 \n ##################################################################################", jobID.Data());
1482 gSystem->Exec("aliensh");
1486 //______________________________________________________________________________
1487 void AliAnalysisAlien::Submit()
1489 // Submit all master jobs.
1490 Int_t nmasterjobs = fInputFiles->GetEntries();
1491 Long_t tshoot = gSystem->Now();
1492 if (!fNsubmitted) SubmitNext();
1493 while (fNsubmitted < nmasterjobs) {
1494 Long_t now = gSystem->Now();
1495 if ((now-tshoot)>30000) {
1502 //______________________________________________________________________________
1503 void AliAnalysisAlien::SubmitNext()
1505 // Submit next bunch of master jobs if the queue is free.
1506 static Bool_t iscalled = kFALSE;
1507 static Int_t firstmaster = 0;
1508 static Int_t lastmaster = 0;
1509 static Int_t npermaster = 0;
1510 if (iscalled) return;
1512 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1513 Int_t ntosubmit = 0;
1516 if (!fNsubmitted) ntosubmit = 1;
1518 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1519 printf("=== master %d: %s\n", lastmaster, status.Data());
1520 // If last master not split, just return
1521 if (status != "SPLIT") {iscalled = kFALSE; return;}
1522 // No more than 100 waiting jobs
1523 if (nwaiting>100) {iscalled = kFALSE; return;}
1524 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1525 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1526 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1527 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1529 Int_t nmasterjobs = fInputFiles->GetEntries();
1530 for (Int_t i=0; i<ntosubmit; i++) {
1531 // Submit for a range of enumeration of runs.
1532 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1534 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1535 printf("********* %s\n",query.Data());
1536 res = gGrid->Command(query);
1538 TString cjobId1 = res->GetKey(0,"jobId");
1539 if (!cjobId1.Length()) {
1540 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1544 Info("StartAnalysis", "\n_______________________________________________________________________ \
1545 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1546 \n_______________________________________________________________________",
1547 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1550 lastmaster = cjobId1.Atoi();
1551 if (!firstmaster) firstmaster = lastmaster;
1560 //______________________________________________________________________________
1561 void AliAnalysisAlien::WriteAnalysisFile()
1563 // Write current analysis manager into the file analysis.root
1564 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1565 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1566 if (!mgr || !mgr->IsInitialized()) {
1567 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1570 // Check analysis type
1572 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1573 handler = (TObject*)mgr->GetInputEventHandler();
1575 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1576 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1578 TDirectory *cdir = gDirectory;
1579 TFile *file = TFile::Open("analysis.root", "RECREATE");
1584 if (cdir) cdir->cd();
1585 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1587 Bool_t copy = kTRUE;
1588 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1591 TString workdir = gGrid->GetHomeDirectory();
1592 workdir += fGridWorkingDir;
1593 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1594 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1595 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1599 //______________________________________________________________________________
1600 void AliAnalysisAlien::WriteAnalysisMacro()
1602 // Write the analysis macro that will steer the analysis in grid mode.
1603 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1605 out.open(fAnalysisMacro.Data(), ios::out);
1607 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1610 TString func = fAnalysisMacro;
1611 TString type = "ESD";
1612 TString comment = "// Analysis using ";
1613 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1614 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1618 if (type!="AOD" && fFriendChainName!="") {
1619 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1622 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1623 else comment += " data";
1624 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1625 func.ReplaceAll(".C", "");
1626 out << "void " << func.Data() << "()" << endl;
1628 out << comment.Data() << endl;
1629 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1630 out << " TStopwatch timer;" << endl;
1631 out << " timer.Start();" << endl << endl;
1632 out << "// load base root libraries" << endl;
1633 out << " gSystem->Load(\"libTree\");" << endl;
1634 out << " gSystem->Load(\"libGeom\");" << endl;
1635 out << " gSystem->Load(\"libVMC\");" << endl;
1636 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1637 out << "// Load analysis framework libraries" << endl;
1639 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1640 out << " gSystem->Load(\"libESD\");" << endl;
1641 out << " gSystem->Load(\"libAOD\");" << endl;
1642 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1643 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1644 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1646 TIter next(fPackages);
1649 Bool_t hasSTEERBase = kFALSE;
1650 Bool_t hasESD = kFALSE;
1651 Bool_t hasAOD = kFALSE;
1652 Bool_t hasANALYSIS = kFALSE;
1653 Bool_t hasANALYSISalice = kFALSE;
1654 Bool_t hasCORRFW = kFALSE;
1655 while ((obj=next())) {
1656 pkgname = obj->GetName();
1657 if (pkgname == "STEERBase" ||
1658 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1659 if (pkgname == "ESD" ||
1660 pkgname == "ESD.par") hasESD = kTRUE;
1661 if (pkgname == "AOD" ||
1662 pkgname == "AOD.par") hasAOD = kTRUE;
1663 if (pkgname == "ANALYSIS" ||
1664 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1665 if (pkgname == "ANALYSISalice" ||
1666 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1667 if (pkgname == "CORRFW" ||
1668 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1670 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1671 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1672 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1673 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1674 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1675 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1676 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1677 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1678 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1679 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1680 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1681 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1682 out << "// Compile other par packages" << endl;
1684 while ((obj=next())) {
1685 pkgname = obj->GetName();
1686 if (pkgname == "STEERBase" ||
1687 pkgname == "STEERBase.par" ||
1689 pkgname == "ESD.par" ||
1691 pkgname == "AOD.par" ||
1692 pkgname == "ANALYSIS" ||
1693 pkgname == "ANALYSIS.par" ||
1694 pkgname == "ANALYSISalice" ||
1695 pkgname == "ANALYSISalice.par" ||
1696 pkgname == "CORRFW" ||
1697 pkgname == "CORRFW.par") continue;
1698 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1701 out << "// include path" << endl;
1702 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1703 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1704 if (fAdditionalLibs.Length()) {
1705 out << "// Add aditional AliRoot libraries" << endl;
1706 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1709 while((str=(TObjString*)next())) {
1710 if (str->GetString().Contains(".so"))
1711 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1713 if (list) delete list;
1716 out << "// analysis source to be compiled at runtime (if any)" << endl;
1717 if (fAnalysisSource.Length()) {
1718 TObjArray *list = fAnalysisSource.Tokenize(" ");
1721 while((str=(TObjString*)next())) {
1722 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1724 if (list) delete list;
1727 out << "// connect to AliEn and make the chain" << endl;
1728 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1729 if (IsUsingTags()) {
1730 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1732 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1733 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1735 out << " // Check if the macro to create the chain was provided" << endl;
1736 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1737 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1738 out << " return;" << endl;
1739 out << " }" << endl;
1740 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1741 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1744 out << "// read the analysis manager from file" << endl;
1745 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1746 out << " if (!file) return;" << endl;
1747 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1748 out << " AliAnalysisManager *mgr = 0;" << endl;
1749 out << " TKey *key;" << endl;
1750 out << " while ((key=(TKey*)nextkey())) {" << endl;
1751 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1752 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1753 out << " };" << endl;
1754 out << " if (!mgr) {" << endl;
1755 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1756 out << " return;" << endl;
1757 out << " }" << endl << endl;
1758 out << " mgr->PrintStatus();" << endl;
1759 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1760 out << " timer.Stop();" << endl;
1761 out << " timer.Print();" << endl;
1762 out << "}" << endl << endl;
1763 if (IsUsingTags()) {
1764 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1766 out << "// Create a chain using tags from the xml file." << endl;
1767 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1768 out << " if (!coll) {" << endl;
1769 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1770 out << " return NULL;" << endl;
1771 out << " }" << endl;
1772 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1773 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1774 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1775 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1776 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1777 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1778 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1779 out << " // Check if the cuts configuration file was provided" << endl;
1780 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1781 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1782 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1783 out << " }" << endl;
1784 if (fFriendChainName=="") {
1785 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1787 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1788 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1789 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1791 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1792 out << " chain->ls();" << endl;
1793 out << " return chain;" << endl;
1794 out << "}" << endl << endl;
1795 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1796 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1797 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1798 msg += " AliLHCTagCuts *lhcCuts,\n";
1799 msg += " AliDetectorTagCuts *detCuts,\n";
1800 msg += " AliEventTagCuts *evCuts)";
1801 Info("WriteAnalysisMacro", msg.Data());
1804 if (!IsUsingTags() || fFriendChainName!="") {
1805 out <<"//________________________________________________________________________________" << endl;
1806 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1808 out << "// Create a chain using url's from xml file" << endl;
1809 out << " TString treename = type;" << endl;
1810 out << " treename.ToLower();" << endl;
1811 out << " treename += \"Tree\";" << endl;
1812 out << " printf(\"***************************************\\n\");" << endl;
1813 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1814 out << " printf(\"***************************************\\n\");" << endl;
1815 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1816 out << " if (!coll) {" << endl;
1817 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1818 out << " return NULL;" << endl;
1819 out << " }" << endl;
1820 out << " TChain *chain = new TChain(treename);" << endl;
1821 if(fFriendChainName!="") {
1822 out << " TChain *chainFriend = new TChain(treename);" << endl;
1824 out << " coll->Reset();" << endl;
1825 out << " while (coll->Next()) {" << endl;
1826 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1827 if(fFriendChainName!="") {
1828 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1829 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1830 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1831 out << " chainFriend->Add(fileFriend.Data());" << endl;
1833 out << " }" << endl;
1834 out << " if (!chain->GetNtrees()) {" << endl;
1835 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1836 out << " return NULL;" << endl;
1837 out << " }" << endl;
1838 if(fFriendChainName!="") {
1839 out << " chain->AddFriend(chainFriend);" << endl;
1841 out << " return chain;" << endl;
1842 out << "}" << endl << endl;
1845 out <<"//________________________________________________________________________________" << endl;
1846 out << "Bool_t SetupPar(const char *package) {" << endl;
1847 out << "// Compile the package and set it up." << endl;
1848 out << " TString pkgdir = package;" << endl;
1849 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1850 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1851 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1852 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1853 out << " // Check for BUILD.sh and execute" << endl;
1854 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1855 out << " printf(\"*******************************\\n\");" << endl;
1856 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1857 out << " printf(\"*******************************\\n\");" << endl;
1858 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1859 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1860 out << " gSystem->ChangeDirectory(cdir);" << endl;
1861 out << " return kFALSE;" << endl;
1862 out << " }" << endl;
1863 out << " } else {" << endl;
1864 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1865 out << " gSystem->ChangeDirectory(cdir);" << endl;
1866 out << " return kFALSE;" << endl;
1867 out << " }" << endl;
1868 out << " // Check for SETUP.C and execute" << endl;
1869 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1870 out << " printf(\"*******************************\\n\");" << endl;
1871 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1872 out << " printf(\"*******************************\\n\");" << endl;
1873 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1874 out << " } else {" << endl;
1875 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
1876 out << " gSystem->ChangeDirectory(cdir);" << endl;
1877 out << " return kFALSE;" << endl;
1878 out << " }" << endl;
1879 out << " // Restore original workdir" << endl;
1880 out << " gSystem->ChangeDirectory(cdir);" << endl;
1881 out << " return kTRUE;" << endl;
1884 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1886 Bool_t copy = kTRUE;
1887 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1890 TString workdir = gGrid->GetHomeDirectory();
1891 workdir += fGridWorkingDir;
1892 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1893 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1894 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1895 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1896 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1898 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1899 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1903 //______________________________________________________________________________
1904 void AliAnalysisAlien::WriteExecutable()
1906 // Generate the alien executable script.
1907 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1909 out.open(fExecutable.Data(), ios::out);
1911 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
1914 out << "#!/bin/bash" << endl;
1915 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1916 out << "echo \"=========================================\"" << endl;
1917 out << "echo \"############## PATH : ##############\"" << endl;
1918 out << "echo $PATH" << endl;
1919 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1920 out << "echo $LD_LIBRARY_PATH" << endl;
1921 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1922 out << "echo $ROOTSYS" << endl;
1923 out << "echo \"############## which root : ##############\"" << endl;
1924 out << "which root" << endl;
1925 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1926 out << "echo $ALICE_ROOT" << endl;
1927 out << "echo \"############## which aliroot : ##############\"" << endl;
1928 out << "which aliroot" << endl;
1929 out << "echo \"=========================================\"" << endl << endl;
1930 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1931 out << "root -b -q ";
1932 out << fAnalysisMacro.Data() << endl << endl;
1933 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1935 Bool_t copy = kTRUE;
1936 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1939 TString workdir = gGrid->GetHomeDirectory();
1940 workdir += fGridWorkingDir;
1941 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1942 if (FileExists(executable)) gGrid->Rm(executable);
1943 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1944 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1948 //______________________________________________________________________________
1949 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
1951 // Write the production file to be submitted by LPM manager. The format is:
1952 // First line: full_path_to_jdl estimated_no_subjobs_per_master
1953 // Next lines: full_path_to_dataset XXX (XXX is a string)
1954 // To submit, one has to: submit jdl XXX for all lines
1956 out.open(filename, ios::out);
1958 Error("WriteProductionFile", "Bad file name: %s", filename);
1961 TString workdir = gGrid->GetHomeDirectory();
1962 workdir += fGridWorkingDir;
1963 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
1964 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1965 out << locjdl << " " << njobspermaster << endl;
1966 Int_t nmasterjobs = fInputFiles->GetEntries();
1967 for (Int_t i=0; i<nmasterjobs; i++) {
1968 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
1970 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
1971 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
1974 //______________________________________________________________________________
1975 void AliAnalysisAlien::WriteValidationScript()
1977 // Generate the alien validation script.
1978 // Generate the validation script
1981 Error("WriteValidationScript", "Alien connection required");
1984 TString out_stream = "";
1985 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1986 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1988 out.open("validate.sh", ios::out);
1989 out << "#!/bin/bash" << endl;
1990 out << "##################################################" << endl;
1991 out << "validateout=`dirname $0`" << endl;
1992 out << "validatetime=`date`" << endl;
1993 out << "validated=\"0\";" << endl;
1994 out << "error=0" << endl;
1995 out << "if [ -z $validateout ]" << endl;
1996 out << "then" << endl;
1997 out << " validateout=\".\"" << endl;
1998 out << "fi" << endl << endl;
1999 out << "cd $validateout;" << endl;
2000 out << "validateworkdir=`pwd`;" << endl << endl;
2001 out << "echo \"*******************************************************\"" << out_stream << endl;
2002 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2004 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2005 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2006 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2007 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2008 out << "ls -la ./" << out_stream << endl;
2009 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2010 out << "##################################################" << endl;
2013 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2014 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2015 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2018 out << "if [ ! -f stderr ] ; then" << endl;
2019 out << " error=1" << endl;
2020 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2021 out << " echo \"Error = $error\" " << out_stream << endl;
2022 out << "fi" << endl;
2024 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2025 out << " error=1" << endl;
2026 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2027 out << " echo \"$parArch\" " << out_stream << endl;
2028 out << " echo \"Error = $error\" " << out_stream << endl;
2029 out << "fi" << endl;
2031 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2032 out << " error=1" << endl;
2033 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2034 out << " echo \"$segViol\" " << out_stream << endl;
2035 out << " echo \"Error = $error\" " << out_stream << endl;
2036 out << "fi" << endl;
2038 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2039 out << " error=1" << endl;
2040 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2041 out << " echo \"$segFault\" " << out_stream << endl;
2042 out << " echo \"Error = $error\" " << out_stream << endl;
2043 out << "fi" << endl;
2045 // Part dedicated to the specific analyses running into the train
2047 TObjArray *arr = fOutputFiles.Tokenize(" ");
2049 TString output_file;
2050 while ((os=(TObjString*)next1())) {
2051 output_file = os->GetString();
2052 Int_t index = output_file.Index("@");
2053 if (index > 0) output_file.Remove(index);
2054 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2055 out << " error=1" << endl;
2056 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2057 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2058 out << "fi" << endl;
2061 out << "if [ $error = 0 ] ; then" << endl;
2062 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2063 out << "fi" << endl;
2065 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2066 out << "echo \"*******************************************************\"" << out_stream << endl;
2067 out << "cd -" << endl;
2068 out << "exit $error" << endl;
2070 Bool_t copy = kTRUE;
2071 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2074 TString workdir = gGrid->GetHomeDirectory();
2075 workdir += fGridWorkingDir;
2076 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
2077 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
2078 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));