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