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 fGridJDL->SetExecutable(fExecutable);
735 // fGridJDL->SetTTL((UInt_t)fTTL);
736 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
737 if (fMaxInitFailed > 0)
738 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
739 if (fSplitMaxInputFileNumber > 0)
740 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
741 if (fSplitMode.Length())
742 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
743 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
744 if (fAliROOTVersion.Length())
745 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
746 if (fROOTVersion.Length())
747 fGridJDL->AddToPackages("ROOT", fROOTVersion);
748 if (fAPIVersion.Length())
749 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
750 fGridJDL->SetInputDataListFormat(fInputFormat);
751 fGridJDL->SetInputDataList("wn.xml");
752 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
753 fGridJDL->AddToInputSandbox(Form("LF:%s/analysis.root", workdir.Data()));
754 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
755 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
756 if (fAdditionalLibs.Length()) {
757 arr = fAdditionalLibs.Tokenize(" ");
759 while ((os=(TObjString*)next())) {
760 if (os->GetString().Contains(".so")) continue;
761 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
766 TIter next(fPackages);
769 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
771 if (fOutputArchive.Length()) {
772 arr = fOutputArchive.Tokenize(" ");
774 while ((os=(TObjString*)next()))
775 if (!os->GetString().Contains("@") && fCloseSE.Length())
776 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
778 fGridJDL->AddToOutputArchive(os->GetString());
781 arr = fOutputFiles.Tokenize(" ");
783 while ((os=(TObjString*)next())) {
784 if (!os->GetString().Contains("@") && fCloseSE.Length())
785 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
787 fGridJDL->AddToOutputSandbox(os->GetString());
790 // fGridJDL->SetPrice((UInt_t)fPrice);
791 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
792 fGridJDL->SetValidationCommand(Form("%s/validate.sh", workdir.Data()));
793 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
794 // Write a jdl with 2 input parameters: collection name and output dir name.
797 // Copy jdl to grid workspace
799 if (fAdditionalLibs.Length()) {
800 arr = fAdditionalLibs.Tokenize(" ");
803 while ((os=(TObjString*)next())) {
804 if (os->GetString().Contains(".so")) continue;
805 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
806 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
807 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
812 TIter next(fPackages);
814 while ((obj=next())) {
815 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
816 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
823 //______________________________________________________________________________
824 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
826 // Writes one or more JDL's corresponding to findex. If findex is negative,
827 // all run numbers are considered in one go (jdl). For non-negative indices
828 // they correspond to the indices in the array fInputFiles.
829 if (!fInputFiles) return kFALSE;
831 TString workdir = gGrid->GetHomeDirectory();
832 workdir += fGridWorkingDir;
834 if (!fRunNumbers.Length() && !fRunRange[0]) {
835 // One jdl with no parameters in case input data is specified by name.
836 TIter next(fInputFiles);
837 while ((os=(TObjString*)next()))
838 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
839 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
841 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
842 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
843 fGridJDL->SetOutputDirectory(Form("%s/$2#alien_counter_03i#", fGridOutputDir.Data()));
847 // Generate the JDL as a string
848 TString sjdl = fGridJDL->Generate();
850 index = sjdl.Index("Executable");
851 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
852 index = sjdl.Index("Split ");
853 if (index >= 0) sjdl.Insert(index, "\n# We split per storage element\n");
854 index = sjdl.Index("SplitMaxInputFileNumber");
855 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
856 index = sjdl.Index("InputDataCollection");
857 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
858 index = sjdl.Index("InputFile");
859 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
860 index = sjdl.Index("InputDataList ");
861 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
862 index = sjdl.Index("InputDataListFormat");
863 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
864 index = sjdl.Index("Price");
865 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
866 index = sjdl.Index("Requirements");
867 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
868 index = sjdl.Index("Packages");
869 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
870 index = sjdl.Index("User =");
871 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
872 index = sjdl.Index("TTL");
873 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
874 index = sjdl.Index("OutputFile");
875 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
876 index = sjdl.Index("OutputDir");
877 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
878 index = sjdl.Index("OutputArchive");
879 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
880 index = sjdl.Index("MaxInitFailed");
881 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
882 index = sjdl.Index("MasterResubmitThreshold");
883 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
884 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
885 index = sjdl.Index("Validationcommand");
886 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
887 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
888 sjdl.ReplaceAll("(member", "\n (member");
889 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
890 sjdl.ReplaceAll("{", "{\n ");
891 sjdl.ReplaceAll("};", "\n};");
892 sjdl.ReplaceAll("{\n \n", "{\n");
893 sjdl.ReplaceAll("\n\n", "\n");
894 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
895 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
896 sjdl.Prepend("JobTag = \"Automatically generated analysis JDL\";\n");
897 index = sjdl.Index("JDLVariables");
898 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
901 out.open(fJDLName.Data(), ios::out);
903 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
908 // Copy jdl to grid workspace
910 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
912 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
913 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
914 if (FileExists(locjdl)) gGrid->Rm(locjdl);
915 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s/%s", fGridOutputDir.Data(), fJDLName.Data()));
920 //______________________________________________________________________________
921 Bool_t AliAnalysisAlien::FileExists(const char *lfn) const
923 // Returns true if file exists.
925 Error("FileExists", "No connection to grid");
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::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1350 // Start remote grid analysis.
1352 // Check if output files have to be taken from the analysis manager
1353 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1354 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1355 if (!mgr || !mgr->IsInitialized()) {
1356 Error("StartAnalysis", "You need an initialized analysis manager for this");
1360 TIter next(mgr->GetOutputs());
1361 AliAnalysisDataContainer *output;
1362 while ((output=(AliAnalysisDataContainer*)next())) {
1363 const char *filename = output->GetFileName();
1364 if (!(strcmp(filename, "default"))) {
1365 if (!mgr->GetOutputEventHandler()) continue;
1366 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1368 if (fOutputFiles.Length()) fOutputFiles += " ";
1369 fOutputFiles += filename;
1371 // Add extra files registered to the analysis manager
1372 if (mgr->GetExtraFiles().Length()) {
1373 if (fOutputFiles.Length()) fOutputFiles += " ";
1374 fOutputFiles += mgr->GetExtraFiles();
1377 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1378 if (TestBit(AliAnalysisGrid::kOffline)) {
1379 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1380 \n there nor any job run. You can revise the JDL and analysis \
1381 \n macro then run the same in \"submit\" mode.");
1382 } else if (TestBit(AliAnalysisGrid::kTest)) {
1383 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1385 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1386 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1387 \n space and job submitted.");
1388 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1389 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1392 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1396 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1400 if (!CheckInputData()) {
1401 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1404 CreateDataset(fDataPattern);
1405 WriteAnalysisFile();
1406 WriteAnalysisMacro();
1408 WriteValidationScript();
1409 if (!CreateJDL()) return;
1410 if (TestBit(AliAnalysisGrid::kOffline)) return;
1411 if (TestBit(AliAnalysisGrid::kTest)) {
1412 // Locally testing the analysis
1413 Info("StartAnalysis", "\n_______________________________________________________________________ \
1414 \n Running analysis script in a daughter shell as on a worker node \
1415 \n_______________________________________________________________________");
1416 TObjArray *list = fOutputFiles.Tokenize(" ");
1419 TString output_file;
1420 while((str=(TObjString*)next())) {
1421 output_file = str->GetString();
1422 Int_t index = output_file.Index("@");
1423 if (index > 0) output_file.Remove(index);
1424 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1427 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1428 gSystem->Exec("bash validate.sh");
1429 // gSystem->Exec("cat stdout");
1432 // Submit AliEn job(s)
1433 gGrid->Cd(fGridOutputDir);
1436 if (!fRunNumbers.Length() && !fRunRange[0]) {
1437 // Submit a given xml or a set of runs
1438 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1439 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1441 const char *cjobId = res->GetKey(0,"jobId");
1443 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1446 Info("StartAnalysis", "\n_______________________________________________________________________ \
1447 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1448 \n_______________________________________________________________________",
1449 fJDLName.Data(), cjobId);
1455 // Submit for a range of enumeration of runs.
1459 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1460 \n You may exit at any time and terminate the job later using the option <terminate> \
1461 \n ##################################################################################", jobID.Data());
1462 gSystem->Exec("aliensh");
1465 //______________________________________________________________________________
1466 void AliAnalysisAlien::Submit()
1468 // Submit all master jobs.
1469 Int_t nmasterjobs = fInputFiles->GetEntries();
1470 Long_t tshoot = gSystem->Now();
1471 if (!fNsubmitted) SubmitNext();
1472 while (fNsubmitted < nmasterjobs) {
1473 Long_t now = gSystem->Now();
1474 if ((now-tshoot)>30000) {
1481 //______________________________________________________________________________
1482 void AliAnalysisAlien::SubmitNext()
1484 // Submit next bunch of master jobs if the queue is free.
1485 static Bool_t iscalled = kFALSE;
1486 static Int_t firstmaster = 0;
1487 static Int_t lastmaster = 0;
1488 static Int_t npermaster = 0;
1489 if (iscalled) return;
1491 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1492 Int_t ntosubmit = 0;
1495 if (!fNsubmitted) ntosubmit = 1;
1497 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1498 printf("=== master %d: %s\n", lastmaster, status.Data());
1499 // If last master not split, just return
1500 if (status != "SPLIT") {iscalled = kFALSE; return;}
1501 // No more than 100 waiting jobs
1502 if (nwaiting>100) {iscalled = kFALSE; return;}
1503 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1504 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1505 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1506 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1508 Int_t nmasterjobs = fInputFiles->GetEntries();
1509 for (Int_t i=0; i<ntosubmit; i++) {
1510 // Submit for a range of enumeration of runs.
1511 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1513 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1514 printf("********* %s\n",query.Data());
1515 res = gGrid->Command(query);
1517 TString cjobId1 = res->GetKey(0,"jobId");
1518 if (!cjobId1.Length()) {
1519 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1523 Info("StartAnalysis", "\n_______________________________________________________________________ \
1524 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1525 \n_______________________________________________________________________",
1526 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1529 lastmaster = cjobId1.Atoi();
1530 if (!firstmaster) firstmaster = lastmaster;
1539 //______________________________________________________________________________
1540 void AliAnalysisAlien::WriteAnalysisFile()
1542 // Write current analysis manager into the file analysis.root
1543 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1544 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1545 if (!mgr || !mgr->IsInitialized()) {
1546 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1549 // Check analysis type
1551 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1552 handler = (TObject*)mgr->GetInputEventHandler();
1554 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1555 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1557 TDirectory *cdir = gDirectory;
1558 TFile *file = TFile::Open("analysis.root", "RECREATE");
1563 if (cdir) cdir->cd();
1564 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <analysis.root>\n", mgr->GetName());
1566 Bool_t copy = kTRUE;
1567 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1570 TString workdir = gGrid->GetHomeDirectory();
1571 workdir += fGridWorkingDir;
1572 Info("CreateJDL", "\n##### Copying file <analysis.root> containing your initialized analysis manager to your alien workspace");
1573 if (FileExists("analysis.root")) gGrid->Rm("analysis.root");
1574 TFile::Cp("file:analysis.root", Form("alien://%s/analysis.root", workdir.Data()));
1578 //______________________________________________________________________________
1579 void AliAnalysisAlien::WriteAnalysisMacro()
1581 // Write the analysis macro that will steer the analysis in grid mode.
1582 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1584 out.open(fAnalysisMacro.Data(), ios::out);
1586 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1589 TString func = fAnalysisMacro;
1590 TString type = "ESD";
1591 TString comment = "// Analysis using ";
1592 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1593 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1597 if (type!="AOD" && fFriendChainName!="") {
1598 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1601 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1602 else comment += " data";
1603 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1604 func.ReplaceAll(".C", "");
1605 out << "void " << func.Data() << "()" << endl;
1607 out << comment.Data() << endl;
1608 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1609 out << " TStopwatch timer;" << endl;
1610 out << " timer.Start();" << endl << endl;
1611 out << "// load base root libraries" << endl;
1612 out << " gSystem->Load(\"libTree\");" << endl;
1613 out << " gSystem->Load(\"libGeom\");" << endl;
1614 out << " gSystem->Load(\"libVMC\");" << endl;
1615 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1616 out << "// Load analysis framework libraries" << endl;
1618 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1619 out << " gSystem->Load(\"libESD\");" << endl;
1620 out << " gSystem->Load(\"libAOD\");" << endl;
1621 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1622 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1623 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1625 TIter next(fPackages);
1628 Bool_t hasSTEERBase = kFALSE;
1629 Bool_t hasESD = kFALSE;
1630 Bool_t hasAOD = kFALSE;
1631 Bool_t hasANALYSIS = kFALSE;
1632 Bool_t hasANALYSISalice = kFALSE;
1633 Bool_t hasCORRFW = kFALSE;
1634 while ((obj=next())) {
1635 pkgname = obj->GetName();
1636 if (pkgname == "STEERBase" ||
1637 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1638 if (pkgname == "ESD" ||
1639 pkgname == "ESD.par") hasESD = kTRUE;
1640 if (pkgname == "AOD" ||
1641 pkgname == "AOD.par") hasAOD = kTRUE;
1642 if (pkgname == "ANALYSIS" ||
1643 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1644 if (pkgname == "ANALYSISalice" ||
1645 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1646 if (pkgname == "CORRFW" ||
1647 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1649 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1650 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1651 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1652 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1653 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1654 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1655 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1656 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1657 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1658 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1659 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1660 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1661 out << "// Compile other par packages" << endl;
1663 while ((obj=next())) {
1664 pkgname = obj->GetName();
1665 if (pkgname == "STEERBase" ||
1666 pkgname == "STEERBase.par" ||
1668 pkgname == "ESD.par" ||
1670 pkgname == "AOD.par" ||
1671 pkgname == "ANALYSIS" ||
1672 pkgname == "ANALYSIS.par" ||
1673 pkgname == "ANALYSISalice" ||
1674 pkgname == "ANALYSISalice.par" ||
1675 pkgname == "CORRFW" ||
1676 pkgname == "CORRFW.par") continue;
1677 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1680 out << "// include path" << endl;
1681 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1682 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1683 if (fAdditionalLibs.Length()) {
1684 out << "// Add aditional AliRoot libraries" << endl;
1685 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1688 while((str=(TObjString*)next())) {
1689 if (str->GetString().Contains(".so"))
1690 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1692 if (list) delete list;
1695 out << "// analysis source to be compiled at runtime (if any)" << endl;
1696 if (fAnalysisSource.Length()) {
1697 TObjArray *list = fAnalysisSource.Tokenize(" ");
1700 while((str=(TObjString*)next())) {
1701 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1703 if (list) delete list;
1706 out << "// connect to AliEn and make the chain" << endl;
1707 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1708 if (IsUsingTags()) {
1709 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1711 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1713 out << "// read the analysis manager from file" << endl;
1714 out << " TFile *file = TFile::Open(\"analysis.root\");" << endl;
1715 out << " if (!file) return;" << endl;
1716 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1717 out << " AliAnalysisManager *mgr = 0;" << endl;
1718 out << " TKey *key;" << endl;
1719 out << " while ((key=(TKey*)nextkey())) {" << endl;
1720 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1721 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1722 out << " };" << endl;
1723 out << " if (!mgr) {" << endl;
1724 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file analysis.root\");" << endl;
1725 out << " return;" << endl;
1726 out << " }" << endl << endl;
1727 out << " mgr->PrintStatus();" << endl;
1728 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1729 out << " timer.Stop();" << endl;
1730 out << " timer.Print();" << endl;
1731 out << "}" << endl << endl;
1732 if (IsUsingTags()) {
1733 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1735 out << "// Create a chain using tags from the xml file." << endl;
1736 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1737 out << " if (!coll) {" << endl;
1738 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1739 out << " return NULL;" << endl;
1740 out << " }" << endl;
1741 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1742 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1743 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1744 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1745 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1746 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1747 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1748 out << " // Check if the cuts configuration file was provided" << endl;
1749 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1750 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1751 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1752 out << " }" << endl;
1753 if (fFriendChainName=="") {
1754 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1756 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1757 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1758 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1760 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1761 out << " chain->ls();" << endl;
1762 out << " return chain;" << endl;
1763 out << "}" << endl << endl;
1764 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1765 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1766 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1767 msg += " AliLHCTagCuts *lhcCuts,\n";
1768 msg += " AliDetectorTagCuts *detCuts,\n";
1769 msg += " AliEventTagCuts *evCuts)";
1770 Info("WriteAnalysisMacro", msg.Data());
1773 if (!IsUsingTags() || fFriendChainName!="") {
1774 out <<"//________________________________________________________________________________" << endl;
1775 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1777 out << "// Create a chain using url's from xml file" << endl;
1778 out << " TString treename = type;" << endl;
1779 out << " treename.ToLower();" << endl;
1780 out << " treename += \"Tree\";" << endl;
1781 out << " printf(\"***************************************\\n\");" << endl;
1782 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1783 out << " printf(\"***************************************\\n\");" << endl;
1784 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1785 out << " if (!coll) {" << endl;
1786 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1787 out << " return NULL;" << endl;
1788 out << " }" << endl;
1789 out << " TChain *chain = new TChain(treename);" << endl;
1790 if(fFriendChainName!="") {
1791 out << " TChain *chainFriend = new TChain(treename);" << endl;
1793 out << " coll->Reset();" << endl;
1794 out << " while (coll->Next()) {" << endl;
1795 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1796 if(fFriendChainName!="") {
1797 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1798 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1799 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1800 out << " chainFriend->Add(fileFriend.Data());" << endl;
1802 out << " }" << endl;
1803 out << " if (!chain->GetNtrees()) {" << endl;
1804 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1805 out << " return NULL;" << endl;
1806 out << " }" << endl;
1807 if(fFriendChainName!="") {
1808 out << " chain->AddFriend(chainFriend);" << endl;
1810 out << " return chain;" << endl;
1811 out << "}" << endl << endl;
1814 out <<"//________________________________________________________________________________" << endl;
1815 out << "Bool_t SetupPar(const char *package) {" << endl;
1816 out << "// Compile the package and set it up." << endl;
1817 out << " TString pkgdir = package;" << endl;
1818 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1819 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1820 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1821 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1822 out << " // Check for BUILD.sh and execute" << endl;
1823 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1824 out << " printf(\"*******************************\\n\");" << endl;
1825 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1826 out << " printf(\"*******************************\\n\");" << endl;
1827 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1828 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1829 out << " gSystem->ChangeDirectory(cdir);" << endl;
1830 out << " return kFALSE;" << endl;
1831 out << " }" << endl;
1832 out << " } else {" << endl;
1833 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1834 out << " gSystem->ChangeDirectory(cdir);" << endl;
1835 out << " return kFALSE;" << endl;
1836 out << " }" << endl;
1837 out << " // Check for SETUP.C and execute" << endl;
1838 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1839 out << " printf(\"*******************************\\n\");" << endl;
1840 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
1841 out << " printf(\"*******************************\\n\");" << endl;
1842 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
1843 out << " } else {" << endl;
1844 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
1845 out << " gSystem->ChangeDirectory(cdir);" << endl;
1846 out << " return kFALSE;" << endl;
1847 out << " }" << endl;
1848 out << " // Restore original workdir" << endl;
1849 out << " gSystem->ChangeDirectory(cdir);" << endl;
1850 out << " return kTRUE;" << endl;
1853 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
1855 Bool_t copy = kTRUE;
1856 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1859 TString workdir = gGrid->GetHomeDirectory();
1860 workdir += fGridWorkingDir;
1861 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
1862 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
1863 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
1864 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
1865 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
1867 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
1868 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
1872 //______________________________________________________________________________
1873 void AliAnalysisAlien::WriteExecutable()
1875 // Generate the alien executable script.
1876 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1878 out.open(fExecutable.Data(), ios::out);
1880 Error("CreateJDL", "Bad file name for executable: %s", fExecutable.Data());
1883 out << "#!/bin/bash" << endl;
1884 out << "export GCLIENT_SERVER_LIST=\"pcapiserv04.cern.ch:10000|pcapiserv05.cern.ch:10000|pcapiserv06.cern.ch:10000|pcapiserv07.cern.ch:10000\"" << endl;
1885 out << "echo \"=========================================\"" << endl;
1886 out << "echo \"############## PATH : ##############\"" << endl;
1887 out << "echo $PATH" << endl;
1888 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
1889 out << "echo $LD_LIBRARY_PATH" << endl;
1890 out << "echo \"############## ROOTSYS : ##############\"" << endl;
1891 out << "echo $ROOTSYS" << endl;
1892 out << "echo \"############## which root : ##############\"" << endl;
1893 out << "which root" << endl;
1894 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
1895 out << "echo $ALICE_ROOT" << endl;
1896 out << "echo \"############## which aliroot : ##############\"" << endl;
1897 out << "which aliroot" << endl;
1898 out << "echo \"=========================================\"" << endl << endl;
1899 // if (TestBit(AliAnalysisGrid::kTest)) out << "root ";
1900 out << "root -b -q ";
1901 out << fAnalysisMacro.Data() << endl << endl;
1902 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
1904 Bool_t copy = kTRUE;
1905 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1908 TString workdir = gGrid->GetHomeDirectory();
1909 workdir += fGridWorkingDir;
1910 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
1911 if (FileExists(executable)) gGrid->Rm(executable);
1912 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
1913 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
1917 //______________________________________________________________________________
1918 void AliAnalysisAlien::WriteValidationScript()
1920 // Generate the alien validation script.
1921 // Generate the validation script
1924 Error("WriteValidationScript", "Alien connection required");
1927 TString out_stream = "";
1928 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
1929 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1931 out.open("validate.sh", ios::out);
1932 out << "#!/bin/bash" << endl;
1933 out << "##################################################" << endl;
1934 out << "validateout=`dirname $0`" << endl;
1935 out << "validatetime=`date`" << endl;
1936 out << "validated=\"0\";" << endl;
1937 out << "error=0" << endl;
1938 out << "if [ -z $validateout ]" << endl;
1939 out << "then" << endl;
1940 out << " validateout=\".\"" << endl;
1941 out << "fi" << endl << endl;
1942 out << "cd $validateout;" << endl;
1943 out << "validateworkdir=`pwd`;" << endl << endl;
1944 out << "echo \"*******************************************************\"" << out_stream << endl;
1945 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
1947 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
1948 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
1949 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
1950 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
1951 out << "ls -la ./" << out_stream << endl;
1952 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
1953 out << "##################################################" << endl;
1956 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
1957 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
1958 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
1961 out << "if [ ! -f stderr ] ; then" << endl;
1962 out << " error=1" << endl;
1963 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
1964 out << " echo \"Error = $error\" " << out_stream << endl;
1965 out << "fi" << endl;
1967 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
1968 out << " error=1" << endl;
1969 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
1970 out << " echo \"$parArch\" " << out_stream << endl;
1971 out << " echo \"Error = $error\" " << out_stream << endl;
1972 out << "fi" << endl;
1974 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
1975 out << " error=1" << endl;
1976 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
1977 out << " echo \"$segViol\" " << out_stream << endl;
1978 out << " echo \"Error = $error\" " << out_stream << endl;
1979 out << "fi" << endl;
1981 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
1982 out << " error=1" << endl;
1983 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
1984 out << " echo \"$segFault\" " << out_stream << endl;
1985 out << " echo \"Error = $error\" " << out_stream << endl;
1986 out << "fi" << endl;
1988 // Part dedicated to the specific analyses running into the train
1990 TObjArray *arr = fOutputFiles.Tokenize(" ");
1992 TString output_file;
1993 while ((os=(TObjString*)next1())) {
1994 output_file = os->GetString();
1995 Int_t index = output_file.Index("@");
1996 if (index > 0) output_file.Remove(index);
1997 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
1998 out << " error=1" << endl;
1999 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2000 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2001 out << "fi" << endl;
2004 out << "if [ $error = 0 ] ; then" << endl;
2005 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2006 out << "fi" << endl;
2008 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2009 out << "echo \"*******************************************************\"" << out_stream << endl;
2010 out << "cd -" << endl;
2011 out << "exit $error" << endl;
2013 Bool_t copy = kTRUE;
2014 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2017 TString workdir = gGrid->GetHomeDirectory();
2018 workdir += fGridWorkingDir;
2019 Info("CreateJDL", "\n##### Copying validation script <validate.sh> to your AliEn working space");
2020 if (FileExists("validate.sh")) gGrid->Rm("validate.sh");
2021 TFile::Cp("file:validate.sh", Form("alien://%s/validate.sh", workdir.Data()));