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),
87 //______________________________________________________________________________
88 AliAnalysisAlien::AliAnalysisAlien(const char *name)
89 :AliAnalysisGrid(name),
93 fSplitMaxInputFileNumber(0),
95 fMasterResubmitThreshold(0),
131 //______________________________________________________________________________
132 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
133 :AliAnalysisGrid(other),
135 fPrice(other.fPrice),
137 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
138 fMaxInitFailed(other.fMaxInitFailed),
139 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
140 fNtestFiles(other.fNtestFiles),
141 fNrunsPerMaster(other.fNrunsPerMaster),
142 fMaxMergeFiles(other.fMaxMergeFiles),
143 fNsubmitted(other.fNsubmitted),
144 fRunNumbers(other.fRunNumbers),
145 fExecutable(other.fExecutable),
146 fArguments(other.fArguments),
147 fAnalysisMacro(other.fAnalysisMacro),
148 fAnalysisSource(other.fAnalysisSource),
149 fAdditionalLibs(other.fAdditionalLibs),
150 fSplitMode(other.fSplitMode),
151 fAPIVersion(other.fAPIVersion),
152 fROOTVersion(other.fROOTVersion),
153 fAliROOTVersion(other.fAliROOTVersion),
155 fGridWorkingDir(other.fGridWorkingDir),
156 fGridDataDir(other.fGridDataDir),
157 fDataPattern(other.fDataPattern),
158 fGridOutputDir(other.fGridOutputDir),
159 fOutputArchive(other.fOutputArchive),
160 fOutputFiles(other.fOutputFiles),
161 fInputFormat(other.fInputFormat),
162 fDatasetName(other.fDatasetName),
163 fJDLName(other.fJDLName),
164 fMergeExcludes(other.fMergeExcludes),
165 fIncludePath(other.fIncludePath),
166 fCloseSE(other.fCloseSE),
167 fFriendChainName(other.fFriendChainName),
172 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
173 fRunRange[0] = other.fRunRange[0];
174 fRunRange[1] = other.fRunRange[1];
175 if (other.fInputFiles) {
176 fInputFiles = new TObjArray();
177 TIter next(other.fInputFiles);
179 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
180 fInputFiles->SetOwner();
182 if (other.fPackages) {
183 fPackages = new TObjArray();
184 TIter next(other.fPackages);
186 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
187 fPackages->SetOwner();
191 //______________________________________________________________________________
192 AliAnalysisAlien::~AliAnalysisAlien()
195 if (fGridJDL) delete fGridJDL;
196 if (fInputFiles) delete fInputFiles;
197 if (fPackages) delete fPackages;
200 //______________________________________________________________________________
201 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
204 if (this != &other) {
205 AliAnalysisGrid::operator=(other);
206 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
207 fPrice = other.fPrice;
209 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
210 fMaxInitFailed = other.fMaxInitFailed;
211 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
212 fNtestFiles = other.fNtestFiles;
213 fRunNumbers = other.fRunNumbers;
214 fExecutable = other.fExecutable;
215 fArguments = other.fArguments;
216 fAnalysisMacro = other.fAnalysisMacro;
217 fAnalysisSource = other.fAnalysisSource;
218 fAdditionalLibs = other.fAdditionalLibs;
219 fSplitMode = other.fSplitMode;
220 fAPIVersion = other.fAPIVersion;
221 fROOTVersion = other.fROOTVersion;
222 fAliROOTVersion = other.fAliROOTVersion;
224 fGridWorkingDir = other.fGridWorkingDir;
225 fGridDataDir = other.fGridDataDir;
226 fDataPattern = other.fDataPattern;
227 fGridOutputDir = other.fGridOutputDir;
228 fOutputArchive = other.fOutputArchive;
229 fOutputFiles = other.fOutputFiles;
230 fInputFormat = other.fInputFormat;
231 fDatasetName = other.fDatasetName;
232 fJDLName = other.fJDLName;
233 fMergeExcludes = other.fMergeExcludes;
234 fIncludePath = other.fIncludePath;
235 fCloseSE = other.fCloseSE;
236 fFriendChainName = other.fFriendChainName;
237 if (other.fInputFiles) {
238 fInputFiles = new TObjArray();
239 TIter next(other.fInputFiles);
241 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
242 fInputFiles->SetOwner();
244 if (other.fPackages) {
245 fPackages = new TObjArray();
246 TIter next(other.fPackages);
248 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
249 fPackages->SetOwner();
255 //______________________________________________________________________________
256 void AliAnalysisAlien::AddIncludePath(const char *path)
258 // Add include path in the remote analysis macro.
260 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
261 else fIncludePath += Form("-I%s ", path);
264 //______________________________________________________________________________
265 void AliAnalysisAlien::AddRunNumber(Int_t run)
267 // Add a run number to the list of runs to be processed.
268 if (fRunNumbers.Length()) fRunNumbers += " ";
269 fRunNumbers += Form("%d", run);
272 //______________________________________________________________________________
273 void AliAnalysisAlien::AddDataFile(const char *lfn)
275 // Adds a data file to the input to be analysed. The file should be a valid LFN
276 // or point to an existing file in the alien workdir.
277 if (!fInputFiles) fInputFiles = new TObjArray();
278 fInputFiles->Add(new TObjString(lfn));
281 //______________________________________________________________________________
282 Bool_t AliAnalysisAlien::Connect()
284 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
285 if (gGrid && gGrid->IsConnected()) return kTRUE;
286 if (!gSystem->Getenv("alien_API_USER")) {
287 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
288 gSystem->Getenv("UID"));
292 Info("Connect", "Trying to connect to AliEn ...");
293 TGrid::Connect("alien://");
295 if (!gGrid || !gGrid->IsConnected()) {
296 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
299 fUser = gGrid->GetUser();
300 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
304 //______________________________________________________________________________
305 void AliAnalysisAlien::CdWork()
307 // Check validity of alien workspace. Create directory if possible.
309 Error("CdWork", "Alien connection required");
312 TString homedir = gGrid->GetHomeDirectory();
313 TString workdir = homedir + fGridWorkingDir;
314 if (!gGrid->Cd(workdir)) {
316 if (gGrid->Mkdir(workdir)) {
317 gGrid->Cd(fGridWorkingDir);
318 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
320 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
321 workdir.Data(), homedir.Data());
322 fGridWorkingDir = "";
327 //______________________________________________________________________________
328 Bool_t AliAnalysisAlien::CheckInputData()
330 // Check validity of input data. If necessary, create xml files.
331 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
332 if (!fGridDataDir.Length()) {
333 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
336 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
339 // Process declared files
340 Bool_t is_collection = kFALSE;
341 Bool_t is_xml = kFALSE;
342 Bool_t use_tags = kFALSE;
343 Bool_t checked = kFALSE;
346 TString workdir = gGrid->GetHomeDirectory();
347 workdir += fGridWorkingDir;
350 TIter next(fInputFiles);
351 while ((objstr=(TObjString*)next())) {
354 file += objstr->GetString();
355 // Store full lfn path
356 if (FileExists(file)) objstr->SetString(file);
358 file = objstr->GetName();
359 if (!FileExists(objstr->GetName())) {
360 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
361 objstr->GetName(), workdir.Data());
365 Bool_t iscoll, isxml, usetags;
366 CheckDataType(file, iscoll, isxml, usetags);
369 is_collection = iscoll;
372 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
374 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
375 Error("CheckInputData", "Some conflict was found in the types of inputs");
381 // Process requested run numbers
382 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
383 // Check validity of alien data directory
384 if (!fGridDataDir.Length()) {
385 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
388 if (!gGrid->Cd(fGridDataDir)) {
389 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
393 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
397 if (checked && !is_xml) {
398 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
401 // Check validity of run number(s)
409 use_tags = fDataPattern.Contains("tag");
410 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
412 if (use_tags != fDataPattern.Contains("tag")) {
413 Error("CheckInputData", "Cannot mix input files using/not using tags");
416 if (fRunNumbers.Length()) {
417 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
418 arr = fRunNumbers.Tokenize(" ");
420 while ((os=(TObjString*)next())) {
421 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
422 if (!gGrid->Cd(path)) {
423 Warning("CheckInputData", "Run number %s not found in path: %s", os->GetString().Data(), path.Data());
426 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
427 TString msg = "\n##### file: ";
429 msg += " type: xml_collection;";
430 if (use_tags) msg += " using_tags: Yes";
431 else msg += " using_tags: No";
432 Info("CheckDataType", msg.Data());
433 if (fNrunsPerMaster<2) {
434 AddDataFile(Form("%s.xml", os->GetString().Data()));
437 if (((nruns-1)%fNrunsPerMaster) == 0) {
438 schunk = os->GetString();
440 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
441 schunk += Form("_%s.xml", os->GetString().Data());
447 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
448 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
449 path = Form("%s/%d ", fGridDataDir.Data(), irun);
450 if (!gGrid->Cd(path)) {
451 Warning("CheckInputData", "Run number %d not found in path: %s", irun, path.Data());
454 path = Form("%s/%d.xml", workdir.Data(),irun);
455 TString msg = "\n##### file: ";
457 msg += " type: xml_collection;";
458 if (use_tags) msg += " using_tags: Yes";
459 else msg += " using_tags: No";
460 Info("CheckDataType", msg.Data());
461 if (fNrunsPerMaster<2) {
462 AddDataFile(Form("%d.xml",irun));
465 if (((nruns-1)%fNrunsPerMaster) == 0) {
466 schunk = Form("%d", irun);
468 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
469 schunk += Form("_%d.xml", irun);
477 //______________________________________________________________________________
478 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
480 // Create dataset for the grid data directory + run number.
481 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
483 Error("CreateDataset", "Cannot create dataset with no grid connection");
489 TString workdir = gGrid->GetHomeDirectory();
490 workdir += fGridWorkingDir;
492 // Compose the 'find' command arguments
494 TString options = "-x collection ";
495 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
496 TString conditions = "";
502 TGridCollection *cbase=0, *cadd=0;
503 if (!fRunNumbers.Length() && !fRunRange[0]) {
504 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
505 // Make a single data collection from data directory.
507 if (!gGrid->Cd(path)) {
508 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
512 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
513 else file = Form("%s.xml", gSystem->BaseName(path));
514 if (gSystem->AccessPathName(file)) {
520 command += conditions;
521 printf("command: %s\n", command.Data());
522 TGridResult *res = gGrid->Command(command);
524 // Write standard output to file
525 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
527 if (!TestBit(AliAnalysisGrid::kTest) && !FileExists(file)) {
528 // Copy xml file to alien space
529 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
530 if (!FileExists(file)) {
531 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
534 // Update list of files to be processed.
536 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
540 if (fRunNumbers.Length()) {
541 TObjArray *arr = fRunNumbers.Tokenize(" ");
544 while ((os=(TObjString*)next())) {
545 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
546 if (!gGrid->Cd(path)) continue;
548 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
549 else file = Form("%s.xml", os->GetString().Data());
550 // If local collection file does not exist, create it via 'find' command.
551 if (gSystem->AccessPathName(file)) {
556 command += conditions;
557 TGridResult *res = gGrid->Command(command);
559 // Write standard output to file
560 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
562 if (TestBit(AliAnalysisGrid::kTest)) break;
563 // Check if there is one run per master job.
564 if (fNrunsPerMaster<2) {
565 if (FileExists(file)) {
566 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
569 // Copy xml file to alien space
570 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
571 if (!FileExists(file)) {
572 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
578 if (((nruns-1)%fNrunsPerMaster) == 0) {
579 schunk = os->GetString();
580 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
582 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
583 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
587 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
590 schunk += Form("_%s.xml", os->GetString().Data());
591 if (FileExists(schunk)) {
592 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
595 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
596 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
597 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
598 if (!FileExists(schunk)) {
599 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
607 // Process a full run range.
608 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
609 path = Form("%s/%d ", fGridDataDir.Data(), irun);
610 if (!gGrid->Cd(path)) continue;
612 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
613 else file = Form("%d.xml", irun);
614 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
615 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
619 // If local collection file does not exist, create it via 'find' command.
620 if (gSystem->AccessPathName(file)) {
625 command += conditions;
626 TGridResult *res = gGrid->Command(command);
628 // Write standard output to file
629 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
631 if (TestBit(AliAnalysisGrid::kTest)) break;
632 // Check if there is one run per master job.
633 if (fNrunsPerMaster<2) {
634 if (FileExists(file)) {
635 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
638 // Copy xml file to alien space
639 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
640 if (!FileExists(file)) {
641 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
646 // Check if the collection for the chunk exist locally.
647 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
648 if (FileExists(fInputFiles->At(nchunk)->GetName())) continue;
649 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
650 if (((nruns-1)%fNrunsPerMaster) == 0) {
651 schunk = Form("%d", irun);
652 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
654 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
658 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1]) {
661 schunk += Form("_%d.xml", irun);
662 if (FileExists(schunk)) {
663 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
666 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
667 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
668 if (FileExists(schunk)) {
669 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
672 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
673 if (!FileExists(schunk)) {
674 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
683 //______________________________________________________________________________
684 Bool_t AliAnalysisAlien::CreateJDL()
686 // Generate a JDL file according to current settings. The name of the file is
687 // specified by fJDLName.
688 Bool_t error = kFALSE;
691 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
692 Bool_t generate = kTRUE;
693 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
695 Error("CreateJDL", "Alien connection required");
698 // Check validity of alien workspace
700 TString workdir = gGrid->GetHomeDirectory();
701 workdir += fGridWorkingDir;
705 Error("CreateJDL()", "Define some input files for your analysis.");
708 // Compose list of input files
709 // Check if output files were defined
710 if (!fOutputFiles.Length()) {
711 Error("CreateJDL", "You must define at least one output file");
714 // Check if an output directory was defined and valid
715 if (!fGridOutputDir.Length()) {
716 Error("CreateJDL", "You must define AliEn output directory");
719 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
720 if (!gGrid->Cd(fGridOutputDir)) {
721 if (gGrid->Mkdir(fGridOutputDir)) {
722 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
724 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
730 // Exit if any error up to now
731 if (error) return kFALSE;
733 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
734 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
735 fGridJDL->SetExecutable(executable);
736 // fGridJDL->SetTTL((UInt_t)fTTL);
737 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
738 if (fMaxInitFailed > 0)
739 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
740 if (fSplitMaxInputFileNumber > 0)
741 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
742 if (fSplitMode.Length())
743 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
744 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
745 if (fAliROOTVersion.Length())
746 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
747 if (fROOTVersion.Length())
748 fGridJDL->AddToPackages("ROOT", fROOTVersion);
749 if (fAPIVersion.Length())
750 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
751 fGridJDL->SetInputDataListFormat(fInputFormat);
752 fGridJDL->SetInputDataList("wn.xml");
753 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
754 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
755 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
756 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
757 if (fAdditionalLibs.Length()) {
758 arr = fAdditionalLibs.Tokenize(" ");
760 while ((os=(TObjString*)next())) {
761 if (os->GetString().Contains(".so")) continue;
762 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
767 TIter next(fPackages);
770 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
772 if (fOutputArchive.Length()) {
773 arr = fOutputArchive.Tokenize(" ");
775 while ((os=(TObjString*)next()))
776 if (!os->GetString().Contains("@") && fCloseSE.Length())
777 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
779 fGridJDL->AddToOutputArchive(os->GetString());
782 arr = fOutputFiles.Tokenize(" ");
784 while ((os=(TObjString*)next())) {
785 if (!os->GetString().Contains("@") && fCloseSE.Length())
786 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
788 fGridJDL->AddToOutputSandbox(os->GetString());
791 // fGridJDL->SetPrice((UInt_t)fPrice);
792 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
793 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
794 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
795 // Write a jdl with 2 input parameters: collection name and output dir name.
798 // Copy jdl to grid workspace
800 if (fAdditionalLibs.Length()) {
801 arr = fAdditionalLibs.Tokenize(" ");
804 while ((os=(TObjString*)next())) {
805 if (os->GetString().Contains(".so")) continue;
806 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
807 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
808 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
813 TIter next(fPackages);
815 while ((obj=next())) {
816 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
817 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
824 //______________________________________________________________________________
825 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
827 // Writes one or more JDL's corresponding to findex. If findex is negative,
828 // all run numbers are considered in one go (jdl). For non-negative indices
829 // they correspond to the indices in the array fInputFiles.
830 if (!fInputFiles) return kFALSE;
832 TString workdir = gGrid->GetHomeDirectory();
833 workdir += fGridWorkingDir;
835 if (!fRunNumbers.Length() && !fRunRange[0]) {
836 // One jdl with no parameters in case input data is specified by name.
837 TIter next(fInputFiles);
838 while ((os=(TObjString*)next()))
839 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
840 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
842 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
843 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
844 fGridJDL->SetOutputDirectory(Form("%s/$2#alien_counter_03i#", fGridOutputDir.Data()));
848 // Generate the JDL as a string
849 TString sjdl = fGridJDL->Generate();
851 index = sjdl.Index("Executable");
852 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
853 index = sjdl.Index("Split ");
854 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
855 index = sjdl.Index("SplitMaxInputFileNumber");
856 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
857 index = sjdl.Index("InputDataCollection");
858 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
859 index = sjdl.Index("InputFile");
860 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
861 index = sjdl.Index("InputDataList ");
862 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
863 index = sjdl.Index("InputDataListFormat");
864 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
865 index = sjdl.Index("Price");
866 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
867 index = sjdl.Index("Requirements");
868 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
869 index = sjdl.Index("Packages");
870 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
871 index = sjdl.Index("User =");
872 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
873 index = sjdl.Index("TTL");
874 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
875 index = sjdl.Index("OutputFile");
876 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
877 index = sjdl.Index("OutputDir");
878 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
879 index = sjdl.Index("OutputArchive");
880 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
881 index = sjdl.Index("MaxInitFailed");
882 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
883 index = sjdl.Index("MasterResubmitThreshold");
884 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
885 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
886 index = sjdl.Index("Validationcommand");
887 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
888 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
889 sjdl.ReplaceAll("(member", "\n (member");
890 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
891 sjdl.ReplaceAll("{", "{\n ");
892 sjdl.ReplaceAll("};", "\n};");
893 sjdl.ReplaceAll("{\n \n", "{\n");
894 sjdl.ReplaceAll("\n\n", "\n");
895 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
896 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
897 sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
898 index = sjdl.Index("JDLVariables");
899 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
902 out.open(fJDLName.Data(), ios::out);
904 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
909 // Copy jdl to grid workspace
911 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
913 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
914 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
915 if (TObject::TestBit(AliAnalysisGrid::kProductionMode))
916 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
917 if (FileExists(locjdl)) gGrid->Rm(locjdl);
918 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
923 //______________________________________________________________________________
924 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
926 // Returns true if file exists.
927 if (!gGrid) return kFALSE;
928 TGridResult *res = gGrid->Ls(lfn);
929 if (!res) return kFALSE;
930 TMap *map = dynamic_cast<TMap*>(res->At(0));
935 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
936 if (!objs || !objs->GetString().Length()) {
944 //______________________________________________________________________________
945 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
947 // Check input data type.
948 is_collection = kFALSE;
952 Error("CheckDataType", "No connection to grid");
955 is_collection = IsCollection(lfn);
956 TString msg = "\n##### file: ";
959 msg += " type: raw_collection;";
960 // special treatment for collections
962 // check for tag files in the collection
963 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
965 msg += " using_tags: No (unknown)";
966 Info("CheckDataType", msg.Data());
969 const char* typeStr = res->GetKey(0, "origLFN");
970 if (!typeStr || !strlen(typeStr)) {
971 msg += " using_tags: No (unknown)";
972 Info("CheckDataType", msg.Data());
975 TString file = typeStr;
976 use_tags = file.Contains(".tag");
977 if (use_tags) msg += " using_tags: Yes";
978 else msg += " using_tags: No";
979 Info("CheckDataType", msg.Data());
984 is_xml = slfn.Contains(".xml");
986 // Open xml collection and check if there are tag files inside
987 msg += " type: xml_collection;";
988 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
990 msg += " using_tags: No (unknown)";
991 Info("CheckDataType", msg.Data());
994 TMap *map = coll->Next();
996 msg += " using_tags: No (unknown)";
997 Info("CheckDataType", msg.Data());
1000 map = (TMap*)map->GetValue("");
1002 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1003 use_tags = file.Contains(".tag");
1005 if (use_tags) msg += " using_tags: Yes";
1006 else msg += " using_tags: No";
1007 Info("CheckDataType", msg.Data());
1010 use_tags = slfn.Contains(".tag");
1011 if (slfn.Contains(".root")) msg += " type: root file;";
1012 else msg += " type: unhnown file;";
1013 if (use_tags) msg += " using_tags: Yes";
1014 else msg += " using_tags: No";
1015 Info("CheckDataType", msg.Data());
1018 //______________________________________________________________________________
1019 void AliAnalysisAlien::EnablePackage(const char *package)
1021 // Enables a par file supposed to exist in the current directory.
1022 TString pkg(package);
1023 pkg.ReplaceAll(".par", "");
1025 if (gSystem->AccessPathName(pkg)) {
1026 Error("EnablePackage", "Package %s not found", pkg.Data());
1029 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1030 Info("EnablePackage", "AliEn plugin will use .par packages");
1031 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1033 fPackages = new TObjArray();
1034 fPackages->SetOwner();
1036 fPackages->Add(new TObjString(pkg));
1039 //______________________________________________________________________________
1040 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1042 // Get job status for all jobs with jobid>jobidstart.
1043 static char mstatus[20];
1049 TGridJobStatusList *list = gGrid->Ps("");
1050 if (!list) return mstatus;
1051 Int_t nentries = list->GetSize();
1052 TGridJobStatus *status;
1054 for (Int_t ijob=0; ijob<nentries; ijob++) {
1055 status = (TGridJobStatus *)list->At(ijob);
1056 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1057 if (pid<jobidstart) continue;
1058 if (pid == lastid) {
1059 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1061 switch (status->GetStatus()) {
1062 case TGridJobStatus::kWAITING:
1064 case TGridJobStatus::kRUNNING:
1066 case TGridJobStatus::kABORTED:
1067 case TGridJobStatus::kFAIL:
1068 case TGridJobStatus::kUNKNOWN:
1070 case TGridJobStatus::kDONE:
1079 //______________________________________________________________________________
1080 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1082 // Returns true if file is a collection. Functionality duplicated from
1083 // TAlien::Type() because we don't want to directly depend on TAlien.
1085 Error("IsCollection", "No connection to grid");
1088 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1089 if (!res) return kFALSE;
1090 const char* typeStr = res->GetKey(0, "type");
1091 if (!typeStr || !strlen(typeStr)) return kFALSE;
1092 if (!strcmp(typeStr, "collection")) return kTRUE;
1097 //______________________________________________________________________________
1098 void AliAnalysisAlien::Print(Option_t *) const
1100 // Print current plugin settings.
1101 printf("### AliEn analysis plugin current settings ###\n");
1102 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1103 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1104 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1106 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1107 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1108 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1109 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1110 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1111 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1112 if (fRunNumbers.Length())
1113 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1115 printf("= Run range to be processed: ___________________ %d-%d\n", fRunRange[0], fRunRange[1]);
1116 if (!fRunRange[0] && !fRunNumbers.Length()) {
1117 TIter next(fInputFiles);
1120 while ((obj=next())) list += obj->GetName();
1121 printf("= Input files to be processed: _________________ %s\n", list.Data());
1123 if (TestBit(AliAnalysisGrid::kTest))
1124 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1125 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1126 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1127 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1128 printf("=====================================================================\n");
1129 printf("= Job price: ___________________________________ %d\n", fPrice);
1130 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1131 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1132 if (fMaxInitFailed>0)
1133 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1134 if (fMasterResubmitThreshold>0)
1135 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1136 if (fNrunsPerMaster>0)
1137 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1138 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1139 printf("= Name of the generated execution script: ______ %s\n",fExecutable.Data());
1140 if (fArguments.Length())
1141 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1142 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1143 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1144 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1145 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1147 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1148 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1149 if (fIncludePath.Data())
1150 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1151 if (fCloseSE.Length())
1152 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1153 if (fFriendChainName.Length())
1154 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1156 TIter next(fPackages);
1159 while ((obj=next())) list += obj->GetName();
1160 printf("= Par files to be used: ________________________ %s\n", list.Data());
1164 //______________________________________________________________________________
1165 void AliAnalysisAlien::SetDefaults()
1167 // Set default values for everything. What cannot be filled will be left empty.
1168 if (fGridJDL) delete fGridJDL;
1169 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1172 fSplitMaxInputFileNumber = 100;
1174 fMasterResubmitThreshold = 0;
1178 fNrunsPerMaster = 1;
1179 fMaxMergeFiles = 100;
1181 fExecutable = "analysis.sh";
1183 fAnalysisMacro = "myAnalysis.C";
1184 fAnalysisSource = "";
1185 fAdditionalLibs = "";
1189 fAliROOTVersion = "";
1190 fUser = ""; // Your alien user name
1191 fGridWorkingDir = "";
1192 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1193 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1194 fFriendChainName = "";
1195 fGridOutputDir = "output";
1196 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1197 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1198 fInputFormat = "xml-single";
1199 fJDLName = "analysis.jdl";
1200 fMergeExcludes = "";
1203 //______________________________________________________________________________
1204 Bool_t AliAnalysisAlien::MergeOutputs()
1206 // Merge analysis outputs existing in the AliEn space.
1207 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1208 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1210 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1213 // Get the output path
1214 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1215 if (!gGrid->Cd(fGridOutputDir)) {
1216 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1219 if (!fOutputFiles.Length()) {
1220 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1223 TObjArray *list = fOutputFiles.Tokenize(" ");
1227 TString output_file;
1228 TString output_chunk;
1229 TString previous_chunk;
1230 Int_t count_chunk = 0;
1231 Int_t count_zero = fMaxMergeFiles;
1232 Bool_t merged = kTRUE;
1233 while((str=(TObjString*)next())) {
1234 output_file = str->GetString();
1235 Int_t index = output_file.Index("@");
1236 if (index > 0) output_file.Remove(index);
1237 // Skip already merged outputs
1238 if (!gSystem->AccessPathName(output_file)) {
1239 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1242 if (fMergeExcludes.Length() &&
1243 fMergeExcludes.Contains(output_file.Data())) continue;
1244 // Perform a 'find' command in the output directory, looking for registered outputs
1245 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
1246 printf("command: %s\n", command.Data());
1247 TGridResult *res = gGrid->Command(command);
1249 TFileMerger *fm = 0;
1252 previous_chunk = "";
1254 // Check if there is a merge operation to resume
1255 output_chunk = output_file;
1256 output_chunk.ReplaceAll(".root", "_*.root");
1257 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1259 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1261 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1265 output_chunk = output_file;
1266 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1267 printf("%s\n", output_chunk.Data());
1269 if (gSystem->AccessPathName(output_chunk)) continue;
1270 // Merged file with chunks up to <count_chunk> found
1271 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1272 previous_chunk = output_chunk;
1276 count_zero = fMaxMergeFiles;
1277 while ((map=(TMap*)nextmap())) {
1278 // Loop 'find' results and get next LFN
1279 if (count_zero == fMaxMergeFiles) {
1280 // First file in chunk - create file merger and add previous chunk if any.
1281 fm = new TFileMerger(kFALSE);
1282 fm->SetFastMethod(kTRUE);
1283 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1284 output_chunk = output_file;
1285 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1287 // If last file found, put merged results in the output file
1288 if (map == res->Last()) output_chunk = output_file;
1289 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1290 if (!objs || !objs->GetString().Length()) {
1291 // Nothing found - skip this output
1296 // Add file to be merged and decrement chunk counter.
1297 fm->AddFile(objs->GetString());
1299 if (count_zero==0 || map == res->Last()) {
1300 fm->OutputFile(output_chunk);
1301 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1302 // Nothing found - skip this output
1303 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1308 // Merge the outputs, then go to next chunk
1310 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1316 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1317 gSystem->Unlink(previous_chunk);
1319 if (map == res->Last()) {
1325 count_zero = fMaxMergeFiles;
1326 previous_chunk = output_chunk;
1331 Error("MergeOutputs", "Terminate() will NOT be executed");
1336 //______________________________________________________________________________
1337 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1339 // Use the output files connected to output containers from the analysis manager
1340 // rather than the files defined by SetOutputFiles
1341 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1342 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1344 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1347 //______________________________________________________________________________
1348 void AliAnalysisAlien::SetProductionMode(Bool_t flag)
1350 // If production mode is set, all required files are produced and copied to
1351 // AliEn but the master jobs are not submitted. A file .prod containing all
1352 // submit parameters is copied to the work directory.
1353 if (flag && !TObject::TestBit(AliAnalysisGrid::kProductionMode))
1354 Info("SetProductionMode", "Plugin in production mode. Jobs are not submitted.");
1355 TObject::SetBit(AliAnalysisGrid::kProductionMode, flag);
1358 //______________________________________________________________________________
1359 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1361 // Start remote grid analysis.
1363 // Check if output files have to be taken from the analysis manager
1364 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1365 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1366 if (!mgr || !mgr->IsInitialized()) {
1367 Error("StartAnalysis", "You need an initialized analysis manager for this");
1371 TIter next(mgr->GetOutputs());
1372 AliAnalysisDataContainer *output;
1373 while ((output=(AliAnalysisDataContainer*)next())) {
1374 const char *filename = output->GetFileName();
1375 if (!(strcmp(filename, "default"))) {
1376 if (!mgr->GetOutputEventHandler()) continue;
1377 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1379 if (fOutputFiles.Length()) fOutputFiles += " ";
1380 fOutputFiles += filename;
1382 // Add extra files registered to the analysis manager
1383 if (mgr->GetExtraFiles().Length()) {
1384 if (fOutputFiles.Length()) fOutputFiles += " ";
1385 fOutputFiles += mgr->GetExtraFiles();
1388 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1389 if (TestBit(AliAnalysisGrid::kOffline)) {
1390 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1391 \n there nor any job run. You can revise the JDL and analysis \
1392 \n macro then run the same in \"submit\" mode.");
1393 } else if (TestBit(AliAnalysisGrid::kTest)) {
1394 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1396 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1397 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1398 \n space and job submitted.");
1399 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1400 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1403 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1407 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1411 if (!CheckInputData()) {
1412 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1415 CreateDataset(fDataPattern);
1416 WriteAnalysisFile();
1417 WriteAnalysisMacro();
1419 WriteValidationScript();
1420 if (!CreateJDL()) return kFALSE;
1421 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1422 if (TestBit(AliAnalysisGrid::kTest)) {
1423 // Locally testing the analysis
1424 Info("StartAnalysis", "\n_______________________________________________________________________ \
1425 \n Running analysis script in a daughter shell as on a worker node \
1426 \n_______________________________________________________________________");
1427 TObjArray *list = fOutputFiles.Tokenize(" ");
1430 TString output_file;
1431 while((str=(TObjString*)next())) {
1432 output_file = str->GetString();
1433 Int_t index = output_file.Index("@");
1434 if (index > 0) output_file.Remove(index);
1435 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1438 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1439 gSystem->Exec("bash validate.sh");
1440 // gSystem->Exec("cat stdout");
1443 // Check if submitting is managed by LPM manager
1444 if (TObject::TestBit(AliAnalysisGrid::kProductionMode)) {
1445 TString prodfile = fJDLName;
1446 prodfile.ReplaceAll(".jdl", ".prod");
1447 WriteProductionFile(prodfile);
1448 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1451 // Submit AliEn job(s)
1452 gGrid->Cd(fGridOutputDir);
1455 if (!fRunNumbers.Length() && !fRunRange[0]) {
1456 // Submit a given xml or a set of runs
1457 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1458 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1460 const char *cjobId = res->GetKey(0,"jobId");
1462 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1465 Info("StartAnalysis", "\n_______________________________________________________________________ \
1466 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1467 \n_______________________________________________________________________",
1468 fJDLName.Data(), cjobId);
1474 // Submit for a range of enumeration of runs.
1478 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1479 \n You may exit at any time and terminate the job later using the option <terminate> \
1480 \n ##################################################################################", jobID.Data());
1481 gSystem->Exec("aliensh");
1485 //______________________________________________________________________________
1486 void AliAnalysisAlien::Submit()
1488 // Submit all master jobs.
1489 Int_t nmasterjobs = fInputFiles->GetEntries();
1490 Long_t tshoot = gSystem->Now();
1491 if (!fNsubmitted) SubmitNext();
1492 while (fNsubmitted < nmasterjobs) {
1493 Long_t now = gSystem->Now();
1494 if ((now-tshoot)>30000) {
1501 //______________________________________________________________________________
1502 void AliAnalysisAlien::SubmitNext()
1504 // Submit next bunch of master jobs if the queue is free.
1505 static Bool_t iscalled = kFALSE;
1506 static Int_t firstmaster = 0;
1507 static Int_t lastmaster = 0;
1508 static Int_t npermaster = 0;
1509 if (iscalled) return;
1511 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1512 Int_t ntosubmit = 0;
1515 if (!fNsubmitted) ntosubmit = 1;
1517 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1518 printf("=== master %d: %s\n", lastmaster, status.Data());
1519 // If last master not split, just return
1520 if (status != "SPLIT") {iscalled = kFALSE; return;}
1521 // No more than 100 waiting jobs
1522 if (nwaiting>100) {iscalled = kFALSE; return;}
1523 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1524 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1525 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1526 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1528 Int_t nmasterjobs = fInputFiles->GetEntries();
1529 for (Int_t i=0; i<ntosubmit; i++) {
1530 // Submit for a range of enumeration of runs.
1531 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1533 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1534 printf("********* %s\n",query.Data());
1535 res = gGrid->Command(query);
1537 TString cjobId1 = res->GetKey(0,"jobId");
1538 if (!cjobId1.Length()) {
1539 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1543 Info("StartAnalysis", "\n_______________________________________________________________________ \
1544 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1545 \n_______________________________________________________________________",
1546 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1549 lastmaster = cjobId1.Atoi();
1550 if (!firstmaster) firstmaster = lastmaster;
1559 //______________________________________________________________________________
1560 void AliAnalysisAlien::WriteAnalysisFile()
1562 // Write current analysis manager into the file analysis.root
1563 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1564 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1565 if (!mgr || !mgr->IsInitialized()) {
1566 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1569 // Check analysis type
1571 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1572 handler = (TObject*)mgr->GetInputEventHandler();
1574 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1575 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1577 TDirectory *cdir = gDirectory;
1578 TFile *file = TFile::Open("analysis.root", "RECREATE");
1583 if (cdir) cdir->cd();
1584 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1586 Bool_t copy = kTRUE;
1587 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1590 TString workdir = gGrid->GetHomeDirectory();
1591 workdir += fGridWorkingDir;
1592 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1593 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1594 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1598 //______________________________________________________________________________
1599 void AliAnalysisAlien::WriteAnalysisMacro()
1601 // Write the analysis macro that will steer the analysis in grid mode.
1602 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1604 out.open(fAnalysisMacro.Data(), ios::out);
1606 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1609 TString func = fAnalysisMacro;
1610 TString type = "ESD";
1611 TString comment = "// Analysis using ";
1612 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1613 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1617 if (type!="AOD" && fFriendChainName!="") {
1618 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1621 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1622 else comment += " data";
1623 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1624 func.ReplaceAll(".C", "");
1625 out << "void " << func.Data() << "()" << endl;
1627 out << comment.Data() << endl;
1628 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1629 out << " TStopwatch timer;" << endl;
1630 out << " timer.Start();" << endl << endl;
1631 out << "// load base root libraries" << endl;
1632 out << " gSystem->Load(\"libTree\");" << endl;
1633 out << " gSystem->Load(\"libGeom\");" << endl;
1634 out << " gSystem->Load(\"libVMC\");" << endl;
1635 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1636 out << "// Load analysis framework libraries" << endl;
1638 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1639 out << " gSystem->Load(\"libESD\");" << endl;
1640 out << " gSystem->Load(\"libAOD\");" << endl;
1641 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1642 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1643 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1645 TIter next(fPackages);
1648 Bool_t hasSTEERBase = kFALSE;
1649 Bool_t hasESD = kFALSE;
1650 Bool_t hasAOD = kFALSE;
1651 Bool_t hasANALYSIS = kFALSE;
1652 Bool_t hasANALYSISalice = kFALSE;
1653 Bool_t hasCORRFW = kFALSE;
1654 while ((obj=next())) {
1655 pkgname = obj->GetName();
1656 if (pkgname == "STEERBase" ||
1657 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1658 if (pkgname == "ESD" ||
1659 pkgname == "ESD.par") hasESD = kTRUE;
1660 if (pkgname == "AOD" ||
1661 pkgname == "AOD.par") hasAOD = kTRUE;
1662 if (pkgname == "ANALYSIS" ||
1663 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1664 if (pkgname == "ANALYSISalice" ||
1665 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1666 if (pkgname == "CORRFW" ||
1667 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1669 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1670 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1671 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1672 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1673 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1674 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1675 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1676 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1677 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1678 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1679 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1680 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1681 out << "// Compile other par packages" << endl;
1683 while ((obj=next())) {
1684 pkgname = obj->GetName();
1685 if (pkgname == "STEERBase" ||
1686 pkgname == "STEERBase.par" ||
1688 pkgname == "ESD.par" ||
1690 pkgname == "AOD.par" ||
1691 pkgname == "ANALYSIS" ||
1692 pkgname == "ANALYSIS.par" ||
1693 pkgname == "ANALYSISalice" ||
1694 pkgname == "ANALYSISalice.par" ||
1695 pkgname == "CORRFW" ||
1696 pkgname == "CORRFW.par") continue;
1697 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1700 out << "// include path" << endl;
1701 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1702 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1703 if (fAdditionalLibs.Length()) {
1704 out << "// Add aditional AliRoot libraries" << endl;
1705 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1708 while((str=(TObjString*)next())) {
1709 if (str->GetString().Contains(".so"))
1710 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1712 if (list) delete list;
1715 out << "// analysis source to be compiled at runtime (if any)" << endl;
1716 if (fAnalysisSource.Length()) {
1717 TObjArray *list = fAnalysisSource.Tokenize(" ");
1720 while((str=(TObjString*)next())) {
1721 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1723 if (list) delete list;
1726 out << "// connect to AliEn and make the chain" << endl;
1727 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1728 if (IsUsingTags()) {
1729 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1731 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1733 out << "// read the analysis manager from file" << endl;
1734 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1735 out << " if (!file) return;" << endl;
1736 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1737 out << " AliAnalysisManager *mgr = 0;" << endl;
1738 out << " TKey *key;" << endl;
1739 out << " while ((key=(TKey*)nextkey())) {" << endl;
1740 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1741 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1742 out << " };" << endl;
1743 out << " if (!mgr) {" << endl;
1744 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1745 out << " return;" << endl;
1746 out << " }" << endl << endl;
1747 out << " mgr->PrintStatus();" << endl;
1748 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1749 out << " timer.Stop();" << endl;
1750 out << " timer.Print();" << endl;
1751 out << "}" << endl << endl;
1752 if (IsUsingTags()) {
1753 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1755 out << "// Create a chain using tags from the xml file." << endl;
1756 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1757 out << " if (!coll) {" << endl;
1758 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1759 out << " return NULL;" << endl;
1760 out << " }" << endl;
1761 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1762 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1763 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1764 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1765 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1766 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1767 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1768 out << " // Check if the cuts configuration file was provided" << endl;
1769 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1770 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1771 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1772 out << " }" << endl;
1773 if (fFriendChainName=="") {
1774 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1776 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1777 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1778 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1780 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1781 out << " chain->ls();" << endl;
1782 out << " return chain;" << endl;
1783 out << "}" << endl << endl;
1784 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1785 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1786 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1787 msg += " AliLHCTagCuts *lhcCuts,\n";
1788 msg += " AliDetectorTagCuts *detCuts,\n";
1789 msg += " AliEventTagCuts *evCuts)";
1790 Info("WriteAnalysisMacro", msg.Data());
1793 if (!IsUsingTags() || fFriendChainName!="") {
1794 out <<"//________________________________________________________________________________" << endl;
1795 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1797 out << "// Create a chain using url's from xml file" << endl;
1798 out << " TString treename = type;" << endl;
1799 out << " treename.ToLower();" << endl;
1800 out << " treename += \"Tree\";" << endl;
1801 out << " printf(\"***************************************\\n\");" << endl;
1802 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1803 out << " printf(\"***************************************\\n\");" << endl;
1804 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1805 out << " if (!coll) {" << endl;
1806 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1807 out << " return NULL;" << endl;
1808 out << " }" << endl;
1809 out << " TChain *chain = new TChain(treename);" << endl;
1810 if(fFriendChainName!="") {
1811 out << " TChain *chainFriend = new TChain(treename);" << endl;
1813 out << " coll->Reset();" << endl;
1814 out << " while (coll->Next()) {" << endl;
1815 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1816 if(fFriendChainName!="") {
1817 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1818 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1819 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1820 out << " chainFriend->Add(fileFriend.Data());" << endl;
1822 out << " }" << endl;
1823 out << " if (!chain->GetNtrees()) {" << endl;
1824 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1825 out << " return NULL;" << endl;
1826 out << " }" << endl;
1827 if(fFriendChainName!="") {
1828 out << " chain->AddFriend(chainFriend);" << endl;
1830 out << " return chain;" << endl;
1831 out << "}" << endl << endl;
1834 out <<"//________________________________________________________________________________" << endl;
1835 out << "Bool_t SetupPar(const char *package) {" << endl;
1836 out << "// Compile the package and set it up." << endl;
1837 out << " TString pkgdir = package;" << endl;
1838 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1839 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1840 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1841 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1842 out << " // Check for BUILD.sh and execute" << endl;
1843 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1844 out << " printf(\"*******************************\\n\");" << endl;
1845 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1846 out << " printf(\"*******************************\\n\");" << endl;
1847 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1848 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1849 out << " gSystem->ChangeDirectory(cdir);" << endl;
1850 out << " return kFALSE;" << endl;
1851 out << " }" << endl;
1852 out << " } else {" << endl;
1853 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1854 out << " gSystem->ChangeDirectory(cdir);" << endl;
1855 out << " return kFALSE;" << endl;
1856 out << " }" << endl;
1857 out << " // Check for SETUP.C and execute" << endl;
1858 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1859 out << " printf(\"*******************************\\n\");" << endl;
1860 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1861 out << " printf(\"*******************************\\n\");" << endl;
1862 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1863 out << " } else {" << endl;
1864 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
1865 out << " gSystem->ChangeDirectory(cdir);" << endl;
1866 out << " return kFALSE;" << endl;
1867 out << " }" << endl;
1868 out << " // Restore original workdir" << endl;
1869 out << " gSystem->ChangeDirectory(cdir);" << endl;
1870 out << " return kTRUE;" << endl;
1873 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1875 Bool_t copy = kTRUE;
1876 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1879 TString workdir = gGrid->GetHomeDirectory();
1880 workdir += fGridWorkingDir;
1881 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1882 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1883 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1884 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1885 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1887 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1888 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1892 //______________________________________________________________________________
1893 void AliAnalysisAlien::WriteExecutable()
1895 // Generate the alien executable script.
1896 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1898 out.open(fExecutable.Data(), ios::out);
1900 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
1903 out << "#!/bin/bash" << endl;
1904 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1905 out << "echo \"=========================================\"" << endl;
1906 out << "echo \"############## PATH : ##############\"" << endl;
1907 out << "echo $PATH" << endl;
1908 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1909 out << "echo $LD_LIBRARY_PATH" << endl;
1910 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1911 out << "echo $ROOTSYS" << endl;
1912 out << "echo \"############## which root : ##############\"" << endl;
1913 out << "which root" << endl;
1914 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1915 out << "echo $ALICE_ROOT" << endl;
1916 out << "echo \"############## which aliroot : ##############\"" << endl;
1917 out << "which aliroot" << endl;
1918 out << "echo \"=========================================\"" << endl << endl;
1919 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1920 out << "root -b -q ";
1921 out << fAnalysisMacro.Data() << endl << endl;
1922 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1924 Bool_t copy = kTRUE;
1925 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1928 TString workdir = gGrid->GetHomeDirectory();
1929 workdir += fGridWorkingDir;
1930 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1931 if (FileExists(executable)) gGrid->Rm(executable);
1932 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1933 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1937 //______________________________________________________________________________
1938 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
1940 // Write the production file to be submitted by LPM manager. The format is:
1941 // First line: full_path_to_jdl estimated_no_subjobs_per_master
1942 // Next lines: full_path_to_dataset XXX (XXX is a string)
1943 // To submit, one has to: submit jdl XXX for all lines
1945 out.open(filename, ios::out);
1947 Error("WriteProductionFile", "Bad file name: %s", filename);
1950 TString workdir = gGrid->GetHomeDirectory();
1951 workdir += fGridWorkingDir;
1952 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
1953 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1954 out << locjdl << " " << njobspermaster << endl;
1955 Int_t nmasterjobs = fInputFiles->GetEntries();
1956 for (Int_t i=0; i<nmasterjobs; i++) {
1957 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
1959 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
1960 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
1963 //______________________________________________________________________________
1964 void AliAnalysisAlien::WriteValidationScript()
1966 // Generate the alien validation script.
1967 // Generate the validation script
1970 Error("WriteValidationScript", "Alien connection required");
1973 TString out_stream = "";
1974 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1975 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1977 out.open("validate.sh", ios::out);
1978 out << "#!/bin/bash" << endl;
1979 out << "##################################################" << endl;
1980 out << "validateout=`dirname $0`" << endl;
1981 out << "validatetime=`date`" << endl;
1982 out << "validated=\"0\";" << endl;
1983 out << "error=0" << endl;
1984 out << "if [ -z $validateout ]" << endl;
1985 out << "then" << endl;
1986 out << " validateout=\".\"" << endl;
1987 out << "fi" << endl << endl;
1988 out << "cd $validateout;" << endl;
1989 out << "validateworkdir=`pwd`;" << endl << endl;
1990 out << "echo \"*******************************************************\"" << out_stream << endl;
1991 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1993 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1994 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1995 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1996 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1997 out << "ls -la ./" << out_stream << endl;
1998 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1999 out << "##################################################" << endl;
2002 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2003 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2004 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2007 out << "if [ ! -f stderr ] ; then" << endl;
2008 out << " error=1" << endl;
2009 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2010 out << " echo \"Error = $error\" " << out_stream << endl;
2011 out << "fi" << endl;
2013 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2014 out << " error=1" << endl;
2015 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2016 out << " echo \"$parArch\" " << out_stream << endl;
2017 out << " echo \"Error = $error\" " << out_stream << endl;
2018 out << "fi" << endl;
2020 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2021 out << " error=1" << endl;
2022 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2023 out << " echo \"$segViol\" " << out_stream << endl;
2024 out << " echo \"Error = $error\" " << out_stream << endl;
2025 out << "fi" << endl;
2027 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2028 out << " error=1" << endl;
2029 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2030 out << " echo \"$segFault\" " << out_stream << endl;
2031 out << " echo \"Error = $error\" " << out_stream << endl;
2032 out << "fi" << endl;
2034 // Part dedicated to the specific analyses running into the train
2036 TObjArray *arr = fOutputFiles.Tokenize(" ");
2038 TString output_file;
2039 while ((os=(TObjString*)next1())) {
2040 output_file = os->GetString();
2041 Int_t index = output_file.Index("@");
2042 if (index > 0) output_file.Remove(index);
2043 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2044 out << " error=1" << endl;
2045 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2046 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2047 out << "fi" << endl;
2050 out << "if [ $error = 0 ] ; then" << endl;
2051 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2052 out << "fi" << endl;
2054 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2055 out << "echo \"*******************************************************\"" << out_stream << endl;
2056 out << "cd -" << endl;
2057 out << "exit $error" << endl;
2059 Bool_t copy = kTRUE;
2060 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2063 TString workdir = gGrid->GetHomeDirectory();
2064 workdir += fGridWorkingDir;
2065 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
2066 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
2067 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));