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