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),
65 fAdditionalRootLibs(),
96 //______________________________________________________________________________
97 AliAnalysisAlien::AliAnalysisAlien(const char *name)
98 :AliAnalysisGrid(name),
102 fSplitMaxInputFileNumber(0),
104 fMasterResubmitThreshold(0),
113 fExecutableCommand(),
118 fAdditionalRootLibs(),
149 //______________________________________________________________________________
150 AliAnalysisAlien::AliAnalysisAlien(const AliAnalysisAlien& other)
151 :AliAnalysisGrid(other),
153 fPrice(other.fPrice),
155 fSplitMaxInputFileNumber(other.fSplitMaxInputFileNumber),
156 fMaxInitFailed(other.fMaxInitFailed),
157 fMasterResubmitThreshold(other.fMasterResubmitThreshold),
158 fNtestFiles(other.fNtestFiles),
159 fNrunsPerMaster(other.fNrunsPerMaster),
160 fMaxMergeFiles(other.fMaxMergeFiles),
161 fNsubmitted(other.fNsubmitted),
162 fProductionMode(other.fProductionMode),
163 fOutputToRunNo(other.fOutputToRunNo),
164 fRunNumbers(other.fRunNumbers),
165 fExecutable(other.fExecutable),
166 fExecutableCommand(other.fExecutableCommand),
167 fArguments(other.fArguments),
168 fExecutableArgs(other.fExecutableArgs),
169 fAnalysisMacro(other.fAnalysisMacro),
170 fAnalysisSource(other.fAnalysisSource),
171 fAdditionalRootLibs(other.fAdditionalRootLibs),
172 fAdditionalLibs(other.fAdditionalLibs),
173 fSplitMode(other.fSplitMode),
174 fAPIVersion(other.fAPIVersion),
175 fROOTVersion(other.fROOTVersion),
176 fAliROOTVersion(other.fAliROOTVersion),
177 fExternalPackages(other.fExternalPackages),
179 fGridWorkingDir(other.fGridWorkingDir),
180 fGridDataDir(other.fGridDataDir),
181 fDataPattern(other.fDataPattern),
182 fGridOutputDir(other.fGridOutputDir),
183 fOutputArchive(other.fOutputArchive),
184 fOutputFiles(other.fOutputFiles),
185 fInputFormat(other.fInputFormat),
186 fDatasetName(other.fDatasetName),
187 fJDLName(other.fJDLName),
188 fMergeExcludes(other.fMergeExcludes),
189 fIncludePath(other.fIncludePath),
190 fCloseSE(other.fCloseSE),
191 fFriendChainName(other.fFriendChainName),
192 fJobTag(other.fJobTag),
193 fOutputSingle(other.fOutputSingle),
194 fRunPrefix(other.fRunPrefix),
199 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
200 fRunRange[0] = other.fRunRange[0];
201 fRunRange[1] = other.fRunRange[1];
202 if (other.fInputFiles) {
203 fInputFiles = new TObjArray();
204 TIter next(other.fInputFiles);
206 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
207 fInputFiles->SetOwner();
209 if (other.fPackages) {
210 fPackages = new TObjArray();
211 TIter next(other.fPackages);
213 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
214 fPackages->SetOwner();
218 //______________________________________________________________________________
219 AliAnalysisAlien::~AliAnalysisAlien()
222 if (fGridJDL) delete fGridJDL;
223 if (fInputFiles) delete fInputFiles;
224 if (fPackages) delete fPackages;
227 //______________________________________________________________________________
228 AliAnalysisAlien &AliAnalysisAlien::operator=(const AliAnalysisAlien& other)
231 if (this != &other) {
232 AliAnalysisGrid::operator=(other);
233 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
234 fPrice = other.fPrice;
236 fSplitMaxInputFileNumber = other.fSplitMaxInputFileNumber;
237 fMaxInitFailed = other.fMaxInitFailed;
238 fMasterResubmitThreshold = other.fMasterResubmitThreshold;
239 fNtestFiles = other.fNtestFiles;
240 fNrunsPerMaster = other.fNrunsPerMaster;
241 fMaxMergeFiles = other.fMaxMergeFiles;
242 fNsubmitted = other.fNsubmitted;
243 fProductionMode = other.fProductionMode;
244 fOutputToRunNo = other.fOutputToRunNo;
245 fRunNumbers = other.fRunNumbers;
246 fExecutable = other.fExecutable;
247 fExecutableCommand = other.fExecutableCommand;
248 fArguments = other.fArguments;
249 fExecutableArgs = other.fExecutableArgs;
250 fAnalysisMacro = other.fAnalysisMacro;
251 fAnalysisSource = other.fAnalysisSource;
252 fAdditionalRootLibs = other.fAdditionalRootLibs;
253 fAdditionalLibs = other.fAdditionalLibs;
254 fSplitMode = other.fSplitMode;
255 fAPIVersion = other.fAPIVersion;
256 fROOTVersion = other.fROOTVersion;
257 fAliROOTVersion = other.fAliROOTVersion;
258 fExternalPackages = other.fExternalPackages;
260 fGridWorkingDir = other.fGridWorkingDir;
261 fGridDataDir = other.fGridDataDir;
262 fDataPattern = other.fDataPattern;
263 fGridOutputDir = other.fGridOutputDir;
264 fOutputArchive = other.fOutputArchive;
265 fOutputFiles = other.fOutputFiles;
266 fInputFormat = other.fInputFormat;
267 fDatasetName = other.fDatasetName;
268 fJDLName = other.fJDLName;
269 fMergeExcludes = other.fMergeExcludes;
270 fIncludePath = other.fIncludePath;
271 fCloseSE = other.fCloseSE;
272 fFriendChainName = other.fFriendChainName;
273 fJobTag = other.fJobTag;
274 fOutputSingle = other.fOutputSingle;
275 fRunPrefix = other.fRunPrefix;
276 if (other.fInputFiles) {
277 fInputFiles = new TObjArray();
278 TIter next(other.fInputFiles);
280 while ((obj=next())) fInputFiles->Add(new TObjString(obj->GetName()));
281 fInputFiles->SetOwner();
283 if (other.fPackages) {
284 fPackages = new TObjArray();
285 TIter next(other.fPackages);
287 while ((obj=next())) fPackages->Add(new TObjString(obj->GetName()));
288 fPackages->SetOwner();
294 //______________________________________________________________________________
295 void AliAnalysisAlien::AddIncludePath(const char *path)
297 // Add include path in the remote analysis macro.
299 if (p.Contains("-I")) fIncludePath += Form("%s ", path);
300 else fIncludePath += Form("-I%s ", path);
303 //______________________________________________________________________________
304 void AliAnalysisAlien::AddRunNumber(Int_t run)
306 // Add a run number to the list of runs to be processed.
307 if (fRunNumbers.Length()) fRunNumbers += " ";
308 fRunNumbers += Form("%s%d", fRunPrefix.Data(), run);
311 //______________________________________________________________________________
312 void AliAnalysisAlien::AddRunNumber(const char* run)
314 // Add a run number to the list of runs to be processed.
315 if (fRunNumbers.Length()) fRunNumbers += " ";
319 //______________________________________________________________________________
320 void AliAnalysisAlien::AddDataFile(const char *lfn)
322 // Adds a data file to the input to be analysed. The file should be a valid LFN
323 // or point to an existing file in the alien workdir.
324 if (!fInputFiles) fInputFiles = new TObjArray();
325 fInputFiles->Add(new TObjString(lfn));
328 //______________________________________________________________________________
329 void AliAnalysisAlien::AddExternalPackage(const char *package)
331 // Adds external packages w.r.t to the default ones (root,aliroot and gapi)
332 if (fExternalPackages) fExternalPackages += " ";
333 fExternalPackages += package;
336 //______________________________________________________________________________
337 Bool_t AliAnalysisAlien::Connect()
339 // Try to connect to AliEn. User needs a valid token and /tmp/gclient_env_$UID sourced.
340 if (gGrid && gGrid->IsConnected()) return kTRUE;
341 if (!gSystem->Getenv("alien_API_USER")) {
342 Error("Connect", "Make sure you:\n 1. Have called: alien-token-init <username> today\n 2. Have sourced /tmp/gclient_env_%s",
343 gSystem->Getenv("UID"));
347 Info("Connect", "Trying to connect to AliEn ...");
348 TGrid::Connect("alien://");
350 if (!gGrid || !gGrid->IsConnected()) {
351 Error("Connect", "Did not managed to connect to AliEn. Make sure you have a valid token.");
354 fUser = gGrid->GetUser();
355 Info("Connect", "\n##### Connected to AliEn as user %s. Setting analysis user to <%s>", fUser.Data(), fUser.Data());
359 //______________________________________________________________________________
360 void AliAnalysisAlien::CdWork()
362 // Check validity of alien workspace. Create directory if possible.
364 Error("CdWork", "Alien connection required");
367 TString homedir = gGrid->GetHomeDirectory();
368 TString workdir = homedir + fGridWorkingDir;
369 if (DirectoryExists(workdir)) {
373 // Work directory not existing - create it
375 if (gGrid->Mkdir(workdir)) {
376 gGrid->Cd(fGridWorkingDir);
377 Info("CreateJDL", "\n##### Created alien working directory %s", fGridWorkingDir.Data());
379 Warning("CreateJDL", "Working directory %s cannot be created.\n Using %s instead.",
380 workdir.Data(), homedir.Data());
381 fGridWorkingDir = "";
385 //______________________________________________________________________________
386 Bool_t AliAnalysisAlien::CheckInputData()
388 // Check validity of input data. If necessary, create xml files.
389 if (!fInputFiles && !fRunNumbers.Length() && !fRunRange[0]) {
390 if (!fGridDataDir.Length()) {
391 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
394 Info("CheckInputData", "Analysis will make a single xml for base data directory %s",fGridDataDir.Data());
397 // Process declared files
398 Bool_t is_collection = kFALSE;
399 Bool_t is_xml = kFALSE;
400 Bool_t use_tags = kFALSE;
401 Bool_t checked = kFALSE;
404 TString workdir = gGrid->GetHomeDirectory();
405 workdir += fGridWorkingDir;
408 TIter next(fInputFiles);
409 while ((objstr=(TObjString*)next())) {
412 file += objstr->GetString();
413 // Store full lfn path
414 if (FileExists(file)) objstr->SetString(file);
416 file = objstr->GetName();
417 if (!FileExists(objstr->GetName())) {
418 Error("CheckInputData", "Data file %s not found or not in your working dir: %s",
419 objstr->GetName(), workdir.Data());
423 Bool_t iscoll, isxml, usetags;
424 CheckDataType(file, iscoll, isxml, usetags);
427 is_collection = iscoll;
430 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
432 if ((iscoll != is_collection) || (isxml != is_xml) || (usetags != use_tags)) {
433 Error("CheckInputData", "Some conflict was found in the types of inputs");
439 // Process requested run numbers
440 if (!fRunNumbers.Length() && !fRunRange[0]) return kTRUE;
441 // Check validity of alien data directory
442 if (!fGridDataDir.Length()) {
443 Error("CkeckInputData", "AliEn path to base data directory must be set.\n = Use: SetGridDataDir()");
446 if (!DirectoryExists(fGridDataDir)) {
447 Error("CheckInputData", "Data directory %s not existing.", fGridDataDir.Data());
451 Error("CheckInputData", "You are using raw AliEn collections as input. Cannot process run numbers.");
455 if (checked && !is_xml) {
456 Error("CheckInputData", "Cannot mix processing of full runs with non-xml files");
459 // Check validity of run number(s)
463 TString schunk, schunk2;
467 use_tags = fDataPattern.Contains("tag");
468 TObject::SetBit(AliAnalysisGrid::kUseTags, use_tags);
470 if (use_tags != fDataPattern.Contains("tag")) {
471 Error("CheckInputData", "Cannot mix input files using/not using tags");
474 if (fRunNumbers.Length()) {
475 Info("CheckDataType", "Using supplied run numbers (run ranges are ignored)");
476 arr = fRunNumbers.Tokenize(" ");
478 while ((os=(TObjString*)next())) {
479 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
480 if (!DirectoryExists(path)) {
481 Warning("CheckInputData", "Run number %s not found in path: <%s>", os->GetString().Data(), path.Data());
484 path = Form("%s/%s.xml", workdir.Data(),os->GetString().Data());
485 TString msg = "\n##### file: ";
487 msg += " type: xml_collection;";
488 if (use_tags) msg += " using_tags: Yes";
489 else msg += " using_tags: No";
490 Info("CheckDataType", msg.Data());
491 if (fNrunsPerMaster<2) {
492 AddDataFile(Form("%s.xml", os->GetString().Data()));
495 if (((nruns-1)%fNrunsPerMaster) == 0) {
496 schunk = os->GetString();
498 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) continue;
499 schunk += Form("_%s.xml", os->GetString().Data());
505 Info("CheckDataType", "Using run range [%d, %d]", fRunRange[0], fRunRange[1]);
506 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
507 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
508 if (!DirectoryExists(path)) {
509 // Warning("CheckInputData", "Run number %d not found in path: <%s>", irun, path.Data());
512 path = Form("%s/%s%d.xml", workdir.Data(),fRunPrefix.Data(),irun);
513 TString msg = "\n##### file: ";
515 msg += " type: xml_collection;";
516 if (use_tags) msg += " using_tags: Yes";
517 else msg += " using_tags: No";
518 Info("CheckDataType", msg.Data());
519 if (fNrunsPerMaster<2) {
520 AddDataFile(Form("%s%d.xml",fRunPrefix.Data(),irun));
523 if (((nruns-1)%fNrunsPerMaster) == 0) {
524 schunk = Form("%s%d", fRunPrefix.Data(),irun);
526 schunk2 = Form("_%s%d.xml", fRunPrefix.Data(), irun);
527 if ((nruns%fNrunsPerMaster)!=0 && irun != fRunRange[1]) continue;
540 //______________________________________________________________________________
541 Bool_t AliAnalysisAlien::CreateDataset(const char *pattern)
543 // Create dataset for the grid data directory + run number.
544 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
546 Error("CreateDataset", "Cannot create dataset with no grid connection");
552 TString workdir = gGrid->GetHomeDirectory();
553 workdir += fGridWorkingDir;
555 // Compose the 'find' command arguments
557 TString options = "-x collection ";
558 if (TestBit(AliAnalysisGrid::kTest)) options += Form("-l %d ", fNtestFiles);
559 TString conditions = "";
564 TString schunk, schunk2;
565 TGridCollection *cbase=0, *cadd=0;
566 if (!fRunNumbers.Length() && !fRunRange[0]) {
567 if (fInputFiles && fInputFiles->GetEntries()) return kTRUE;
568 // Make a single data collection from data directory.
570 if (!DirectoryExists(path)) {
571 Error("CreateDataset", "Path to data directory %s not valid",fGridDataDir.Data());
575 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
576 else file = Form("%s.xml", gSystem->BaseName(path));
577 if (gSystem->AccessPathName(file) || TestBit(AliAnalysisGrid::kTest)) {
583 command += conditions;
584 printf("command: %s\n", command.Data());
585 TGridResult *res = gGrid->Command(command);
587 // Write standard output to file
588 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
590 if (!TestBit(AliAnalysisGrid::kTest) && !FileExists(file)) {
591 // Copy xml file to alien space
592 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
593 if (!FileExists(file)) {
594 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
597 // Update list of files to be processed.
599 AddDataFile(Form("%s/%s", workdir.Data(), file.Data()));
603 if (fRunNumbers.Length()) {
604 TObjArray *arr = fRunNumbers.Tokenize(" ");
607 while ((os=(TObjString*)next())) {
608 path = Form("%s/%s ", fGridDataDir.Data(), os->GetString().Data());
609 if (!DirectoryExists(path)) continue;
611 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
612 else file = Form("%s.xml", os->GetString().Data());
613 // If local collection file does not exist, create it via 'find' command.
614 if (gSystem->AccessPathName(file)) {
619 command += conditions;
620 TGridResult *res = gGrid->Command(command);
622 // Write standard output to file
623 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
625 if (TestBit(AliAnalysisGrid::kTest)) break;
626 // Check if there is one run per master job.
627 if (fNrunsPerMaster<2) {
628 if (FileExists(file)) {
629 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
632 // Copy xml file to alien space
633 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
634 if (!FileExists(file)) {
635 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
641 if (((nruns-1)%fNrunsPerMaster) == 0) {
642 schunk = os->GetString();
643 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
645 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
646 printf(" Merging collection <%s> into masterjob input...\n", file.Data());
650 if ((nruns%fNrunsPerMaster)!=0 && os!=arr->Last()) {
653 schunk += Form("_%s.xml", os->GetString().Data());
654 if (FileExists(schunk)) {
655 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
658 printf("Exporting merged collection <%s> and copying to AliEn\n", schunk.Data());
659 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
660 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
661 if (!FileExists(schunk)) {
662 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
670 // Process a full run range.
671 for (Int_t irun=fRunRange[0]; irun<=fRunRange[1]; irun++) {
672 path = Form("%s/%s%d ", fGridDataDir.Data(), fRunPrefix.Data(), irun);
673 if (!DirectoryExists(path)) continue;
675 if (TestBit(AliAnalysisGrid::kTest)) file = "wn.xml";
676 else file = Form("%s%d.xml", fRunPrefix.Data(), irun);
677 if (FileExists(file) && fNrunsPerMaster<2 && !TestBit(AliAnalysisGrid::kTest)) {
678 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
682 // If local collection file does not exist, create it via 'find' command.
683 if (gSystem->AccessPathName(file)) {
688 command += conditions;
689 TGridResult *res = gGrid->Command(command);
691 // Write standard output to file
692 gROOT->ProcessLine(Form("gGrid->Stdout(); > %s", file.Data()));
694 if (TestBit(AliAnalysisGrid::kTest)) break;
695 // Check if there is one run per master job.
696 if (fNrunsPerMaster<2) {
697 if (FileExists(file)) {
698 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", file.Data());
701 // Copy xml file to alien space
702 TFile::Cp(Form("file:%s",file.Data()), Form("alien://%s/%s",workdir.Data(), file.Data()));
703 if (!FileExists(file)) {
704 Error("CreateDataset", "Command %s did NOT succeed", command.Data());
709 // Check if the collection for the chunk exist locally.
710 Int_t nchunk = (nruns-1)/fNrunsPerMaster;
711 if (FileExists(fInputFiles->At(nchunk)->GetName())) continue;
712 printf(" Merging collection <%s> into %d runs chunk...\n",file.Data(),fNrunsPerMaster);
713 if (((nruns-1)%fNrunsPerMaster) == 0) {
714 schunk = Form("%s%d", fRunPrefix.Data(), irun);
715 cbase = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
717 cadd = (TGridCollection*)gROOT->ProcessLine(Form("new TAlienCollection(\"%s\", 1000000);",file.Data()));
721 schunk2 = Form("%s_%s%d.xml", schunk.Data(), fRunPrefix.Data(), irun);
722 if ((nruns%fNrunsPerMaster)!=0 && irun!=fRunRange[1] && schunk2 != fInputFiles->Last()->GetName()) {
726 if (FileExists(schunk)) {
727 Info("CreateDataset", "\n##### Dataset %s exist. Skipping creation...", schunk.Data());
730 printf("Exporting merged collection <%s> and copying to AliEn.\n", schunk.Data());
731 cbase->ExportXML(Form("file://%s", schunk.Data()),kFALSE,kFALSE, schunk, "Merged runs");
732 if (FileExists(schunk)) {
733 Info("CreateDataset", "\n##### Dataset %s exist. Skipping copy...", schunk.Data());
736 TFile::Cp(Form("file:%s",schunk.Data()), Form("alien://%s/%s",workdir.Data(), schunk.Data()));
737 if (!FileExists(schunk)) {
738 Error("CreateDataset", "Copy command did NOT succeed for %s", schunk.Data());
747 //______________________________________________________________________________
748 Bool_t AliAnalysisAlien::CreateJDL()
750 // Generate a JDL file according to current settings. The name of the file is
751 // specified by fJDLName.
752 Bool_t error = kFALSE;
755 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
756 Bool_t generate = kTRUE;
757 if (TestBit(AliAnalysisGrid::kTest) || TestBit(AliAnalysisGrid::kSubmit)) generate = kFALSE;
759 Error("CreateJDL", "Alien connection required");
762 // Check validity of alien workspace
764 TString workdir = gGrid->GetHomeDirectory();
765 workdir += fGridWorkingDir;
769 Error("CreateJDL()", "Define some input files for your analysis.");
772 // Compose list of input files
773 // Check if output files were defined
774 if (!fOutputFiles.Length()) {
775 Error("CreateJDL", "You must define at least one output file");
778 // Check if an output directory was defined and valid
779 if (!fGridOutputDir.Length()) {
780 Error("CreateJDL", "You must define AliEn output directory");
783 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
784 if (!DirectoryExists(fGridOutputDir)) {
785 if (gGrid->Mkdir(fGridOutputDir)) {
786 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
788 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
794 // Exit if any error up to now
795 if (error) return kFALSE;
797 fGridJDL->SetValue("User", Form("\"%s\"", fUser.Data()));
798 fGridJDL->SetExecutable(fExecutable);
799 if (!fArguments.IsNull())
800 fGridJDL->SetArguments(fArguments, "Arguments for the executable command");
801 // fGridJDL->SetTTL((UInt_t)fTTL);
802 fGridJDL->SetValue("TTL", Form("\"%d\"", fTTL));
803 if (fMaxInitFailed > 0)
804 fGridJDL->SetValue("MaxInitFailed", Form("\"%d\"",fMaxInitFailed));
805 if (fSplitMaxInputFileNumber > 0)
806 fGridJDL->SetValue("SplitMaxInputFileNumber", Form("\"%d\"", fSplitMaxInputFileNumber));
807 if (fSplitMode.Length())
808 fGridJDL->SetValue("Split", Form("\"%s\"", fSplitMode.Data()));
809 // fGridJDL->SetSplitMode(fSplitMode, (UInt_t)fSplitMaxInputFileNumber);
810 if (fAliROOTVersion.Length())
811 fGridJDL->AddToPackages("AliRoot", fAliROOTVersion);
812 if (fROOTVersion.Length())
813 fGridJDL->AddToPackages("ROOT", fROOTVersion);
814 if (fAPIVersion.Length())
815 fGridJDL->AddToPackages("APISCONFIG", fAPIVersion);
816 if (!fExternalPackages.IsNull()) {
817 arr = fExternalPackages.Tokenize(" ");
819 while ((os=(TObjString*)next())) {
820 TString pkgname = os->GetString();
821 Int_t index = pkgname.Index("::");
822 TString pkgversion = pkgname(index+2, pkgname.Length());
823 pkgname.Remove(index);
824 fGridJDL->AddToPackages(pkgname, pkgversion);
828 fGridJDL->SetInputDataListFormat(fInputFormat);
829 fGridJDL->SetInputDataList("wn.xml");
830 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), fAnalysisMacro.Data()));
831 TString analysisFile = fExecutable;
832 analysisFile.ReplaceAll(".sh", ".root");
833 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(),analysisFile.Data()));
834 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C"))
835 fGridJDL->AddToInputSandbox(Form("LF:%s/ConfigureCuts.C", workdir.Data()));
836 if (fAdditionalLibs.Length()) {
837 arr = fAdditionalLibs.Tokenize(" ");
839 while ((os=(TObjString*)next())) {
840 if (os->GetString().Contains(".so")) continue;
841 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), os->GetString().Data()));
846 TIter next(fPackages);
849 fGridJDL->AddToInputSandbox(Form("LF:%s/%s", workdir.Data(), obj->GetName()));
851 if (fOutputArchive.Length()) {
852 arr = fOutputArchive.Tokenize(" ");
854 while ((os=(TObjString*)next()))
855 if (!os->GetString().Contains("@") && fCloseSE.Length())
856 fGridJDL->AddToOutputArchive(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
858 fGridJDL->AddToOutputArchive(os->GetString());
861 arr = fOutputFiles.Tokenize(" ");
863 while ((os=(TObjString*)next())) {
864 // Ignore ouputs in jdl that are also in outputarchive
865 TString sout = os->GetString();
866 if (sout.Index("@")>0) sout.Remove(sout.Index("@"));
867 if (fOutputArchive.Contains(sout)) continue;
868 if (!os->GetString().Contains("@") && fCloseSE.Length())
869 fGridJDL->AddToOutputSandbox(Form("%s@%s",os->GetString().Data(), fCloseSE.Data()));
871 fGridJDL->AddToOutputSandbox(os->GetString());
874 // fGridJDL->SetPrice((UInt_t)fPrice);
875 fGridJDL->SetValue("Price", Form("\"%d\"", fPrice));
876 TString validationScript = fExecutable;
877 validationScript.ReplaceAll(".sh", "_validation.sh");
878 fGridJDL->SetValidationCommand(Form("%s/%s", workdir.Data(),validationScript.Data()));
879 if (fMasterResubmitThreshold) fGridJDL->SetValue("MasterResubmitThreshold", Form("\"%d%%\"", fMasterResubmitThreshold));
880 // Write a jdl with 2 input parameters: collection name and output dir name.
883 // Copy jdl to grid workspace
885 // Check if an output directory was defined and valid
886 if (!fGridOutputDir.Length()) {
887 Error("CreateJDL", "You must define AliEn output directory");
890 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("%s/%s", workdir.Data(), fGridOutputDir.Data());
891 if (!DirectoryExists(fGridOutputDir)) {
892 if (gGrid->Mkdir(fGridOutputDir)) {
893 Info("CreateJDL", "\n##### Created alien output directory %s", fGridOutputDir.Data());
895 Error("CreateJDL", "Could not create alien output directory %s", fGridOutputDir.Data());
901 if (TestBit(AliAnalysisGrid::kSubmit)) {
902 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
903 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
905 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
906 if (FileExists(locjdl)) gGrid->Rm(locjdl);
907 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
909 if (fAdditionalLibs.Length()) {
910 arr = fAdditionalLibs.Tokenize(" ");
913 while ((os=(TObjString*)next())) {
914 if (os->GetString().Contains(".so")) continue;
915 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", os->GetString().Data());
916 if (FileExists(os->GetString())) gGrid->Rm(os->GetString());
917 TFile::Cp(Form("file:%s",os->GetString().Data()), Form("alien://%s/%s", workdir.Data(), os->GetString().Data()));
922 TIter next(fPackages);
924 while ((obj=next())) {
925 if (FileExists(obj->GetName())) gGrid->Rm(obj->GetName());
926 Info("CreateJDL", "\n##### Copying dependency: <%s> to your alien workspace", obj->GetName());
927 TFile::Cp(Form("file:%s",obj->GetName()), Form("alien://%s/%s", workdir.Data(), obj->GetName()));
934 //______________________________________________________________________________
935 Bool_t AliAnalysisAlien::WriteJDL(Bool_t copy)
937 // Writes one or more JDL's corresponding to findex. If findex is negative,
938 // all run numbers are considered in one go (jdl). For non-negative indices
939 // they correspond to the indices in the array fInputFiles.
940 if (!fInputFiles) return kFALSE;
942 TString workdir = gGrid->GetHomeDirectory();
943 workdir += fGridWorkingDir;
945 if (!fRunNumbers.Length() && !fRunRange[0]) {
946 // One jdl with no parameters in case input data is specified by name.
947 TIter next(fInputFiles);
948 while ((os=(TObjString*)next()))
949 fGridJDL->AddToInputDataCollection(Form("LF:%s,nodownload", os->GetString().Data()));
950 if (!fOutputSingle.IsNull())
951 fGridJDL->SetOutputDirectory(Form("#alienfulldir#/../%s",fOutputSingle.Data()));
953 fGridJDL->SetOutputDirectory(Form("%s/#alien_counter_03i#", fGridOutputDir.Data()));
955 // One jdl to be submitted with 2 input parameters: data collection name and output dir prefix
956 fGridJDL->AddToInputDataCollection(Form("LF:%s/$1,nodownload", workdir.Data()));
957 if (!fOutputSingle.IsNull()) {
958 if (!fOutputToRunNo) fGridJDL->SetOutputDirectory(Form("#alienfulldir#/%s",fOutputSingle.Data()));
959 else fGridJDL->SetOutputDirectory(Form("%s/$2",fGridOutputDir.Data()));
961 fGridJDL->SetOutputDirectory(Form("%s/$2/#alien_counter_03i#", fGridOutputDir.Data()));
966 // Generate the JDL as a string
967 TString sjdl = fGridJDL->Generate();
969 index = sjdl.Index("Executable");
970 if (index >= 0) sjdl.Insert(index, "\n# This is the startup script\n");
971 index = sjdl.Index("Split ");
972 if (index >= 0) sjdl.Insert(index, "\n# We split per SE or file\n");
973 index = sjdl.Index("SplitMaxInputFileNumber");
974 if (index >= 0) sjdl.Insert(index, "\n# We want each subjob to get maximum this number of input files\n");
975 index = sjdl.Index("InputDataCollection");
976 if (index >= 0) sjdl.Insert(index, "# Input xml collections\n");
977 index = sjdl.Index("InputFile");
978 if (index >= 0) sjdl.Insert(index, "\n# List of input files to be uploaded to wn's\n");
979 index = sjdl.Index("InputDataList ");
980 if (index >= 0) sjdl.Insert(index, "\n# Collection to be processed on wn\n");
981 index = sjdl.Index("InputDataListFormat");
982 if (index >= 0) sjdl.Insert(index, "\n# Format of input data\n");
983 index = sjdl.Index("Price");
984 if (index >= 0) sjdl.Insert(index, "\n# AliEn price for this job\n");
985 index = sjdl.Index("Requirements");
986 if (index >= 0) sjdl.Insert(index, "\n# Additional requirements for the computing element\n");
987 index = sjdl.Index("Packages");
988 if (index >= 0) sjdl.Insert(index, "\n# Packages to be used\n");
989 index = sjdl.Index("User =");
990 if (index >= 0) sjdl.Insert(index, "\n# AliEn user\n");
991 index = sjdl.Index("TTL");
992 if (index >= 0) sjdl.Insert(index, "\n# Time to live for the job\n");
993 index = sjdl.Index("OutputFile");
994 if (index >= 0) sjdl.Insert(index, "\n# List of output files to be registered\n");
995 index = sjdl.Index("OutputDir");
996 if (index >= 0) sjdl.Insert(index, "\n# Output directory\n");
997 index = sjdl.Index("OutputArchive");
998 if (index >= 0) sjdl.Insert(index, "\n# Files to be archived\n");
999 index = sjdl.Index("MaxInitFailed");
1000 if (index >= 0) sjdl.Insert(index, "\n# Maximum number of first failing jobs to abort the master job\n");
1001 index = sjdl.Index("MasterResubmitThreshold");
1002 if (index >= 0) sjdl.Insert(index, "\n# Resubmit failed jobs until DONE rate reaches this percentage\n");
1003 sjdl.ReplaceAll("ValidationCommand", "Validationcommand");
1004 index = sjdl.Index("Validationcommand");
1005 if (index >= 0) sjdl.Insert(index, "\n# Validation script to be run for each subjob\n");
1006 sjdl.ReplaceAll("\"LF:", "\n \"LF:");
1007 sjdl.ReplaceAll("(member", "\n (member");
1008 sjdl.ReplaceAll("\",\"VO_", "\",\n \"VO_");
1009 sjdl.ReplaceAll("{", "{\n ");
1010 sjdl.ReplaceAll("};", "\n};");
1011 sjdl.ReplaceAll("{\n \n", "{\n");
1012 sjdl.ReplaceAll("\n\n", "\n");
1013 sjdl.ReplaceAll("OutputDirectory", "OutputDir");
1014 sjdl += "JDLVariables = \n{\n \"Packages\",\n \"OutputDir\"\n};\n";
1015 sjdl.Prepend(Form("Jobtag = {\n \"comment:%s\"\n};\n", fJobTag.Data()));
1016 index = sjdl.Index("JDLVariables");
1017 if (index >= 0) sjdl.Insert(index, "\n# JDL variables\n");
1018 // Write jdl to file
1020 out.open(fJDLName.Data(), ios::out);
1022 Error("CreateJDL", "Bad file name: %s", fJDLName.Data());
1025 out << sjdl << endl;
1027 // Copy jdl to grid workspace
1029 Info("CreateJDL", "\n##### You may want to review jdl:%s and analysis macro:%s before running in <submit> mode", fJDLName.Data(), fAnalysisMacro.Data());
1031 Info("CreateJDL", "\n##### Copying JDL file <%s> to your AliEn output directory", fJDLName.Data());
1032 TString locjdl = Form("%s/%s", fGridOutputDir.Data(),fJDLName.Data());
1033 if (fProductionMode)
1034 locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
1035 if (FileExists(locjdl)) gGrid->Rm(locjdl);
1036 TFile::Cp(Form("file:%s",fJDLName.Data()), Form("alien://%s", locjdl.Data()));
1041 //______________________________________________________________________________
1042 Bool_t AliAnalysisAlien::FileExists(const char *lfn)
1044 // Returns true if file exists.
1045 if (!gGrid) return kFALSE;
1046 TGridResult *res = gGrid->Ls(lfn);
1047 if (!res) return kFALSE;
1048 TMap *map = dynamic_cast<TMap*>(res->At(0));
1053 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("name"));
1054 if (!objs || !objs->GetString().Length()) {
1062 //______________________________________________________________________________
1063 Bool_t AliAnalysisAlien::DirectoryExists(const char *dirname)
1065 // Returns true if directory exists. Can be also a path.
1066 if (!gGrid) return kFALSE;
1067 // Check if dirname is a path
1068 TString dirstripped = dirname;
1069 dirstripped = dirstripped.Strip();
1070 dirstripped = dirstripped.Strip(TString::kTrailing, '/');
1071 TString dir = gSystem->BaseName(dirstripped);
1073 TString path = gSystem->DirName(dirstripped);
1074 TGridResult *res = gGrid->Ls(path, "-F");
1075 if (!res) return kFALSE;
1079 while ((map=dynamic_cast<TMap*>(next()))) {
1080 obj = map->GetValue("name");
1082 if (dir == obj->GetName()) {
1091 //______________________________________________________________________________
1092 void AliAnalysisAlien::CheckDataType(const char *lfn, Bool_t &is_collection, Bool_t &is_xml, Bool_t &use_tags)
1094 // Check input data type.
1095 is_collection = kFALSE;
1099 Error("CheckDataType", "No connection to grid");
1102 is_collection = IsCollection(lfn);
1103 TString msg = "\n##### file: ";
1105 if (is_collection) {
1106 msg += " type: raw_collection;";
1107 // special treatment for collections
1109 // check for tag files in the collection
1110 TGridResult *res = gGrid->Command(Form("listFilesFromCollection -z -v %s",lfn), kFALSE);
1112 msg += " using_tags: No (unknown)";
1113 Info("CheckDataType", msg.Data());
1116 const char* typeStr = res->GetKey(0, "origLFN");
1117 if (!typeStr || !strlen(typeStr)) {
1118 msg += " using_tags: No (unknown)";
1119 Info("CheckDataType", msg.Data());
1122 TString file = typeStr;
1123 use_tags = file.Contains(".tag");
1124 if (use_tags) msg += " using_tags: Yes";
1125 else msg += " using_tags: No";
1126 Info("CheckDataType", msg.Data());
1131 is_xml = slfn.Contains(".xml");
1133 // Open xml collection and check if there are tag files inside
1134 msg += " type: xml_collection;";
1135 TGridCollection *coll = (TGridCollection*)gROOT->ProcessLine(Form("TAlienCollection::Open(\"alien://%s\",1);",lfn));
1137 msg += " using_tags: No (unknown)";
1138 Info("CheckDataType", msg.Data());
1141 TMap *map = coll->Next();
1143 msg += " using_tags: No (unknown)";
1144 Info("CheckDataType", msg.Data());
1147 map = (TMap*)map->GetValue("");
1149 if (map && map->GetValue("name")) file = map->GetValue("name")->GetName();
1150 use_tags = file.Contains(".tag");
1152 if (use_tags) msg += " using_tags: Yes";
1153 else msg += " using_tags: No";
1154 Info("CheckDataType", msg.Data());
1157 use_tags = slfn.Contains(".tag");
1158 if (slfn.Contains(".root")) msg += " type: root file;";
1159 else msg += " type: unhnown file;";
1160 if (use_tags) msg += " using_tags: Yes";
1161 else msg += " using_tags: No";
1162 Info("CheckDataType", msg.Data());
1165 //______________________________________________________________________________
1166 void AliAnalysisAlien::EnablePackage(const char *package)
1168 // Enables a par file supposed to exist in the current directory.
1169 TString pkg(package);
1170 pkg.ReplaceAll(".par", "");
1172 if (gSystem->AccessPathName(pkg)) {
1173 Error("EnablePackage", "Package %s not found", pkg.Data());
1176 if (!TObject::TestBit(AliAnalysisGrid::kUsePars))
1177 Info("EnablePackage", "AliEn plugin will use .par packages");
1178 TObject::SetBit(AliAnalysisGrid::kUsePars, kTRUE);
1180 fPackages = new TObjArray();
1181 fPackages->SetOwner();
1183 fPackages->Add(new TObjString(pkg));
1186 //______________________________________________________________________________
1187 const char *AliAnalysisAlien::GetJobStatus(Int_t jobidstart, Int_t lastid, Int_t &nrunning, Int_t &nwaiting, Int_t &nerror, Int_t &ndone)
1189 // Get job status for all jobs with jobid>jobidstart.
1190 static char mstatus[20];
1196 TGridJobStatusList *list = gGrid->Ps("");
1197 if (!list) return mstatus;
1198 Int_t nentries = list->GetSize();
1199 TGridJobStatus *status;
1201 for (Int_t ijob=0; ijob<nentries; ijob++) {
1202 status = (TGridJobStatus *)list->At(ijob);
1203 pid = gROOT->ProcessLine(Form("atoi(((TAlienJobStatus*)0x%lx)->GetKey(\"queueId\"));", (ULong_t)status));
1204 if (pid<jobidstart) continue;
1205 if (pid == lastid) {
1206 gROOT->ProcessLine(Form("sprintf((char*)0x%lx,((TAlienJobStatus*)0x%lx)->GetKey(\"status\"));",(ULong_t)mstatus, (ULong_t)status));
1208 switch (status->GetStatus()) {
1209 case TGridJobStatus::kWAITING:
1211 case TGridJobStatus::kRUNNING:
1213 case TGridJobStatus::kABORTED:
1214 case TGridJobStatus::kFAIL:
1215 case TGridJobStatus::kUNKNOWN:
1217 case TGridJobStatus::kDONE:
1226 //______________________________________________________________________________
1227 Bool_t AliAnalysisAlien::IsCollection(const char *lfn) const
1229 // Returns true if file is a collection. Functionality duplicated from
1230 // TAlien::Type() because we don't want to directly depend on TAlien.
1232 Error("IsCollection", "No connection to grid");
1235 TGridResult *res = gGrid->Command(Form("type -z %s",lfn),kFALSE);
1236 if (!res) return kFALSE;
1237 const char* typeStr = res->GetKey(0, "type");
1238 if (!typeStr || !strlen(typeStr)) return kFALSE;
1239 if (!strcmp(typeStr, "collection")) return kTRUE;
1244 //______________________________________________________________________________
1245 Bool_t AliAnalysisAlien::IsSingleOutput() const
1247 // Check if single-ouput option is on.
1248 return (!fOutputSingle.IsNull());
1251 //______________________________________________________________________________
1252 void AliAnalysisAlien::Print(Option_t *) const
1254 // Print current plugin settings.
1255 printf("### AliEn analysis plugin current settings ###\n");
1256 printf("= Production mode:______________________________ %d\n", fProductionMode);
1257 printf("= Version of API requested: ____________________ %s\n", fAPIVersion.Data());
1258 printf("= Version of ROOT requested: ___________________ %s\n", fROOTVersion.Data());
1259 printf("= Version of AliRoot requested: ________________ %s\n", fAliROOTVersion.Data());
1261 printf("= User running the plugin: _____________________ %s\n", fUser.Data());
1262 printf("= Grid workdir relative to user $HOME: _________ %s\n", fGridWorkingDir.Data());
1263 printf("= Grid output directory relative to workdir: ___ %s\n", fGridOutputDir.Data());
1264 printf("= Data base directory path requested: __________ %s\n", fGridDataDir.Data());
1265 printf("= Data search pattern: _________________________ %s\n", fDataPattern.Data());
1266 printf("= Input data format: ___________________________ %s\n", fInputFormat.Data());
1267 if (fRunNumbers.Length())
1268 printf("= Run numbers to be processed: _________________ %s\n", fRunNumbers.Data());
1270 printf("= Run range to be processed: ___________________ %s%d-%s%d\n", fRunPrefix.Data(), fRunRange[0], fRunPrefix.Data(), fRunRange[1]);
1271 if (!fRunRange[0] && !fRunNumbers.Length()) {
1272 TIter next(fInputFiles);
1275 while ((obj=next())) list += obj->GetName();
1276 printf("= Input files to be processed: _________________ %s\n", list.Data());
1278 if (TestBit(AliAnalysisGrid::kTest))
1279 printf("= Number of input files used in test mode: _____ %d\n", fNtestFiles);
1280 printf("= List of output files to be registered: _______ %s\n", fOutputFiles.Data());
1281 printf("= List of outputs going to be archived: ________ %s\n", fOutputArchive.Data());
1282 printf("= List of outputs that should not be merged: ___ %s\n", fMergeExcludes.Data());
1283 printf("=====================================================================\n");
1284 printf("= Job price: ___________________________________ %d\n", fPrice);
1285 printf("= Time to live (TTL): __________________________ %d\n", fTTL);
1286 printf("= Max files per subjob: ________________________ %d\n", fSplitMaxInputFileNumber);
1287 if (fMaxInitFailed>0)
1288 printf("= Max number of subjob fails to kill: __________ %d\n", fMaxInitFailed);
1289 if (fMasterResubmitThreshold>0)
1290 printf("= Resubmit master job if failed subjobs >_______ %d\n", fMasterResubmitThreshold);
1291 if (fNrunsPerMaster>0)
1292 printf("= Number of runs per master job: _______________ %d\n", fNrunsPerMaster);
1293 printf("= Number of files in one chunk to be merged: ___ %d\n", fMaxMergeFiles);
1294 printf("= Name of the generated execution script: ______ %s\n", fExecutable.Data());
1295 printf("= Executable command: __________________________ %s\n", fExecutableCommand.Data());
1296 if (fArguments.Length())
1297 printf("= Arguments for the execution script: __________ %s\n",fArguments.Data());
1298 if (fExecutableArgs.Length())
1299 printf("= Arguments after macro name in executable______ %s\n",fExecutableArgs.Data());
1300 printf("= Name of the generated analysis macro: ________ %s\n",fAnalysisMacro.Data());
1301 printf("= User analysis files to be deployed: __________ %s\n",fAnalysisSource.Data());
1302 printf("= Additional libs to be loaded or souces to be compiled runtime: <%s>\n",fAdditionalLibs.Data());
1303 printf("= Master jobs split mode: ______________________ %s\n",fSplitMode.Data());
1305 printf("= Custom name for the dataset to be created: ___ %s\n", fDatasetName.Data());
1306 printf("= Name of the generated JDL: ___________________ %s\n", fJDLName.Data());
1307 if (fIncludePath.Data())
1308 printf("= Include path for runtime task compilation: ___ %s\n", fIncludePath.Data());
1309 if (fCloseSE.Length())
1310 printf("= Force job outputs to storage element: ________ %s\n", fCloseSE.Data());
1311 if (fFriendChainName.Length())
1312 printf("= Open friend chain file on worker: ____________ %s\n", fFriendChainName.Data());
1314 TIter next(fPackages);
1317 while ((obj=next())) list += obj->GetName();
1318 printf("= Par files to be used: ________________________ %s\n", list.Data());
1322 //______________________________________________________________________________
1323 void AliAnalysisAlien::SetDefaults()
1325 // Set default values for everything. What cannot be filled will be left empty.
1326 if (fGridJDL) delete fGridJDL;
1327 fGridJDL = (TGridJDL*)gROOT->ProcessLine("new TAlienJDL()");
1330 fSplitMaxInputFileNumber = 100;
1332 fMasterResubmitThreshold = 0;
1336 fNrunsPerMaster = 1;
1337 fMaxMergeFiles = 100;
1339 fExecutable = "analysis.sh";
1340 fExecutableCommand = "root -b -q";
1342 fExecutableArgs = "";
1343 fAnalysisMacro = "myAnalysis.C";
1344 fAnalysisSource = "";
1345 fAdditionalLibs = "";
1349 fAliROOTVersion = "";
1350 fUser = ""; // Your alien user name
1351 fGridWorkingDir = "";
1352 fGridDataDir = ""; // Can be like: /alice/sim/PDC_08a/LHC08c9/
1353 fDataPattern = "*AliESDs.root"; // Can be like: *AliESDs.root, */pass1/*AliESDs.root, ...
1354 fFriendChainName = "";
1355 fGridOutputDir = "output";
1356 fOutputArchive = "log_archive.zip:stdout,stderr root_archive.zip:*.root";
1357 fOutputFiles = ""; // Like "AliAODs.root histos.root"
1358 fInputFormat = "xml-single";
1359 fJDLName = "analysis.jdl";
1360 fJobTag = "Automatically generated analysis JDL";
1361 fMergeExcludes = "";
1364 //______________________________________________________________________________
1365 Bool_t AliAnalysisAlien::MergeOutputs()
1367 // Merge analysis outputs existing in the AliEn space.
1368 if (TestBit(AliAnalysisGrid::kTest)) return kTRUE;
1369 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1371 Error("MergeOutputs", "Cannot merge outputs without grid connection. Terminate will NOT be executed");
1374 // Get the output path
1375 if (!fGridOutputDir.Contains("/")) fGridOutputDir = Form("/%s/%s/%s", gGrid->GetHomeDirectory(), fGridWorkingDir.Data(), fGridOutputDir.Data());
1376 if (!DirectoryExists(fGridOutputDir)) {
1377 Error("MergeOutputs", "Grid output directory %s not found. Terminate() will NOT be executed", fGridOutputDir.Data());
1380 if (!fOutputFiles.Length()) {
1381 Error("MergeOutputs", "No output file names defined. Are you running the right AliAnalysisAlien configuration ?");
1384 TObjArray *list = fOutputFiles.Tokenize(" ");
1388 TString output_file;
1389 TString output_chunk;
1390 TString previous_chunk;
1391 Int_t count_chunk = 0;
1392 Int_t count_zero = fMaxMergeFiles;
1393 Bool_t merged = kTRUE;
1394 while((str=(TObjString*)next())) {
1395 output_file = str->GetString();
1396 Int_t index = output_file.Index("@");
1397 if (index > 0) output_file.Remove(index);
1398 // Skip already merged outputs
1399 if (!gSystem->AccessPathName(output_file)) {
1400 Info("MergeOutputs", "Output file <%s> found. Not merging again.", output_file.Data());
1403 if (fMergeExcludes.Length() &&
1404 fMergeExcludes.Contains(output_file.Data())) continue;
1405 // Perform a 'find' command in the output directory, looking for registered outputs
1406 command = Form("find %s/ *%s", fGridOutputDir.Data(), output_file.Data());
1407 printf("command: %s\n", command.Data());
1408 TGridResult *res = gGrid->Command(command);
1410 TFileMerger *fm = 0;
1413 previous_chunk = "";
1415 // Check if there is a merge operation to resume
1416 output_chunk = output_file;
1417 output_chunk.ReplaceAll(".root", "_*.root");
1418 if (!gSystem->Exec(Form("ls %s", output_chunk.Data()))) {
1420 for (Int_t counter=0; counter<fMaxMergeFiles; counter++) map = (TMap*)nextmap();
1422 Error("MergeOutputs", "Cannot resume merging for <%s>, nentries=%d", output_file.Data(), res->GetSize());
1426 output_chunk = output_file;
1427 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1428 printf("%s\n", output_chunk.Data());
1430 if (gSystem->AccessPathName(output_chunk)) continue;
1431 // Merged file with chunks up to <count_chunk> found
1432 printf("Resume merging of <%s> from <%s>\n", output_file.Data(), output_chunk.Data());
1433 previous_chunk = output_chunk;
1437 count_zero = fMaxMergeFiles;
1438 while ((map=(TMap*)nextmap())) {
1439 // Loop 'find' results and get next LFN
1440 if (count_zero == fMaxMergeFiles) {
1441 // First file in chunk - create file merger and add previous chunk if any.
1442 fm = new TFileMerger(kFALSE);
1443 fm->SetFastMethod(kTRUE);
1444 if (previous_chunk.Length()) fm->AddFile(previous_chunk.Data());
1445 output_chunk = output_file;
1446 output_chunk.ReplaceAll(".root", Form("_%04d.root", count_chunk));
1448 // If last file found, put merged results in the output file
1449 if (map == res->Last()) output_chunk = output_file;
1450 TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
1451 if (!objs || !objs->GetString().Length()) {
1452 // Nothing found - skip this output
1457 // Add file to be merged and decrement chunk counter.
1458 fm->AddFile(objs->GetString());
1460 if (count_zero==0 || map == res->Last()) {
1461 fm->OutputFile(output_chunk);
1462 if (!fm->GetMergeList() || !fm->GetMergeList()->GetSize()) {
1463 // Nothing found - skip this output
1464 Warning("MergeOutputs", "No <%s> files found.", output_file.Data());
1469 // Merge the outputs, then go to next chunk
1471 Error("MergeOutputs", "Could not merge all <%s> files", output_file.Data());
1477 Info("MergeOutputs", "\n##### Merged %d output files to <%s>", fm->GetMergeList()->GetSize(), output_chunk.Data());
1478 gSystem->Unlink(previous_chunk);
1480 if (map == res->Last()) {
1486 count_zero = fMaxMergeFiles;
1487 previous_chunk = output_chunk;
1492 Error("MergeOutputs", "Terminate() will NOT be executed");
1497 //______________________________________________________________________________
1498 void AliAnalysisAlien::SetDefaultOutputs(Bool_t flag)
1500 // Use the output files connected to output containers from the analysis manager
1501 // rather than the files defined by SetOutputFiles
1502 if (flag && !TObject::TestBit(AliAnalysisGrid::kDefaultOutputs))
1503 Info("SetDefaultOutputs", "Plugin will use the output files taken from \
1505 TObject::SetBit(AliAnalysisGrid::kDefaultOutputs, flag);
1508 //______________________________________________________________________________
1509 Bool_t AliAnalysisAlien::StartAnalysis(Long64_t /*nentries*/, Long64_t /*firstEntry*/)
1511 // Start remote grid analysis.
1513 // Check if output files have to be taken from the analysis manager
1514 if (TestBit(AliAnalysisGrid::kDefaultOutputs)) {
1515 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1516 if (!mgr || !mgr->IsInitialized()) {
1517 Error("StartAnalysis", "You need an initialized analysis manager for this");
1521 TIter next(mgr->GetOutputs());
1522 AliAnalysisDataContainer *output;
1523 while ((output=(AliAnalysisDataContainer*)next())) {
1524 const char *filename = output->GetFileName();
1525 if (!(strcmp(filename, "default"))) {
1526 if (!mgr->GetOutputEventHandler()) continue;
1527 filename = mgr->GetOutputEventHandler()->GetOutputFileName();
1529 if (fOutputFiles.Contains(filename)) continue;
1530 if (fOutputFiles.Length()) fOutputFiles += " ";
1531 fOutputFiles += filename;
1533 // Add extra files registered to the analysis manager
1534 if (mgr->GetExtraFiles().Length()) {
1535 if (fOutputFiles.Length()) fOutputFiles += " ";
1536 fOutputFiles += mgr->GetExtraFiles();
1539 // if (!fCloseSE.Length()) fCloseSE = gSystem->Getenv("alien_CLOSE_SE");
1540 if (TestBit(AliAnalysisGrid::kOffline)) {
1541 Info("StartAnalysis","\n##### OFFLINE MODE ##### Files to be used in GRID are produced but not copied \
1542 \n there nor any job run. You can revise the JDL and analysis \
1543 \n macro then run the same in \"submit\" mode.");
1544 } else if (TestBit(AliAnalysisGrid::kTest)) {
1545 Info("StartAnalysis","\n##### LOCAL MODE ##### Your analysis will be run locally on a subset of the requested \
1547 } else if (TestBit(AliAnalysisGrid::kSubmit)) {
1548 Info("StartAnalysis","\n##### SUBMIT MODE ##### Files required by your analysis are copied to your grid working \
1549 \n space and job submitted.");
1550 } else if (TestBit(AliAnalysisGrid::kMerge)) {
1551 Info("StartAnalysis","\n##### MERGE MODE ##### The registered outputs of the analysis will be merged");
1554 Info("StartAnalysis","\n##### FULL ANALYSIS MODE ##### Producing needed files and submitting your analysis job...");
1558 Error("StartAnalysis", "Cannot start grid analysis without grid connection");
1562 if (!CheckInputData()) {
1563 Error("StartAnalysis", "There was an error in preprocessing your requested input data");
1566 CreateDataset(fDataPattern);
1567 WriteAnalysisFile();
1568 WriteAnalysisMacro();
1570 WriteValidationScript();
1571 if (!CreateJDL()) return kFALSE;
1572 if (TestBit(AliAnalysisGrid::kOffline)) return kFALSE;
1573 if (TestBit(AliAnalysisGrid::kTest)) {
1574 // Locally testing the analysis
1575 Info("StartAnalysis", "\n_______________________________________________________________________ \
1576 \n Running analysis script in a daughter shell as on a worker node \
1577 \n_______________________________________________________________________");
1578 TObjArray *list = fOutputFiles.Tokenize(" ");
1581 TString output_file;
1582 while((str=(TObjString*)next())) {
1583 output_file = str->GetString();
1584 Int_t index = output_file.Index("@");
1585 if (index > 0) output_file.Remove(index);
1586 if (!gSystem->AccessPathName(output_file)) gSystem->Exec(Form("rm %s", output_file.Data()));
1589 gSystem->Exec(Form("bash %s 2>stderr", fExecutable.Data()));
1590 TString validationScript = fExecutable;
1591 validationScript.ReplaceAll(".sh", "_validation.sh");
1592 gSystem->Exec(Form("bash %s",validationScript.Data()));
1593 // gSystem->Exec("cat stdout");
1596 // Check if submitting is managed by LPM manager
1597 if (fProductionMode) {
1598 TString prodfile = fJDLName;
1599 prodfile.ReplaceAll(".jdl", ".prod");
1600 WriteProductionFile(prodfile);
1601 Info("StartAnalysis", "Job submitting is managed by LPM. Rerun in terminate mode after jobs finished.");
1604 // Submit AliEn job(s)
1605 gGrid->Cd(fGridOutputDir);
1608 if (!fRunNumbers.Length() && !fRunRange[0]) {
1609 // Submit a given xml or a set of runs
1610 res = gGrid->Command(Form("submit %s", fJDLName.Data()));
1611 printf("*************************** %s\n",Form("submit %s", fJDLName.Data()));
1613 const char *cjobId = res->GetKey(0,"jobId");
1615 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1618 Info("StartAnalysis", "\n_______________________________________________________________________ \
1619 \n##### Your JDL %s was successfully submitted. \nTHE JOB ID IS: %s \
1620 \n_______________________________________________________________________",
1621 fJDLName.Data(), cjobId);
1627 // Submit for a range of enumeration of runs.
1631 Info("StartAnalysis", "\n#### STARTING AN ALIEN SHELL FOR YOU. EXIT WHEN YOUR JOB %s HAS FINISHED. #### \
1632 \n You may exit at any time and terminate the job later using the option <terminate> \
1633 \n ##################################################################################", jobID.Data());
1634 gSystem->Exec("aliensh");
1638 //______________________________________________________________________________
1639 void AliAnalysisAlien::Submit()
1641 // Submit all master jobs.
1642 Int_t nmasterjobs = fInputFiles->GetEntries();
1643 Long_t tshoot = gSystem->Now();
1644 if (!fNsubmitted) SubmitNext();
1645 while (fNsubmitted < nmasterjobs) {
1646 Long_t now = gSystem->Now();
1647 if ((now-tshoot)>30000) {
1654 //______________________________________________________________________________
1655 void AliAnalysisAlien::SubmitNext()
1657 // Submit next bunch of master jobs if the queue is free.
1658 static Bool_t iscalled = kFALSE;
1659 static Int_t firstmaster = 0;
1660 static Int_t lastmaster = 0;
1661 static Int_t npermaster = 0;
1662 if (iscalled) return;
1664 Int_t nrunning=0, nwaiting=0, nerror=0, ndone=0;
1665 Int_t ntosubmit = 0;
1668 if (!fNsubmitted) ntosubmit = 1;
1670 TString status = GetJobStatus(firstmaster, lastmaster, nrunning, nwaiting, nerror, ndone);
1671 printf("=== master %d: %s\n", lastmaster, status.Data());
1672 // If last master not split, just return
1673 if (status != "SPLIT") {iscalled = kFALSE; return;}
1674 // No more than 100 waiting jobs
1675 if (nwaiting>100) {iscalled = kFALSE; return;}
1676 npermaster = (nrunning+nwaiting+nerror+ndone)/fNsubmitted;
1677 if (npermaster) ntosubmit = (100-nwaiting)/npermaster;
1678 printf("=== WAITING(%d) RUNNING(%d) DONE(%d) OTHER(%d) NperMaster=%d => to submit %d jobs\n",
1679 nwaiting, nrunning, ndone, nerror, npermaster, ntosubmit);
1681 Int_t nmasterjobs = fInputFiles->GetEntries();
1682 for (Int_t i=0; i<ntosubmit; i++) {
1683 // Submit for a range of enumeration of runs.
1684 if (fNsubmitted>=nmasterjobs) {iscalled = kFALSE; return;}
1686 TString runOutDir = gSystem->BaseName(fInputFiles->At(fNsubmitted)->GetName());
1687 runOutDir.ReplaceAll(".xml", "");
1689 query = Form("submit %s %s %s", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), runOutDir.Data());
1691 query = Form("submit %s %s %03d", fJDLName.Data(), fInputFiles->At(fNsubmitted)->GetName(), fNsubmitted);
1692 printf("********* %s\n",query.Data());
1693 res = gGrid->Command(query);
1695 TString cjobId1 = res->GetKey(0,"jobId");
1696 if (!cjobId1.Length()) {
1697 Error("StartAnalysis", "Your JDL %s could not be submitted", fJDLName.Data());
1701 Info("StartAnalysis", "\n_______________________________________________________________________ \
1702 \n##### Your JDL %s submitted (%d to go). \nTHE JOB ID IS: %s \
1703 \n_______________________________________________________________________",
1704 fJDLName.Data(), nmasterjobs-fNsubmitted-1, cjobId1.Data());
1707 lastmaster = cjobId1.Atoi();
1708 if (!firstmaster) firstmaster = lastmaster;
1717 //______________________________________________________________________________
1718 void AliAnalysisAlien::WriteAnalysisFile()
1720 // Write current analysis manager into the file <analysisFile>
1721 TString analysisFile = fExecutable;
1722 analysisFile.ReplaceAll(".sh", ".root");
1723 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1724 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1725 if (!mgr || !mgr->IsInitialized()) {
1726 Error("WriteAnalysisFile", "You need an initialized analysis manager for this");
1729 // Check analysis type
1731 if (mgr->GetMCtruthEventHandler()) TObject::SetBit(AliAnalysisGrid::kUseMC);
1732 handler = (TObject*)mgr->GetInputEventHandler();
1734 if (handler->InheritsFrom("AliESDInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseESD);
1735 if (handler->InheritsFrom("AliAODInputHandler")) TObject::SetBit(AliAnalysisGrid::kUseAOD);
1737 TDirectory *cdir = gDirectory;
1738 TFile *file = TFile::Open(analysisFile, "RECREATE");
1740 // Skip task Terminate calls for the grid job
1741 mgr->SetSkipTerminate(kTRUE);
1742 // Unless merging makes no sense
1743 if (IsSingleOutput()) mgr->SetSkipTerminate(kFALSE);
1746 // Enable termination for local jobs
1747 mgr->SetSkipTerminate(kFALSE);
1749 if (cdir) cdir->cd();
1750 Info("WriteAnalysisFile", "\n##### Analysis manager: %s wrote to file <%s>\n", mgr->GetName(),analysisFile.Data());
1752 Bool_t copy = kTRUE;
1753 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
1756 TString workdir = gGrid->GetHomeDirectory();
1757 workdir += fGridWorkingDir;
1758 Info("CreateJDL", "\n##### Copying file <%s> containing your initialized analysis manager to your alien workspace", analysisFile.Data());
1759 if (FileExists(analysisFile)) gGrid->Rm(analysisFile);
1760 TFile::Cp(Form("file:%s",analysisFile.Data()), Form("alien://%s/%s", workdir.Data(),analysisFile.Data()));
1764 //______________________________________________________________________________
1765 void AliAnalysisAlien::WriteAnalysisMacro()
1767 // Write the analysis macro that will steer the analysis in grid mode.
1768 if (!TestBit(AliAnalysisGrid::kSubmit)) {
1770 out.open(fAnalysisMacro.Data(), ios::out);
1772 Error("WriteAnalysisMacro", "could not open file %s for writing", fAnalysisMacro.Data());
1775 TString func = fAnalysisMacro;
1776 TString type = "ESD";
1777 TString comment = "// Analysis using ";
1778 if (TObject::TestBit(AliAnalysisGrid::kUseESD)) comment += "ESD";
1779 if (TObject::TestBit(AliAnalysisGrid::kUseAOD)) {
1783 if (type!="AOD" && fFriendChainName!="") {
1784 Error("WriteAnalysisMacro", "Friend chain can be attached only to AOD");
1787 if (TObject::TestBit(AliAnalysisGrid::kUseMC)) comment += "/MC";
1788 else comment += " data";
1789 out << "const char *anatype = \"" << type.Data() << "\";" << endl << endl;
1790 func.ReplaceAll(".C", "");
1791 out << "void " << func.Data() << "()" << endl;
1793 out << comment.Data() << endl;
1794 out << "// Automatically generated analysis steering macro executed in grid subjobs" << endl << endl;
1795 out << " TStopwatch timer;" << endl;
1796 out << " timer.Start();" << endl << endl;
1797 out << "// load base root libraries" << endl;
1798 out << " gSystem->Load(\"libTree\");" << endl;
1799 out << " gSystem->Load(\"libGeom\");" << endl;
1800 out << " gSystem->Load(\"libVMC\");" << endl;
1801 out << " gSystem->Load(\"libPhysics\");" << endl << endl;
1802 out << " gSystem->Load(\"libMinuit\");" << endl << endl;
1803 if (fAdditionalRootLibs.Length()) {
1804 // in principle libtree /lib geom libvmc etc. can go into this list, too
1805 out << "// Add aditional libraries" << endl;
1806 TObjArray *list = fAdditionalRootLibs.Tokenize(" ");
1809 while((str=(TObjString*)next())) {
1810 if (str->GetString().Contains(".so"))
1811 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1813 if (list) delete list;
1815 out << "// Load analysis framework libraries" << endl;
1819 out << " gSystem->Load(\"libSTEERBase\");" << endl;
1820 out << " gSystem->Load(\"libESD\");" << endl;
1821 out << " gSystem->Load(\"libAOD\");" << endl;
1822 out << " gSystem->Load(\"libANALYSIS\");" << endl;
1823 out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1824 out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1826 TIter next(fPackages);
1829 Bool_t hasSTEERBase = kFALSE;
1830 Bool_t hasESD = kFALSE;
1831 Bool_t hasAOD = kFALSE;
1832 Bool_t hasANALYSIS = kFALSE;
1833 Bool_t hasANALYSISalice = kFALSE;
1834 Bool_t hasCORRFW = kFALSE;
1835 while ((obj=next())) {
1836 pkgname = obj->GetName();
1837 if (pkgname == "STEERBase" ||
1838 pkgname == "STEERBase.par") hasSTEERBase = kTRUE;
1839 if (pkgname == "ESD" ||
1840 pkgname == "ESD.par") hasESD = kTRUE;
1841 if (pkgname == "AOD" ||
1842 pkgname == "AOD.par") hasAOD = kTRUE;
1843 if (pkgname == "ANALYSIS" ||
1844 pkgname == "ANALYSIS.par") hasANALYSIS = kTRUE;
1845 if (pkgname == "ANALYSISalice" ||
1846 pkgname == "ANALYSISalice.par") hasANALYSISalice = kTRUE;
1847 if (pkgname == "CORRFW" ||
1848 pkgname == "CORRFW.par") hasCORRFW = kTRUE;
1850 if (!hasSTEERBase) out << " gSystem->Load(\"libSTEERBase\");" << endl;
1851 else out << " if (!SetupPar(\"STEERBase\")) return;" << endl;
1852 if (!hasESD) out << " gSystem->Load(\"libESD\");" << endl;
1853 else out << " if (!SetupPar(\"ESD\")) return;" << endl;
1854 if (!hasAOD) out << " gSystem->Load(\"libAOD\");" << endl;
1855 else out << " if (!SetupPar(\"AOD\")) return;" << endl;
1856 if (!hasANALYSIS) out << " gSystem->Load(\"libANALYSIS\");" << endl;
1857 else out << " if (!SetupPar(\"ANALYSIS\")) return;" << endl;
1858 if (!hasANALYSISalice) out << " gSystem->Load(\"libANALYSISalice\");" << endl;
1859 else out << " if (!SetupPar(\"ANALYSISalice\")) return;" << endl;
1860 if (!hasCORRFW) out << " gSystem->Load(\"libCORRFW\");" << endl << endl;
1861 else out << " if (!SetupPar(\"CORRFW\")) return;" << endl << endl;
1862 out << "// Compile other par packages" << endl;
1864 while ((obj=next())) {
1865 pkgname = obj->GetName();
1866 if (pkgname == "STEERBase" ||
1867 pkgname == "STEERBase.par" ||
1869 pkgname == "ESD.par" ||
1871 pkgname == "AOD.par" ||
1872 pkgname == "ANALYSIS" ||
1873 pkgname == "ANALYSIS.par" ||
1874 pkgname == "ANALYSISalice" ||
1875 pkgname == "ANALYSISalice.par" ||
1876 pkgname == "CORRFW" ||
1877 pkgname == "CORRFW.par") continue;
1878 out << " if (!SetupPar(\"" << obj->GetName() << "\")) return;" << endl;
1881 out << "// include path" << endl;
1882 if (fIncludePath.Length()) out << " gSystem->AddIncludePath(\"" << fIncludePath.Data() << "\");" << endl;
1883 out << " gSystem->AddIncludePath(\"-I$ALICE_ROOT/include\");" << endl << endl;
1884 if (fAdditionalLibs.Length()) {
1885 out << "// Add aditional AliRoot libraries" << endl;
1886 TObjArray *list = fAdditionalLibs.Tokenize(" ");
1889 while((str=(TObjString*)next())) {
1890 if (str->GetString().Contains(".so"))
1891 out << " gSystem->Load(\"" << str->GetString().Data() << "\");" << endl;
1893 if (list) delete list;
1896 out << "// analysis source to be compiled at runtime (if any)" << endl;
1897 if (fAnalysisSource.Length()) {
1898 TObjArray *list = fAnalysisSource.Tokenize(" ");
1901 while((str=(TObjString*)next())) {
1902 out << " gROOT->ProcessLine(\".L " << str->GetString().Data() << "+g\");" << endl;
1904 if (list) delete list;
1907 out << "// connect to AliEn and make the chain" << endl;
1908 out << " if (!TGrid::Connect(\"alien://\")) return;" << endl;
1909 if (IsUsingTags()) {
1910 out << " TChain *chain = CreateChainFromTags(\"wn.xml\", anatype);" << endl << endl;
1912 if(fFriendChainName!="AliAOD.VertexingHF.root") {
1913 out << " TChain *chain = CreateChain(\"wn.xml\", anatype);" << endl << endl;
1915 out << " // Check if the macro to create the chain was provided" << endl;
1916 out << " if (gSystem->AccessPathName(\"MakeAODInputChain.C\")) {" << endl;
1917 out << " ::Error(\"" << func.Data() << "\", \"File MakeAODInputChain.C not provided. Aborting.\");" << endl;
1918 out << " return;" << endl;
1919 out << " }" << endl;
1920 out << " gROOT->LoadMacro(\"MakeAODInputChain.C\");" << endl;
1921 out << " TChain *chain = MakeAODInputChain(\"wn.xml\",\"none\");" << endl << endl;
1924 out << "// read the analysis manager from file" << endl;
1925 TString analysisFile = fExecutable;
1926 analysisFile.ReplaceAll(".sh", ".root");
1927 out << " TFile *file = TFile::Open(\"" << analysisFile << "\");" << endl;
1928 out << " if (!file) return;" << endl;
1929 out << " TIter nextkey(file->GetListOfKeys());" << endl;
1930 out << " AliAnalysisManager *mgr = 0;" << endl;
1931 out << " TKey *key;" << endl;
1932 out << " while ((key=(TKey*)nextkey())) {" << endl;
1933 out << " if (!strcmp(key->GetClassName(), \"AliAnalysisManager\"))" << endl;
1934 out << " mgr = (AliAnalysisManager*)file->Get(key->GetName());" << endl;
1935 out << " };" << endl;
1936 out << " if (!mgr) {" << endl;
1937 out << " ::Error(\"" << func.Data() << "\", \"No analysis manager found in file" << analysisFile <<"\");" << endl;
1938 out << " return;" << endl;
1939 out << " }" << endl << endl;
1940 out << " mgr->PrintStatus();" << endl;
1941 out << " mgr->StartAnalysis(\"localfile\", chain);" << endl;
1942 out << " timer.Stop();" << endl;
1943 out << " timer.Print();" << endl;
1944 out << "}" << endl << endl;
1945 if (IsUsingTags()) {
1946 out << "TChain* CreateChainFromTags(const char *xmlfile, const char *type=\"ESD\")" << endl;
1948 out << "// Create a chain using tags from the xml file." << endl;
1949 out << " TAlienCollection* coll = TAlienCollection::Open(xmlfile);" << endl;
1950 out << " if (!coll) {" << endl;
1951 out << " ::Error(\"CreateChainFromTags\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
1952 out << " return NULL;" << endl;
1953 out << " }" << endl;
1954 out << " TGridResult* tagResult = coll->GetGridResult(\"\",kFALSE,kFALSE);" << endl;
1955 out << " AliTagAnalysis *tagAna = new AliTagAnalysis(type);" << endl;
1956 out << " tagAna->ChainGridTags(tagResult);" << endl << endl;
1957 out << " AliRunTagCuts *runCuts = new AliRunTagCuts();" << endl;
1958 out << " AliLHCTagCuts *lhcCuts = new AliLHCTagCuts();" << endl;
1959 out << " AliDetectorTagCuts *detCuts = new AliDetectorTagCuts();" << endl;
1960 out << " AliEventTagCuts *evCuts = new AliEventTagCuts();" << endl;
1961 out << " // Check if the cuts configuration file was provided" << endl;
1962 out << " if (!gSystem->AccessPathName(\"ConfigureCuts.C\")) {" << endl;
1963 out << " gROOT->LoadMacro(\"ConfigureCuts.C\");" << endl;
1964 out << " ConfigureCuts(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1965 out << " }" << endl;
1966 if (fFriendChainName=="") {
1967 out << " TChain *chain = tagAna->QueryTags(runCuts, lhcCuts, detCuts, evCuts);" << endl;
1969 out << " TString tmpColl=\"tmpCollection.xml\";" << endl;
1970 out << " tagAna->CreateXMLCollection(tmpColl.Data(),runCuts, lhcCuts, detCuts, evCuts);" << endl;
1971 out << " TChain *chain = CreateChain(tmpColl.Data(),type);" << endl;
1973 out << " if (!chain || !chain->GetNtrees()) return NULL;" << endl;
1974 out << " chain->ls();" << endl;
1975 out << " return chain;" << endl;
1976 out << "}" << endl << endl;
1977 if (gSystem->AccessPathName("ConfigureCuts.C")) {
1978 TString msg = "\n##### You may want to provide a macro ConfigureCuts.C with a method:\n";
1979 msg += " void ConfigureCuts(AliRunTagCuts *runCuts,\n";
1980 msg += " AliLHCTagCuts *lhcCuts,\n";
1981 msg += " AliDetectorTagCuts *detCuts,\n";
1982 msg += " AliEventTagCuts *evCuts)";
1983 Info("WriteAnalysisMacro", msg.Data());
1986 if (!IsUsingTags() || fFriendChainName!="") {
1987 out <<"//________________________________________________________________________________" << endl;
1988 out << "TChain* CreateChain(const char *xmlfile, const char *type=\"ESD\")" << endl;
1990 out << "// Create a chain using url's from xml file" << endl;
1991 out << " TString treename = type;" << endl;
1992 out << " treename.ToLower();" << endl;
1993 out << " treename += \"Tree\";" << endl;
1994 out << " printf(\"***************************************\\n\");" << endl;
1995 out << " printf(\" Getting chain of trees %s\\n\", treename.Data());" << endl;
1996 out << " printf(\"***************************************\\n\");" << endl;
1997 out << " TAlienCollection *coll = TAlienCollection::Open(xmlfile);" << endl;
1998 out << " if (!coll) {" << endl;
1999 out << " ::Error(\"CreateChain\", \"Cannot create an AliEn collection from %s\", xmlfile);" << endl;
2000 out << " return NULL;" << endl;
2001 out << " }" << endl;
2002 out << " TChain *chain = new TChain(treename);" << endl;
2003 if(fFriendChainName!="") {
2004 out << " TChain *chainFriend = new TChain(treename);" << endl;
2006 out << " coll->Reset();" << endl;
2007 out << " while (coll->Next()) {" << endl;
2008 out << " chain->Add(coll->GetTURL(\"\"));" << endl;
2009 if(fFriendChainName!="") {
2010 out << " TString fileFriend=coll->GetTURL(\"\");" << endl;
2011 out << " fileFriend.ReplaceAll(\"AliAOD.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2012 out << " fileFriend.ReplaceAll(\"AliAODs.root\",\""<<fFriendChainName.Data()<<"\");" << endl;
2013 out << " chainFriend->Add(fileFriend.Data());" << endl;
2015 out << " }" << endl;
2016 out << " if (!chain->GetNtrees()) {" << endl;
2017 out << " ::Error(\"CreateChain\", \"No tree found from collection %s\", xmlfile);" << endl;
2018 out << " return NULL;" << endl;
2019 out << " }" << endl;
2020 if(fFriendChainName!="") {
2021 out << " chain->AddFriend(chainFriend);" << endl;
2023 out << " return chain;" << endl;
2024 out << "}" << endl << endl;
2027 out <<"//________________________________________________________________________________" << endl;
2028 out << "Bool_t SetupPar(const char *package) {" << endl;
2029 out << "// Compile the package and set it up." << endl;
2030 out << " TString pkgdir = package;" << endl;
2031 out << " pkgdir.ReplaceAll(\".par\",\"\");" << endl;
2032 out << " gSystem->Exec(Form(\"tar xvzf %s.par\", pkgdir.Data()));" << endl;
2033 out << " TString cdir = gSystem->WorkingDirectory();" << endl;
2034 out << " gSystem->ChangeDirectory(pkgdir);" << endl;
2035 out << " // Check for BUILD.sh and execute" << endl;
2036 out << " if (!gSystem->AccessPathName(\"PROOF-INF/BUILD.sh\")) {" << endl;
2037 out << " printf(\"*******************************\\n\");" << endl;
2038 out << " printf(\"*** Building PAR archive ***\\n\");" << endl;
2039 out << " printf(\"*******************************\\n\");" << endl;
2040 out << " if (gSystem->Exec(\"PROOF-INF/BUILD.sh\")) {" << endl;
2041 out << " ::Error(\"SetupPar\", \"Cannot build par archive %s\", pkgdir.Data());" << endl;
2042 out << " gSystem->ChangeDirectory(cdir);" << endl;
2043 out << " return kFALSE;" << endl;
2044 out << " }" << endl;
2045 out << " } else {" << endl;
2046 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/BUILD.sh for package %s\", pkgdir.Data());" << endl;
2047 out << " gSystem->ChangeDirectory(cdir);" << endl;
2048 out << " return kFALSE;" << endl;
2049 out << " }" << endl;
2050 out << " // Check for SETUP.C and execute" << endl;
2051 out << " if (!gSystem->AccessPathName(\"PROOF-INF/SETUP.C\")) {" << endl;
2052 out << " printf(\"*******************************\\n\");" << endl;
2053 out << " printf(\"*** Setup PAR archive ***\\n\");" << endl;
2054 out << " printf(\"*******************************\\n\");" << endl;
2055 out << " gROOT->Macro(\"PROOF-INF/SETUP.C\");" << endl;
2056 out << " } else {" << endl;
2057 out << " ::Error(\"SetupPar\",\"Cannot access PROOF-INF/SETUP.C for package %s\", pkgdir.Data());" << endl;
2058 out << " gSystem->ChangeDirectory(cdir);" << endl;
2059 out << " return kFALSE;" << endl;
2060 out << " }" << endl;
2061 out << " // Restore original workdir" << endl;
2062 out << " gSystem->ChangeDirectory(cdir);" << endl;
2063 out << " return kTRUE;" << endl;
2066 Info("WriteAnalysisMacro", "\n##### Analysis macro to run on worker nodes <%s> written",fAnalysisMacro.Data());
2068 Bool_t copy = kTRUE;
2069 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2072 TString workdir = gGrid->GetHomeDirectory();
2073 workdir += fGridWorkingDir;
2074 if (FileExists(fAnalysisMacro)) gGrid->Rm(fAnalysisMacro);
2075 if (IsUsingTags() && !gSystem->AccessPathName("ConfigureCuts.C")) {
2076 if (FileExists("ConfigureCuts.C")) gGrid->Rm("ConfigureCuts.C");
2077 Info("WriteAnalysisMacro", "\n##### Copying cuts configuration macro: <ConfigureCuts.C> to your alien workspace");
2078 TFile::Cp("file:ConfigureCuts.C", Form("alien://%s/ConfigureCuts.C", workdir.Data()));
2080 Info("WriteAnalysisMacro", "\n##### Copying analysis macro: <%s> to your alien workspace", fAnalysisMacro.Data());
2081 TFile::Cp(Form("file:%s",fAnalysisMacro.Data()), Form("alien://%s/%s", workdir.Data(), fAnalysisMacro.Data()));
2085 //______________________________________________________________________________
2086 void AliAnalysisAlien::WriteExecutable()
2088 // Generate the alien executable script.
2089 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2091 out.open(fExecutable.Data(), ios::out);
2093 Error("WriteExecutable", "Bad file name for executable: %s", fExecutable.Data());
2096 out << "#!/bin/bash" << endl;
2097 out << "echo \"=========================================\"" << endl;
2098 out << "echo \"############## PATH : ##############\"" << endl;
2099 out << "echo $PATH" << endl;
2100 out << "echo \"############## LD_LIBRARY_PATH : ##############\"" << endl;
2101 out << "echo $LD_LIBRARY_PATH" << endl;
2102 out << "echo \"############## ROOTSYS : ##############\"" << endl;
2103 out << "echo $ROOTSYS" << endl;
2104 out << "echo \"############## which root : ##############\"" << endl;
2105 out << "which root" << endl;
2106 out << "echo \"############## ALICE_ROOT : ##############\"" << endl;
2107 out << "echo $ALICE_ROOT" << endl;
2108 out << "echo \"############## which aliroot : ##############\"" << endl;
2109 out << "which aliroot" << endl;
2110 out << "echo \"############## system limits : ##############\"" << endl;
2111 out << "ulimit -a" << endl;
2112 out << "echo \"############## memory : ##############\"" << endl;
2113 out << "free -m" << endl;
2114 out << "echo \"=========================================\"" << endl << endl;
2115 // Make sure we can properly compile par files
2116 if (TObject::TestBit(AliAnalysisGrid::kUsePars)) out << "export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH" << endl;
2117 out << fExecutableCommand << " ";
2118 out << fAnalysisMacro.Data() << " " << fExecutableArgs.Data() << endl << endl;
2119 out << "echo \"======== " << fAnalysisMacro.Data() << " finished with exit code: $? ========\"" << endl;
2120 out << "echo \"############## memory after: ##############\"" << endl;
2121 out << "free -m" << endl;
2122 out << "echo \"############## Last 10 lines from dmesg : ##############\"" << endl;
2123 out << "dmesg | tail -n 10" << endl;
2125 Bool_t copy = kTRUE;
2126 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2129 TString workdir = gGrid->GetHomeDirectory();
2130 TString bindir = Form("%s/bin", workdir.Data());
2131 if (!DirectoryExists(bindir)) gGrid->Mkdir(bindir);
2132 workdir += fGridWorkingDir;
2133 TString executable = Form("%s/bin/%s", gGrid->GetHomeDirectory(), fExecutable.Data());
2134 if (FileExists(executable)) gGrid->Rm(executable);
2135 Info("CreateJDL", "\n##### Copying executable file <%s> to your AliEn bin directory", fExecutable.Data());
2136 TFile::Cp(Form("file:%s",fExecutable.Data()), Form("alien://%s", executable.Data()));
2140 //______________________________________________________________________________
2141 void AliAnalysisAlien::WriteProductionFile(const char *filename) const
2143 // Write the production file to be submitted by LPM manager. The format is:
2144 // First line: full_path_to_jdl estimated_no_subjobs_per_master
2145 // Next lines: full_path_to_dataset XXX (XXX is a string)
2146 // To submit, one has to: submit jdl XXX for all lines
2148 out.open(filename, ios::out);
2150 Error("WriteProductionFile", "Bad file name: %s", filename);
2153 TString workdir = gGrid->GetHomeDirectory();
2154 workdir += fGridWorkingDir;
2155 Int_t njobspermaster = 1000*fNrunsPerMaster/fSplitMaxInputFileNumber;
2156 TString locjdl = Form("%s/%s", workdir.Data(),fJDLName.Data());
2157 out << locjdl << " " << njobspermaster << endl;
2158 Int_t nmasterjobs = fInputFiles->GetEntries();
2159 for (Int_t i=0; i<nmasterjobs; i++) {
2160 out << Form("%s", fInputFiles->At(i)->GetName()) << " " << Form("%03d", i) << endl;
2162 Info("WriteProductionFile", "\n##### Copying production file <%s> to your work directory", filename);
2163 if (FileExists(filename)) gGrid->Rm(filename);
2164 TFile::Cp(Form("file:%s",filename), Form("alien://%s/%s", workdir.Data(),filename));
2167 //______________________________________________________________________________
2168 void AliAnalysisAlien::WriteValidationScript()
2170 // Generate the alien validation script.
2171 // Generate the validation script
2173 TString validationScript = fExecutable;
2174 validationScript.ReplaceAll(".sh", "_validation.sh");
2176 Error("WriteValidationScript", "Alien connection required");
2179 TString out_stream = "";
2180 if (!TestBit(AliAnalysisGrid::kTest)) out_stream = " >> stdout";
2181 if (!TestBit(AliAnalysisGrid::kSubmit)) {
2183 out.open(validationScript, ios::out);
2184 out << "#!/bin/bash" << endl;
2185 out << "##################################################" << endl;
2186 out << "validateout=`dirname $0`" << endl;
2187 out << "validatetime=`date`" << endl;
2188 out << "validated=\"0\";" << endl;
2189 out << "error=0" << endl;
2190 out << "if [ -z $validateout ]" << endl;
2191 out << "then" << endl;
2192 out << " validateout=\".\"" << endl;
2193 out << "fi" << endl << endl;
2194 out << "cd $validateout;" << endl;
2195 out << "validateworkdir=`pwd`;" << endl << endl;
2196 out << "echo \"*******************************************************\"" << out_stream << endl;
2197 out << "echo \"* Automatically generated validation script *\"" << out_stream << endl;
2199 out << "echo \"* Time: $validatetime \"" << out_stream << endl;
2200 out << "echo \"* Dir: $validateout\"" << out_stream << endl;
2201 out << "echo \"* Workdir: $validateworkdir\"" << out_stream << endl;
2202 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2203 out << "ls -la ./" << out_stream << endl;
2204 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl << endl;
2205 out << "##################################################" << endl;
2208 out << "parArch=`grep -Ei \"Cannot Build the PAR Archive\" stderr`" << endl;
2209 out << "segViol=`grep -Ei \"Segmentation violation\" stderr`" << endl;
2210 out << "segFault=`grep -Ei \"Segmentation fault\" stderr`" << endl;
2213 out << "if [ ! -f stderr ] ; then" << endl;
2214 out << " error=1" << endl;
2215 out << " echo \"* ########## Job not validated - no stderr ###\" " << out_stream << endl;
2216 out << " echo \"Error = $error\" " << out_stream << endl;
2217 out << "fi" << endl;
2219 out << "if [ \"$parArch\" != \"\" ] ; then" << endl;
2220 out << " error=1" << endl;
2221 out << " echo \"* ########## Job not validated - PAR archive not built ###\" " << out_stream << endl;
2222 out << " echo \"$parArch\" " << out_stream << endl;
2223 out << " echo \"Error = $error\" " << out_stream << endl;
2224 out << "fi" << endl;
2226 out << "if [ \"$segViol\" != \"\" ] ; then" << endl;
2227 out << " error=1" << endl;
2228 out << " echo \"* ########## Job not validated - Segment. violation ###\" " << out_stream << endl;
2229 out << " echo \"$segViol\" " << out_stream << endl;
2230 out << " echo \"Error = $error\" " << out_stream << endl;
2231 out << "fi" << endl;
2233 out << "if [ \"$segFault\" != \"\" ] ; then" << endl;
2234 out << " error=1" << endl;
2235 out << " echo \"* ########## Job not validated - Segment. fault ###\" " << out_stream << endl;
2236 out << " echo \"$segFault\" " << out_stream << endl;
2237 out << " echo \"Error = $error\" " << out_stream << endl;
2238 out << "fi" << endl;
2240 // Part dedicated to the specific analyses running into the train
2242 TObjArray *arr = fOutputFiles.Tokenize(" ");
2244 TString output_file;
2245 while ((os=(TObjString*)next1())) {
2246 output_file = os->GetString();
2247 Int_t index = output_file.Index("@");
2248 if (index > 0) output_file.Remove(index);
2249 out << "if ! [ -f " << output_file.Data() << " ] ; then" << endl;
2250 out << " error=1" << endl;
2251 out << " echo \"Output file(s) not found. Job FAILED !\"" << out_stream << endl;
2252 out << " echo \"Output file(s) not found. Job FAILED !\" >> stderr" << endl;
2253 out << "fi" << endl;
2256 out << "if ! [ -f outputs_valid ] ; then" << endl;
2257 out << " error=1" << endl;
2258 out << " echo \"Output files were not validated by the analysis manager\" >> stdout" << endl;
2259 out << " echo \"Output files were not validated by the analysis manager\" >> stderr" << endl;
2260 out << "fi" << endl;
2262 out << "if [ $error = 0 ] ; then" << endl;
2263 out << " echo \"* ---------------- Job Validated ------------------*\"" << out_stream << endl;
2264 out << "fi" << endl;
2266 out << "echo \"* ----------------------------------------------------*\"" << out_stream << endl;
2267 out << "echo \"*******************************************************\"" << out_stream << endl;
2268 out << "cd -" << endl;
2269 out << "exit $error" << endl;
2271 Bool_t copy = kTRUE;
2272 if (TestBit(AliAnalysisGrid::kOffline) || TestBit(AliAnalysisGrid::kTest)) copy = kFALSE;
2275 TString workdir = gGrid->GetHomeDirectory();
2276 workdir += fGridWorkingDir;
2277 Info("CreateJDL", "\n##### Copying validation script <%s> to your AliEn working space", validationScript.Data());
2278 if (FileExists(validationScript)) gGrid->Rm(validationScript);
2279 TFile::Cp(Form("file:%s",validationScript.Data()), Form("alien://%s/%s", workdir.Data(),validationScript.Data()));