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 // Ignore ouputs in jdl that are also in outputarchive
796 TString sout = os->GetString();
797 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
798 if (fOutputArchive.Contains(sout)) continue;
799 if (!os->GetString().Contains("@") && fCloseSE.Length())
800 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
802 fGridJDL->AddToOutputSandbox(os->GetString());
805 // fGridJDL->SetPrice((UInt_t)fPrice);
806 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
807 TString validationScript = fExecutable;
808 validationScript.ReplaceAll(".sh", "_validation.sh");
809 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()));
810 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
811 // Write a jdl with 2 input parameters: collection name and output dir name.
814 // Copy jdl to grid workspace
816 if (fAdditionalLibs.Length()) {
817 arr = fAdditionalLibs.Tokenize(" ");
820 while ((os=(TObjString*)next())) {
821 if (os->GetString().Contains(".so")) continue;
822 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
823 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
824 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
829 TIter next(fPackages);
831 while ((obj=next())) {
832 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
833 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
840 //______________________________________________________________________________
841 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
843 // Writes one or more JDL's corresponding to findex. If findex is negative,
844 // all run numbers are considered in one go (jdl). For non-negative indices
845 // they correspond to the indices in the array fInputFiles.
846 if (!fInputFiles) return kFALSE;
848 TString workdir = gGrid->GetHomeDirectory();
849 workdir += fGridWorkingDir;
851 if (!fRunNumbers.Length() && !fRunRange[0]) {
852 // One jdl with no parameters in case input data is specified by name.
853 TIter next(fInputFiles);
854 while ((os=(TObjString*)next()))
855 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
856 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
858 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
859 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
860 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()));
864 // Generate the JDL as a string
865 TString sjdl = fGridJDL->Generate();
867 index = sjdl.Index("Executable");
868 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
869 index = sjdl.Index("Split ");
870 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
871 index = sjdl.Index("SplitMaxInputFileNumber");
872 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
873 index = sjdl.Index("InputDataCollection");
874 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
875 index = sjdl.Index("InputFile");
876 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
877 index = sjdl.Index("InputDataList ");
878 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
879 index = sjdl.Index("InputDataListFormat");
880 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
881 index = sjdl.Index("Price");
882 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
883 index = sjdl.Index("Requirements");
884 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
885 index = sjdl.Index("Packages");
886 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
887 index = sjdl.Index("User =");
888 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
889 index = sjdl.Index("TTL");
890 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
891 index = sjdl.Index("OutputFile");
892 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
893 index = sjdl.Index("OutputDir");
894 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
895 index = sjdl.Index("OutputArchive");
896 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
897 index = sjdl.Index("MaxInitFailed");
898 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
899 index = sjdl.Index("MasterResubmitThreshold");
900 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
901 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
902 index = sjdl.Index("Validationcommand");
903 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
904 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
905 sjdl.ReplaceAll("(member", "\n (member");
906 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
907 sjdl.ReplaceAll("{", "{\n ");
908 sjdl.ReplaceAll("};", "\n};");
909 sjdl.ReplaceAll("{\n \n", "{\n");
910 sjdl.ReplaceAll("\n\n", "\n");
911 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
912 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
913 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
914 index = sjdl.Index("JDLVariables");
915 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
918 out.open(fJDLName.Data(), ios::out);
920 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
925 // Copy jdl to grid workspace
927 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
929 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
930 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
932 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
933 if (FileExists(locjdl)) gGrid->Rm(locjdl);
934 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
939 //______________________________________________________________________________
940 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
942 // Returns true if file exists.
943 if (!gGrid) return kFALSE;
944 TGridResult *res = gGrid->Ls(lfn);
945 if (!res) return kFALSE;
946 TMap *map = dynamic_cast<TMap*>(res->At(0));
951 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
952 if (!objs || !objs->GetString().Length()) {
960 //______________________________________________________________________________
961 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
963 // Check input data type.
964 is_collection = kFALSE;
968 Error("CheckDataType", "No connection to grid");
971 is_collection = IsCollection(lfn);
972 TString msg = "\n##### file: ";
975 msg += " type: raw_collection;";
976 // special treatment for collections
978 // check for tag files in the collection
979 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
981 msg += " using_tags: No (unknown)";
982 Info("CheckDataType", msg.Data());
985 const char* typeStr = res->GetKey(0, "origLFN");
986 if (!typeStr || !strlen(typeStr)) {
987 msg += " using_tags: No (unknown)";
988 Info("CheckDataType", msg.Data());
991 TString file = typeStr;
992 use_tags = file.Contains(".tag");
993 if (use_tags) msg += " using_tags: Yes";
994 else msg += " using_tags: No";
995 Info("CheckDataType", msg.Data());
1000 is_xml = slfn.Contains(".xml");
1002 // Open xml collection and check if there are tag files inside
1003 msg += " type: xml_collection;";
1004 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1006 msg += " using_tags: No (unknown)";
1007 Info("CheckDataType", msg.Data());
1010 TMap *map = coll->Next();
1012 msg += " using_tags: No (unknown)";
1013 Info("CheckDataType", msg.Data());
1016 map = (TMap*)map->GetValue("");
1018 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1019 use_tags = file.Contains(".tag");
1021 if (use_tags) msg += " using_tags: Yes";
1022 else msg += " using_tags: No";
1023 Info("CheckDataType", msg.Data());
1026 use_tags = slfn.Contains(".tag");
1027 if (slfn.Contains(".root")) msg += " type: root file;";
1028 else msg += " type: unhnown file;";
1029 if (use_tags) msg += " using_tags: Yes";
1030 else msg += " using_tags: No";
1031 Info("CheckDataType", msg.Data());
1034 //______________________________________________________________________________
1035 void AliAnalysisAlien::EnablePackage(const char *package)
1037 // Enables a par file supposed to exist in the current directory.
1038 TString pkg(package);
1039 pkg.ReplaceAll(".par", "");
1041 if (gSystem->AccessPathName(pkg)) {
1042 Error("EnablePackage", "Package %s not found", pkg.Data());
1045 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1046 Info("EnablePackage", "AliEn plugin will use .par packages");
1047 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1049 fPackages = new TObjArray();
1050 fPackages->SetOwner();
1052 fPackages->Add(new TObjString(pkg));
1055 //______________________________________________________________________________
1056 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1058 // Get job status for all jobs with jobid>jobidstart.
1059 static char mstatus[20];
1065 TGridJobStatusList *list = gGrid->Ps("");
1066 if (!list) return mstatus;
1067 Int_t nentries = list->GetSize();
1068 TGridJobStatus *status;
1070 for (Int_t ijob=0; ijob<nentries; ijob++) {
1071 status = (TGridJobStatus *)list->At(ijob);
1072 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1073 if (pid<jobidstart) continue;
1074 if (pid == lastid) {
1075 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1077 switch (status->GetStatus()) {
1078 case TGridJobStatus::kWAITING:
1080 case TGridJobStatus::kRUNNING:
1082 case TGridJobStatus::kABORTED:
1083 case TGridJobStatus::kFAIL:
1084 case TGridJobStatus::kUNKNOWN:
1086 case TGridJobStatus::kDONE:
1095 //______________________________________________________________________________
1096 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1098 // Returns true if file is a collection. Functionality duplicated from
1099 // TAlien::Type() because we don't want to directly depend on TAlien.
1101 Error("IsCollection", "No connection to grid");
1104 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1105 if (!res) return kFALSE;
1106 const char* typeStr = res->GetKey(0, "type");
1107 if (!typeStr || !strlen(typeStr)) return kFALSE;
1108 if (!strcmp(typeStr, "collection")) return kTRUE;
1113 //______________________________________________________________________________
1114 void AliAnalysisAlien::Print(Option_t *) const
1116 // Print current plugin settings.
1117 printf("### AliEn analysis plugin current settings ###\n");
1118 printf("= Production mode:______________________________ %d\n", fProductionMode);
1119 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1120 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1121 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1123 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1124 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1125 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1126 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1127 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1128 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1129 if (fRunNumbers.Length())
1130 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1132 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1133 if (!fRunRange[0] && !fRunNumbers.Length()) {
1134 TIter next(fInputFiles);
1137 while ((obj=next())) list += obj->GetName();
1138 printf("= Input files to be processed: _________________ %s\n", list.Data());
1140 if (TestBit(AliAnalysisGrid::kTest))
1141 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1142 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1143 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1144 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1145 printf("=====================================================================\n");
1146 printf("= Job price: ___________________________________ %d\n", fPrice);
1147 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1148 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1149 if (fMaxInitFailed>0)
1150 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1151 if (fMasterResubmitThreshold>0)
1152 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1153 if (fNrunsPerMaster>0)
1154 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1155 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1156 printf("= Name of the generated execution script: ______ %s\n",fExecutable.Data());
1157 if (fArguments.Length())
1158 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1159 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1160 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1161 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1162 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1164 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1165 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1166 if (fIncludePath.Data())
1167 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1168 if (fCloseSE.Length())
1169 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1170 if (fFriendChainName.Length())
1171 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1173 TIter next(fPackages);
1176 while ((obj=next())) list += obj->GetName();
1177 printf("= Par files to be used: ________________________ %s\n", list.Data());
1181 //______________________________________________________________________________
1182 void AliAnalysisAlien::SetDefaults()
1184 // Set default values for everything. What cannot be filled will be left empty.
1185 if (fGridJDL) delete fGridJDL;
1186 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1189 fSplitMaxInputFileNumber = 100;
1191 fMasterResubmitThreshold = 0;
1195 fNrunsPerMaster = 1;
1196 fMaxMergeFiles = 100;
1198 fExecutable = "analysis.sh";
1200 fAnalysisMacro = "myAnalysis.C";
1201 fAnalysisSource = "";
1202 fAdditionalLibs = "";
1206 fAliROOTVersion = "";
1207 fUser = ""; // Your alien user name
1208 fGridWorkingDir = "";
1209 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1210 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1211 fFriendChainName = "";
1212 fGridOutputDir = "output";
1213 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1214 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1215 fInputFormat = "xml-single";
1216 fJDLName = "analysis.jdl";
1217 fJobTag = "Automatically generated analysis JDL";
1218 fMergeExcludes = "";
1221 //______________________________________________________________________________
1222 Bool_t AliAnalysisAlien::MergeOutputs()
1224 // Merge analysis outputs existing in the AliEn space.
1225 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1226 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1228 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1231 // Get the output path
1232 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1233 if (!gGrid->Cd(fGridOutputDir)) {
1234 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1237 if (!fOutputFiles.Length()) {
1238 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1241 TObjArray *list = fOutputFiles.Tokenize(" ");
1245 TString output_file;
1246 TString output_chunk;
1247 TString previous_chunk;
1248 Int_t count_chunk = 0;
1249 Int_t count_zero = fMaxMergeFiles;
1250 Bool_t merged = kTRUE;
1251 while((str=(TObjString*)next())) {
1252 output_file = str->GetString();
1253 Int_t index = output_file.Index("@");
1254 if (index > 0) output_file.Remove(index);
1255 // Skip already merged outputs
1256 if (!gSystem->AccessPathName(output_file)) {
1257 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1260 if (fMergeExcludes.Length() &&
1261 fMergeExcludes.Contains(output_file.Data())) continue;
1262 // Perform a 'find' command in the output directory, looking for registered outputs
1263 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
1264 printf("command: %s\n", command.Data());
1265 TGridResult *res = gGrid->Command(command);
1267 TFileMerger *fm = 0;
1270 previous_chunk = "";
1272 // Check if there is a merge operation to resume
1273 output_chunk = output_file;
1274 output_chunk.ReplaceAll(".root", "_*.root");
1275 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1277 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1279 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1283 output_chunk = output_file;
1284 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1285 printf("%s\n", output_chunk.Data());
1287 if (gSystem->AccessPathName(output_chunk)) continue;
1288 // Merged file with chunks up to <count_chunk> found
1289 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1290 previous_chunk = output_chunk;
1294 count_zero = fMaxMergeFiles;
1295 while ((map=(TMap*)nextmap())) {
1296 // Loop 'find' results and get next LFN
1297 if (count_zero == fMaxMergeFiles) {
1298 // First file in chunk - create file merger and add previous chunk if any.
1299 fm = new TFileMerger(kFALSE);
1300 fm->SetFastMethod(kTRUE);
1301 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1302 output_chunk = output_file;
1303 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1305 // If last file found, put merged results in the output file
1306 if (map == res->Last()) output_chunk = output_file;
1307 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1308 if (!objs || !objs->GetString().Length()) {
1309 // Nothing found - skip this output
1314 // Add file to be merged and decrement chunk counter.
1315 fm->AddFile(objs->GetString());
1317 if (count_zero==0 || map == res->Last()) {
1318 fm->OutputFile(output_chunk);
1319 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1320 // Nothing found - skip this output
1321 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1326 // Merge the outputs, then go to next chunk
1328 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1334 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1335 gSystem->Unlink(previous_chunk);
1337 if (map == res->Last()) {
1343 count_zero = fMaxMergeFiles;
1344 previous_chunk = output_chunk;
1349 Error("MergeOutputs", "Terminate() will NOT be executed");
1354 //______________________________________________________________________________
1355 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1357 // Use the output files connected to output containers from the analysis manager
1358 // rather than the files defined by SetOutputFiles
1359 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1360 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1362 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1365 //______________________________________________________________________________
1366 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1368 // Start remote grid analysis.
1370 // Check if output files have to be taken from the analysis manager
1371 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1372 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1373 if (!mgr || !mgr->IsInitialized()) {
1374 Error("StartAnalysis", "You need an initialized analysis manager for this");
1378 TIter next(mgr->GetOutputs());
1379 AliAnalysisDataContainer *output;
1380 while ((output=(AliAnalysisDataContainer*)next())) {
1381 const char *filename = output->GetFileName();
1382 if (!(strcmp(filename, "default"))) {
1383 if (!mgr->GetOutputEventHandler()) continue;
1384 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1386 if (fOutputFiles.Length()) fOutputFiles += " ";
1387 fOutputFiles += filename;
1389 // Add extra files registered to the analysis manager
1390 if (mgr->GetExtraFiles().Length()) {
1391 if (fOutputFiles.Length()) fOutputFiles += " ";
1392 fOutputFiles += mgr->GetExtraFiles();
1395 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1396 if (TestBit(AliAnalysisGrid::kOffline)) {
1397 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1398 \n there nor any job run. You can revise the JDL and analysis \
1399 \n macro then run the same in \"submit\" mode.");
1400 } else if (TestBit(AliAnalysisGrid::kTest)) {
1401 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1403 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1404 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1405 \n space and job submitted.");
1406 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1407 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1410 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1414 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1418 if (!CheckInputData()) {
1419 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1422 CreateDataset(fDataPattern);
1423 WriteAnalysisFile();
1424 WriteAnalysisMacro();
1426 WriteValidationScript();
1427 if (!CreateJDL()) return kFALSE;
1428 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1429 if (TestBit(AliAnalysisGrid::kTest)) {
1430 // Locally testing the analysis
1431 Info("StartAnalysis", "\n_______________________________________________________________________ \
1432 \n Running analysis script in a daughter shell as on a worker node \
1433 \n_______________________________________________________________________");
1434 TObjArray *list = fOutputFiles.Tokenize(" ");
1437 TString output_file;
1438 while((str=(TObjString*)next())) {
1439 output_file = str->GetString();
1440 Int_t index = output_file.Index("@");
1441 if (index > 0) output_file.Remove(index);
1442 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1445 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1446 TString validationScript = fExecutable;
1447 validationScript.ReplaceAll(".sh", "_validation.sh");
1448 gSystem->Exec(Form("bash %s",validationScript.Data()));
1449 // gSystem->Exec("cat stdout");
1452 // Check if submitting is managed by LPM manager
1453 if (fProductionMode) {
1454 TString prodfile = fJDLName;
1455 prodfile.ReplaceAll(".jdl", ".prod");
1456 WriteProductionFile(prodfile);
1457 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1460 // Submit AliEn job(s)
1461 gGrid->Cd(fGridOutputDir);
1464 if (!fRunNumbers.Length() && !fRunRange[0]) {
1465 // Submit a given xml or a set of runs
1466 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1467 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1469 const char *cjobId = res->GetKey(0,"jobId");
1471 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1474 Info("StartAnalysis", "\n_______________________________________________________________________ \
1475 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1476 \n_______________________________________________________________________",
1477 fJDLName.Data(), cjobId);
1483 // Submit for a range of enumeration of runs.
1487 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1488 \n You may exit at any time and terminate the job later using the option <terminate> \
1489 \n ##################################################################################", jobID.Data());
1490 gSystem->Exec("aliensh");
1494 //______________________________________________________________________________
1495 void AliAnalysisAlien::Submit()
1497 // Submit all master jobs.
1498 Int_t nmasterjobs = fInputFiles->GetEntries();
1499 Long_t tshoot = gSystem->Now();
1500 if (!fNsubmitted) SubmitNext();
1501 while (fNsubmitted < nmasterjobs) {
1502 Long_t now = gSystem->Now();
1503 if ((now-tshoot)>30000) {
1510 //______________________________________________________________________________
1511 void AliAnalysisAlien::SubmitNext()
1513 // Submit next bunch of master jobs if the queue is free.
1514 static Bool_t iscalled = kFALSE;
1515 static Int_t firstmaster = 0;
1516 static Int_t lastmaster = 0;
1517 static Int_t npermaster = 0;
1518 if (iscalled) return;
1520 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1521 Int_t ntosubmit = 0;
1524 if (!fNsubmitted) ntosubmit = 1;
1526 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1527 printf("=== master %d: %s\n", lastmaster, status.Data());
1528 // If last master not split, just return
1529 if (status != "SPLIT") {iscalled = kFALSE; return;}
1530 // No more than 100 waiting jobs
1531 if (nwaiting>100) {iscalled = kFALSE; return;}
1532 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1533 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1534 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1535 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1537 Int_t nmasterjobs = fInputFiles->GetEntries();
1538 for (Int_t i=0; i<ntosubmit; i++) {
1539 // Submit for a range of enumeration of runs.
1540 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1542 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1543 printf("********* %s\n",query.Data());
1544 res = gGrid->Command(query);
1546 TString cjobId1 = res->GetKey(0,"jobId");
1547 if (!cjobId1.Length()) {
1548 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1552 Info("StartAnalysis", "\n_______________________________________________________________________ \
1553 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1554 \n_______________________________________________________________________",
1555 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1558 lastmaster = cjobId1.Atoi();
1559 if (!firstmaster) firstmaster = lastmaster;
1568 //______________________________________________________________________________
1569 void AliAnalysisAlien::WriteAnalysisFile()
1571 // Write current analysis manager into the file analysis.root
1572 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1573 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1574 if (!mgr || !mgr->IsInitialized()) {
1575 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1578 // Check analysis type
1580 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1581 handler = (TObject*)mgr->GetInputEventHandler();
1583 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1584 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1586 TDirectory *cdir = gDirectory;
1587 TFile *file = TFile::Open("analysis.root", "RECREATE");
1592 if (cdir) cdir->cd();
1593 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1595 Bool_t copy = kTRUE;
1596 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1599 TString workdir = gGrid->GetHomeDirectory();
1600 workdir += fGridWorkingDir;
1601 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1602 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1603 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1607 //______________________________________________________________________________
1608 void AliAnalysisAlien::WriteAnalysisMacro()
1610 // Write the analysis macro that will steer the analysis in grid mode.
1611 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1613 out.open(fAnalysisMacro.Data(), ios::out);
1615 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1618 TString func = fAnalysisMacro;
1619 TString type = "ESD";
1620 TString comment = "// Analysis using ";
1621 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1622 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1626 if (type!="AOD" && fFriendChainName!="") {
1627 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1630 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1631 else comment += " data";
1632 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1633 func.ReplaceAll(".C", "");
1634 out << "void " << func.Data() << "()" << endl;
1636 out << comment.Data() << endl;
1637 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1638 out << " TStopwatch timer;" << endl;
1639 out << " timer.Start();" << endl << endl;
1640 out << "// load base root libraries" << endl;
1641 out << " gSystem->Load(\"libTree\");" << endl;
1642 out << " gSystem->Load(\"libGeom\");" << endl;
1643 out << " gSystem->Load(\"libVMC\");" << endl;
1644 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1645 out << "// Load analysis framework libraries" << endl;
1647 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1648 out << " gSystem->Load(\"libESD\");" << endl;
1649 out << " gSystem->Load(\"libAOD\");" << endl;
1650 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1651 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1652 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1654 TIter next(fPackages);
1657 Bool_t hasSTEERBase = kFALSE;
1658 Bool_t hasESD = kFALSE;
1659 Bool_t hasAOD = kFALSE;
1660 Bool_t hasANALYSIS = kFALSE;
1661 Bool_t hasANALYSISalice = kFALSE;
1662 Bool_t hasCORRFW = kFALSE;
1663 while ((obj=next())) {
1664 pkgname = obj->GetName();
1665 if (pkgname == "STEERBase" ||
1666 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1667 if (pkgname == "ESD" ||
1668 pkgname == "ESD.par") hasESD = kTRUE;
1669 if (pkgname == "AOD" ||
1670 pkgname == "AOD.par") hasAOD = kTRUE;
1671 if (pkgname == "ANALYSIS" ||
1672 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1673 if (pkgname == "ANALYSISalice" ||
1674 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1675 if (pkgname == "CORRFW" ||
1676 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1678 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1679 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1680 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1681 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1682 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1683 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1684 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1685 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1686 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1687 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1688 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1689 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1690 out << "// Compile other par packages" << endl;
1692 while ((obj=next())) {
1693 pkgname = obj->GetName();
1694 if (pkgname == "STEERBase" ||
1695 pkgname == "STEERBase.par" ||
1697 pkgname == "ESD.par" ||
1699 pkgname == "AOD.par" ||
1700 pkgname == "ANALYSIS" ||
1701 pkgname == "ANALYSIS.par" ||
1702 pkgname == "ANALYSISalice" ||
1703 pkgname == "ANALYSISalice.par" ||
1704 pkgname == "CORRFW" ||
1705 pkgname == "CORRFW.par") continue;
1706 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1709 out << "// include path" << endl;
1710 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1711 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1712 if (fAdditionalLibs.Length()) {
1713 out << "// Add aditional AliRoot libraries" << endl;
1714 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1717 while((str=(TObjString*)next())) {
1718 if (str->GetString().Contains(".so"))
1719 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1721 if (list) delete list;
1724 out << "// analysis source to be compiled at runtime (if any)" << endl;
1725 if (fAnalysisSource.Length()) {
1726 TObjArray *list = fAnalysisSource.Tokenize(" ");
1729 while((str=(TObjString*)next())) {
1730 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1732 if (list) delete list;
1735 out << "// connect to AliEn and make the chain" << endl;
1736 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1737 if (IsUsingTags()) {
1738 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1740 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1741 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1743 out << " // Check if the macro to create the chain was provided" << endl;
1744 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1745 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1746 out << " return;" << endl;
1747 out << " }" << endl;
1748 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1749 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1752 out << "// read the analysis manager from file" << endl;
1753 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1754 out << " if (!file) return;" << endl;
1755 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1756 out << " AliAnalysisManager *mgr = 0;" << endl;
1757 out << " TKey *key;" << endl;
1758 out << " while ((key=(TKey*)nextkey())) {" << endl;
1759 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1760 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1761 out << " };" << endl;
1762 out << " if (!mgr) {" << endl;
1763 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1764 out << " return;" << endl;
1765 out << " }" << endl << endl;
1766 out << " mgr->PrintStatus();" << endl;
1767 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1768 out << " timer.Stop();" << endl;
1769 out << " timer.Print();" << endl;
1770 out << "}" << endl << endl;
1771 if (IsUsingTags()) {
1772 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1774 out << "// Create a chain using tags from the xml file." << endl;
1775 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1776 out << " if (!coll) {" << endl;
1777 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1778 out << " return NULL;" << endl;
1779 out << " }" << endl;
1780 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1781 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1782 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1783 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1784 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1785 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1786 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1787 out << " // Check if the cuts configuration file was provided" << endl;
1788 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1789 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1790 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1791 out << " }" << endl;
1792 if (fFriendChainName=="") {
1793 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1795 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1796 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1797 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1799 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1800 out << " chain->ls();" << endl;
1801 out << " return chain;" << endl;
1802 out << "}" << endl << endl;
1803 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1804 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1805 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1806 msg += " AliLHCTagCuts *lhcCuts,\n";
1807 msg += " AliDetectorTagCuts *detCuts,\n";
1808 msg += " AliEventTagCuts *evCuts)";
1809 Info("WriteAnalysisMacro", msg.Data());
1812 if (!IsUsingTags() || fFriendChainName!="") {
1813 out <<"//________________________________________________________________________________" << endl;
1814 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1816 out << "// Create a chain using url's from xml file" << endl;
1817 out << " TString treename = type;" << endl;
1818 out << " treename.ToLower();" << endl;
1819 out << " treename += \"Tree\";" << endl;
1820 out << " printf(\"***************************************\\n\");" << endl;
1821 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1822 out << " printf(\"***************************************\\n\");" << endl;
1823 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1824 out << " if (!coll) {" << endl;
1825 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1826 out << " return NULL;" << endl;
1827 out << " }" << endl;
1828 out << " TChain *chain = new TChain(treename);" << endl;
1829 if(fFriendChainName!="") {
1830 out << " TChain *chainFriend = new TChain(treename);" << endl;
1832 out << " coll->Reset();" << endl;
1833 out << " while (coll->Next()) {" << endl;
1834 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1835 if(fFriendChainName!="") {
1836 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1837 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1838 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1839 out << " chainFriend->Add(fileFriend.Data());" << endl;
1841 out << " }" << endl;
1842 out << " if (!chain->GetNtrees()) {" << endl;
1843 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1844 out << " return NULL;" << endl;
1845 out << " }" << endl;
1846 if(fFriendChainName!="") {
1847 out << " chain->AddFriend(chainFriend);" << endl;
1849 out << " return chain;" << endl;
1850 out << "}" << endl << endl;
1853 out <<"//________________________________________________________________________________" << endl;
1854 out << "Bool_t SetupPar(const char *package) {" << endl;
1855 out << "// Compile the package and set it up." << endl;
1856 out << " TString pkgdir = package;" << endl;
1857 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1858 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1859 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1860 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1861 out << " // Check for BUILD.sh and execute" << endl;
1862 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1863 out << " printf(\"*******************************\\n\");" << endl;
1864 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1865 out << " printf(\"*******************************\\n\");" << endl;
1866 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1867 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1868 out << " gSystem->ChangeDirectory(cdir);" << endl;
1869 out << " return kFALSE;" << endl;
1870 out << " }" << endl;
1871 out << " } else {" << endl;
1872 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1873 out << " gSystem->ChangeDirectory(cdir);" << endl;
1874 out << " return kFALSE;" << endl;
1875 out << " }" << endl;
1876 out << " // Check for SETUP.C and execute" << endl;
1877 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1878 out << " printf(\"*******************************\\n\");" << endl;
1879 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1880 out << " printf(\"*******************************\\n\");" << endl;
1881 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1882 out << " } else {" << endl;
1883 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
1884 out << " gSystem->ChangeDirectory(cdir);" << endl;
1885 out << " return kFALSE;" << endl;
1886 out << " }" << endl;
1887 out << " // Restore original workdir" << endl;
1888 out << " gSystem->ChangeDirectory(cdir);" << endl;
1889 out << " return kTRUE;" << endl;
1892 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1894 Bool_t copy = kTRUE;
1895 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1898 TString workdir = gGrid->GetHomeDirectory();
1899 workdir += fGridWorkingDir;
1900 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1901 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1902 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1903 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1904 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1906 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1907 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1911 //______________________________________________________________________________
1912 void AliAnalysisAlien::WriteExecutable()
1914 // Generate the alien executable script.
1915 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1917 out.open(fExecutable.Data(), ios::out);
1919 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
1922 out << "#!/bin/bash" << endl;
1923 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1924 out << "echo \"=========================================\"" << endl;
1925 out << "echo \"############## PATH : ##############\"" << endl;
1926 out << "echo $PATH" << endl;
1927 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1928 out << "echo $LD_LIBRARY_PATH" << endl;
1929 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1930 out << "echo $ROOTSYS" << endl;
1931 out << "echo \"############## which root : ##############\"" << endl;
1932 out << "which root" << endl;
1933 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1934 out << "echo $ALICE_ROOT" << endl;
1935 out << "echo \"############## which aliroot : ##############\"" << endl;
1936 out << "which aliroot" << endl;
1937 out << "echo \"=========================================\"" << endl << endl;
1938 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1939 out << "root -b -q ";
1940 out << fAnalysisMacro.Data() << endl << endl;
1941 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1943 Bool_t copy = kTRUE;
1944 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1947 TString workdir = gGrid->GetHomeDirectory();
1948 workdir += fGridWorkingDir;
1949 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1950 if (FileExists(executable)) gGrid->Rm(executable);
1951 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1952 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1956 //______________________________________________________________________________
1957 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
1959 // Write the production file to be submitted by LPM manager. The format is:
1960 // First line: full_path_to_jdl estimated_no_subjobs_per_master
1961 // Next lines: full_path_to_dataset XXX (XXX is a string)
1962 // To submit, one has to: submit jdl XXX for all lines
1964 out.open(filename, ios::out);
1966 Error("WriteProductionFile", "Bad file name: %s", filename);
1969 TString workdir = gGrid->GetHomeDirectory();
1970 workdir += fGridWorkingDir;
1971 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
1972 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1973 out << locjdl << " " << njobspermaster << endl;
1974 Int_t nmasterjobs = fInputFiles->GetEntries();
1975 for (Int_t i=0; i<nmasterjobs; i++) {
1976 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
1978 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
1979 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
1982 //______________________________________________________________________________
1983 void AliAnalysisAlien::WriteValidationScript()
1985 // Generate the alien validation script.
1986 // Generate the validation script
1988 TString validationScript = fExecutable;
1989 validationScript.ReplaceAll(".sh", "_validation.sh");
1991 Error("WriteValidationScript", "Alien connection required");
1994 TString out_stream = "";
1995 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1996 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1998 out.open(validationScript, ios::out);
1999 out << "#!/bin/bash" << endl;
2000 out << "##################################################" << endl;
2001 out << "validateout=`dirname $0`" << endl;
2002 out << "validatetime=`date`" << endl;
2003 out << "validated=\"0\";" << endl;
2004 out << "error=0" << endl;
2005 out << "if [ -z $validateout ]" << endl;
2006 out << "then" << endl;
2007 out << " validateout=\".\"" << endl;
2008 out << "fi" << endl << endl;
2009 out << "cd $validateout;" << endl;
2010 out << "validateworkdir=`pwd`;" << endl << endl;
2011 out << "echo \"*******************************************************\"" << out_stream << endl;
2012 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2014 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2015 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2016 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2017 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2018 out << "ls -la ./" << out_stream << endl;
2019 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2020 out << "##################################################" << endl;
2023 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2024 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2025 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2028 out << "if [ ! -f stderr ] ; then" << endl;
2029 out << " error=1" << endl;
2030 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2031 out << " echo \"Error = $error\" " << out_stream << endl;
2032 out << "fi" << endl;
2034 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2035 out << " error=1" << endl;
2036 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2037 out << " echo \"$parArch\" " << out_stream << endl;
2038 out << " echo \"Error = $error\" " << out_stream << endl;
2039 out << "fi" << endl;
2041 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2042 out << " error=1" << endl;
2043 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2044 out << " echo \"$segViol\" " << out_stream << endl;
2045 out << " echo \"Error = $error\" " << out_stream << endl;
2046 out << "fi" << endl;
2048 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2049 out << " error=1" << endl;
2050 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2051 out << " echo \"$segFault\" " << out_stream << endl;
2052 out << " echo \"Error = $error\" " << out_stream << endl;
2053 out << "fi" << endl;
2055 // Part dedicated to the specific analyses running into the train
2057 TObjArray *arr = fOutputFiles.Tokenize(" ");
2059 TString output_file;
2060 while ((os=(TObjString*)next1())) {
2061 output_file = os->GetString();
2062 Int_t index = output_file.Index("@");
2063 if (index > 0) output_file.Remove(index);
2064 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2065 out << " error=1" << endl;
2066 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2067 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2068 out << "fi" << endl;
2071 out << "if [ $error = 0 ] ; then" << endl;
2072 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2073 out << "fi" << endl;
2075 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2076 out << "echo \"*******************************************************\"" << out_stream << endl;
2077 out << "cd -" << endl;
2078 out << "exit $error" << endl;
2080 Bool_t copy = kTRUE;
2081 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2084 TString workdir = gGrid->GetHomeDirectory();
2085 workdir += fGridWorkingDir;
2086 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2087 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2088 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));