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.64 2007/11/13 16:15:47 acolla
19 DCS map is stored in a file in the temp folder where the detector is processed.
20 If the preprocessor fails, the temp folder is not removed. This will help the debugging of the problem.
22 Revision 1.63 2007/11/02 10:53:16 acolla
23 Protection added to AliShuttle::CopyFileLocally
25 Revision 1.62 2007/10/31 18:23:13 acolla
26 Furter developement on the Shuttle:
28 - Shuttle now connects to the Grid as alidaq. The OCDB and Reference folders
29 are now built from /alice/data, e.g.:
30 /alice/data/2007/LHC07a/OCDB
32 the year and LHC period are taken from the Shuttle.
33 Raw metadata files are stored by GRP to:
34 /alice/data/2007/LHC07a/<runNb>/Raw/RunMetadata.root
36 - Shuttle sends a mail to DCS experts each time DP retrieval fails.
38 Revision 1.61 2007/10/30 20:33:51 acolla
39 Improved managing of temporary folders, which weren't correctly handled.
40 Resolved bug introduced in StoreReferenceFile, which caused SPD preprocessor fail.
42 Revision 1.60 2007/10/29 18:06:16 acolla
44 New function StoreRunMetadataFile added to preprocessor and Shuttle interface
45 This function can be used by GRP only. It stores raw data tags merged file to the
46 raw data folder (e.g. /alice/data/2008/LHC08a/000099999/Raw).
50 1. Shuttle cannot write to /alice/data/ because it belongs to alidaq. Tag file is stored in /alice/simulation/... for the time being.
51 2. Due to a bug in TAlien::Mkdir, the creation of a folder in recursive mode (-p option) does not work. The problem
52 has been corrected in the root package on the Shuttle machine.
54 Revision 1.59 2007/10/05 12:40:55 acolla
56 Result error code added to AliDCSClient data members (it was "lost" with the new implementation of TMap* GetAliasValues and GetDPValues).
58 Revision 1.58 2007/09/28 15:27:40 acolla
60 AliDCSClient "multiSplit" option added in the DCS configuration
61 in AliDCSMessage: variable MAX_BODY_SIZE set to 500000
63 Revision 1.57 2007/09/27 16:53:13 acolla
64 Detectors can have more than one AMANDA server. SHUTTLE queries the servers sequentially,
65 merges the dcs aliases/DPs in one TMap and sends it to the preprocessor.
67 Revision 1.56 2007/09/14 16:46:14 jgrosseo
68 1) Connect and Close are called before and after each query, so one can
69 keep the same AliDCSClient object.
70 2) The splitting of a query is moved to GetDPValues/GetAliasValues.
71 3) Splitting interval can be specified in constructor
73 Revision 1.55 2007/08/06 12:26:40 acolla
74 Function Bool_t GetHLTStatus added to preprocessor. It returns the status of HLT
75 read from the run logbook.
77 Revision 1.54 2007/07/12 09:51:25 jgrosseo
78 removed duplicated log message in GetFile
80 Revision 1.53 2007/07/12 09:26:28 jgrosseo
81 updating hlt fxs base path
83 Revision 1.52 2007/07/12 08:06:45 jgrosseo
84 adding log messages in getfile... functions
85 adding not implemented copy constructor in alishuttleconfigholder
87 Revision 1.51 2007/07/03 17:24:52 acolla
88 root moved to v5-16-00. TFileMerger->Cp moved to TFile::Cp.
90 Revision 1.50 2007/07/02 17:19:32 acolla
91 preprocessor is run in a temp directory that is removed when process is finished.
93 Revision 1.49 2007/06/29 10:45:06 acolla
94 Number of columns in MySql Shuttle logbook increased by one (HLT added)
96 Revision 1.48 2007/06/21 13:06:19 acolla
97 GetFileSources returns dummy list with 1 source if system=DCS (better than
98 returning error as it was)
100 Revision 1.47 2007/06/19 17:28:56 acolla
101 HLT updated; missing map bug removed.
103 Revision 1.46 2007/06/09 13:01:09 jgrosseo
104 Switching to retrieval of several DCS DPs at a time (multiDPrequest)
106 Revision 1.45 2007/05/30 06:35:20 jgrosseo
107 Adding functionality to the Shuttle/TestShuttle:
108 o) Function to retrieve list of sources from a given system (GetFileSources with id=0)
109 o) Function to retrieve list of IDs for a given source (GetFileIDs)
110 These functions are needed for dealing with the tag files that are saved for the GRP preprocessor
111 Example code has been added to the TestProcessor in TestShuttle
113 Revision 1.44 2007/05/11 16:09:32 acolla
114 Reference files for ITS, MUON and PHOS are now stored in OfflineDetName/OnlineDetName/run_...
115 example: ITS/SPD/100_filename.root
117 Revision 1.43 2007/05/10 09:59:51 acolla
118 Various bug fixes in StoreRefFilesToGrid; Cleaning of reference storage before processing detector (CleanReferenceStorage)
120 Revision 1.42 2007/05/03 08:01:39 jgrosseo
121 typo in last commit :-(
123 Revision 1.41 2007/05/03 08:00:48 jgrosseo
124 fixing log message when pp want to skip dcs value retrieval
126 Revision 1.40 2007/04/27 07:06:48 jgrosseo
127 GetFileSources returns empty list in case of no files, but successful query
128 No mails sent in testmode
130 Revision 1.39 2007/04/17 12:43:57 acolla
131 Correction in StoreOCDB; change of text in mail to detector expert
133 Revision 1.38 2007/04/12 08:26:18 jgrosseo
136 Revision 1.37 2007/04/10 16:53:14 jgrosseo
137 redirecting sub detector stdout, stderr to sub detector log file
139 Revision 1.35 2007/04/04 16:26:38 acolla
140 1. Re-organization of function calls in TestPreprocessor to make it more meaningful.
141 2. Added missing dependency in test preprocessors.
142 3. in AliShuttle.cxx: processing time and memory consumption info on a single line.
144 Revision 1.34 2007/04/04 10:33:36 jgrosseo
145 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.
146 In case of an error with the Grid, the Shuttle will retry the storing later, the preprocessor does not need to be run again.
148 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.
150 3) New function StoreReferenceFile to _directly_ store a file (without opening it) to the reference storage.
152 4) The memory usage of the preprocessor is monitored. If it exceeds 2 GB it is terminated.
154 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.
155 If you always need DCS data (like before), you do not need to implement it.
157 6) The run type has been added to the monitoring page
159 Revision 1.33 2007/04/03 13:56:01 acolla
160 Grid Storage at the end of preprocessing. Added virtual method to disable DCS query according to the
163 Revision 1.32 2007/02/28 10:41:56 acolla
164 Run type field added in SHUTTLE framework. Run type is read from "run type" logbook and retrieved by
165 AliPreprocessor::GetRunType() function.
166 Added some ldap definition files.
168 Revision 1.30 2007/02/13 11:23:21 acolla
169 Moved getters and setters of Shuttle's main OCDB/Reference, local
170 OCDB/Reference, temp and log folders to AliShuttleInterface
172 Revision 1.27 2007/01/30 17:52:42 jgrosseo
173 adding monalisa monitoring
175 Revision 1.26 2007/01/23 19:20:03 acolla
176 Removed old ldif files, added TOF, MCH ldif files. Added some options in
177 AliShuttleConfig::Print. Added in Ali Shuttle: SetShuttleTempDir and
180 Revision 1.25 2007/01/15 19:13:52 acolla
181 Moved some AliInfo to AliDebug in SendMail function
183 Revision 1.21 2006/12/07 08:51:26 jgrosseo
185 table, db names in ldap configuration
186 added GRP preprocessor
187 DCS data can also be retrieved by data point
189 Revision 1.20 2006/11/16 16:16:48 jgrosseo
190 introducing strict run ordering flag
191 removed giving preprocessor name to preprocessor, they have to know their name themselves ;-)
193 Revision 1.19 2006/11/06 14:23:04 jgrosseo
194 major update (Alberto)
195 o) reading of run parameters from the logbook
196 o) online offline naming conversion
197 o) standalone DCSclient package
199 Revision 1.18 2006/10/20 15:22:59 jgrosseo
200 o) Adding time out to the execution of the preprocessors: The Shuttle forks and the parent process monitors the child
201 o) Merging Collect, CollectAll, CollectNew function
202 o) Removing implementation of empty copy constructors (declaration still there!)
204 Revision 1.17 2006/10/05 16:20:55 jgrosseo
205 adapting to new CDB classes
207 Revision 1.16 2006/10/05 15:46:26 jgrosseo
208 applying to the new interface
210 Revision 1.15 2006/10/02 16:38:39 jgrosseo
213 storing of objects that failed to be stored to the grid before
214 interfacing of shuttle status table in daq system
216 Revision 1.14 2006/08/29 09:16:05 jgrosseo
219 Revision 1.13 2006/08/15 10:50:00 jgrosseo
220 effc++ corrections (alberto)
222 Revision 1.12 2006/08/08 14:19:29 jgrosseo
223 Update to shuttle classes (Alberto)
225 - Possibility to set the full object's path in the Preprocessor's and
226 Shuttle's Store functions
227 - Possibility to extend the object's run validity in the same classes
228 ("startValidity" and "validityInfinite" parameters)
229 - Implementation of the StoreReferenceData function to store reference
230 data in a dedicated CDB storage.
232 Revision 1.11 2006/07/21 07:37:20 jgrosseo
233 last run is stored after each run
235 Revision 1.10 2006/07/20 09:54:40 jgrosseo
236 introducing status management: The processing per subdetector is divided into several steps,
237 after each step the status is stored on disk. If the system crashes in any of the steps the Shuttle
238 can keep track of the number of failures and skips further processing after a certain threshold is
239 exceeded. These thresholds can be configured in LDAP.
241 Revision 1.9 2006/07/19 10:09:55 jgrosseo
242 new configuration, accesst to DAQ FES (Alberto)
244 Revision 1.8 2006/07/11 12:44:36 jgrosseo
245 adding parameters for extended validity range of data produced by preprocessor
247 Revision 1.7 2006/07/10 14:37:09 jgrosseo
248 small fix + todo comment
250 Revision 1.6 2006/07/10 13:01:41 jgrosseo
251 enhanced storing of last sucessfully processed run (alberto)
253 Revision 1.5 2006/07/04 14:59:57 jgrosseo
254 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
256 Revision 1.4 2006/06/12 09:11:16 jgrosseo
257 coding conventions (Alberto)
259 Revision 1.3 2006/06/06 14:26:40 jgrosseo
260 o) removed files that were moved to STEER
261 o) shuttle updated to follow the new interface (Alberto)
263 Revision 1.2 2006/03/07 07:52:34 hristov
264 New version (B.Yordanov)
266 Revision 1.6 2005/11/19 17:19:14 byordano
267 RetrieveDATEEntries and RetrieveConditionsData added
269 Revision 1.5 2005/11/19 11:09:27 byordano
270 AliShuttle declaration added
272 Revision 1.4 2005/11/17 17:47:34 byordano
273 TList changed to TObjArray
275 Revision 1.3 2005/11/17 14:43:23 byordano
278 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
279 Initial import as subdirectory in AliRoot
281 Revision 1.2 2005/09/13 08:41:15 byordano
282 default startTime endTime added
284 Revision 1.4 2005/08/30 09:13:02 byordano
287 Revision 1.3 2005/08/29 21:15:47 byordano
293 // This class is the main manager for AliShuttle.
294 // It organizes the data retrieval from DCS and call the
295 // interface methods of AliPreprocessor.
296 // For every detector in AliShuttleConfgi (see AliShuttleConfig),
297 // data for its set of aliases is retrieved. If there is registered
298 // AliPreprocessor for this detector then it will be used
299 // accroding to the schema (see AliPreprocessor).
300 // If there isn't registered AliPreprocessor than the retrieved
301 // data is stored automatically to the undelying AliCDBStorage.
302 // For detSpec is used the alias name.
305 #include "AliShuttle.h"
307 #include "AliCDBManager.h"
308 #include "AliCDBStorage.h"
309 #include "AliCDBId.h"
310 #include "AliCDBRunRange.h"
311 #include "AliCDBPath.h"
312 #include "AliCDBEntry.h"
313 #include "AliShuttleConfig.h"
314 #include "DCSClient/AliDCSClient.h"
316 #include "AliPreprocessor.h"
317 #include "AliShuttleStatus.h"
318 #include "AliShuttleLogbookEntry.h"
323 #include <TTimeStamp.h>
324 #include <TObjString.h>
325 #include <TSQLServer.h>
326 #include <TSQLResult.h>
329 #include <TSystemDirectory.h>
330 #include <TSystemFile.h>
333 #include <TGridResult.h>
335 #include <TMonaLisaWriter.h>
339 #include <sys/types.h>
340 #include <sys/wait.h>
344 //______________________________________________________________________________________________
345 AliShuttle::AliShuttle(const AliShuttleConfig* config,
346 UInt_t timeout, Int_t retries):
348 fTimeout(timeout), fRetries(retries),
358 fReadTestMode(kFALSE),
359 fOutputRedirected(kFALSE)
362 // config: AliShuttleConfig used
363 // timeout: timeout used for AliDCSClient connection
364 // retries: the number of retries in case of connection error.
367 if (!fConfig->IsValid()) AliFatal("********** !!!!! Invalid configuration !!!!! **********");
368 for(int iSys=0;iSys<4;iSys++) {
371 fFXSlist[iSys].SetOwner(kTRUE);
373 fPreprocessorMap.SetOwner(kTRUE);
375 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
376 fFirstUnprocessed[iDet] = kFALSE;
378 fMonitoringMutex = new TMutex();
381 //______________________________________________________________________________________________
382 AliShuttle::~AliShuttle()
388 fPreprocessorMap.DeleteAll();
389 for(int iSys=0;iSys<4;iSys++)
391 fServer[iSys]->Close();
392 delete fServer[iSys];
401 if (fMonitoringMutex)
403 delete fMonitoringMutex;
404 fMonitoringMutex = 0;
408 //______________________________________________________________________________________________
409 void AliShuttle::RegisterPreprocessor(AliPreprocessor* preprocessor)
412 // Registers new AliPreprocessor.
413 // It uses GetName() for indentificator of the pre processor.
414 // The pre processor is registered it there isn't any other
415 // with the same identificator (GetName()).
418 const char* detName = preprocessor->GetName();
419 if(GetDetPos(detName) < 0)
420 AliFatal(Form("********** !!!!! Invalid detector name: %s !!!!! **********", detName));
422 if (fPreprocessorMap.GetValue(detName)) {
423 AliWarning(Form("AliPreprocessor %s is already registered!", detName));
427 fPreprocessorMap.Add(new TObjString(detName), preprocessor);
429 //______________________________________________________________________________________________
430 Bool_t AliShuttle::Store(const AliCDBPath& path, TObject* object,
431 AliCDBMetaData* metaData, Int_t validityStart, Bool_t validityInfinite)
433 // Stores a CDB object in the storage for offline reconstruction. Objects that are not needed for
434 // offline reconstruction, but should be stored anyway (e.g. for debugging) should NOT be stored
435 // using this function. Use StoreReferenceData instead!
436 // It calls StoreLocally function which temporarily stores the data locally; when the preprocessor
437 // finishes the data are transferred to the main storage (Grid).
439 return StoreLocally(fgkLocalCDB, path, object, metaData, validityStart, validityInfinite);
442 //______________________________________________________________________________________________
443 Bool_t AliShuttle::StoreReferenceData(const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData)
445 // Stores a CDB object in the storage for reference data. This objects will not be available during
446 // offline reconstrunction. Use this function for reference data only!
447 // It calls StoreLocally function which temporarily stores the data locally; when the preprocessor
448 // finishes the data are transferred to the main storage (Grid).
450 return StoreLocally(fgkLocalRefStorage, path, object, metaData);
453 //______________________________________________________________________________________________
454 Bool_t AliShuttle::StoreLocally(const TString& localUri,
455 const AliCDBPath& path, TObject* object, AliCDBMetaData* metaData,
456 Int_t validityStart, Bool_t validityInfinite)
458 // Store object temporarily in local storage. Parameters are passed by Store and StoreReferenceData functions.
459 // when the preprocessor finishes the data are transferred to the main storage (Grid).
460 // The parameters are:
461 // 1) Uri of the backup storage (Local)
462 // 2) the object's path.
463 // 3) the object to be stored
464 // 4) the metaData to be associated with the object
465 // 5) the validity start run number w.r.t. the current run,
466 // if the data is valid only for this run leave the default 0
467 // 6) specifies if the calibration data is valid for infinity (this means until updated),
468 // typical for calibration runs, the default is kFALSE
470 // returns 0 if fail, 1 otherwise
472 if (fTestMode & kErrorStorage)
474 Log(fCurrentDetector, "StoreLocally - In TESTMODE - Simulating error while storing locally");
478 const char* cdbType = (localUri == fgkLocalCDB) ? "CDB" : "Reference";
480 Int_t firstRun = GetCurrentRun() - validityStart;
482 AliWarning("First valid run happens to be less than 0! Setting it to 0.");
487 if(validityInfinite) {
488 lastRun = AliCDBRunRange::Infinity();
490 lastRun = GetCurrentRun();
493 // Version is set to current run, it will be used later to transfer data to Grid
494 AliCDBId id(path, firstRun, lastRun, GetCurrentRun(), -1);
496 if(! dynamic_cast<TObjString*> (metaData->GetProperty("RunUsed(TObjString)"))){
497 TObjString runUsed = Form("%d", GetCurrentRun());
498 metaData->SetProperty("RunUsed(TObjString)", runUsed.Clone());
501 Bool_t result = kFALSE;
503 if (!(AliCDBManager::Instance()->GetStorage(localUri))) {
504 Log("SHUTTLE", Form("StoreLocally - Cannot activate local %s storage", cdbType));
506 result = AliCDBManager::Instance()->GetStorage(localUri)
507 ->Put(object, id, metaData);
512 Log(fCurrentDetector, Form("StoreLocally - Can't store object <%s>!", id.ToString().Data()));
518 //______________________________________________________________________________________________
519 Bool_t AliShuttle::StoreOCDB()
522 // Called when preprocessor ends successfully or when previous storage attempt failed (kStoreError status)
523 // Calls underlying StoreOCDB(const char*) function twice, for OCDB and Reference storage.
524 // Then calls StoreRefFilesToGrid to store reference files.
527 if (fTestMode & kErrorGrid)
529 Log("SHUTTLE", "StoreOCDB - In TESTMODE - Simulating error while storing in the Grid");
530 Log(fCurrentDetector, "StoreOCDB - In TESTMODE - Simulating error while storing in the Grid");
534 Log("SHUTTLE","StoreOCDB - Storing OCDB data ...");
535 Bool_t resultCDB = StoreOCDB(fgkMainCDB);
537 Log("SHUTTLE","StoreOCDB - Storing reference data ...");
538 Bool_t resultRef = StoreOCDB(fgkMainRefStorage);
540 Log("SHUTTLE","StoreOCDB - Storing reference files ...");
541 Bool_t resultRefFiles = CopyFilesToGrid("reference");
543 Bool_t resultMetadata = kTRUE;
544 if(fCurrentDetector == "GRP")
546 Log("StoreOCDB - SHUTTLE","Storing Run Metadata file ...");
547 resultMetadata = CopyFilesToGrid("metadata");
550 return resultCDB && resultRef && resultRefFiles && resultMetadata;
553 //______________________________________________________________________________________________
554 Bool_t AliShuttle::StoreOCDB(const TString& gridURI)
557 // Called by StoreOCDB(), performs actual storage to the main OCDB and reference storages (Grid)
560 TObjArray* gridIds=0;
562 Bool_t result = kTRUE;
564 const char* type = 0;
566 if(gridURI == fgkMainCDB) {
568 localURI = fgkLocalCDB;
569 } else if(gridURI == fgkMainRefStorage) {
571 localURI = fgkLocalRefStorage;
573 AliError(Form("Invalid storage URI: %s", gridURI.Data()));
577 AliCDBManager* man = AliCDBManager::Instance();
579 AliCDBStorage *gridSto = man->GetStorage(gridURI);
582 Form("StoreOCDB - cannot activate main %s storage", type));
586 gridIds = gridSto->GetQueryCDBList();
588 // get objects previously stored in local CDB
589 AliCDBStorage *localSto = man->GetStorage(localURI);
592 Form("StoreOCDB - cannot activate local %s storage", type));
595 AliCDBPath aPath(GetOfflineDetName(fCurrentDetector.Data()),"*","*");
596 // Local objects were stored with current run as Grid version!
597 TList* localEntries = localSto->GetAll(aPath.GetPath(), GetCurrentRun(), GetCurrentRun());
598 localEntries->SetOwner(1);
600 // loop on local stored objects
601 TIter localIter(localEntries);
602 AliCDBEntry *aLocEntry = 0;
603 while((aLocEntry = dynamic_cast<AliCDBEntry*> (localIter.Next()))){
604 aLocEntry->SetOwner(1);
605 AliCDBId aLocId = aLocEntry->GetId();
606 aLocEntry->SetVersion(-1);
607 aLocEntry->SetSubVersion(-1);
609 // If local object is valid up to infinity we store it only if it is
610 // the first unprocessed run!
611 if (aLocId.GetLastRun() == AliCDBRunRange::Infinity() &&
612 !fFirstUnprocessed[GetDetPos(fCurrentDetector)])
614 Log("SHUTTLE", Form("StoreOCDB - %s: object %s has validity infinite but "
615 "there are previous unprocessed runs!",
616 fCurrentDetector.Data(), aLocId.GetPath().Data()));
620 // loop on Grid valid Id's
621 Bool_t store = kTRUE;
622 TIter gridIter(gridIds);
623 AliCDBId* aGridId = 0;
624 while((aGridId = dynamic_cast<AliCDBId*> (gridIter.Next()))){
625 if(aGridId->GetPath() != aLocId.GetPath()) continue;
626 // skip all objects valid up to infinity
627 if(aGridId->GetLastRun() == AliCDBRunRange::Infinity()) continue;
628 // if we get here, it means there's already some more recent object stored on Grid!
633 // If we get here, the file can be stored!
634 Bool_t storeOk = gridSto->Put(aLocEntry);
635 if(!store || storeOk){
639 Log(fCurrentDetector.Data(),
640 Form("StoreOCDB - A more recent object already exists in %s storage: <%s>",
641 type, aGridId->ToString().Data()));
644 Form("StoreOCDB - Object <%s> successfully put into %s storage",
645 aLocId.ToString().Data(), type));
646 Log(fCurrentDetector.Data(),
647 Form("StoreOCDB - Object <%s> successfully put into %s storage",
648 aLocId.ToString().Data(), type));
651 // removing local filename...
653 localSto->IdToFilename(aLocId, filename);
654 Log("SHUTTLE", Form("StoreOCDB - Removing local file %s", filename.Data()));
655 RemoveFile(filename.Data());
659 Form("StoreOCDB - Grid %s storage of object <%s> failed",
660 type, aLocId.ToString().Data()));
661 Log(fCurrentDetector.Data(),
662 Form("StoreOCDB - Grid %s storage of object <%s> failed",
663 type, aLocId.ToString().Data()));
667 localEntries->Clear();
672 //______________________________________________________________________________________________
673 Bool_t AliShuttle::CleanReferenceStorage(const char* detector)
675 // clears the directory used to store reference files of a given subdetector
677 AliCDBManager* man = AliCDBManager::Instance();
678 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
679 TString localBaseFolder = sto->GetBaseFolder();
681 TString targetDir = GetRefFilePrefix(localBaseFolder.Data(), detector);
683 Log("SHUTTLE", Form("CleanReferenceStorage - Cleaning %s", targetDir.Data()));
686 begin.Form("%d_", GetCurrentRun());
688 TSystemDirectory* baseDir = new TSystemDirectory("/", targetDir);
692 TList* dirList = baseDir->GetListOfFiles();
695 if (!dirList) return kTRUE;
697 if (dirList->GetEntries() < 3)
703 Int_t nDirs = 0, nDel = 0;
704 TIter dirIter(dirList);
705 TSystemFile* entry = 0;
707 Bool_t success = kTRUE;
709 while ((entry = dynamic_cast<TSystemFile*> (dirIter.Next())))
711 if (entry->IsDirectory())
714 TString fileName(entry->GetName());
715 if (!fileName.BeginsWith(begin))
721 Int_t result = gSystem->Unlink(fileName.Data());
725 Log("SHUTTLE", Form("CleanReferenceStorage - Could not delete file %s!", fileName.Data()));
733 Log("SHUTTLE", Form("CleanReferenceStorage - %d (over %d) reference files in folder %s were deleted.",
734 nDel, nDirs, targetDir.Data()));
745 Int_t result = gSystem->GetPathInfo(targetDir, 0, (Long64_t*) 0, 0, 0);
749 result = gSystem->Exec(Form("rm -rf %s", targetDir.Data()));
752 Log("SHUTTLE", Form("CleanReferenceStorage - Could not clean directory %s", targetDir.Data()));
757 result = gSystem->mkdir(targetDir, kTRUE);
760 Log("SHUTTLE", Form("CleanReferenceStorage - Error creating base directory %s", targetDir.Data()));
767 //______________________________________________________________________________________________
768 Bool_t AliShuttle::StoreReferenceFile(const char* detector, const char* localFile, const char* gridFileName)
771 // Stores reference file directly (without opening it). This function stores the file locally.
773 // The file is stored under the following location:
774 // <base folder of local reference storage>/<DET>/<RUN#>_<gridFileName>
775 // where <gridFileName> is the second parameter given to the function
778 if (fTestMode & kErrorStorage)
780 Log(fCurrentDetector, "StoreReferenceFile - In TESTMODE - Simulating error while storing locally");
784 AliCDBManager* man = AliCDBManager::Instance();
785 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
787 TString localBaseFolder = sto->GetBaseFolder();
789 TString target = GetRefFilePrefix(localBaseFolder.Data(), detector);
790 target.Append(Form("/%d_%s", GetCurrentRun(), gridFileName));
792 return CopyFileLocally(localFile, target);
795 //______________________________________________________________________________________________
796 Bool_t AliShuttle::StoreRunMetadataFile(const char* localFile, const char* gridFileName)
799 // Stores Run metadata file to the Grid, in the run folder
801 // Only GRP can call this function.
803 if (fTestMode & kErrorStorage)
805 Log(fCurrentDetector, "StoreRunMetaDataFile - In TESTMODE - Simulating error while storing locally");
809 AliCDBManager* man = AliCDBManager::Instance();
810 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
812 TString localBaseFolder = sto->GetBaseFolder();
814 // Build Run level folder
815 // folder = /alice/data/year/lhcPeriod/runNb/Raw
818 TString lhcPeriod = GetLHCPeriod();
819 if (lhcPeriod.Length() == 0)
821 Log("SHUTTLE","StoreRunMetaDataFile - LHCPeriod not found in logbook!");
825 TString target = Form("%s/GRP/RunMetadata/alice/data/%d/%s/%09d/Raw/%s",
826 localBaseFolder.Data(), GetCurrentYear(),
827 lhcPeriod.Data(), GetCurrentRun(), gridFileName);
829 return CopyFileLocally(localFile, target);
832 //______________________________________________________________________________________________
833 Bool_t AliShuttle::CopyFileLocally(const char* localFile, const TString& target)
836 // Stores file locally. Called by StoreReferenceFile and StoreRunMetadataFile
837 // Files are temporarily stored in the local reference storage. When the preprocessor
838 // finishes, the Shuttle calls CopyFilesToGrid to transfer the files to AliEn
839 // (in reference or run level folders)
842 TString targetDir(target(0, target.Last('/')));
844 //try to open base dir folder, if it does not exist
845 void* dir = gSystem->OpenDirectory(targetDir.Data());
847 if (gSystem->mkdir(targetDir.Data(), kTRUE)) {
848 Log("SHUTTLE", Form("StoreFileLocally - Can't open directory <%s>", targetDir.Data()));
853 gSystem->FreeDirectory(dir);
858 result = gSystem->GetPathInfo(localFile, 0, (Long64_t*) 0, 0, 0);
861 Log("SHUTTLE", Form("StoreFileLocally - %s does not exist", localFile));
865 result = gSystem->GetPathInfo(target, 0, (Long64_t*) 0, 0, 0);
868 Log("SHUTTLE", Form("StoreFileLocally - target file %s already exist, removing...", target.Data()));
869 if (gSystem->Unlink(target.Data()))
871 Log("SHUTTLE", Form("StoreFileLocally - Could not remove existing target file %s!", target.Data()));
876 result = gSystem->CopyFile(localFile, target);
880 Log("SHUTTLE", Form("StoreFileLocally - File %s stored locally to %s", localFile, target.Data()));
885 Log("SHUTTLE", Form("StoreFileLocally - Could not store file %s to %s! Error code = %d",
886 localFile, target.Data(), result));
894 //______________________________________________________________________________________________
895 Bool_t AliShuttle::CopyFilesToGrid(const char* type)
898 // Transfers local files to the Grid. Local files can be reference files
899 // or run metadata file (from GRP only).
901 // According to the type (ref, metadata) the files are stored under the following location:
902 // ref --> <base folder of reference storage>/<DET>/<RUN#>_<gridFileName>
903 // metadata --> <run data folder>/<MetadataFileName>
906 AliCDBManager* man = AliCDBManager::Instance();
907 AliCDBStorage* sto = man->GetStorage(fgkLocalRefStorage);
910 TString localBaseFolder = sto->GetBaseFolder();
916 if (strcmp(type, "reference") == 0)
918 dir = GetRefFilePrefix(localBaseFolder.Data(), fCurrentDetector.Data());
919 AliCDBStorage* gridSto = man->GetStorage(fgkMainRefStorage);
922 TString gridBaseFolder = gridSto->GetBaseFolder();
923 alienDir = GetRefFilePrefix(gridBaseFolder.Data(), fCurrentDetector.Data());
924 begin = Form("%d_", GetCurrentRun());
926 else if (strcmp(type, "metadata") == 0)
929 TString lhcPeriod = GetLHCPeriod();
931 if (lhcPeriod.Length() == 0)
933 Log("SHUTTLE","CopyFilesToGrid - LHCPeriod not found in logbook!");
937 dir = Form("%s/GRP/RunMetadata/alice/data/%d/%s/%09d/Raw",
938 localBaseFolder.Data(), GetCurrentYear(),
939 lhcPeriod.Data(), GetCurrentRun());
940 alienDir = dir(dir.Index("/alice/data/"), dir.Length());
946 Log("SHUTTLE", "CopyFilesToGrid - Unexpected: type label must be reference or metadata!");
950 TSystemDirectory* baseDir = new TSystemDirectory("/", dir);
954 TList* dirList = baseDir->GetListOfFiles();
957 if (!dirList) return kTRUE;
959 if (dirList->GetEntries() < 3)
967 Log("SHUTTLE", "CopyFilesToGrid - Connection to Grid failed: Cannot continue!");
972 Int_t nDirs = 0, nTransfer = 0;
973 TIter dirIter(dirList);
974 TSystemFile* entry = 0;
976 Bool_t success = kTRUE;
977 Bool_t first = kTRUE;
979 while ((entry = dynamic_cast<TSystemFile*> (dirIter.Next())))
981 if (entry->IsDirectory())
984 TString fileName(entry->GetName());
985 if (!fileName.BeginsWith(begin))
993 // check that folder exists, otherwise create it
994 TGridResult* result = gGrid->Ls(alienDir.Data(), "a");
1002 if (!result->GetFileName(1)) // TODO: It looks like element 0 is always 0!!
1004 // TODO It does not work currently! Bug in TAliEn::Mkdir
1005 // TODO Manually fixed in local root v5-16-00
1006 if (!gGrid->Mkdir(alienDir.Data(),"-p",0))
1008 Log("SHUTTLE", Form("CopyFilesToGrid - Cannot create directory %s",
1013 Log("SHUTTLE",Form("CopyFilesToGrid - Folder %s created", alienDir.Data()));
1017 Log("SHUTTLE",Form("CopyFilesToGrid - Folder %s found", alienDir.Data()));
1021 TString fullLocalPath;
1022 fullLocalPath.Form("%s/%s", dir.Data(), fileName.Data());
1024 TString fullGridPath;
1025 fullGridPath.Form("alien://%s/%s", alienDir.Data(), fileName.Data());
1027 Bool_t result = TFile::Cp(fullLocalPath, fullGridPath);
1031 Log("SHUTTLE", Form("CopyFilesToGrid - Copying local file %s to %s succeeded!",
1032 fullLocalPath.Data(), fullGridPath.Data()));
1033 RemoveFile(fullLocalPath);
1038 Log("SHUTTLE", Form("CopyFilesToGrid - Copying local file %s to %s FAILED!",
1039 fullLocalPath.Data(), fullGridPath.Data()));
1044 Log("SHUTTLE", Form("CopyFilesToGrid - %d (over %d) files in folder %s copied to Grid.",
1045 nTransfer, nDirs, dir.Data()));
1052 //______________________________________________________________________________________________
1053 const char* AliShuttle::GetRefFilePrefix(const char* base, const char* detector)
1056 // Get folder name of reference files
1059 TString offDetStr(GetOfflineDetName(detector));
1061 if (offDetStr == "ITS" || offDetStr == "MUON" || offDetStr == "PHOS")
1063 dir.Form("%s/%s/%s", base, offDetStr.Data(), detector);
1065 dir.Form("%s/%s", base, offDetStr.Data());
1073 //______________________________________________________________________________________________
1074 void AliShuttle::CleanLocalStorage(const TString& uri)
1077 // Called in case the preprocessor is declared failed. Remove remaining objects from the local storages.
1080 const char* type = 0;
1081 if(uri == fgkLocalCDB) {
1083 } else if(uri == fgkLocalRefStorage) {
1086 AliError(Form("Invalid storage URI: %s", uri.Data()));
1090 AliCDBManager* man = AliCDBManager::Instance();
1092 // open local storage
1093 AliCDBStorage *localSto = man->GetStorage(uri);
1096 Form("CleanLocalStorage - cannot activate local %s storage", type));
1100 TString filename(Form("%s/%s/*/Run*_v%d_s*.root",
1101 localSto->GetBaseFolder().Data(), GetOfflineDetName(fCurrentDetector.Data()), GetCurrentRun()));
1103 AliDebug(2, Form("filename = %s", filename.Data()));
1105 Log("SHUTTLE", Form("Removing remaining local files for run %d and detector %s ...",
1106 GetCurrentRun(), fCurrentDetector.Data()));
1108 RemoveFile(filename.Data());
1112 //______________________________________________________________________________________________
1113 void AliShuttle::RemoveFile(const char* filename)
1116 // removes local file
1119 TString command(Form("rm -f %s", filename));
1121 Int_t result = gSystem->Exec(command.Data());
1124 Log("SHUTTLE", Form("RemoveFile - %s: Cannot remove file %s!",
1125 fCurrentDetector.Data(), filename));
1129 //______________________________________________________________________________________________
1130 AliShuttleStatus* AliShuttle::ReadShuttleStatus()
1133 // Reads the AliShuttleStatus from the CDB
1137 delete fStatusEntry;
1141 fStatusEntry = AliCDBManager::Instance()->GetStorage(GetLocalCDB())
1142 ->Get(Form("/SHUTTLE/STATUS/%s", fCurrentDetector.Data()), GetCurrentRun());
1144 if (!fStatusEntry) return 0;
1145 fStatusEntry->SetOwner(1);
1147 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
1149 AliError("Invalid object stored to CDB!");
1156 //______________________________________________________________________________________________
1157 Bool_t AliShuttle::WriteShuttleStatus(AliShuttleStatus* status)
1160 // writes the status for one subdetector
1164 delete fStatusEntry;
1168 Int_t run = GetCurrentRun();
1170 AliCDBId id(AliCDBPath("SHUTTLE", "STATUS", fCurrentDetector), run, run);
1172 fStatusEntry = new AliCDBEntry(status, id, new AliCDBMetaData);
1173 fStatusEntry->SetOwner(1);
1175 UInt_t result = AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
1178 Log("SHUTTLE", Form("WriteShuttleStatus - Failed for %s, run %d",
1179 fCurrentDetector.Data(), run));
1188 //______________________________________________________________________________________________
1189 void AliShuttle::UpdateShuttleStatus(AliShuttleStatus::Status newStatus, Bool_t increaseCount)
1192 // changes the AliShuttleStatus for the given detector and run to the given status
1196 AliError("UNEXPECTED: fStatusEntry empty");
1200 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
1203 Log("SHUTTLE", "UpdateShuttleStatus - UNEXPECTED: status could not be read from current CDB entry");
1207 TString actionStr = Form("UpdateShuttleStatus - %s: Changing state from %s to %s",
1208 fCurrentDetector.Data(),
1209 status->GetStatusName(),
1210 status->GetStatusName(newStatus));
1211 Log("SHUTTLE", actionStr);
1212 SetLastAction(actionStr);
1214 status->SetStatus(newStatus);
1215 if (increaseCount) status->IncreaseCount();
1217 AliCDBManager::Instance()->GetStorage(fgkLocalCDB)->Put(fStatusEntry);
1222 //______________________________________________________________________________________________
1223 void AliShuttle::SendMLInfo()
1226 // sends ML information about the current status of the current detector being processed
1229 AliShuttleStatus* status = dynamic_cast<AliShuttleStatus*> (fStatusEntry->GetObject());
1232 Log("SHUTTLE", "SendMLInfo - UNEXPECTED: status could not be read from current CDB entry");
1236 TMonaLisaText mlStatus(Form("%s_status", fCurrentDetector.Data()), status->GetStatusName());
1237 TMonaLisaValue mlRetryCount(Form("%s_count", fCurrentDetector.Data()), status->GetCount());
1240 mlList.Add(&mlStatus);
1241 mlList.Add(&mlRetryCount);
1243 fMonaLisa->SendParameters(&mlList);
1246 //______________________________________________________________________________________________
1247 Bool_t AliShuttle::ContinueProcessing()
1249 // this function reads the AliShuttleStatus information from CDB and
1250 // checks if the processing should be continued
1251 // if yes it returns kTRUE and updates the AliShuttleStatus with nextStatus
1253 if (!fConfig->HostProcessDetector(fCurrentDetector)) return kFALSE;
1255 AliPreprocessor* aPreprocessor =
1256 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
1259 Log("SHUTTLE", Form("ContinueProcessing - %s: no preprocessor registered", fCurrentDetector.Data()));
1263 AliShuttleLogbookEntry::Status entryStatus =
1264 fLogbookEntry->GetDetectorStatus(fCurrentDetector);
1266 if(entryStatus != AliShuttleLogbookEntry::kUnprocessed) {
1267 Log("SHUTTLE", Form("ContinueProcessing - %s is %s",
1268 fCurrentDetector.Data(),
1269 fLogbookEntry->GetDetectorStatusName(entryStatus)));
1273 // if we get here, according to Shuttle logbook subdetector is in UNPROCESSED state
1275 // check if current run is first unprocessed run for current detector
1276 if (fConfig->StrictRunOrder(fCurrentDetector) &&
1277 !fFirstUnprocessed[GetDetPos(fCurrentDetector)])
1279 if (fTestMode == kNone)
1281 Log("SHUTTLE", Form("ContinueProcessing - %s requires strict run ordering"
1282 " but this is not the first unprocessed run!"));
1287 Log("SHUTTLE", Form("ContinueProcessing - In TESTMODE - "
1288 "Although %s requires strict run ordering "
1289 "and this is not the first unprocessed run, "
1290 "the SHUTTLE continues"));
1294 AliShuttleStatus* status = ReadShuttleStatus();
1297 Log("SHUTTLE", Form("ContinueProcessing - %s: Processing first time",
1298 fCurrentDetector.Data()));
1299 status = new AliShuttleStatus(AliShuttleStatus::kStarted);
1300 return WriteShuttleStatus(status);
1303 // The following two cases shouldn't happen if Shuttle Logbook was correctly updated.
1304 // If it happens it may mean Logbook updating failed... let's do it now!
1305 if (status->GetStatus() == AliShuttleStatus::kDone ||
1306 status->GetStatus() == AliShuttleStatus::kFailed){
1307 Log("SHUTTLE", Form("ContinueProcessing - %s is already %s. Updating Shuttle Logbook",
1308 fCurrentDetector.Data(),
1309 status->GetStatusName(status->GetStatus())));
1310 UpdateShuttleLogbook(fCurrentDetector.Data(),
1311 status->GetStatusName(status->GetStatus()));
1315 if (status->GetStatus() == AliShuttleStatus::kStoreError) {
1317 Form("ContinueProcessing - %s: Grid storage of one or more "
1318 "objects failed. Trying again now",
1319 fCurrentDetector.Data()));
1320 UpdateShuttleStatus(AliShuttleStatus::kStoreStarted);
1322 Log("SHUTTLE", Form("ContinueProcessing - %s: all objects "
1323 "successfully stored into main storage",
1324 fCurrentDetector.Data()));
1325 UpdateShuttleStatus(AliShuttleStatus::kDone);
1326 UpdateShuttleLogbook(fCurrentDetector.Data(), "DONE");
1329 Form("ContinueProcessing - %s: Grid storage failed again",
1330 fCurrentDetector.Data()));
1331 UpdateShuttleStatus(AliShuttleStatus::kStoreError);
1336 // if we get here, there is a restart
1337 Bool_t cont = kFALSE;
1340 if (status->GetCount() >= fConfig->GetMaxRetries()) {
1341 Log("SHUTTLE", Form("ContinueProcessing - %s failed %d times in status %s - "
1342 "Updating Shuttle Logbook", fCurrentDetector.Data(),
1343 status->GetCount(), status->GetStatusName()));
1344 UpdateShuttleLogbook(fCurrentDetector.Data(), "FAILED");
1345 UpdateShuttleStatus(AliShuttleStatus::kFailed);
1347 // there may still be objects in local OCDB and reference storage
1348 // and FXS databases may be not updated: do it now!
1350 // TODO Currently disabled, we want to keep files in case of failure!
1351 // CleanLocalStorage(fgkLocalCDB);
1352 // CleanLocalStorage(fgkLocalRefStorage);
1353 // UpdateTableFailCase();
1355 // Send mail to detector expert!
1356 Log("SHUTTLE", Form("ContinueProcessing - Sending mail to %s expert...",
1357 fCurrentDetector.Data()));
1359 Log("SHUTTLE", Form("ContinueProcessing - Could not send mail to %s expert",
1360 fCurrentDetector.Data()));
1363 Log("SHUTTLE", Form("ContinueProcessing - %s: restarting. "
1364 "Aborted before with %s. Retry number %d.", fCurrentDetector.Data(),
1365 status->GetStatusName(), status->GetCount()));
1366 Bool_t increaseCount = kTRUE;
1367 if (status->GetStatus() == AliShuttleStatus::kDCSError ||
1368 status->GetStatus() == AliShuttleStatus::kDCSStarted)
1369 increaseCount = kFALSE;
1371 UpdateShuttleStatus(AliShuttleStatus::kStarted, increaseCount);
1378 //______________________________________________________________________________________________
1379 Bool_t AliShuttle::Process(AliShuttleLogbookEntry* entry)
1382 // Makes data retrieval for all detectors in the configuration.
1383 // entry: Shuttle logbook entry, contains run paramenters and status of detectors
1384 // (Unprocessed, Inactive, Failed or Done).
1385 // Returns kFALSE in case of error occured and kTRUE otherwise
1388 if (!entry) return kFALSE;
1390 fLogbookEntry = entry;
1392 Log("SHUTTLE", Form("\t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: START ^*^*^*^*^*^*^*^*^*^*^*^*",
1395 // create ML instance that monitors this run
1396 fMonaLisa = new TMonaLisaWriter(Form("%d", GetCurrentRun()), fConfig->GetMonitorTable(),
1397 fConfig->GetMonitorHost());
1398 // disable monitoring of other parameters that come e.g. from TFile
1399 gMonitoringWriter = 0;
1401 // Send the information to ML
1402 TMonaLisaText mlStatus("SHUTTLE_status", "Processing");
1403 TMonaLisaText mlRunType("SHUTTLE_runtype", Form("%s (%s)", entry->GetRunType(), entry->GetRunParameter("log")));
1406 mlList.Add(&mlStatus);
1407 mlList.Add(&mlRunType);
1409 fMonaLisa->SendParameters(&mlList);
1411 if (fLogbookEntry->IsDone())
1413 Log("SHUTTLE","Process - Shuttle is already DONE. Updating logbook");
1414 UpdateShuttleLogbook("shuttle_done");
1419 // read test mode if flag is set
1423 TString logEntry(entry->GetRunParameter("log"));
1424 //printf("log entry = %s\n", logEntry.Data());
1425 TString searchStr("Testmode: ");
1426 Int_t pos = logEntry.Index(searchStr.Data());
1427 //printf("%d\n", pos);
1430 TSubString subStr = logEntry(pos + searchStr.Length(), logEntry.Length());
1431 //printf("%s\n", subStr.String().Data());
1432 TString newStr(subStr.Data());
1433 TObjArray* token = newStr.Tokenize(' ');
1437 TObjString* tmpStr = dynamic_cast<TObjString*> (token->First());
1440 Int_t testMode = tmpStr->String().Atoi();
1443 Log("SHUTTLE", Form("Process - Enabling test mode %d", testMode));
1444 SetTestMode((TestMode) testMode);
1452 fLogbookEntry->Print("all");
1455 Bool_t hasError = kFALSE;
1457 // Set the CDB and Reference folders according to the year and LHC period
1458 TString lhcPeriod(GetLHCPeriod());
1459 if (lhcPeriod.Length() == 0)
1461 Log("SHUTTLE","StoreRunMetaDataFile - LHCPeriod not found in logbook!");
1465 if (fgkMainCDB.Length() == 0)
1466 fgkMainCDB = Form("alien://folder=/alice/data/%d/%s/OCDB?user=alidaq?cacheFold=/tmp/OCDBCache",
1467 GetCurrentYear(), lhcPeriod.Data());
1469 if (fgkMainRefStorage.Length() == 0)
1470 fgkMainRefStorage = Form("alien://folder=/alice/data/%d/%s/Reference?user=alidaq?cacheFold=/tmp/OCDBCache",
1471 GetCurrentYear(), lhcPeriod.Data());
1473 AliCDBStorage *mainCDBSto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
1474 if(mainCDBSto) mainCDBSto->QueryCDB(GetCurrentRun());
1475 AliCDBStorage *mainRefSto = AliCDBManager::Instance()->GetStorage(fgkMainRefStorage);
1476 if(mainRefSto) mainRefSto->QueryCDB(GetCurrentRun());
1478 // Loop on detectors in the configuration
1479 TIter iter(fConfig->GetDetectors());
1480 TObjString* aDetector = 0;
1482 while ((aDetector = (TObjString*) iter.Next()))
1484 fCurrentDetector = aDetector->String();
1486 if (ContinueProcessing() == kFALSE) continue;
1488 Log("SHUTTLE", Form("\t\t\t****** run %d - %s: START ******",
1489 GetCurrentRun(), aDetector->GetName()));
1491 for(Int_t iSys=0;iSys<3;iSys++) fFXSCalled[iSys]=kFALSE;
1493 Log(fCurrentDetector.Data(), "Process - Starting processing");
1499 Log("SHUTTLE", "Process - ERROR: Forking failed");
1504 Log("SHUTTLE", Form("Process - In parent process of %d - %s: Starting monitoring",
1505 GetCurrentRun(), aDetector->GetName()));
1507 Long_t begin = time(0);
1509 int status; // to be used with waitpid, on purpose an int (not Int_t)!
1510 while (waitpid(pid, &status, WNOHANG) == 0)
1512 Long_t expiredTime = time(0) - begin;
1514 if (expiredTime > fConfig->GetPPTimeOut())
1517 tmp.Form("Process - Process of %s time out. "
1518 "Run time: %d seconds. Killing...",
1519 fCurrentDetector.Data(), expiredTime);
1520 Log("SHUTTLE", tmp);
1521 Log(fCurrentDetector, tmp);
1525 UpdateShuttleStatus(AliShuttleStatus::kPPTimeOut);
1528 gSystem->Sleep(1000);
1532 gSystem->Sleep(1000);
1535 checkStr.Form("ps -o vsize --pid %d | tail -n 1", pid);
1536 FILE* pipe = gSystem->OpenPipe(checkStr, "r");
1539 Log("SHUTTLE", Form("Process - Error: "
1540 "Could not open pipe to %s", checkStr.Data()));
1545 if (!fgets(buffer, 100, pipe))
1547 Log("SHUTTLE", "Process - Error: ps did not return anything");
1548 gSystem->ClosePipe(pipe);
1551 gSystem->ClosePipe(pipe);
1553 //Log("SHUTTLE", Form("ps returned %s", buffer));
1556 if ((sscanf(buffer, "%d\n", &mem) != 1) || !mem)
1558 Log("SHUTTLE", "Process - Error: Could not parse output of ps");
1562 if (expiredTime % 60 == 0)
1563 Log("SHUTTLE", Form("Process - %s: Checking process. "
1564 "Run time: %d seconds - Memory consumption: %d KB",
1565 fCurrentDetector.Data(), expiredTime, mem));
1567 if (mem > fConfig->GetPPMaxMem())
1570 tmp.Form("Process - Process exceeds maximum allowed memory "
1571 "(%d KB > %d KB). Killing...",
1572 mem, fConfig->GetPPMaxMem());
1573 Log("SHUTTLE", tmp);
1574 Log(fCurrentDetector, tmp);
1578 UpdateShuttleStatus(AliShuttleStatus::kPPOutOfMemory);
1581 gSystem->Sleep(1000);
1586 Log("SHUTTLE", Form("Process - In parent process of %d - %s: Client has terminated.",
1587 GetCurrentRun(), aDetector->GetName()));
1589 if (WIFEXITED(status))
1591 Int_t returnCode = WEXITSTATUS(status);
1593 Log("SHUTTLE", Form("Process - %s: the return code is %d", fCurrentDetector.Data(),
1596 if (returnCode == 0) hasError = kTRUE;
1602 Log("SHUTTLE", Form("Process - In client process of %d - %s", GetCurrentRun(),
1603 aDetector->GetName()));
1605 Log("SHUTTLE", Form("Process - Redirecting output to %s log",fCurrentDetector.Data()));
1607 if ((freopen(GetLogFileName(fCurrentDetector), "a", stdout)) == 0)
1609 Log("SHUTTLE", "Process - Could not freopen stdout");
1613 fOutputRedirected = kTRUE;
1614 if ((dup2(fileno(stdout), fileno(stderr))) < 0)
1615 Log("SHUTTLE", "Process - Could not redirect stderr");
1619 TString wd = gSystem->WorkingDirectory();
1620 TString tmpDir = Form("%s/%s_%d_process", GetShuttleTempDir(),
1621 fCurrentDetector.Data(), GetCurrentRun());
1623 Int_t result = gSystem->GetPathInfo(tmpDir.Data(), 0, (Long64_t*) 0, 0, 0);
1624 if (!result) // temp dir already exists!
1626 Log(fCurrentDetector.Data(),
1627 Form("Process - %s dir already exists! Removing...", tmpDir.Data()));
1628 gSystem->Exec(Form("rm -rf %s",tmpDir.Data()));
1631 if (gSystem->mkdir(tmpDir.Data(), 1))
1633 Log(fCurrentDetector.Data(), "Process - could not make temp directory!!");
1637 if (!gSystem->ChangeDirectory(tmpDir.Data()))
1639 Log(fCurrentDetector.Data(), "Process - could not change directory!!");
1643 Bool_t success = ProcessCurrentDetector();
1645 gSystem->ChangeDirectory(wd.Data());
1647 if (success) // Preprocessor finished successfully!
1649 // remove temporary folder
1650 gSystem->Exec(Form("rm -rf %s",tmpDir.Data()));
1652 // Update time_processed field in FXS DB
1653 if (UpdateTable() == kFALSE)
1654 Log("SHUTTLE", Form("Process - %s: Could not update FXS databases!",
1655 fCurrentDetector.Data()));
1657 // Transfer the data from local storage to main storage (Grid)
1658 UpdateShuttleStatus(AliShuttleStatus::kStoreStarted);
1659 if (StoreOCDB() == kFALSE)
1662 Form("\t\t\t****** run %d - %s: STORAGE ERROR ******",
1663 GetCurrentRun(), aDetector->GetName()));
1664 UpdateShuttleStatus(AliShuttleStatus::kStoreError);
1668 Form("\t\t\t****** run %d - %s: DONE ******",
1669 GetCurrentRun(), aDetector->GetName()));
1670 UpdateShuttleStatus(AliShuttleStatus::kDone);
1671 UpdateShuttleLogbook(fCurrentDetector, "DONE");
1676 Form("\t\t\t****** run %d - %s: PP ERROR ******",
1677 GetCurrentRun(), aDetector->GetName()));
1680 for (UInt_t iSys=0; iSys<3; iSys++)
1682 if (fFXSCalled[iSys]) fFXSlist[iSys].Clear();
1685 Log("SHUTTLE", Form("Process - Client process of %d - %s is exiting now with %d.",
1686 GetCurrentRun(), aDetector->GetName(), success));
1688 // the client exits here
1689 gSystem->Exit(success);
1691 AliError("We should never get here!!!");
1695 Log("SHUTTLE", Form("\t\t\t^*^*^*^*^*^*^*^*^*^*^*^* run %d: FINISH ^*^*^*^*^*^*^*^*^*^*^*^*",
1698 //check if shuttle is done for this run, if so update logbook
1699 TObjArray checkEntryArray;
1700 checkEntryArray.SetOwner(1);
1701 TString whereClause = Form("where run=%d", GetCurrentRun());
1702 if (!QueryShuttleLogbook(whereClause.Data(), checkEntryArray) || checkEntryArray.GetEntries() == 0) {
1703 Log("SHUTTLE", Form("Process - Warning: Cannot check status of run %d on Shuttle logbook!",
1705 return hasError == kFALSE;
1708 AliShuttleLogbookEntry* checkEntry = dynamic_cast<AliShuttleLogbookEntry*>
1709 (checkEntryArray.At(0));
1713 if (checkEntry->IsDone())
1715 Log("SHUTTLE","Process - Shuttle is DONE. Updating logbook");
1716 UpdateShuttleLogbook("shuttle_done");
1720 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
1722 if (checkEntry->GetDetectorStatus(iDet) == AliShuttleLogbookEntry::kUnprocessed)
1724 AliDebug(2, Form("Run %d: setting %s as \"not first time unprocessed\"",
1725 checkEntry->GetRun(), GetDetName(iDet)));
1726 fFirstUnprocessed[iDet] = kFALSE;
1732 // remove ML instance
1738 return hasError == kFALSE;
1741 //______________________________________________________________________________________________
1742 Bool_t AliShuttle::ProcessCurrentDetector()
1745 // Makes data retrieval just for a specific detector (fCurrentDetector).
1746 // Threre should be a configuration for this detector.
1748 Log("SHUTTLE", Form("ProcessCurrentDetector - Retrieving values for %s, run %d",
1749 fCurrentDetector.Data(), GetCurrentRun()));
1751 TString wd = gSystem->WorkingDirectory();
1753 if (!CleanReferenceStorage(fCurrentDetector.Data()))
1756 gSystem->ChangeDirectory(wd.Data());
1758 TMap* dcsMap = new TMap();
1760 // call preprocessor
1761 AliPreprocessor* aPreprocessor =
1762 dynamic_cast<AliPreprocessor*> (fPreprocessorMap.GetValue(fCurrentDetector));
1764 aPreprocessor->Initialize(GetCurrentRun(), GetCurrentStartTime(), GetCurrentEndTime());
1766 Bool_t processDCS = aPreprocessor->ProcessDCS();
1770 Log(fCurrentDetector, "ProcessCurrentDetector -"
1771 " The preprocessor requested to skip the retrieval of DCS values");
1773 else if (fTestMode & kSkipDCS)
1775 Log(fCurrentDetector, "ProcessCurrentDetector - In TESTMODE: Skipping DCS processing");
1777 else if (fTestMode & kErrorDCS)
1779 Log(fCurrentDetector, "ProcessCurrentDetector - In TESTMODE: Simulating DCS error");
1780 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
1781 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1786 UpdateShuttleStatus(AliShuttleStatus::kDCSStarted);
1788 // Query DCS archive
1789 Int_t nServers = fConfig->GetNServers(fCurrentDetector);
1791 for (int iServ=0; iServ<nServers; iServ++)
1794 TString host(fConfig->GetDCSHost(fCurrentDetector, iServ));
1795 Int_t port = fConfig->GetDCSPort(fCurrentDetector, iServ);
1796 Int_t multiSplit = fConfig->GetMultiSplit(fCurrentDetector, iServ);
1798 Log(fCurrentDetector, Form("ProcessCurrentDetector -"
1799 " Querying DCS Amanda server %s:%d (%d of %d)",
1800 host.Data(), port, iServ+1, nServers));
1805 if (fConfig->GetDCSAliases(fCurrentDetector, iServ)->GetEntries() > 0)
1807 aliasMap = GetValueSet(host, port,
1808 fConfig->GetDCSAliases(fCurrentDetector, iServ),
1809 kAlias, multiSplit);
1812 Log(fCurrentDetector,
1813 Form("ProcessCurrentDetector -"
1814 " Error retrieving DCS aliases from server %s."
1815 " Sending mail to DCS experts!", host.Data()));
1816 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1818 if (!SendMailToDCS())
1819 Log("SHUTTLE", Form("ProcessCurrentDetector - Could not send mail to DCS experts!"));
1826 if (fConfig->GetDCSDataPoints(fCurrentDetector, iServ)->GetEntries() > 0)
1828 dpMap = GetValueSet(host, port,
1829 fConfig->GetDCSDataPoints(fCurrentDetector, iServ),
1833 Log(fCurrentDetector,
1834 Form("ProcessCurrentDetector -"
1835 " Error retrieving DCS data points from server %s."
1836 " Sending mail to DCS experts!", host.Data()));
1837 UpdateShuttleStatus(AliShuttleStatus::kDCSError);
1839 if (!SendMailToDCS())
1840 Log("SHUTTLE", Form("ProcessCurrentDetector - Could not send mail to DCS experts!"));
1842 if (aliasMap) delete aliasMap;
1848 // merge aliasMap and dpMap into dcsMap
1850 TIter iter(aliasMap);
1851 TObjString* key = 0;
1852 while ((key = (TObjString*) iter.Next()))
1853 dcsMap->Add(key, aliasMap->GetValue(key->String()));
1855 aliasMap->SetOwner(kFALSE);
1861 TObjString* key = 0;
1862 while ((key = (TObjString*) iter.Next()))
1863 dcsMap->Add(key, dpMap->GetValue(key->String()));
1865 dpMap->SetOwner(kFALSE);
1871 // save map into file, to help debugging in case of preprocessor error
1872 TFile* f = TFile::Open("DCSMap.root","recreate");
1874 dcsMap->Write("DCSMap", TObject::kSingleKey);
1878 // DCS Archive DB processing successful. Call Preprocessor!
1879 UpdateShuttleStatus(AliShuttleStatus::kPPStarted);
1881 UInt_t returnValue = aPreprocessor->Process(dcsMap);
1883 if (returnValue > 0) // Preprocessor error!
1885 Log(fCurrentDetector, Form("ProcessCurrentDetector - "
1886 "Preprocessor failed. Process returned %d.", returnValue));
1887 UpdateShuttleStatus(AliShuttleStatus::kPPError);
1888 dcsMap->DeleteAll();
1894 UpdateShuttleStatus(AliShuttleStatus::kPPDone);
1895 Log(fCurrentDetector, Form("ProcessCurrentDetector - %s preprocessor returned success",
1896 fCurrentDetector.Data()));
1898 dcsMap->DeleteAll();
1904 //______________________________________________________________________________________________
1905 Bool_t AliShuttle::QueryShuttleLogbook(const char* whereClause,
1908 // Query DAQ's Shuttle logbook and fills detector status object.
1909 // Call QueryRunParameters to query DAQ logbook for run parameters.
1912 entries.SetOwner(1);
1914 // check connection, in case connect
1915 if(!Connect(3)) return kFALSE;
1918 sqlQuery = Form("select * from %s %s order by run", fConfig->GetShuttlelbTable(), whereClause);
1920 TSQLResult* aResult = fServer[3]->Query(sqlQuery);
1922 AliError(Form("Can't execute query <%s>!", sqlQuery.Data()));
1926 AliDebug(2,Form("Query = %s", sqlQuery.Data()));
1928 if(aResult->GetRowCount() == 0) {
1929 Log("SHUTTLE", "No entries in Shuttle Logbook match request");
1934 // TODO Check field count!
1935 const UInt_t nCols = 23;
1936 if (aResult->GetFieldCount() != (Int_t) nCols) {
1937 Log("SHUTTLE", "Invalid SQL result field number!");
1943 while ((aRow = aResult->Next())) {
1944 TString runString(aRow->GetField(0), aRow->GetFieldLength(0));
1945 Int_t run = runString.Atoi();
1947 AliShuttleLogbookEntry *entry = QueryRunParameters(run);
1951 // loop on detectors
1952 for(UInt_t ii = 0; ii < nCols; ii++)
1953 entry->SetDetectorStatus(aResult->GetFieldName(ii), aRow->GetField(ii));
1955 entries.AddLast(entry);
1963 //______________________________________________________________________________________________
1964 AliShuttleLogbookEntry* AliShuttle::QueryRunParameters(Int_t run)
1967 // Retrieve run parameters written in the DAQ logbook and sets them into AliShuttleLogbookEntry object
1970 // check connection, in case connect
1975 sqlQuery.Form("select * from %s where run=%d", fConfig->GetDAQlbTable(), run);
1977 TSQLResult* aResult = fServer[3]->Query(sqlQuery);
1979 Log("SHUTTLE", Form("Can't execute query <%s>!", sqlQuery.Data()));
1983 if (aResult->GetRowCount() == 0) {
1984 Log("SHUTTLE", Form("QueryRunParameters - No entry in DAQ Logbook for run %d. Skipping", run));
1989 if (aResult->GetRowCount() > 1) {
1990 Log("SHUTTLE", Form("QueryRunParameters - UNEXPECTED: "
1991 "more than one entry in DAQ Logbook for run %d!", run));
1996 TSQLRow* aRow = aResult->Next();
1999 Log("SHUTTLE", Form("QueryRunParameters - Could not retrieve row for run %d. Skipping", run));
2004 AliShuttleLogbookEntry* entry = new AliShuttleLogbookEntry(run);
2006 for (Int_t ii = 0; ii < aResult->GetFieldCount(); ii++)
2007 entry->SetRunParameter(aResult->GetFieldName(ii), aRow->GetField(ii));
2009 UInt_t startTime = entry->GetStartTime();
2010 UInt_t endTime = entry->GetEndTime();
2012 if (!startTime || !endTime || startTime > endTime) {
2014 Form("QueryRunParameters - Invalid parameters for Run %d: startTime = %d, endTime = %d",
2015 run, startTime, endTime));
2028 //______________________________________________________________________________________________
2029 TMap* AliShuttle::GetValueSet(const char* host, Int_t port, const TSeqCollection* entries,
2030 DCSType type, Int_t multiSplit)
2032 // Retrieve all "entry" data points from the DCS server
2033 // host, port: TSocket connection parameters
2034 // entries: list of name of the alias or data point
2035 // type: kAlias or kDP
2036 // returns TMap of values, 0 when failure
2038 AliDCSClient client(host, port, fTimeout, fRetries, multiSplit);
2043 result = client.GetAliasValues(entries, GetCurrentStartTime(),
2044 GetCurrentEndTime());
2046 else if (type == kDP)
2048 result = client.GetDPValues(entries, GetCurrentStartTime(),
2049 GetCurrentEndTime());
2054 Log(fCurrentDetector.Data(), Form("GetValueSet - Can't get entries! Reason: %s",
2055 client.GetErrorString(client.GetResultErrorCode())));
2056 if (client.GetResultErrorCode() == AliDCSClient::fgkServerError)
2057 Log(fCurrentDetector.Data(), Form("GetValueSet - Server error code: %s",
2058 client.GetServerError().Data()));
2066 //______________________________________________________________________________________________
2067 const char* AliShuttle::GetFile(Int_t system, const char* detector,
2068 const char* id, const char* source)
2070 // Get calibration file from file exchange servers
2071 // First queris the FXS database for the file name, using the run, detector, id and source info
2072 // then calls RetrieveFile(filename) for actual copy to local disk
2073 // run: current run being processed (given by Logbook entry fLogbookEntry)
2074 // detector: the Preprocessor name
2075 // id: provided as a parameter by the Preprocessor
2076 // source: provided by the Preprocessor through GetFileSources function
2078 // check if test mode should simulate a FXS error
2079 if (fTestMode & kErrorFXSFiles)
2081 Log(detector, Form("GetFile - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
2085 // check connection, in case connect
2086 if (!Connect(system))
2088 Log(detector, Form("GetFile - Couldn't connect to %s FXS database", GetSystemName(system)));
2092 // Query preparation
2093 TString sourceName(source);
2095 TString sqlQueryStart = Form("select filePath,size,fileChecksum from %s where",
2096 fConfig->GetFXSdbTable(system));
2097 TString whereClause = Form("run=%d and detector=\"%s\" and fileId=\"%s\"",
2098 GetCurrentRun(), detector, id);
2102 whereClause += Form(" and DAQsource=\"%s\"", source);
2104 else if (system == kDCS)
2108 else if (system == kHLT)
2110 whereClause += Form(" and DDLnumbers=\"%s\"", source);
2114 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
2116 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2119 TSQLResult* aResult = 0;
2120 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2122 Log(detector, Form("GetFileName - Can't execute SQL query to %s database for: id = %s, source = %s",
2123 GetSystemName(system), id, sourceName.Data()));
2127 if(aResult->GetRowCount() == 0)
2130 Form("GetFileName - No entry in %s FXS db for: id = %s, source = %s",
2131 GetSystemName(system), id, sourceName.Data()));
2136 if (aResult->GetRowCount() > 1) {
2138 Form("GetFileName - More than one entry in %s FXS db for: id = %s, source = %s",
2139 GetSystemName(system), id, sourceName.Data()));
2144 if (aResult->GetFieldCount() != nFields) {
2146 Form("GetFileName - Wrong field count in %s FXS db for: id = %s, source = %s",
2147 GetSystemName(system), id, sourceName.Data()));
2152 TSQLRow* aRow = dynamic_cast<TSQLRow*> (aResult->Next());
2155 Log(detector, Form("GetFileName - Empty set result in %s FXS db from query: id = %s, source = %s",
2156 GetSystemName(system), id, sourceName.Data()));
2161 TString filePath(aRow->GetField(0), aRow->GetFieldLength(0));
2162 TString fileSize(aRow->GetField(1), aRow->GetFieldLength(1));
2163 TString fileChecksum(aRow->GetField(2), aRow->GetFieldLength(2));
2168 AliDebug(2, Form("filePath = %s; size = %s, fileChecksum = %s",
2169 filePath.Data(), fileSize.Data(), fileChecksum.Data()));
2171 // retrieved file is renamed to make it unique
2172 TString localFileName = Form("%s/%s_%d_process/%s_%s_%d_%s_%s.shuttle",
2173 GetShuttleTempDir(), detector, GetCurrentRun(),
2174 GetSystemName(system), detector, GetCurrentRun(),
2175 id, sourceName.Data());
2178 // file retrieval from FXS
2179 UInt_t nRetries = 0;
2180 UInt_t maxRetries = 3;
2181 Bool_t result = kFALSE;
2183 // copy!! if successful TSystem::Exec returns 0
2184 while(nRetries++ < maxRetries) {
2185 AliDebug(2, Form("Trying to copy file. Retry # %d", nRetries));
2186 result = RetrieveFile(system, filePath.Data(), localFileName.Data());
2189 Log(detector, Form("GetFileName - Copy of file %s from %s FXS failed",
2190 filePath.Data(), GetSystemName(system)));
2194 if (fileChecksum.Length()>0)
2196 // compare md5sum of local file with the one stored in the FXS DB
2197 Int_t md5Comp = gSystem->Exec(Form("md5sum %s |grep %s 2>&1 > /dev/null",
2198 localFileName.Data(), fileChecksum.Data()));
2202 Log(detector, Form("GetFileName - md5sum of file %s does not match with local copy!",
2208 Log(fCurrentDetector, Form("GetFile - md5sum of file %s not set in %s database, skipping comparison",
2209 filePath.Data(), GetSystemName(system)));
2214 if(!result) return 0;
2216 fFXSCalled[system]=kTRUE;
2217 TObjString *fileParams = new TObjString(Form("%s#!?!#%s", id, sourceName.Data()));
2218 fFXSlist[system].Add(fileParams);
2220 static TString staticLocalFileName;
2221 staticLocalFileName.Form("%s", localFileName.Data());
2223 Log(fCurrentDetector, Form("GetFile - Retrieved file with id %s and "
2224 "source %s from %s to %s", id, source,
2225 GetSystemName(system), localFileName.Data()));
2227 return staticLocalFileName.Data();
2230 //______________________________________________________________________________________________
2231 Bool_t AliShuttle::RetrieveFile(UInt_t system, const char* fxsFileName, const char* localFileName)
2234 // Copies file from FXS to local Shuttle machine
2237 // check temp directory: trying to cd to temp; if it does not exist, create it
2238 AliDebug(2, Form("Copy file %s from %s FXS into %s",
2239 GetSystemName(system), fxsFileName, localFileName));
2241 TString tmpDir(localFileName);
2243 tmpDir = tmpDir(0,tmpDir.Last('/'));
2245 Int_t noDir = gSystem->GetPathInfo(tmpDir.Data(), 0, (Long64_t*) 0, 0, 0);
2246 if (noDir) // temp dir does not exists!
2248 if (gSystem->mkdir(tmpDir.Data(), 1))
2250 Log(fCurrentDetector.Data(), "RetrieveFile - could not make temp directory!!");
2255 TString baseFXSFolder;
2258 baseFXSFolder = "FES/";
2260 else if (system == kDCS)
2264 else if (system == kHLT)
2266 baseFXSFolder = "/opt/FXS/";
2270 TString command = Form("scp -oPort=%d -2 %s@%s:%s%s %s",
2271 fConfig->GetFXSPort(system),
2272 fConfig->GetFXSUser(system),
2273 fConfig->GetFXSHost(system),
2274 baseFXSFolder.Data(),
2278 AliDebug(2, Form("%s",command.Data()));
2280 Bool_t result = (gSystem->Exec(command.Data()) == 0);
2285 //______________________________________________________________________________________________
2286 TList* AliShuttle::GetFileSources(Int_t system, const char* detector, const char* id)
2289 // Get sources producing the condition file Id from file exchange servers
2290 // if id is NULL all sources are returned (distinct)
2293 Log(detector, Form("GetFileSources - Retrieving sources with id %s from %s", id, GetSystemName(system)));
2295 // check if test mode should simulate a FXS error
2296 if (fTestMode & kErrorFXSSources)
2298 Log(detector, Form("GetFileSources - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
2304 Log(detector, "GetFileSources - WARNING: DCS system has only one source of data!");
2305 TList *list = new TList();
2307 list->Add(new TObjString(" "));
2311 // check connection, in case connect
2312 if (!Connect(system))
2314 Log(detector, Form("GetFileSources - Couldn't connect to %s FXS database", GetSystemName(system)));
2318 TString sourceName = 0;
2321 sourceName = "DAQsource";
2322 } else if (system == kHLT)
2324 sourceName = "DDLnumbers";
2327 TString sqlQueryStart = Form("select distinct %s from %s where", sourceName.Data(), fConfig->GetFXSdbTable(system));
2328 TString whereClause = Form("run=%d and detector=\"%s\"",
2329 GetCurrentRun(), detector);
2331 whereClause += Form(" and fileId=\"%s\"", id);
2332 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
2334 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2337 TSQLResult* aResult;
2338 aResult = fServer[system]->Query(sqlQuery);
2340 Log(detector, Form("GetFileSources - Can't execute SQL query to %s database for id: %s",
2341 GetSystemName(system), id));
2345 TList *list = new TList();
2348 if (aResult->GetRowCount() == 0)
2351 Form("GetFileSources - No entry in %s FXS table for id: %s", GetSystemName(system), id));
2356 Log(detector, Form("GetFileSources - Found %d sources", aResult->GetRowCount()));
2359 while ((aRow = aResult->Next()))
2362 TString source(aRow->GetField(0), aRow->GetFieldLength(0));
2363 AliDebug(2, Form("%s = %s", sourceName.Data(), source.Data()));
2364 list->Add(new TObjString(source));
2373 //______________________________________________________________________________________________
2374 TList* AliShuttle::GetFileIDs(Int_t system, const char* detector, const char* source)
2377 // Get all ids of condition files produced by a given source from file exchange servers
2380 Log(detector, Form("GetFileIDs - Retrieving ids with source %s with %s", source, GetSystemName(system)));
2382 // check if test mode should simulate a FXS error
2383 if (fTestMode & kErrorFXSSources)
2385 Log(detector, Form("GetFileIDs - In TESTMODE - Simulating error while connecting to %s FXS", GetSystemName(system)));
2389 // check connection, in case connect
2390 if (!Connect(system))
2392 Log(detector, Form("GetFileIDs - Couldn't connect to %s FXS database", GetSystemName(system)));
2396 TString sourceName = 0;
2399 sourceName = "DAQsource";
2400 } else if (system == kHLT)
2402 sourceName = "DDLnumbers";
2405 TString sqlQueryStart = Form("select fileId from %s where", fConfig->GetFXSdbTable(system));
2406 TString whereClause = Form("run=%d and detector=\"%s\"",
2407 GetCurrentRun(), detector);
2408 if (sourceName.Length() > 0 && source)
2409 whereClause += Form(" and %s=\"%s\"", sourceName.Data(), source);
2410 TString sqlQuery = Form("%s %s", sqlQueryStart.Data(), whereClause.Data());
2412 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2415 TSQLResult* aResult;
2416 aResult = fServer[system]->Query(sqlQuery);
2418 Log(detector, Form("GetFileIDs - Can't execute SQL query to %s database for source: %s",
2419 GetSystemName(system), source));
2423 TList *list = new TList();
2426 if (aResult->GetRowCount() == 0)
2429 Form("GetFileIDs - No entry in %s FXS table for source: %s", GetSystemName(system), source));
2434 Log(detector, Form("GetFileIDs - Found %d ids", aResult->GetRowCount()));
2438 while ((aRow = aResult->Next()))
2441 TString id(aRow->GetField(0), aRow->GetFieldLength(0));
2442 AliDebug(2, Form("fileId = %s", id.Data()));
2443 list->Add(new TObjString(id));
2452 //______________________________________________________________________________________________
2453 Bool_t AliShuttle::Connect(Int_t system)
2455 // Connect to MySQL Server of the system's FXS MySQL databases
2456 // DAQ Logbook, Shuttle Logbook and DAQ FXS db are on the same host
2459 // check connection: if already connected return
2460 if(fServer[system] && fServer[system]->IsConnected()) return kTRUE;
2462 TString dbHost, dbUser, dbPass, dbName;
2464 if (system < 3) // FXS db servers
2466 dbHost = Form("mysql://%s:%d", fConfig->GetFXSdbHost(system), fConfig->GetFXSdbPort(system));
2467 dbUser = fConfig->GetFXSdbUser(system);
2468 dbPass = fConfig->GetFXSdbPass(system);
2469 dbName = fConfig->GetFXSdbName(system);
2470 } else { // Run & Shuttle logbook servers
2471 // TODO Will the Shuttle logbook server be the same as the Run logbook server ???
2472 dbHost = Form("mysql://%s:%d", fConfig->GetDAQlbHost(), fConfig->GetDAQlbPort());
2473 dbUser = fConfig->GetDAQlbUser();
2474 dbPass = fConfig->GetDAQlbPass();
2475 dbName = fConfig->GetDAQlbDB();
2478 fServer[system] = TSQLServer::Connect(dbHost.Data(), dbUser.Data(), dbPass.Data());
2479 if (!fServer[system] || !fServer[system]->IsConnected()) {
2482 AliError(Form("Can't establish connection to FXS database for %s",
2483 AliShuttleInterface::GetSystemName(system)));
2485 AliError("Can't establish connection to Run logbook.");
2487 if(fServer[system]) delete fServer[system];
2492 TSQLResult* aResult=0;
2495 aResult = fServer[kDAQ]->GetTables(dbName.Data());
2498 aResult = fServer[kDCS]->GetTables(dbName.Data());
2501 aResult = fServer[kHLT]->GetTables(dbName.Data());
2504 aResult = fServer[3]->GetTables(dbName.Data());
2512 //______________________________________________________________________________________________
2513 Bool_t AliShuttle::UpdateTable()
2516 // Update FXS table filling time_processed field in all rows corresponding to current run and detector
2519 Bool_t result = kTRUE;
2521 for (UInt_t system=0; system<3; system++)
2523 if(!fFXSCalled[system]) continue;
2525 // check connection, in case connect
2526 if (!Connect(system))
2528 Log(fCurrentDetector, Form("UpdateTable - Couldn't connect to %s FXS database", GetSystemName(system)));
2533 TTimeStamp now; // now
2535 // Loop on FXS list entries
2536 TIter iter(&fFXSlist[system]);
2537 TObjString *aFXSentry=0;
2538 while ((aFXSentry = dynamic_cast<TObjString*> (iter.Next())))
2540 TString aFXSentrystr = aFXSentry->String();
2541 TObjArray *aFXSarray = aFXSentrystr.Tokenize("#!?!#");
2542 if (!aFXSarray || aFXSarray->GetEntries() != 2 )
2544 Log(fCurrentDetector, Form("UpdateTable - error updating %s FXS entry. Check string: <%s>",
2545 GetSystemName(system), aFXSentrystr.Data()));
2546 if(aFXSarray) delete aFXSarray;
2550 const char* fileId = ((TObjString*) aFXSarray->At(0))->GetName();
2551 const char* source = ((TObjString*) aFXSarray->At(1))->GetName();
2553 TString whereClause;
2556 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DAQsource=\"%s\";",
2557 GetCurrentRun(), fCurrentDetector.Data(), fileId, source);
2559 else if (system == kDCS)
2561 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\";",
2562 GetCurrentRun(), fCurrentDetector.Data(), fileId);
2564 else if (system == kHLT)
2566 whereClause = Form("where run=%d and detector=\"%s\" and fileId=\"%s\" and DDLnumbers=\"%s\";",
2567 GetCurrentRun(), fCurrentDetector.Data(), fileId, source);
2572 TString sqlQuery = Form("update %s set time_processed=%d %s", fConfig->GetFXSdbTable(system),
2573 now.GetSec(), whereClause.Data());
2575 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2578 TSQLResult* aResult;
2579 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2582 Log(fCurrentDetector, Form("UpdateTable - %s db: can't execute SQL query <%s>",
2583 GetSystemName(system), sqlQuery.Data()));
2594 //______________________________________________________________________________________________
2595 Bool_t AliShuttle::UpdateTableFailCase()
2597 // Update FXS table filling time_processed field in all rows corresponding to current run and detector
2598 // this is called in case the preprocessor is declared failed for the current run, because
2599 // the fields are updated only in case of success
2601 Bool_t result = kTRUE;
2603 for (UInt_t system=0; system<3; system++)
2605 // check connection, in case connect
2606 if (!Connect(system))
2608 Log(fCurrentDetector, Form("UpdateTableFailCase - Couldn't connect to %s FXS database",
2609 GetSystemName(system)));
2614 TTimeStamp now; // now
2616 // Loop on FXS list entries
2618 TString whereClause = Form("where run=%d and detector=\"%s\";",
2619 GetCurrentRun(), fCurrentDetector.Data());
2622 TString sqlQuery = Form("update %s set time_processed=%d %s", fConfig->GetFXSdbTable(system),
2623 now.GetSec(), whereClause.Data());
2625 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2628 TSQLResult* aResult;
2629 aResult = dynamic_cast<TSQLResult*> (fServer[system]->Query(sqlQuery));
2632 Log(fCurrentDetector, Form("UpdateTableFailCase - %s db: can't execute SQL query <%s>",
2633 GetSystemName(system), sqlQuery.Data()));
2643 //______________________________________________________________________________________________
2644 Bool_t AliShuttle::UpdateShuttleLogbook(const char* detector, const char* status)
2647 // Update Shuttle logbook filling detector or shuttle_done column
2648 // ex. of usage: UpdateShuttleLogbook("PHOS", "DONE") or UpdateShuttleLogbook("shuttle_done")
2651 // check connection, in case connect
2653 Log("SHUTTLE", "UpdateShuttleLogbook - Couldn't connect to DAQ Logbook.");
2657 TString detName(detector);
2659 if(detName == "shuttle_done")
2661 setClause = "set shuttle_done=1";
2663 // Send the information to ML
2664 TMonaLisaText mlStatus("SHUTTLE_status", "Done");
2667 mlList.Add(&mlStatus);
2669 fMonaLisa->SendParameters(&mlList);
2671 TString statusStr(status);
2672 if(statusStr.Contains("done", TString::kIgnoreCase) ||
2673 statusStr.Contains("failed", TString::kIgnoreCase)){
2674 setClause = Form("set %s=\"%s\"", detector, status);
2677 Form("UpdateShuttleLogbook - Invalid status <%s> for detector %s",
2683 TString whereClause = Form("where run=%d", GetCurrentRun());
2685 TString sqlQuery = Form("update %s %s %s",
2686 fConfig->GetShuttlelbTable(), setClause.Data(), whereClause.Data());
2688 AliDebug(2, Form("SQL query: \n%s",sqlQuery.Data()));
2691 TSQLResult* aResult;
2692 aResult = dynamic_cast<TSQLResult*> (fServer[3]->Query(sqlQuery));
2694 Log("SHUTTLE", Form("UpdateShuttleLogbook - Can't execute query <%s>", sqlQuery.Data()));
2702 //______________________________________________________________________________________________
2703 Int_t AliShuttle::GetCurrentRun() const
2706 // Get current run from logbook entry
2709 return fLogbookEntry ? fLogbookEntry->GetRun() : -1;
2712 //______________________________________________________________________________________________
2713 UInt_t AliShuttle::GetCurrentStartTime() const
2716 // get current start time
2719 return fLogbookEntry ? fLogbookEntry->GetStartTime() : 0;
2722 //______________________________________________________________________________________________
2723 UInt_t AliShuttle::GetCurrentEndTime() const
2726 // get current end time from logbook entry
2729 return fLogbookEntry ? fLogbookEntry->GetEndTime() : 0;
2732 //______________________________________________________________________________________________
2733 UInt_t AliShuttle::GetCurrentYear() const
2736 // Get current year from logbook entry
2739 if (!fLogbookEntry) return 0;
2741 TTimeStamp startTime(GetCurrentStartTime());
2742 TString year = Form("%d",startTime.GetDate());
2748 //______________________________________________________________________________________________
2749 const char* AliShuttle::GetLHCPeriod() const
2752 // Get current LHC period from logbook entry
2755 if (!fLogbookEntry) return 0;
2757 return fLogbookEntry->GetRunParameter("LHCperiod");
2760 //______________________________________________________________________________________________
2761 void AliShuttle::Log(const char* detector, const char* message)
2764 // Fill log string with a message
2767 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
2769 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE)) {
2770 AliError(Form("Can't open directory <%s>", GetShuttleLogDir()));
2775 gSystem->FreeDirectory(dir);
2778 TString toLog = Form("%s (%d): %s - ", TTimeStamp(time(0)).AsString("s"), getpid(), detector);
2779 if (GetCurrentRun() >= 0)
2780 toLog += Form("run %d - ", GetCurrentRun());
2781 toLog += Form("%s", message);
2783 AliInfo(toLog.Data());
2785 // if we redirect the log output already to the file, leave here
2786 if (fOutputRedirected && strcmp(detector, "SHUTTLE") != 0)
2789 TString fileName = GetLogFileName(detector);
2791 gSystem->ExpandPathName(fileName);
2794 logFile.open(fileName, ofstream::out | ofstream::app);
2796 if (!logFile.is_open()) {
2797 AliError(Form("Could not open file %s", fileName.Data()));
2801 logFile << toLog.Data() << "\n";
2806 //______________________________________________________________________________________________
2807 TString AliShuttle::GetLogFileName(const char* detector) const
2810 // returns the name of the log file for a given sub detector
2815 if (GetCurrentRun() >= 0)
2816 fileName.Form("%s/%s_%d.log", GetShuttleLogDir(), detector, GetCurrentRun());
2818 fileName.Form("%s/%s.log", GetShuttleLogDir(), detector);
2823 //______________________________________________________________________________________________
2824 Bool_t AliShuttle::Collect(Int_t run)
2827 // Collects conditions data for all UNPROCESSED run written to DAQ LogBook in case of run = -1 (default)
2828 // If a dedicated run is given this run is processed
2830 // In operational mode, this is the Shuttle function triggered by the EOR signal.
2834 Log("SHUTTLE","Collect - Shuttle called. Collecting conditions data for unprocessed runs");
2836 Log("SHUTTLE", Form("Collect - Shuttle called. Collecting conditions data for run %d", run));
2838 SetLastAction("Starting");
2840 TString whereClause("where shuttle_done=0");
2842 whereClause += Form(" and run=%d", run);
2844 TObjArray shuttleLogbookEntries;
2845 if (!QueryShuttleLogbook(whereClause, shuttleLogbookEntries))
2847 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2851 if (shuttleLogbookEntries.GetEntries() == 0)
2854 Log("SHUTTLE","Collect - Found no UNPROCESSED runs in Shuttle logbook");
2856 Log("SHUTTLE", Form("Collect - Run %d is already DONE "
2857 "or it does not exist in Shuttle logbook", run));
2861 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
2862 fFirstUnprocessed[iDet] = kTRUE;
2866 // query Shuttle logbook for earlier runs, check if some detectors are unprocessed,
2867 // flag them into fFirstUnprocessed array
2868 TString whereClause(Form("where shuttle_done=0 and run < %d", run));
2869 TObjArray tmpLogbookEntries;
2870 if (!QueryShuttleLogbook(whereClause, tmpLogbookEntries))
2872 Log("SHUTTLE", "Collect - Can't retrieve entries from Shuttle logbook");
2876 TIter iter(&tmpLogbookEntries);
2877 AliShuttleLogbookEntry* anEntry = 0;
2878 while ((anEntry = dynamic_cast<AliShuttleLogbookEntry*> (iter.Next())))
2880 for (UInt_t iDet=0; iDet<NDetectors(); iDet++)
2882 if (anEntry->GetDetectorStatus(iDet) == AliShuttleLogbookEntry::kUnprocessed)
2884 AliDebug(2, Form("Run %d: setting %s as \"not first time unprocessed\"",
2885 anEntry->GetRun(), GetDetName(iDet)));
2886 fFirstUnprocessed[iDet] = kFALSE;
2894 if (!RetrieveConditionsData(shuttleLogbookEntries))
2896 Log("SHUTTLE", "Collect - Process of at least one run failed");
2900 Log("SHUTTLE", "Collect - Requested run(s) successfully processed");
2904 //______________________________________________________________________________________________
2905 Bool_t AliShuttle::RetrieveConditionsData(const TObjArray& dateEntries)
2908 // Retrieve conditions data for all runs that aren't processed yet
2911 Bool_t hasError = kFALSE;
2913 TIter iter(&dateEntries);
2914 AliShuttleLogbookEntry* anEntry;
2916 while ((anEntry = (AliShuttleLogbookEntry*) iter.Next())){
2917 if (!Process(anEntry)){
2921 // clean SHUTTLE temp directory
2922 //TString filename = Form("%s/*.shuttle", GetShuttleTempDir());
2923 //RemoveFile(filename.Data());
2926 return hasError == kFALSE;
2929 //______________________________________________________________________________________________
2930 ULong_t AliShuttle::GetTimeOfLastAction() const
2933 // Gets time of last action
2938 fMonitoringMutex->Lock();
2940 tmp = fLastActionTime;
2942 fMonitoringMutex->UnLock();
2947 //______________________________________________________________________________________________
2948 const TString AliShuttle::GetLastAction() const
2951 // returns a string description of the last action
2956 fMonitoringMutex->Lock();
2960 fMonitoringMutex->UnLock();
2965 //______________________________________________________________________________________________
2966 void AliShuttle::SetLastAction(const char* action)
2969 // updates the monitoring variables
2972 fMonitoringMutex->Lock();
2974 fLastAction = action;
2975 fLastActionTime = time(0);
2977 fMonitoringMutex->UnLock();
2980 //______________________________________________________________________________________________
2981 const char* AliShuttle::GetRunParameter(const char* param)
2984 // returns run parameter read from DAQ logbook
2987 if(!fLogbookEntry) {
2988 AliError("No logbook entry!");
2992 return fLogbookEntry->GetRunParameter(param);
2995 //______________________________________________________________________________________________
2996 AliCDBEntry* AliShuttle::GetFromOCDB(const char* detector, const AliCDBPath& path)
2999 // returns object from OCDB valid for current run
3002 if (fTestMode & kErrorOCDB)
3004 Log(detector, "GetFromOCDB - In TESTMODE - Simulating error with OCDB");
3008 AliCDBStorage *sto = AliCDBManager::Instance()->GetStorage(fgkMainCDB);
3011 Log(detector, "GetFromOCDB - Cannot activate main OCDB for query!");
3015 return dynamic_cast<AliCDBEntry*> (sto->Get(path, GetCurrentRun()));
3018 //______________________________________________________________________________________________
3019 Bool_t AliShuttle::SendMail()
3022 // sends a mail to the subdetector expert in case of preprocessor error
3025 if (fTestMode != kNone)
3028 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
3031 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE))
3033 Log("SHUTTLE", Form("SendMail - Can't open directory <%s>", GetShuttleLogDir()));
3038 gSystem->FreeDirectory(dir);
3041 TString bodyFileName;
3042 bodyFileName.Form("%s/mail.body", GetShuttleLogDir());
3043 gSystem->ExpandPathName(bodyFileName);
3046 mailBody.open(bodyFileName, ofstream::out);
3048 if (!mailBody.is_open())
3050 Log("SHUTTLE", Form("Could not open mail body file %s", bodyFileName.Data()));
3055 TIter iterExperts(fConfig->GetResponsibles(fCurrentDetector));
3056 TObjString *anExpert=0;
3057 while ((anExpert = (TObjString*) iterExperts.Next()))
3059 to += Form("%s,", anExpert->GetName());
3061 to.Remove(to.Length()-1);
3062 AliDebug(2, Form("to: %s",to.Data()));
3065 Log("SHUTTLE", "List of detector responsibles not yet set!");
3069 TString cc="alberto.colla@cern.ch";
3071 TString subject = Form("%s Shuttle preprocessor FAILED in run %d !",
3072 fCurrentDetector.Data(), GetCurrentRun());
3073 AliDebug(2, Form("subject: %s", subject.Data()));
3075 TString body = Form("Dear %s expert(s), \n\n", fCurrentDetector.Data());
3076 body += Form("SHUTTLE just detected that your preprocessor "
3077 "failed processing run %d!!\n\n", GetCurrentRun());
3078 body += Form("Please check %s status on the SHUTTLE monitoring page: \n\n", fCurrentDetector.Data());
3079 body += Form("\thttp://pcalimonitor.cern.ch:8889/shuttle.jsp?time=168 \n\n");
3080 body += Form("Find the %s log for the current run on \n\n"
3081 "\thttp://pcalishuttle01.cern.ch:8880/logs/%s_%d.log \n\n",
3082 fCurrentDetector.Data(), fCurrentDetector.Data(), GetCurrentRun());
3083 body += Form("The last 10 lines of %s log file are following:\n\n");
3085 AliDebug(2, Form("Body begin: %s", body.Data()));
3087 mailBody << body.Data();
3089 mailBody.open(bodyFileName, ofstream::out | ofstream::app);
3091 TString logFileName = Form("%s/%s_%d.log", GetShuttleLogDir(), fCurrentDetector.Data(), GetCurrentRun());
3092 TString tailCommand = Form("tail -n 10 %s >> %s", logFileName.Data(), bodyFileName.Data());
3093 if (gSystem->Exec(tailCommand.Data()))
3095 mailBody << Form("%s log file not found ...\n\n", fCurrentDetector.Data());
3098 TString endBody = Form("------------------------------------------------------\n\n");
3099 endBody += Form("In case of problems please contact the SHUTTLE core team.\n\n");
3100 endBody += "Please do not answer this message directly, it is automatically generated.\n\n";
3101 endBody += "Greetings,\n\n \t\t\tthe SHUTTLE\n";
3103 AliDebug(2, Form("Body end: %s", endBody.Data()));
3105 mailBody << endBody.Data();
3110 TString mailCommand = Form("mail -s \"%s\" -c %s %s < %s",
3114 bodyFileName.Data());
3115 AliDebug(2, Form("mail command: %s", mailCommand.Data()));
3117 Bool_t result = gSystem->Exec(mailCommand.Data());
3122 //______________________________________________________________________________________________
3123 Bool_t AliShuttle::SendMailToDCS()
3126 // sends a mail to the DCS experts in case of DCS error
3129 if (fTestMode != kNone)
3132 void* dir = gSystem->OpenDirectory(GetShuttleLogDir());
3135 if (gSystem->mkdir(GetShuttleLogDir(), kTRUE))
3137 Log("SHUTTLE", Form("SendMailToDCS - Can't open directory <%s>", GetShuttleLogDir()));
3142 gSystem->FreeDirectory(dir);
3145 TString bodyFileName;
3146 bodyFileName.Form("%s/mail.body", GetShuttleLogDir());
3147 gSystem->ExpandPathName(bodyFileName);
3150 mailBody.open(bodyFileName, ofstream::out);
3152 if (!mailBody.is_open())
3154 Log("SHUTTLE", Form("SendMailToDCS - Could not open mail body file %s", bodyFileName.Data()));
3158 TString to="Vladimir.Fekete@cern.ch, Svetozar.Kapusta@cern.ch";
3159 //TString to="alberto.colla@cern.ch";
3160 AliDebug(2, Form("to: %s",to.Data()));
3163 Log("SHUTTLE", "List of detector responsibles not yet set!");
3167 TString cc="alberto.colla@cern.ch";
3169 TString subject = Form("Retrieval of data points for %s FAILED in run %d !",
3170 fCurrentDetector.Data(), GetCurrentRun());
3171 AliDebug(2, Form("subject: %s", subject.Data()));
3173 TString body = Form("Dear DCS experts, \n\n");
3174 body += Form("SHUTTLE couldn\'t retrieve the data points for detector %s "
3175 "in run %d!!\n\n", fCurrentDetector.Data(), GetCurrentRun());
3176 body += Form("Please check %s status on the SHUTTLE monitoring page: \n\n", fCurrentDetector.Data());
3177 body += Form("\thttp://pcalimonitor.cern.ch:8889/shuttle.jsp?time=168 \n\n");
3178 body += Form("Find the %s log for the current run on \n\n"
3179 "\thttp://pcalishuttle01.cern.ch:8880/logs/%s_%d.log \n\n",
3180 fCurrentDetector.Data(), fCurrentDetector.Data(), GetCurrentRun());
3181 body += Form("The last 10 lines of %s log file are following:\n\n");
3183 AliDebug(2, Form("Body begin: %s", body.Data()));
3185 mailBody << body.Data();
3187 mailBody.open(bodyFileName, ofstream::out | ofstream::app);
3189 TString logFileName = Form("%s/%s_%d.log", GetShuttleLogDir(), fCurrentDetector.Data(), GetCurrentRun());
3190 TString tailCommand = Form("tail -n 10 %s >> %s", logFileName.Data(), bodyFileName.Data());
3191 if (gSystem->Exec(tailCommand.Data()))
3193 mailBody << Form("%s log file not found ...\n\n", fCurrentDetector.Data());
3196 TString endBody = Form("------------------------------------------------------\n\n");
3197 endBody += Form("In case of problems please contact the SHUTTLE core team.\n\n");
3198 endBody += "Please do not answer this message directly, it is automatically generated.\n\n";
3199 endBody += "Greetings,\n\n \t\t\tthe SHUTTLE\n";
3201 AliDebug(2, Form("Body end: %s", endBody.Data()));
3203 mailBody << endBody.Data();
3208 TString mailCommand = Form("mail -s \"%s\" -c %s %s < %s",
3212 bodyFileName.Data());
3213 AliDebug(2, Form("mail command: %s", mailCommand.Data()));
3215 Bool_t result = gSystem->Exec(mailCommand.Data());
3220 //______________________________________________________________________________________________
3221 const char* AliShuttle::GetRunType()
3224 // returns run type read from "run type" logbook
3227 if(!fLogbookEntry) {
3228 AliError("No logbook entry!");
3232 return fLogbookEntry->GetRunType();
3235 //______________________________________________________________________________________________
3236 Bool_t AliShuttle::GetHLTStatus()
3238 // Return HLT status (ON=1 OFF=0)
3239 // Converts the HLT status from the status string read in the run logbook (not just a bool)
3241 if(!fLogbookEntry) {
3242 AliError("No logbook entry!");
3246 // TODO implement when HLTStatus is inserted in run logbook
3247 //TString hltStatus = fLogbookEntry->GetRunParameter("HLTStatus");
3248 //if(hltStatus == "OFF") {return kFALSE};
3253 //______________________________________________________________________________________________
3254 void AliShuttle::SetShuttleTempDir(const char* tmpDir)
3257 // sets Shuttle temp directory
3260 fgkShuttleTempDir = gSystem->ExpandPathName(tmpDir);
3263 //______________________________________________________________________________________________
3264 void AliShuttle::SetShuttleLogDir(const char* logDir)
3267 // sets Shuttle log directory
3270 fgkShuttleLogDir = gSystem->ExpandPathName(logDir);