1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // Author: Mihaela Gheata, 01/09/2008
18 //==============================================================================
19 // AliAnalysisAlien - AliEn utility class. Provides interface for creating
20 // a personalized JDL, finding and creating a dataset.
21 //==============================================================================
23 #include "Riostream.h"
27 #include "TObjString.h"
28 #include "TObjArray.h"
30 #include "TGridResult.h"
31 #include "TGridCollection.h"
33 #include "TGridJobStatusList.h"
34 #include "TGridJobStatus.h"
35 #include "TFileMerger.h"
36 #include "AliAnalysisManager.h"
37 #include "AliVEventHandler.h"
38 #include "AliAnalysisDataContainer.h"
39 #include "AliAnalysisAlien.h"
41 ClassImp(AliAnalysisAlien)
43 //______________________________________________________________________________
44 AliAnalysisAlien::AliAnalysisAlien()
49 fSplitMaxInputFileNumber(0),
51 fMasterResubmitThreshold(0),
93 //______________________________________________________________________________
94 AliAnalysisAlien::AliAnalysisAlien(const char *name)
95 :AliAnalysisGrid(name),
99 fSplitMaxInputFileNumber(0),
101 fMasterResubmitThreshold(0),
109 fExecutableCommand(),
143 //______________________________________________________________________________
144 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
145 :AliAnalysisGrid(other),
147 fPrice(other.fPrice),
149 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
150 fMaxInitFailed(other.fMaxInitFailed),
151 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
152 fNtestFiles(other.fNtestFiles),
153 fNrunsPerMaster(other.fNrunsPerMaster),
154 fMaxMergeFiles(other.fMaxMergeFiles),
155 fNsubmitted(other.fNsubmitted),
156 fProductionMode(other.fProductionMode),
157 fRunNumbers(other.fRunNumbers),
158 fExecutable(other.fExecutable),
159 fExecutableCommand(other.fExecutableCommand),
160 fArguments(other.fArguments),
161 fAnalysisMacro(other.fAnalysisMacro),
162 fAnalysisSource(other.fAnalysisSource),
163 fAdditionalLibs(other.fAdditionalLibs),
164 fSplitMode(other.fSplitMode),
165 fAPIVersion(other.fAPIVersion),
166 fROOTVersion(other.fROOTVersion),
167 fAliROOTVersion(other.fAliROOTVersion),
168 fExternalPackages(other.fExternalPackages),
170 fGridWorkingDir(other.fGridWorkingDir),
171 fGridDataDir(other.fGridDataDir),
172 fDataPattern(other.fDataPattern),
173 fGridOutputDir(other.fGridOutputDir),
174 fOutputArchive(other.fOutputArchive),
175 fOutputFiles(other.fOutputFiles),
176 fInputFormat(other.fInputFormat),
177 fDatasetName(other.fDatasetName),
178 fJDLName(other.fJDLName),
179 fMergeExcludes(other.fMergeExcludes),
180 fIncludePath(other.fIncludePath),
181 fCloseSE(other.fCloseSE),
182 fFriendChainName(other.fFriendChainName),
183 fJobTag(other.fJobTag),
184 fOutputSingle(other.fOutputSingle),
185 fRunPrefix(other.fRunPrefix),
190 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
191 fRunRange[0] = other.fRunRange[0];
192 fRunRange[1] = other.fRunRange[1];
193 if (other.fInputFiles) {
194 fInputFiles = new TObjArray();
195 TIter next(other.fInputFiles);
197 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
198 fInputFiles->SetOwner();
200 if (other.fPackages) {
201 fPackages = new TObjArray();
202 TIter next(other.fPackages);
204 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
205 fPackages->SetOwner();
209 //______________________________________________________________________________
210 AliAnalysisAlien::~AliAnalysisAlien()
213 if (fGridJDL) delete fGridJDL;
214 if (fInputFiles) delete fInputFiles;
215 if (fPackages) delete fPackages;
218 //______________________________________________________________________________
219 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
222 if (this != &other) {
223 AliAnalysisGrid::operator=(other);
224 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
225 fPrice = other.fPrice;
227 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
228 fMaxInitFailed = other.fMaxInitFailed;
229 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
230 fNtestFiles = other.fNtestFiles;
231 fNrunsPerMaster = other.fNrunsPerMaster;
232 fMaxMergeFiles = other.fMaxMergeFiles;
233 fNsubmitted = other.fNsubmitted;
234 fProductionMode = other.fProductionMode;
235 fRunNumbers = other.fRunNumbers;
236 fExecutable = other.fExecutable;
237 fExecutableCommand = other.fExecutableCommand;
238 fArguments = other.fArguments;
239 fAnalysisMacro = other.fAnalysisMacro;
240 fAnalysisSource = other.fAnalysisSource;
241 fAdditionalLibs = other.fAdditionalLibs;
242 fSplitMode = other.fSplitMode;
243 fAPIVersion = other.fAPIVersion;
244 fROOTVersion = other.fROOTVersion;
245 fAliROOTVersion = other.fAliROOTVersion;
246 fExternalPackages = other.fExternalPackages;
248 fGridWorkingDir = other.fGridWorkingDir;
249 fGridDataDir = other.fGridDataDir;
250 fDataPattern = other.fDataPattern;
251 fGridOutputDir = other.fGridOutputDir;
252 fOutputArchive = other.fOutputArchive;
253 fOutputFiles = other.fOutputFiles;
254 fInputFormat = other.fInputFormat;
255 fDatasetName = other.fDatasetName;
256 fJDLName = other.fJDLName;
257 fMergeExcludes = other.fMergeExcludes;
258 fIncludePath = other.fIncludePath;
259 fCloseSE = other.fCloseSE;
260 fFriendChainName = other.fFriendChainName;
261 fJobTag = other.fJobTag;
262 fOutputSingle = other.fOutputSingle;
263 fRunPrefix = other.fRunPrefix;
264 if (other.fInputFiles) {
265 fInputFiles = new TObjArray();
266 TIter next(other.fInputFiles);
268 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
269 fInputFiles->SetOwner();
271 if (other.fPackages) {
272 fPackages = new TObjArray();
273 TIter next(other.fPackages);
275 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
276 fPackages->SetOwner();
282 //______________________________________________________________________________
283 void AliAnalysisAlien::AddIncludePath(const char *path)
285 // Add include path in the remote analysis macro.
287 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
288 else fIncludePath += Form("-I%s ", path);
291 //______________________________________________________________________________
292 void AliAnalysisAlien::AddRunNumber(Int_t run)
294 // Add a run number to the list of runs to be processed.
295 if (fRunNumbers.Length()) fRunNumbers += " ";
296 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
299 //______________________________________________________________________________
300 void AliAnalysisAlien::AddRunNumber(const char* run)
302 // Add a run number to the list of runs to be processed.
303 if (fRunNumbers.Length()) fRunNumbers += " ";
307 //______________________________________________________________________________
308 void AliAnalysisAlien::AddDataFile(const char *lfn)
310 // Adds a data file to the input to be analysed. The file should be a valid LFN
311 // or point to an existing file in the alien workdir.
312 if (!fInputFiles) fInputFiles = new TObjArray();
313 fInputFiles->Add(new TObjString(lfn));
316 //______________________________________________________________________________
317 void AliAnalysisAlien::AddExternalPackage(const char *package)
319 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
320 if (fExternalPackages) fExternalPackages += " ";
321 fExternalPackages += package;
324 //______________________________________________________________________________
325 Bool_t AliAnalysisAlien::Connect()
327 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
328 if (gGrid && gGrid->IsConnected()) return kTRUE;
329 if (!gSystem->Getenv("alien_API_USER")) {
330 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
331 gSystem->Getenv("UID"));
335 Info("Connect", "Trying to connect to AliEn ...");
336 TGrid::Connect("alien://");
338 if (!gGrid || !gGrid->IsConnected()) {
339 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
342 fUser = gGrid->GetUser();
343 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
347 //______________________________________________________________________________
348 void AliAnalysisAlien::CdWork()
350 // Check validity of alien workspace. Create directory if possible.
352 Error("CdWork", "Alien connection required");
355 TString homedir = gGrid->GetHomeDirectory();
356 TString workdir = homedir + fGridWorkingDir;
357 if (DirectoryExists(workdir)) {
361 // Work directory not existing - create it
363 if (gGrid->Mkdir(workdir)) {
364 gGrid->Cd(fGridWorkingDir);
365 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
367 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
368 workdir.Data(), homedir.Data());
369 fGridWorkingDir = "";
373 //______________________________________________________________________________
374 Bool_t AliAnalysisAlien::CheckInputData()
376 // Check validity of input data. If necessary, create xml files.
377 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
378 if (!fGridDataDir.Length()) {
379 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
382 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
385 // Process declared files
386 Bool_t is_collection = kFALSE;
387 Bool_t is_xml = kFALSE;
388 Bool_t use_tags = kFALSE;
389 Bool_t checked = kFALSE;
392 TString workdir = gGrid->GetHomeDirectory();
393 workdir += fGridWorkingDir;
396 TIter next(fInputFiles);
397 while ((objstr=(TObjString*)next())) {
400 file += objstr->GetString();
401 // Store full lfn path
402 if (FileExists(file)) objstr->SetString(file);
404 file = objstr->GetName();
405 if (!FileExists(objstr->GetName())) {
406 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
407 objstr->GetName(), workdir.Data());
411 Bool_t iscoll, isxml, usetags;
412 CheckDataType(file, iscoll, isxml, usetags);
415 is_collection = iscoll;
418 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
420 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
421 Error("CheckInputData", "Some conflict was found in the types of inputs");
427 // Process requested run numbers
428 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
429 // Check validity of alien data directory
430 if (!fGridDataDir.Length()) {
431 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
434 if (!DirectoryExists(fGridDataDir)) {
435 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
439 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
443 if (checked && !is_xml) {
444 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
447 // Check validity of run number(s)
451 TString schunk, schunk2;
455 use_tags = fDataPattern.Contains("tag");
456 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
458 if (use_tags != fDataPattern.Contains("tag")) {
459 Error("CheckInputData", "Cannot mix input files using/not using tags");
462 if (fRunNumbers.Length()) {
463 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
464 arr = fRunNumbers.Tokenize(" ");
466 while ((os=(TObjString*)next())) {
467 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
468 if (!DirectoryExists(path)) {
469 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
472 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
473 TString msg = "\n##### file: ";
475 msg += " type: xml_collection;";
476 if (use_tags) msg += " using_tags: Yes";
477 else msg += " using_tags: No";
478 Info("CheckDataType", msg.Data());
479 if (fNrunsPerMaster<2) {
480 AddDataFile(Form("%s.xml", os->GetString().Data()));
483 if (((nruns-1)%fNrunsPerMaster) == 0) {
484 schunk = os->GetString();
486 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
487 schunk += Form("_%s.xml", os->GetString().Data());
493 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
494 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
495 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
496 if (!DirectoryExists(path)) {
497 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
500 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
501 TString msg = "\n##### file: ";
503 msg += " type: xml_collection;";
504 if (use_tags) msg += " using_tags: Yes";
505 else msg += " using_tags: No";
506 Info("CheckDataType", msg.Data());
507 if (fNrunsPerMaster<2) {
508 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
511 if (((nruns-1)%fNrunsPerMaster) == 0) {
512 schunk = Form("%s%d", fRunPrefix.Data(),irun);
514 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
515 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
528 //______________________________________________________________________________
529 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
531 // Create dataset for the grid data directory + run number.
532 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
534 Error("CreateDataset", "Cannot create dataset with no grid connection");
540 TString workdir = gGrid->GetHomeDirectory();
541 workdir += fGridWorkingDir;
543 // Compose the 'find' command arguments
545 TString options = "-x collection ";
546 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
547 TString conditions = "";
552 TString schunk, schunk2;
553 TGridCollection *cbase=0, *cadd=0;
554 if (!fRunNumbers.Length() && !fRunRange[0]) {
555 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
556 // Make a single data collection from data directory.
558 if (!DirectoryExists(path)) {
559 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
563 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
564 else file = Form("%s.xml", gSystem->BaseName(path));
565 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest)) {
571 command += conditions;
572 printf("command: %s\n", command.Data());
573 TGridResult *res = gGrid->Command(command);
575 // Write standard output to file
576 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
578 if (!TestBit(AliAnalysisGrid::kTest) && !FileExists(file)) {
579 // Copy xml file to alien space
580 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
581 if (!FileExists(file)) {
582 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
585 // Update list of files to be processed.
587 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
591 if (fRunNumbers.Length()) {
592 TObjArray *arr = fRunNumbers.Tokenize(" ");
595 while ((os=(TObjString*)next())) {
596 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
597 if (!DirectoryExists(path)) continue;
599 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
600 else file = Form("%s.xml", os->GetString().Data());
601 // If local collection file does not exist, create it via 'find' command.
602 if (gSystem->AccessPathName(file)) {
607 command += conditions;
608 TGridResult *res = gGrid->Command(command);
610 // Write standard output to file
611 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
613 if (TestBit(AliAnalysisGrid::kTest)) break;
614 // Check if there is one run per master job.
615 if (fNrunsPerMaster<2) {
616 if (FileExists(file)) {
617 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
620 // Copy xml file to alien space
621 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
622 if (!FileExists(file)) {
623 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
629 if (((nruns-1)%fNrunsPerMaster) == 0) {
630 schunk = os->GetString();
631 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
633 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
634 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
638 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
641 schunk += Form("_%s.xml", os->GetString().Data());
642 if (FileExists(schunk)) {
643 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
646 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
647 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
648 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
649 if (!FileExists(schunk)) {
650 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
658 // Process a full run range.
659 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
660 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
661 if (!DirectoryExists(path)) continue;
663 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
664 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
665 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
666 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
670 // If local collection file does not exist, create it via 'find' command.
671 if (gSystem->AccessPathName(file)) {
676 command += conditions;
677 TGridResult *res = gGrid->Command(command);
679 // Write standard output to file
680 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
682 if (TestBit(AliAnalysisGrid::kTest)) break;
683 // Check if there is one run per master job.
684 if (fNrunsPerMaster<2) {
685 if (FileExists(file)) {
686 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
689 // Copy xml file to alien space
690 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
691 if (!FileExists(file)) {
692 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
697 // Check if the collection for the chunk exist locally.
698 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
699 if (FileExists(fInputFiles->At(nchunk)->GetName())) continue;
700 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
701 if (((nruns-1)%fNrunsPerMaster) == 0) {
702 schunk = Form("%s%d", fRunPrefix.Data(), irun);
703 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
705 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
709 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
710 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
714 if (FileExists(schunk)) {
715 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
718 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
719 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
720 if (FileExists(schunk)) {
721 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
724 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
725 if (!FileExists(schunk)) {
726 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
735 //______________________________________________________________________________
736 Bool_t AliAnalysisAlien::CreateJDL()
738 // Generate a JDL file according to current settings. The name of the file is
739 // specified by fJDLName.
740 Bool_t error = kFALSE;
743 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
744 Bool_t generate = kTRUE;
745 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
747 Error("CreateJDL", "Alien connection required");
750 // Check validity of alien workspace
752 TString workdir = gGrid->GetHomeDirectory();
753 workdir += fGridWorkingDir;
757 Error("CreateJDL()", "Define some input files for your analysis.");
760 // Compose list of input files
761 // Check if output files were defined
762 if (!fOutputFiles.Length()) {
763 Error("CreateJDL", "You must define at least one output file");
766 // Check if an output directory was defined and valid
767 if (!fGridOutputDir.Length()) {
768 Error("CreateJDL", "You must define AliEn output directory");
771 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
772 if (!DirectoryExists(fGridOutputDir)) {
773 if (gGrid->Mkdir(fGridOutputDir)) {
774 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
776 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
782 // Exit if any error up to now
783 if (error) return kFALSE;
785 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
786 fGridJDL->SetExecutable(fExecutable);
787 // fGridJDL->SetTTL((UInt_t)fTTL);
788 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
789 if (fMaxInitFailed > 0)
790 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
791 if (fSplitMaxInputFileNumber > 0)
792 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
793 if (fSplitMode.Length())
794 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
795 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
796 if (fAliROOTVersion.Length())
797 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
798 if (fROOTVersion.Length())
799 fGridJDL->AddToPackages("ROOT", fROOTVersion);
800 if (fAPIVersion.Length())
801 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
802 if (!fExternalPackages.IsNull()) {
803 arr = fExternalPackages.Tokenize(" ");
805 while ((os=(TObjString*)next())) {
806 TString pkgname = os->GetString();
807 Int_t index = pkgname.Index("::");
808 TString pkgversion = pkgname(index+2, pkgname.Length());
809 pkgname.Remove(index);
810 fGridJDL->AddToPackages(pkgname, pkgversion);
814 fGridJDL->SetInputDataListFormat(fInputFormat);
815 fGridJDL->SetInputDataList("wn.xml");
816 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
817 TString analysisFile = fExecutable;
818 analysisFile.ReplaceAll(".sh", ".root");
819 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
820 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
821 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
822 if (fAdditionalLibs.Length()) {
823 arr = fAdditionalLibs.Tokenize(" ");
825 while ((os=(TObjString*)next())) {
826 if (os->GetString().Contains(".so")) continue;
827 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
832 TIter next(fPackages);
835 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
837 if (fOutputArchive.Length()) {
838 arr = fOutputArchive.Tokenize(" ");
840 while ((os=(TObjString*)next()))
841 if (!os->GetString().Contains("@") && fCloseSE.Length())
842 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
844 fGridJDL->AddToOutputArchive(os->GetString());
847 arr = fOutputFiles.Tokenize(" ");
849 while ((os=(TObjString*)next())) {
850 // Ignore ouputs in jdl that are also in outputarchive
851 TString sout = os->GetString();
852 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
853 if (fOutputArchive.Contains(sout)) continue;
854 if (!os->GetString().Contains("@") && fCloseSE.Length())
855 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
857 fGridJDL->AddToOutputSandbox(os->GetString());
860 // fGridJDL->SetPrice((UInt_t)fPrice);
861 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
862 TString validationScript = fExecutable;
863 validationScript.ReplaceAll(".sh", "_validation.sh");
864 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()));
865 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
866 // Write a jdl with 2 input parameters: collection name and output dir name.
869 // Copy jdl to grid workspace
871 // Check if an output directory was defined and valid
872 if (!fGridOutputDir.Length()) {
873 Error("CreateJDL", "You must define AliEn output directory");
876 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
877 if (!DirectoryExists(fGridOutputDir)) {
878 if (gGrid->Mkdir(fGridOutputDir)) {
879 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
881 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
887 if (TestBit(AliAnalysisGrid::kSubmit)) {
888 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
889 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
891 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
892 if (FileExists(locjdl)) gGrid->Rm(locjdl);
893 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
895 if (fAdditionalLibs.Length()) {
896 arr = fAdditionalLibs.Tokenize(" ");
899 while ((os=(TObjString*)next())) {
900 if (os->GetString().Contains(".so")) continue;
901 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
902 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
903 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
908 TIter next(fPackages);
910 while ((obj=next())) {
911 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
912 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
919 //______________________________________________________________________________
920 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
922 // Writes one or more JDL's corresponding to findex. If findex is negative,
923 // all run numbers are considered in one go (jdl). For non-negative indices
924 // they correspond to the indices in the array fInputFiles.
925 if (!fInputFiles) return kFALSE;
927 TString workdir = gGrid->GetHomeDirectory();
928 workdir += fGridWorkingDir;
930 if (!fRunNumbers.Length() && !fRunRange[0]) {
931 // One jdl with no parameters in case input data is specified by name.
932 TIter next(fInputFiles);
933 while ((os=(TObjString*)next()))
934 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
935 if (!fOutputSingle.IsNull())
936 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
938 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
940 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
941 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
942 if (!fOutputSingle.IsNull())
943 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
944 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()));
948 // Generate the JDL as a string
949 TString sjdl = fGridJDL->Generate();
951 index = sjdl.Index("Executable");
952 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
953 index = sjdl.Index("Split ");
954 if (index >= 0) sjdl.Insert(index, "\n# We split per SE or file\n");
955 index = sjdl.Index("SplitMaxInputFileNumber");
956 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
957 index = sjdl.Index("InputDataCollection");
958 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
959 index = sjdl.Index("InputFile");
960 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
961 index = sjdl.Index("InputDataList ");
962 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
963 index = sjdl.Index("InputDataListFormat");
964 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
965 index = sjdl.Index("Price");
966 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
967 index = sjdl.Index("Requirements");
968 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
969 index = sjdl.Index("Packages");
970 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
971 index = sjdl.Index("User =");
972 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
973 index = sjdl.Index("TTL");
974 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
975 index = sjdl.Index("OutputFile");
976 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
977 index = sjdl.Index("OutputDir");
978 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
979 index = sjdl.Index("OutputArchive");
980 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
981 index = sjdl.Index("MaxInitFailed");
982 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
983 index = sjdl.Index("MasterResubmitThreshold");
984 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
985 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
986 index = sjdl.Index("Validationcommand");
987 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
988 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
989 sjdl.ReplaceAll("(member", "\n (member");
990 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
991 sjdl.ReplaceAll("{", "{\n ");
992 sjdl.ReplaceAll("};", "\n};");
993 sjdl.ReplaceAll("{\n \n", "{\n");
994 sjdl.ReplaceAll("\n\n", "\n");
995 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
996 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
997 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
998 index = sjdl.Index("JDLVariables");
999 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1000 // Write jdl to file
1002 out.open(fJDLName.Data(), ios::out);
1004 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1007 out << sjdl << endl;
1009 // Copy jdl to grid workspace
1011 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1013 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1014 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1015 if (fProductionMode)
1016 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1017 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1018 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1023 //______________________________________________________________________________
1024 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1026 // Returns true if file exists.
1027 if (!gGrid) return kFALSE;
1028 TGridResult *res = gGrid->Ls(lfn);
1029 if (!res) return kFALSE;
1030 TMap *map = dynamic_cast<TMap*>(res->At(0));
1035 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1036 if (!objs || !objs->GetString().Length()) {
1044 //______________________________________________________________________________
1045 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1047 // Returns true if directory exists. Can be also a path.
1048 if (!gGrid) return kFALSE;
1049 // Check if dirname is a path
1050 TString dirstripped = dirname;
1051 dirstripped = dirstripped.Strip();
1052 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1053 TString dir = gSystem->BaseName(dirstripped);
1055 TString path = gSystem->DirName(dirstripped);
1056 TGridResult *res = gGrid->Ls(path, "-F");
1057 if (!res) return kFALSE;
1061 while ((map=dynamic_cast<TMap*>(next()))) {
1062 obj = map->GetValue("name");
1064 if (dir == obj->GetName()) {
1073 //______________________________________________________________________________
1074 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1076 // Check input data type.
1077 is_collection = kFALSE;
1081 Error("CheckDataType", "No connection to grid");
1084 is_collection = IsCollection(lfn);
1085 TString msg = "\n##### file: ";
1087 if (is_collection) {
1088 msg += " type: raw_collection;";
1089 // special treatment for collections
1091 // check for tag files in the collection
1092 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1094 msg += " using_tags: No (unknown)";
1095 Info("CheckDataType", msg.Data());
1098 const char* typeStr = res->GetKey(0, "origLFN");
1099 if (!typeStr || !strlen(typeStr)) {
1100 msg += " using_tags: No (unknown)";
1101 Info("CheckDataType", msg.Data());
1104 TString file = typeStr;
1105 use_tags = file.Contains(".tag");
1106 if (use_tags) msg += " using_tags: Yes";
1107 else msg += " using_tags: No";
1108 Info("CheckDataType", msg.Data());
1113 is_xml = slfn.Contains(".xml");
1115 // Open xml collection and check if there are tag files inside
1116 msg += " type: xml_collection;";
1117 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1119 msg += " using_tags: No (unknown)";
1120 Info("CheckDataType", msg.Data());
1123 TMap *map = coll->Next();
1125 msg += " using_tags: No (unknown)";
1126 Info("CheckDataType", msg.Data());
1129 map = (TMap*)map->GetValue("");
1131 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1132 use_tags = file.Contains(".tag");
1134 if (use_tags) msg += " using_tags: Yes";
1135 else msg += " using_tags: No";
1136 Info("CheckDataType", msg.Data());
1139 use_tags = slfn.Contains(".tag");
1140 if (slfn.Contains(".root")) msg += " type: root file;";
1141 else msg += " type: unhnown file;";
1142 if (use_tags) msg += " using_tags: Yes";
1143 else msg += " using_tags: No";
1144 Info("CheckDataType", msg.Data());
1147 //______________________________________________________________________________
1148 void AliAnalysisAlien::EnablePackage(const char *package)
1150 // Enables a par file supposed to exist in the current directory.
1151 TString pkg(package);
1152 pkg.ReplaceAll(".par", "");
1154 if (gSystem->AccessPathName(pkg)) {
1155 Error("EnablePackage", "Package %s not found", pkg.Data());
1158 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1159 Info("EnablePackage", "AliEn plugin will use .par packages");
1160 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1162 fPackages = new TObjArray();
1163 fPackages->SetOwner();
1165 fPackages->Add(new TObjString(pkg));
1168 //______________________________________________________________________________
1169 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1171 // Get job status for all jobs with jobid>jobidstart.
1172 static char mstatus[20];
1178 TGridJobStatusList *list = gGrid->Ps("");
1179 if (!list) return mstatus;
1180 Int_t nentries = list->GetSize();
1181 TGridJobStatus *status;
1183 for (Int_t ijob=0; ijob<nentries; ijob++) {
1184 status = (TGridJobStatus *)list->At(ijob);
1185 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1186 if (pid<jobidstart) continue;
1187 if (pid == lastid) {
1188 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1190 switch (status->GetStatus()) {
1191 case TGridJobStatus::kWAITING:
1193 case TGridJobStatus::kRUNNING:
1195 case TGridJobStatus::kABORTED:
1196 case TGridJobStatus::kFAIL:
1197 case TGridJobStatus::kUNKNOWN:
1199 case TGridJobStatus::kDONE:
1208 //______________________________________________________________________________
1209 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1211 // Returns true if file is a collection. Functionality duplicated from
1212 // TAlien::Type() because we don't want to directly depend on TAlien.
1214 Error("IsCollection", "No connection to grid");
1217 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1218 if (!res) return kFALSE;
1219 const char* typeStr = res->GetKey(0, "type");
1220 if (!typeStr || !strlen(typeStr)) return kFALSE;
1221 if (!strcmp(typeStr, "collection")) return kTRUE;
1226 //______________________________________________________________________________
1227 void AliAnalysisAlien::Print(Option_t *) const
1229 // Print current plugin settings.
1230 printf("### AliEn analysis plugin current settings ###\n");
1231 printf("= Production mode:______________________________ %d\n", fProductionMode);
1232 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1233 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1234 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1236 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1237 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1238 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1239 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1240 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1241 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1242 if (fRunNumbers.Length())
1243 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1245 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1246 if (!fRunRange[0] && !fRunNumbers.Length()) {
1247 TIter next(fInputFiles);
1250 while ((obj=next())) list += obj->GetName();
1251 printf("= Input files to be processed: _________________ %s\n", list.Data());
1253 if (TestBit(AliAnalysisGrid::kTest))
1254 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1255 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1256 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1257 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1258 printf("=====================================================================\n");
1259 printf("= Job price: ___________________________________ %d\n", fPrice);
1260 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1261 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1262 if (fMaxInitFailed>0)
1263 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1264 if (fMasterResubmitThreshold>0)
1265 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1266 if (fNrunsPerMaster>0)
1267 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1268 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1269 printf("= Name of the generated execution script: ______ %s\n",fExecutable.Data());
1270 if (fArguments.Length())
1271 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1272 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1273 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1274 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1275 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1277 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1278 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1279 if (fIncludePath.Data())
1280 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1281 if (fCloseSE.Length())
1282 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1283 if (fFriendChainName.Length())
1284 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1286 TIter next(fPackages);
1289 while ((obj=next())) list += obj->GetName();
1290 printf("= Par files to be used: ________________________ %s\n", list.Data());
1294 //______________________________________________________________________________
1295 void AliAnalysisAlien::SetDefaults()
1297 // Set default values for everything. What cannot be filled will be left empty.
1298 if (fGridJDL) delete fGridJDL;
1299 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1302 fSplitMaxInputFileNumber = 100;
1304 fMasterResubmitThreshold = 0;
1308 fNrunsPerMaster = 1;
1309 fMaxMergeFiles = 100;
1311 fExecutable = "analysis.sh";
1312 fExecutableCommand = "root -b -q";
1314 fAnalysisMacro = "myAnalysis.C";
1315 fAnalysisSource = "";
1316 fAdditionalLibs = "";
1320 fAliROOTVersion = "";
1321 fUser = ""; // Your alien user name
1322 fGridWorkingDir = "";
1323 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1324 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1325 fFriendChainName = "";
1326 fGridOutputDir = "output";
1327 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1328 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1329 fInputFormat = "xml-single";
1330 fJDLName = "analysis.jdl";
1331 fJobTag = "Automatically generated analysis JDL";
1332 fMergeExcludes = "";
1335 //______________________________________________________________________________
1336 Bool_t AliAnalysisAlien::MergeOutputs()
1338 // Merge analysis outputs existing in the AliEn space.
1339 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1340 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1342 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1345 // Get the output path
1346 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1347 if (!DirectoryExists(fGridOutputDir)) {
1348 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1351 if (!fOutputFiles.Length()) {
1352 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1355 TObjArray *list = fOutputFiles.Tokenize(" ");
1359 TString output_file;
1360 TString output_chunk;
1361 TString previous_chunk;
1362 Int_t count_chunk = 0;
1363 Int_t count_zero = fMaxMergeFiles;
1364 Bool_t merged = kTRUE;
1365 while((str=(TObjString*)next())) {
1366 output_file = str->GetString();
1367 Int_t index = output_file.Index("@");
1368 if (index > 0) output_file.Remove(index);
1369 // Skip already merged outputs
1370 if (!gSystem->AccessPathName(output_file)) {
1371 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1374 if (fMergeExcludes.Length() &&
1375 fMergeExcludes.Contains(output_file.Data())) continue;
1376 // Perform a 'find' command in the output directory, looking for registered outputs
1377 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
1378 printf("command: %s\n", command.Data());
1379 TGridResult *res = gGrid->Command(command);
1381 TFileMerger *fm = 0;
1384 previous_chunk = "";
1386 // Check if there is a merge operation to resume
1387 output_chunk = output_file;
1388 output_chunk.ReplaceAll(".root", "_*.root");
1389 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1391 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1393 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1397 output_chunk = output_file;
1398 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1399 printf("%s\n", output_chunk.Data());
1401 if (gSystem->AccessPathName(output_chunk)) continue;
1402 // Merged file with chunks up to <count_chunk> found
1403 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1404 previous_chunk = output_chunk;
1408 count_zero = fMaxMergeFiles;
1409 while ((map=(TMap*)nextmap())) {
1410 // Loop 'find' results and get next LFN
1411 if (count_zero == fMaxMergeFiles) {
1412 // First file in chunk - create file merger and add previous chunk if any.
1413 fm = new TFileMerger(kFALSE);
1414 fm->SetFastMethod(kTRUE);
1415 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1416 output_chunk = output_file;
1417 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1419 // If last file found, put merged results in the output file
1420 if (map == res->Last()) output_chunk = output_file;
1421 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1422 if (!objs || !objs->GetString().Length()) {
1423 // Nothing found - skip this output
1428 // Add file to be merged and decrement chunk counter.
1429 fm->AddFile(objs->GetString());
1431 if (count_zero==0 || map == res->Last()) {
1432 fm->OutputFile(output_chunk);
1433 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1434 // Nothing found - skip this output
1435 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1440 // Merge the outputs, then go to next chunk
1442 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1448 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1449 gSystem->Unlink(previous_chunk);
1451 if (map == res->Last()) {
1457 count_zero = fMaxMergeFiles;
1458 previous_chunk = output_chunk;
1463 Error("MergeOutputs", "Terminate() will NOT be executed");
1468 //______________________________________________________________________________
1469 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1471 // Use the output files connected to output containers from the analysis manager
1472 // rather than the files defined by SetOutputFiles
1473 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1474 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1476 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1479 //______________________________________________________________________________
1480 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1482 // Start remote grid analysis.
1484 // Check if output files have to be taken from the analysis manager
1485 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1486 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1487 if (!mgr || !mgr->IsInitialized()) {
1488 Error("StartAnalysis", "You need an initialized analysis manager for this");
1492 TIter next(mgr->GetOutputs());
1493 AliAnalysisDataContainer *output;
1494 while ((output=(AliAnalysisDataContainer*)next())) {
1495 const char *filename = output->GetFileName();
1496 if (!(strcmp(filename, "default"))) {
1497 if (!mgr->GetOutputEventHandler()) continue;
1498 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1500 if (fOutputFiles.Contains(filename)) continue;
1501 if (fOutputFiles.Length()) fOutputFiles += " ";
1502 fOutputFiles += filename;
1504 // Add extra files registered to the analysis manager
1505 if (mgr->GetExtraFiles().Length()) {
1506 if (fOutputFiles.Length()) fOutputFiles += " ";
1507 fOutputFiles += mgr->GetExtraFiles();
1510 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1511 if (TestBit(AliAnalysisGrid::kOffline)) {
1512 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1513 \n there nor any job run. You can revise the JDL and analysis \
1514 \n macro then run the same in \"submit\" mode.");
1515 } else if (TestBit(AliAnalysisGrid::kTest)) {
1516 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1518 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1519 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1520 \n space and job submitted.");
1521 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1522 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1525 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1529 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1533 if (!CheckInputData()) {
1534 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1537 CreateDataset(fDataPattern);
1538 WriteAnalysisFile();
1539 WriteAnalysisMacro();
1541 WriteValidationScript();
1542 if (!CreateJDL()) return kFALSE;
1543 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1544 if (TestBit(AliAnalysisGrid::kTest)) {
1545 // Locally testing the analysis
1546 Info("StartAnalysis", "\n_______________________________________________________________________ \
1547 \n Running analysis script in a daughter shell as on a worker node \
1548 \n_______________________________________________________________________");
1549 TObjArray *list = fOutputFiles.Tokenize(" ");
1552 TString output_file;
1553 while((str=(TObjString*)next())) {
1554 output_file = str->GetString();
1555 Int_t index = output_file.Index("@");
1556 if (index > 0) output_file.Remove(index);
1557 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1560 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1561 TString validationScript = fExecutable;
1562 validationScript.ReplaceAll(".sh", "_validation.sh");
1563 gSystem->Exec(Form("bash %s",validationScript.Data()));
1564 // gSystem->Exec("cat stdout");
1567 // Check if submitting is managed by LPM manager
1568 if (fProductionMode) {
1569 TString prodfile = fJDLName;
1570 prodfile.ReplaceAll(".jdl", ".prod");
1571 WriteProductionFile(prodfile);
1572 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1575 // Submit AliEn job(s)
1576 gGrid->Cd(fGridOutputDir);
1579 if (!fRunNumbers.Length() && !fRunRange[0]) {
1580 // Submit a given xml or a set of runs
1581 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1582 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1584 const char *cjobId = res->GetKey(0,"jobId");
1586 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1589 Info("StartAnalysis", "\n_______________________________________________________________________ \
1590 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1591 \n_______________________________________________________________________",
1592 fJDLName.Data(), cjobId);
1598 // Submit for a range of enumeration of runs.
1602 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1603 \n You may exit at any time and terminate the job later using the option <terminate> \
1604 \n ##################################################################################", jobID.Data());
1605 gSystem->Exec("aliensh");
1609 //______________________________________________________________________________
1610 void AliAnalysisAlien::Submit()
1612 // Submit all master jobs.
1613 Int_t nmasterjobs = fInputFiles->GetEntries();
1614 Long_t tshoot = gSystem->Now();
1615 if (!fNsubmitted) SubmitNext();
1616 while (fNsubmitted < nmasterjobs) {
1617 Long_t now = gSystem->Now();
1618 if ((now-tshoot)>30000) {
1625 //______________________________________________________________________________
1626 void AliAnalysisAlien::SubmitNext()
1628 // Submit next bunch of master jobs if the queue is free.
1629 static Bool_t iscalled = kFALSE;
1630 static Int_t firstmaster = 0;
1631 static Int_t lastmaster = 0;
1632 static Int_t npermaster = 0;
1633 if (iscalled) return;
1635 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1636 Int_t ntosubmit = 0;
1639 if (!fNsubmitted) ntosubmit = 1;
1641 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1642 printf("=== master %d: %s\n", lastmaster, status.Data());
1643 // If last master not split, just return
1644 if (status != "SPLIT") {iscalled = kFALSE; return;}
1645 // No more than 100 waiting jobs
1646 if (nwaiting>100) {iscalled = kFALSE; return;}
1647 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1648 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1649 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1650 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1652 Int_t nmasterjobs = fInputFiles->GetEntries();
1653 for (Int_t i=0; i<ntosubmit; i++) {
1654 // Submit for a range of enumeration of runs.
1655 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1657 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1658 printf("********* %s\n",query.Data());
1659 res = gGrid->Command(query);
1661 TString cjobId1 = res->GetKey(0,"jobId");
1662 if (!cjobId1.Length()) {
1663 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1667 Info("StartAnalysis", "\n_______________________________________________________________________ \
1668 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1669 \n_______________________________________________________________________",
1670 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1673 lastmaster = cjobId1.Atoi();
1674 if (!firstmaster) firstmaster = lastmaster;
1683 //______________________________________________________________________________
1684 void AliAnalysisAlien::WriteAnalysisFile()
1686 // Write current analysis manager into the file <analysisFile>
1687 TString analysisFile = fExecutable;
1688 analysisFile.ReplaceAll(".sh", ".root");
1689 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1690 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1691 if (!mgr || !mgr->IsInitialized()) {
1692 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1695 // Check analysis type
1697 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1698 handler = (TObject*)mgr->GetInputEventHandler();
1700 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1701 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1703 TDirectory *cdir = gDirectory;
1704 TFile *file = TFile::Open(analysisFile, "RECREATE");
1709 if (cdir) cdir->cd();
1710 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
1712 Bool_t copy = kTRUE;
1713 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1716 TString workdir = gGrid->GetHomeDirectory();
1717 workdir += fGridWorkingDir;
1718 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1719 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1720 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
1724 //______________________________________________________________________________
1725 void AliAnalysisAlien::WriteAnalysisMacro()
1727 // Write the analysis macro that will steer the analysis in grid mode.
1728 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1730 out.open(fAnalysisMacro.Data(), ios::out);
1732 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1735 TString func = fAnalysisMacro;
1736 TString type = "ESD";
1737 TString comment = "// Analysis using ";
1738 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1739 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1743 if (type!="AOD" && fFriendChainName!="") {
1744 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1747 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1748 else comment += " data";
1749 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1750 func.ReplaceAll(".C", "");
1751 out << "void " << func.Data() << "()" << endl;
1753 out << comment.Data() << endl;
1754 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1755 out << " TStopwatch timer;" << endl;
1756 out << " timer.Start();" << endl << endl;
1757 out << "// load base root libraries" << endl;
1758 out << " gSystem->Load(\"libTree\");" << endl;
1759 out << " gSystem->Load(\"libGeom\");" << endl;
1760 out << " gSystem->Load(\"libVMC\");" << endl;
1761 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1762 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
1763 out << "// Load analysis framework libraries" << endl;
1765 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1766 out << " gSystem->Load(\"libESD\");" << endl;
1767 out << " gSystem->Load(\"libAOD\");" << endl;
1768 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1769 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1770 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1772 TIter next(fPackages);
1775 Bool_t hasSTEERBase = kFALSE;
1776 Bool_t hasESD = kFALSE;
1777 Bool_t hasAOD = kFALSE;
1778 Bool_t hasANALYSIS = kFALSE;
1779 Bool_t hasANALYSISalice = kFALSE;
1780 Bool_t hasCORRFW = kFALSE;
1781 while ((obj=next())) {
1782 pkgname = obj->GetName();
1783 if (pkgname == "STEERBase" ||
1784 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1785 if (pkgname == "ESD" ||
1786 pkgname == "ESD.par") hasESD = kTRUE;
1787 if (pkgname == "AOD" ||
1788 pkgname == "AOD.par") hasAOD = kTRUE;
1789 if (pkgname == "ANALYSIS" ||
1790 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1791 if (pkgname == "ANALYSISalice" ||
1792 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1793 if (pkgname == "CORRFW" ||
1794 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1796 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1797 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1798 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1799 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1800 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1801 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1802 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1803 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1804 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1805 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1806 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1807 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1808 out << "// Compile other par packages" << endl;
1810 while ((obj=next())) {
1811 pkgname = obj->GetName();
1812 if (pkgname == "STEERBase" ||
1813 pkgname == "STEERBase.par" ||
1815 pkgname == "ESD.par" ||
1817 pkgname == "AOD.par" ||
1818 pkgname == "ANALYSIS" ||
1819 pkgname == "ANALYSIS.par" ||
1820 pkgname == "ANALYSISalice" ||
1821 pkgname == "ANALYSISalice.par" ||
1822 pkgname == "CORRFW" ||
1823 pkgname == "CORRFW.par") continue;
1824 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1827 out << "// include path" << endl;
1828 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1829 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1830 if (fAdditionalLibs.Length()) {
1831 out << "// Add aditional AliRoot libraries" << endl;
1832 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1835 while((str=(TObjString*)next())) {
1836 if (str->GetString().Contains(".so"))
1837 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1839 if (list) delete list;
1842 out << "// analysis source to be compiled at runtime (if any)" << endl;
1843 if (fAnalysisSource.Length()) {
1844 TObjArray *list = fAnalysisSource.Tokenize(" ");
1847 while((str=(TObjString*)next())) {
1848 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1850 if (list) delete list;
1853 out << "// connect to AliEn and make the chain" << endl;
1854 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1855 if (IsUsingTags()) {
1856 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1858 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1859 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1861 out << " // Check if the macro to create the chain was provided" << endl;
1862 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1863 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1864 out << " return;" << endl;
1865 out << " }" << endl;
1866 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1867 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1870 out << "// read the analysis manager from file" << endl;
1871 TString analysisFile = fExecutable;
1872 analysisFile.ReplaceAll(".sh", ".root");
1873 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
1874 out << " if (!file) return;" << endl;
1875 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1876 out << " AliAnalysisManager *mgr = 0;" << endl;
1877 out << " TKey *key;" << endl;
1878 out << " while ((key=(TKey*)nextkey())) {" << endl;
1879 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1880 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1881 out << " };" << endl;
1882 out << " if (!mgr) {" << endl;
1883 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
1884 out << " return;" << endl;
1885 out << " }" << endl << endl;
1886 out << " mgr->PrintStatus();" << endl;
1887 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1888 out << " timer.Stop();" << endl;
1889 out << " timer.Print();" << endl;
1890 out << "}" << endl << endl;
1891 if (IsUsingTags()) {
1892 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1894 out << "// Create a chain using tags from the xml file." << endl;
1895 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1896 out << " if (!coll) {" << endl;
1897 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1898 out << " return NULL;" << endl;
1899 out << " }" << endl;
1900 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1901 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1902 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1903 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1904 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1905 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1906 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1907 out << " // Check if the cuts configuration file was provided" << endl;
1908 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1909 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1910 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1911 out << " }" << endl;
1912 if (fFriendChainName=="") {
1913 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1915 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1916 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1917 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1919 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1920 out << " chain->ls();" << endl;
1921 out << " return chain;" << endl;
1922 out << "}" << endl << endl;
1923 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1924 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1925 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1926 msg += " AliLHCTagCuts *lhcCuts,\n";
1927 msg += " AliDetectorTagCuts *detCuts,\n";
1928 msg += " AliEventTagCuts *evCuts)";
1929 Info("WriteAnalysisMacro", msg.Data());
1932 if (!IsUsingTags() || fFriendChainName!="") {
1933 out <<"//________________________________________________________________________________" << endl;
1934 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1936 out << "// Create a chain using url's from xml file" << endl;
1937 out << " TString treename = type;" << endl;
1938 out << " treename.ToLower();" << endl;
1939 out << " treename += \"Tree\";" << endl;
1940 out << " printf(\"***************************************\\n\");" << endl;
1941 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1942 out << " printf(\"***************************************\\n\");" << endl;
1943 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1944 out << " if (!coll) {" << endl;
1945 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1946 out << " return NULL;" << endl;
1947 out << " }" << endl;
1948 out << " TChain *chain = new TChain(treename);" << endl;
1949 if(fFriendChainName!="") {
1950 out << " TChain *chainFriend = new TChain(treename);" << endl;
1952 out << " coll->Reset();" << endl;
1953 out << " while (coll->Next()) {" << endl;
1954 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
1955 if(fFriendChainName!="") {
1956 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
1957 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1958 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
1959 out << " chainFriend->Add(fileFriend.Data());" << endl;
1961 out << " }" << endl;
1962 out << " if (!chain->GetNtrees()) {" << endl;
1963 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
1964 out << " return NULL;" << endl;
1965 out << " }" << endl;
1966 if(fFriendChainName!="") {
1967 out << " chain->AddFriend(chainFriend);" << endl;
1969 out << " return chain;" << endl;
1970 out << "}" << endl << endl;
1973 out <<"//________________________________________________________________________________" << endl;
1974 out << "Bool_t SetupPar(const char *package) {" << endl;
1975 out << "// Compile the package and set it up." << endl;
1976 out << " TString pkgdir = package;" << endl;
1977 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
1978 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
1979 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
1980 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
1981 out << " // Check for BUILD.sh and execute" << endl;
1982 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
1983 out << " printf(\"*******************************\\n\");" << endl;
1984 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
1985 out << " printf(\"*******************************\\n\");" << endl;
1986 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
1987 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
1988 out << " gSystem->ChangeDirectory(cdir);" << endl;
1989 out << " return kFALSE;" << endl;
1990 out << " }" << endl;
1991 out << " } else {" << endl;
1992 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
1993 out << " gSystem->ChangeDirectory(cdir);" << endl;
1994 out << " return kFALSE;" << endl;
1995 out << " }" << endl;
1996 out << " // Check for SETUP.C and execute" << endl;
1997 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
1998 out << " printf(\"*******************************\\n\");" << endl;
1999 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2000 out << " printf(\"*******************************\\n\");" << endl;
2001 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2002 out << " } else {" << endl;
2003 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2004 out << " gSystem->ChangeDirectory(cdir);" << endl;
2005 out << " return kFALSE;" << endl;
2006 out << " }" << endl;
2007 out << " // Restore original workdir" << endl;
2008 out << " gSystem->ChangeDirectory(cdir);" << endl;
2009 out << " return kTRUE;" << endl;
2012 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2014 Bool_t copy = kTRUE;
2015 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2018 TString workdir = gGrid->GetHomeDirectory();
2019 workdir += fGridWorkingDir;
2020 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2021 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2022 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2023 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2024 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2026 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2027 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2031 //______________________________________________________________________________
2032 void AliAnalysisAlien::WriteExecutable()
2034 // Generate the alien executable script.
2035 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2037 out.open(fExecutable.Data(), ios::out);
2039 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2042 out << "#!/bin/bash" << endl;
2043 out << "echo \"=========================================\"" << endl;
2044 out << "echo \"############## PATH : ##############\"" << endl;
2045 out << "echo $PATH" << endl;
2046 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2047 out << "echo $LD_LIBRARY_PATH" << endl;
2048 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2049 out << "echo $ROOTSYS" << endl;
2050 out << "echo \"############## which root : ##############\"" << endl;
2051 out << "which root" << endl;
2052 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2053 out << "echo $ALICE_ROOT" << endl;
2054 out << "echo \"############## which aliroot : ##############\"" << endl;
2055 out << "which aliroot" << endl;
2056 out << "echo \"=========================================\"" << endl << endl;
2057 // Make sure we can properly compile par files
2058 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2059 out << fExecutableCommand << " ";
2060 out << fAnalysisMacro.Data() << endl << endl;
2061 out << "echo \"======== " << fAnalysisMacro.Data() << " finished ========\"" << endl;
2063 Bool_t copy = kTRUE;
2064 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2067 TString workdir = gGrid->GetHomeDirectory();
2068 TString bindir = Form("%s/bin", workdir.Data());
2069 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2070 workdir += fGridWorkingDir;
2071 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2072 if (FileExists(executable)) gGrid->Rm(executable);
2073 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2074 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2078 //______________________________________________________________________________
2079 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2081 // Write the production file to be submitted by LPM manager. The format is:
2082 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2083 // Next lines: full_path_to_dataset XXX (XXX is a string)
2084 // To submit, one has to: submit jdl XXX for all lines
2086 out.open(filename, ios::out);
2088 Error("WriteProductionFile", "Bad file name: %s", filename);
2091 TString workdir = gGrid->GetHomeDirectory();
2092 workdir += fGridWorkingDir;
2093 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2094 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2095 out << locjdl << " " << njobspermaster << endl;
2096 Int_t nmasterjobs = fInputFiles->GetEntries();
2097 for (Int_t i=0; i<nmasterjobs; i++) {
2098 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2100 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2101 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2104 //______________________________________________________________________________
2105 void AliAnalysisAlien::WriteValidationScript()
2107 // Generate the alien validation script.
2108 // Generate the validation script
2110 TString validationScript = fExecutable;
2111 validationScript.ReplaceAll(".sh", "_validation.sh");
2113 Error("WriteValidationScript", "Alien connection required");
2116 TString out_stream = "";
2117 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2118 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2120 out.open(validationScript, ios::out);
2121 out << "#!/bin/bash" << endl;
2122 out << "##################################################" << endl;
2123 out << "validateout=`dirname $0`" << endl;
2124 out << "validatetime=`date`" << endl;
2125 out << "validated=\"0\";" << endl;
2126 out << "error=0" << endl;
2127 out << "if [ -z $validateout ]" << endl;
2128 out << "then" << endl;
2129 out << " validateout=\".\"" << endl;
2130 out << "fi" << endl << endl;
2131 out << "cd $validateout;" << endl;
2132 out << "validateworkdir=`pwd`;" << endl << endl;
2133 out << "echo \"*******************************************************\"" << out_stream << endl;
2134 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2136 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2137 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2138 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2139 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2140 out << "ls -la ./" << out_stream << endl;
2141 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2142 out << "##################################################" << endl;
2145 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2146 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2147 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2150 out << "if [ ! -f stderr ] ; then" << endl;
2151 out << " error=1" << endl;
2152 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2153 out << " echo \"Error = $error\" " << out_stream << endl;
2154 out << "fi" << endl;
2156 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2157 out << " error=1" << endl;
2158 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2159 out << " echo \"$parArch\" " << out_stream << endl;
2160 out << " echo \"Error = $error\" " << out_stream << endl;
2161 out << "fi" << endl;
2163 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2164 out << " error=1" << endl;
2165 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2166 out << " echo \"$segViol\" " << out_stream << endl;
2167 out << " echo \"Error = $error\" " << out_stream << endl;
2168 out << "fi" << endl;
2170 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2171 out << " error=1" << endl;
2172 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2173 out << " echo \"$segFault\" " << out_stream << endl;
2174 out << " echo \"Error = $error\" " << out_stream << endl;
2175 out << "fi" << endl;
2177 // Part dedicated to the specific analyses running into the train
2179 TObjArray *arr = fOutputFiles.Tokenize(" ");
2181 TString output_file;
2182 while ((os=(TObjString*)next1())) {
2183 output_file = os->GetString();
2184 Int_t index = output_file.Index("@");
2185 if (index > 0) output_file.Remove(index);
2186 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2187 out << " error=1" << endl;
2188 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2189 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2190 out << "fi" << endl;
2193 out << "if ! [ -f outputs_valid ] ; then" << endl;
2194 out << " error=1" << endl;
2195 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2196 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2197 out << "fi" << endl;
2199 out << "if [ $error = 0 ] ; then" << endl;
2200 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2201 out << "fi" << endl;
2203 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2204 out << "echo \"*******************************************************\"" << out_stream << endl;
2205 out << "cd -" << endl;
2206 out << "exit $error" << endl;
2208 Bool_t copy = kTRUE;
2209 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2212 TString workdir = gGrid->GetHomeDirectory();
2213 workdir += fGridWorkingDir;
2214 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2215 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2216 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));