1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 Revision 1.62 2007/10/31 18:23:13 acolla
19 Furter developement on the Shuttle:
21 - Shuttle now connects to the Grid as alidaq. The OCDB and Reference folders
22 are now built from /alice/data, e.g.:
23 /alice/data/2007/LHC07a/OCDB
25 the year and LHC period are taken from the Shuttle.
26 Raw metadata files are stored by GRP to:
27 /alice/data/2007/LHC07a/<runNb>/Raw/RunMetadata.root
29 - Shuttle sends a mail to DCS experts each time DP retrieval fails.
31 Revision 1.61 2007/10/30 20:33:51 acolla
32 Improved managing of temporary folders, which weren't correctly handled.
33 Resolved bug introduced in StoreReferenceFile, which caused SPD preprocessor fail.
35 Revision 1.60 2007/10/29 18:06:16 acolla
37 New function StoreRunMetadataFile added to preprocessor and Shuttle interface
38 This function can be used by GRP only. It stores raw data tags merged file to the
39 raw data folder (e.g. /alice/data/2008/LHC08a/000099999/Raw).
43 1. Shuttle cannot write to /alice/data/ because it belongs to alidaq. Tag file is stored in /alice/simulation/... for the time being.
44 2. Due to a bug in TAlien::Mkdir, the creation of a folder in recursive mode (-p option) does not work. The problem
45 has been corrected in the root package on the Shuttle machine.
47 Revision 1.59 2007/10/05 12:40:55 acolla
49 Result error code added to AliDCSClient data members (it was "lost" with the new implementation of TMap* GetAliasValues and GetDPValues).
51 Revision 1.58 2007/09/28 15:27:40 acolla
53 AliDCSClient "multiSplit" option added in the DCS configuration
54 in AliDCSMessage: variable MAX_BODY_SIZE set to 500000
56 Revision 1.57 2007/09/27 16:53:13 acolla
57 Detectors can have more than one AMANDA server. SHUTTLE queries the servers sequentially,
58 merges the dcs aliases/DPs in one TMap and sends it to the preprocessor.
60 Revision 1.56 2007/09/14 16:46:14 jgrosseo
61 1) Connect and Close are called before and after each query, so one can
62 keep the same AliDCSClient object.
63 2) The splitting of a query is moved to GetDPValues/GetAliasValues.
64 3) Splitting interval can be specified in constructor
66 Revision 1.55 2007/08/06 12:26:40 acolla
67 Function Bool_t GetHLTStatus added to preprocessor. It returns the status of HLT
68 read from the run logbook.
70 Revision 1.54 2007/07/12 09:51:25 jgrosseo
71 removed duplicated log message in GetFile
73 Revision 1.53 2007/07/12 09:26:28 jgrosseo
74 updating hlt fxs base path
76 Revision 1.52 2007/07/12 08:06:45 jgrosseo
77 adding log messages in getfile... functions
78 adding not implemented copy constructor in alishuttleconfigholder
80 Revision 1.51 2007/07/03 17:24:52 acolla
81 root moved to v5-16-00. TFileMerger->Cp moved to TFile::Cp.
83 Revision 1.50 2007/07/02 17:19:32 acolla
84 preprocessor is run in a temp directory that is removed when process is finished.
86 Revision 1.49 2007/06/29 10:45:06 acolla
87 Number of columns in MySql Shuttle logbook increased by one (HLT added)
89 Revision 1.48 2007/06/21 13:06:19 acolla
90 GetFileSources returns dummy list with 1 source if system=DCS (better than
91 returning error as it was)
93 Revision 1.47 2007/06/19 17:28:56 acolla
94 HLT updated; missing map bug removed.
96 Revision 1.46 2007/06/09 13:01:09 jgrosseo
97 Switching to retrieval of several DCS DPs at a time (multiDPrequest)
99 Revision 1.45 2007/05/30 06:35:20 jgrosseo
100 Adding functionality to the Shuttle/TestShuttle:
101 o) Function to retrieve list of sources from a given system (GetFileSources with id=0)
102 o) Function to retrieve list of IDs for a given source (GetFileIDs)
103 These functions are needed for dealing with the tag files that are saved for the GRP preprocessor
104 Example code has been added to the TestProcessor in TestShuttle
106 Revision 1.44 2007/05/11 16:09:32 acolla
107 Reference files for ITS, MUON and PHOS are now stored in OfflineDetName/OnlineDetName/run_...
108 example: ITS/SPD/100_filename.root
110 Revision 1.43 2007/05/10 09:59:51 acolla
111 Various bug fixes in StoreRefFilesToGrid; Cleaning of reference storage before processing detector (CleanReferenceStorage)
113 Revision 1.42 2007/05/03 08:01:39 jgrosseo
114 typo in last commit :-(
116 Revision 1.41 2007/05/03 08:00:48 jgrosseo
117 fixing log message when pp want to skip dcs value retrieval
119 Revision 1.40 2007/04/27 07:06:48 jgrosseo
120 GetFileSources returns empty list in case of no files, but successful query
121 No mails sent in testmode
123 Revision 1.39 2007/04/17 12:43:57 acolla
124 Correction in StoreOCDB; change of text in mail to detector expert
126 Revision 1.38 2007/04/12 08:26:18 jgrosseo
129 Revision 1.37 2007/04/10 16:53:14 jgrosseo
130 redirecting sub detector stdout, stderr to sub detector log file
132 Revision 1.35 2007/04/04 16:26:38 acolla
133 1. Re-organization of function calls in TestPreprocessor to make it more meaningful.
134 2. Added missing dependency in test preprocessors.
135 3. in AliShuttle.cxx: processing time and memory consumption info on a single line.
137 Revision 1.34 2007/04/04 10:33:36 jgrosseo
138 1) Storing of files to the Grid is now done _after_ your preprocessors succeeded. This is transparent, which means that you can still use the same functions (Store, StoreReferenceData) to store files to the Grid. However, the Shuttle first stores them locally and transfers them after the preprocessor finished. The return code of these two functions has changed from UInt_t to Bool_t which gives you the success of the storing.
139 In case of an error with the Grid, the Shuttle will retry the storing later, the preprocessor does not need to be run again.
141 2) The meaning of the return code of the preprocessor has changed. 0 is now success and any other value means failure. This value is stored in the log and you can use it to keep details about the error condition.
143 3) New function StoreReferenceFile to _directly_ store a file (without opening it) to the reference storage.
145 4) The memory usage of the preprocessor is monitored. If it exceeds 2 GB it is terminated.
147 5) New function AliPreprocessor::ProcessDCS(). If you do not need to have DCS data in all cases, you can skip the processing by implemting this function and returning kFALSE under certain conditions. E.g. if there is a certain run type.
148 If you always need DCS data (like before), you do not need to implement it.
150 6) The run type has been added to the monitoring page
152 Revision 1.33 2007/04/03 13:56:01 acolla
153 Grid Storage at the end of preprocessing. Added virtual method to disable DCS query according to the
156 Revision 1.32 2007/02/28 10:41:56 acolla
157 Run type field added in SHUTTLE framework. Run type is read from "run type" logbook and retrieved by
158 AliPreprocessor::GetRunType() function.
159 Added some ldap definition files.
161 Revision 1.30 2007/02/13 11:23:21 acolla
162 Moved getters and setters of Shuttle's main OCDB/Reference, local
163 OCDB/Reference, temp and log folders to AliShuttleInterface
165 Revision 1.27 2007/01/30 17:52:42 jgrosseo
166 adding monalisa monitoring
168 Revision 1.26 2007/01/23 19:20:03 acolla
169 Removed old ldif files, added TOF, MCH ldif files. Added some options in
170 AliShuttleConfig::Print. Added in Ali Shuttle: SetShuttleTempDir and
173 Revision 1.25 2007/01/15 19:13:52 acolla
174 Moved some AliInfo to AliDebug in SendMail function
176 Revision 1.21 2006/12/07 08:51:26 jgrosseo
178 table, db names in ldap configuration
179 added GRP preprocessor
180 DCS data can also be retrieved by data point
182 Revision 1.20 2006/11/16 16:16:48 jgrosseo
183 introducing strict run ordering flag
184 removed giving preprocessor name to preprocessor, they have to know their name themselves ;-)
186 Revision 1.19 2006/11/06 14:23:04 jgrosseo
187 major update (Alberto)
188 o) reading of run parameters from the logbook
189 o) online offline naming conversion
190 o) standalone DCSclient package
192 Revision 1.18 2006/10/20 15:22:59 jgrosseo
193 o) Adding time out to the execution of the preprocessors: The Shuttle forks and the parent process monitors the child
194 o) Merging Collect, CollectAll, CollectNew function
195 o) Removing implementation of empty copy constructors (declaration still there!)
197 Revision 1.17 2006/10/05 16:20:55 jgrosseo
198 adapting to new CDB classes
200 Revision 1.16 2006/10/05 15:46:26 jgrosseo
201 applying to the new interface
203 Revision 1.15 2006/10/02 16:38:39 jgrosseo
206 storing of objects that failed to be stored to the grid before
207 interfacing of shuttle status table in daq system
209 Revision 1.14 2006/08/29 09:16:05 jgrosseo
212 Revision 1.13 2006/08/15 10:50:00 jgrosseo
213 effc++ corrections (alberto)
215 Revision 1.12 2006/08/08 14:19:29 jgrosseo
216 Update to shuttle classes (Alberto)
218 - Possibility to set the full object's path in the Preprocessor's and
219 Shuttle's Store functions
220 - Possibility to extend the object's run validity in the same classes
221 ("startValidity" and "validityInfinite" parameters)
222 - Implementation of the StoreReferenceData function to store reference
223 data in a dedicated CDB storage.
225 Revision 1.11 2006/07/21 07:37:20 jgrosseo
226 last run is stored after each run
228 Revision 1.10 2006/07/20 09:54:40 jgrosseo
229 introducing status management: The processing per subdetector is divided into several steps,
230 after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
231 can keep track of the number of failures and skips further processing after a certain threshold is
232 exceeded. These thresholds can be configured in LDAP.
234 Revision 1.9 2006/07/19 10:09:55 jgrosseo
235 new configuration, accesst to DAQ FES (Alberto)
237 Revision 1.8 2006/07/11 12:44:36 jgrosseo
238 adding parameters for extended validity range of data produced by preprocessor
240 Revision 1.7 2006/07/10 14:37:09 jgrosseo
241 small fix + todo comment
243 Revision 1.6 2006/07/10 13:01:41 jgrosseo
244 enhanced storing of last sucessfully processed run (alberto)
246 Revision 1.5 2006/07/04 14:59:57 jgrosseo
247 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
249 Revision 1.4 2006/06/12 09:11:16 jgrosseo
250 coding conventions (Alberto)
252 Revision 1.3 2006/06/06 14:26:40 jgrosseo
253 o) removed files that were moved to STEER
254 o) shuttle updated to follow the new interface (Alberto)
256 Revision 1.2 2006/03/07 07:52:34 hristov
257 New version (B.Yordanov)
259 Revision 1.6 2005/11/19 17:19:14 byordano
260 RetrieveDATEEntries and RetrieveConditionsData added
262 Revision 1.5 2005/11/19 11:09:27 byordano
263 AliShuttle declaration added
265 Revision 1.4 2005/11/17 17:47:34 byordano
266 TList changed to TObjArray
268 Revision 1.3 2005/11/17 14:43:23 byordano
271 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
272 Initial import as subdirectory in AliRoot
274 Revision 1.2 2005/09/13 08:41:15 byordano
275 default startTime endTime added
277 Revision 1.4 2005/08/30 09:13:02 byordano
280 Revision 1.3 2005/08/29 21:15:47 byordano
286 // This class is the main manager for AliShuttle.
287 // It organizes the data retrieval from DCS and call the
288 // interface methods of AliPreprocessor.
289 // For every detector in AliShuttleConfgi (see AliShuttleConfig),
290 // data for its set of aliases is retrieved. If there is registered
291 // AliPreprocessor for this detector then it will be used
292 // accroding to the schema (see AliPreprocessor).
293 // If there isn't registered AliPreprocessor than the retrieved
294 // data is stored automatically to the undelying AliCDBStorage.
295 // For detSpec is used the alias name.
298 #include "AliShuttle.h"
300 #include "AliCDBManager.h"
301 #include "AliCDBStorage.h"
302 #include "AliCDBId.h"
303 #include "AliCDBRunRange.h"
304 #include "AliCDBPath.h"
305 #include "AliCDBEntry.h"
306 #include "AliShuttleConfig.h"
307 #include "DCSClient/AliDCSClient.h"
309 #include "AliPreprocessor.h"
310 #include "AliShuttleStatus.h"
311 #include "AliShuttleLogbookEntry.h"
316 #include <TTimeStamp.h>
317 #include <TObjString.h>
318 #include <TSQLServer.h>
319 #include <TSQLResult.h>
322 #include <TSystemDirectory.h>
323 #include <TSystemFile.h>
326 #include <TGridResult.h>
328 #include <TMonaLisaWriter.h>
332 #include <sys/types.h>
333 #include <sys/wait.h>
337 //______________________________________________________________________________________________
338 AliShuttle::AliShuttle(const AliShuttleConfig* config,
339 UInt_t timeout, Int_t retries):
341 fTimeout(timeout), fRetries(retries),
351 fReadTestMode(kFALSE),
352 fOutputRedirected(kFALSE)
355 // config: AliShuttleConfig used
356 // timeout: timeout used for AliDCSClient connection
357 // retries: the number of retries in case of connection error.
360 if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
361 for(int iSys=0;iSys<4;iSys++) {
364 fFXSlist[iSys].SetOwner(kTRUE);
366 fPreprocessorMap.SetOwner(kTRUE);
368 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
369 fFirstUnprocessed[iDet] = kFALSE;
371 fMonitoringMutex = new TMutex();
374 //______________________________________________________________________________________________
375 AliShuttle::~AliShuttle()
381 fPreprocessorMap.DeleteAll();
382 for(int iSys=0;iSys<4;iSys++)
384 fServer[iSys]->Close();
385 delete fServer[iSys];
394 if (fMonitoringMutex)
396 delete fMonitoringMutex;
397 fMonitoringMutex = 0;
401 //______________________________________________________________________________________________
402 void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
405 // Registers new AliPreprocessor.
406 // It uses GetName() for indentificator of the pre processor.
407 // The pre processor is registered it there isn't any other
408 // with the same identificator (GetName()).
411 const char* detName = preprocessor->GetName();
412 if(GetDetPos(detName) < 0)
413 AliFatal(Form("********** !!!!! Invalid detector name: %s !!!!! **********", detName));
415 if (fPreprocessorMap.GetValue(detName)) {
416 AliWarning(Form("AliPreprocessor %s is already registered!", detName));
420 fPreprocessorMap.Add(new TObjString(detName), preprocessor);
422 //______________________________________________________________________________________________
423 Bool_t AliShuttle::Store(const AliCDBPath& path, TObject* object,
424 AliCDBMetaData* metaData, Int_t validityStart, Bool_t validityInfinite)
426 // Stores a CDB object in the storage for offline reconstruction. Objects that are not needed for
427 // offline reconstruction, but should be stored anyway (e.g. for debugging) should NOT be stored
428 // using this function. Use StoreReferenceData instead!
429 // It calls StoreLocally function which temporarily stores the data locally; when the preprocessor
430 // finishes the data are transferred to the main storage (Grid).
432 return StoreLocally(fgkLocalCDB, path, object, metaData, validityStart, validityInfinite);
435 //______________________________________________________________________________________________
436 Bool_t AliShuttle::StoreReferenceData(const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData)
438 // Stores a CDB object in the storage for reference data. This objects will not be available during
439 // offline reconstrunction. Use this function for reference data only!
440 // It calls StoreLocally function which temporarily stores the data locally; when the preprocessor
441 // finishes the data are transferred to the main storage (Grid).
443 return StoreLocally(fgkLocalRefStorage, path, object, metaData);
446 //______________________________________________________________________________________________
447 Bool_t AliShuttle::StoreLocally(const TString& localUri,
448 const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData,
449 Int_t validityStart, Bool_t validityInfinite)
451 // Store object temporarily in local storage. Parameters are passed by Store and StoreReferenceData functions.
452 // when the preprocessor finishes the data are transferred to the main storage (Grid).
453 // The parameters are:
454 // 1) Uri of the backup storage (Local)
455 // 2) the object's path.
456 // 3) the object to be stored
457 // 4) the metaData to be associated with the object
458 // 5) the validity start run number w.r.t. the current run,
459 // if the data is valid only for this run leave the default 0
460 // 6) specifies if the calibration data is valid for infinity (this means until updated),
461 // typical for calibration runs, the default is kFALSE
463 // returns 0 if fail, 1 otherwise
465 if (fTestMode & kErrorStorage)
467 Log(fCurrentDetector, "StoreLocally - In TESTMODE - Simulating error while storing locally");
471 const char* cdbType = (localUri == fgkLocalCDB) ? "CDB" : "Reference";
473 Int_t firstRun = GetCurrentRun() - validityStart;
475 AliWarning("First valid run happens to be less than 0! Setting it to 0.");
480 if(validityInfinite) {
481 lastRun = AliCDBRunRange::Infinity();
483 lastRun = GetCurrentRun();
486 // Version is set to current run, it will be used later to transfer data to Grid
487 AliCDBId id(path, firstRun, lastRun, GetCurrentRun(), -1);
489 if(! dynamic_cast<TObjString*> (metaData->GetProperty("RunUsed(TObjString)"))){
490 TObjString runUsed = Form("%d", GetCurrentRun());
491 metaData->SetProperty("RunUsed(TObjString)", runUsed.Clone());
494 Bool_t result = kFALSE;
496 if (!(AliCDBManager::Instance()->GetStorage(localUri))) {
497 Log("SHUTTLE", Form("StoreLocally - Cannot activate local %s storage", cdbType));
499 result = AliCDBManager::Instance()->GetStorage(localUri)
500 ->Put(object, id, metaData);
505 Log(fCurrentDetector, Form("StoreLocally - Can't store object <%s>!", id.ToString().Data()));
511 //______________________________________________________________________________________________
512 Bool_t AliShuttle::StoreOCDB()
515 // Called when preprocessor ends successfully or when previous storage attempt failed (kStoreError status)
516 // Calls underlying StoreOCDB(const char*) function twice, for OCDB and Reference storage.
517 // Then calls StoreRefFilesToGrid to store reference files.
520 if (fTestMode & kErrorGrid)
522 Log("SHUTTLE", "StoreOCDB - In TESTMODE - Simulating error while storing in the Grid");
523 Log(fCurrentDetector, "StoreOCDB - In TESTMODE - Simulating error while storing in the Grid");
527 Log("SHUTTLE","StoreOCDB - Storing OCDB data ...");
528 Bool_t resultCDB = StoreOCDB(fgkMainCDB);
530 Log("SHUTTLE","StoreOCDB - Storing reference data ...");
531 Bool_t resultRef = StoreOCDB(fgkMainRefStorage);
533 Log("SHUTTLE","StoreOCDB - Storing reference files ...");
534 Bool_t resultRefFiles = CopyFilesToGrid("reference");
536 Bool_t resultMetadata = kTRUE;
537 if(fCurrentDetector == "GRP")
539 Log("StoreOCDB - SHUTTLE","Storing Run Metadata file ...");
540 resultMetadata = CopyFilesToGrid("metadata");
543 return resultCDB && resultRef && resultRefFiles && resultMetadata;
546 //______________________________________________________________________________________________
547 Bool_t AliShuttle::StoreOCDB(const TString& gridURI)
550 // Called by StoreOCDB(), performs actual storage to the main OCDB and reference storages (Grid)
553 TObjArray* gridIds=0;
555 Bool_t result = kTRUE;
557 const char* type = 0;
559 if(gridURI == fgkMainCDB) {
561 localURI = fgkLocalCDB;
562 } else if(gridURI == fgkMainRefStorage) {
564 localURI = fgkLocalRefStorage;
566 AliError(Form("Invalid storage URI: %s", gridURI.Data()));
570 AliCDBManager* man = AliCDBManager::Instance();
572 AliCDBStorage *gridSto = man->GetStorage(gridURI);
575 Form("StoreOCDB - cannot activate main %s storage", type));
579 gridIds = gridSto->GetQueryCDBList();
581 // get objects previously stored in local CDB
582 AliCDBStorage *localSto = man->GetStorage(localURI);
585 Form("StoreOCDB - cannot activate local %s storage", type));
588 AliCDBPath aPath(GetOfflineDetName(fCurrentDetector.Data()),"*","*");
589 // Local objects were stored with current run as Grid version!
590 TList* localEntries = localSto->GetAll(aPath.GetPath(), GetCurrentRun(), GetCurrentRun());
591 localEntries->SetOwner(1);
593 // loop on local stored objects
594 TIter localIter(localEntries);
595 AliCDBEntry *aLocEntry = 0;
596 while((aLocEntry = dynamic_cast<AliCDBEntry*> (localIter.Next()))){
597 aLocEntry->SetOwner(1);
598 AliCDBId aLocId = aLocEntry->GetId();
599 aLocEntry->SetVersion(-1);
600 aLocEntry->SetSubVersion(-1);
602 // If local object is valid up to infinity we store it only if it is
603 // the first unprocessed run!
604 if (aLocId.GetLastRun() == AliCDBRunRange::Infinity() &&
605 !fFirstUnprocessed[GetDetPos(fCurrentDetector)])
607 Log("SHUTTLE", Form("StoreOCDB - %s: object %s has validity infinite but "
608 "there are previous unprocessed runs!",
609 fCurrentDetector.Data(), aLocId.GetPath().Data()));
613 // loop on Grid valid Id's
614 Bool_t store = kTRUE;
615 TIter gridIter(gridIds);
616 AliCDBId* aGridId = 0;
617 while((aGridId = dynamic_cast<AliCDBId*> (gridIter.Next()))){
618 if(aGridId->GetPath() != aLocId.GetPath()) continue;
619 // skip all objects valid up to infinity
620 if(aGridId->GetLastRun() == AliCDBRunRange::Infinity()) continue;
621 // if we get here, it means there's already some more recent object stored on Grid!
626 // If we get here, the file can be stored!
627 Bool_t storeOk = gridSto->Put(aLocEntry);
628 if(!store || storeOk){
632 Log(fCurrentDetector.Data(),
633 Form("StoreOCDB - A more recent object already exists in %s storage: <%s>",
634 type, aGridId->ToString().Data()));
637 Form("StoreOCDB - Object <%s> successfully put into %s storage",
638 aLocId.ToString().Data(), type));
639 Log(fCurrentDetector.Data(),
640 Form("StoreOCDB - Object <%s> successfully put into %s storage",
641 aLocId.ToString().Data(), type));
644 // removing local filename...
646 localSto->IdToFilename(aLocId, filename);
647 Log("SHUTTLE", Form("StoreOCDB - Removing local file %s", filename.Data()));
648 RemoveFile(filename.Data());
652 Form("StoreOCDB - Grid %s storage of object <%s> failed",
653 type, aLocId.ToString().Data()));
654 Log(fCurrentDetector.Data(),
655 Form("StoreOCDB - Grid %s storage of object <%s> failed",
656 type, aLocId.ToString().Data()));
660 localEntries->Clear();
665 //______________________________________________________________________________________________
666 Bool_t AliShuttle::CleanReferenceStorage(const char* detector)
668 // clears the directory used to store reference files of a given subdetector
670 AliCDBManager* man = AliCDBManager::Instance();
671 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
672 TString localBaseFolder = sto->GetBaseFolder();
674 TString targetDir = GetRefFilePrefix(localBaseFolder.Data(), detector);
676 Log("SHUTTLE", Form("CleanReferenceStorage - Cleaning %s", targetDir.Data()));
679 begin.Form("%d_", GetCurrentRun());
681 TSystemDirectory* baseDir = new TSystemDirectory("/", targetDir);
685 TList* dirList = baseDir->GetListOfFiles();
688 if (!dirList) return kTRUE;
690 if (dirList->GetEntries() < 3)
696 Int_t nDirs = 0, nDel = 0;
697 TIter dirIter(dirList);
698 TSystemFile* entry = 0;
700 Bool_t success = kTRUE;
702 while ((entry = dynamic_cast<TSystemFile*> (dirIter.Next())))
704 if (entry->IsDirectory())
707 TString fileName(entry->GetName());
708 if (!fileName.BeginsWith(begin))
714 Int_t result = gSystem->Unlink(fileName.Data());
718 Log("SHUTTLE", Form("CleanReferenceStorage - Could not delete file %s!", fileName.Data()));
726 Log("SHUTTLE", Form("CleanReferenceStorage - %d (over %d) reference files in folder %s were deleted.",
727 nDel, nDirs, targetDir.Data()));
738 Int_t result = gSystem->GetPathInfo(targetDir, 0, (Long64_t*) 0, 0, 0);
742 result = gSystem->Exec(Form("rm -rf %s", targetDir.Data()));
745 Log("SHUTTLE", Form("CleanReferenceStorage - Could not clean directory %s", targetDir.Data()));
750 result = gSystem->mkdir(targetDir, kTRUE);
753 Log("SHUTTLE", Form("CleanReferenceStorage - Error creating base directory %s", targetDir.Data()));
760 //______________________________________________________________________________________________
761 Bool_t AliShuttle::StoreReferenceFile(const char* detector, const char* localFile, const char* gridFileName)
764 // Stores reference file directly (without opening it). This function stores the file locally.
766 // The file is stored under the following location:
767 // <base folder of local reference storage>/<DET>/<RUN#>_<gridFileName>
768 // where <gridFileName> is the second parameter given to the function
771 if (fTestMode & kErrorStorage)
773 Log(fCurrentDetector, "StoreReferenceFile - In TESTMODE - Simulating error while storing locally");
777 AliCDBManager* man = AliCDBManager::Instance();
778 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
780 TString localBaseFolder = sto->GetBaseFolder();
782 TString target = GetRefFilePrefix(localBaseFolder.Data(), detector);
783 target.Append(Form("/%d_%s", GetCurrentRun(), gridFileName));
785 return CopyFileLocally(localFile, target);
788 //______________________________________________________________________________________________
789 Bool_t AliShuttle::StoreRunMetadataFile(const char* localFile, const char* gridFileName)
792 // Stores Run metadata file to the Grid, in the run folder
794 // Only GRP can call this function.
796 if (fTestMode & kErrorStorage)
798 Log(fCurrentDetector, "StoreRunMetaDataFile - In TESTMODE - Simulating error while storing locally");
802 AliCDBManager* man = AliCDBManager::Instance();
803 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
805 TString localBaseFolder = sto->GetBaseFolder();
807 // Build Run level folder
808 // folder = /alice/data/year/lhcPeriod/runNb/Raw
811 TString lhcPeriod = GetLHCPeriod();
812 if (lhcPeriod.Length() == 0)
814 Log("SHUTTLE","StoreRunMetaDataFile - LHCPeriod not found in logbook!");
818 TString target = Form("%s/GRP/RunMetadata/alice/data/%d/%s/%09d/Raw/%s",
819 localBaseFolder.Data(), GetCurrentYear(),
820 lhcPeriod.Data(), GetCurrentRun(), gridFileName);
822 return CopyFileLocally(localFile, target);
825 //______________________________________________________________________________________________
826 Bool_t AliShuttle::CopyFileLocally(const char* localFile, const TString& target)
829 // Stores file locally. Called by StoreReferenceFile and StoreRunMetadataFile
830 // Files are temporarily stored in the local reference storage. When the preprocessor
831 // finishes, the Shuttle calls CopyFilesToGrid to transfer the files to AliEn
832 // (in reference or run level folders)
835 TString targetDir(target(0, target.Last('/')));
837 //try to open base dir folder, if it does not exist
838 void* dir = gSystem->OpenDirectory(targetDir.Data());
840 if (gSystem->mkdir(targetDir.Data(), kTRUE)) {
841 Log("SHUTTLE", Form("StoreFileLocally - Can't open directory <%s>", targetDir.Data()));
846 gSystem->FreeDirectory(dir);
851 result = gSystem->GetPathInfo(localFile, 0, (Long64_t*) 0, 0, 0);
854 Log("SHUTTLE", Form("StoreFileLocally - %s does not exist", localFile));
858 result = gSystem->GetPathInfo(target, 0, (Long64_t*) 0, 0, 0);
861 Log("SHUTTLE", Form("StoreFileLocally - target file %s already exist, removing...", target.Data()));
862 if (gSystem->Unlink(target.Data()))
864 Log("SHUTTLE", Form("StoreFileLocally - Could not remove existing target file %s!", target.Data()));
869 result = gSystem->CopyFile(localFile, target);
873 Log("SHUTTLE", Form("StoreFileLocally - File %s stored locally to %s", localFile, target.Data()));
878 Log("SHUTTLE", Form("StoreFileLocally - Could not store file %s to %s! Error code = %d",
879 localFile, target.Data(), result));
887 //______________________________________________________________________________________________
888 Bool_t AliShuttle::CopyFilesToGrid(const char* type)
891 // Transfers local files to the Grid. Local files can be reference files
892 // or run metadata file (from GRP only).
894 // According to the type (ref, metadata) the files are stored under the following location:
895 // ref --> <base folder of reference storage>/<DET>/<RUN#>_<gridFileName>
896 // metadata --> <run data folder>/<MetadataFileName>
899 AliCDBManager* man = AliCDBManager::Instance();
900 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
903 TString localBaseFolder = sto->GetBaseFolder();
909 if (strcmp(type, "reference") == 0)
911 dir = GetRefFilePrefix(localBaseFolder.Data(), fCurrentDetector.Data());
912 AliCDBStorage* gridSto = man->GetStorage(fgkMainRefStorage);
915 TString gridBaseFolder = gridSto->GetBaseFolder();
916 alienDir = GetRefFilePrefix(gridBaseFolder.Data(), fCurrentDetector.Data());
917 begin = Form("%d_", GetCurrentRun());
919 else if (strcmp(type, "metadata") == 0)
922 TString lhcPeriod = GetLHCPeriod();
924 if (lhcPeriod.Length() == 0)
926 Log("SHUTTLE","CopyFilesToGrid - LHCPeriod not found in logbook!");
930 dir = Form("%s/GRP/RunMetadata/alice/data/%d/%s/%09d/Raw",
931 localBaseFolder.Data(), GetCurrentYear(),
932 lhcPeriod.Data(), GetCurrentRun());
933 alienDir = dir(dir.Index("/alice/data/"), dir.Length());
939 Log("SHUTTLE", "CopyFilesToGrid - Unexpected: type label must be reference or metadata!");
943 TSystemDirectory* baseDir = new TSystemDirectory("/", dir);
947 TList* dirList = baseDir->GetListOfFiles();
950 if (!dirList) return kTRUE;
952 if (dirList->GetEntries() < 3)
960 Log("SHUTTLE", "CopyFilesToGrid - Connection to Grid failed: Cannot continue!");
965 Int_t nDirs = 0, nTransfer = 0;
966 TIter dirIter(dirList);
967 TSystemFile* entry = 0;
969 Bool_t success = kTRUE;
970 Bool_t first = kTRUE;
972 while ((entry = dynamic_cast<TSystemFile*> (dirIter.Next())))
974 if (entry->IsDirectory())
977 TString fileName(entry->GetName());
978 if (!fileName.BeginsWith(begin))
986 // check that folder exists, otherwise create it
987 TGridResult* result = gGrid->Ls(alienDir.Data(), "a");
995 if (!result->GetFileName(1)) // TODO: It looks like element 0 is always 0!!
997 // TODO It does not work currently! Bug in TAliEn::Mkdir
998 // TODO Manually fixed in local root v5-16-00
999 if (!gGrid->Mkdir(alienDir.Data(),"-p",0))
1001 Log("SHUTTLE", Form("CopyFilesToGrid - Cannot create directory %s",
1006 Log("SHUTTLE",Form("CopyFilesToGrid - Folder %s created", alienDir.Data()));
1010 Log("SHUTTLE",Form("CopyFilesToGrid - Folder %s found", alienDir.Data()));
1014 TString fullLocalPath;
1015 fullLocalPath.Form("%s/%s", dir.Data(), fileName.Data());
1017 TString fullGridPath;
1018 fullGridPath.Form("alien://%s/%s", alienDir.Data(), fileName.Data());
1020 Bool_t result = TFile::Cp(fullLocalPath, fullGridPath);
1024 Log("SHUTTLE", Form("CopyFilesToGrid - Copying local file %s to %s succeeded!",
1025 fullLocalPath.Data(), fullGridPath.Data()));
1026 RemoveFile(fullLocalPath);
1031 Log("SHUTTLE", Form("CopyFilesToGrid - Copying local file %s to %s FAILED!",
1032 fullLocalPath.Data(), fullGridPath.Data()));
1037 Log("SHUTTLE", Form("CopyFilesToGrid - %d (over %d) files in folder %s copied to Grid.",
1038 nTransfer, nDirs, dir.Data()));
1045 //______________________________________________________________________________________________
1046 const char* AliShuttle::GetRefFilePrefix(const char* base, const char* detector)
1049 // Get folder name of reference files
1052 TString offDetStr(GetOfflineDetName(detector));
1054 if (offDetStr == "ITS" || offDetStr == "MUON" || offDetStr == "PHOS")
1056 dir.Form("%s/%s/%s", base, offDetStr.Data(), detector);
1058 dir.Form("%s/%s", base, offDetStr.Data());
1066 //______________________________________________________________________________________________
1067 void AliShuttle::CleanLocalStorage(const TString& uri)
1070 // Called in case the preprocessor is declared failed. Remove remaining objects from the local storages.
1073 const char* type = 0;
1074 if(uri == fgkLocalCDB) {
1076 } else if(uri == fgkLocalRefStorage) {
1079 AliError(Form("Invalid storage URI: %s", uri.Data()));
1083 AliCDBManager* man = AliCDBManager::Instance();
1085 // open local storage
1086 AliCDBStorage *localSto = man->GetStorage(uri);
1089 Form("CleanLocalStorage - cannot activate local %s storage", type));
1093 TString filename(Form("%s/%s/*/Run*_v%d_s*.root",
1094 localSto->GetBaseFolder().Data(), GetOfflineDetName(fCurrentDetector.Data()), GetCurrentRun()));
1096 AliDebug(2, Form("filename = %s", filename.Data()));
1098 Log("SHUTTLE", Form("Removing remaining local files for run %d and detector %s ...",
1099 GetCurrentRun(), fCurrentDetector.Data()));
1101 RemoveFile(filename.Data());
1105 //______________________________________________________________________________________________
1106 void AliShuttle::RemoveFile(const char* filename)
1109 // removes local file
1112 TString command(Form("rm -f %s", filename));
1114 Int_t result = gSystem->Exec(command.Data());
1117 Log("SHUTTLE", Form("RemoveFile - %s: Cannot remove file %s!",
1118 fCurrentDetector.Data(), filename));
1122 //______________________________________________________________________________________________
1123 AliShuttleStatus* AliShuttle::ReadShuttleStatus()
1126 // Reads the AliShuttleStatus from the CDB
1130 delete fStatusEntry;
1134 fStatusEntry = AliCDBManager::Instance()->GetStorage(GetLocalCDB())
1135 ->Get(Form("/SHUTTLE/STATUS/%s", fCurrentDetector.Data()), GetCurrentRun());
1137 if (!fStatusEntry) return 0;
1138 fStatusEntry->SetOwner(1);
1140 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
1142 AliError("Invalid object stored to CDB!");
1149 //______________________________________________________________________________________________
1150 Bool_t AliShuttle::WriteShuttleStatus(AliShuttleStatus* status)
1153 // writes the status for one subdetector
1157 delete fStatusEntry;
1161 Int_t run = GetCurrentRun();
1163 AliCDBId id(AliCDBPath("SHUTTLE", "STATUS", fCurrentDetector), run, run);
1165 fStatusEntry = new AliCDBEntry(status, id, new AliCDBMetaData);
1166 fStatusEntry->SetOwner(1);
1168 UInt_t result = AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
1171 Log("SHUTTLE", Form("WriteShuttleStatus - Failed for %s, run %d",
1172 fCurrentDetector.Data(), run));
1181 //______________________________________________________________________________________________
1182 void AliShuttle::UpdateShuttleStatus(AliShuttleStatus::Status newStatus, Bool_t increaseCount)
1185 // changes the AliShuttleStatus for the given detector and run to the given status
1189 AliError("UNEXPECTED: fStatusEntry empty");
1193 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
1196 Log("SHUTTLE", "UpdateShuttleStatus - UNEXPECTED: status could not be read from current CDB entry");
1200 TString actionStr = Form("UpdateShuttleStatus - %s: Changing state from %s to %s",
1201 fCurrentDetector.Data(),
1202 status->GetStatusName(),
1203 status->GetStatusName(newStatus));
1204 Log("SHUTTLE", actionStr);
1205 SetLastAction(actionStr);
1207 status->SetStatus(newStatus);
1208 if (increaseCount) status->IncreaseCount();
1210 AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
1215 //______________________________________________________________________________________________
1216 void AliShuttle::SendMLInfo()
1219 // sends ML information about the current status of the current detector being processed
1222 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
1225 Log("SHUTTLE", "SendMLInfo - UNEXPECTED: status could not be read from current CDB entry");
1229 TMonaLisaText mlStatus(Form("%s_status", fCurrentDetector.Data()), status->GetStatusName());
1230 TMonaLisaValue mlRetryCount(Form("%s_count", fCurrentDetector.Data()), status->GetCount());
1233 mlList.Add(&mlStatus);
1234 mlList.Add(&mlRetryCount);
1236 fMonaLisa->SendParameters(&mlList);
1239 //______________________________________________________________________________________________
1240 Bool_t AliShuttle::ContinueProcessing()
1242 // this function reads the AliShuttleStatus information from CDB and
1243 // checks if the processing should be continued
1244 // if yes it returns kTRUE and updates the AliShuttleStatus with nextStatus
1246 if (!fConfig->HostProcessDetector(fCurrentDetector)) return kFALSE;
1248 AliPreprocessor* aPreprocessor =
1249 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
1252 Log("SHUTTLE", Form("ContinueProcessing - %s: no preprocessor registered", fCurrentDetector.Data()));
1256 AliShuttleLogbookEntry::Status entryStatus =
1257 fLogbookEntry->GetDetectorStatus(fCurrentDetector);
1259 if(entryStatus != AliShuttleLogbookEntry::kUnprocessed) {
1260 Log("SHUTTLE", Form("ContinueProcessing - %s is %s",
1261 fCurrentDetector.Data(),
1262 fLogbookEntry->GetDetectorStatusName(entryStatus)));
1266 // if we get here, according to Shuttle logbook subdetector is in UNPROCESSED state
1268 // check if current run is first unprocessed run for current detector
1269 if (fConfig->StrictRunOrder(fCurrentDetector) &&
1270 !fFirstUnprocessed[GetDetPos(fCurrentDetector)])
1272 if (fTestMode == kNone)
1274 Log("SHUTTLE", Form("ContinueProcessing - %s requires strict run ordering"
1275 " but this is not the first unprocessed run!"));
1280 Log("SHUTTLE", Form("ContinueProcessing - In TESTMODE - "
1281 "Although %s requires strict run ordering "
1282 "and this is not the first unprocessed run, "
1283 "the SHUTTLE continues"));
1287 AliShuttleStatus* status = ReadShuttleStatus();
1290 Log("SHUTTLE", Form("ContinueProcessing - %s: Processing first time",
1291 fCurrentDetector.Data()));
1292 status = new AliShuttleStatus(AliShuttleStatus::kStarted);
1293 return WriteShuttleStatus(status);
1296 // The following two cases shouldn't happen if Shuttle Logbook was correctly updated.
1297 // If it happens it may mean Logbook updating failed... let's do it now!
1298 if (status->GetStatus() == AliShuttleStatus::kDone ||
1299 status->GetStatus() == AliShuttleStatus::kFailed){
1300 Log("SHUTTLE", Form("ContinueProcessing - %s is already %s. Updating Shuttle Logbook",
1301 fCurrentDetector.Data(),
1302 status->GetStatusName(status->GetStatus())));
1303 UpdateShuttleLogbook(fCurrentDetector.Data(),
1304 status->GetStatusName(status->GetStatus()));
1308 if (status->GetStatus() == AliShuttleStatus::kStoreError) {
1310 Form("ContinueProcessing - %s: Grid storage of one or more "
1311 "objects failed. Trying again now",
1312 fCurrentDetector.Data()));
1313 UpdateShuttleStatus(AliShuttleStatus::kStoreStarted);
1315 Log("SHUTTLE", Form("ContinueProcessing - %s: all objects "
1316 "successfully stored into main storage",
1317 fCurrentDetector.Data()));
1318 UpdateShuttleStatus(AliShuttleStatus::kDone);
1319 UpdateShuttleLogbook(fCurrentDetector.Data(), "DONE");
1322 Form("ContinueProcessing - %s: Grid storage failed again",
1323 fCurrentDetector.Data()));
1324 UpdateShuttleStatus(AliShuttleStatus::kStoreError);
1329 // if we get here, there is a restart
1330 Bool_t cont = kFALSE;
1333 if (status->GetCount() >= fConfig->GetMaxRetries()) {
1334 Log("SHUTTLE", Form("ContinueProcessing - %s failed %d times in status %s - "
1335 "Updating Shuttle Logbook", fCurrentDetector.Data(),
1336 status->GetCount(), status->GetStatusName()));
1337 UpdateShuttleLogbook(fCurrentDetector.Data(), "FAILED");
1338 UpdateShuttleStatus(AliShuttleStatus::kFailed);
1340 // there may still be objects in local OCDB and reference storage
1341 // and FXS databases may be not updated: do it now!
1343 // TODO Currently disabled, we want to keep files in case of failure!
1344 // CleanLocalStorage(fgkLocalCDB);
1345 // CleanLocalStorage(fgkLocalRefStorage);
1346 // UpdateTableFailCase();
1348 // Send mail to detector expert!
1349 Log("SHUTTLE", Form("ContinueProcessing - Sending mail to %s expert...",
1350 fCurrentDetector.Data()));
1352 Log("SHUTTLE", Form("ContinueProcessing - Could not send mail to %s expert",
1353 fCurrentDetector.Data()));
1356 Log("SHUTTLE", Form("ContinueProcessing - %s: restarting. "
1357 "Aborted before with %s. Retry number %d.", fCurrentDetector.Data(),
1358 status->GetStatusName(), status->GetCount()));
1359 Bool_t increaseCount = kTRUE;
1360 if (status->GetStatus() == AliShuttleStatus::kDCSError ||
1361 status->GetStatus() == AliShuttleStatus::kDCSStarted)
1362 increaseCount = kFALSE;
1364 UpdateShuttleStatus(AliShuttleStatus::kStarted, increaseCount);
1371 //______________________________________________________________________________________________
1372 Bool_t AliShuttle::Process(AliShuttleLogbookEntry* entry)
1375 // Makes data retrieval for all detectors in the configuration.
1376 // entry: Shuttle logbook entry, contains run paramenters and status of detectors
1377 // (Unprocessed, Inactive, Failed or Done).
1378 // Returns kFALSE in case of error occured and kTRUE otherwise
1381 if (!entry) return kFALSE;
1383 fLogbookEntry = entry;
1385 Log("SHUTTLE", Form("\t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: START ^*^*^*^*^*^*^*^*^*^*^*^*",
1388 // create ML instance that monitors this run
1389 fMonaLisa = new TMonaLisaWriter(Form("%d", GetCurrentRun()), "SHUTTLE", "aliendb1.cern.ch");
1390 // disable monitoring of other parameters that come e.g. from TFile
1391 gMonitoringWriter = 0;
1393 // Send the information to ML
1394 TMonaLisaText mlStatus("SHUTTLE_status", "Processing");
1395 TMonaLisaText mlRunType("SHUTTLE_runtype", Form("%s (%s)", entry->GetRunType(), entry->GetRunParameter("log")));
1398 mlList.Add(&mlStatus);
1399 mlList.Add(&mlRunType);
1401 fMonaLisa->SendParameters(&mlList);
1403 if (fLogbookEntry->IsDone())
1405 Log("SHUTTLE","Process - Shuttle is already DONE. Updating logbook");
1406 UpdateShuttleLogbook("shuttle_done");
1411 // read test mode if flag is set
1415 TString logEntry(entry->GetRunParameter("log"));
1416 //printf("log entry = %s\n", logEntry.Data());
1417 TString searchStr("Testmode: ");
1418 Int_t pos = logEntry.Index(searchStr.Data());
1419 //printf("%d\n", pos);
1422 TSubString subStr = logEntry(pos + searchStr.Length(), logEntry.Length());
1423 //printf("%s\n", subStr.String().Data());
1424 TString newStr(subStr.Data());
1425 TObjArray* token = newStr.Tokenize(' ');
1429 TObjString* tmpStr = dynamic_cast<TObjString*> (token->First());
1432 Int_t testMode = tmpStr->String().Atoi();
1435 Log("SHUTTLE", Form("Process - Enabling test mode %d", testMode));
1436 SetTestMode((TestMode) testMode);
1444 fLogbookEntry->Print("all");
1447 Bool_t hasError = kFALSE;
1449 // Set the CDB and Reference folders according to the year and LHC period
1450 TString lhcPeriod(GetLHCPeriod());
1451 if (lhcPeriod.Length() == 0)
1453 Log("SHUTTLE","StoreRunMetaDataFile - LHCPeriod not found in logbook!");
1457 if (fgkMainCDB.Length() == 0)
1458 fgkMainCDB = Form("alien://folder=/alice/data/%d/%s/OCDB?user=alidaq?cacheFold=/tmp/OCDBCache",
1459 GetCurrentYear(), lhcPeriod.Data());
1461 if (fgkMainRefStorage.Length() == 0)
1462 fgkMainRefStorage = Form("alien://folder=/alice/data/%d/%s/Reference?user=alidaq?cacheFold=/tmp/OCDBCache",
1463 GetCurrentYear(), lhcPeriod.Data());
1465 AliCDBStorage *mainCDBSto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
1466 if(mainCDBSto) mainCDBSto->QueryCDB(GetCurrentRun());
1467 AliCDBStorage *mainRefSto = AliCDBManager::Instance()->GetStorage(fgkMainRefStorage);
1468 if(mainRefSto) mainRefSto->QueryCDB(GetCurrentRun());
1470 // Loop on detectors in the configuration
1471 TIter iter(fConfig->GetDetectors());
1472 TObjString* aDetector = 0;
1474 while ((aDetector = (TObjString*) iter.Next()))
1476 fCurrentDetector = aDetector->String();
1478 if (ContinueProcessing() == kFALSE) continue;
1480 Log("SHUTTLE", Form("\t\t\t****** run %d - %s: START ******",
1481 GetCurrentRun(), aDetector->GetName()));
1483 for(Int_t iSys=0;iSys<3;iSys++) fFXSCalled[iSys]=kFALSE;
1485 Log(fCurrentDetector.Data(), "Process - Starting processing");
1491 Log("SHUTTLE", "Process - ERROR: Forking failed");
1496 Log("SHUTTLE", Form("Process - In parent process of %d - %s: Starting monitoring",
1497 GetCurrentRun(), aDetector->GetName()));
1499 Long_t begin = time(0);
1501 int status; // to be used with waitpid, on purpose an int (not Int_t)!
1502 while (waitpid(pid, &status, WNOHANG) == 0)
1504 Long_t expiredTime = time(0) - begin;
1506 if (expiredTime > fConfig->GetPPTimeOut())
1509 tmp.Form("Process - Process of %s time out. "
1510 "Run time: %d seconds. Killing...",
1511 fCurrentDetector.Data(), expiredTime);
1512 Log("SHUTTLE", tmp);
1513 Log(fCurrentDetector, tmp);
1517 UpdateShuttleStatus(AliShuttleStatus::kPPTimeOut);
1520 gSystem->Sleep(1000);
1524 gSystem->Sleep(1000);
1527 checkStr.Form("ps -o vsize --pid %d | tail -n 1", pid);
1528 FILE* pipe = gSystem->OpenPipe(checkStr, "r");
1531 Log("SHUTTLE", Form("Process - Error: "
1532 "Could not open pipe to %s", checkStr.Data()));
1537 if (!fgets(buffer, 100, pipe))
1539 Log("SHUTTLE", "Process - Error: ps did not return anything");
1540 gSystem->ClosePipe(pipe);
1543 gSystem->ClosePipe(pipe);
1545 //Log("SHUTTLE", Form("ps returned %s", buffer));
1548 if ((sscanf(buffer, "%d\n", &mem) != 1) || !mem)
1550 Log("SHUTTLE", "Process - Error: Could not parse output of ps");
1554 if (expiredTime % 60 == 0)
1555 Log("SHUTTLE", Form("Process - %s: Checking process. "
1556 "Run time: %d seconds - Memory consumption: %d KB",
1557 fCurrentDetector.Data(), expiredTime, mem));
1559 if (mem > fConfig->GetPPMaxMem())
1562 tmp.Form("Process - Process exceeds maximum allowed memory "
1563 "(%d KB > %d KB). Killing...",
1564 mem, fConfig->GetPPMaxMem());
1565 Log("SHUTTLE", tmp);
1566 Log(fCurrentDetector, tmp);
1570 UpdateShuttleStatus(AliShuttleStatus::kPPOutOfMemory);
1573 gSystem->Sleep(1000);
1578 Log("SHUTTLE", Form("Process - In parent process of %d - %s: Client has terminated.",
1579 GetCurrentRun(), aDetector->GetName()));
1581 if (WIFEXITED(status))
1583 Int_t returnCode = WEXITSTATUS(status);
1585 Log("SHUTTLE", Form("Process - %s: the return code is %d", fCurrentDetector.Data(),
1588 if (returnCode == 0) hasError = kTRUE;
1594 Log("SHUTTLE", Form("Process - In client process of %d - %s", GetCurrentRun(),
1595 aDetector->GetName()));
1597 Log("SHUTTLE", Form("Process - Redirecting output to %s log",fCurrentDetector.Data()));
1599 if ((freopen(GetLogFileName(fCurrentDetector), "a", stdout)) == 0)
1601 Log("SHUTTLE", "Process - Could not freopen stdout");
1605 fOutputRedirected = kTRUE;
1606 if ((dup2(fileno(stdout), fileno(stderr))) < 0)
1607 Log("SHUTTLE", "Process - Could not redirect stderr");
1611 TString wd = gSystem->WorkingDirectory();
1612 TString tmpDir = Form("%s/%s_%d_process", GetShuttleTempDir(),
1613 fCurrentDetector.Data(), GetCurrentRun());
1615 Int_t result = gSystem->GetPathInfo(tmpDir.Data(), 0, (Long64_t*) 0, 0, 0);
1616 if (!result) // temp dir already exists!
1618 Log(fCurrentDetector.Data(),
1619 Form("Process - %s dir already exists! Removing...", tmpDir.Data()));
1620 gSystem->Exec(Form("rm -rf %s",tmpDir.Data()));
1623 if (gSystem->mkdir(tmpDir.Data(), 1))
1625 Log(fCurrentDetector.Data(), "Process - could not make temp directory!!");
1629 if (!gSystem->ChangeDirectory(tmpDir.Data()))
1631 Log(fCurrentDetector.Data(), "Process - could not change directory!!");
1635 Bool_t success = ProcessCurrentDetector();
1637 gSystem->ChangeDirectory(wd.Data());
1639 gSystem->Exec(Form("rm -rf %s",tmpDir.Data()));
1641 if (success) // Preprocessor finished successfully!
1643 // Update time_processed field in FXS DB
1644 if (UpdateTable() == kFALSE)
1645 Log("SHUTTLE", Form("Process - %s: Could not update FXS databases!",
1646 fCurrentDetector.Data()));
1648 // Transfer the data from local storage to main storage (Grid)
1649 UpdateShuttleStatus(AliShuttleStatus::kStoreStarted);
1650 if (StoreOCDB() == kFALSE)
1653 Form("\t\t\t****** run %d - %s: STORAGE ERROR ******",
1654 GetCurrentRun(), aDetector->GetName()));
1655 UpdateShuttleStatus(AliShuttleStatus::kStoreError);
1659 Form("\t\t\t****** run %d - %s: DONE ******",
1660 GetCurrentRun(), aDetector->GetName()));
1661 UpdateShuttleStatus(AliShuttleStatus::kDone);
1662 UpdateShuttleLogbook(fCurrentDetector, "DONE");
1667 Form("\t\t\t****** run %d - %s: PP ERROR ******",
1668 GetCurrentRun(), aDetector->GetName()));
1671 for (UInt_t iSys=0; iSys<3; iSys++)
1673 if (fFXSCalled[iSys]) fFXSlist[iSys].Clear();
1676 Log("SHUTTLE", Form("Process - Client process of %d - %s is exiting now with %d.",
1677 GetCurrentRun(), aDetector->GetName(), success));
1679 // the client exits here
1680 gSystem->Exit(success);
1682 AliError("We should never get here!!!");
1686 Log("SHUTTLE", Form("\t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: FINISH ^*^*^*^*^*^*^*^*^*^*^*^*",
1689 //check if shuttle is done for this run, if so update logbook
1690 TObjArray checkEntryArray;
1691 checkEntryArray.SetOwner(1);
1692 TString whereClause = Form("where run=%d", GetCurrentRun());
1693 if (!QueryShuttleLogbook(whereClause.Data(), checkEntryArray) || checkEntryArray.GetEntries() == 0) {
1694 Log("SHUTTLE", Form("Process - Warning: Cannot check status of run %d on Shuttle logbook!",
1696 return hasError == kFALSE;
1699 AliShuttleLogbookEntry* checkEntry = dynamic_cast<AliShuttleLogbookEntry*>
1700 (checkEntryArray.At(0));
1704 if (checkEntry->IsDone())
1706 Log("SHUTTLE","Process - Shuttle is DONE. Updating logbook");
1707 UpdateShuttleLogbook("shuttle_done");
1711 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
1713 if (checkEntry->GetDetectorStatus(iDet) == AliShuttleLogbookEntry::kUnprocessed)
1715 AliDebug(2, Form("Run %d: setting %s as \"not first time unprocessed\"",
1716 checkEntry->GetRun(), GetDetName(iDet)));
1717 fFirstUnprocessed[iDet] = kFALSE;
1723 // remove ML instance
1729 return hasError == kFALSE;
1732 //______________________________________________________________________________________________
1733 Bool_t AliShuttle::ProcessCurrentDetector()
1736 // Makes data retrieval just for a specific detector (fCurrentDetector).
1737 // Threre should be a configuration for this detector.
1739 Log("SHUTTLE", Form("ProcessCurrentDetector - Retrieving values for %s, run %d",
1740 fCurrentDetector.Data(), GetCurrentRun()));
1742 TString wd = gSystem->WorkingDirectory();
1744 if (!CleanReferenceStorage(fCurrentDetector.Data()))
1747 gSystem->ChangeDirectory(wd.Data());
1749 TMap* dcsMap = new TMap();
1751 // call preprocessor
1752 AliPreprocessor* aPreprocessor =
1753 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
1755 aPreprocessor->Initialize(GetCurrentRun(), GetCurrentStartTime(), GetCurrentEndTime());
1757 Bool_t processDCS = aPreprocessor->ProcessDCS();
1761 Log(fCurrentDetector, "ProcessCurrentDetector -"
1762 " The preprocessor requested to skip the retrieval of DCS values");
1764 else if (fTestMode & kSkipDCS)
1766 Log(fCurrentDetector, "ProcessCurrentDetector - In TESTMODE: Skipping DCS processing");
1768 else if (fTestMode & kErrorDCS)
1770 Log(fCurrentDetector, "ProcessCurrentDetector - In TESTMODE: Simulating DCS error");
1771 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
1772 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1777 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
1779 // Query DCS archive
1780 Int_t nServers = fConfig->GetNServers(fCurrentDetector);
1782 for (int iServ=0; iServ<nServers; iServ++)
1785 TString host(fConfig->GetDCSHost(fCurrentDetector, iServ));
1786 Int_t port = fConfig->GetDCSPort(fCurrentDetector, iServ);
1787 Int_t multiSplit = fConfig->GetMultiSplit(fCurrentDetector, iServ);
1789 Log(fCurrentDetector, Form("ProcessCurrentDetector -"
1790 " Querying DCS Amanda server %s:%d (%d of %d)",
1791 host.Data(), port, iServ+1, nServers));
1796 if (fConfig->GetDCSAliases(fCurrentDetector, iServ)->GetEntries() > 0)
1798 aliasMap = GetValueSet(host, port,
1799 fConfig->GetDCSAliases(fCurrentDetector, iServ),
1800 kAlias, multiSplit);
1803 Log(fCurrentDetector,
1804 Form("ProcessCurrentDetector -"
1805 " Error retrieving DCS aliases from server %s."
1806 " Sending mail to DCS experts!", host.Data()));
1807 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1809 if (!SendMailToDCS())
1810 Log("SHUTTLE", Form("ProcessCurrentDetector - Could not send mail to DCS experts!"));
1817 if (fConfig->GetDCSDataPoints(fCurrentDetector, iServ)->GetEntries() > 0)
1819 dpMap = GetValueSet(host, port,
1820 fConfig->GetDCSDataPoints(fCurrentDetector, iServ),
1824 Log(fCurrentDetector,
1825 Form("ProcessCurrentDetector -"
1826 " Error retrieving DCS data points from server %s."
1827 " Sending mail to DCS experts!", host.Data()));
1828 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1830 if (!SendMailToDCS())
1831 Log("SHUTTLE", Form("ProcessCurrentDetector - Could not send mail to DCS experts!"));
1833 if (aliasMap) delete aliasMap;
1839 // merge aliasMap and dpMap into dcsMap
1841 TIter iter(aliasMap);
1842 TObjString* key = 0;
1843 while ((key = (TObjString*) iter.Next()))
1844 dcsMap->Add(key, aliasMap->GetValue(key->String()));
1846 aliasMap->SetOwner(kFALSE);
1852 TObjString* key = 0;
1853 while ((key = (TObjString*) iter.Next()))
1854 dcsMap->Add(key, dpMap->GetValue(key->String()));
1856 dpMap->SetOwner(kFALSE);
1862 // DCS Archive DB processing successful. Call Preprocessor!
1863 UpdateShuttleStatus(AliShuttleStatus::kPPStarted);
1865 UInt_t returnValue = aPreprocessor->Process(dcsMap);
1867 if (returnValue > 0) // Preprocessor error!
1869 Log(fCurrentDetector, Form("ProcessCurrentDetector - "
1870 "Preprocessor failed. Process returned %d.", returnValue));
1871 UpdateShuttleStatus(AliShuttleStatus::kPPError);
1872 dcsMap->DeleteAll();
1878 UpdateShuttleStatus(AliShuttleStatus::kPPDone);
1879 Log(fCurrentDetector, Form("ProcessCurrentDetector - %s preprocessor returned success",
1880 fCurrentDetector.Data()));
1882 dcsMap->DeleteAll();
1888 //______________________________________________________________________________________________
1889 Bool_t AliShuttle::QueryShuttleLogbook(const char* whereClause,
1892 // Query DAQ's Shuttle logbook and fills detector status object.
1893 // Call QueryRunParameters to query DAQ logbook for run parameters.
1896 entries.SetOwner(1);
1898 // check connection, in case connect
1899 if(!Connect(3)) return kFALSE;
1902 sqlQuery = Form("select * from %s %s order by run", fConfig->GetShuttlelbTable(), whereClause);
1904 TSQLResult* aResult = fServer[3]->Query(sqlQuery);
1906 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
1910 AliDebug(2,Form("Query = %s", sqlQuery.Data()));
1912 if(aResult->GetRowCount() == 0) {
1913 Log("SHUTTLE", "No entries in Shuttle Logbook match request");
1918 // TODO Check field count!
1919 const UInt_t nCols = 23;
1920 if (aResult->GetFieldCount() != (Int_t) nCols) {
1921 Log("SHUTTLE", "Invalid SQL result field number!");
1927 while ((aRow = aResult->Next())) {
1928 TString runString(aRow->GetField(0), aRow->GetFieldLength(0));
1929 Int_t run = runString.Atoi();
1931 AliShuttleLogbookEntry *entry = QueryRunParameters(run);
1935 // loop on detectors
1936 for(UInt_t ii = 0; ii < nCols; ii++)
1937 entry->SetDetectorStatus(aResult->GetFieldName(ii), aRow->GetField(ii));
1939 entries.AddLast(entry);
1947 //______________________________________________________________________________________________
1948 AliShuttleLogbookEntry* AliShuttle::QueryRunParameters(Int_t run)
1951 // Retrieve run parameters written in the DAQ logbook and sets them into AliShuttleLogbookEntry object
1954 // check connection, in case connect
1959 sqlQuery.Form("select * from %s where run=%d", fConfig->GetDAQlbTable(), run);
1961 TSQLResult* aResult = fServer[3]->Query(sqlQuery);
1963 Log("SHUTTLE", Form("Can't execute query <%s>!", sqlQuery.Data()));
1967 if (aResult->GetRowCount() == 0) {
1968 Log("SHUTTLE", Form("QueryRunParameters - No entry in DAQ Logbook for run %d. Skipping", run));
1973 if (aResult->GetRowCount() > 1) {
1974 Log("SHUTTLE", Form("QueryRunParameters - UNEXPECTED: "
1975 "more than one entry in DAQ Logbook for run %d!", run));
1980 TSQLRow* aRow = aResult->Next();
1983 Log("SHUTTLE", Form("QueryRunParameters - Could not retrieve row for run %d. Skipping", run));
1988 AliShuttleLogbookEntry* entry = new AliShuttleLogbookEntry(run);
1990 for (Int_t ii = 0; ii < aResult->GetFieldCount(); ii++)
1991 entry->SetRunParameter(aResult->GetFieldName(ii), aRow->GetField(ii));
1993 UInt_t startTime = entry->GetStartTime();
1994 UInt_t endTime = entry->GetEndTime();
1996 if (!startTime || !endTime || startTime > endTime) {
1998 Form("QueryRunParameters - Invalid parameters for Run %d: startTime = %d, endTime = %d",
1999 run, startTime, endTime));
2012 //______________________________________________________________________________________________
2013 TMap* AliShuttle::GetValueSet(const char* host, Int_t port, const TSeqCollection* entries,
2014 DCSType type, Int_t multiSplit)
2016 // Retrieve all "entry" data points from the DCS server
2017 // host, port: TSocket connection parameters
2018 // entries: list of name of the alias or data point
2019 // type: kAlias or kDP
2020 // returns TMap of values, 0 when failure
2022 AliDCSClient client(host, port, fTimeout, fRetries, multiSplit);
2027 result = client.GetAliasValues(entries, GetCurrentStartTime(),
2028 GetCurrentEndTime());
2030 else if (type == kDP)
2032 result = client.GetDPValues(entries, GetCurrentStartTime(),
2033 GetCurrentEndTime());
2038 Log(fCurrentDetector.Data(), Form("GetValueSet - Can't get entries! Reason: %s",
2039 client.GetErrorString(client.GetResultErrorCode())));
2040 if (client.GetResultErrorCode() == AliDCSClient::fgkServerError)
2041 Log(fCurrentDetector.Data(), Form("GetValueSet - Server error code: %s",
2042 client.GetServerError().Data()));
2050 //______________________________________________________________________________________________
2051 const char* AliShuttle::GetFile(Int_t system, const char* detector,
2052 const char* id, const char* source)
2054 // Get calibration file from file exchange servers
2055 // First queris the FXS database for the file name, using the run, detector, id and source info
2056 // then calls RetrieveFile(filename) for actual copy to local disk
2057 // run: current run being processed (given by Logbook entry fLogbookEntry)
2058 // detector: the Preprocessor name
2059 // id: provided as a parameter by the Preprocessor
2060 // source: provided by the Preprocessor through GetFileSources function
2062 // check if test mode should simulate a FXS error
2063 if (fTestMode & kErrorFXSFiles)
2065 Log(detector, Form("GetFile - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
2069 // check connection, in case connect
2070 if (!Connect(system))
2072 Log(detector, Form("GetFile - Couldn't connect to %s FXS database", GetSystemName(system)));
2076 // Query preparation
2077 TString sourceName(source);
2079 TString sqlQueryStart = Form("select filePath,size,fileChecksum from %s where",
2080 fConfig->GetFXSdbTable(system));
2081 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
2082 GetCurrentRun(), detector, id);
2086 whereClause += Form(" and DAQsource=\"%s\"", source);
2088 else if (system == kDCS)
2092 else if (system == kHLT)
2094 whereClause += Form(" and DDLnumbers=\"%s\"", source);
2098 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
2100 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2103 TSQLResult* aResult = 0;
2104 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2106 Log(detector, Form("GetFileName - Can't execute SQL query to %s database for: id = %s, source = %s",
2107 GetSystemName(system), id, sourceName.Data()));
2111 if(aResult->GetRowCount() == 0)
2114 Form("GetFileName - No entry in %s FXS db for: id = %s, source = %s",
2115 GetSystemName(system), id, sourceName.Data()));
2120 if (aResult->GetRowCount() > 1) {
2122 Form("GetFileName - More than one entry in %s FXS db for: id = %s, source = %s",
2123 GetSystemName(system), id, sourceName.Data()));
2128 if (aResult->GetFieldCount() != nFields) {
2130 Form("GetFileName - Wrong field count in %s FXS db for: id = %s, source = %s",
2131 GetSystemName(system), id, sourceName.Data()));
2136 TSQLRow* aRow = dynamic_cast<TSQLRow*> (aResult->Next());
2139 Log(detector, Form("GetFileName - Empty set result in %s FXS db from query: id = %s, source = %s",
2140 GetSystemName(system), id, sourceName.Data()));
2145 TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
2146 TString fileSize(aRow->GetField(1), aRow->GetFieldLength(1));
2147 TString fileChecksum(aRow->GetField(2), aRow->GetFieldLength(2));
2152 AliDebug(2, Form("filePath = %s; size = %s, fileChecksum = %s",
2153 filePath.Data(), fileSize.Data(), fileChecksum.Data()));
2155 // retrieved file is renamed to make it unique
2156 TString localFileName = Form("%s/%s_%d_process/%s_%s_%d_%s_%s.shuttle",
2157 GetShuttleTempDir(), detector, GetCurrentRun(),
2158 GetSystemName(system), detector, GetCurrentRun(),
2159 id, sourceName.Data());
2162 // file retrieval from FXS
2163 UInt_t nRetries = 0;
2164 UInt_t maxRetries = 3;
2165 Bool_t result = kFALSE;
2167 // copy!! if successful TSystem::Exec returns 0
2168 while(nRetries++ < maxRetries) {
2169 AliDebug(2, Form("Trying to copy file. Retry # %d", nRetries));
2170 result = RetrieveFile(system, filePath.Data(), localFileName.Data());
2173 Log(detector, Form("GetFileName - Copy of file %s from %s FXS failed",
2174 filePath.Data(), GetSystemName(system)));
2178 if (fileChecksum.Length()>0)
2180 // compare md5sum of local file with the one stored in the FXS DB
2181 Int_t md5Comp = gSystem->Exec(Form("md5sum %s |grep %s 2>&1 > /dev/null",
2182 localFileName.Data(), fileChecksum.Data()));
2186 Log(detector, Form("GetFileName - md5sum of file %s does not match with local copy!",
2192 Log(fCurrentDetector, Form("GetFile - md5sum of file %s not set in %s database, skipping comparison",
2193 filePath.Data(), GetSystemName(system)));
2198 if(!result) return 0;
2200 fFXSCalled[system]=kTRUE;
2201 TObjString *fileParams = new TObjString(Form("%s#!?!#%s", id, sourceName.Data()));
2202 fFXSlist[system].Add(fileParams);
2204 static TString staticLocalFileName;
2205 staticLocalFileName.Form("%s", localFileName.Data());
2207 Log(fCurrentDetector, Form("GetFile - Retrieved file with id %s and "
2208 "source %s from %s to %s", id, source,
2209 GetSystemName(system), localFileName.Data()));
2211 return staticLocalFileName.Data();
2214 //______________________________________________________________________________________________
2215 Bool_t AliShuttle::RetrieveFile(UInt_t system, const char* fxsFileName, const char* localFileName)
2218 // Copies file from FXS to local Shuttle machine
2221 // check temp directory: trying to cd to temp; if it does not exist, create it
2222 AliDebug(2, Form("Copy file %s from %s FXS into %s",
2223 GetSystemName(system), fxsFileName, localFileName));
2225 TString tmpDir(localFileName);
2227 tmpDir = tmpDir(0,tmpDir.Last('/'));
2229 Int_t noDir = gSystem->GetPathInfo(tmpDir.Data(), 0, (Long64_t*) 0, 0, 0);
2230 if (noDir) // temp dir does not exists!
2232 if (gSystem->mkdir(tmpDir.Data(), 1))
2234 Log(fCurrentDetector.Data(), "RetrieveFile - could not make temp directory!!");
2239 TString baseFXSFolder;
2242 baseFXSFolder = "FES/";
2244 else if (system == kDCS)
2248 else if (system == kHLT)
2250 baseFXSFolder = "/opt/FXS/";
2254 TString command = Form("scp -oPort=%d -2 %s@%s:%s%s %s",
2255 fConfig->GetFXSPort(system),
2256 fConfig->GetFXSUser(system),
2257 fConfig->GetFXSHost(system),
2258 baseFXSFolder.Data(),
2262 AliDebug(2, Form("%s",command.Data()));
2264 Bool_t result = (gSystem->Exec(command.Data()) == 0);
2269 //______________________________________________________________________________________________
2270 TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
2273 // Get sources producing the condition file Id from file exchange servers
2274 // if id is NULL all sources are returned (distinct)
2277 Log(detector, Form("GetFileSources - Retrieving sources with id %s from %s", id, GetSystemName(system)));
2279 // check if test mode should simulate a FXS error
2280 if (fTestMode & kErrorFXSSources)
2282 Log(detector, Form("GetFileSources - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
2288 Log(detector, "GetFileSources - WARNING: DCS system has only one source of data!");
2289 TList *list = new TList();
2291 list->Add(new TObjString(" "));
2295 // check connection, in case connect
2296 if (!Connect(system))
2298 Log(detector, Form("GetFileSources - Couldn't connect to %s FXS database", GetSystemName(system)));
2302 TString sourceName = 0;
2305 sourceName = "DAQsource";
2306 } else if (system == kHLT)
2308 sourceName = "DDLnumbers";
2311 TString sqlQueryStart = Form("select distinct %s from %s where", sourceName.Data(), fConfig->GetFXSdbTable(system));
2312 TString whereClause = Form("run=%d and detector=\"%s\"",
2313 GetCurrentRun(), detector);
2315 whereClause += Form(" and fileId=\"%s\"", id);
2316 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
2318 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2321 TSQLResult* aResult;
2322 aResult = fServer[system]->Query(sqlQuery);
2324 Log(detector, Form("GetFileSources - Can't execute SQL query to %s database for id: %s",
2325 GetSystemName(system), id));
2329 TList *list = new TList();
2332 if (aResult->GetRowCount() == 0)
2335 Form("GetFileSources - No entry in %s FXS table for id: %s", GetSystemName(system), id));
2340 Log(detector, Form("GetFileSources - Found %d sources", aResult->GetRowCount()));
2343 while ((aRow = aResult->Next()))
2346 TString source(aRow->GetField(0), aRow->GetFieldLength(0));
2347 AliDebug(2, Form("%s = %s", sourceName.Data(), source.Data()));
2348 list->Add(new TObjString(source));
2357 //______________________________________________________________________________________________
2358 TList* AliShuttle::GetFileIDs(Int_t system, const char* detector, const char* source)
2361 // Get all ids of condition files produced by a given source from file exchange servers
2364 Log(detector, Form("GetFileIDs - Retrieving ids with source %s with %s", source, GetSystemName(system)));
2366 // check if test mode should simulate a FXS error
2367 if (fTestMode & kErrorFXSSources)
2369 Log(detector, Form("GetFileIDs - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
2373 // check connection, in case connect
2374 if (!Connect(system))
2376 Log(detector, Form("GetFileIDs - Couldn't connect to %s FXS database", GetSystemName(system)));
2380 TString sourceName = 0;
2383 sourceName = "DAQsource";
2384 } else if (system == kHLT)
2386 sourceName = "DDLnumbers";
2389 TString sqlQueryStart = Form("select fileId from %s where", fConfig->GetFXSdbTable(system));
2390 TString whereClause = Form("run=%d and detector=\"%s\"",
2391 GetCurrentRun(), detector);
2392 if (sourceName.Length() > 0 && source)
2393 whereClause += Form(" and %s=\"%s\"", sourceName.Data(), source);
2394 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
2396 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2399 TSQLResult* aResult;
2400 aResult = fServer[system]->Query(sqlQuery);
2402 Log(detector, Form("GetFileIDs - Can't execute SQL query to %s database for source: %s",
2403 GetSystemName(system), source));
2407 TList *list = new TList();
2410 if (aResult->GetRowCount() == 0)
2413 Form("GetFileIDs - No entry in %s FXS table for source: %s", GetSystemName(system), source));
2418 Log(detector, Form("GetFileIDs - Found %d ids", aResult->GetRowCount()));
2422 while ((aRow = aResult->Next()))
2425 TString id(aRow->GetField(0), aRow->GetFieldLength(0));
2426 AliDebug(2, Form("fileId = %s", id.Data()));
2427 list->Add(new TObjString(id));
2436 //______________________________________________________________________________________________
2437 Bool_t AliShuttle::Connect(Int_t system)
2439 // Connect to MySQL Server of the system's FXS MySQL databases
2440 // DAQ Logbook, Shuttle Logbook and DAQ FXS db are on the same host
2443 // check connection: if already connected return
2444 if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
2446 TString dbHost, dbUser, dbPass, dbName;
2448 if (system < 3) // FXS db servers
2450 dbHost = Form("mysql://%s:%d", fConfig->GetFXSdbHost(system), fConfig->GetFXSdbPort(system));
2451 dbUser = fConfig->GetFXSdbUser(system);
2452 dbPass = fConfig->GetFXSdbPass(system);
2453 dbName = fConfig->GetFXSdbName(system);
2454 } else { // Run & Shuttle logbook servers
2455 // TODO Will the Shuttle logbook server be the same as the Run logbook server ???
2456 dbHost = Form("mysql://%s:%d", fConfig->GetDAQlbHost(), fConfig->GetDAQlbPort());
2457 dbUser = fConfig->GetDAQlbUser();
2458 dbPass = fConfig->GetDAQlbPass();
2459 dbName = fConfig->GetDAQlbDB();
2462 fServer[system] = TSQLServer::Connect(dbHost.Data(), dbUser.Data(), dbPass.Data());
2463 if (!fServer[system] || !fServer[system]->IsConnected()) {
2466 AliError(Form("Can't establish connection to FXS database for %s",
2467 AliShuttleInterface::GetSystemName(system)));
2469 AliError("Can't establish connection to Run logbook.");
2471 if(fServer[system]) delete fServer[system];
2476 TSQLResult* aResult=0;
2479 aResult = fServer[kDAQ]->GetTables(dbName.Data());
2482 aResult = fServer[kDCS]->GetTables(dbName.Data());
2485 aResult = fServer[kHLT]->GetTables(dbName.Data());
2488 aResult = fServer[3]->GetTables(dbName.Data());
2496 //______________________________________________________________________________________________
2497 Bool_t AliShuttle::UpdateTable()
2500 // Update FXS table filling time_processed field in all rows corresponding to current run and detector
2503 Bool_t result = kTRUE;
2505 for (UInt_t system=0; system<3; system++)
2507 if(!fFXSCalled[system]) continue;
2509 // check connection, in case connect
2510 if (!Connect(system))
2512 Log(fCurrentDetector, Form("UpdateTable - Couldn't connect to %s FXS database", GetSystemName(system)));
2517 TTimeStamp now; // now
2519 // Loop on FXS list entries
2520 TIter iter(&fFXSlist[system]);
2521 TObjString *aFXSentry=0;
2522 while ((aFXSentry = dynamic_cast<TObjString*> (iter.Next())))
2524 TString aFXSentrystr = aFXSentry->String();
2525 TObjArray *aFXSarray = aFXSentrystr.Tokenize("#!?!#");
2526 if (!aFXSarray || aFXSarray->GetEntries() != 2 )
2528 Log(fCurrentDetector, Form("UpdateTable - error updating %s FXS entry. Check string: <%s>",
2529 GetSystemName(system), aFXSentrystr.Data()));
2530 if(aFXSarray) delete aFXSarray;
2534 const char* fileId = ((TObjString*) aFXSarray->At(0))->GetName();
2535 const char* source = ((TObjString*) aFXSarray->At(1))->GetName();
2537 TString whereClause;
2540 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\";",
2541 GetCurrentRun(), fCurrentDetector.Data(), fileId, source);
2543 else if (system == kDCS)
2545 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\";",
2546 GetCurrentRun(), fCurrentDetector.Data(), fileId);
2548 else if (system == kHLT)
2550 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DDLnumbers=\"%s\";",
2551 GetCurrentRun(), fCurrentDetector.Data(), fileId, source);
2556 TString sqlQuery = Form("update %s set time_processed=%d %s", fConfig->GetFXSdbTable(system),
2557 now.GetSec(), whereClause.Data());
2559 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2562 TSQLResult* aResult;
2563 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2566 Log(fCurrentDetector, Form("UpdateTable - %s db: can't execute SQL query <%s>",
2567 GetSystemName(system), sqlQuery.Data()));
2578 //______________________________________________________________________________________________
2579 Bool_t AliShuttle::UpdateTableFailCase()
2581 // Update FXS table filling time_processed field in all rows corresponding to current run and detector
2582 // this is called in case the preprocessor is declared failed for the current run, because
2583 // the fields are updated only in case of success
2585 Bool_t result = kTRUE;
2587 for (UInt_t system=0; system<3; system++)
2589 // check connection, in case connect
2590 if (!Connect(system))
2592 Log(fCurrentDetector, Form("UpdateTableFailCase - Couldn't connect to %s FXS database",
2593 GetSystemName(system)));
2598 TTimeStamp now; // now
2600 // Loop on FXS list entries
2602 TString whereClause = Form("where run=%d and detector=\"%s\";",
2603 GetCurrentRun(), fCurrentDetector.Data());
2606 TString sqlQuery = Form("update %s set time_processed=%d %s", fConfig->GetFXSdbTable(system),
2607 now.GetSec(), whereClause.Data());
2609 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2612 TSQLResult* aResult;
2613 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2616 Log(fCurrentDetector, Form("UpdateTableFailCase - %s db: can't execute SQL query <%s>",
2617 GetSystemName(system), sqlQuery.Data()));
2627 //______________________________________________________________________________________________
2628 Bool_t AliShuttle::UpdateShuttleLogbook(const char* detector, const char* status)
2631 // Update Shuttle logbook filling detector or shuttle_done column
2632 // ex. of usage: UpdateShuttleLogbook("PHOS", "DONE") or UpdateShuttleLogbook("shuttle_done")
2635 // check connection, in case connect
2637 Log("SHUTTLE", "UpdateShuttleLogbook - Couldn't connect to DAQ Logbook.");
2641 TString detName(detector);
2643 if(detName == "shuttle_done")
2645 setClause = "set shuttle_done=1";
2647 // Send the information to ML
2648 TMonaLisaText mlStatus("SHUTTLE_status", "Done");
2651 mlList.Add(&mlStatus);
2653 fMonaLisa->SendParameters(&mlList);
2655 TString statusStr(status);
2656 if(statusStr.Contains("done", TString::kIgnoreCase) ||
2657 statusStr.Contains("failed", TString::kIgnoreCase)){
2658 setClause = Form("set %s=\"%s\"", detector, status);
2661 Form("UpdateShuttleLogbook - Invalid status <%s> for detector %s",
2667 TString whereClause = Form("where run=%d", GetCurrentRun());
2669 TString sqlQuery = Form("update %s %s %s",
2670 fConfig->GetShuttlelbTable(), setClause.Data(), whereClause.Data());
2672 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2675 TSQLResult* aResult;
2676 aResult = dynamic_cast<TSQLResult*> (fServer[3]->Query(sqlQuery));
2678 Log("SHUTTLE", Form("UpdateShuttleLogbook - Can't execute query <%s>", sqlQuery.Data()));
2686 //______________________________________________________________________________________________
2687 Int_t AliShuttle::GetCurrentRun() const
2690 // Get current run from logbook entry
2693 return fLogbookEntry ? fLogbookEntry->GetRun() : -1;
2696 //______________________________________________________________________________________________
2697 UInt_t AliShuttle::GetCurrentStartTime() const
2700 // get current start time
2703 return fLogbookEntry ? fLogbookEntry->GetStartTime() : 0;
2706 //______________________________________________________________________________________________
2707 UInt_t AliShuttle::GetCurrentEndTime() const
2710 // get current end time from logbook entry
2713 return fLogbookEntry ? fLogbookEntry->GetEndTime() : 0;
2716 //______________________________________________________________________________________________
2717 UInt_t AliShuttle::GetCurrentYear() const
2720 // Get current year from logbook entry
2723 if (!fLogbookEntry) return 0;
2725 TTimeStamp startTime(GetCurrentStartTime());
2726 TString year = Form("%d",startTime.GetDate());
2732 //______________________________________________________________________________________________
2733 const char* AliShuttle::GetLHCPeriod() const
2736 // Get current LHC period from logbook entry
2739 if (!fLogbookEntry) return 0;
2741 return fLogbookEntry->GetRunParameter("LHCperiod");
2744 //______________________________________________________________________________________________
2745 void AliShuttle::Log(const char* detector, const char* message)
2748 // Fill log string with a message
2751 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
2753 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE)) {
2754 AliError(Form("Can't open directory <%s>", GetShuttleLogDir()));
2759 gSystem->FreeDirectory(dir);
2762 TString toLog = Form("%s (%d): %s - ", TTimeStamp(time(0)).AsString("s"), getpid(), detector);
2763 if (GetCurrentRun() >= 0)
2764 toLog += Form("run %d - ", GetCurrentRun());
2765 toLog += Form("%s", message);
2767 AliInfo(toLog.Data());
2769 // if we redirect the log output already to the file, leave here
2770 if (fOutputRedirected && strcmp(detector, "SHUTTLE") != 0)
2773 TString fileName = GetLogFileName(detector);
2775 gSystem->ExpandPathName(fileName);
2778 logFile.open(fileName, ofstream::out | ofstream::app);
2780 if (!logFile.is_open()) {
2781 AliError(Form("Could not open file %s", fileName.Data()));
2785 logFile << toLog.Data() << "\n";
2790 //______________________________________________________________________________________________
2791 TString AliShuttle::GetLogFileName(const char* detector) const
2794 // returns the name of the log file for a given sub detector
2799 if (GetCurrentRun() >= 0)
2800 fileName.Form("%s/%s_%d.log", GetShuttleLogDir(), detector, GetCurrentRun());
2802 fileName.Form("%s/%s.log", GetShuttleLogDir(), detector);
2807 //______________________________________________________________________________________________
2808 Bool_t AliShuttle::Collect(Int_t run)
2811 // Collects conditions data for all UNPROCESSED run written to DAQ LogBook in case of run = -1 (default)
2812 // If a dedicated run is given this run is processed
2814 // In operational mode, this is the Shuttle function triggered by the EOR signal.
2818 Log("SHUTTLE","Collect - Shuttle called. Collecting conditions data for unprocessed runs");
2820 Log("SHUTTLE", Form("Collect - Shuttle called. Collecting conditions data for run %d", run));
2822 SetLastAction("Starting");
2824 TString whereClause("where shuttle_done=0");
2826 whereClause += Form(" and run=%d", run);
2828 TObjArray shuttleLogbookEntries;
2829 if (!QueryShuttleLogbook(whereClause, shuttleLogbookEntries))
2831 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2835 if (shuttleLogbookEntries.GetEntries() == 0)
2838 Log("SHUTTLE","Collect - Found no UNPROCESSED runs in Shuttle logbook");
2840 Log("SHUTTLE", Form("Collect - Run %d is already DONE "
2841 "or it does not exist in Shuttle logbook", run));
2845 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
2846 fFirstUnprocessed[iDet] = kTRUE;
2850 // query Shuttle logbook for earlier runs, check if some detectors are unprocessed,
2851 // flag them into fFirstUnprocessed array
2852 TString whereClause(Form("where shuttle_done=0 and run < %d", run));
2853 TObjArray tmpLogbookEntries;
2854 if (!QueryShuttleLogbook(whereClause, tmpLogbookEntries))
2856 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2860 TIter iter(&tmpLogbookEntries);
2861 AliShuttleLogbookEntry* anEntry = 0;
2862 while ((anEntry = dynamic_cast<AliShuttleLogbookEntry*> (iter.Next())))
2864 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
2866 if (anEntry->GetDetectorStatus(iDet) == AliShuttleLogbookEntry::kUnprocessed)
2868 AliDebug(2, Form("Run %d: setting %s as \"not first time unprocessed\"",
2869 anEntry->GetRun(), GetDetName(iDet)));
2870 fFirstUnprocessed[iDet] = kFALSE;
2878 if (!RetrieveConditionsData(shuttleLogbookEntries))
2880 Log("SHUTTLE", "Collect - Process of at least one run failed");
2884 Log("SHUTTLE", "Collect - Requested run(s) successfully processed");
2888 //______________________________________________________________________________________________
2889 Bool_t AliShuttle::RetrieveConditionsData(const TObjArray& dateEntries)
2892 // Retrieve conditions data for all runs that aren't processed yet
2895 Bool_t hasError = kFALSE;
2897 TIter iter(&dateEntries);
2898 AliShuttleLogbookEntry* anEntry;
2900 while ((anEntry = (AliShuttleLogbookEntry*) iter.Next())){
2901 if (!Process(anEntry)){
2905 // clean SHUTTLE temp directory
2906 //TString filename = Form("%s/*.shuttle", GetShuttleTempDir());
2907 //RemoveFile(filename.Data());
2910 return hasError == kFALSE;
2913 //______________________________________________________________________________________________
2914 ULong_t AliShuttle::GetTimeOfLastAction() const
2917 // Gets time of last action
2922 fMonitoringMutex->Lock();
2924 tmp = fLastActionTime;
2926 fMonitoringMutex->UnLock();
2931 //______________________________________________________________________________________________
2932 const TString AliShuttle::GetLastAction() const
2935 // returns a string description of the last action
2940 fMonitoringMutex->Lock();
2944 fMonitoringMutex->UnLock();
2949 //______________________________________________________________________________________________
2950 void AliShuttle::SetLastAction(const char* action)
2953 // updates the monitoring variables
2956 fMonitoringMutex->Lock();
2958 fLastAction = action;
2959 fLastActionTime = time(0);
2961 fMonitoringMutex->UnLock();
2964 //______________________________________________________________________________________________
2965 const char* AliShuttle::GetRunParameter(const char* param)
2968 // returns run parameter read from DAQ logbook
2971 if(!fLogbookEntry) {
2972 AliError("No logbook entry!");
2976 return fLogbookEntry->GetRunParameter(param);
2979 //______________________________________________________________________________________________
2980 AliCDBEntry* AliShuttle::GetFromOCDB(const char* detector, const AliCDBPath& path)
2983 // returns object from OCDB valid for current run
2986 if (fTestMode & kErrorOCDB)
2988 Log(detector, "GetFromOCDB - In TESTMODE - Simulating error with OCDB");
2992 AliCDBStorage *sto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
2995 Log(detector, "GetFromOCDB - Cannot activate main OCDB for query!");
2999 return dynamic_cast<AliCDBEntry*> (sto->Get(path, GetCurrentRun()));
3002 //______________________________________________________________________________________________
3003 Bool_t AliShuttle::SendMail()
3006 // sends a mail to the subdetector expert in case of preprocessor error
3009 if (fTestMode != kNone)
3012 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
3015 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE))
3017 Log("SHUTTLE", Form("SendMail - Can't open directory <%s>", GetShuttleLogDir()));
3022 gSystem->FreeDirectory(dir);
3025 TString bodyFileName;
3026 bodyFileName.Form("%s/mail.body", GetShuttleLogDir());
3027 gSystem->ExpandPathName(bodyFileName);
3030 mailBody.open(bodyFileName, ofstream::out);
3032 if (!mailBody.is_open())
3034 Log("SHUTTLE", Form("Could not open mail body file %s", bodyFileName.Data()));
3039 TIter iterExperts(fConfig->GetResponsibles(fCurrentDetector));
3040 TObjString *anExpert=0;
3041 while ((anExpert = (TObjString*) iterExperts.Next()))
3043 to += Form("%s,", anExpert->GetName());
3045 to.Remove(to.Length()-1);
3046 AliDebug(2, Form("to: %s",to.Data()));
3049 Log("SHUTTLE", "List of detector responsibles not yet set!");
3053 TString cc="alberto.colla@cern.ch";
3055 TString subject = Form("%s Shuttle preprocessor FAILED in run %d !",
3056 fCurrentDetector.Data(), GetCurrentRun());
3057 AliDebug(2, Form("subject: %s", subject.Data()));
3059 TString body = Form("Dear %s expert(s), \n\n", fCurrentDetector.Data());
3060 body += Form("SHUTTLE just detected that your preprocessor "
3061 "failed processing run %d!!\n\n", GetCurrentRun());
3062 body += Form("Please check %s status on the SHUTTLE monitoring page: \n\n", fCurrentDetector.Data());
3063 body += Form("\thttp://pcalimonitor.cern.ch:8889/shuttle.jsp?time=168 \n\n");
3064 body += Form("Find the %s log for the current run on \n\n"
3065 "\thttp://pcalishuttle01.cern.ch:8880/logs/%s_%d.log \n\n",
3066 fCurrentDetector.Data(), fCurrentDetector.Data(), GetCurrentRun());
3067 body += Form("The last 10 lines of %s log file are following:\n\n");
3069 AliDebug(2, Form("Body begin: %s", body.Data()));
3071 mailBody << body.Data();
3073 mailBody.open(bodyFileName, ofstream::out | ofstream::app);
3075 TString logFileName = Form("%s/%s_%d.log", GetShuttleLogDir(), fCurrentDetector.Data(), GetCurrentRun());
3076 TString tailCommand = Form("tail -n 10 %s >> %s", logFileName.Data(), bodyFileName.Data());
3077 if (gSystem->Exec(tailCommand.Data()))
3079 mailBody << Form("%s log file not found ...\n\n", fCurrentDetector.Data());
3082 TString endBody = Form("------------------------------------------------------\n\n");
3083 endBody += Form("In case of problems please contact the SHUTTLE core team.\n\n");
3084 endBody += "Please do not answer this message directly, it is automatically generated.\n\n";
3085 endBody += "Greetings,\n\n \t\t\tthe SHUTTLE\n";
3087 AliDebug(2, Form("Body end: %s", endBody.Data()));
3089 mailBody << endBody.Data();
3094 TString mailCommand = Form("mail -s \"%s\" -c %s %s < %s",
3098 bodyFileName.Data());
3099 AliDebug(2, Form("mail command: %s", mailCommand.Data()));
3101 Bool_t result = gSystem->Exec(mailCommand.Data());
3106 //______________________________________________________________________________________________
3107 Bool_t AliShuttle::SendMailToDCS()
3110 // sends a mail to the DCS experts in case of DCS error
3113 if (fTestMode != kNone)
3116 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
3119 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE))
3121 Log("SHUTTLE", Form("SendMailToDCS - Can't open directory <%s>", GetShuttleLogDir()));
3126 gSystem->FreeDirectory(dir);
3129 TString bodyFileName;
3130 bodyFileName.Form("%s/mail.body", GetShuttleLogDir());
3131 gSystem->ExpandPathName(bodyFileName);
3134 mailBody.open(bodyFileName, ofstream::out);
3136 if (!mailBody.is_open())
3138 Log("SHUTTLE", Form("SendMailToDCS - Could not open mail body file %s", bodyFileName.Data()));
3142 TString to="Vladimir.Fekete@cern.ch, Svetozar.Kapusta@cern.ch";
3143 //TString to="alberto.colla@cern.ch";
3144 AliDebug(2, Form("to: %s",to.Data()));
3147 Log("SHUTTLE", "List of detector responsibles not yet set!");
3151 TString cc="alberto.colla@cern.ch";
3153 TString subject = Form("Retrieval of data points for %s FAILED in run %d !",
3154 fCurrentDetector.Data(), GetCurrentRun());
3155 AliDebug(2, Form("subject: %s", subject.Data()));
3157 TString body = Form("Dear DCS experts, \n\n");
3158 body += Form("SHUTTLE couldn\'t retrieve the data points for detector %s "
3159 "in run %d!!\n\n", fCurrentDetector.Data(), GetCurrentRun());
3160 body += Form("Please check %s status on the SHUTTLE monitoring page: \n\n", fCurrentDetector.Data());
3161 body += Form("\thttp://pcalimonitor.cern.ch:8889/shuttle.jsp?time=168 \n\n");
3162 body += Form("Find the %s log for the current run on \n\n"
3163 "\thttp://pcalishuttle01.cern.ch:8880/logs/%s_%d.log \n\n",
3164 fCurrentDetector.Data(), fCurrentDetector.Data(), GetCurrentRun());
3165 body += Form("The last 10 lines of %s log file are following:\n\n");
3167 AliDebug(2, Form("Body begin: %s", body.Data()));
3169 mailBody << body.Data();
3171 mailBody.open(bodyFileName, ofstream::out | ofstream::app);
3173 TString logFileName = Form("%s/%s_%d.log", GetShuttleLogDir(), fCurrentDetector.Data(), GetCurrentRun());
3174 TString tailCommand = Form("tail -n 10 %s >> %s", logFileName.Data(), bodyFileName.Data());
3175 if (gSystem->Exec(tailCommand.Data()))
3177 mailBody << Form("%s log file not found ...\n\n", fCurrentDetector.Data());
3180 TString endBody = Form("------------------------------------------------------\n\n");
3181 endBody += Form("In case of problems please contact the SHUTTLE core team.\n\n");
3182 endBody += "Please do not answer this message directly, it is automatically generated.\n\n";
3183 endBody += "Greetings,\n\n \t\t\tthe SHUTTLE\n";
3185 AliDebug(2, Form("Body end: %s", endBody.Data()));
3187 mailBody << endBody.Data();
3192 TString mailCommand = Form("mail -s \"%s\" -c %s %s < %s",
3196 bodyFileName.Data());
3197 AliDebug(2, Form("mail command: %s", mailCommand.Data()));
3199 Bool_t result = gSystem->Exec(mailCommand.Data());
3204 //______________________________________________________________________________________________
3205 const char* AliShuttle::GetRunType()
3208 // returns run type read from "run type" logbook
3211 if(!fLogbookEntry) {
3212 AliError("No logbook entry!");
3216 return fLogbookEntry->GetRunType();
3219 //______________________________________________________________________________________________
3220 Bool_t AliShuttle::GetHLTStatus()
3222 // Return HLT status (ON=1 OFF=0)
3223 // Converts the HLT status from the status string read in the run logbook (not just a bool)
3225 if(!fLogbookEntry) {
3226 AliError("No logbook entry!");
3230 // TODO implement when HLTStatus is inserted in run logbook
3231 //TString hltStatus = fLogbookEntry->GetRunParameter("HLTStatus");
3232 //if(hltStatus == "OFF") {return kFALSE};
3237 //______________________________________________________________________________________________
3238 void AliShuttle::SetShuttleTempDir(const char* tmpDir)
3241 // sets Shuttle temp directory
3244 fgkShuttleTempDir = gSystem->ExpandPathName(tmpDir);
3247 //______________________________________________________________________________________________
3248 void AliShuttle::SetShuttleLogDir(const char* logDir)
3251 // sets Shuttle log directory
3254 fgkShuttleLogDir = gSystem->ExpandPathName(logDir);