1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 **************************************************************************/
18 Revision 1.42 2007/05/03 08:01:39 jgrosseo
19 typo in last commit :-(
21 Revision 1.41 2007/05/03 08:00:48 jgrosseo
22 fixing log message when pp want to skip dcs value retrieval
24 Revision 1.40 2007/04/27 07:06:48 jgrosseo
25 GetFileSources returns empty list in case of no files, but successful query
26 No mails sent in testmode
28 Revision 1.39 2007/04/17 12:43:57 acolla
29 Correction in StoreOCDB; change of text in mail to detector expert
31 Revision 1.38 2007/04/12 08:26:18 jgrosseo
34 Revision 1.37 2007/04/10 16:53:14 jgrosseo
35 redirecting sub detector stdout, stderr to sub detector log file
37 Revision 1.35 2007/04/04 16:26:38 acolla
38 1. Re-organization of function calls in TestPreprocessor to make it more meaningful.
39 2. Added missing dependency in test preprocessors.
40 3. in AliShuttle.cxx: processing time and memory consumption info on a single line.
42 Revision 1.34 2007/04/04 10:33:36 jgrosseo
43 1) Storing of files to the Grid is now done _after_ your preprocessors succeeded. This is transparent, which means that you can still use the same functions (Store, StoreReferenceData) to store files to the Grid. However, the Shuttle first stores them locally and transfers them after the preprocessor finished. The return code of these two functions has changed from UInt_t to Bool_t which gives you the success of the storing.
44 In case of an error with the Grid, the Shuttle will retry the storing later, the preprocessor does not need to be run again.
46 2) The meaning of the return code of the preprocessor has changed. 0 is now success and any other value means failure. This value is stored in the log and you can use it to keep details about the error condition.
48 3) New function StoreReferenceFile to _directly_ store a file (without opening it) to the reference storage.
50 4) The memory usage of the preprocessor is monitored. If it exceeds 2 GB it is terminated.
52 5) New function AliPreprocessor::ProcessDCS(). If you do not need to have DCS data in all cases, you can skip the processing by implemting this function and returning kFALSE under certain conditions. E.g. if there is a certain run type.
53 If you always need DCS data (like before), you do not need to implement it.
55 6) The run type has been added to the monitoring page
57 Revision 1.33 2007/04/03 13:56:01 acolla
58 Grid Storage at the end of preprocessing. Added virtual method to disable DCS query according to the
61 Revision 1.32 2007/02/28 10:41:56 acolla
62 Run type field added in SHUTTLE framework. Run type is read from "run type" logbook and retrieved by
63 AliPreprocessor::GetRunType() function.
64 Added some ldap definition files.
66 Revision 1.30 2007/02/13 11:23:21 acolla
67 Moved getters and setters of Shuttle's main OCDB/Reference, local
68 OCDB/Reference, temp and log folders to AliShuttleInterface
70 Revision 1.27 2007/01/30 17:52:42 jgrosseo
71 adding monalisa monitoring
73 Revision 1.26 2007/01/23 19:20:03 acolla
74 Removed old ldif files, added TOF, MCH ldif files. Added some options in
75 AliShuttleConfig::Print. Added in Ali Shuttle: SetShuttleTempDir and
78 Revision 1.25 2007/01/15 19:13:52 acolla
79 Moved some AliInfo to AliDebug in SendMail function
81 Revision 1.21 2006/12/07 08:51:26 jgrosseo
83 table, db names in ldap configuration
84 added GRP preprocessor
85 DCS data can also be retrieved by data point
87 Revision 1.20 2006/11/16 16:16:48 jgrosseo
88 introducing strict run ordering flag
89 removed giving preprocessor name to preprocessor, they have to know their name themselves ;-)
91 Revision 1.19 2006/11/06 14:23:04 jgrosseo
92 major update (Alberto)
93 o) reading of run parameters from the logbook
94 o) online offline naming conversion
95 o) standalone DCSclient package
97 Revision 1.18 2006/10/20 15:22:59 jgrosseo
98 o) Adding time out to the execution of the preprocessors: The Shuttle forks and the parent process monitors the child
99 o) Merging Collect, CollectAll, CollectNew function
100 o) Removing implementation of empty copy constructors (declaration still there!)
102 Revision 1.17 2006/10/05 16:20:55 jgrosseo
103 adapting to new CDB classes
105 Revision 1.16 2006/10/05 15:46:26 jgrosseo
106 applying to the new interface
108 Revision 1.15 2006/10/02 16:38:39 jgrosseo
111 storing of objects that failed to be stored to the grid before
112 interfacing of shuttle status table in daq system
114 Revision 1.14 2006/08/29 09:16:05 jgrosseo
117 Revision 1.13 2006/08/15 10:50:00 jgrosseo
118 effc++ corrections (alberto)
120 Revision 1.12 2006/08/08 14:19:29 jgrosseo
121 Update to shuttle classes (Alberto)
123 - Possibility to set the full object's path in the Preprocessor's and
124 Shuttle's Store functions
125 - Possibility to extend the object's run validity in the same classes
126 ("startValidity" and "validityInfinite" parameters)
127 - Implementation of the StoreReferenceData function to store reference
128 data in a dedicated CDB storage.
130 Revision 1.11 2006/07/21 07:37:20 jgrosseo
131 last run is stored after each run
133 Revision 1.10 2006/07/20 09:54:40 jgrosseo
134 introducing status management: The processing per subdetector is divided into several steps,
135 after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
136 can keep track of the number of failures and skips further processing after a certain threshold is
137 exceeded. These thresholds can be configured in LDAP.
139 Revision 1.9 2006/07/19 10:09:55 jgrosseo
140 new configuration, accesst to DAQ FES (Alberto)
142 Revision 1.8 2006/07/11 12:44:36 jgrosseo
143 adding parameters for extended validity range of data produced by preprocessor
145 Revision 1.7 2006/07/10 14:37:09 jgrosseo
146 small fix + todo comment
148 Revision 1.6 2006/07/10 13:01:41 jgrosseo
149 enhanced storing of last sucessfully processed run (alberto)
151 Revision 1.5 2006/07/04 14:59:57 jgrosseo
152 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
154 Revision 1.4 2006/06/12 09:11:16 jgrosseo
155 coding conventions (Alberto)
157 Revision 1.3 2006/06/06 14:26:40 jgrosseo
158 o) removed files that were moved to STEER
159 o) shuttle updated to follow the new interface (Alberto)
161 Revision 1.2 2006/03/07 07:52:34 hristov
162 New version (B.Yordanov)
164 Revision 1.6 2005/11/19 17:19:14 byordano
165 RetrieveDATEEntries and RetrieveConditionsData added
167 Revision 1.5 2005/11/19 11:09:27 byordano
168 AliShuttle declaration added
170 Revision 1.4 2005/11/17 17:47:34 byordano
171 TList changed to TObjArray
173 Revision 1.3 2005/11/17 14:43:23 byordano
176 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
177 Initial import as subdirectory in AliRoot
179 Revision 1.2 2005/09/13 08:41:15 byordano
180 default startTime endTime added
182 Revision 1.4 2005/08/30 09:13:02 byordano
185 Revision 1.3 2005/08/29 21:15:47 byordano
191 // This class is the main manager for AliShuttle.
192 // It organizes the data retrieval from DCS and call the
193 // interface methods of AliPreprocessor.
194 // For every detector in AliShuttleConfgi (see AliShuttleConfig),
195 // data for its set of aliases is retrieved. If there is registered
196 // AliPreprocessor for this detector then it will be used
197 // accroding to the schema (see AliPreprocessor).
198 // If there isn't registered AliPreprocessor than the retrieved
199 // data is stored automatically to the undelying AliCDBStorage.
200 // For detSpec is used the alias name.
203 #include "AliShuttle.h"
205 #include "AliCDBManager.h"
206 #include "AliCDBStorage.h"
207 #include "AliCDBId.h"
208 #include "AliCDBRunRange.h"
209 #include "AliCDBPath.h"
210 #include "AliCDBEntry.h"
211 #include "AliShuttleConfig.h"
212 #include "DCSClient/AliDCSClient.h"
214 #include "AliPreprocessor.h"
215 #include "AliShuttleStatus.h"
216 #include "AliShuttleLogbookEntry.h"
221 #include <TTimeStamp.h>
222 #include <TObjString.h>
223 #include <TSQLServer.h>
224 #include <TSQLResult.h>
227 #include <TSystemDirectory.h>
228 #include <TSystemFile.h>
229 #include <TFileMerger.h>
231 #include <TGridResult.h>
233 #include <TMonaLisaWriter.h>
237 #include <sys/types.h>
238 #include <sys/wait.h>
242 //______________________________________________________________________________________________
243 AliShuttle::AliShuttle(const AliShuttleConfig* config,
244 UInt_t timeout, Int_t retries):
246 fTimeout(timeout), fRetries(retries),
256 fReadTestMode(kFALSE),
257 fOutputRedirected(kFALSE)
260 // config: AliShuttleConfig used
261 // timeout: timeout used for AliDCSClient connection
262 // retries: the number of retries in case of connection error.
265 if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
266 for(int iSys=0;iSys<4;iSys++) {
269 fFXSlist[iSys].SetOwner(kTRUE);
271 fPreprocessorMap.SetOwner(kTRUE);
273 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
274 fFirstUnprocessed[iDet] = kFALSE;
276 fMonitoringMutex = new TMutex();
279 //______________________________________________________________________________________________
280 AliShuttle::~AliShuttle()
286 fPreprocessorMap.DeleteAll();
287 for(int iSys=0;iSys<4;iSys++)
289 fServer[iSys]->Close();
290 delete fServer[iSys];
299 if (fMonitoringMutex)
301 delete fMonitoringMutex;
302 fMonitoringMutex = 0;
306 //______________________________________________________________________________________________
307 void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
310 // Registers new AliPreprocessor.
311 // It uses GetName() for indentificator of the pre processor.
312 // The pre processor is registered it there isn't any other
313 // with the same identificator (GetName()).
316 const char* detName = preprocessor->GetName();
317 if(GetDetPos(detName) < 0)
318 AliFatal(Form("********** !!!!! Invalid detector name: %s !!!!! **********", detName));
320 if (fPreprocessorMap.GetValue(detName)) {
321 AliWarning(Form("AliPreprocessor %s is already registered!", detName));
325 fPreprocessorMap.Add(new TObjString(detName), preprocessor);
327 //______________________________________________________________________________________________
328 Bool_t AliShuttle::Store(const AliCDBPath& path, TObject* object,
329 AliCDBMetaData* metaData, Int_t validityStart, Bool_t validityInfinite)
331 // Stores a CDB object in the storage for offline reconstruction. Objects that are not needed for
332 // offline reconstruction, but should be stored anyway (e.g. for debugging) should NOT be stored
333 // using this function. Use StoreReferenceData instead!
334 // It calls StoreLocally function which temporarily stores the data locally; when the preprocessor
335 // finishes the data are transferred to the main storage (Grid).
337 return StoreLocally(fgkLocalCDB, path, object, metaData, validityStart, validityInfinite);
340 //______________________________________________________________________________________________
341 Bool_t AliShuttle::StoreReferenceData(const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData)
343 // Stores a CDB object in the storage for reference data. This objects will not be available during
344 // offline reconstrunction. Use this function for reference data only!
345 // It calls StoreLocally function which temporarily stores the data locally; when the preprocessor
346 // finishes the data are transferred to the main storage (Grid).
348 return StoreLocally(fgkLocalRefStorage, path, object, metaData);
351 //______________________________________________________________________________________________
352 Bool_t AliShuttle::StoreLocally(const TString& localUri,
353 const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData,
354 Int_t validityStart, Bool_t validityInfinite)
356 // Store object temporarily in local storage. Parameters are passed by Store and StoreReferenceData functions.
357 // when the preprocessor finishes the data are transferred to the main storage (Grid).
358 // The parameters are:
359 // 1) Uri of the backup storage (Local)
360 // 2) the object's path.
361 // 3) the object to be stored
362 // 4) the metaData to be associated with the object
363 // 5) the validity start run number w.r.t. the current run,
364 // if the data is valid only for this run leave the default 0
365 // 6) specifies if the calibration data is valid for infinity (this means until updated),
366 // typical for calibration runs, the default is kFALSE
368 // returns 0 if fail, 1 otherwise
370 if (fTestMode & kErrorStorage)
372 Log(fCurrentDetector, "StoreLocally - In TESTMODE - Simulating error while storing locally");
376 const char* cdbType = (localUri == fgkLocalCDB) ? "CDB" : "Reference";
378 Int_t firstRun = GetCurrentRun() - validityStart;
380 AliWarning("First valid run happens to be less than 0! Setting it to 0.");
385 if(validityInfinite) {
386 lastRun = AliCDBRunRange::Infinity();
388 lastRun = GetCurrentRun();
391 // Version is set to current run, it will be used later to transfer data to Grid
392 AliCDBId id(path, firstRun, lastRun, GetCurrentRun(), -1);
394 if(! dynamic_cast<TObjString*> (metaData->GetProperty("RunUsed(TObjString)"))){
395 TObjString runUsed = Form("%d", GetCurrentRun());
396 metaData->SetProperty("RunUsed(TObjString)", runUsed.Clone());
399 Bool_t result = kFALSE;
401 if (!(AliCDBManager::Instance()->GetStorage(localUri))) {
402 Log("SHUTTLE", Form("StoreLocally - Cannot activate local %s storage", cdbType));
404 result = AliCDBManager::Instance()->GetStorage(localUri)
405 ->Put(object, id, metaData);
410 Log(fCurrentDetector, Form("StoreLocally - Can't store object <%s>!", id.ToString().Data()));
416 //______________________________________________________________________________________________
417 Bool_t AliShuttle::StoreOCDB()
420 // Called when preprocessor ends successfully or when previous storage attempt failed (kStoreError status)
421 // Calls underlying StoreOCDB(const char*) function twice, for OCDB and Reference storage.
422 // Then calls StoreRefFilesToGrid to store reference files.
425 if (fTestMode & kErrorGrid)
427 Log("SHUTTLE", "StoreOCDB - In TESTMODE - Simulating error while storing in the Grid");
428 Log(fCurrentDetector, "StoreOCDB - In TESTMODE - Simulating error while storing in the Grid");
432 AliInfo("Storing OCDB data ...");
433 Bool_t resultCDB = StoreOCDB(fgkMainCDB);
435 AliInfo("Storing reference data ...");
436 Bool_t resultRef = StoreOCDB(fgkMainRefStorage);
438 AliInfo("Storing reference files ...");
439 Bool_t resultRefFiles = StoreRefFilesToGrid();
441 return resultCDB && resultRef && resultRefFiles;
444 //______________________________________________________________________________________________
445 Bool_t AliShuttle::StoreOCDB(const TString& gridURI)
448 // Called by StoreOCDB(), performs actual storage to the main OCDB and reference storages (Grid)
451 TObjArray* gridIds=0;
453 Bool_t result = kTRUE;
455 const char* type = 0;
457 if(gridURI == fgkMainCDB) {
459 localURI = fgkLocalCDB;
460 } else if(gridURI == fgkMainRefStorage) {
462 localURI = fgkLocalRefStorage;
464 AliError(Form("Invalid storage URI: %s", gridURI.Data()));
468 AliCDBManager* man = AliCDBManager::Instance();
470 AliCDBStorage *gridSto = man->GetStorage(gridURI);
473 Form("StoreOCDB - cannot activate main %s storage", type));
477 gridIds = gridSto->GetQueryCDBList();
479 // get objects previously stored in local CDB
480 AliCDBStorage *localSto = man->GetStorage(localURI);
483 Form("StoreOCDB - cannot activate local %s storage", type));
486 AliCDBPath aPath(GetOfflineDetName(fCurrentDetector.Data()),"*","*");
487 // Local objects were stored with current run as Grid version!
488 TList* localEntries = localSto->GetAll(aPath.GetPath(), GetCurrentRun(), GetCurrentRun());
489 localEntries->SetOwner(1);
491 // loop on local stored objects
492 TIter localIter(localEntries);
493 AliCDBEntry *aLocEntry = 0;
494 while((aLocEntry = dynamic_cast<AliCDBEntry*> (localIter.Next()))){
495 aLocEntry->SetOwner(1);
496 AliCDBId aLocId = aLocEntry->GetId();
497 aLocEntry->SetVersion(-1);
498 aLocEntry->SetSubVersion(-1);
500 // If local object is valid up to infinity we store it only if it is
501 // the first unprocessed run!
502 if (aLocId.GetLastRun() == AliCDBRunRange::Infinity() &&
503 !fFirstUnprocessed[GetDetPos(fCurrentDetector)])
505 Log("SHUTTLE", Form("StoreOCDB - %s: object %s has validity infinite but "
506 "there are previous unprocessed runs!",
507 fCurrentDetector.Data(), aLocId.GetPath().Data()));
511 // loop on Grid valid Id's
512 Bool_t store = kTRUE;
513 TIter gridIter(gridIds);
514 AliCDBId* aGridId = 0;
515 while((aGridId = dynamic_cast<AliCDBId*> (gridIter.Next()))){
516 if(aGridId->GetPath() != aLocId.GetPath()) continue;
517 // skip all objects valid up to infinity
518 if(aGridId->GetLastRun() == AliCDBRunRange::Infinity()) continue;
519 // if we get here, it means there's already some more recent object stored on Grid!
524 // If we get here, the file can be stored!
525 Bool_t storeOk = gridSto->Put(aLocEntry);
526 if(!store || storeOk){
530 Log(fCurrentDetector.Data(),
531 Form("StoreOCDB - A more recent object already exists in %s storage: <%s>",
532 type, aGridId->ToString().Data()));
535 Form("StoreOCDB - Object <%s> successfully put into %s storage",
536 aLocId.ToString().Data(), type));
539 // removing local filename...
541 localSto->IdToFilename(aLocId, filename);
542 AliInfo(Form("Removing local file %s", filename.Data()));
543 RemoveFile(filename.Data());
547 Form("StoreOCDB - Grid %s storage of object <%s> failed",
548 type, aLocId.ToString().Data()));
552 localEntries->Clear();
557 //______________________________________________________________________________________________
558 Bool_t AliShuttle::CleanReferenceStorage(const char* detector)
560 // clears the directory used to store reference files of a given subdetector
562 AliCDBManager* man = AliCDBManager::Instance();
563 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
564 TString localBaseFolder = sto->GetBaseFolder();
567 targetDir.Form("%s/%s", localBaseFolder.Data(), detector);
569 Log("SHUTTLE", Form("Cleaning %s", targetDir.Data()));
571 Int_t result = gSystem->GetPathInfo(targetDir, 0, (Long64_t*) 0, 0, 0);
575 result = gSystem->Exec(Form("rm -r %s", targetDir.Data()));
578 Log("SHUTTLE", Form("StoreReferenceFile - Could not clear directory %s", targetDir.Data()));
583 result = gSystem->mkdir(targetDir, kTRUE);
586 Log("SHUTTLE", Form("StoreReferenceFile - Error creating base directory %s", targetDir.Data()));
593 //______________________________________________________________________________________________
594 Bool_t AliShuttle::StoreReferenceFile(const char* detector, const char* localFile, const char* gridFileName)
597 // Stores reference file directly (without opening it). This function stores the file locally.
599 // The file is stored under the following location:
600 // <base folder of local reference storage>/<DET>/<RUN#>_<gridFileName>
601 // where <gridFileName> is the second parameter given to the function
604 if (fTestMode & kErrorStorage)
606 Log(fCurrentDetector, "StoreReferenceFile - In TESTMODE - Simulating error while storing locally");
610 AliCDBManager* man = AliCDBManager::Instance();
611 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
613 TString localBaseFolder = sto->GetBaseFolder();
616 targetDir.Form("%s/%s", localBaseFolder.Data(), GetOfflineDetName(detector));
619 target.Form("%s/%d_%s", targetDir.Data(), GetCurrentRun(), gridFileName);
621 Int_t result = gSystem->GetPathInfo(localFile, 0, (Long64_t*) 0, 0, 0);
624 Log("SHUTTLE", Form("StoreReferenceFile - %s does not exist", localFile));
628 result = gSystem->CopyFile(localFile, target);
632 Log("SHUTTLE", Form("StoreReferenceFile - Stored file %s locally to %s", localFile, target.Data()));
637 Log("SHUTTLE", Form("StoreReferenceFile - Storing file %s locally to %s failed. Error code = %d",
638 localFile, target.Data(), result));
643 //______________________________________________________________________________________________
644 Bool_t AliShuttle::StoreRefFilesToGrid()
647 // Transfers the reference file to the Grid.
649 // The files are stored under the following location:
650 // <base folder of reference storage>/<DET>/<RUN#>_<gridFileName>
653 AliCDBManager* man = AliCDBManager::Instance();
654 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
657 TString localBaseFolder = sto->GetBaseFolder();
660 dir.Form("%s/%s", localBaseFolder.Data(), GetOfflineDetName(fCurrentDetector));
662 AliCDBStorage* gridSto = man->GetStorage(fgkMainRefStorage);
665 TString gridBaseFolder = gridSto->GetBaseFolder();
667 alienDir.Form("%s%s", gridBaseFolder.Data(), GetOfflineDetName(fCurrentDetector));
670 begin.Form("%d_", GetCurrentRun());
672 TSystemDirectory* baseDir = new TSystemDirectory("/", dir);
676 TList* dirList = baseDir->GetListOfFiles();
683 Int_t nDirs = dirList->GetEntries();
685 Log("SHUTTLE", Form("There are %d reference files in folder %s to be transferred to Grid",
686 nDirs, GetOfflineDetName(fCurrentDetector)));
688 if(nDirs < 1) return kTRUE;
692 Log("SHUTTLE", "Connection to Grid failed: Cannot continue!");
696 Bool_t success = kTRUE;
697 Bool_t first = kTRUE;
699 for (Int_t iDir=0; iDir<nDirs; ++iDir)
701 TSystemFile* entry = dynamic_cast<TSystemFile*> (dirList->At(iDir));
705 if (entry->IsDirectory())
708 TString fileName(entry->GetName());
709 if (!fileName.BeginsWith(begin))
715 // check that DET folder exists, otherwise create it
716 TGridResult* result = gGrid->Ls(alienDir.Data(), "a");
721 if (!result->GetFileName(1)) // TODO: It looks like element 0 is always 0!!
723 if (!gGrid->Mkdir(alienDir.Data(),"",0))
725 Log("SHUTTLE", Form("StoreRefFilesToGrid - Cannot create directory %s",
730 Log("SHUTTLE",Form("Folder %s created", alienDir.Data()));
734 Log("SHUTTLE",Form("Folder %s found", alienDir.Data()));
738 TString fullLocalPath;
739 fullLocalPath.Form("%s/%s", dir.Data(), fileName.Data());
741 TString fullGridPath;
742 fullGridPath.Form("alien://%s/%s", alienDir.Data(), fileName.Data());
744 Log("SHUTTLE", Form("StoreRefFilesToGrid - Copying local file %s to %s", fullLocalPath.Data(), fullGridPath.Data()));
746 TFileMerger fileMerger;
747 Bool_t result = fileMerger.Cp(fullLocalPath, fullGridPath);
751 Log("SHUTTLE", Form("StoreRefFilesToGrid - Copying local file %s to %s succeeded", fullLocalPath.Data(), fullGridPath.Data()));
752 RemoveFile(fullLocalPath);
756 Log("SHUTTLE", Form("StoreRefFilesToGrid - Copying local file %s to %s failed", fullLocalPath.Data(), fullGridPath.Data()));
766 //______________________________________________________________________________________________
767 void AliShuttle::CleanLocalStorage(const TString& uri)
770 // Called in case the preprocessor is declared failed. Remove remaining objects from the local storages.
773 const char* type = 0;
774 if(uri == fgkLocalCDB) {
776 } else if(uri == fgkLocalRefStorage) {
779 AliError(Form("Invalid storage URI: %s", uri.Data()));
783 AliCDBManager* man = AliCDBManager::Instance();
785 // open local storage
786 AliCDBStorage *localSto = man->GetStorage(uri);
789 Form("CleanLocalStorage - cannot activate local %s storage", type));
793 TString filename(Form("%s/%s/*/Run*_v%d_s*.root",
794 localSto->GetBaseFolder().Data(), GetOfflineDetName(fCurrentDetector.Data()), GetCurrentRun()));
796 AliInfo(Form("filename = %s", filename.Data()));
798 AliInfo(Form("Removing remaining local files from run %d and detector %s ...",
799 GetCurrentRun(), fCurrentDetector.Data()));
801 RemoveFile(filename.Data());
805 //______________________________________________________________________________________________
806 void AliShuttle::RemoveFile(const char* filename)
809 // removes local file
812 TString command(Form("rm -f %s", filename));
814 Int_t result = gSystem->Exec(command.Data());
817 Log("SHUTTLE", Form("RemoveFile - %s: Cannot remove file %s!",
818 fCurrentDetector.Data(), filename));
822 //______________________________________________________________________________________________
823 AliShuttleStatus* AliShuttle::ReadShuttleStatus()
826 // Reads the AliShuttleStatus from the CDB
834 fStatusEntry = AliCDBManager::Instance()->GetStorage(GetLocalCDB())
835 ->Get(Form("/SHUTTLE/STATUS/%s", fCurrentDetector.Data()), GetCurrentRun());
837 if (!fStatusEntry) return 0;
838 fStatusEntry->SetOwner(1);
840 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
842 AliError("Invalid object stored to CDB!");
849 //______________________________________________________________________________________________
850 Bool_t AliShuttle::WriteShuttleStatus(AliShuttleStatus* status)
853 // writes the status for one subdetector
861 Int_t run = GetCurrentRun();
863 AliCDBId id(AliCDBPath("SHUTTLE", "STATUS", fCurrentDetector), run, run);
865 fStatusEntry = new AliCDBEntry(status, id, new AliCDBMetaData);
866 fStatusEntry->SetOwner(1);
868 UInt_t result = AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
871 Log("SHUTTLE", Form("WriteShuttleStatus - Failed for %s, run %d",
872 fCurrentDetector.Data(), run));
881 //______________________________________________________________________________________________
882 void AliShuttle::UpdateShuttleStatus(AliShuttleStatus::Status newStatus, Bool_t increaseCount)
885 // changes the AliShuttleStatus for the given detector and run to the given status
889 AliError("UNEXPECTED: fStatusEntry empty");
893 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
896 Log("SHUTTLE", "UNEXPECTED: status could not be read from current CDB entry");
900 TString actionStr = Form("UpdateShuttleStatus - %s: Changing state from %s to %s",
901 fCurrentDetector.Data(),
902 status->GetStatusName(),
903 status->GetStatusName(newStatus));
904 Log("SHUTTLE", actionStr);
905 SetLastAction(actionStr);
907 status->SetStatus(newStatus);
908 if (increaseCount) status->IncreaseCount();
910 AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
915 //______________________________________________________________________________________________
916 void AliShuttle::SendMLInfo()
919 // sends ML information about the current status of the current detector being processed
922 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
925 Log("SHUTTLE", "SendMLInfo - UNEXPECTED: status could not be read from current CDB entry");
929 TMonaLisaText mlStatus(Form("%s_status", fCurrentDetector.Data()), status->GetStatusName());
930 TMonaLisaValue mlRetryCount(Form("%s_count", fCurrentDetector.Data()), status->GetCount());
933 mlList.Add(&mlStatus);
934 mlList.Add(&mlRetryCount);
936 fMonaLisa->SendParameters(&mlList);
939 //______________________________________________________________________________________________
940 Bool_t AliShuttle::ContinueProcessing()
942 // this function reads the AliShuttleStatus information from CDB and
943 // checks if the processing should be continued
944 // if yes it returns kTRUE and updates the AliShuttleStatus with nextStatus
946 if (!fConfig->HostProcessDetector(fCurrentDetector)) return kFALSE;
948 AliPreprocessor* aPreprocessor =
949 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
952 AliInfo(Form("%s: no preprocessor registered", fCurrentDetector.Data()));
956 AliShuttleLogbookEntry::Status entryStatus =
957 fLogbookEntry->GetDetectorStatus(fCurrentDetector);
959 if(entryStatus != AliShuttleLogbookEntry::kUnprocessed) {
960 AliInfo(Form("ContinueProcessing - %s is %s",
961 fCurrentDetector.Data(),
962 fLogbookEntry->GetDetectorStatusName(entryStatus)));
966 // if we get here, according to Shuttle logbook subdetector is in UNPROCESSED state
968 // check if current run is first unprocessed run for current detector
969 if (fConfig->StrictRunOrder(fCurrentDetector) &&
970 !fFirstUnprocessed[GetDetPos(fCurrentDetector)])
972 if (fTestMode == kNone)
974 Log("SHUTTLE", Form("ContinueProcessing - %s requires strict run ordering but this is not the first unprocessed run!"));
979 Log("SHUTTLE", Form("ContinueProcessing - In TESTMODE - Although %s requires strict run ordering and this is not the first unprocessed run, the SHUTTLE continues"));
983 AliShuttleStatus* status = ReadShuttleStatus();
986 Log("SHUTTLE", Form("ContinueProcessing - %s: Processing first time",
987 fCurrentDetector.Data()));
988 status = new AliShuttleStatus(AliShuttleStatus::kStarted);
989 return WriteShuttleStatus(status);
992 // The following two cases shouldn't happen if Shuttle Logbook was correctly updated.
993 // If it happens it may mean Logbook updating failed... let's do it now!
994 if (status->GetStatus() == AliShuttleStatus::kDone ||
995 status->GetStatus() == AliShuttleStatus::kFailed){
996 Log("SHUTTLE", Form("ContinueProcessing - %s is already %s. Updating Shuttle Logbook",
997 fCurrentDetector.Data(),
998 status->GetStatusName(status->GetStatus())));
999 UpdateShuttleLogbook(fCurrentDetector.Data(),
1000 status->GetStatusName(status->GetStatus()));
1004 if (status->GetStatus() == AliShuttleStatus::kStoreError) {
1006 Form("ContinueProcessing - %s: Grid storage of one or more objects failed. Trying again now",
1007 fCurrentDetector.Data()));
1008 UpdateShuttleStatus(AliShuttleStatus::kStoreStarted);
1010 Log("SHUTTLE", Form("ContinueProcessing - %s: all objects successfully stored into main storage",
1011 fCurrentDetector.Data()));
1012 UpdateShuttleStatus(AliShuttleStatus::kDone);
1013 UpdateShuttleLogbook(fCurrentDetector.Data(), "DONE");
1016 Form("ContinueProcessing - %s: Grid storage failed again",
1017 fCurrentDetector.Data()));
1018 UpdateShuttleStatus(AliShuttleStatus::kStoreError);
1023 // if we get here, there is a restart
1024 Bool_t cont = kFALSE;
1027 if (status->GetCount() >= fConfig->GetMaxRetries()) {
1028 Log("SHUTTLE", Form("ContinueProcessing - %s failed %d times in status %s - "
1029 "Updating Shuttle Logbook", fCurrentDetector.Data(),
1030 status->GetCount(), status->GetStatusName()));
1031 UpdateShuttleLogbook(fCurrentDetector.Data(), "FAILED");
1032 UpdateShuttleStatus(AliShuttleStatus::kFailed);
1034 // there may still be objects in local OCDB and reference storage
1035 // and FXS databases may be not updated: do it now!
1037 // TODO Currently disabled, we want to keep files in case of failure!
1038 // CleanLocalStorage(fgkLocalCDB);
1039 // CleanLocalStorage(fgkLocalRefStorage);
1040 // UpdateTableFailCase();
1042 // Send mail to detector expert!
1043 AliInfo(Form("Sending mail to %s expert...", fCurrentDetector.Data()));
1045 Log("SHUTTLE", Form("ContinueProcessing - Could not send mail to %s expert",
1046 fCurrentDetector.Data()));
1049 Log("SHUTTLE", Form("ContinueProcessing - %s: restarting. "
1050 "Aborted before with %s. Retry number %d.", fCurrentDetector.Data(),
1051 status->GetStatusName(), status->GetCount()));
1052 Bool_t increaseCount = kTRUE;
1053 if (status->GetStatus() == AliShuttleStatus::kDCSError || status->GetStatus() == AliShuttleStatus::kDCSStarted)
1054 increaseCount = kFALSE;
1055 UpdateShuttleStatus(AliShuttleStatus::kStarted, increaseCount);
1062 //______________________________________________________________________________________________
1063 Bool_t AliShuttle::Process(AliShuttleLogbookEntry* entry)
1066 // Makes data retrieval for all detectors in the configuration.
1067 // entry: Shuttle logbook entry, contains run paramenters and status of detectors
1068 // (Unprocessed, Inactive, Failed or Done).
1069 // Returns kFALSE in case of error occured and kTRUE otherwise
1072 if (!entry) return kFALSE;
1074 fLogbookEntry = entry;
1076 AliInfo(Form("\n\n \t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: START ^*^*^*^*^*^*^*^*^*^*^*^* \n",
1079 // create ML instance that monitors this run
1080 fMonaLisa = new TMonaLisaWriter(Form("%d", GetCurrentRun()), "SHUTTLE", "aliendb1.cern.ch");
1081 // disable monitoring of other parameters that come e.g. from TFile
1082 gMonitoringWriter = 0;
1084 // Send the information to ML
1085 TMonaLisaText mlStatus("SHUTTLE_status", "Processing");
1086 TMonaLisaText mlRunType("SHUTTLE_runtype", Form("%s (%s)", entry->GetRunType(), entry->GetRunParameter("log")));
1089 mlList.Add(&mlStatus);
1090 mlList.Add(&mlRunType);
1092 fMonaLisa->SendParameters(&mlList);
1094 if (fLogbookEntry->IsDone())
1096 Log("SHUTTLE","Process - Shuttle is already DONE. Updating logbook");
1097 UpdateShuttleLogbook("shuttle_done");
1102 // read test mode if flag is set
1106 TString logEntry(entry->GetRunParameter("log"));
1107 //printf("log entry = %s\n", logEntry.Data());
1108 TString searchStr("Testmode: ");
1109 Int_t pos = logEntry.Index(searchStr.Data());
1110 //printf("%d\n", pos);
1113 TSubString subStr = logEntry(pos + searchStr.Length(), logEntry.Length());
1114 //printf("%s\n", subStr.String().Data());
1115 TString newStr(subStr.Data());
1116 TObjArray* token = newStr.Tokenize(' ');
1120 TObjString* tmpStr = dynamic_cast<TObjString*> (token->First());
1123 Int_t testMode = tmpStr->String().Atoi();
1126 Log("SHUTTLE", Form("Enabling test mode %d", testMode));
1127 SetTestMode((TestMode) testMode);
1135 Log("SHUTTLE", Form("The test mode flag is %d", (Int_t) fTestMode));
1137 fLogbookEntry->Print("all");
1140 Bool_t hasError = kFALSE;
1142 AliCDBStorage *mainCDBSto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
1143 if(mainCDBSto) mainCDBSto->QueryCDB(GetCurrentRun());
1144 AliCDBStorage *mainRefSto = AliCDBManager::Instance()->GetStorage(fgkMainRefStorage);
1145 if(mainRefSto) mainRefSto->QueryCDB(GetCurrentRun());
1147 // Loop on detectors in the configuration
1148 TIter iter(fConfig->GetDetectors());
1149 TObjString* aDetector = 0;
1151 while ((aDetector = (TObjString*) iter.Next()))
1153 fCurrentDetector = aDetector->String();
1155 if (ContinueProcessing() == kFALSE) continue;
1157 AliInfo(Form("\n\n \t\t\t****** run %d - %s: START ******",
1158 GetCurrentRun(), aDetector->GetName()));
1160 for(Int_t iSys=0;iSys<3;iSys++) fFXSCalled[iSys]=kFALSE;
1162 Log(fCurrentDetector.Data(), "Starting processing");
1168 Log("SHUTTLE", "ERROR: Forking failed");
1173 AliInfo(Form("In parent process of %d - %s: Starting monitoring",
1174 GetCurrentRun(), aDetector->GetName()));
1176 Long_t begin = time(0);
1178 int status; // to be used with waitpid, on purpose an int (not Int_t)!
1179 while (waitpid(pid, &status, WNOHANG) == 0)
1181 Long_t expiredTime = time(0) - begin;
1183 if (expiredTime > fConfig->GetPPTimeOut())
1186 tmp.Form("Process of %s time out. Run time: %d seconds. Killing...",
1187 fCurrentDetector.Data(), expiredTime);
1188 Log("SHUTTLE", tmp);
1189 Log(fCurrentDetector, tmp);
1193 UpdateShuttleStatus(AliShuttleStatus::kPPTimeOut);
1196 gSystem->Sleep(1000);
1200 gSystem->Sleep(1000);
1203 checkStr.Form("ps -o vsize --pid %d | tail -n 1", pid);
1204 FILE* pipe = gSystem->OpenPipe(checkStr, "r");
1207 Log("SHUTTLE", Form("Error: Could not open pipe to %s", checkStr.Data()));
1212 if (!fgets(buffer, 100, pipe))
1214 Log("SHUTTLE", "Error: ps did not return anything");
1215 gSystem->ClosePipe(pipe);
1218 gSystem->ClosePipe(pipe);
1220 //Log("SHUTTLE", Form("ps returned %s", buffer));
1223 if ((sscanf(buffer, "%d\n", &mem) != 1) || !mem)
1225 Log("SHUTTLE", "Error: Could not parse output of ps");
1229 if (expiredTime % 60 == 0)
1230 Log("SHUTTLE", Form("%s: Checking process. Run time: %d seconds - Memory consumption: %d KB",
1231 fCurrentDetector.Data(), expiredTime, mem));
1233 if (mem > fConfig->GetPPMaxMem())
1236 tmp.Form("Process exceeds maximum allowed memory (%d KB > %d KB). Killing...",
1237 mem, fConfig->GetPPMaxMem());
1238 Log("SHUTTLE", tmp);
1239 Log(fCurrentDetector, tmp);
1243 UpdateShuttleStatus(AliShuttleStatus::kPPOutOfMemory);
1246 gSystem->Sleep(1000);
1251 AliInfo(Form("In parent process of %d - %s: Client has terminated.",
1252 GetCurrentRun(), aDetector->GetName()));
1254 if (WIFEXITED(status))
1256 Int_t returnCode = WEXITSTATUS(status);
1258 Log("SHUTTLE", Form("%s: the return code is %d", fCurrentDetector.Data(),
1261 if (returnCode == 0) hasError = kTRUE;
1267 AliInfo(Form("In client process of %d - %s", GetCurrentRun(), aDetector->GetName()));
1269 AliInfo("Redirecting output...");
1271 if ((freopen(GetLogFileName(fCurrentDetector), "a", stdout)) == 0)
1273 Log("SHUTTLE", "Could not freopen stdout");
1277 fOutputRedirected = kTRUE;
1278 if ((dup2(fileno(stdout), fileno(stderr))) < 0)
1279 Log("SHUTTLE", "Could not redirect stderr");
1283 Bool_t success = ProcessCurrentDetector();
1284 if (success) // Preprocessor finished successfully!
1286 // Update time_processed field in FXS DB
1287 if (UpdateTable() == kFALSE)
1288 Log("SHUTTLE", Form("Process - %s: Could not update FXS databases!"));
1290 // Transfer the data from local storage to main storage (Grid)
1291 UpdateShuttleStatus(AliShuttleStatus::kStoreStarted);
1292 if (StoreOCDB() == kFALSE)
1294 AliInfo(Form("\n \t\t\t****** run %d - %s: STORAGE ERROR ****** \n\n",
1295 GetCurrentRun(), aDetector->GetName()));
1296 UpdateShuttleStatus(AliShuttleStatus::kStoreError);
1299 AliInfo(Form("\n \t\t\t****** run %d - %s: DONE ****** \n\n",
1300 GetCurrentRun(), aDetector->GetName()));
1301 UpdateShuttleStatus(AliShuttleStatus::kDone);
1302 UpdateShuttleLogbook(fCurrentDetector, "DONE");
1306 for (UInt_t iSys=0; iSys<3; iSys++)
1308 if (fFXSCalled[iSys]) fFXSlist[iSys].Clear();
1311 AliInfo(Form("Client process of %d - %s is exiting now with %d.",
1312 GetCurrentRun(), aDetector->GetName(), success));
1314 // the client exits here
1315 gSystem->Exit(success);
1317 AliError("We should never get here!!!");
1321 AliInfo(Form("\n\n \t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: FINISH ^*^*^*^*^*^*^*^*^*^*^*^* \n",
1324 //check if shuttle is done for this run, if so update logbook
1325 TObjArray checkEntryArray;
1326 checkEntryArray.SetOwner(1);
1327 TString whereClause = Form("where run=%d", GetCurrentRun());
1328 if (!QueryShuttleLogbook(whereClause.Data(), checkEntryArray) || checkEntryArray.GetEntries() == 0) {
1329 Log("SHUTTLE", Form("Process - Warning: Cannot check status of run %d on Shuttle logbook!",
1331 return hasError == kFALSE;
1334 AliShuttleLogbookEntry* checkEntry = dynamic_cast<AliShuttleLogbookEntry*>
1335 (checkEntryArray.At(0));
1339 if (checkEntry->IsDone())
1341 Log("SHUTTLE","Process - Shuttle is DONE. Updating logbook");
1342 UpdateShuttleLogbook("shuttle_done");
1346 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
1348 if (checkEntry->GetDetectorStatus(iDet) == AliShuttleLogbookEntry::kUnprocessed)
1350 AliDebug(2, Form("Run %d: setting %s as \"not first time unprocessed\"",
1351 checkEntry->GetRun(), GetDetName(iDet)));
1352 fFirstUnprocessed[iDet] = kFALSE;
1358 // remove ML instance
1364 return hasError == kFALSE;
1367 //______________________________________________________________________________________________
1368 Bool_t AliShuttle::ProcessCurrentDetector()
1371 // Makes data retrieval just for a specific detector (fCurrentDetector).
1372 // Threre should be a configuration for this detector.
1374 AliInfo(Form("Retrieving values for %s, run %d", fCurrentDetector.Data(), GetCurrentRun()));
1376 if (!CleanReferenceStorage(GetOfflineDetName(fCurrentDetector)))
1382 Bool_t aDCSError = kFALSE;
1384 // call preprocessor
1385 AliPreprocessor* aPreprocessor =
1386 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
1388 aPreprocessor->Initialize(GetCurrentRun(), GetCurrentStartTime(), GetCurrentEndTime());
1390 Bool_t processDCS = aPreprocessor->ProcessDCS();
1394 Log(fCurrentDetector, "The preprocessor requested to skip the retrieval of DCS values");
1396 else if (fTestMode & kSkipDCS)
1398 Log(fCurrentDetector, "In TESTMODE - Skipping DCS processing!");
1400 else if (fTestMode & kErrorDCS)
1402 Log(fCurrentDetector, "In TESTMODE - Simulating DCS error");
1403 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
1404 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1408 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
1410 TString host(fConfig->GetDCSHost(fCurrentDetector));
1411 Int_t port = fConfig->GetDCSPort(fCurrentDetector);
1413 // Retrieval of Aliases
1414 TObjString* anAlias = 0;
1416 Int_t nTotAliases= ((TMap*)fConfig->GetDCSAliases(fCurrentDetector))->GetEntries();
1417 TIter iterAliases(fConfig->GetDCSAliases(fCurrentDetector));
1418 while ((anAlias = (TObjString*) iterAliases.Next()))
1420 TObjArray *valueSet = new TObjArray();
1421 valueSet->SetOwner(1);
1424 if (((iAlias-1) % 500) == 0 || iAlias == nTotAliases)
1425 AliInfo(Form("Querying DCS archive: alias %s (%d of %d)",
1426 anAlias->GetName(), iAlias, nTotAliases));
1427 aDCSError = (GetValueSet(host, port, anAlias->String(), valueSet, kAlias) == 0);
1431 dcsMap.Add(anAlias->Clone(), valueSet);
1433 Log(fCurrentDetector,
1434 Form("ProcessCurrentDetector - Error while retrieving alias %s",
1435 anAlias->GetName()));
1436 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1442 // Retrieval of Data Points
1443 TObjString* aDP = 0;
1445 Int_t nTotDPs= ((TMap*)fConfig->GetDCSDataPoints(fCurrentDetector))->GetEntries();
1446 TIter iterDP(fConfig->GetDCSDataPoints(fCurrentDetector));
1447 while ((aDP = (TObjString*) iterDP.Next()))
1449 TObjArray *valueSet = new TObjArray();
1450 valueSet->SetOwner(1);
1451 if (((iDP-1) % 500) == 0 || iDP == nTotDPs)
1452 AliInfo(Form("Querying DCS archive: DP %s (%d of %d)",
1453 aDP->GetName(), iDP++, nTotDPs));
1454 aDCSError = (GetValueSet(host, port, aDP->String(), valueSet, kDP) == 0);
1458 dcsMap.Add(aDP->Clone(), valueSet);
1460 Log(fCurrentDetector,
1461 Form("ProcessCurrentDetector - Error while retrieving data point %s",
1463 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1470 // DCS Archive DB processing successful. Call Preprocessor!
1471 UpdateShuttleStatus(AliShuttleStatus::kPPStarted);
1473 UInt_t returnValue = aPreprocessor->Process(&dcsMap);
1475 if (returnValue > 0) // Preprocessor error!
1477 Log(fCurrentDetector, Form("Preprocessor failed. Process returned %d.", returnValue));
1478 UpdateShuttleStatus(AliShuttleStatus::kPPError);
1484 UpdateShuttleStatus(AliShuttleStatus::kPPDone);
1485 Log(fCurrentDetector, Form("ProcessCurrentDetector - %s preprocessor returned success",
1486 fCurrentDetector.Data()));
1493 //______________________________________________________________________________________________
1494 Bool_t AliShuttle::QueryShuttleLogbook(const char* whereClause,
1497 // Query DAQ's Shuttle logbook and fills detector status object.
1498 // Call QueryRunParameters to query DAQ logbook for run parameters.
1501 entries.SetOwner(1);
1503 // check connection, in case connect
1504 if(!Connect(3)) return kFALSE;
1507 sqlQuery = Form("select * from %s %s order by run", fConfig->GetShuttlelbTable(), whereClause);
1509 TSQLResult* aResult = fServer[3]->Query(sqlQuery);
1511 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
1515 AliDebug(2,Form("Query = %s", sqlQuery.Data()));
1517 if(aResult->GetRowCount() == 0) {
1518 AliInfo("No entries in Shuttle Logbook match request");
1523 // TODO Check field count!
1524 const UInt_t nCols = 22;
1525 if (aResult->GetFieldCount() != (Int_t) nCols) {
1526 AliError("Invalid SQL result field number!");
1532 while ((aRow = aResult->Next())) {
1533 TString runString(aRow->GetField(0), aRow->GetFieldLength(0));
1534 Int_t run = runString.Atoi();
1536 AliShuttleLogbookEntry *entry = QueryRunParameters(run);
1540 // loop on detectors
1541 for(UInt_t ii = 0; ii < nCols; ii++)
1542 entry->SetDetectorStatus(aResult->GetFieldName(ii), aRow->GetField(ii));
1544 entries.AddLast(entry);
1552 //______________________________________________________________________________________________
1553 AliShuttleLogbookEntry* AliShuttle::QueryRunParameters(Int_t run)
1556 // Retrieve run parameters written in the DAQ logbook and sets them into AliShuttleLogbookEntry object
1559 // check connection, in case connect
1564 sqlQuery.Form("select * from %s where run=%d", fConfig->GetDAQlbTable(), run);
1566 TSQLResult* aResult = fServer[3]->Query(sqlQuery);
1568 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
1572 if (aResult->GetRowCount() == 0) {
1573 Log("SHUTTLE", Form("QueryRunParameters - No entry in DAQ Logbook for run %d. Skipping", run));
1578 if (aResult->GetRowCount() > 1) {
1579 AliError(Form("More than one entry in DAQ Logbook for run %d. Skipping", run));
1584 TSQLRow* aRow = aResult->Next();
1587 AliError(Form("Could not retrieve row for run %d. Skipping", run));
1592 AliShuttleLogbookEntry* entry = new AliShuttleLogbookEntry(run);
1594 for (Int_t ii = 0; ii < aResult->GetFieldCount(); ii++)
1595 entry->SetRunParameter(aResult->GetFieldName(ii), aRow->GetField(ii));
1597 UInt_t startTime = entry->GetStartTime();
1598 UInt_t endTime = entry->GetEndTime();
1600 if (!startTime || !endTime || startTime > endTime) {
1602 Form("QueryRunParameters - Invalid parameters for Run %d: startTime = %d, endTime = %d",
1603 run, startTime, endTime));
1616 //______________________________________________________________________________________________
1617 Bool_t AliShuttle::GetValueSet(const char* host, Int_t port, const char* entry,
1618 TObjArray* valueSet, DCSType type)
1620 // Retrieve all "entry" data points from the DCS server
1621 // host, port: TSocket connection parameters
1622 // entry: name of the alias or data point
1623 // valueSet: array of retrieved AliDCSValue's
1624 // type: kAlias or kDP
1626 AliDCSClient client(host, port, fTimeout, fRetries);
1627 if (!client.IsConnected())
1636 result = client.GetAliasValues(entry,
1637 GetCurrentStartTime(), GetCurrentEndTime(), valueSet);
1641 result = client.GetDPValues(entry,
1642 GetCurrentStartTime(), GetCurrentEndTime(), valueSet);
1647 Log(fCurrentDetector.Data(), Form("GetValueSet - Can't get '%s'! Reason: %s",
1648 entry, AliDCSClient::GetErrorString(result)));
1650 if (result == AliDCSClient::fgkServerError)
1652 Log(fCurrentDetector.Data(), Form("GetValueSet - Server error: %s",
1653 client.GetServerError().Data()));
1662 //______________________________________________________________________________________________
1663 const char* AliShuttle::GetFile(Int_t system, const char* detector,
1664 const char* id, const char* source)
1666 // Get calibration file from file exchange servers
1667 // First queris the FXS database for the file name, using the run, detector, id and source info
1668 // then calls RetrieveFile(filename) for actual copy to local disk
1669 // run: current run being processed (given by Logbook entry fLogbookEntry)
1670 // detector: the Preprocessor name
1671 // id: provided as a parameter by the Preprocessor
1672 // source: provided by the Preprocessor through GetFileSources function
1674 // check if test mode should simulate a FXS error
1675 if (fTestMode & kErrorFXSFiles)
1677 Log(detector, Form("GetFile - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
1681 // check connection, in case connect
1682 if (!Connect(system))
1684 Log(detector, Form("GetFile - Couldn't connect to %s FXS database", GetSystemName(system)));
1688 // Query preparation
1689 TString sourceName(source);
1691 TString sqlQueryStart = Form("select filePath,size,fileChecksum from %s where",
1692 fConfig->GetFXSdbTable(system));
1693 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
1694 GetCurrentRun(), detector, id);
1698 whereClause += Form(" and DAQsource=\"%s\"", source);
1700 else if (system == kDCS)
1704 else if (system == kHLT)
1706 whereClause += Form(" and DDLnumbers=\"%s\"", source);
1710 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
1712 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
1715 TSQLResult* aResult = 0;
1716 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
1718 Log(detector, Form("GetFileName - Can't execute SQL query to %s database for: id = %s, source = %s",
1719 GetSystemName(system), id, sourceName.Data()));
1723 if(aResult->GetRowCount() == 0)
1726 Form("GetFileName - No entry in %s FXS db for: id = %s, source = %s",
1727 GetSystemName(system), id, sourceName.Data()));
1732 if (aResult->GetRowCount() > 1) {
1734 Form("GetFileName - More than one entry in %s FXS db for: id = %s, source = %s",
1735 GetSystemName(system), id, sourceName.Data()));
1740 if (aResult->GetFieldCount() != nFields) {
1742 Form("GetFileName - Wrong field count in %s FXS db for: id = %s, source = %s",
1743 GetSystemName(system), id, sourceName.Data()));
1748 TSQLRow* aRow = dynamic_cast<TSQLRow*> (aResult->Next());
1751 Log(detector, Form("GetFileName - Empty set result in %s FXS db from query: id = %s, source = %s",
1752 GetSystemName(system), id, sourceName.Data()));
1757 TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
1758 TString fileSize(aRow->GetField(1), aRow->GetFieldLength(1));
1759 TString fileChecksum(aRow->GetField(2), aRow->GetFieldLength(2));
1764 AliDebug(2, Form("filePath = %s; size = %s, fileChecksum = %s",
1765 filePath.Data(), fileSize.Data(), fileChecksum.Data()));
1767 // retrieved file is renamed to make it unique
1768 TString localFileName = Form("%s_%s_%d_%s_%s.shuttle",
1769 GetSystemName(system), detector, GetCurrentRun(), id, sourceName.Data());
1772 // file retrieval from FXS
1773 UInt_t nRetries = 0;
1774 UInt_t maxRetries = 3;
1775 Bool_t result = kFALSE;
1777 // copy!! if successful TSystem::Exec returns 0
1778 while(nRetries++ < maxRetries) {
1779 AliDebug(2, Form("Trying to copy file. Retry # %d", nRetries));
1780 result = RetrieveFile(system, filePath.Data(), localFileName.Data());
1783 Log(detector, Form("GetFileName - Copy of file %s from %s FXS failed",
1784 filePath.Data(), GetSystemName(system)));
1787 AliInfo(Form("File %s copied from %s FXS into %s/%s",
1788 filePath.Data(), GetSystemName(system),
1789 GetShuttleTempDir(), localFileName.Data()));
1792 if (fileChecksum.Length()>0)
1794 // compare md5sum of local file with the one stored in the FXS DB
1795 Int_t md5Comp = gSystem->Exec(Form("md5sum %s/%s |grep %s 2>&1 > /dev/null",
1796 GetShuttleTempDir(), localFileName.Data(), fileChecksum.Data()));
1800 Log(detector, Form("GetFileName - md5sum of file %s does not match with local copy!",
1806 Log(fCurrentDetector, Form("GetFile - md5sum of file %s not set in %s database, skipping comparison",
1807 filePath.Data(), GetSystemName(system)));
1812 if(!result) return 0;
1814 fFXSCalled[system]=kTRUE;
1815 TObjString *fileParams = new TObjString(Form("%s#!?!#%s", id, sourceName.Data()));
1816 fFXSlist[system].Add(fileParams);
1818 static TString fullLocalFileName;
1819 fullLocalFileName = TString::Format("%s/%s", GetShuttleTempDir(), localFileName.Data());
1821 AliInfo(Form("fullLocalFileName = %s", fullLocalFileName.Data()));
1823 return fullLocalFileName.Data();
1827 //______________________________________________________________________________________________
1828 Bool_t AliShuttle::RetrieveFile(UInt_t system, const char* fxsFileName, const char* localFileName)
1831 // Copies file from FXS to local Shuttle machine
1834 // check temp directory: trying to cd to temp; if it does not exist, create it
1835 AliDebug(2, Form("Copy file %s from %s FXS into %s/%s",
1836 GetSystemName(system), fxsFileName, GetShuttleTempDir(), localFileName));
1838 void* dir = gSystem->OpenDirectory(GetShuttleTempDir());
1840 if (gSystem->mkdir(GetShuttleTempDir(), kTRUE)) {
1841 AliError(Form("Can't open directory <%s>", GetShuttleTempDir()));
1846 gSystem->FreeDirectory(dir);
1849 TString baseFXSFolder;
1852 baseFXSFolder = "FES/";
1854 else if (system == kDCS)
1858 else if (system == kHLT)
1860 baseFXSFolder = "~/";
1864 TString command = Form("scp -oPort=%d -2 %s@%s:%s%s %s/%s",
1865 fConfig->GetFXSPort(system),
1866 fConfig->GetFXSUser(system),
1867 fConfig->GetFXSHost(system),
1868 baseFXSFolder.Data(),
1870 GetShuttleTempDir(),
1873 AliDebug(2, Form("%s",command.Data()));
1875 Bool_t result = (gSystem->Exec(command.Data()) == 0);
1880 //______________________________________________________________________________________________
1881 TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
1884 // Get sources producing the condition file Id from file exchange servers
1887 // check if test mode should simulate a FXS error
1888 if (fTestMode & kErrorFXSSources)
1890 Log(detector, Form("GetFileSources - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
1897 AliError("DCS system has only one source of data!");
1901 // check connection, in case connect
1902 if (!Connect(system))
1904 Log(detector, Form("GetFile - Couldn't connect to %s FXS database", GetSystemName(system)));
1908 TString sourceName = 0;
1911 sourceName = "DAQsource";
1912 } else if (system == kHLT)
1914 sourceName = "DDLnumbers";
1917 TString sqlQueryStart = Form("select %s from %s where", sourceName.Data(), fConfig->GetFXSdbTable(system));
1918 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
1919 GetCurrentRun(), detector, id);
1920 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
1922 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
1925 TSQLResult* aResult;
1926 aResult = fServer[system]->Query(sqlQuery);
1928 Log(detector, Form("GetFileSources - Can't execute SQL query to %s database for id: %s",
1929 GetSystemName(system), id));
1933 TList *list = new TList();
1936 if (aResult->GetRowCount() == 0)
1939 Form("GetFileSources - No entry in %s FXS table for id: %s", GetSystemName(system), id));
1946 while ((aRow = aResult->Next()))
1949 TString source(aRow->GetField(0), aRow->GetFieldLength(0));
1950 AliDebug(2, Form("%s = %s", sourceName.Data(), source.Data()));
1951 list->Add(new TObjString(source));
1960 //______________________________________________________________________________________________
1961 Bool_t AliShuttle::Connect(Int_t system)
1963 // Connect to MySQL Server of the system's FXS MySQL databases
1964 // DAQ Logbook, Shuttle Logbook and DAQ FXS db are on the same host
1967 // check connection: if already connected return
1968 if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
1970 TString dbHost, dbUser, dbPass, dbName;
1972 if (system < 3) // FXS db servers
1974 dbHost = Form("mysql://%s:%d", fConfig->GetFXSdbHost(system), fConfig->GetFXSdbPort(system));
1975 dbUser = fConfig->GetFXSdbUser(system);
1976 dbPass = fConfig->GetFXSdbPass(system);
1977 dbName = fConfig->GetFXSdbName(system);
1978 } else { // Run & Shuttle logbook servers
1979 // TODO Will the Shuttle logbook server be the same as the Run logbook server ???
1980 dbHost = Form("mysql://%s:%d", fConfig->GetDAQlbHost(), fConfig->GetDAQlbPort());
1981 dbUser = fConfig->GetDAQlbUser();
1982 dbPass = fConfig->GetDAQlbPass();
1983 dbName = fConfig->GetDAQlbDB();
1986 fServer[system] = TSQLServer::Connect(dbHost.Data(), dbUser.Data(), dbPass.Data());
1987 if (!fServer[system] || !fServer[system]->IsConnected()) {
1990 AliError(Form("Can't establish connection to FXS database for %s",
1991 AliShuttleInterface::GetSystemName(system)));
1993 AliError("Can't establish connection to Run logbook.");
1995 if(fServer[system]) delete fServer[system];
2000 TSQLResult* aResult=0;
2003 aResult = fServer[kDAQ]->GetTables(dbName.Data());
2006 aResult = fServer[kDCS]->GetTables(dbName.Data());
2009 aResult = fServer[kHLT]->GetTables(dbName.Data());
2012 aResult = fServer[3]->GetTables(dbName.Data());
2020 //______________________________________________________________________________________________
2021 Bool_t AliShuttle::UpdateTable()
2024 // Update FXS table filling time_processed field in all rows corresponding to current run and detector
2027 Bool_t result = kTRUE;
2029 for (UInt_t system=0; system<3; system++)
2031 if(!fFXSCalled[system]) continue;
2033 // check connection, in case connect
2034 if (!Connect(system))
2036 Log(fCurrentDetector, Form("UpdateTable - Couldn't connect to %s FXS database", GetSystemName(system)));
2041 TTimeStamp now; // now
2043 // Loop on FXS list entries
2044 TIter iter(&fFXSlist[system]);
2045 TObjString *aFXSentry=0;
2046 while ((aFXSentry = dynamic_cast<TObjString*> (iter.Next())))
2048 TString aFXSentrystr = aFXSentry->String();
2049 TObjArray *aFXSarray = aFXSentrystr.Tokenize("#!?!#");
2050 if (!aFXSarray || aFXSarray->GetEntries() != 2 )
2052 Log(fCurrentDetector, Form("UpdateTable - error updating %s FXS entry. Check string: <%s>",
2053 GetSystemName(system), aFXSentrystr.Data()));
2054 if(aFXSarray) delete aFXSarray;
2058 const char* fileId = ((TObjString*) aFXSarray->At(0))->GetName();
2059 const char* source = ((TObjString*) aFXSarray->At(1))->GetName();
2061 TString whereClause;
2064 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\";",
2065 GetCurrentRun(), fCurrentDetector.Data(), fileId, source);
2067 else if (system == kDCS)
2069 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\";",
2070 GetCurrentRun(), fCurrentDetector.Data(), fileId);
2072 else if (system == kHLT)
2074 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DDLnumbers=\"%s\";",
2075 GetCurrentRun(), fCurrentDetector.Data(), fileId, source);
2080 TString sqlQuery = Form("update %s set time_processed=%d %s", fConfig->GetFXSdbTable(system),
2081 now.GetSec(), whereClause.Data());
2083 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2086 TSQLResult* aResult;
2087 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2090 Log(fCurrentDetector, Form("UpdateTable - %s db: can't execute SQL query <%s>",
2091 GetSystemName(system), sqlQuery.Data()));
2102 //______________________________________________________________________________________________
2103 Bool_t AliShuttle::UpdateTableFailCase()
2105 // Update FXS table filling time_processed field in all rows corresponding to current run and detector
2106 // this is called in case the preprocessor is declared failed for the current run, because
2107 // the fields are updated only in case of success
2109 Bool_t result = kTRUE;
2111 for (UInt_t system=0; system<3; system++)
2113 // check connection, in case connect
2114 if (!Connect(system))
2116 Log(fCurrentDetector, Form("UpdateTableFailCase - Couldn't connect to %s FXS database",
2117 GetSystemName(system)));
2122 TTimeStamp now; // now
2124 // Loop on FXS list entries
2126 TString whereClause = Form("where run=%d and detector=\"%s\";",
2127 GetCurrentRun(), fCurrentDetector.Data());
2130 TString sqlQuery = Form("update %s set time_processed=%d %s", fConfig->GetFXSdbTable(system),
2131 now.GetSec(), whereClause.Data());
2133 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2136 TSQLResult* aResult;
2137 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2140 Log(fCurrentDetector, Form("UpdateTableFailCase - %s db: can't execute SQL query <%s>",
2141 GetSystemName(system), sqlQuery.Data()));
2151 //______________________________________________________________________________________________
2152 Bool_t AliShuttle::UpdateShuttleLogbook(const char* detector, const char* status)
2155 // Update Shuttle logbook filling detector or shuttle_done column
2156 // ex. of usage: UpdateShuttleLogbook("PHOS", "DONE") or UpdateShuttleLogbook("shuttle_done")
2159 // check connection, in case connect
2161 Log("SHUTTLE", "UpdateShuttleLogbook - Couldn't connect to DAQ Logbook.");
2165 TString detName(detector);
2167 if(detName == "shuttle_done")
2169 setClause = "set shuttle_done=1";
2171 // Send the information to ML
2172 TMonaLisaText mlStatus("SHUTTLE_status", "Done");
2175 mlList.Add(&mlStatus);
2177 fMonaLisa->SendParameters(&mlList);
2179 TString statusStr(status);
2180 if(statusStr.Contains("done", TString::kIgnoreCase) ||
2181 statusStr.Contains("failed", TString::kIgnoreCase)){
2182 setClause = Form("set %s=\"%s\"", detector, status);
2185 Form("UpdateShuttleLogbook - Invalid status <%s> for detector %s",
2191 TString whereClause = Form("where run=%d", GetCurrentRun());
2193 TString sqlQuery = Form("update %s %s %s",
2194 fConfig->GetShuttlelbTable(), setClause.Data(), whereClause.Data());
2196 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2199 TSQLResult* aResult;
2200 aResult = dynamic_cast<TSQLResult*> (fServer[3]->Query(sqlQuery));
2202 Log("SHUTTLE", Form("UpdateShuttleLogbook - Can't execute query <%s>", sqlQuery.Data()));
2210 //______________________________________________________________________________________________
2211 Int_t AliShuttle::GetCurrentRun() const
2214 // Get current run from logbook entry
2217 return fLogbookEntry ? fLogbookEntry->GetRun() : -1;
2220 //______________________________________________________________________________________________
2221 UInt_t AliShuttle::GetCurrentStartTime() const
2224 // get current start time
2227 return fLogbookEntry ? fLogbookEntry->GetStartTime() : 0;
2230 //______________________________________________________________________________________________
2231 UInt_t AliShuttle::GetCurrentEndTime() const
2234 // get current end time from logbook entry
2237 return fLogbookEntry ? fLogbookEntry->GetEndTime() : 0;
2240 //______________________________________________________________________________________________
2241 void AliShuttle::Log(const char* detector, const char* message)
2244 // Fill log string with a message
2247 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
2249 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE)) {
2250 AliError(Form("Can't open directory <%s>", GetShuttleLogDir()));
2255 gSystem->FreeDirectory(dir);
2258 TString toLog = Form("%s (%d): %s - ", TTimeStamp(time(0)).AsString("s"), getpid(), detector);
2259 if (GetCurrentRun() >= 0)
2260 toLog += Form("run %d - ", GetCurrentRun());
2261 toLog += Form("%s", message);
2263 AliInfo(toLog.Data());
2265 // if we redirect the log output already to the file, leave here
2266 if (fOutputRedirected && strcmp(detector, "SHUTTLE") != 0)
2269 TString fileName = GetLogFileName(detector);
2271 gSystem->ExpandPathName(fileName);
2274 logFile.open(fileName, ofstream::out | ofstream::app);
2276 if (!logFile.is_open()) {
2277 AliError(Form("Could not open file %s", fileName.Data()));
2281 logFile << toLog.Data() << "\n";
2286 //______________________________________________________________________________________________
2287 TString AliShuttle::GetLogFileName(const char* detector) const
2290 // returns the name of the log file for a given sub detector
2295 if (GetCurrentRun() >= 0)
2296 fileName.Form("%s/%s_%d.log", GetShuttleLogDir(), detector, GetCurrentRun());
2298 fileName.Form("%s/%s.log", GetShuttleLogDir(), detector);
2303 //______________________________________________________________________________________________
2304 Bool_t AliShuttle::Collect(Int_t run)
2307 // Collects conditions data for all UNPROCESSED run written to DAQ LogBook in case of run = -1 (default)
2308 // If a dedicated run is given this run is processed
2310 // In operational mode, this is the Shuttle function triggered by the EOR signal.
2314 Log("SHUTTLE","Collect - Shuttle called. Collecting conditions data for unprocessed runs");
2316 Log("SHUTTLE", Form("Collect - Shuttle called. Collecting conditions data for run %d", run));
2318 SetLastAction("Starting");
2320 TString whereClause("where shuttle_done=0");
2322 whereClause += Form(" and run=%d", run);
2324 TObjArray shuttleLogbookEntries;
2325 if (!QueryShuttleLogbook(whereClause, shuttleLogbookEntries))
2327 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2331 if (shuttleLogbookEntries.GetEntries() == 0)
2334 Log("SHUTTLE","Collect - Found no UNPROCESSED runs in Shuttle logbook");
2336 Log("SHUTTLE", Form("Collect - Run %d is already DONE "
2337 "or it does not exist in Shuttle logbook", run));
2341 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
2342 fFirstUnprocessed[iDet] = kTRUE;
2346 // query Shuttle logbook for earlier runs, check if some detectors are unprocessed,
2347 // flag them into fFirstUnprocessed array
2348 TString whereClause(Form("where shuttle_done=0 and run < %d", run));
2349 TObjArray tmpLogbookEntries;
2350 if (!QueryShuttleLogbook(whereClause, tmpLogbookEntries))
2352 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2356 TIter iter(&tmpLogbookEntries);
2357 AliShuttleLogbookEntry* anEntry = 0;
2358 while ((anEntry = dynamic_cast<AliShuttleLogbookEntry*> (iter.Next())))
2360 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
2362 if (anEntry->GetDetectorStatus(iDet) == AliShuttleLogbookEntry::kUnprocessed)
2364 AliDebug(2, Form("Run %d: setting %s as \"not first time unprocessed\"",
2365 anEntry->GetRun(), GetDetName(iDet)));
2366 fFirstUnprocessed[iDet] = kFALSE;
2374 if (!RetrieveConditionsData(shuttleLogbookEntries))
2376 Log("SHUTTLE", "Collect - Process of at least one run failed");
2380 Log("SHUTTLE", "Collect - Requested run(s) successfully processed");
2384 //______________________________________________________________________________________________
2385 Bool_t AliShuttle::RetrieveConditionsData(const TObjArray& dateEntries)
2388 // Retrieve conditions data for all runs that aren't processed yet
2391 Bool_t hasError = kFALSE;
2393 TIter iter(&dateEntries);
2394 AliShuttleLogbookEntry* anEntry;
2396 while ((anEntry = (AliShuttleLogbookEntry*) iter.Next())){
2397 if (!Process(anEntry)){
2401 // clean SHUTTLE temp directory
2402 TString filename = Form("%s/*.shuttle", GetShuttleTempDir());
2403 RemoveFile(filename.Data());
2406 return hasError == kFALSE;
2409 //______________________________________________________________________________________________
2410 ULong_t AliShuttle::GetTimeOfLastAction() const
2413 // Gets time of last action
2418 fMonitoringMutex->Lock();
2420 tmp = fLastActionTime;
2422 fMonitoringMutex->UnLock();
2427 //______________________________________________________________________________________________
2428 const TString AliShuttle::GetLastAction() const
2431 // returns a string description of the last action
2436 fMonitoringMutex->Lock();
2440 fMonitoringMutex->UnLock();
2445 //______________________________________________________________________________________________
2446 void AliShuttle::SetLastAction(const char* action)
2449 // updates the monitoring variables
2452 fMonitoringMutex->Lock();
2454 fLastAction = action;
2455 fLastActionTime = time(0);
2457 fMonitoringMutex->UnLock();
2460 //______________________________________________________________________________________________
2461 const char* AliShuttle::GetRunParameter(const char* param)
2464 // returns run parameter read from DAQ logbook
2467 if(!fLogbookEntry) {
2468 AliError("No logbook entry!");
2472 return fLogbookEntry->GetRunParameter(param);
2475 //______________________________________________________________________________________________
2476 AliCDBEntry* AliShuttle::GetFromOCDB(const char* detector, const AliCDBPath& path)
2479 // returns object from OCDB valid for current run
2482 if (fTestMode & kErrorOCDB)
2484 Log(detector, "GetFromOCDB - In TESTMODE - Simulating error with OCDB");
2488 AliCDBStorage *sto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
2491 Log(detector, "GetFromOCDB - Cannot activate main OCDB for query!");
2495 return dynamic_cast<AliCDBEntry*> (sto->Get(path, GetCurrentRun()));
2498 //______________________________________________________________________________________________
2499 Bool_t AliShuttle::SendMail()
2502 // sends a mail to the subdetector expert in case of preprocessor error
2505 if (fTestMode != kNone)
2508 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
2511 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE))
2513 AliError(Form("Can't open directory <%s>", GetShuttleLogDir()));
2518 gSystem->FreeDirectory(dir);
2521 TString bodyFileName;
2522 bodyFileName.Form("%s/mail.body", GetShuttleLogDir());
2523 gSystem->ExpandPathName(bodyFileName);
2526 mailBody.open(bodyFileName, ofstream::out);
2528 if (!mailBody.is_open())
2530 AliError(Form("Could not open mail body file %s", bodyFileName.Data()));
2535 TIter iterExperts(fConfig->GetResponsibles(fCurrentDetector));
2536 TObjString *anExpert=0;
2537 while ((anExpert = (TObjString*) iterExperts.Next()))
2539 to += Form("%s,", anExpert->GetName());
2541 to.Remove(to.Length()-1);
2542 AliDebug(2, Form("to: %s",to.Data()));
2545 AliInfo("List of detector responsibles not yet set!");
2549 TString cc="alberto.colla@cern.ch";
2551 TString subject = Form("%s Shuttle preprocessor FAILED in run %d !",
2552 fCurrentDetector.Data(), GetCurrentRun());
2553 AliDebug(2, Form("subject: %s", subject.Data()));
2555 TString body = Form("Dear %s expert(s), \n\n", fCurrentDetector.Data());
2556 body += Form("SHUTTLE just detected that your preprocessor "
2557 "failed processing run %d!!\n\n", GetCurrentRun());
2558 body += Form("Please check %s status on the SHUTTLE monitoring page: \n\n", fCurrentDetector.Data());
2559 body += Form("\thttp://pcalimonitor.cern.ch:8889/shuttle.jsp?time=168 \n\n");
2560 body += Form("Find the %s log for the current run on \n\n"
2561 "\thttp://pcalishuttle01.cern.ch:8880/logs/%s_%d.log \n\n",
2562 fCurrentDetector.Data(), fCurrentDetector.Data(), GetCurrentRun());
2563 body += Form("The last 10 lines of %s log file are following:\n\n");
2565 AliDebug(2, Form("Body begin: %s", body.Data()));
2567 mailBody << body.Data();
2569 mailBody.open(bodyFileName, ofstream::out | ofstream::app);
2571 TString logFileName = Form("%s/%s_%d.log", GetShuttleLogDir(), fCurrentDetector.Data(), GetCurrentRun());
2572 TString tailCommand = Form("tail -n 10 %s >> %s", logFileName.Data(), bodyFileName.Data());
2573 if (gSystem->Exec(tailCommand.Data()))
2575 mailBody << Form("%s log file not found ...\n\n", fCurrentDetector.Data());
2578 TString endBody = Form("------------------------------------------------------\n\n");
2579 endBody += Form("In case of problems please contact the SHUTTLE core team.\n\n");
2580 endBody += "Please do not answer this message directly, it is automatically generated.\n\n";
2581 endBody += "Greetings,\n\n \t\t\tthe SHUTTLE\n";
2583 AliDebug(2, Form("Body end: %s", endBody.Data()));
2585 mailBody << endBody.Data();
2590 TString mailCommand = Form("mail -s \"%s\" -c %s %s < %s",
2594 bodyFileName.Data());
2595 AliDebug(2, Form("mail command: %s", mailCommand.Data()));
2597 Bool_t result = gSystem->Exec(mailCommand.Data());
2602 //______________________________________________________________________________________________
2603 const char* AliShuttle::GetRunType()
2606 // returns run type read from "run type" logbook
2609 if(!fLogbookEntry) {
2610 AliError("No logbook entry!");
2614 return fLogbookEntry->GetRunType();
2617 //______________________________________________________________________________________________
2618 void AliShuttle::SetShuttleTempDir(const char* tmpDir)
2621 // sets Shuttle temp directory
2624 fgkShuttleTempDir = gSystem->ExpandPathName(tmpDir);
2627 //______________________________________________________________________________________________
2628 void AliShuttle::SetShuttleLogDir(const char* logDir)
2631 // sets Shuttle log directory
2634 fgkShuttleLogDir = gSystem->ExpandPathName(logDir);