new configuration, accesst to DAQ FES (Alberto)
[u/mrichter/AliRoot.git] / SHUTTLE / AliShuttleTrigger.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.5  2006/07/10 13:01:41  jgrosseo
19  enhanced storing of last sucessfully processed run (alberto)
20
21  Revision 1.4  2006/07/04 14:59:57  jgrosseo
22  revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
23
24  Revision 1.3  2006/06/12 09:11:16  jgrosseo
25  coding conventions (Alberto)
26
27  Revision 1.2  2006/06/06 14:26:40  jgrosseo
28  o) removed files that were moved to STEER
29  o) shuttle updated to follow the new interface (Alberto)
30
31  Revision 1.1  2006/03/07 07:52:34  hristov
32  New version (B.Yordanov)
33
34  Revision 1.5  2005/11/21 09:03:48  byordano
35  one more print added
36
37  Revision 1.4  2005/11/20 10:12:37  byordano
38  comments added to AliShuttleTrigger
39
40  */
41
42
43 // 
44 // This class is to deal with DAQ LogBook and DAQ "end of run" notification.
45 // It has severeal two modes:
46 //      1) syncrhnized - Collect(), CollectNew() and CollectAll methods
47 //      2) asynchronized - Run() - starts listening for DAQ "end of run"
48 //              notification by DIM service.
49 //
50
51 #include "AliShuttleTrigger.h"
52
53 #include <TSQLServer.h>
54 #include <TSQLResult.h>
55 #include <TSQLRow.h>
56 #include <TObjArray.h>
57 #include <TSystem.h>
58
59 #include "AliLog.h"
60 #include "AliCDBManager.h"
61 #include "AliCDBStorage.h"
62 #include "AliCDBEntry.h"
63
64 #include "AliDCSValue.h"
65 #include "AliShuttleConfig.h"
66 #include "AliShuttle.h"
67 #include "DATENotifier.h"
68
69 ClassImp(TerminateSignalHandler)
70
71 //______________________________________________________________________
72 TerminateSignalHandler::TerminateSignalHandler(const TerminateSignalHandler& /*other*/):
73 TSignalHandler()
74 {
75 // copy constructor (not implemented)
76
77 }
78
79 //______________________________________________________________________
80 TerminateSignalHandler &TerminateSignalHandler::operator=(const TerminateSignalHandler& /*other*/)
81 {
82 // assignment operator (not implemented)
83
84 return *this;
85 }
86
87 //______________________________________________________________________________________________
88 Bool_t TerminateSignalHandler::Notify() 
89 {
90 // Sentd terminate command to the Shuttle trigger
91
92         AliInfo("Terminate signal received ...");
93         fTrigger->Terminate();
94
95         return kTRUE;
96 }
97
98 //______________________________________________________________________________________________
99 //______________________________________________________________________________________________
100
101 ClassImp(AliShuttleTrigger)
102
103 //______________________________________________________________________________________________
104 AliShuttleTrigger::AliShuttleTrigger(const AliShuttleConfig* config,
105                 UInt_t timeout, Int_t retries):
106         fConfig(config), fShuttle(NULL),
107         fNotified(kFALSE), fTerminate(kFALSE), fCondition(&fMutex),
108         fQuitSignalHandler(this, kSigQuit), 
109         fInterruptSignalHandler(this, kSigInterrupt)
110 {
111         //
112         // config - pointer to the AliShuttleConfig object which represents
113         // the configuration
114         // mainStorage - pointer to AliCDBStorage for the undelying CDBStorage
115         // localStorage (local) CDB storage to be used if mainStorage is unavailable
116         //
117
118         fShuttle = new AliShuttle(config, timeout, retries);
119
120         gSystem->AddSignalHandler(&fQuitSignalHandler);
121         gSystem->AddSignalHandler(&fInterruptSignalHandler);
122 }
123
124
125
126 //______________________________________________________________________
127 AliShuttleTrigger::AliShuttleTrigger(const AliShuttleTrigger& /*other*/):
128 TObject()
129 {
130 // copy constructor (not implemented)
131
132 }
133
134 //______________________________________________________________________
135 AliShuttleTrigger &AliShuttleTrigger::operator=(const AliShuttleTrigger& /*other*/)
136 {
137 // assignment operator (not implemented)
138
139 return *this;
140 }
141
142
143
144
145
146 //______________________________________________________________________________________________
147 AliShuttleTrigger::~AliShuttleTrigger() 
148 {
149 // destructor
150
151         gSystem->RemoveSignalHandler(&fQuitSignalHandler);
152         gSystem->RemoveSignalHandler(&fInterruptSignalHandler);
153
154         delete fShuttle;
155 }
156
157 //______________________________________________________________________________________________
158 Bool_t AliShuttleTrigger::Notify() {
159         //
160         // Trigger CollectNew() methods in asynchronized (listen) mode.
161         // Usually called automaticly by DATENotifier on "end of run" 
162         // notification event.
163         //
164
165         fMutex.Lock();
166
167         fNotified = kTRUE;
168         fCondition.Signal();
169
170         fMutex.UnLock();
171
172         return kTRUE;
173 }
174
175 //______________________________________________________________________________________________
176 void AliShuttleTrigger::Terminate() {
177         //
178         // Stop triggers listen mode and exist from Run()
179         // Usually called automaticly by TerminateSignalHandler.
180         //
181
182         fTerminate = kTRUE;
183         fCondition.Signal();
184 }
185
186 //______________________________________________________________________________________________
187 void AliShuttleTrigger::Run() {
188         //
189         // AliShuttleTrigger main loop for asynchronized (listen) mode.
190         // It spawns DIM service listener and waits for DAQ "end of run"
191         // notification. Calls CollectNew() on notification.
192         //
193
194         fTerminate = kFALSE;
195
196         DATENotifier* notifier = new DATENotifier(this, "/DATE/LOGBOOK/UPDATE");
197
198         while (1) {
199         
200                 fMutex.Lock();
201
202                 while (!(fNotified || fTerminate)) {
203                         fCondition.Wait();
204                 }
205
206                 fNotified = kFALSE;
207                 
208                 fMutex.UnLock();
209
210                 if (fTerminate) {
211                         AliInfo("Terminated.");
212                         break;          
213                 }
214         
215                 CollectNew();
216         }
217
218         delete notifier;
219 }
220
221 //______________________________________________________________________________________________
222 Bool_t AliShuttleTrigger::RetrieveDATEEntries(const char* whereClause,
223                 TObjArray& entries)
224 {
225 // Retrieve start time and end time for all runs in the DAQ logbook
226 // that aren't processed yet
227
228         TString sqlQuery;
229         sqlQuery = Form("select run, time_start, time_end from logbook %s order by run",
230                 whereClause);
231
232         TSQLServer* aServer;
233         TString logbookHost=Form("mysql://%s", fConfig->GetDAQlbHost());
234
235         aServer = TSQLServer::Connect(logbookHost,
236                         fConfig->GetDAQlbUser(),
237                         fConfig->GetDAQlbPass());
238         if (!aServer) {
239                 AliError("Can't establish connection to DAQ log book DB!");
240                 return kFALSE;
241         }
242
243         aServer->GetTables("REFSYSLOG");
244
245         TSQLResult* aResult;
246         aResult = aServer->Query(sqlQuery);
247         if (!aResult) {
248                 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
249                 delete aServer;
250                 return kFALSE;
251         }
252
253         if (aResult->GetFieldCount() != 3) {
254                 AliError("Invalid SQL result field number!");
255                 delete aResult;
256                 delete aServer;
257                 return kFALSE;
258         }
259
260         TSQLRow* aRow;
261         while ((aRow = aResult->Next())) {
262                 TString runString(aRow->GetField(0), aRow->GetFieldLength(0));
263                 Int_t run = runString.Atoi();
264
265                 TString startTimeString(aRow->GetField(1),
266                                 aRow->GetFieldLength(1));
267                 Int_t startTime = startTimeString.Atoi();
268                 if (!startTime) {
269                         AliWarning(Form("Zero StartTime for run <%d>!", run));
270                         AliWarning("Going to skip this run!");
271                         continue;
272                 }
273
274                 TString endTimeString(aRow->GetField(2),
275                                 aRow->GetFieldLength(2));
276                 Int_t endTime = endTimeString.Atoi();
277                 if (!endTime) {
278                         AliWarning(Form("Zero EndTime for run <%d>!", run));
279                         AliWarning("Going to skip this run!");
280                         continue;
281                 }
282
283                 if (startTime > endTime) {
284                         AliWarning(Form("StartTime bigger than EndTime for run <%d>", run));
285                         AliWarning("Going to skip this run!");
286                         continue;
287                 }
288
289                 entries.AddLast(new AliShuttleTriggerDATEEntry(run, startTime, endTime));
290                 delete aRow;
291         }
292
293         delete aResult;
294
295         aServer->Close();
296         delete aServer;
297
298         entries.SetOwner(1);
299
300         return kTRUE;
301 }
302
303 //______________________________________________________________________________________________
304 Bool_t AliShuttleTrigger::RetrieveConditionsData(const TObjArray& dateEntries, Int_t &lastRun)
305 {
306 // Retrieve conditions data for all runs that aren't processed yet
307
308         Bool_t hasError = kFALSE;
309
310         TIter iter(&dateEntries);
311         AliShuttleTriggerDATEEntry* anEntry;
312         lastRun=-1;
313         while ((anEntry = (AliShuttleTriggerDATEEntry*) iter.Next())) {
314                 Bool_t processError = kFALSE;
315                 if(lastRun == -1) lastRun = anEntry->GetRun();
316                 if(!fShuttle->Process(anEntry->GetRun(),
317                                 anEntry->GetStartTime(),
318                                 anEntry->GetEndTime())) {
319                                         processError = kTRUE;
320                                         hasError = kTRUE;
321                 }
322                 // Only the last SUCCESSFUL run must be stored!
323                 if(!hasError && !processError) lastRun = anEntry->GetRun();
324         }
325
326         return hasError == kFALSE;
327 }
328
329 //______________________________________________________________________________________________
330 Bool_t AliShuttleTrigger::Collect(Int_t run)
331 {
332         //
333         // Collects conditions date for the given run.
334         //
335
336         AliInfo(Form("Collecting conditions data for run <%d> ...", run));
337
338         TString whereClause("where run = ");
339         whereClause += run;
340
341         TObjArray dateEntries;
342         if (!RetrieveDATEEntries(whereClause, dateEntries)) {
343                 AliError("Can't retrieve entries from DAQ log book.");
344                 return kFALSE;
345         }
346
347         if (!dateEntries.GetEntriesFast()) {
348                 AliError(Form("There isn't entry for run <%d> in DAQ log book!",
349                         run));
350                 return kFALSE;
351         }
352
353         if (dateEntries.GetEntriesFast() > 1) {
354                 AliError(Form("There is more than one entry for run <%d> in DAQ log book", run));
355                 return kFALSE;
356         }
357
358         Int_t lastRun;
359         if (!RetrieveConditionsData(dateEntries, lastRun)) {
360                 AliError("An error occured during conditions data retrieval!");
361                 return kFALSE;
362         }
363
364         return kTRUE;
365 }
366
367 //______________________________________________________________________________________________
368 Bool_t AliShuttleTrigger::CollectNew() 
369 {
370         //
371         // Collects conditions data for all new run written to DAQ LogBook.
372         //
373
374   // TODO revise this! last run number is ONLY allowed to be written when run was processed successfully!!!
375
376         AliInfo("Collecting conditions data for new runs ...");
377
378         Int_t lastRun;
379
380         AliCDBEntry* cdbEntry = AliCDBManager::Instance()->GetStorage(AliShuttle::GetLocalURI())
381                                 ->Get("/SHUTTLE/SYSTEM/LASTRUN", 0);
382         if (cdbEntry) {
383                 TObject* anObject = cdbEntry->GetObject();
384                 if (anObject == NULL ||
385                         anObject->IsA() != AliDCSValue::Class()) {
386                         AliError("Invalid last run object stored to CDB!");
387                         return kFALSE;
388                 }
389                 AliDCSValue* simpleValue = (AliDCSValue*) anObject;
390                 lastRun = simpleValue->GetInt();
391                 AliInfo(Form("Last run successfully stored: %d",lastRun));
392                 delete cdbEntry;
393         } else {
394                 AliWarning("There isn't last run stored! Starting from run 21240");
395                 lastRun = 21240; // TODO maybe exit here
396         }
397
398         AliInfo(Form("Last run number <%d>", lastRun));
399
400         TString whereClause("where run > ");
401         whereClause += lastRun;
402
403         Int_t newLastRun;
404         TObjArray dateEntries;
405         if (!RetrieveDATEEntries(whereClause, dateEntries)) {
406                 AliError("Can't retrieve entries from DAQ log book.");
407                 return kFALSE;
408         }
409
410         if (!RetrieveConditionsData(dateEntries, newLastRun)) {
411                 AliError("Process of at least one run failed!");
412                 // return kFALSE;
413         }
414         
415         if (newLastRun > lastRun) {
416                 AliDCSValue lastRunObj(newLastRun, 0);
417                 AliCDBMetaData metaData;
418                 AliCDBId cdbID(AliCDBPath("SHUTTLE", "SYSTEM", "LASTRUN"), 0, 0);
419
420                 UInt_t result = AliCDBManager::Instance()->GetStorage(AliShuttle::GetLocalURI())
421                                 ->Put(&lastRunObj, cdbID, &metaData);
422
423                 if (!result) {
424                         AliError("Can't store last run to CDB!");
425                         return kFALSE;
426                 }
427         }
428
429         
430         return kTRUE;
431 }
432
433 //______________________________________________________________________________________________
434 Bool_t AliShuttleTrigger::CollectAll() 
435 {
436         //
437         // Collects conditions data for all run written in DAQ LogBook.
438         //
439
440         AliInfo("Collecting conditions data for all runs ...");
441
442         Int_t lastRun;
443         TObjArray dateEntries;
444         if (!RetrieveDATEEntries("", dateEntries)) {
445                 AliError("Can't retrieve entries from DAQ log book.");
446                 return kFALSE;
447         }
448
449         if (!RetrieveConditionsData(dateEntries, lastRun)) {
450                 AliError("An error occured during conditions data retrieval!");
451                 return kFALSE;
452         }
453
454         return kTRUE;
455 }
456