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