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