- Added back the old constructor that takes care of loading/unloading Kinematics,
[u/mrichter/AliRoot.git] / SHUTTLE / AliShuttle.cxx
CommitLineData
73abe331 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$
eba76848 18Revision 1.18 2006/10/20 15:22:59 jgrosseo
19o) Adding time out to the execution of the preprocessors: The Shuttle forks and the parent process monitors the child
20o) Merging Collect, CollectAll, CollectNew function
21o) Removing implementation of empty copy constructors (declaration still there!)
22
cb343cfd 23Revision 1.17 2006/10/05 16:20:55 jgrosseo
24adapting to new CDB classes
25
6ec0e06c 26Revision 1.16 2006/10/05 15:46:26 jgrosseo
27applying to the new interface
28
481441a2 29Revision 1.15 2006/10/02 16:38:39 jgrosseo
30update (alberto):
31fixed memory leaks
32storing of objects that failed to be stored to the grid before
33interfacing of shuttle status table in daq system
34
2bb7b766 35Revision 1.14 2006/08/29 09:16:05 jgrosseo
36small update
37
85a80aa9 38Revision 1.13 2006/08/15 10:50:00 jgrosseo
39effc++ corrections (alberto)
40
4f0ab988 41Revision 1.12 2006/08/08 14:19:29 jgrosseo
42Update to shuttle classes (Alberto)
43
44- Possibility to set the full object's path in the Preprocessor's and
45Shuttle's Store functions
46- Possibility to extend the object's run validity in the same classes
47("startValidity" and "validityInfinite" parameters)
48- Implementation of the StoreReferenceData function to store reference
49data in a dedicated CDB storage.
50
84090f85 51Revision 1.11 2006/07/21 07:37:20 jgrosseo
52last run is stored after each run
53
7bfb2090 54Revision 1.10 2006/07/20 09:54:40 jgrosseo
55introducing status management: The processing per subdetector is divided into several steps,
56after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
57can keep track of the number of failures and skips further processing after a certain threshold is
58exceeded. These thresholds can be configured in LDAP.
59
5164a766 60Revision 1.9 2006/07/19 10:09:55 jgrosseo
61new configuration, accesst to DAQ FES (Alberto)
62
57f50b3c 63Revision 1.8 2006/07/11 12:44:36 jgrosseo
64adding parameters for extended validity range of data produced by preprocessor
65
17111222 66Revision 1.7 2006/07/10 14:37:09 jgrosseo
67small fix + todo comment
68
e090413b 69Revision 1.6 2006/07/10 13:01:41 jgrosseo
70enhanced storing of last sucessfully processed run (alberto)
71
a7160fe9 72Revision 1.5 2006/07/04 14:59:57 jgrosseo
73revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
74
45a493ce 75Revision 1.4 2006/06/12 09:11:16 jgrosseo
76coding conventions (Alberto)
77
58bc3020 78Revision 1.3 2006/06/06 14:26:40 jgrosseo
79o) removed files that were moved to STEER
80o) shuttle updated to follow the new interface (Alberto)
81
b948db8d 82Revision 1.2 2006/03/07 07:52:34 hristov
83New version (B.Yordanov)
84
d477ad88 85Revision 1.6 2005/11/19 17:19:14 byordano
86RetrieveDATEEntries and RetrieveConditionsData added
87
88Revision 1.5 2005/11/19 11:09:27 byordano
89AliShuttle declaration added
90
91Revision 1.4 2005/11/17 17:47:34 byordano
92TList changed to TObjArray
93
94Revision 1.3 2005/11/17 14:43:23 byordano
95import to local CVS
96
97Revision 1.1.1.1 2005/10/28 07:33:58 hristov
98Initial import as subdirectory in AliRoot
99
73abe331 100Revision 1.2 2005/09/13 08:41:15 byordano
101default startTime endTime added
102
103Revision 1.4 2005/08/30 09:13:02 byordano
104some docs added
105
106Revision 1.3 2005/08/29 21:15:47 byordano
107some docs added
108
109*/
110
111//
112// This class is the main manager for AliShuttle.
113// It organizes the data retrieval from DCS and call the
b948db8d 114// interface methods of AliPreprocessor.
73abe331 115// For every detector in AliShuttleConfgi (see AliShuttleConfig),
116// data for its set of aliases is retrieved. If there is registered
b948db8d 117// AliPreprocessor for this detector then it will be used
118// accroding to the schema (see AliPreprocessor).
119// If there isn't registered AliPreprocessor than the retrieved
73abe331 120// data is stored automatically to the undelying AliCDBStorage.
121// For detSpec is used the alias name.
122//
123
124#include "AliShuttle.h"
125
126#include "AliCDBManager.h"
127#include "AliCDBStorage.h"
128#include "AliCDBId.h"
84090f85 129#include "AliCDBRunRange.h"
130#include "AliCDBPath.h"
5164a766 131#include "AliCDBEntry.h"
73abe331 132#include "AliShuttleConfig.h"
eba76848 133#include "DCSClient/AliDCSClient.h"
73abe331 134#include "AliLog.h"
b948db8d 135#include "AliPreprocessor.h"
5164a766 136#include "AliShuttleStatus.h"
2bb7b766 137#include "AliShuttleLogbookEntry.h"
73abe331 138
57f50b3c 139#include <TSystem.h>
58bc3020 140#include <TObject.h>
b948db8d 141#include <TString.h>
57f50b3c 142#include <TTimeStamp.h>
73abe331 143#include <TObjString.h>
57f50b3c 144#include <TSQLServer.h>
145#include <TSQLResult.h>
146#include <TSQLRow.h>
cb343cfd 147#include <TMutex.h>
73abe331 148
5164a766 149#include <fstream>
150
cb343cfd 151#include <sys/types.h>
152#include <sys/wait.h>
153
73abe331 154ClassImp(AliShuttle)
155
2bb7b766 156TString AliShuttle::fgkMainCDB("alien://folder=ShuttleCDB");
84090f85 157TString AliShuttle::fgkLocalCDB("local://LocalShuttleCDB");
2bb7b766 158TString AliShuttle::fgkMainRefStorage("alien://folder=ShuttleReference");
84090f85 159TString AliShuttle::fgkLocalRefStorage("local://LocalReferenceStorage");
160
4f0ab988 161Bool_t AliShuttle::fgkProcessDCS(kTRUE);
162
84090f85 163const char* AliShuttle::fgkShuttleTempDir = gSystem->ExpandPathName("$ALICE_ROOT/SHUTTLE/temp");
164const char* AliShuttle::fgkShuttleLogDir = gSystem->ExpandPathName("$ALICE_ROOT/SHUTTLE/log");
57f50b3c 165
b948db8d 166//______________________________________________________________________________________________
167AliShuttle::AliShuttle(const AliShuttleConfig* config,
168 UInt_t timeout, Int_t retries):
4f0ab988 169fConfig(config),
170fTimeout(timeout), fRetries(retries),
171fPreprocessorMap(),
2bb7b766 172fLogbookEntry(0),
eba76848 173fCurrentDetector(),
85a80aa9 174fStatusEntry(0),
cb343cfd 175fGridError(kFALSE),
176fMonitoringMutex(0),
eba76848 177fLastActionTime(0),
178fLastAction()
73abe331 179{
180 //
181 // config: AliShuttleConfig used
73abe331 182 // timeout: timeout used for AliDCSClient connection
183 // retries: the number of retries in case of connection error.
184 //
185
57f50b3c 186 if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
187 for(int iSys=0;iSys<3;iSys++) {
188 fServer[iSys]=0;
189 fFESlist[iSys].SetOwner(kTRUE);
190 }
2bb7b766 191 fPreprocessorMap.SetOwner(kTRUE);
cb343cfd 192
193 fMonitoringMutex = new TMutex();
58bc3020 194}
195
b948db8d 196//______________________________________________________________________________________________
57f50b3c 197AliShuttle::~AliShuttle()
58bc3020 198{
199// destructor
200
b948db8d 201 fPreprocessorMap.DeleteAll();
57f50b3c 202 for(int iSys=0;iSys<3;iSys++)
203 if(fServer[iSys]) {
204 fServer[iSys]->Close();
205 delete fServer[iSys];
eba76848 206 fServer[iSys] = 0;
57f50b3c 207 }
2bb7b766 208
209 if (fStatusEntry){
210 delete fStatusEntry;
211 fStatusEntry = 0;
212 }
cb343cfd 213
214 if (fMonitoringMutex)
215 {
216 delete fMonitoringMutex;
217 fMonitoringMutex = 0;
218 }
73abe331 219}
220
b948db8d 221//______________________________________________________________________________________________
57f50b3c 222void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
58bc3020 223{
73abe331 224 //
b948db8d 225 // Registers new AliPreprocessor.
73abe331 226 // It uses GetName() for indentificator of the pre processor.
227 // The pre processor is registered it there isn't any other
228 // with the same identificator (GetName()).
229 //
230
eba76848 231 const char* detName = preprocessor->GetName();
232 if(GetDetPos(detName) < 0)
233 AliFatal(Form("********** !!!!! Invalid detector name: %s !!!!! **********", detName));
234
235 if (fPreprocessorMap.GetValue(detName)) {
236 AliWarning(Form("AliPreprocessor %s is already registered!", detName));
73abe331 237 return;
238 }
239
eba76848 240 fPreprocessorMap.Add(new TObjString(detName), preprocessor);
73abe331 241}
b948db8d 242//______________________________________________________________________________________________
84090f85 243UInt_t AliShuttle::Store(const AliCDBPath& path, TObject* object,
244 AliCDBMetaData* metaData, Int_t validityStart, Bool_t validityInfinite)
73abe331 245{
84090f85 246 // Stores a CDB object in the storage for offline reconstruction. Objects that are not needed for
247 // offline reconstruction, but should be stored anyway (e.g. for debugging) should NOT be stored
248 // using this function. Use StoreReferenceData instead!
85a80aa9 249 // It calls WriteToCDB function which perform actual storage
b948db8d 250
85a80aa9 251 return WriteToCDB(fgkMainCDB, fgkLocalCDB, path, object,
252 metaData, validityStart, validityInfinite);
84090f85 253
254}
255
256//______________________________________________________________________________________________
481441a2 257UInt_t AliShuttle::StoreReferenceData(const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData)
84090f85 258{
259 // Stores a CDB object in the storage for reference data. This objects will not be available during
260 // offline reconstrunction. Use this function for reference data only!
85a80aa9 261 // It calls WriteToCDB function which perform actual storage
262
481441a2 263 return WriteToCDB(fgkMainRefStorage, fgkLocalRefStorage, path, object, metaData);
84090f85 264
85a80aa9 265}
266
267//______________________________________________________________________________________________
268UInt_t AliShuttle::WriteToCDB(const char* mainUri, const char* localUri,
269 const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData,
270 Int_t validityStart, Bool_t validityInfinite)
271{
272 // write object into the CDB. Parameters are passed by Store and StoreReferenceData functions.
273 // The parameters are:
274 // 1) Uri of the main storage (Grid)
275 // 2) Uri of the backup storage (Local)
276 // 3) the object's path.
277 // 4) the object to be stored
278 // 5) the metaData to be associated with the object
279 // 6) the validity start run number w.r.t. the current run,
84090f85 280 // if the data is valid only for this run leave the default 0
85a80aa9 281 // 7) specifies if the calibration data is valid for infinity (this means until updated),
84090f85 282 // typical for calibration runs, the default is kFALSE
283 //
84090f85 284 // returns 0 if fail
85a80aa9 285 // 1 if stored in main (Grid) storage
286 // 2 if stored in backup (Local) storage
84090f85 287
85a80aa9 288 const char* cdbType = (mainUri == fgkMainCDB) ? "CDB" : "Reference";
2bb7b766 289
85a80aa9 290 Int_t firstRun = GetCurrentRun() - validityStart;
84090f85 291 if(firstRun < 0) {
2bb7b766 292 AliError("First valid run happens to be less than 0! Setting it to 0.");
84090f85 293 firstRun=0;
294 }
295
296 Int_t lastRun = -1;
297 if(validityInfinite) {
298 lastRun = AliCDBRunRange::Infinity();
299 } else {
300 lastRun = GetCurrentRun();
301 }
302
2bb7b766 303 AliCDBId id(path, firstRun, lastRun, -1, -1);
304
305 if(! dynamic_cast<TObjString*> (metaData->GetProperty("RunUsed(TObjString)"))){
306 TObjString runUsed = Form("%d", GetCurrentRun());
307 metaData->SetProperty("RunUsed(TObjString)",&runUsed);
308 }
84090f85 309
310 UInt_t result = 0;
311
85a80aa9 312 if (!(AliCDBManager::Instance()->GetStorage(mainUri))) {
2bb7b766 313 AliError(Form("WriteToCDB - Cannot activate main %s storage", cdbType));
84090f85 314 } else {
85a80aa9 315 result = (UInt_t) AliCDBManager::Instance()->GetStorage(mainUri)
84090f85 316 ->Put(object, id, metaData);
317 }
318
319 if(!result) {
320
321 Log(fCurrentDetector,
2bb7b766 322 Form("WriteToCDB - Problem with main %s storage. Putting <%s> into backup storage",
323 cdbType, path.GetPath().Data()));
324
325 // Set Grid version to current run number, to ease retrieval later
326 id.SetVersion(GetCurrentRun());
84090f85 327
85a80aa9 328 result = AliCDBManager::Instance()->GetStorage(localUri)
84090f85 329 ->Put(object, id, metaData);
330
331 if(result) {
332 result = 2;
85a80aa9 333 fGridError = kTRUE;
84090f85 334 }else{
2bb7b766 335 Log(fCurrentDetector, "WriteToCDB - Can't store data!");
b948db8d 336 }
337 }
2bb7b766 338
b948db8d 339 return result;
340
73abe331 341}
342
b948db8d 343//______________________________________________________________________________________________
5164a766 344AliShuttleStatus* AliShuttle::ReadShuttleStatus()
345{
2bb7b766 346// Reads the AliShuttleStatus from the CDB
5164a766 347
2bb7b766 348 if (fStatusEntry){
349 delete fStatusEntry;
350 fStatusEntry = 0;
351 }
5164a766 352
2bb7b766 353 fStatusEntry = AliCDBManager::Instance()->GetStorage(AliShuttle::GetLocalCDB())
354 ->Get(Form("/SHUTTLE/STATUS/%s", fCurrentDetector.Data()), GetCurrentRun());
5164a766 355
2bb7b766 356 if (!fStatusEntry) return 0;
357 fStatusEntry->SetOwner(1);
5164a766 358
2bb7b766 359 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
360 if (!status) {
361 AliError("Invalid object stored to CDB!");
362 return 0;
363 }
5164a766 364
2bb7b766 365 return status;
5164a766 366}
367
368//______________________________________________________________________________________________
7bfb2090 369Bool_t AliShuttle::WriteShuttleStatus(AliShuttleStatus* status)
5164a766 370{
2bb7b766 371// writes the status for one subdetector
372
373 if (fStatusEntry){
374 delete fStatusEntry;
375 fStatusEntry = 0;
376 }
5164a766 377
2bb7b766 378 Int_t run = GetCurrentRun();
5164a766 379
2bb7b766 380 AliCDBId id(AliCDBPath("SHUTTLE", "STATUS", fCurrentDetector), run, run);
5164a766 381
2bb7b766 382 fStatusEntry = new AliCDBEntry(status, id, new AliCDBMetaData);
383 fStatusEntry->SetOwner(1);
5164a766 384
2bb7b766 385 UInt_t result = AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
7bfb2090 386
2bb7b766 387 if (!result) {
388 AliError(Form("WriteShuttleStatus for %s, run %d failed", fCurrentDetector.Data(), run));
389 return kFALSE;
390 }
7bfb2090 391
2bb7b766 392 return kTRUE;
5164a766 393}
394
395//______________________________________________________________________________________________
396void AliShuttle::UpdateShuttleStatus(AliShuttleStatus::Status newStatus, Bool_t increaseCount)
397{
398 // changes the AliShuttleStatus for the given detector and run to the given status
399
2bb7b766 400 if (!fStatusEntry){
401 AliError("UNEXPECTED: fStatusEntry empty");
402 return;
403 }
5164a766 404
2bb7b766 405 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
5164a766 406
2bb7b766 407 if (!status){
408 AliError("UNEXPECTED: status could not be read from current CDB entry");
409 return;
410 }
5164a766 411
eba76848 412 TString actionStr = Form("UpdateShuttleStatus - %s: Changing state from %s to %s",
413 fCurrentDetector.Data(),
414 status->GetStatusName(),
415 status->GetStatusName(newStatus));
cb343cfd 416 Log("SHUTTLE", actionStr);
417 SetLastAction(actionStr);
5164a766 418
2bb7b766 419 status->SetStatus(newStatus);
420 if (increaseCount) status->IncreaseCount();
5164a766 421
2bb7b766 422 AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
5164a766 423}
5164a766 424//______________________________________________________________________________________________
425Bool_t AliShuttle::ContinueProcessing()
426{
2bb7b766 427// this function reads the AliShuttleStatus information from CDB and
428// checks if the processing should be continued
429// if yes it returns kTRUE and updates the AliShuttleStatus with nextStatus
430
2bb7b766 431 AliShuttleLogbookEntry::Status entryStatus =
eba76848 432 fLogbookEntry->GetDetectorStatus(fCurrentDetector);
2bb7b766 433
434 if(entryStatus != AliShuttleLogbookEntry::kUnprocessed) {
eba76848 435 Log("SHUTTLE", Form("ContinueProcessing - %s is %s",
2bb7b766 436 fCurrentDetector.Data(),
437 fLogbookEntry->GetDetectorStatusName(entryStatus)));
438 return kFALSE;
439 }
440
441 // if we get here, according to Shuttle logbook subdetector is in UNPROCESSED state
442 AliShuttleStatus* status = ReadShuttleStatus();
443 if (!status) {
444 // first time
445 Log("SHUTTLE", Form("ContinueProcessing - %s: Processing first time",
446 fCurrentDetector.Data()));
447 status = new AliShuttleStatus(AliShuttleStatus::kStarted);
448 return WriteShuttleStatus(status);
449 }
450
451 // The following two cases shouldn't happen if Shuttle Logbook was correctly updated.
452 // If it happens it may mean Logbook updating failed... let's do it now!
453 if (status->GetStatus() == AliShuttleStatus::kDone ||
454 status->GetStatus() == AliShuttleStatus::kFailed){
455 Log("SHUTTLE", Form("ContinueProcessing - %s is already %s. Updating Shuttle Logbook",
456 fCurrentDetector.Data(),
457 status->GetStatusName(status->GetStatus())));
458 UpdateShuttleLogbook(fCurrentDetector.Data(),
459 status->GetStatusName(status->GetStatus()));
460 return kFALSE;
461 }
462
463 if (status->GetStatus() == AliShuttleStatus::kStoreFailed) {
464 Log("SHUTTLE",
465 Form("ContinueProcessing - %s: Grid storage of one or more objects failed. Trying again now",
466 fCurrentDetector.Data()));
467 if(TryToStoreAgain()){
468 Log(fCurrentDetector.Data(), "ContinueProcessing - All objects successfully stored into OCDB");
469 UpdateShuttleStatus(AliShuttleStatus::kDone);
470 UpdateShuttleLogbook(fCurrentDetector.Data(), "DONE");
471 } else {
472 Log("SHUTTLE",
473 Form("ContinueProcessing - %s: Grid storage failed again",
474 fCurrentDetector.Data()));
475 }
476 return kFALSE;
477 }
478
479 // if we get here, there is a restart
480
481 // abort conditions
cb343cfd 482 if (status->GetCount() >= fConfig->GetMaxRetries()) {
2bb7b766 483 Log("SHUTTLE",
484 Form("ContinueProcessing - %s failed %d times in status %s - Updating Shuttle Logbook",
485 fCurrentDetector.Data(),
486 status->GetCount(), status->GetStatusName()));
487 UpdateShuttleLogbook(fCurrentDetector.Data(), "FAILED");
488 return kFALSE;
489 }
490
eba76848 491 Log("SHUTTLE", Form("ContinueProcessing - %s: restarting. Aborted before with %s. Retry number %d.",
2bb7b766 492 fCurrentDetector.Data(),
493 status->GetStatusName(), status->GetCount()));
494
cb343cfd 495 UpdateShuttleStatus(AliShuttleStatus::kStarted, kTRUE);
2bb7b766 496
497 return kTRUE;
5164a766 498}
499
500//______________________________________________________________________________________________
2bb7b766 501Bool_t AliShuttle::Process(AliShuttleLogbookEntry* entry)
58bc3020 502{
73abe331 503 //
b948db8d 504 // Makes data retrieval for all detectors in the configuration.
2bb7b766 505 // entry: Shuttle logbook entry, contains run paramenters and status of detectors
506 // (Unprocessed, Inactive, Failed or Done).
d477ad88 507 // Returns kFALSE in case of error occured and kTRUE otherwise
73abe331 508 //
509
2bb7b766 510 if(!entry) return kFALSE;
511
512 fLogbookEntry = entry;
513
514 if(fLogbookEntry->IsDone()){
515 Log("SHUTTLE","Process - Shuttle is already DONE. Updating logbook");
516 UpdateShuttleLogbook("shuttle_done");
517 fLogbookEntry = 0;
518 return kTRUE;
519 }
520
521
522 AliInfo(Form("\n\n \t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: START ^*^*^*^*^*^*^*^*^*^*^*^* \n",
523 GetCurrentRun()));
524
eba76848 525 fLogbookEntry->Print("all");
57f50b3c 526
527 // Initialization
d477ad88 528 Bool_t hasError = kFALSE;
57f50b3c 529 for(Int_t iSys=0;iSys<3;iSys++) fFESCalled[iSys]=kFALSE;
5164a766 530
2bb7b766 531 AliCDBStorage *mainCDBSto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
532 if(mainCDBSto) mainCDBSto->QueryCDB(GetCurrentRun());
533 AliCDBStorage *mainRefSto = AliCDBManager::Instance()->GetStorage(fgkMainRefStorage);
534 if(mainRefSto) mainRefSto->QueryCDB(GetCurrentRun());
d477ad88 535
57f50b3c 536 // Loop on detectors in the configuration
b948db8d 537 TIter iter(fConfig->GetDetectors());
2bb7b766 538 TObjString* aDetector = 0;
b948db8d 539
73abe331 540 while ((aDetector = (TObjString*) iter.Next())) {
7bfb2090 541 fCurrentDetector = aDetector->String();
5164a766 542
5164a766 543 if (!fConfig->HostProcessDetector(fCurrentDetector)) continue;
544
2bb7b766 545 AliPreprocessor* aPreprocessor =
546 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
547 if(!aPreprocessor){
eba76848 548 Log("SHUTTLE",Form("Process - %s: no preprocessor registered. Skipping",
549 fCurrentDetector.Data()));
2bb7b766 550 continue;
551 }
552
7bfb2090 553 if (ContinueProcessing() == kFALSE) continue;
5164a766 554
2bb7b766 555 AliInfo(Form("\n\n \t\t\t****** run %d - %s: START ******",
556 GetCurrentRun(), aDetector->GetName()));
557
85a80aa9 558
cb343cfd 559 Int_t pid = fork();
2bb7b766 560
cb343cfd 561 if (pid < 0)
562 {
563 Log("SHUTTLE", "ERROR: Forking failed");
564 }
565 else if (pid > 0)
566 {
567 // parent
568 AliInfo(Form("In parent process of %d - %s: Starting monitoring", GetCurrentRun(), aDetector->GetName()));
57f50b3c 569
cb343cfd 570 Long_t begin = time(0);
571
572 int status; // to be used with waitpid, on purpose an int (not Int_t)!
573 while (waitpid(pid, &status, WNOHANG) == 0)
574 {
575 Long_t expiredTime = time(0) - begin;
576
577 if (expiredTime > fConfig->GetPPTimeOut())
578 {
579 Log("SHUTTLE", Form("Process time out. Run time: %d seconds. Killing...", expiredTime));
d477ad88 580
cb343cfd 581 kill(pid, 9);
582
583 hasError = kTRUE;
584
585 gSystem->Sleep(1000);
586 }
587 else
588 {
589 if (expiredTime % 60 == 0)
590 Log("SHUTTLE", Form("Checked process. Run time: %d seconds.", expiredTime));
591
592 gSystem->Sleep(1000);
593 }
594 }
595
596 AliInfo(Form("In parent process of %d - %s: Client has terminated.", GetCurrentRun(), aDetector->GetName()));
597
598 if (WIFEXITED(status))
599 {
600 Int_t returnCode = WEXITSTATUS(status);
601
602 Log("SHUTTLE", Form("The return code is %d", returnCode));
603
604 if (returnCode != 0)
605 hasError = kTRUE;
606 }
607 }
608 else if (pid == 0)
609 {
610 // client
611 AliInfo(Form("In client process of %d - %s", GetCurrentRun(), aDetector->GetName()));
612
613 UInt_t result = ProcessCurrentDetector();
614
615 Int_t returnCode = 0; // will be set to 1 in case of an error
616
617 if (!result) {
618 returnCode = 1;
619 AliInfo(Form("\n \t\t\t****** run %d - %s: PREPROCESSOR ERROR ****** \n\n",
620 GetCurrentRun(), aDetector->GetName()));
621 }
622 else if(result == 2) {
623 AliInfo(Form("\n \t\t\t****** run %d - %s: STORAGE ERROR ****** \n\n",
624 GetCurrentRun(), aDetector->GetName()));
625 } else {
626 AliInfo(Form("\n \t\t\t****** run %d - %s: DONE ****** \n\n",
627 GetCurrentRun(), aDetector->GetName()));
628 }
629
630 if (result > 0)
631 {
632 // Process successful: Update time_processed field in FES logbooks!
633 if(fFESCalled[kDAQ]) {
634 if (UpdateDAQTable() == kFALSE)
635 returnCode = 1;
636 fFESlist[kDAQ].Clear();
637 }
638 //if(fFESCalled[kDCS]) {
639 // if (UpdateDCSTable(aDetector->GetName()) == kFALSE)
640 // returnCode = 1;
641 // fFESlist[kDCS].Clear();
642 //}
643 //if(fFESCalled[kHLT]) {
644 // if (UpdateHLTTable(aDetector->GetName()) == kFALSE)
645 // returnCode = 1;
646 // fFESlist[kHLT].Clear();
647 //}
648 }
649
650 AliInfo(Form("Client process of %d - %s is exiting now with %d.", GetCurrentRun(), aDetector->GetName(), returnCode));
651
652 // the client exits here
653 gSystem->Exit(returnCode);
654
655 AliError("We should never get here!!!");
656 }
7bfb2090 657 }
5164a766 658
2bb7b766 659 AliInfo(Form("\n\n \t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: FINISH ^*^*^*^*^*^*^*^*^*^*^*^* \n",
660 GetCurrentRun()));
661
662 //check if shuttle is done for this run, if so update logbook
663 TObjArray checkEntryArray;
664 checkEntryArray.SetOwner(1);
665 TString whereClause = Form("where run=%d",GetCurrentRun());
666 if(QueryShuttleLogbook(whereClause.Data(), checkEntryArray)) {
b948db8d 667
2bb7b766 668 AliShuttleLogbookEntry* checkEntry = dynamic_cast<AliShuttleLogbookEntry*>
669 (checkEntryArray.At(0));
670
671 if(checkEntry && checkEntry->IsDone()){
672 Log("SHUTTLE","Process - Shuttle is DONE. Updating logbook");
673 UpdateShuttleLogbook("shuttle_done");
674 }
675 }
676
677 fLogbookEntry = 0;
85a80aa9 678
a7160fe9 679 return hasError == kFALSE;
73abe331 680}
681
b948db8d 682//______________________________________________________________________________________________
2bb7b766 683UInt_t AliShuttle::ProcessCurrentDetector()
73abe331 684{
685 //
2bb7b766 686 // Makes data retrieval just for a specific detector (fCurrentDetector).
73abe331 687 // Threre should be a configuration for this detector.
73abe331 688
2bb7b766 689 AliInfo(Form("Retrieving values for %s, run %d", fCurrentDetector.Data(), GetCurrentRun()));
73abe331 690
7bfb2090 691 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
73abe331 692
7bfb2090 693 TString host(fConfig->GetDCSHost(fCurrentDetector));
5164a766 694 Int_t port = fConfig->GetDCSPort(fCurrentDetector);
695
696 TIter iter(fConfig->GetDCSAliases(fCurrentDetector));
73abe331 697 TObjString* anAlias;
b948db8d 698 TMap aliasMap;
2bb7b766 699 aliasMap.SetOwner(1);
73abe331 700
85a80aa9 701 Bool_t aDCSError = kFALSE;
702 fGridError = kFALSE;
d477ad88 703
b948db8d 704 while ((anAlias = (TObjString*) iter.Next())) {
2bb7b766 705 TObjArray *valueSet = new TObjArray();
706 valueSet->SetOwner(1);
4f0ab988 707 // TODO Test only... I've added a flag that allows to
708 // exclude DCS archive DB query
709 if(fgkProcessDCS){
710 AliInfo("Querying DCS archive DB data...");
85a80aa9 711 aDCSError = (GetValueSet(host, port, anAlias->String(), valueSet) == 0);
4f0ab988 712 } else {
713 AliInfo(Form("Skipping DCS processing. Port = %d",port));
85a80aa9 714 aDCSError = kFALSE;
4f0ab988 715 }
85a80aa9 716 if(!aDCSError) {
2bb7b766 717 aliasMap.Add(anAlias->Clone(), valueSet);
b948db8d 718 }else{
2bb7b766 719 Log(fCurrentDetector, Form("ProcessCurrentDetector - Error while retrieving alias %s",
720 anAlias->GetName()));
721 UpdateShuttleStatus(AliShuttleStatus::kDCSError, kTRUE);
722 aliasMap.DeleteAll();
723 return 0;
73abe331 724 }
725 }
b948db8d 726
2bb7b766 727 // DCS Archive DB processing successful. Call Preprocessor!
85a80aa9 728 UpdateShuttleStatus(AliShuttleStatus::kPPStarted);
a7160fe9 729
85a80aa9 730 AliPreprocessor* aPreprocessor =
5164a766 731 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
b948db8d 732
2bb7b766 733 aPreprocessor->Initialize(GetCurrentRun(), GetCurrentStartTime(), GetCurrentEndTime());
2bb7b766 734 UInt_t aPPResult = aPreprocessor->Process(&aliasMap);
735
736 UInt_t returnValue = 0;
85a80aa9 737 if (aPPResult == 0) { // Preprocessor error
cb343cfd 738 UpdateShuttleStatus(AliShuttleStatus::kPPError);
2bb7b766 739 returnValue = 0;
85a80aa9 740 } else if (fGridError == kFALSE) { // process and Grid storage ok!
741 UpdateShuttleStatus(AliShuttleStatus::kDone);
2bb7b766 742 UpdateShuttleLogbook(fCurrentDetector, "DONE");
743 Log(fCurrentDetector.Data(),
744 "ProcessCurrentDetector - Preprocessor and Grid storage ended successfully");
745 returnValue = 1;
85a80aa9 746 } else { // Grid storage error (process ok, but object put in local storage)
747 UpdateShuttleStatus(AliShuttleStatus::kStoreFailed);
2bb7b766 748 returnValue = 2;
85a80aa9 749 }
b948db8d 750
2bb7b766 751 aliasMap.DeleteAll();
b948db8d 752
2bb7b766 753 return returnValue;
754}
755
756//______________________________________________________________________________________________
757Bool_t AliShuttle::QueryShuttleLogbook(const char* whereClause,
758 TObjArray& entries)
759{
760// Query DAQ's Shuttle logbook and fills detector status object.
761// Call QueryRunParameters to query DAQ logbook for run parameters.
762
763 // check connection, in case connect
764 if(!Connect(kDAQ)) return kFALSE;
765
766 TString sqlQuery;
767 sqlQuery = Form("select * from logbook_shuttle %s order by run", whereClause);
768
769 TSQLResult* aResult = fServer[kDAQ]->Query(sqlQuery);
770 if (!aResult) {
771 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
772 return kFALSE;
773 }
774
775 if(aResult->GetRowCount() == 0) {
776 if(sqlQuery.Contains("where shuttle_done=0")){
777 Log("SHUTTLE", "QueryShuttleLogbook - All runs in Shuttle Logbook are already DONE");
778 delete aResult;
779 return kTRUE;
780 } else {
781 AliError("No entries in Shuttle Logbook match request");
782 delete aResult;
783 return kFALSE;
784 }
785 }
786
787 // TODO Check field count!
788 const UInt_t nCols = 24;
789 if (aResult->GetFieldCount() != (Int_t) nCols) {
790 AliError("Invalid SQL result field number!");
791 delete aResult;
792 return kFALSE;
793 }
794
795 entries.SetOwner(1);
796
797 TSQLRow* aRow;
798 while ((aRow = aResult->Next())) {
799 TString runString(aRow->GetField(0), aRow->GetFieldLength(0));
800 Int_t run = runString.Atoi();
801
eba76848 802 AliShuttleLogbookEntry *entry = QueryRunParameters(run);
803 if (!entry)
804 continue;
2bb7b766 805
806 // loop on detectors
eba76848 807 for(UInt_t ii = 0; ii < nCols; ii++)
808 entry->SetDetectorStatus(aResult->GetFieldName(ii), aRow->GetField(ii));
2bb7b766 809
eba76848 810 entries.AddLast(entry);
2bb7b766 811 delete aRow;
812 }
813
814 if(sqlQuery.Contains("where shuttle_done=0"))
815 Log("SHUTTLE", Form("QueryShuttleLogbook - Found %d unprocessed runs in Shuttle Logbook",
816 entries.GetEntriesFast()));
817 delete aResult;
818 return kTRUE;
819}
820
821//______________________________________________________________________________________________
eba76848 822AliShuttleLogbookEntry* AliShuttle::QueryRunParameters(Int_t run)
2bb7b766 823{
eba76848 824 //
825 // Retrieve run parameters written in the DAQ logbook and sets them into AliShuttleLogbookEntry object
826 //
2bb7b766 827
828 // check connection, in case connect
eba76848 829 if (!Connect(kDAQ))
830 return 0;
2bb7b766 831
832 TString sqlQuery;
eba76848 833 sqlQuery.Form("select * from logbook where run=%d", run);
2bb7b766 834
835 TSQLResult* aResult = fServer[kDAQ]->Query(sqlQuery);
836 if (!aResult) {
837 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
eba76848 838 return 0;
2bb7b766 839 }
840
eba76848 841 if (aResult->GetRowCount() == 0) {
2bb7b766 842 Log("SHUTTLE", Form("QueryRunParameters - No entry in DAQ Logbook for run %d. Skipping", run));
843 delete aResult;
eba76848 844 return 0;
2bb7b766 845 }
846
eba76848 847 if (aResult->GetRowCount() > 1) {
2bb7b766 848 AliError(Form("More than one entry in DAQ Logbook for run %d. Skipping", run));
849 delete aResult;
eba76848 850 return 0;
2bb7b766 851 }
852
eba76848 853 TSQLRow* aRow = aResult->Next();
854 if (!aRow)
855 {
856 AliError(Form("Could not retrieve row for run %d. Skipping", run));
857 delete aResult;
858 return 0;
859 }
2bb7b766 860
eba76848 861 AliShuttleLogbookEntry* entry = new AliShuttleLogbookEntry(run);
2bb7b766 862
eba76848 863 for (Int_t ii = 0; ii < aResult->GetFieldCount(); ii++)
864 entry->SetRunParameter(aResult->GetFieldName(ii), aRow->GetField(ii));
2bb7b766 865
eba76848 866 UInt_t startTime = entry->GetStartTime();
867 UInt_t endTime = entry->GetEndTime();
868
869 if (!startTime || !endTime || startTime > endTime) {
870 Log("SHUTTLE",
871 Form("QueryRunParameters - Invalid parameters for Run %d: startTime = %d, endTime = %d",
872 run, startTime, endTime));
873 delete entry;
2bb7b766 874 delete aRow;
eba76848 875 delete aResult;
876 return 0;
2bb7b766 877 }
878
eba76848 879 delete aRow;
2bb7b766 880 delete aResult;
eba76848 881
882 return entry;
2bb7b766 883}
884
885//______________________________________________________________________________________________
886Bool_t AliShuttle::TryToStoreAgain()
887{
888 // Called in case the detector failed to store the object in Grid OCDB
889 // It tries to store the object again, if it does not find more recent and overlapping objects
890 // Calls underlying TryToStoreAgain(const char*) function twice, for OCDB and Reference storage.
891
892 AliInfo("Trying to store OCDB data again...");
893 Bool_t resultCDB = TryToStoreAgain(fgkMainCDB);
894
895 AliInfo("Trying to store reference data again...");
896 Bool_t resultRef = TryToStoreAgain(fgkMainRefStorage);
897
898 return resultCDB && resultRef;
899}
900
901//______________________________________________________________________________________________
902Bool_t AliShuttle::TryToStoreAgain(TString& gridURI)
903{
904 // Called by TryToStoreAgain(), performs actual storage retry
905
6ec0e06c 906 TObjArray* gridIds=0;
2bb7b766 907
908 Bool_t result = kTRUE;
909
910 const char* type = 0;
911 TString backupURI;
912 if(gridURI == fgkMainCDB) {
913 type = "OCDB";
914 backupURI = fgkLocalCDB;
915 } else if(gridURI == fgkMainRefStorage) {
916 type = "reference";
917 backupURI = fgkLocalRefStorage;
918 } else {
919 AliError(Form("Invalid storage URI: %s", gridURI.Data()));
920 return kFALSE;
921 }
922
923 AliCDBManager* man = AliCDBManager::Instance();
924
925 AliCDBStorage *gridSto = man->GetStorage(gridURI);
926 if(!gridSto) {
927 Log(fCurrentDetector.Data(),
928 Form("TryToStoreAgain - cannot activate main %s storage", type));
929 return kFALSE;
930 }
931
932 gridIds = gridSto->GetQueryCDBList();
933
934 // get objects previously stored in local CDB
935 AliCDBStorage *backupSto = man->GetStorage(backupURI);
eba76848 936 AliCDBPath aPath(GetOfflineDetName(fCurrentDetector.Data()),"*","*");
2bb7b766 937 // Local objects were stored with current run as Grid version!
938 TList* localEntries = backupSto->GetAll(aPath.GetPath(), GetCurrentRun(), GetCurrentRun());
939 localEntries->SetOwner(1);
940
941 // loop on local stored objects
942 TIter localIter(localEntries);
943 AliCDBEntry *aLocEntry = 0;
944 while((aLocEntry = dynamic_cast<AliCDBEntry*> (localIter.Next()))){
945 aLocEntry->SetOwner(1);
946 AliCDBId aLocId = aLocEntry->GetId();
947 aLocEntry->SetVersion(-1);
948 aLocEntry->SetSubVersion(-1);
949
950 // loop on Grid valid Id's
951 Bool_t store = kTRUE;
952 TIter gridIter(gridIds);
953 AliCDBId* aGridId = 0;
954 while((aGridId = dynamic_cast<AliCDBId*> (gridIter.Next()))){
955 // If local object is valid up to infinity we store it anyway
956 // TODO This does not work! It may hide more recent objects...
957 if(aLocId.GetLastRun() == AliCDBRunRange::Infinity()) {
958 // TODO Check that it won't hide more recent files! how????
959 break;
960 }
961 if(aGridId->GetPath() != aLocId.GetPath()) continue;
962 // skip all objects valid up to infinity
963 if(aGridId->GetLastRun() == AliCDBRunRange::Infinity()) continue;
964 // if we get here, it means there's already some more recent object stored on Grid!
965 store = kFALSE;
966 break;
967 }
968
969 if(!store){
970 Log(fCurrentDetector.Data(),
971 Form("TryToStoreAgain - A more recent object already exists in %s storage: <%s>",
972 type, aGridId->ToString().Data()));
973 // removing local filename...
974 // TODO maybe it's better not to remove it, it was not copied to the Grid!
975 TString filename;
976 backupSto->IdToFilename(aLocId, filename);
977 AliInfo(Form("Removing local file %s", filename.Data()));
978 gSystem->Exec(Form("rm %s",filename.Data()));
979 continue;
980 }
981
982 // If we get here, the file can be stored!
983 Bool_t storeOk = gridSto->Put(aLocEntry);
984 if(storeOk){
985 Log(fCurrentDetector.Data(),
986 Form("TryToStoreAgain - Object <%s> successfully put into %s storage",
987 aLocId.ToString().Data(), type));
988
989 // removing local filename...
990 TString filename;
991 backupSto->IdToFilename(aLocId, filename);
992 AliInfo(Form("Removing local file %s", filename.Data()));
993 gSystem->Exec(Form("rm %s", filename.Data()));
994 continue;
995 } else {
996 Log(fCurrentDetector.Data(),
997 Form("TryToStoreAgain - Grid %s storage of object <%s> failed again",
998 type, aLocId.ToString().Data()));
999 result = kFALSE;
1000 }
1001 }
1002 localEntries->Clear();
1003
1004 return result;
73abe331 1005}
1006
b948db8d 1007//______________________________________________________________________________________________
73abe331 1008Bool_t AliShuttle::GetValueSet(const char* host, Int_t port, const char* alias,
2bb7b766 1009 TObjArray* valueSet)
73abe331 1010{
58bc3020 1011// Retrieve all "alias" data points from the DCS server
1012// host, port: TSocket connection parameters
1013// alias: name of the alias
2bb7b766 1014// valueSet: array of retrieved AliDCSValue's
58bc3020 1015
73abe331 1016 AliDCSClient client(host, port, fTimeout, fRetries);
1017 if (!client.IsConnected()) {
b948db8d 1018 return kFALSE;
73abe331 1019 }
1020
57f50b3c 1021 Int_t result = client.GetAliasValues(alias,
73abe331 1022 GetCurrentStartTime(), GetCurrentEndTime(), valueSet);
1023
1024 if (result < 0) {
2bb7b766 1025 Log(fCurrentDetector.Data(), Form("GetValueSet - Can't get '%s'! Reason: %s",
73abe331 1026 alias, AliDCSClient::GetErrorString(result)));
1027
1028 if (result == AliDCSClient::fgkServerError) {
2bb7b766 1029 Log(fCurrentDetector.Data(), Form("GetValueSet - Server error: %s",
73abe331 1030 client.GetServerError().Data()));
1031 }
1032
1033 return kFALSE;
1034 }
1035
1036 return kTRUE;
1037}
b948db8d 1038
1039//______________________________________________________________________________________________
57f50b3c 1040const char* AliShuttle::GetFile(Int_t system, const char* detector,
1041 const char* id, const char* source)
b948db8d 1042{
57f50b3c 1043// Get calibration file from file exchange servers
1044// calls specific getter according to system index (kDAQ, kDCS, kHLT)
1045
1046 switch(system){
1047 case kDAQ:
1048 return GetDAQFileName(detector, id, source);
1049 break;
1050 case kDCS:
1051 return GetDCSFileName(detector, id, source);
1052 break;
1053 case kHLT:
1054 return GetHLTFileName(detector, id, source);
1055 break;
1056 default:
1057 AliError(Form("No valid system index: %d",system));
1058 }
b948db8d 1059
b948db8d 1060 return 0;
1061}
1062
b948db8d 1063//______________________________________________________________________________________________
57f50b3c 1064TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
b948db8d 1065{
57f50b3c 1066// Get sources producing the condition file Id from file exchange servers
1067// calls specific getter according to system index (kDAQ, kDCS, kHLT)
1068
1069 switch(system){
1070 case kDAQ:
1071 return GetDAQFileSources(detector, id);
1072 break;
1073 case kDCS:
1074 return GetDCSFileSources(detector, id);
1075 break;
1076 case kHLT:
1077 return GetHLTFileSources(detector, id);
1078 break;
1079 default:
1080 AliError(Form("No valid system index: %d",system));
1081 }
1082
1083 return NULL;
1084}
1085
1086//______________________________________________________________________________________________
2bb7b766 1087Bool_t AliShuttle::Connect(Int_t system)
1088{
57f50b3c 1089// Connect to MySQL Server of the system's FES logbook
2bb7b766 1090// DAQ Logbook, Shuttle Logbook and DAQ FES Logbook are on the same host
57f50b3c 1091
1092 // check connection: if already connected return
1093 if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
1094
1095 TString aFESlbHost= Form("mysql://%s", fConfig->GetFESlbHost(system));
1096
1097 fServer[system] = TSQLServer::Connect(aFESlbHost,
1098 fConfig->GetFESlbUser(system),
1099 fConfig->GetFESlbPass(system));
1100 if (!fServer[system] || !fServer[system]->IsConnected()) {
eba76848 1101 AliError(Form("Can't establish connection to FES logbook for %s",
1102 AliShuttleInterface::GetSystemName(system)));
2bb7b766 1103 if(fServer[system]) delete fServer[system];
57f50b3c 1104 return kFALSE;
1105 }
1106
1107 // Get tables
1108 // TODO in the configuration should the table name be there too?
2bb7b766 1109 TSQLResult* aResult=0;
57f50b3c 1110 switch(system){
1111 case kDAQ:
2bb7b766 1112 aResult = fServer[kDAQ]->GetTables("REFSYSLOG");
57f50b3c 1113 break;
1114 case kDCS:
2bb7b766 1115 //aResult = fServer[kDCS]->GetTables("REFSYSLOG");
57f50b3c 1116 break;
1117 case kHLT:
2bb7b766 1118 //aResult = fServer[kHLT]->GetTables("REFSYSLOG");
57f50b3c 1119 break;
1120 default:
1121 break;
1122 }
1123
2bb7b766 1124 delete aResult;
57f50b3c 1125 return kTRUE;
1126}
1127
1128//______________________________________________________________________________________________
2bb7b766 1129const char* AliShuttle::GetDAQFileName(const char* detector, const char* id, const char* source)
1130{
57f50b3c 1131// Retrieves a file from the DAQ FES.
1132// First queris the DAQ logbook_fs for the DAQ file name, using the run, detector, id and source info
1133// then calls RetrieveDAQFile(DAQfilename) for actual copy to local disk
2bb7b766 1134// run: current run being processed (given by Logbook entry fLogbookEntry)
eba76848 1135// detector: the Preprocessor name
57f50b3c 1136// id: provided as a parameter by the Preprocessor
1137// source: provided by the Preprocessor through GetFileSources function
1138
1139 // check connection, in case connect
eba76848 1140 if (!Connect(kDAQ))
1141 {
2bb7b766 1142 Log(detector, "GetDAQFileName - Couldn't connect to DAQ Logbook");
57f50b3c 1143 return 0;
1144 }
1145
1146 // Query preparation
1147 TString sqlQueryStart = "select filePath from logbook_fs where";
1148 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\"",
eba76848 1149 GetCurrentRun(), detector, id, source);
57f50b3c 1150 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
1151
84090f85 1152 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
57f50b3c 1153
1154 // Query execution
2bb7b766 1155 TSQLResult* aResult = 0;
1156 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
57f50b3c 1157 if (!aResult) {
2bb7b766 1158 Log(detector, Form("GetDAQFileName - Can't execute SQL query for: id = %s, source = %s",
1159 id, source));
57f50b3c 1160 return 0;
1161 }
1162
eba76848 1163 if(aResult->GetRowCount() == 0)
1164 {
57f50b3c 1165 Log(detector,
2bb7b766 1166 Form("GetDAQFileName - No entry in FES table for: id = %s, source = %s",
1167 id, source));
57f50b3c 1168 delete aResult;
1169 return 0;
1170 }
1171
eba76848 1172 if (aResult->GetRowCount() > 1) {
57f50b3c 1173 Log(detector,
2bb7b766 1174 Form("GetDAQFileName - More than one entry in FES table for: id = %s, source = %s",
1175 id, source));
57f50b3c 1176 delete aResult;
1177 return 0;
1178 }
1179
2bb7b766 1180 TSQLRow* aRow = dynamic_cast<TSQLRow*> (aResult->Next());
57f50b3c 1181
eba76848 1182 if (!aRow){
2bb7b766 1183 Log(detector, Form("GetDAQFileName - Empty set result from query: id = %s, source = %s",
1184 id, source));
57f50b3c 1185 delete aResult;
1186 return 0;
1187 }
1188
1189 TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
1190
1191 delete aResult;
2bb7b766 1192 delete aRow;
57f50b3c 1193
84090f85 1194 AliDebug(2, Form("filePath = %s",filePath.Data()));
57f50b3c 1195
1196 // retrieved file is renamed to make it unique
1197 TString localFileName = Form("%s_%d_%s_%s.shuttle",
2bb7b766 1198 detector, GetCurrentRun(), id, source);
57f50b3c 1199
1200 // file retrieval from DAQ FES
1201 Bool_t result = RetrieveDAQFile(filePath.Data(), localFileName.Data());
1202 if(!result) {
2bb7b766 1203 Log(detector, Form("GetDAQFileName - Copy of file %s from DAQ FES failed", filePath.Data()));
57f50b3c 1204 return 0;
1205 } else {
2bb7b766 1206 AliInfo(Form("File %s copied from DAQ FES into %s/%s",
57f50b3c 1207 filePath.Data(), fgkShuttleTempDir, localFileName.Data()));
1208 }
1209
1210
1211 fFESCalled[kDAQ]=kTRUE;
1212 TObjString *fileParams = new TObjString(Form("%s_!?!_%s", id, source));
1213 fFESlist[kDAQ].Add(fileParams);
1214
1215 return localFileName.Data();
1216
1217}
1218
1219//______________________________________________________________________________________________
2bb7b766 1220Bool_t AliShuttle::RetrieveDAQFile(const char* daqFileName, const char* localFileName)
1221{
57f50b3c 1222
1223 // check temp directory: trying to cd to temp; if it does not exist, create it
84090f85 1224 AliDebug(2, Form("Copy file %s from DAQ FES into folder %s and rename it as %s",
57f50b3c 1225 daqFileName,fgkShuttleTempDir, localFileName));
1226
1227 void* dir = gSystem->OpenDirectory(fgkShuttleTempDir);
1228 if (dir == NULL) {
1229 if (gSystem->mkdir(fgkShuttleTempDir, kTRUE)) {
2bb7b766 1230 AliError(Form("Can't open directory <%s>", fgkShuttleTempDir));
57f50b3c 1231 return kFALSE;
1232 }
1233
1234 } else {
1235 gSystem->FreeDirectory(dir);
1236 }
1237
1238 TString baseDAQFESFolder = "DAQ";
1239 TString command = Form("scp %s@%s:%s/%s %s/%s",
1240 fConfig->GetFESUser(kDAQ),
1241 fConfig->GetFESHost(kDAQ),
1242 baseDAQFESFolder.Data(),
1243 daqFileName,
1244 fgkShuttleTempDir,
1245 localFileName);
1246
84090f85 1247 AliDebug(2, Form("%s",command.Data()));
57f50b3c 1248
1249 UInt_t nRetries = 0;
1250 UInt_t maxRetries = 3;
1251
1252 // copy!! if successful TSystem::Exec returns 0
1253 while(nRetries++ < maxRetries) {
84090f85 1254 AliDebug(2, Form("Trying to copy file. Retry # %d", nRetries));
57f50b3c 1255 if(gSystem->Exec(command.Data()) == 0) return kTRUE;
1256 }
1257
1258 return kFALSE;
1259
1260}
1261
1262//______________________________________________________________________________________________
2bb7b766 1263TList* AliShuttle::GetDAQFileSources(const char* detector, const char* id)
1264{
57f50b3c 1265// Retrieves a file from the DCS FES.
1266
1267 // check connection, in case connect
1268 if(!Connect(kDAQ)){
2bb7b766 1269 Log(detector, "GetDAQFileSources - Couldn't connect to DAQ Logbook");
57f50b3c 1270 return 0;
1271 }
1272
1273 // Query preparation
1274 TString sqlQueryStart = "select DAQsource from logbook_fs where";
1275 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
eba76848 1276 GetCurrentRun(), detector, id);
57f50b3c 1277 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
1278
84090f85 1279 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
57f50b3c 1280
1281 // Query execution
1282 TSQLResult* aResult;
1283 aResult = fServer[kDAQ]->Query(sqlQuery);
1284 if (!aResult) {
2bb7b766 1285 Log(detector, Form("GetDAQFileSources - Can't execute SQL query for id: %s", id));
57f50b3c 1286 return 0;
1287 }
1288
1289 if (aResult->GetRowCount() == 0) {
1290 Log(detector,
2bb7b766 1291 Form("GetDAQFileSources - No entry in FES table for id: %s", id));
57f50b3c 1292 delete aResult;
1293 return 0;
1294 }
1295
1296 TSQLRow* aRow;
1297 TList *list = new TList();
1298 list->SetOwner(1);
1299
1300 while((aRow = aResult->Next())){
1301
1302 TString daqSource(aRow->GetField(0), aRow->GetFieldLength(0));
84090f85 1303 AliDebug(2, Form("daqSource = %s", daqSource.Data()));
57f50b3c 1304 list->Add(new TObjString(daqSource));
2bb7b766 1305 delete aRow;
57f50b3c 1306 }
1307 delete aResult;
1308
1309 return list;
1310
1311}
1312
1313//______________________________________________________________________________________________
2bb7b766 1314const char* AliShuttle::GetDCSFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
1315// Retrieves a file from the DCS FES.
1316
1317return "You're in DCS";
1318
1319}
1320
1321//______________________________________________________________________________________________
1322TList* AliShuttle::GetDCSFileSources(const char* /*detector*/, const char* /*id*/){
1323// Retrieves a file from the DCS FES.
1324
1325return NULL;
1326
1327}
1328
1329//______________________________________________________________________________________________
1330const char* AliShuttle::GetHLTFileName(const char* /*detector*/, const char* /*id*/, const char* /*source*/){
1331// Retrieves a file from the HLT FES.
1332
1333return "You're in HLT";
1334
1335}
1336
1337//______________________________________________________________________________________________
1338TList* AliShuttle::GetHLTFileSources(const char* /*detector*/, const char* /*id*/){
1339// Retrieves a file from the HLT FES.
1340
1341return NULL;
1342
1343}
1344
1345//______________________________________________________________________________________________
1346Bool_t AliShuttle::UpdateDAQTable()
1347{
57f50b3c 1348// Update DAQ table filling time_processed field in all rows corresponding to current run and detector
1349
1350 // check connection, in case connect
1351 if(!Connect(kDAQ)){
2bb7b766 1352 Log(fCurrentDetector, "UpdateDAQTable - Couldn't connect to DAQ Logbook");
57f50b3c 1353 return kFALSE;
1354 }
1355
1356 TTimeStamp now; // now
1357
1358 // Loop on FES list entries
1359 TIter iter(&fFESlist[kDAQ]);
1360 TObjString *aFESentry=0;
1361 while((aFESentry = dynamic_cast<TObjString*> (iter.Next()))){
1362 TString aFESentrystr = aFESentry->String();
1363 TObjArray *aFESarray = aFESentrystr.Tokenize("_!?!_");
1364 if(!aFESarray || aFESarray->GetEntries() != 2 ) {
2bb7b766 1365 Log(fCurrentDetector, Form("UpdateDAQTable - error updating FES entry. Check string: <%s>",
57f50b3c 1366 aFESentrystr.Data()));
1367 if(aFESarray) delete aFESarray;
1368 return kFALSE;
1369 }
1370 const char* fileId = ((TObjString*) aFESarray->At(0))->GetName();
1371 const char* daqSource = ((TObjString*) aFESarray->At(1))->GetName();
1372 TString whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\";",
eba76848 1373 GetCurrentRun(), fCurrentDetector.Data(), fileId, daqSource);
57f50b3c 1374
1375 delete aFESarray;
1376
1377 TString sqlQuery = Form("update logbook_fs set time_processed=%d %s", now.GetSec(), whereClause.Data());
1378
84090f85 1379 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
57f50b3c 1380
1381 // Query execution
1382 TSQLResult* aResult;
1383 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
1384 if (!aResult) {
2bb7b766 1385 Log(fCurrentDetector, Form("UpdateDAQTable - Can't execute SQL query <%s>", sqlQuery.Data()));
57f50b3c 1386 return kFALSE;
1387 }
1388 delete aResult;
2bb7b766 1389 }
57f50b3c 1390
2bb7b766 1391 return kTRUE;
1392}
57f50b3c 1393
57f50b3c 1394
2bb7b766 1395//______________________________________________________________________________________________
1396Bool_t AliShuttle::UpdateShuttleLogbook(const char* detector, const char* status)
1397{
1398// Update Shuttle logbook filling detector or shuttle_done column
1399// ex. of usage: UpdateShuttleLogbook("PHOS", "DONE") or UpdateShuttleLogbook("shuttle_done")
57f50b3c 1400
2bb7b766 1401 // check connection, in case connect
1402 if(!Connect(kDAQ)){
1403 Log("SHUTTLE", "UpdateShuttleLogbook - Couldn't connect to DAQ Logbook.");
1404 return kFALSE;
57f50b3c 1405 }
1406
2bb7b766 1407 TString detName(detector);
1408 TString setClause;
1409 if(detName == "shuttle_done") {
1410 setClause = "set shuttle_done=1";
1411 } else {
2bb7b766 1412 TString statusStr(status);
1413 if(statusStr.Contains("done", TString::kIgnoreCase) ||
1414 statusStr.Contains("failed", TString::kIgnoreCase)){
eba76848 1415 setClause = Form("set %s=\"%s\"", detector, status);
2bb7b766 1416 } else {
1417 Log("SHUTTLE",
1418 Form("UpdateShuttleLogbook - Invalid status <%s> for detector %s",
1419 status, detector));
1420 return kFALSE;
1421 }
1422 }
57f50b3c 1423
2bb7b766 1424 TString whereClause = Form("where run=%d", GetCurrentRun());
1425
1426 TString sqlQuery = Form("update logbook_shuttle %s %s",
1427 setClause.Data(), whereClause.Data());
57f50b3c 1428
2bb7b766 1429 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
1430
1431 // Query execution
1432 TSQLResult* aResult;
1433 aResult = dynamic_cast<TSQLResult*> (fServer[kDAQ]->Query(sqlQuery));
1434 if (!aResult) {
1435 Log("SHUTTLE", Form("UpdateShuttleLogbook - Can't execute query <%s>", sqlQuery.Data()));
1436 return kFALSE;
57f50b3c 1437 }
2bb7b766 1438 delete aResult;
57f50b3c 1439
1440 return kTRUE;
1441}
1442
1443//______________________________________________________________________________________________
2bb7b766 1444Int_t AliShuttle::GetCurrentRun() const
1445{
1446// Get current run from logbook entry
57f50b3c 1447
2bb7b766 1448 return fLogbookEntry ? fLogbookEntry->GetRun() : -1;
57f50b3c 1449}
1450
1451//______________________________________________________________________________________________
2bb7b766 1452UInt_t AliShuttle::GetCurrentStartTime() const
1453{
1454// get current start time
57f50b3c 1455
2bb7b766 1456 return fLogbookEntry ? fLogbookEntry->GetStartTime() : 0;
57f50b3c 1457}
1458
1459//______________________________________________________________________________________________
2bb7b766 1460UInt_t AliShuttle::GetCurrentEndTime() const
1461{
1462// get current end time from logbook entry
57f50b3c 1463
2bb7b766 1464 return fLogbookEntry ? fLogbookEntry->GetEndTime() : 0;
57f50b3c 1465}
1466
1467//______________________________________________________________________________________________
b948db8d 1468void AliShuttle::Log(const char* detector, const char* message)
1469{
58bc3020 1470// Fill log string with a message
b948db8d 1471
84090f85 1472 void* dir = gSystem->OpenDirectory(fgkShuttleLogDir);
1473 if (dir == NULL) {
1474 if (gSystem->mkdir(fgkShuttleLogDir, kTRUE)) {
2bb7b766 1475 AliError(Form("Can't open directory <%s>", fgkShuttleTempDir));
84090f85 1476 return;
1477 }
b948db8d 1478
84090f85 1479 } else {
1480 gSystem->FreeDirectory(dir);
1481 }
b948db8d 1482
cb343cfd 1483 TString toLog = Form("%s (%d): %s - ", TTimeStamp(time(0)).AsString("s"), getpid(), detector);
2bb7b766 1484 if(GetCurrentRun()>=0 ) toLog += Form("run %d - ", GetCurrentRun());
1485 toLog += Form("%s", message);
1486
84090f85 1487 AliInfo(toLog.Data());
b948db8d 1488
84090f85 1489 TString fileName;
1490 fileName.Form("%s/%s.log", fgkShuttleLogDir, detector);
1491 gSystem->ExpandPathName(fileName);
1492
1493 ofstream logFile;
1494 logFile.open(fileName, ofstream::out | ofstream::app);
1495
1496 if (!logFile.is_open()) {
1497 AliError(Form("Could not open file %s", fileName.Data()));
1498 return;
1499 }
7bfb2090 1500
84090f85 1501 logFile << toLog.Data() << "\n";
b948db8d 1502
84090f85 1503 logFile.close();
b948db8d 1504}
2bb7b766 1505
2bb7b766 1506//______________________________________________________________________________________________
1507Bool_t AliShuttle::Collect(Int_t run)
1508{
eba76848 1509//
1510// Collects conditions data for all UNPROCESSED run written to DAQ LogBook in case of run = -1 (default)
1511// If a dedicated run is given this run is processed
1512//
1513// In operational mode, this is the Shuttle function triggered by the EOR signal.
1514//
2bb7b766 1515
eba76848 1516 if (run == -1)
1517 Log("SHUTTLE","Collect - Shuttle called. Collecting conditions data for unprocessed runs");
1518 else
1519 Log("SHUTTLE", Form("Collect - Shuttle called. Collecting conditions data for run %d", run));
cb343cfd 1520
1521 SetLastAction("Starting");
2bb7b766 1522
1523 TString whereClause("where shuttle_done=0");
eba76848 1524 if (run != -1)
1525 whereClause += Form(" and run=%d", run);
2bb7b766 1526
1527 TObjArray shuttleLogbookEntries;
1528 if (!QueryShuttleLogbook(whereClause, shuttleLogbookEntries)) {
cb343cfd 1529 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2bb7b766 1530 return kFALSE;
1531 }
1532
1533 if (!RetrieveConditionsData(shuttleLogbookEntries)) {
cb343cfd 1534 Log("SHUTTLE", "Collect - Process of at least one run failed");
2bb7b766 1535 return kFALSE;
1536 }
1537
eba76848 1538 return kTRUE;
2bb7b766 1539}
1540
2bb7b766 1541//______________________________________________________________________________________________
1542Bool_t AliShuttle::RetrieveConditionsData(const TObjArray& dateEntries)
1543{
1544// Retrieve conditions data for all runs that aren't processed yet
1545
1546 Bool_t hasError = kFALSE;
1547
1548 TIter iter(&dateEntries);
1549 AliShuttleLogbookEntry* anEntry;
1550
1551 while ((anEntry = (AliShuttleLogbookEntry*) iter.Next())){
1552 if (!Process(anEntry)){
1553 hasError = kTRUE;
1554 }
1555 }
1556
1557 return hasError == kFALSE;
1558}
cb343cfd 1559
1560//______________________________________________________________________________________________
1561ULong_t AliShuttle::GetTimeOfLastAction() const
1562{
1563 ULong_t tmp;
1564
1565 fMonitoringMutex->Lock();
1566
1567 tmp = fLastActionTime;
1568
1569 fMonitoringMutex->UnLock();
1570
1571 return tmp;
1572}
1573
1574//______________________________________________________________________________________________
1575const TString AliShuttle::GetLastAction() const
1576{
1577 // returns a string description of the last action
1578
1579 TString tmp;
1580
1581 fMonitoringMutex->Lock();
1582
1583 tmp = fLastAction;
1584
1585 fMonitoringMutex->UnLock();
1586
1587 return tmp;
1588}
1589
1590//______________________________________________________________________________________________
1591void AliShuttle::SetLastAction(const char* action)
1592{
1593 // updates the monitoring variables
1594
1595 fMonitoringMutex->Lock();
1596
1597 fLastAction = action;
1598 fLastActionTime = time(0);
1599
1600 fMonitoringMutex->UnLock();
1601}
eba76848 1602
1603//______________________________________________________________________________________________
1604const char* AliShuttle::GetRunParameter(const char* param)
1605{
1606// returns run parameter read from DAQ logbook
1607
1608 if(!fLogbookEntry) {
1609 AliError("No logbook entry!");
1610 return 0;
1611 }
1612
1613 return fLogbookEntry->GetRunParameter(param);
1614}