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