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.8 2006/07/11 12:44:36 jgrosseo
19 adding parameters for extended validity range of data produced by preprocessor
21 Revision 1.7 2006/07/10 14:37:09 jgrosseo
22 small fix + todo comment
24 Revision 1.6 2006/07/10 13:01:41 jgrosseo
25 enhanced storing of last sucessfully processed run (alberto)
27 Revision 1.5 2006/07/04 14:59:57 jgrosseo
28 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
30 Revision 1.4 2006/06/12 09:11:16 jgrosseo
31 coding conventions (Alberto)
33 Revision 1.3 2006/06/06 14:26:40 jgrosseo
34 o) removed files that were moved to STEER
35 o) shuttle updated to follow the new interface (Alberto)
37 Revision 1.2 2006/03/07 07:52:34 hristov
38 New version (B.Yordanov)
40 Revision 1.6 2005/11/19 17:19:14 byordano
41 RetrieveDATEEntries and RetrieveConditionsData added
43 Revision 1.5 2005/11/19 11:09:27 byordano
44 AliShuttle declaration added
46 Revision 1.4 2005/11/17 17:47:34 byordano
47 TList changed to TObjArray
49 Revision 1.3 2005/11/17 14:43:23 byordano
52 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
53 Initial import as subdirectory in AliRoot
55 Revision 1.2 2005/09/13 08:41:15 byordano
56 default startTime endTime added
58 Revision 1.4 2005/08/30 09:13:02 byordano
61 Revision 1.3 2005/08/29 21:15:47 byordano
67 // This class is the main manager for AliShuttle.
68 // It organizes the data retrieval from DCS and call the
69 // interface methods of AliPreprocessor.
70 // For every detector in AliShuttleConfgi (see AliShuttleConfig),
71 // data for its set of aliases is retrieved. If there is registered
72 // AliPreprocessor for this detector then it will be used
73 // accroding to the schema (see AliPreprocessor).
74 // If there isn't registered AliPreprocessor than the retrieved
75 // data is stored automatically to the undelying AliCDBStorage.
76 // For detSpec is used the alias name.
79 #include "AliShuttle.h"
81 #include "AliCDBManager.h"
82 #include "AliCDBStorage.h"
84 #include "AliShuttleConfig.h"
85 #include "AliDCSClient.h"
87 #include "AliPreprocessor.h"
88 #include "AliDefaultPreprocessor.h"
93 #include <TTimeStamp.h>
94 #include <TObjString.h>
95 #include <TSQLServer.h>
96 #include <TSQLResult.h>
101 TString AliShuttle::fgkLocalUri("local://$ALICE_ROOT/SHUTTLE/ShuttleCDB");
102 const char* AliShuttle::fgkShuttleTempDir = "$ALICE_ROOT/SHUTTLE/temp";
104 const char* AliShuttle::fgkDetectorName[AliShuttle::fgkNDetectors] = {"SPD", "SDD", "SSD", "TPC", "TRD", "TOF",
105 "PHOS", "CPV", "RICH", "EMCAL", "MUON_TRK", "MUON_TRG", "FMD", "ZDC", "PMD", "START", "VZERO"};
107 const char* AliShuttle::fgkDetectorCode[AliShuttle::fgkNDetectors] = {"SPD", "SDD", "SSD", "TPC", "TRD", "TOF",
108 "PHS", "CPV", "HMP", "EMC", "MCH", "MTR", "FMD", "ZDC", "PMD", "T00", "V00"};
110 //______________________________________________________________________________________________
111 AliShuttle::AliShuttle(const AliShuttleConfig* config,
112 UInt_t timeout, Int_t retries):
115 fRetries(retries), fCurrentRun(-1), fCurrentStartTime(0),
120 // config: AliShuttleConfig used
121 // timeout: timeout used for AliDCSClient connection
122 // retries: the number of retries in case of connection error.
125 if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
126 for(int iSys=0;iSys<3;iSys++) {
128 fFESlist[iSys].SetOwner(kTRUE);
132 //______________________________________________________________________
133 AliShuttle::AliShuttle(const AliShuttle& /*other*/):
134 AliShuttleInterface()
136 // copy constructor (not implemented)
140 //______________________________________________________________________
141 AliShuttle &AliShuttle::operator=(const AliShuttle& /*other*/)
143 // assignment operator (not implemented)
148 //______________________________________________________________________________________________
149 AliShuttle::~AliShuttle()
153 fPreprocessorMap.DeleteAll();
154 for(int iSys=0;iSys<3;iSys++)
156 fServer[iSys]->Close();
157 delete fServer[iSys];
161 //______________________________________________________________________________________________
162 void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
165 // Registers new AliPreprocessor.
166 // It uses GetName() for indentificator of the pre processor.
167 // The pre processor is registered it there isn't any other
168 // with the same identificator (GetName()).
171 if (fPreprocessorMap.GetValue(preprocessor->GetName())) {
172 AliWarning(Form("AliPreprocessor %s is already registered!",
173 preprocessor->GetName()));
177 fPreprocessorMap.Add(new TObjString(preprocessor->GetName()), preprocessor);
180 //______________________________________________________________________________________________
181 UInt_t AliShuttle::Store(const char* detector,
182 TObject* object, AliCDBMetaData* metaData, Int_t /*validityStart*/, Bool_t /*validityInfinite*/)
184 // store data into CDB
186 // validityStart is the start validity of the data, if not 0 GetCurrentRun() - validityStart is taken
187 // validityInfinite defines if the data is valid until new data arrives (e.g. for calibration runs)
190 // 1 if stored in main (Grid) storage
191 // 2 if stored in backup (Local) storage
193 // TODO implement use of two parameters
195 // TODO shouldn't the path be given by the preprocessor???
196 AliCDBId id(AliCDBPath(detector, "DCS", "Data"),
197 GetCurrentRun(), GetCurrentRun());
200 if (!(AliCDBManager::Instance()->IsDefaultStorageSet())) {
201 Log(detector, "No CDB storage set!");
203 result = (UInt_t) AliCDBManager::Instance()->Put(object, id, metaData);
207 Log(detector, "Error while storing object in main storage!");
208 AliError("local storage will be used!");
210 AliCDBStorage *origStorage = AliCDBManager::Instance()->GetDefaultStorage();
212 result = AliCDBManager::Instance()->GetStorage(fgkLocalUri)
213 ->Put(object, id, metaData);
215 AliCDBManager::Instance()->SetDefaultStorage(origStorage);
220 Log(detector, "Can't store data!");
227 //______________________________________________________________________________________________
228 Bool_t AliShuttle::Process(Int_t run, UInt_t startTime, UInt_t endTime)
231 // Makes data retrieval for all detectors in the configuration.
232 // run: is the run number used
233 // startTime: is the run start time
234 // endTime: is the run end time
235 // Returns kFALSE in case of error occured and kTRUE otherwise
238 AliInfo(Form("\n\n ^*^*^*^*^*^* Processing run %d ^*^*^*^*^*^*", run));
242 Bool_t hasError = kFALSE;
243 for(Int_t iSys=0;iSys<3;iSys++) fFESCalled[iSys]=kFALSE;
245 fCurrentStartTime = startTime;
246 fCurrentEndTime = endTime;
248 // Loop on detectors in the configuration
249 TIter iter(fConfig->GetDetectors());
250 TObjString* aDetector;
252 while ((aDetector = (TObjString*) iter.Next())) {
253 Bool_t detectorError=kFALSE;
254 if(!fConfig->HostProcessDetector(aDetector->GetName())) continue;
255 if(!Process(run, startTime, endTime, aDetector->String())) {
260 AliInfo(Form("Process ended successfully for detector %s!",aDetector->GetName()));
262 // Process successful: Update time_processed field in FES logbooks!
263 if(fFESCalled[kDAQ]) {
264 hasError = (UpdateDAQTable(aDetector->GetName()) == kFALSE);
265 fFESlist[kDAQ].Clear();
267 //if(fFESCalled[kDCS]) {
268 // hasError = UpdateDCSTable(aDetector->GetName());
269 // fFESlist[kDCS].Clear();
271 //if(fFESCalled[kHLT]) {
272 // hasError = UpdateHLTTable(aDetector->GetName());
273 // fFESlist[kHLT].Clear();
277 if(fLog != "") StoreLog(run);
279 fCurrentStartTime = 0;
282 return hasError == kFALSE;
285 //______________________________________________________________________________________________
286 Bool_t AliShuttle::Process(Int_t run, UInt_t startTime, UInt_t endTime,
287 const char* detector)
290 // Makes data retrieval just for one specific detector.
291 // Threre should be a configuration for this detector.
292 // run: is the run number used
293 // startTime: is the run start time
294 // endTime: is the run end time
295 // detector: detector for which the retrieval will be made
296 // Returns kFALSE in case of error occured and kTRUE otherwise
299 AliInfo(Form("Retrieving values for %s, run %d", detector, run));
301 if (!fConfig->HasDetector(detector)) {
302 Log(detector, "There isn't any configuration for %s !");
306 TString host(fConfig->GetDCSHost(detector));
307 Int_t port = fConfig->GetDCSPort(detector);
309 TIter iter(fConfig->GetDCSAliases(detector));
313 Bool_t hasError = kFALSE;
314 Bool_t result=kFALSE;
316 while ((anAlias = (TObjString*) iter.Next())) {
318 result = GetValueSet(host, port, anAlias->String(), valueSet);
319 //AliInfo(Form("Port = %d",port));
322 aliasMap.Add(anAlias->Clone(), valueSet.Clone());
324 TString message = Form("Error while retrieving alias %s !",
326 Log(detector, message.Data());
331 // even if hasError is TRUE the Shuttle should keep on processing the detector (calib files!)
333 if(hasError) return kFALSE;
334 // TODO if(hasError) mark DCS error
336 AliPreprocessor* aPreprocessor =
337 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(detector));
340 aPreprocessor->Initialize(run, startTime, endTime);
341 hasError = (aPreprocessor->Process(&aliasMap) == 0);
343 // TODO default behaviour?
344 AliInfo(Form("No Preprocessor for %s: storing TMap of DP arrays into CDB!",detector));
345 AliCDBMetaData metaData;
346 AliDCSValue dcsValue(startTime, endTime);
347 metaData.SetResponsible(Form("Duck, Donald"));
348 metaData.SetProperty("StartEndTime", &dcsValue);
349 metaData.SetComment("Automatically stored by Shuttle!");
350 hasError = (Store(detector, &aliasMap, &metaData) == 0);
356 return hasError == kFALSE;
359 //______________________________________________________________________________________________
360 Bool_t AliShuttle::GetValueSet(const char* host, Int_t port, const char* alias,
363 // Retrieve all "alias" data points from the DCS server
364 // host, port: TSocket connection parameters
365 // alias: name of the alias
366 // valueSet: array of retrieved AliDCSValue's
368 AliDCSClient client(host, port, fTimeout, fRetries);
369 if (!client.IsConnected()) {
373 Int_t result = client.GetAliasValues(alias,
374 GetCurrentStartTime(), GetCurrentEndTime(), valueSet);
377 AliError(Form("Can't get '%s'! Reason: %s",
378 alias, AliDCSClient::GetErrorString(result)));
380 if (result == AliDCSClient::fgkServerError) {
381 AliError(Form("Server error: %s",
382 client.GetServerError().Data()));
391 //______________________________________________________________________________________________
392 const char* AliShuttle::GetFile(Int_t system, const char* detector,
393 const char* id, const char* source)
395 // Get calibration file from file exchange servers
396 // calls specific getter according to system index (kDAQ, kDCS, kHLT)
400 return GetDAQFileName(detector, id, source);
403 return GetDCSFileName(detector, id, source);
406 return GetHLTFileName(detector, id, source);
409 AliError(Form("No valid system index: %d",system));
415 //______________________________________________________________________________________________
416 TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
418 // Get sources producing the condition file Id from file exchange servers
419 // calls specific getter according to system index (kDAQ, kDCS, kHLT)
423 return GetDAQFileSources(detector, id);
426 return GetDCSFileSources(detector, id);
429 return GetHLTFileSources(detector, id);
432 AliError(Form("No valid system index: %d",system));
438 //______________________________________________________________________________________________
439 Bool_t AliShuttle::Connect(Int_t system){
440 // Connect to MySQL Server of the system's FES logbook
442 // check connection: if already connected return
443 if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
445 TString aFESlbHost= Form("mysql://%s", fConfig->GetFESlbHost(system));
447 fServer[system] = TSQLServer::Connect(aFESlbHost,
448 fConfig->GetFESlbUser(system),
449 fConfig->GetFESlbPass(system));
450 if (!fServer[system] || !fServer[system]->IsConnected()) {
451 AliError(Form("Can't establish connection to FES logbook for %s !",fkSystemNames[system]));
456 // TODO in the configuration should the table name be there too?
459 fServer[kDAQ]->GetTables("REFSYSLOG");
462 //fServer[kDCS]->GetTables("REFSYSLOG");
465 //fServer[kHLT]->GetTables("REFSYSLOG");
474 //______________________________________________________________________________________________
475 const char* AliShuttle::GetDAQFileName(const char* detector, const char* id, const char* source){
476 // Retrieves a file from the DAQ FES.
477 // First queris the DAQ logbook_fs for the DAQ file name, using the run, detector, id and source info
478 // then calls RetrieveDAQFile(DAQfilename) for actual copy to local disk
479 // run: current run being processed (fCurrentRun)
480 // detector: comes from the Preprocessor name (must be converted into detector code with GetDetCode)
481 // id: provided as a parameter by the Preprocessor
482 // source: provided by the Preprocessor through GetFileSources function
484 // check connection, in case connect
486 Log(detector, "GetDAQFileName: Couldn't connect to DAQ Logbook !");
491 TString sqlQueryStart = "select filePath from logbook_fs where";
492 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\"",
493 fCurrentRun, GetDetCode(detector), id, source);
494 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
496 AliInfo(Form("SQL query: \n%s",sqlQuery.Data()));
500 aResult = fServer[kDAQ]->Query(sqlQuery);
502 Log(detector, Form("Can't execute query <%s>!", sqlQuery.Data()));
506 if (aResult->GetRowCount() == 0) {
508 Form("GetDAQFileName: No result from SQL query <%s>!", sqlQuery.Data()));
513 if (aResult->GetRowCount() >1) {
515 Form("GetDAQFileName: More than one row resulting from SQL query <%s>!", sqlQuery.Data()));
520 TSQLRow* aRow = aResult->Next();
523 Log(detector, Form("GetDAQFileName: Empty set result from query <%s>!", sqlQuery.Data()));
528 TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
532 AliInfo(Form("filePath = %s",filePath.Data()));
534 // retrieved file is renamed to make it unique
535 TString localFileName = Form("%s_%d_%s_%s.shuttle",
536 detector, fCurrentRun, id, source);
538 // file retrieval from DAQ FES
539 Bool_t result = RetrieveDAQFile(filePath.Data(), localFileName.Data());
541 Log(detector, Form("copying file %s from DAQ FES failed!", filePath.Data()));
544 AliInfo(Form("File %s copied from DAQ FES into %s/%s !",
545 filePath.Data(), fgkShuttleTempDir, localFileName.Data()));
549 fFESCalled[kDAQ]=kTRUE;
550 TObjString *fileParams = new TObjString(Form("%s_!?!_%s", id, source));
551 fFESlist[kDAQ].Add(fileParams);
553 return localFileName.Data();
557 //______________________________________________________________________________________________
558 Bool_t AliShuttle::RetrieveDAQFile(const char* daqFileName, const char* localFileName){
560 // check temp directory: trying to cd to temp; if it does not exist, create it
561 AliInfo(Form("Copy file %s from DAQ FES into folder %s and rename it as %s",
562 daqFileName,fgkShuttleTempDir, localFileName));
564 void* dir = gSystem->OpenDirectory(fgkShuttleTempDir);
566 if (gSystem->mkdir(fgkShuttleTempDir, kTRUE)) {
567 AliError(Form("Can't open directory <%s>!", fgkShuttleTempDir));
572 gSystem->FreeDirectory(dir);
575 TString baseDAQFESFolder = "DAQ";
576 TString command = Form("scp %s@%s:%s/%s %s/%s",
577 fConfig->GetFESUser(kDAQ),
578 fConfig->GetFESHost(kDAQ),
579 baseDAQFESFolder.Data(),
584 AliInfo(Form("%s",command.Data()));
587 UInt_t maxRetries = 3;
589 // copy!! if successful TSystem::Exec returns 0
590 while(nRetries++ < maxRetries) {
591 AliInfo(Form("Trying to copy file. Retry # %d", nRetries));
592 if(gSystem->Exec(command.Data()) == 0) return kTRUE;
599 //______________________________________________________________________________________________
600 TList* AliShuttle::GetDAQFileSources(const char* detector, const char* id){
601 // Retrieves a file from the DCS FES.
603 // check connection, in case connect
605 Log(detector, "GetDAQFileName: Couldn't connect to DAQ Logbook !");
610 TString sqlQueryStart = "select DAQsource from logbook_fs where";
611 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
612 fCurrentRun, GetDetCode(detector), id);
613 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
615 AliInfo(Form("SQL query: \n%s",sqlQuery.Data()));
619 aResult = fServer[kDAQ]->Query(sqlQuery);
621 Log(detector, Form("GetDAQFileSources: Can't execute query <%s>!", sqlQuery.Data()));
625 if (aResult->GetRowCount() == 0) {
627 Form("GetDAQFileSources: No result from SQL query <%s>!", sqlQuery.Data()));
633 TList *list = new TList();
636 while((aRow = aResult->Next())){
638 TString daqSource(aRow->GetField(0), aRow->GetFieldLength(0));
639 AliInfo(Form("daqSource = %s", daqSource.Data()));
640 list->Add(new TObjString(daqSource));
648 //______________________________________________________________________________________________
649 Bool_t AliShuttle::UpdateDAQTable(const char* detector){
650 // Update DAQ table filling time_processed field in all rows corresponding to current run and detector
652 // check connection, in case connect
654 Log(detector, "UpdateDAQTable: Couldn't connect to DAQ Logbook !");
658 TTimeStamp now; // now
660 // Loop on FES list entries
661 TIter iter(&fFESlist[kDAQ]);
662 TObjString *aFESentry=0;
663 while((aFESentry = dynamic_cast<TObjString*> (iter.Next()))){
664 TString aFESentrystr = aFESentry->String();
665 TObjArray *aFESarray = aFESentrystr.Tokenize("_!?!_");
666 if(!aFESarray || aFESarray->GetEntries() != 2 ) {
667 Log(detector,Form("UpdateDAQTable: error updating FES entry! string = %s",
668 aFESentrystr.Data()));
669 if(aFESarray) delete aFESarray;
672 const char* fileId = ((TObjString*) aFESarray->At(0))->GetName();
673 const char* daqSource = ((TObjString*) aFESarray->At(1))->GetName();
674 TString whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\";",
675 fCurrentRun,GetDetCode(detector), fileId, daqSource);
679 TString sqlQuery = Form("update logbook_fs set time_processed=%d %s", now.GetSec(), whereClause.Data());
681 AliInfo(Form("SQL query: \n%s",sqlQuery.Data()));
685 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
687 Log(detector, Form("UpdateDAQTable: Can't execute query <%s>!", sqlQuery.Data()));
692 // check result - TODO Is it necessary?
693 sqlQuery = Form("select time_processed from logbook_fs %s", whereClause.Data());
694 AliInfo(Form(" CHECK - SQL query: \n%s",sqlQuery.Data()));
696 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
698 AliWarning("Can't check result!");
702 if (aResult->GetRowCount() == 0) {
704 Form("GetDAQFileName: No result from SQL query <%s>!", sqlQuery.Data()));
709 if (aResult->GetRowCount() >1) {
711 Form("GetDAQFileName: More than one row resulting from SQL query <%s>!", sqlQuery.Data()));
716 TSQLRow *row = dynamic_cast<TSQLRow*> (aResult->Next());
717 TString processedTimeString(row->GetField(0), row->GetFieldLength(0));
718 Int_t processedTime = processedTimeString.Atoi();
719 if(processedTime != now.GetSec()){
720 Log(detector, Form("UpdateDAQTable: Update table error: processed_time=%d, now=%d !",
721 processedTime, now.GetSec()));
733 //______________________________________________________________________________________________
734 const char* AliShuttle::GetDCSFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
735 // Retrieves a file from the DCS FES.
737 return "You're in DCS";
741 //______________________________________________________________________________________________
742 TList* AliShuttle::GetDCSFileSources(const char* /*detector*/, const char* /*id*/){
743 // Retrieves a file from the DCS FES.
749 //______________________________________________________________________________________________
750 const char* AliShuttle::GetHLTFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
751 // Retrieves a file from the HLT FES.
753 return "You're in HLT";
757 //______________________________________________________________________________________________
758 TList* AliShuttle::GetHLTFileSources(const char* /*detector*/, const char* /*id*/){
759 // Retrieves a file from the HLT FES.
765 //______________________________________________________________________________________________
766 const char* AliShuttle::GetDetCode(const char* detector){
767 // Return detector code
769 for(int iDet=0; iDet < fgkNDetectors; iDet++){
770 if(!strcmp(fgkDetectorName[iDet], detector)) return fgkDetectorCode[iDet];
776 //______________________________________________________________________________________________
777 void AliShuttle::Log(const char* detector, const char* message)
779 // Fill log string with a message
781 TString toLog = Form("%s - %s", detector, message);
782 AliError(toLog.Data());
789 //______________________________________________________________________________________________
790 void AliShuttle::StoreLog(Int_t run)
792 // store error log string to SHUTTLE/SYSTEM/ERROR (on local storage)
794 AliInfo("Printing fLog...");
795 AliInfo(fLog.Data());
796 // Storing log string for runs with errors in "SHUTTLE/SYSTEM/ERRORLOGS"
797 TObjString *logString = new TObjString(fLog);
798 AliCDBId badRunId("SHUTTLE/SYSTEM/ERRORLOGS",run,run);
799 AliCDBMetaData metaData;
800 AliCDBManager::Instance()->GetStorage(fgkLocalUri)
801 ->Put(logString, badRunId,&metaData);