]> git.uio.no Git - u/mrichter/AliRoot.git/blob - SHUTTLE/AliShuttle.cxx
new configuration, accesst to DAQ FES (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.8  2006/07/11 12:44:36  jgrosseo
19 adding parameters for extended validity range of data produced by preprocessor
20
21 Revision 1.7  2006/07/10 14:37:09  jgrosseo
22 small fix + todo comment
23
24 Revision 1.6  2006/07/10 13:01:41  jgrosseo
25 enhanced storing of last sucessfully processed run (alberto)
26
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
29
30 Revision 1.4  2006/06/12 09:11:16  jgrosseo
31 coding conventions (Alberto)
32
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)
36
37 Revision 1.2  2006/03/07 07:52:34  hristov
38 New version (B.Yordanov)
39
40 Revision 1.6  2005/11/19 17:19:14  byordano
41 RetrieveDATEEntries and RetrieveConditionsData added
42
43 Revision 1.5  2005/11/19 11:09:27  byordano
44 AliShuttle declaration added
45
46 Revision 1.4  2005/11/17 17:47:34  byordano
47 TList changed to TObjArray
48
49 Revision 1.3  2005/11/17 14:43:23  byordano
50 import to local CVS
51
52 Revision 1.1.1.1  2005/10/28 07:33:58  hristov
53 Initial import as subdirectory in AliRoot
54
55 Revision 1.2  2005/09/13 08:41:15  byordano
56 default startTime endTime added
57
58 Revision 1.4  2005/08/30 09:13:02  byordano
59 some docs added
60
61 Revision 1.3  2005/08/29 21:15:47  byordano
62 some docs added
63
64 */
65
66 //
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.
77 //
78
79 #include "AliShuttle.h"
80
81 #include "AliCDBManager.h"
82 #include "AliCDBStorage.h"
83 #include "AliCDBId.h"
84 #include "AliShuttleConfig.h"
85 #include "AliDCSClient.h"
86 #include "AliLog.h"
87 #include "AliPreprocessor.h"
88 #include "AliDefaultPreprocessor.h"
89
90 #include <TSystem.h>
91 #include <TObject.h>
92 #include <TString.h>
93 #include <TTimeStamp.h>
94 #include <TObjString.h>
95 #include <TSQLServer.h>
96 #include <TSQLResult.h>
97 #include <TSQLRow.h>
98
99 ClassImp(AliShuttle)
100
101 TString AliShuttle::fgkLocalUri("local://$ALICE_ROOT/SHUTTLE/ShuttleCDB");
102 const char* AliShuttle::fgkShuttleTempDir = "$ALICE_ROOT/SHUTTLE/temp";
103
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"};
106
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"};
109
110 //______________________________________________________________________________________________
111 AliShuttle::AliShuttle(const AliShuttleConfig* config,
112                 UInt_t timeout, Int_t retries):
113         fConfig(config),
114         fTimeout(timeout),
115         fRetries(retries), fCurrentRun(-1), fCurrentStartTime(0),
116         fCurrentEndTime(0),
117         fLog("")
118 {
119         //
120         // config: AliShuttleConfig used
121         // timeout: timeout used for AliDCSClient connection
122         // retries: the number of retries in case of connection error.
123         //
124
125         if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
126         for(int iSys=0;iSys<3;iSys++) {
127                 fServer[iSys]=0;
128                 fFESlist[iSys].SetOwner(kTRUE);
129         }
130 }
131
132 //______________________________________________________________________
133 AliShuttle::AliShuttle(const AliShuttle& /*other*/):
134 AliShuttleInterface()
135 {
136 // copy constructor (not implemented)
137
138 }
139
140 //______________________________________________________________________
141 AliShuttle &AliShuttle::operator=(const AliShuttle& /*other*/)
142 {
143 // assignment operator (not implemented)
144
145 return *this;
146 }
147
148 //______________________________________________________________________________________________
149 AliShuttle::~AliShuttle()
150 {
151 // destructor
152
153         fPreprocessorMap.DeleteAll();
154         for(int iSys=0;iSys<3;iSys++)
155                 if(fServer[iSys]) {
156                         fServer[iSys]->Close();
157                         delete fServer[iSys];
158                 }
159 }
160
161 //______________________________________________________________________________________________
162 void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
163 {
164         //
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()).
169         //
170
171         if (fPreprocessorMap.GetValue(preprocessor->GetName())) {
172                 AliWarning(Form("AliPreprocessor %s is already registered!",
173                         preprocessor->GetName()));
174                 return;
175         }
176
177         fPreprocessorMap.Add(new TObjString(preprocessor->GetName()), preprocessor);
178 }
179
180 //______________________________________________________________________________________________
181 UInt_t AliShuttle::Store(const char* detector,
182                 TObject* object, AliCDBMetaData* metaData, Int_t /*validityStart*/, Bool_t /*validityInfinite*/)
183 {
184         // store data into CDB
185   //
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)
188   //
189         // returns 0 if fail
190         //         1 if stored in main (Grid) storage
191         //         2 if stored in backup (Local) storage
192
193   // TODO implement use of two parameters
194
195   // TODO shouldn't the path be given by the preprocessor???
196         AliCDBId id(AliCDBPath(detector, "DCS", "Data"),
197                 GetCurrentRun(), GetCurrentRun());
198
199         UInt_t result = 0;
200         if (!(AliCDBManager::Instance()->IsDefaultStorageSet())) {
201                 Log(detector, "No CDB storage set!");
202         } else {
203                 result = (UInt_t) AliCDBManager::Instance()->Put(object, id, metaData);
204         }
205         if(!result) {
206
207                 Log(detector, "Error while storing object in main storage!");
208                 AliError("local storage will be used!");
209
210                 AliCDBStorage *origStorage = AliCDBManager::Instance()->GetDefaultStorage();
211
212                 result = AliCDBManager::Instance()->GetStorage(fgkLocalUri)
213                                         ->Put(object, id, metaData);
214
215                 AliCDBManager::Instance()->SetDefaultStorage(origStorage);
216
217                 if(result) {
218                         result = 2;
219                 }else{
220                         Log(detector, "Can't store data!");
221                 }
222         }
223         return result;
224
225 }
226
227 //______________________________________________________________________________________________
228 Bool_t AliShuttle::Process(Int_t run, UInt_t startTime, UInt_t endTime) 
229 {
230         //
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
236         //
237
238         AliInfo(Form("\n\n ^*^*^*^*^*^* Processing run %d ^*^*^*^*^*^*", run));
239
240         // Initialization
241         ClearLog();
242         Bool_t hasError = kFALSE;
243         for(Int_t iSys=0;iSys<3;iSys++) fFESCalled[iSys]=kFALSE;
244         fCurrentRun = run;
245         fCurrentStartTime = startTime;
246         fCurrentEndTime = endTime;
247
248         // Loop on detectors in the configuration
249         TIter iter(fConfig->GetDetectors());
250         TObjString* aDetector;
251
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())) {
256                         hasError = kTRUE;
257                         detectorError=kTRUE;
258                         continue;
259                 }
260                 AliInfo(Form("Process ended successfully for detector %s!",aDetector->GetName()));
261
262                 // Process successful: Update time_processed field in FES logbooks!
263                 if(fFESCalled[kDAQ]) {
264                         hasError = (UpdateDAQTable(aDetector->GetName()) == kFALSE);
265                         fFESlist[kDAQ].Clear();
266                 }
267                 //if(fFESCalled[kDCS]) {
268                 //      hasError = UpdateDCSTable(aDetector->GetName());
269                 //      fFESlist[kDCS].Clear();
270                 //}
271                 //if(fFESCalled[kHLT]) {
272                 //      hasError = UpdateHLTTable(aDetector->GetName());
273                 //      fFESlist[kHLT].Clear();
274                 //}
275         }
276
277         if(fLog != "") StoreLog(run);
278         fCurrentRun = -1;
279         fCurrentStartTime = 0;
280         fCurrentEndTime = 0;
281
282         return hasError == kFALSE;
283 }
284
285 //______________________________________________________________________________________________
286 Bool_t AliShuttle::Process(Int_t run, UInt_t startTime, UInt_t endTime,
287                 const char* detector)
288 {
289         //
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
297         //
298
299         AliInfo(Form("Retrieving values for %s, run %d", detector, run));
300
301         if (!fConfig->HasDetector(detector)) {
302                 Log(detector, "There isn't any configuration for %s !");
303                 return kFALSE;
304         }
305
306         TString host(fConfig->GetDCSHost(detector));
307         Int_t port = fConfig->GetDCSPort(detector);
308
309         TIter iter(fConfig->GetDCSAliases(detector));
310         TObjString* anAlias;
311         TMap aliasMap;
312
313         Bool_t hasError = kFALSE;
314         Bool_t result=kFALSE;
315
316         while ((anAlias = (TObjString*) iter.Next())) {
317                 TObjArray valueSet;
318                 result = GetValueSet(host, port, anAlias->String(), valueSet);
319                 //AliInfo(Form("Port = %d",port));
320                 //result = kTRUE;
321                 if(result) {
322                         aliasMap.Add(anAlias->Clone(), valueSet.Clone());
323                 }else{
324                         TString message = Form("Error while retrieving alias %s !",
325                                         anAlias->GetName());
326                         Log(detector, message.Data());
327                         hasError = kTRUE;
328                 }
329         }
330
331         // even if hasError is TRUE the Shuttle should keep on processing the detector (calib files!)
332
333         if(hasError) return kFALSE;
334         // TODO if(hasError) mark DCS error
335
336         AliPreprocessor* aPreprocessor =
337                 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(detector));
338         if(aPreprocessor)
339         {
340                 aPreprocessor->Initialize(run, startTime, endTime);
341                 hasError = (aPreprocessor->Process(&aliasMap) == 0);
342         }else{
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);
351         }
352
353
354         aliasMap.Delete();
355
356         return hasError == kFALSE;
357 }
358
359 //______________________________________________________________________________________________
360 Bool_t AliShuttle::GetValueSet(const char* host, Int_t port, const char* alias,
361                                 TObjArray& valueSet)
362 {
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 
367
368         AliDCSClient client(host, port, fTimeout, fRetries);
369         if (!client.IsConnected()) {
370                 return kFALSE;
371         }
372
373         Int_t result = client.GetAliasValues(alias,
374                 GetCurrentStartTime(), GetCurrentEndTime(), valueSet);
375
376         if (result < 0) {
377                 AliError(Form("Can't get '%s'! Reason: %s",
378                         alias, AliDCSClient::GetErrorString(result)));
379
380                 if (result == AliDCSClient::fgkServerError) {
381                         AliError(Form("Server error: %s",
382                                 client.GetServerError().Data()));
383                 }
384
385                 return kFALSE;
386         }
387
388         return kTRUE;
389 }
390
391 //______________________________________________________________________________________________
392 const char* AliShuttle::GetFile(Int_t system, const char* detector,
393                 const char* id, const char* source)
394 {
395 // Get calibration file from file exchange servers
396 // calls specific getter according to system index (kDAQ, kDCS, kHLT)
397
398         switch(system){
399                 case kDAQ:
400                         return GetDAQFileName(detector, id, source);
401                         break;
402                 case kDCS:
403                         return GetDCSFileName(detector, id, source);
404                         break;
405                 case kHLT:
406                         return GetHLTFileName(detector, id, source);
407                         break;
408                 default:
409                         AliError(Form("No valid system index: %d",system));
410         }
411
412         return 0;
413 }
414
415 //______________________________________________________________________________________________
416 TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
417 {
418 // Get sources producing the condition file Id from file exchange servers
419 // calls specific getter according to system index (kDAQ, kDCS, kHLT)
420
421         switch(system){
422                 case kDAQ:
423                         return GetDAQFileSources(detector, id);
424                         break;
425                 case kDCS:
426                         return GetDCSFileSources(detector, id);
427                         break;
428                 case kHLT:
429                         return GetHLTFileSources(detector, id);
430                         break;
431                 default:
432                         AliError(Form("No valid system index: %d",system));
433         }
434
435         return NULL;
436 }
437
438 //______________________________________________________________________________________________
439 Bool_t AliShuttle::Connect(Int_t system){
440 // Connect to MySQL Server of the system's FES logbook
441
442         // check connection: if already connected return
443         if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
444
445         TString aFESlbHost= Form("mysql://%s", fConfig->GetFESlbHost(system));
446
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]));
452                 return kFALSE;
453         }
454
455         // Get tables
456         // TODO in the configuration should the table name be there too?
457         switch(system){
458                 case kDAQ:
459                         fServer[kDAQ]->GetTables("REFSYSLOG");
460                         break;
461                 case kDCS:
462                         //fServer[kDCS]->GetTables("REFSYSLOG");
463                         break;
464                 case kHLT:
465                         //fServer[kHLT]->GetTables("REFSYSLOG");
466                         break;
467                 default:
468                         break;
469         }
470
471         return kTRUE;
472 }
473
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
483
484         // check connection, in case connect
485         if(!Connect(kDAQ)){
486                 Log(detector, "GetDAQFileName: Couldn't connect to DAQ Logbook !");
487                 return 0;
488         }
489
490         // Query preparation
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());
495
496         AliInfo(Form("SQL query: \n%s",sqlQuery.Data()));
497
498         // Query execution
499         TSQLResult* aResult;
500         aResult = fServer[kDAQ]->Query(sqlQuery);
501         if (!aResult) {
502                 Log(detector, Form("Can't execute query <%s>!", sqlQuery.Data()));
503                 return 0;
504         }
505
506         if (aResult->GetRowCount() == 0) {
507                 Log(detector,
508                         Form("GetDAQFileName: No result from SQL query <%s>!", sqlQuery.Data()));
509                 delete aResult;
510                 return 0;
511         }
512
513         if (aResult->GetRowCount() >1) {
514                 Log(detector,
515                         Form("GetDAQFileName: More than one row resulting from SQL query <%s>!", sqlQuery.Data()));
516                 delete aResult;
517                 return 0;
518         }
519
520         TSQLRow* aRow = aResult->Next();
521
522         if(!aRow){
523                 Log(detector, Form("GetDAQFileName: Empty set result from query <%s>!", sqlQuery.Data()));
524                 delete aResult;
525                 return 0;
526         }
527
528         TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
529
530         delete aResult;
531
532         AliInfo(Form("filePath = %s",filePath.Data()));
533
534         // retrieved file is renamed to make it unique
535         TString localFileName = Form("%s_%d_%s_%s.shuttle",
536                                         detector, fCurrentRun, id, source);
537
538         // file retrieval from DAQ FES
539         Bool_t result = RetrieveDAQFile(filePath.Data(), localFileName.Data());
540         if(!result) {
541                 Log(detector, Form("copying file %s from DAQ FES failed!", filePath.Data()));
542                 return 0;
543         } else {
544                 AliInfo(Form("File %s copied from DAQ FES into %s/%s !",
545                         filePath.Data(), fgkShuttleTempDir, localFileName.Data()));
546         }
547
548
549         fFESCalled[kDAQ]=kTRUE;
550         TObjString *fileParams = new TObjString(Form("%s_!?!_%s", id, source));
551         fFESlist[kDAQ].Add(fileParams);
552
553         return localFileName.Data();
554
555 }
556
557 //______________________________________________________________________________________________
558 Bool_t AliShuttle::RetrieveDAQFile(const char* daqFileName, const char* localFileName){
559
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));
563
564         void* dir = gSystem->OpenDirectory(fgkShuttleTempDir);
565         if (dir == NULL) {
566                 if (gSystem->mkdir(fgkShuttleTempDir, kTRUE)) {
567                         AliError(Form("Can't open directory <%s>!", fgkShuttleTempDir));
568                         return kFALSE;
569                 }
570
571         } else {
572                 gSystem->FreeDirectory(dir);
573         }
574
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(),
580                 daqFileName,
581                 fgkShuttleTempDir,
582                 localFileName);
583
584         AliInfo(Form("%s",command.Data()));
585
586         UInt_t nRetries = 0;
587         UInt_t maxRetries = 3;
588
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;
593         }
594
595         return kFALSE;
596
597 }
598
599 //______________________________________________________________________________________________
600 TList* AliShuttle::GetDAQFileSources(const char* detector, const char* id){
601 // Retrieves a file from the DCS FES.
602
603         // check connection, in case connect
604         if(!Connect(kDAQ)){
605                 Log(detector, "GetDAQFileName: Couldn't connect to DAQ Logbook !");
606                 return 0;
607         }
608
609         // Query preparation
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());
614
615         AliInfo(Form("SQL query: \n%s",sqlQuery.Data()));
616
617         // Query execution
618         TSQLResult* aResult;
619         aResult = fServer[kDAQ]->Query(sqlQuery);
620         if (!aResult) {
621                 Log(detector, Form("GetDAQFileSources: Can't execute query <%s>!", sqlQuery.Data()));
622                 return 0;
623         }
624
625         if (aResult->GetRowCount() == 0) {
626                 Log(detector,
627                         Form("GetDAQFileSources: No result from SQL query <%s>!", sqlQuery.Data()));
628                 delete aResult;
629                 return 0;
630         }
631
632         TSQLRow* aRow;
633         TList *list = new TList();
634         list->SetOwner(1);
635
636         while((aRow = aResult->Next())){
637
638                 TString daqSource(aRow->GetField(0), aRow->GetFieldLength(0));
639                 AliInfo(Form("daqSource = %s", daqSource.Data()));
640                 list->Add(new TObjString(daqSource));
641         }
642         delete aResult;
643
644         return list;
645
646 }
647
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
651
652         // check connection, in case connect
653         if(!Connect(kDAQ)){
654                 Log(detector, "UpdateDAQTable: Couldn't connect to DAQ Logbook !");
655                 return kFALSE;
656         }
657
658         TTimeStamp now; // now
659
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;
670                         return kFALSE;
671                 }
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);
676
677                 delete aFESarray;
678
679                 TString sqlQuery = Form("update logbook_fs set time_processed=%d %s", now.GetSec(), whereClause.Data());
680
681                 AliInfo(Form("SQL query: \n%s",sqlQuery.Data()));
682
683                 // Query execution
684                 TSQLResult* aResult;
685                 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
686                 if (!aResult) {
687                         Log(detector, Form("UpdateDAQTable: Can't execute query <%s>!", sqlQuery.Data()));
688                         return kFALSE;
689                 }
690                 delete aResult;
691
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()));
695
696                 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
697                 if (!aResult) {
698                         AliWarning("Can't check result!");
699                         continue;
700                 }
701
702         if (aResult->GetRowCount() == 0) {
703                 Log(detector,
704                         Form("GetDAQFileName: No result from SQL query <%s>!", sqlQuery.Data()));
705                 delete aResult;
706                 //return 0;
707         }
708
709         if (aResult->GetRowCount() >1) {
710                 Log(detector,
711                         Form("GetDAQFileName: More than one row resulting from SQL query <%s>!", sqlQuery.Data()));
712                 delete aResult;
713                 //return 0;
714         }
715
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()));
722                         delete aResult;
723                         return kFALSE;
724                 }
725
726                 delete aResult;
727
728         }
729
730         return kTRUE;
731 }
732
733 //______________________________________________________________________________________________
734 const char* AliShuttle::GetDCSFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
735 // Retrieves a file from the DCS FES.
736
737 return "You're in DCS";
738
739 }
740
741 //______________________________________________________________________________________________
742 TList* AliShuttle::GetDCSFileSources(const char* /*detector*/, const char* /*id*/){
743 // Retrieves a file from the DCS FES.
744
745 return NULL;
746
747 }
748
749 //______________________________________________________________________________________________
750 const char* AliShuttle::GetHLTFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
751 // Retrieves a file from the HLT FES.
752
753 return "You're in HLT";
754
755 }
756
757 //______________________________________________________________________________________________
758 TList* AliShuttle::GetHLTFileSources(const char* /*detector*/, const char* /*id*/){
759 // Retrieves a file from the HLT FES.
760
761 return NULL;
762
763 }
764
765 //______________________________________________________________________________________________
766 const char* AliShuttle::GetDetCode(const char* detector){
767 // Return detector code
768
769         for(int iDet=0; iDet < fgkNDetectors; iDet++){
770                 if(!strcmp(fgkDetectorName[iDet], detector)) return fgkDetectorCode[iDet];
771         }
772
773         return 0;
774 }
775
776 //______________________________________________________________________________________________
777 void AliShuttle::Log(const char* detector, const char* message)
778 {
779 // Fill log string with a message
780
781         TString toLog = Form("%s - %s", detector, message);
782         AliError(toLog.Data());
783
784         fLog += toLog;
785         fLog += "\n";
786
787 }
788
789 //______________________________________________________________________________________________
790 void AliShuttle::StoreLog(Int_t run)
791 {
792 // store error log string to SHUTTLE/SYSTEM/ERROR (on local storage)
793
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);
802         delete logString;
803
804
805 }
806