]> git.uio.no Git - u/mrichter/AliRoot.git/blob - SHUTTLE/AliShuttle.cxx
Update to shuttle classes (Alberto)
[u/mrichter/AliRoot.git] / SHUTTLE / AliShuttle.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 /*
17 $Log$
18 Revision 1.11  2006/07/21 07:37:20  jgrosseo
19 last run is stored after each run
20
21 Revision 1.10  2006/07/20 09:54:40  jgrosseo
22 introducing status management: The processing per subdetector is divided into several steps,
23 after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
24 can keep track of the number of failures and skips further processing after a certain threshold is
25 exceeded. These thresholds can be configured in LDAP.
26
27 Revision 1.9  2006/07/19 10:09:55  jgrosseo
28 new configuration, accesst to DAQ FES (Alberto)
29
30 Revision 1.8  2006/07/11 12:44:36  jgrosseo
31 adding parameters for extended validity range of data produced by preprocessor
32
33 Revision 1.7  2006/07/10 14:37:09  jgrosseo
34 small fix + todo comment
35
36 Revision 1.6  2006/07/10 13:01:41  jgrosseo
37 enhanced storing of last sucessfully processed run (alberto)
38
39 Revision 1.5  2006/07/04 14:59:57  jgrosseo
40 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
41
42 Revision 1.4  2006/06/12 09:11:16  jgrosseo
43 coding conventions (Alberto)
44
45 Revision 1.3  2006/06/06 14:26:40  jgrosseo
46 o) removed files that were moved to STEER
47 o) shuttle updated to follow the new interface (Alberto)
48
49 Revision 1.2  2006/03/07 07:52:34  hristov
50 New version (B.Yordanov)
51
52 Revision 1.6  2005/11/19 17:19:14  byordano
53 RetrieveDATEEntries and RetrieveConditionsData added
54
55 Revision 1.5  2005/11/19 11:09:27  byordano
56 AliShuttle declaration added
57
58 Revision 1.4  2005/11/17 17:47:34  byordano
59 TList changed to TObjArray
60
61 Revision 1.3  2005/11/17 14:43:23  byordano
62 import to local CVS
63
64 Revision 1.1.1.1  2005/10/28 07:33:58  hristov
65 Initial import as subdirectory in AliRoot
66
67 Revision 1.2  2005/09/13 08:41:15  byordano
68 default startTime endTime added
69
70 Revision 1.4  2005/08/30 09:13:02  byordano
71 some docs added
72
73 Revision 1.3  2005/08/29 21:15:47  byordano
74 some docs added
75
76 */
77
78 //
79 // This class is the main manager for AliShuttle. 
80 // It organizes the data retrieval from DCS and call the 
81 // interface methods of AliPreprocessor.
82 // For every detector in AliShuttleConfgi (see AliShuttleConfig),
83 // data for its set of aliases is retrieved. If there is registered
84 // AliPreprocessor for this detector then it will be used
85 // accroding to the schema (see AliPreprocessor).
86 // If there isn't registered AliPreprocessor than the retrieved
87 // data is stored automatically to the undelying AliCDBStorage.
88 // For detSpec is used the alias name.
89 //
90
91 #include "AliShuttle.h"
92
93 #include "AliCDBManager.h"
94 #include "AliCDBStorage.h"
95 #include "AliCDBId.h"
96 #include "AliCDBRunRange.h"
97 #include "AliCDBPath.h"
98 #include "AliCDBEntry.h"
99 #include "AliShuttleConfig.h"
100 #include "AliDCSClient.h"
101 #include "AliLog.h"
102 #include "AliPreprocessor.h"
103 #include "AliShuttleStatus.h"
104
105 #include <TSystem.h>
106 #include <TObject.h>
107 #include <TString.h>
108 #include <TTimeStamp.h>
109 #include <TObjString.h>
110 #include <TSQLServer.h>
111 #include <TSQLResult.h>
112 #include <TSQLRow.h>
113
114 #include <fstream>
115
116 ClassImp(AliShuttle)
117
118 TString AliShuttle::fgkLocalCDB("local://LocalShuttleCDB");
119 TString AliShuttle::fgkMainRefStorage("alien://DBFolder=ShuttleReference");
120 TString AliShuttle::fgkLocalRefStorage("local://LocalReferenceStorage");
121
122 const char* AliShuttle::fgkShuttleTempDir = gSystem->ExpandPathName("$ALICE_ROOT/SHUTTLE/temp");
123 const char* AliShuttle::fgkShuttleLogDir = gSystem->ExpandPathName("$ALICE_ROOT/SHUTTLE/log");
124
125 const char* AliShuttle::fgkDetectorName[AliShuttle::fgkNDetectors] = {"SPD", "SDD", "SSD", "TPC", "TRD", "TOF",
126         "PHOS", "CPV", "RICH", "EMCAL", "MUON_TRK", "MUON_TRG", "FMD", "ZDC", "PMD", "START", "VZERO"};
127
128 const char* AliShuttle::fgkDetectorCode[AliShuttle::fgkNDetectors] = {"SPD", "SDD", "SSD", "TPC", "TRD", "TOF",
129         "PHS", "CPV", "HMP", "EMC", "MCH", "MTR", "FMD", "ZDC", "PMD", "T00", "V00"};
130
131 //______________________________________________________________________________________________
132 AliShuttle::AliShuttle(const AliShuttleConfig* config,
133                 UInt_t timeout, Int_t retries):
134         fConfig(config),
135         fTimeout(timeout),
136         fRetries(retries), fCurrentRun(-1), fCurrentStartTime(0),
137         fCurrentEndTime(0), fStatusEntry(0)
138 {
139         //
140         // config: AliShuttleConfig used
141         // timeout: timeout used for AliDCSClient connection
142         // retries: the number of retries in case of connection error.
143         //
144
145         if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
146         for(int iSys=0;iSys<3;iSys++) {
147                 fServer[iSys]=0;
148                 fFESlist[iSys].SetOwner(kTRUE);
149         }
150 }
151
152 //______________________________________________________________________
153 AliShuttle::AliShuttle(const AliShuttle& /*other*/):
154 AliShuttleInterface()
155 {
156 // copy constructor (not implemented)
157
158 }
159
160 //______________________________________________________________________
161 AliShuttle &AliShuttle::operator=(const AliShuttle& /*other*/)
162 {
163 // assignment operator (not implemented)
164
165 return *this;
166 }
167
168 //______________________________________________________________________________________________
169 AliShuttle::~AliShuttle()
170 {
171 // destructor
172
173         fPreprocessorMap.DeleteAll();
174         for(int iSys=0;iSys<3;iSys++)
175                 if(fServer[iSys]) {
176                         fServer[iSys]->Close();
177                         delete fServer[iSys];
178                 }
179 }
180
181 //______________________________________________________________________________________________
182 void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
183 {
184         //
185         // Registers new AliPreprocessor.
186         // It uses GetName() for indentificator of the pre processor.
187         // The pre processor is registered it there isn't any other
188         // with the same identificator (GetName()).
189         //
190
191         if (fPreprocessorMap.GetValue(preprocessor->GetName())) {
192                 AliWarning(Form("AliPreprocessor %s is already registered!",
193                         preprocessor->GetName()));
194                 return;
195         }
196
197         fPreprocessorMap.Add(new TObjString(preprocessor->GetName()), preprocessor);
198 }
199
200 //______________________________________________________________________________________________
201 UInt_t AliShuttle::Store(const AliCDBPath& path, TObject* object,
202                 AliCDBMetaData* metaData, Int_t validityStart, Bool_t validityInfinite)
203 {
204   // Stores a CDB object in the storage for offline reconstruction. Objects that are not needed for
205   // offline reconstruction, but should be stored anyway (e.g. for debugging) should NOT be stored
206   // using this function. Use StoreReferenceData instead!
207   //
208
209   // The parameters are
210   //   1) the object's path.
211   //   2) the object to be stored
212   //   3) the metaData to be associated with the object
213   //   4) the validity start run number w.r.t. the current run,
214   //      if the data is valid only for this run leave the default 0
215   //   5) specifies if the calibration data is valid for infinity (this means until updated),
216   //      typical for calibration runs, the default is kFALSE
217   //
218   //
219   // returns 0 if fail
220   //         1 if stored in main (Grid) CDB storage
221   //         2 if stored in backup (Local) CDB storage
222
223
224         Int_t firstRun = GetCurrentRun() - validityStart;
225         if(firstRun < 0) {
226                 AliError("First valid run happens to be less than 0! Setting it to 0...");
227                 firstRun=0;
228         }
229
230         Int_t lastRun = -1;
231         if(validityInfinite) {
232                 lastRun = AliCDBRunRange::Infinity();
233         } else {
234                 lastRun = GetCurrentRun();
235         }
236
237         AliCDBId id(path, firstRun, lastRun);
238
239         UInt_t result = 0;
240
241         if (!(AliCDBManager::Instance()->IsDefaultStorageSet())) {
242                 Log(fCurrentDetector, "No CDB storage set!");
243         } else {
244                 result = (UInt_t) AliCDBManager::Instance()->Put(object, id, metaData);
245         }
246         if(!result) {
247
248                 Log(fCurrentDetector,
249                         "Error while storing object in main storage: it will go to local storage!");
250
251                 result = AliCDBManager::Instance()->GetStorage(fgkLocalCDB)
252                                         ->Put(object, id, metaData);
253
254                 if(result) {
255                         result = 2;
256                 }else{
257                         Log(fCurrentDetector, "Can't store data!");
258                 }
259         }
260         return result;
261
262 }
263
264 //______________________________________________________________________________________________
265 UInt_t AliShuttle::StoreReferenceData(const AliCDBPath& path, TObject* object,
266                 AliCDBMetaData* metaData, Int_t validityStart, Bool_t validityInfinite)
267 {
268   // Stores a CDB object in the storage for reference data. This objects will not be available during
269   // offline reconstrunction. Use this function for reference data only!
270   //
271
272   // The parameters are
273   //   1) the object's path.
274   //   2) the object to be stored
275   //   3) the metaData to be associated with the object
276   //   4) the validity start run number w.r.t. the current run,
277   //      if the data is valid only for this run leave the default 0
278   //   5) specifies if the calibration data is valid for infinity (this means until updated),
279   //      typical for calibration runs, the default is kFALSE
280   //
281   //
282   // returns 0 if fail
283   //         1 if stored in main (Grid) reference storage
284   //         2 if stored in backup (Local) reference storage
285
286         Int_t firstRun = GetCurrentRun() - validityStart;
287         if(firstRun < 0) {
288                 AliError("First valid run happens to be less than 0! Setting it to 0...");
289                 firstRun=0;
290         }
291
292         Int_t lastRun = -1;
293         if(validityInfinite) {
294                 lastRun = AliCDBRunRange::Infinity();
295         } else {
296                 lastRun = GetCurrentRun();
297         }
298
299         AliCDBId id(path, firstRun, lastRun);
300
301         UInt_t result = 0;
302
303         if (!(AliCDBManager::Instance()->GetStorage(fgkMainRefStorage))) {
304                 Log(fCurrentDetector, "Cannot activate main reference storage!");
305         } else {
306                 result = (UInt_t) AliCDBManager::Instance()->GetStorage(fgkMainRefStorage)
307                                         ->Put(object, id, metaData);
308         }
309
310         if(!result) {
311
312                 Log(fCurrentDetector,
313                         "Error while storing object in main reference storage: it will go to local ref storage!");
314
315                 result = AliCDBManager::Instance()->GetStorage(fgkLocalRefStorage)
316                                         ->Put(object, id, metaData);
317
318                 if(result) {
319                         result = 2;
320                 }else{
321                         Log(fCurrentDetector, "Can't store reference data!");
322                 }
323         }
324         return result;
325
326 }
327
328 //______________________________________________________________________________________________
329 AliShuttleStatus* AliShuttle::ReadShuttleStatus()
330 {
331   // Reads the AliShuttleStatus from the CDB
332
333   if (fStatusEntry)
334   {
335     delete fStatusEntry;
336     fStatusEntry = 0;
337   }
338
339   fStatusEntry = AliCDBManager::Instance()->GetStorage(AliShuttle::GetLocalCDB())
340       ->Get(Form("/SHUTTLE/STATUS/%s", fCurrentDetector.Data()), fCurrentRun);
341
342   if (!fStatusEntry)
343     return 0;
344
345   TObject* anObject = fStatusEntry->GetObject();
346   if (anObject == NULL || anObject->IsA() != AliShuttleStatus::Class())
347   {
348     AliError("Invalid object stored to CDB!");
349     return 0;
350   }
351
352   AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (anObject);
353   return status;
354 }
355
356 //______________________________________________________________________________________________
357 Bool_t AliShuttle::WriteShuttleStatus(AliShuttleStatus* status)
358 {
359   // writes the status for one subdetector
360
361   if (fStatusEntry)
362   {
363     delete fStatusEntry;
364     fStatusEntry = 0;
365   }
366
367   AliCDBId id(AliCDBPath("SHUTTLE", "STATUS", fCurrentDetector), fCurrentRun, fCurrentRun);
368
369   fStatusEntry = new AliCDBEntry(status, id, new AliCDBMetaData);
370
371   UInt_t result = AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
372
373   if (!result)
374   {
375     AliError(Form("WriteShuttleStatus for %s, run %d failed", fCurrentDetector.Data(), fCurrentRun));
376     return kFALSE;
377   }
378
379   return kTRUE;
380 }
381
382 //______________________________________________________________________________________________
383 void AliShuttle::UpdateShuttleStatus(AliShuttleStatus::Status newStatus, Bool_t increaseCount)
384 {
385   // changes the AliShuttleStatus for the given detector and run to the given status
386
387   if (!fStatusEntry)
388   {
389     AliError("UNEXPECTED: fStatusEntry empty");
390     return;
391   }
392
393   TObject* anObject = fStatusEntry->GetObject();
394   AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (anObject);
395
396   if (!status)
397   {
398     AliError("UNEXPECTED: status could not be read from current CDB entry");
399     return;
400   }
401
402   Log("SHUTTLE", Form("%s: Changing state from %s to %s", fCurrentDetector.Data(),
403                                 status->GetStatusName(), status->GetStatusName(newStatus)));
404
405   status->SetStatus(newStatus);
406   if (increaseCount)
407     status->IncreaseCount();
408
409   AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
410 }
411
412 //______________________________________________________________________________________________
413 Bool_t AliShuttle::ContinueProcessing()
414 {
415   // this function reads the AliShuttleStatus information from CDB and
416   // checks if the processing should be continued
417   // if yes it returns kTRUE and updates the AliShuttleStatus with nextStatus
418
419   AliShuttleStatus* status = ReadShuttleStatus();
420   if (!status)
421   {
422     // first time
423
424     Log("SHUTTLE", Form("%s: Processing first time.", fCurrentDetector.Data()));
425     status = new AliShuttleStatus(AliShuttleStatus::kStarted);
426     return WriteShuttleStatus(status);
427   }
428
429   if (status->GetStatus() == AliShuttleStatus::kDone)
430   {
431     Log("SHUTTLE", Form("%s already done for run %d", fCurrentDetector.Data(), fCurrentRun));
432     return kFALSE;
433   }
434
435   if (status->GetStatus() == AliShuttleStatus::kFailed)
436   {
437     Log("SHUTTLE", Form("%s already in failed state for run %d", fCurrentDetector.Data(), fCurrentRun));
438     return kFALSE;
439   }
440
441   // if we get here, there is a restart
442
443   // abort conditions
444   if (status->GetStatus() == AliShuttleStatus::kPPStarted && status->GetCount() >= fConfig->GetMaxPPRetries() ||
445       status->GetCount() >= fConfig->GetMaxRetries())
446   {
447     Log("SHUTTLE", Form("%s, run %d failed too often, %d times, status %s. Skipping processing.",
448                 fCurrentDetector.Data(), fCurrentRun, status->GetCount(), status->GetStatusName()));
449
450     return kFALSE;
451   }
452
453   Log("SHUTTLE", Form("Restart of %s, run %d. Got stuck before in %s, count %d",
454                 fCurrentDetector.Data(), fCurrentRun, status->GetStatusName(), status->GetCount()));
455
456   UpdateShuttleStatus(AliShuttleStatus::kStarted, kTRUE);
457
458   return kTRUE;
459 }
460
461 //______________________________________________________________________________________________
462 Bool_t AliShuttle::Process(Int_t run, UInt_t startTime, UInt_t endTime)
463 {
464         //
465         // Makes data retrieval for all detectors in the configuration.
466         // run: is the run number used
467         // startTime: is the run start time
468         // endTime: is the run end time
469         // Returns kFALSE in case of error occured and kTRUE otherwise
470         //
471
472         AliInfo(Form("\n\n ^*^*^*^*^*^* Processing run %d ^*^*^*^*^*^*", run));
473
474         // Initialization
475         Bool_t hasError = kFALSE;
476         for(Int_t iSys=0;iSys<3;iSys++) fFESCalled[iSys]=kFALSE;
477
478         fCurrentRun = run;
479         fCurrentStartTime = startTime;
480         fCurrentEndTime = endTime;
481
482         // Loop on detectors in the configuration
483         TIter iter(fConfig->GetDetectors());
484         TObjString* aDetector;
485
486         while ((aDetector = (TObjString*) iter.Next())) {
487                 fCurrentDetector = aDetector->String();
488
489                 Bool_t detectorError=kFALSE;
490                 if (!fConfig->HostProcessDetector(fCurrentDetector)) continue;
491
492                 if (ContinueProcessing() == kFALSE) continue;
493
494                 if(!Process()) {
495                         hasError = kTRUE;
496                         detectorError=kTRUE;
497                         continue;
498                 }
499                 AliInfo(Form("Process ended successfully for detector %s!",aDetector->GetName()));
500
501                 // Process successful: Update time_processed field in FES logbooks!
502                 if(fFESCalled[kDAQ]) {
503                         hasError = (UpdateDAQTable() == kFALSE);
504                         fFESlist[kDAQ].Clear();
505                 }
506                 //if(fFESCalled[kDCS]) {
507                 //      hasError = UpdateDCSTable(aDetector->GetName());
508                 //      fFESlist[kDCS].Clear();
509                 //}
510                 //if(fFESCalled[kHLT]) {
511                 //      hasError = UpdateHLTTable(aDetector->GetName());
512                 //      fFESlist[kHLT].Clear();
513                 //}
514
515                 UpdateShuttleStatus(AliShuttleStatus::kDone);
516         }
517
518         fCurrentRun = -1;
519         fCurrentStartTime = 0;
520         fCurrentEndTime = 0;
521
522         return hasError == kFALSE;
523 }
524
525 //______________________________________________________________________________________________
526 Bool_t AliShuttle::Process()
527 {
528         //
529         // Makes data retrieval just for one specific detector.
530         // Threre should be a configuration for this detector.
531         // run: is the run number used
532         // startTime: is the run start time
533         // endTime: is the run end time
534         // detector: detector for which the retrieval will be made
535         // Returns kFALSE in case of error occured and kTRUE otherwise
536         //
537
538         AliInfo(Form("Retrieving values for %s, run %d", fCurrentDetector.Data(), fCurrentRun));
539
540         if (!fConfig->HasDetector(fCurrentDetector)) {
541                 Log(fCurrentDetector, "There isn't any configuration for %s !");
542                 UpdateShuttleStatus(AliShuttleStatus::kFailed);
543                 return kFALSE;
544         }
545
546         UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
547
548         TString host(fConfig->GetDCSHost(fCurrentDetector));
549         Int_t port = fConfig->GetDCSPort(fCurrentDetector);
550
551         TIter iter(fConfig->GetDCSAliases(fCurrentDetector));
552         TObjString* anAlias;
553         TMap aliasMap;
554
555         Bool_t hasError = kFALSE;
556         Bool_t result=kFALSE;
557
558         while ((anAlias = (TObjString*) iter.Next())) {
559                 TObjArray valueSet;
560                 //result = GetValueSet(host, port, anAlias->String(), valueSet);
561                 AliInfo(Form("Port = %d",port));
562                 result = kTRUE;
563                 if(result) {
564                         aliasMap.Add(anAlias->Clone(), valueSet.Clone());
565                 }else{
566                         TString message = Form("Error while retrieving alias %s !",
567                                         anAlias->GetName());
568                         Log(fCurrentDetector, message.Data());
569                         hasError = kTRUE;
570                         break;
571                 }
572         }
573
574         if (hasError)
575         {
576                 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
577                 return kFALSE;
578         }
579
580   UpdateShuttleStatus(AliShuttleStatus::kPPStarted);
581
582   AliPreprocessor* aPreprocessor =
583                 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
584         if(aPreprocessor)
585         {
586                 aPreprocessor->Initialize(fCurrentRun, fCurrentStartTime, fCurrentEndTime);
587                 hasError = (aPreprocessor->Process(&aliasMap) == 0);
588         }else{
589     // TODO default behaviour?
590                 AliInfo(Form("No Preprocessor for %s: storing TMap of DP arrays into CDB!", fCurrentDetector.Data()));
591                 AliCDBMetaData metaData;
592                 AliDCSValue dcsValue(fCurrentStartTime, fCurrentEndTime);
593                 metaData.SetResponsible(Form("Duck, Donald"));
594                 metaData.SetProperty("StartEndTime", &dcsValue);
595                 metaData.SetComment("Automatically stored by Shuttle!");
596                 AliCDBPath path(fCurrentDetector,"DCS","Data");
597                 hasError = (Store(path, &aliasMap, &metaData) == 0);
598         }
599
600   if (hasError)
601     UpdateShuttleStatus(AliShuttleStatus::kPPError);
602   else
603     UpdateShuttleStatus(AliShuttleStatus::kPPDone);
604
605         aliasMap.Delete();
606
607         return hasError == kFALSE;
608 }
609
610 //______________________________________________________________________________________________
611 Bool_t AliShuttle::GetValueSet(const char* host, Int_t port, const char* alias,
612                                 TObjArray& valueSet)
613 {
614 // Retrieve all "alias" data points from the DCS server
615 // host, port: TSocket connection parameters
616 // alias: name of the alias
617 // valueSet: array of retrieved AliDCSValue's 
618
619         AliDCSClient client(host, port, fTimeout, fRetries);
620         if (!client.IsConnected()) {
621                 return kFALSE;
622         }
623
624         Int_t result = client.GetAliasValues(alias,
625                 GetCurrentStartTime(), GetCurrentEndTime(), valueSet);
626
627         if (result < 0) {
628                 AliError(Form("Can't get '%s'! Reason: %s",
629                         alias, AliDCSClient::GetErrorString(result)));
630
631                 if (result == AliDCSClient::fgkServerError) {
632                         AliError(Form("Server error: %s",
633                                 client.GetServerError().Data()));
634                 }
635
636                 return kFALSE;
637         }
638
639         return kTRUE;
640 }
641
642 //______________________________________________________________________________________________
643 const char* AliShuttle::GetFile(Int_t system, const char* detector,
644                 const char* id, const char* source)
645 {
646 // Get calibration file from file exchange servers
647 // calls specific getter according to system index (kDAQ, kDCS, kHLT)
648
649         switch(system){
650                 case kDAQ:
651                         return GetDAQFileName(detector, id, source);
652                         break;
653                 case kDCS:
654                         return GetDCSFileName(detector, id, source);
655                         break;
656                 case kHLT:
657                         return GetHLTFileName(detector, id, source);
658                         break;
659                 default:
660                         AliError(Form("No valid system index: %d",system));
661         }
662
663         return 0;
664 }
665
666 //______________________________________________________________________________________________
667 TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
668 {
669 // Get sources producing the condition file Id from file exchange servers
670 // calls specific getter according to system index (kDAQ, kDCS, kHLT)
671
672         switch(system){
673                 case kDAQ:
674                         return GetDAQFileSources(detector, id);
675                         break;
676                 case kDCS:
677                         return GetDCSFileSources(detector, id);
678                         break;
679                 case kHLT:
680                         return GetHLTFileSources(detector, id);
681                         break;
682                 default:
683                         AliError(Form("No valid system index: %d",system));
684         }
685
686         return NULL;
687 }
688
689 //______________________________________________________________________________________________
690 Bool_t AliShuttle::Connect(Int_t system){
691 // Connect to MySQL Server of the system's FES logbook
692
693         // check connection: if already connected return
694         if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
695
696         TString aFESlbHost= Form("mysql://%s", fConfig->GetFESlbHost(system));
697
698         fServer[system] = TSQLServer::Connect(aFESlbHost,
699                         fConfig->GetFESlbUser(system),
700                         fConfig->GetFESlbPass(system));
701         if (!fServer[system] || !fServer[system]->IsConnected()) {
702                 AliError(Form("Can't establish connection to FES logbook for %s !",fkSystemNames[system]));
703                 return kFALSE;
704         }
705
706         // Get tables
707         // TODO in the configuration should the table name be there too?
708         switch(system){
709                 case kDAQ:
710                         fServer[kDAQ]->GetTables("REFSYSLOG");
711                         break;
712                 case kDCS:
713                         //fServer[kDCS]->GetTables("REFSYSLOG");
714                         break;
715                 case kHLT:
716                         //fServer[kHLT]->GetTables("REFSYSLOG");
717                         break;
718                 default:
719                         break;
720         }
721
722         return kTRUE;
723 }
724
725 //______________________________________________________________________________________________
726 const char* AliShuttle::GetDAQFileName(const char* detector, const char* id, const char* source){
727 // Retrieves a file from the DAQ FES.
728 // First queris the DAQ logbook_fs for the DAQ file name, using the run, detector, id and source info
729 // then calls RetrieveDAQFile(DAQfilename) for actual copy to local disk
730 // run: current run being processed (fCurrentRun)
731 // detector: comes from the Preprocessor name (must be converted into detector code with GetDetCode)
732 // id: provided as a parameter by the Preprocessor
733 // source: provided by the Preprocessor through GetFileSources function
734
735         // check connection, in case connect
736         if(!Connect(kDAQ)){
737                 Log(detector, "GetDAQFileName: Couldn't connect to DAQ Logbook !");
738                 return 0;
739         }
740
741         // Query preparation
742         TString sqlQueryStart = "select filePath from logbook_fs where";
743         TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\"",
744                                 fCurrentRun, GetDetCode(detector), id, source);
745         TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
746
747         AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
748
749         // Query execution
750         TSQLResult* aResult;
751         aResult = fServer[kDAQ]->Query(sqlQuery);
752         if (!aResult) {
753                 Log(detector, Form("Can't execute query <%s>!", sqlQuery.Data()));
754                 return 0;
755         }
756
757         if (aResult->GetRowCount() == 0) {
758                 Log(detector,
759                         Form("GetDAQFileName: No result from SQL query <%s>!", sqlQuery.Data()));
760                 delete aResult;
761                 return 0;
762         }
763
764         if (aResult->GetRowCount() >1) {
765                 Log(detector,
766                         Form("GetDAQFileName: More than one row resulting from SQL query <%s>!", sqlQuery.Data()));
767                 delete aResult;
768                 return 0;
769         }
770
771         TSQLRow* aRow = aResult->Next();
772
773         if(!aRow){
774                 Log(detector, Form("GetDAQFileName: Empty set result from query <%s>!", sqlQuery.Data()));
775                 delete aResult;
776                 return 0;
777         }
778
779         TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
780
781         delete aResult;
782
783         AliDebug(2, Form("filePath = %s",filePath.Data()));
784
785         // retrieved file is renamed to make it unique
786         TString localFileName = Form("%s_%d_%s_%s.shuttle",
787                                         detector, fCurrentRun, id, source);
788
789         // file retrieval from DAQ FES
790         Bool_t result = RetrieveDAQFile(filePath.Data(), localFileName.Data());
791         if(!result) {
792                 Log(detector, Form("copying file %s from DAQ FES failed!", filePath.Data()));
793                 return 0;
794         } else {
795                 AliInfo(Form("File %s copied from DAQ FES into %s/%s !",
796                         filePath.Data(), fgkShuttleTempDir, localFileName.Data()));
797         }
798
799
800         fFESCalled[kDAQ]=kTRUE;
801         TObjString *fileParams = new TObjString(Form("%s_!?!_%s", id, source));
802         fFESlist[kDAQ].Add(fileParams);
803
804         return localFileName.Data();
805
806 }
807
808 //______________________________________________________________________________________________
809 Bool_t AliShuttle::RetrieveDAQFile(const char* daqFileName, const char* localFileName){
810
811         // check temp directory: trying to cd to temp; if it does not exist, create it
812         AliDebug(2, Form("Copy file %s from DAQ FES into folder %s and rename it as %s",
813                         daqFileName,fgkShuttleTempDir, localFileName));
814
815         void* dir = gSystem->OpenDirectory(fgkShuttleTempDir);
816         if (dir == NULL) {
817                 if (gSystem->mkdir(fgkShuttleTempDir, kTRUE)) {
818                         AliError(Form("Can't open directory <%s>!", fgkShuttleTempDir));
819                         return kFALSE;
820                 }
821
822         } else {
823                 gSystem->FreeDirectory(dir);
824         }
825
826         TString baseDAQFESFolder = "DAQ";
827         TString command = Form("scp %s@%s:%s/%s %s/%s",
828                 fConfig->GetFESUser(kDAQ),
829                 fConfig->GetFESHost(kDAQ),
830                 baseDAQFESFolder.Data(),
831                 daqFileName,
832                 fgkShuttleTempDir,
833                 localFileName);
834
835         AliDebug(2, Form("%s",command.Data()));
836
837         UInt_t nRetries = 0;
838         UInt_t maxRetries = 3;
839
840         // copy!! if successful TSystem::Exec returns 0
841         while(nRetries++ < maxRetries) {
842                 AliDebug(2, Form("Trying to copy file. Retry # %d", nRetries));
843                 if(gSystem->Exec(command.Data()) == 0) return kTRUE;
844         }
845
846         return kFALSE;
847
848 }
849
850 //______________________________________________________________________________________________
851 TList* AliShuttle::GetDAQFileSources(const char* detector, const char* id){
852 // Retrieves a file from the DCS FES.
853
854         // check connection, in case connect
855         if(!Connect(kDAQ)){
856                 Log(detector, "GetDAQFileName: Couldn't connect to DAQ Logbook !");
857                 return 0;
858         }
859
860         // Query preparation
861         TString sqlQueryStart = "select DAQsource from logbook_fs where";
862         TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
863                                 fCurrentRun, GetDetCode(detector), id);
864         TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
865
866         AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
867
868         // Query execution
869         TSQLResult* aResult;
870         aResult = fServer[kDAQ]->Query(sqlQuery);
871         if (!aResult) {
872                 Log(detector, Form("GetDAQFileSources: Can't execute query <%s>!", sqlQuery.Data()));
873                 return 0;
874         }
875
876         if (aResult->GetRowCount() == 0) {
877                 Log(detector,
878                         Form("GetDAQFileSources: No result from SQL query <%s>!", sqlQuery.Data()));
879                 delete aResult;
880                 return 0;
881         }
882
883         TSQLRow* aRow;
884         TList *list = new TList();
885         list->SetOwner(1);
886
887         while((aRow = aResult->Next())){
888
889                 TString daqSource(aRow->GetField(0), aRow->GetFieldLength(0));
890                 AliDebug(2, Form("daqSource = %s", daqSource.Data()));
891                 list->Add(new TObjString(daqSource));
892         }
893         delete aResult;
894
895         return list;
896
897 }
898
899 //______________________________________________________________________________________________
900 Bool_t AliShuttle::UpdateDAQTable(){
901 // Update DAQ table filling time_processed field in all rows corresponding to current run and detector
902
903         // check connection, in case connect
904         if(!Connect(kDAQ)){
905                 Log(fCurrentDetector, "UpdateDAQTable: Couldn't connect to DAQ Logbook !");
906                 return kFALSE;
907         }
908
909         TTimeStamp now; // now
910
911         // Loop on FES list entries
912         TIter iter(&fFESlist[kDAQ]);
913         TObjString *aFESentry=0;
914         while((aFESentry = dynamic_cast<TObjString*> (iter.Next()))){
915                 TString aFESentrystr = aFESentry->String();
916                 TObjArray *aFESarray = aFESentrystr.Tokenize("_!?!_");
917                 if(!aFESarray || aFESarray->GetEntries() != 2 ) {
918                         Log(fCurrentDetector,Form("UpdateDAQTable: error updating FES entry! string = %s",
919                                 aFESentrystr.Data()));
920                         if(aFESarray) delete aFESarray;
921                         return kFALSE;
922                 }
923                 const char* fileId = ((TObjString*) aFESarray->At(0))->GetName();
924                 const char* daqSource = ((TObjString*) aFESarray->At(1))->GetName();
925                 TString whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\";",
926                         fCurrentRun,GetDetCode(fCurrentDetector), fileId, daqSource);
927
928                 delete aFESarray;
929
930                 TString sqlQuery = Form("update logbook_fs set time_processed=%d %s", now.GetSec(), whereClause.Data());
931
932                 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
933
934                 // Query execution
935                 TSQLResult* aResult;
936                 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
937                 if (!aResult) {
938                         Log(fCurrentDetector, Form("UpdateDAQTable: Can't execute query <%s>!", sqlQuery.Data()));
939                         return kFALSE;
940                 }
941                 delete aResult;
942
943                 // check result - TODO Is it necessary?
944                 sqlQuery = Form("select time_processed from logbook_fs %s", whereClause.Data());
945                 AliDebug(2, Form(" CHECK - SQL query: \n%s",sqlQuery.Data()));
946
947                 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
948                 if (!aResult) {
949                         AliWarning("Can't check result!");
950                         continue;
951                 }
952
953         if (aResult->GetRowCount() == 0) {
954                 Log(fCurrentDetector,
955                         Form("GetDAQFileName: No result from SQL query <%s>!", sqlQuery.Data()));
956                 delete aResult;
957                 //return 0;
958         }
959
960         if (aResult->GetRowCount() >1) {
961                 Log(fCurrentDetector,
962                         Form("GetDAQFileName: More than one row resulting from SQL query <%s>!", sqlQuery.Data()));
963                 delete aResult;
964                 //return 0;
965         }
966
967                 TSQLRow *row = dynamic_cast<TSQLRow*> (aResult->Next());
968                 TString processedTimeString(row->GetField(0), row->GetFieldLength(0));
969                 Int_t processedTime = processedTimeString.Atoi();
970                 if(processedTime != now.GetSec()){
971                         Log(fCurrentDetector, Form("UpdateDAQTable: Update table error: processed_time=%d, now=%d !",
972                                 processedTime, now.GetSec()));
973                         delete aResult;
974                         return kFALSE;
975                 }
976
977                 delete aResult;
978
979         }
980
981         return kTRUE;
982 }
983
984 //______________________________________________________________________________________________
985 const char* AliShuttle::GetDCSFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
986 // Retrieves a file from the DCS FES.
987
988 return "You're in DCS";
989
990 }
991
992 //______________________________________________________________________________________________
993 TList* AliShuttle::GetDCSFileSources(const char* /*detector*/, const char* /*id*/){
994 // Retrieves a file from the DCS FES.
995
996 return NULL;
997
998 }
999
1000 //______________________________________________________________________________________________
1001 const char* AliShuttle::GetHLTFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
1002 // Retrieves a file from the HLT FES.
1003
1004 return "You're in HLT";
1005
1006 }
1007
1008 //______________________________________________________________________________________________
1009 TList* AliShuttle::GetHLTFileSources(const char* /*detector*/, const char* /*id*/){
1010 // Retrieves a file from the HLT FES.
1011
1012 return NULL;
1013
1014 }
1015
1016 //______________________________________________________________________________________________
1017 const char* AliShuttle::GetDetCode(const char* detector){
1018 // Return detector code
1019
1020         for(int iDet=0; iDet < fgkNDetectors; iDet++){
1021                 if(!strcmp(fgkDetectorName[iDet], detector)) return fgkDetectorCode[iDet];
1022         }
1023
1024         return 0;
1025 }
1026
1027 //______________________________________________________________________________________________
1028 void AliShuttle::Log(const char* detector, const char* message)
1029 {
1030 // Fill log string with a message
1031
1032         void* dir = gSystem->OpenDirectory(fgkShuttleLogDir);
1033         if (dir == NULL) {
1034                 if (gSystem->mkdir(fgkShuttleLogDir, kTRUE)) {
1035                         AliError(Form("Can't open directory <%s>!", fgkShuttleTempDir));
1036                         return;
1037                 }
1038
1039         } else {
1040                 gSystem->FreeDirectory(dir);
1041         }
1042
1043         TString toLog = Form("%s: %s, run %d - %s", TTimeStamp(time(0)).AsString(),
1044         detector, GetCurrentRun(), message);
1045         AliInfo(toLog.Data());
1046
1047         TString fileName;
1048         fileName.Form("%s/%s.log", fgkShuttleLogDir, detector);
1049         gSystem->ExpandPathName(fileName);
1050
1051         ofstream logFile;
1052         logFile.open(fileName, ofstream::out | ofstream::app);
1053
1054         if (!logFile.is_open()) {
1055                 AliError(Form("Could not open file %s", fileName.Data()));
1056                 return;
1057         }
1058
1059         logFile << toLog.Data() << "\n";
1060
1061         logFile.close();
1062 }