BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
MdcHvDropSvc.cxx
Go to the documentation of this file.
1/**
2 * @file MdcHvDropSvc.cxx
3 * @author zhangzeheng (zhangzeheng@ihep.ac.cn)
4 * @brief main functions of this svc
5 * @version 0.1
6 * @date 2022-01-19
7 *
8 * @copyright Copyright (c) 2022
9 *
10 */
11
12#include <cstdio>
13#include <cstdlib>
14#include <cstring>
15#include <iostream>
16#include <sstream>
17
18#include "GaudiKernel/IDataProviderSvc.h"
19#include "GaudiKernel/IInterface.h"
20#include "GaudiKernel/ISvcLocator.h"
21#include "GaudiKernel/Kernel.h"
22#include "GaudiKernel/MsgStream.h"
23#include "GaudiKernel/PropertyMgr.h"
24#include "GaudiKernel/SmartDataPtr.h"
25#include "GaudiKernel/StatusCode.h"
26// #include "GaudiKernel/SvcFactory.h"
27#include "MdcHvDropSvc.h"
28
29#include "GaudiKernel/IIncidentListener.h"
30#include "GaudiKernel/IIncidentSvc.h"
31#include "GaudiKernel/Incident.h"
32
33#include "EventModel/Event.h"
34#include "EventModel/EventHeader.h"
35#include "EventModel/EventModel.h"
36#include "GaudiKernel/Bootstrap.h"
37#include "GaudiKernel/ISvcLocator.h"
38
39#include <TMath.h>
40
41// using namespace std;
42using std::cout;
43using std::endl;
44using std::string;
45
47
48MdcHvDropSvc::MdcHvDropSvc( const string& name, ISvcLocator* svcloc )
49 : base_class( name, svcloc ) {
50 // declare properties
51 declareProperty( "Host", m_host = std::string( "202.122.33.123" ) );
52 declareProperty( "DbName", m_dbName = std::string( "tof40t_linux" ) );
53 declareProperty( "TableName", m_table = std::string( "MDCLayerVmon" ) );
54 declareProperty( "UserName", m_userName = std::string( "guest" ) );
55 declareProperty( "Password", m_password = std::string( "guestpass" ) );
56 declareProperty( "Port", m_port = 6175 );
57 declareProperty( "IgnoreLayer_21_24", m_ignoreLayer_21_24 = true );
58 declareProperty( "RelativeHvDropThreshold", m_relativeHvDropThreshold = 0.007 );
59 declareProperty( "FetchHvDataLengthInSeconds", m_fetchLength = 5 * 3600 );
60 declareProperty( "UseEtsT1", m_useEtsT1 = 0 ); // whether to use EtsT1, if not, use time().
61 declareProperty( "EtsT1OffSet",
62 m_etsT1Offset = 0 ); // if is 0, and UseEtsT1, will be treated as using
63 // database time from database.. else, acts as
64 // calculating time_override=etsT1+etsT1Offset;
65
66 declareProperty( "Host2", m_host2 = std::string( "bes3db2.ihep.ac.cn" ) );
67 declareProperty( "DbName2", m_dbName2 = std::string( "run" ) );
68 declareProperty( "TableName2", m_table2 = std::string( "RunParams" ) );
69 declareProperty( "UserName2", m_userName2 = std::string( "guest" ) );
70 declareProperty( "Password2", m_password2 = std::string( "guestpass" ) );
71 declareProperty( "Port2", m_port2 = 3306 ); // 3306 is default port for mysql
72}
73
75
76// StatusCode MdcHvDropSvc::queryInterface( const InterfaceID& riid, void** ppvInterface ) {
77// if ( IID_IMdcHvDropSvc.versionMatch( riid ) )
78// { *ppvInterface = static_cast<IMdcHvDropSvc*>( this ); }
79// else { return Service::queryInterface( riid, ppvInterface ); }
80// return StatusCode::SUCCESS;
81// }
82
84 MsgStream log( msgSvc(), name() );
85 log << MSG::INFO << "MdcHvDropSvc::initialize()" << endmsg;
86
87 StatusCode sc = Service::initialize();
88 if ( sc.isFailure() ) return sc;
89
90 IIncidentSvc* incsvc;
91 sc = service( "IncidentSvc", incsvc );
92 int priority = 100;
93 if ( sc.isSuccess() ) { incsvc->addListener( this, "NewRun", priority ); }
94
95 sc = serviceLocator()->service( "EventDataSvc", m_eventSvc, true );
96 if ( sc.isFailure() )
97 {
98 log << MSG::ERROR << "Unable to find EventDataSvc " << endmsg;
99 return sc;
100 }
101
102 sc = initMySql();
103 if ( sc.isFailure() )
104 {
105 log << MSG::ERROR << "Unable to initialize mysql " << endmsg;
106 return sc;
107 }
108
109 return StatusCode::SUCCESS;
110}
111
113 MsgStream log( msgSvc(), name() );
114 log << MSG::INFO << "MdcHvDropSvc::finalize()" << endmsg;
115 // if(m_connect_offline) delete m_connect_offline;
116 return StatusCode::SUCCESS;
117}
118// TODO: multi-run.
119void MdcHvDropSvc::handle( const Incident& inc ) {
120 MsgStream log( msgSvc(), name() );
121 log << MSG::DEBUG << "handle: " << inc.type() << endmsg;
122 // so currently we do nothing.
123 // if (inc.type() == "NewRun") {
124 // log << MSG::DEBUG << "NewRun" << endmsg;
125 //
126 // SmartDataPtr<Event::EventHeader> eventHeader(m_eventSvc, "/Event/EventHeader");
127 // int run = eventHeader->runNumber();
128 // //cout<<"&&&&&&&&&&&&&&:&&&&&&&&&&&&&&&&&&&& MdcHvDropSvc handle,run="<<run<<endl;
129 // if (run < 0) run = -run;
130 // log << MSG::DEBUG << "handle: "
131 // << "Run in handle is: " << run << endmsg;
132 // cout << "-------------in MdcHvDropSvc in the following-----------" << endl;
133 // cout << "handle: "
134 // << "Run in handle is: " << run << endl;
135
136 // if (run >= m_RunFrom && run <= m_RunTo && m_ReadPar == true) {
137 // cout << "do not read the database repeatly in EmcShEnCalibConst" << endl;
138 // cout << "run,RunFrom,runTo=" << run << "," << m_RunFrom << "," << m_RunTo << endl;
139 // } else {
140 //
141 // //cout<<"read the database in EmcShEnCalibConst"<<endl;
142 // if (!getMdcHvDropSvcInfo()) {
143 // log << MSG::ERROR << "can not initilize Shower energy Calib Constants" << endmsg;
144 // } else {
145 // m_ReadPar = true;
146 // std::cout << "in handle of MdcHvDropSvc getPi0CalibFile()= " << getPi0CalibFile()
147 // << std::endl; std::cout << "getSingleGammaCalibFile()= " <<
148 // getSingleGammaCalibFile() << std::endl;
149 // }
150 // }
151 //}
152}
153
154/**
155 * @brief connects to mysql using pre-defined parameters.
156 *
157 * @return StatusCode
158 */
159StatusCode MdcHvDropSvc::initMySql() {
160 // char host [] = "202.122.33.123";
161 // char username[] = "guest";
162 // char password[] = "guestpass";
163 // int m_port = 6175;
164 // char database[] = "tof40t_linux";
165 // char querystring[] = "select * from MDCLayerVmon where id >=1000000 and id <= 1000010";
166
167 mysql_init( &m_mysql );
168
169 if ( !mysql_real_connect( &m_mysql, m_host.c_str(), m_userName.c_str(), m_password.c_str(),
170 m_dbName.c_str(), m_port, NULL, 0 ) )
171 {
172 std::cerr << "Connect to database" << m_host << ":" << m_port << " failed\n"
173 << "due to " << mysql_error( &m_mysql ) << std::endl;
174 return StatusCode::FAILURE;
175 }
176 return StatusCode::SUCCESS;
177}
178
179/**
180 * @brief timestamp to a string of the time in UTC+8
181 *
182 * from timestamp get sql formatted datetime string with TZ=UTC+8, or Asia/Shanghai
183 * our Slow Control Database stores datetime with TZ=UTC+8,
184 *
185 * @param utctime timestamp
186 * @param str the string to store
187 * @param length length of string
188 * @return size_t how many charactors are written to str (including trailing "\0"). basically
189 * 0==fail, !0 == succeed.
190 */
191size_t MdcHvDropSvc::Time_t2str( Time_t utctime, char* str, int length ) {
192 const int tzOffset = 60 * 60 * 8;
193 std::time_t timeShanghai = utctime + tzOffset;
194 std::tm* tm = std::gmtime( &timeShanghai ); // this is not thread safe
195 return std::strftime( str, length, "%Y-%m-%d %H:%M:%S", tm ); // as-is
196}
197
198/**
199 * @brief Get Time_t from a date_time string.
200 * require str be like "%Y-%m-%d %H:%M:%S"
201 * note that our date_time is fixed TZ=UTC+8, or Asia/Shanghai
202 *
203 * @param str date_time string
204 * @return Time_t
205 */
206Time_t MdcHvDropSvc::datetimeStr2Time_t( const char* str ) {
207 const int tzOffset = 60 * 60 * 8;
208 std::tm tm;
209 int year, month, day, hour, min, sec;
210 std::sscanf( str, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec );
211 tm.tm_year = year - 1900;
212 tm.tm_mon = month - 1;
213 tm.tm_mday = day;
214 tm.tm_hour = hour;
215 tm.tm_min = min;
216 tm.tm_sec = sec;
217 tm.tm_isdst = 0;
218 tm.tm_gmtoff = tzOffset;
219 Time_t time = std::mktime( &tm );
220 return time;
221}
222
223/**
224 * @brief fetch hv info from database between timeBegin and timeEnd. in DB time.
225 *
226 * @param timeBegin
227 * @param timeEnd
228 * @return StatusCode
229 */
230StatusCode MdcHvDropSvc::FetchHvInfo( Time_t timeBegin, Time_t timeEnd ) {
231 // MsgStream log(msgSvc(), "MdcHvDropSvc");
232 MsgStream log( msgSvc(), name() );
233 log << MSG::INFO << "MdcHvDropSvc::FetchHvInfo()" << endmsg;
234 char querystring[300];
235 char sTimeBegin[100], sTimeEnd[100];
236 Time_t2str( timeBegin, sTimeBegin, 100 );
237 Time_t2str( timeEnd, sTimeEnd, 100 );
238 // MYSQL_RES *res_set;
239
240 sprintf( querystring, "select * \
241 from %s \
242 where date_time >= '%s' \
243 and date_time <= '%s' ",
244 m_table.c_str(), sTimeBegin, sTimeEnd );
245 log << MSG::INFO << "sql_request=" << querystring << endmsg;
246 // yield:
247
248 // unsigned int nColomn;
249
250 if ( mysql_query( &m_mysql, querystring ) )
251 {
252 log << MSG::ERROR << "Error! mysql_query failed" << endmsg;
253 return StatusCode::FAILURE;
254 }
255 else
256 {
257 m_result = mysql_store_result( &m_mysql );
258 // nColomn = mysql_num_fields(m_result);
259 while ( ( m_row = mysql_fetch_row( m_result ) ) )
260 {
261 // unsigned long *lengths;
262 // lengths = mysql_fetch_lengths(m_result);
263
264 VDataItem item;
265 Time_t time;
266 sqlRow2Item( m_row, m_result, item, time ).ignore();
267 m_vData.push_back_sorted( time, item );
268
269 // for (int i = 0; i < nColomn; i++) {
270 // printf("[%.*s] \t", (int)lengths[i], m_row[i] ? //m_row[i] : "NULL");
271 // item[]
272 //
273 //}
274 // printf("\n");
275 }
276 log << MSG::INFO << "successfully fetched HV data from database." << endmsg;
277 }
278
279 return StatusCode::SUCCESS;
280}
281/**
282 * @brief returns average HV for a slice in a row, row[begin:end]
283 *
284 * contain row[sliceBegin];
285 * contains no row[sliceEnd];
286 */
287inline static double average( MYSQL_ROW row, int sliceBegin, int sliceEnd ) {
288
289 double sum = 0.0;
290 for ( int i = sliceBegin; i < sliceEnd; i++ ) { sum += atof( row[i] ); }
291 return sum / ( sliceEnd - sliceBegin );
292}
293
294/**
295 * @brief grab info stored in a row of mysql result, and build a VDataItem from it. also time.
296 *
297 * @param row
298 * @param result
299 * @param item the item
300 * @param time
301 * @return StatusCode
302 */
303StatusCode MdcHvDropSvc::sqlRow2Item( MYSQL_ROW row, MYSQL_RES* result, VDataItem& item,
304 Time_t& time ) {
305 // VDataItem& item=out;
306 MsgStream log( msgSvc(), name() );
307 log << MSG::DEBUG << "MdcHvDropSvc::sqlRow2Item()" << endmsg;
308 int nColomn = mysql_num_fields( result );
309 if ( nColomn != 102 )
310 {
311 log << MSG::ERROR << "ERROR: SQL output does not meet expectation" << endmsg;
312 return StatusCode::FAILURE;
313 }
314 // unsigned long *lengths;
315 // lengths = mysql_fetch_lengths(result);
316 time = datetimeStr2Time_t( row[1] );
317 item[0] = average( row, 39, 44 ); // S1
318 item[1] = average( row, 44, 50 ); // S2
319 item[2] = average( row, 50, 56 ); // S3
320 item[3] = average( row, 56, 62 ); // S4
321 item[4] = atof( row[80] ); // S5
322 item[5] = atof( row[81] ); // S6
323 for ( int i = 2; i < 39; i++ )
324 {
325 int layer = i + 4;
326 item[layer] = atof( row[i] ); // S7~43
327 }
328 return StatusCode::SUCCESS;
329
330 // from
331 // ia[:,2:39].astype(float)#S7-43
332}
333
335 MsgStream log( msgSvc(), name() );
336 // log << MSG::DEBUG << "MdcHvDropSvc::sqlRow2Item()" << endmsg;
337 SmartDataPtr<Event::EventHeader> eventHeader( m_eventSvc, "/Event/EventHeader" );
338 Time_t time = eventHeader->time();
339 Time_t fetchBeginTime = time;
340 int run = eventHeader->runNumber();
341 unsigned long time_etsT1 = eventHeader->etsT1();
342 long time_etsT1_timelike32 = ( ( time_etsT1 / 2000000 ) & 0x00000000ffffffffLU );
343
344 // handle etsT1 logic
345 // declareProperty("UseEtsT1",m_useEtsT1=0); // whether to use EtsT1, if not, use time().
346 // declareProperty("EtsT1OffSet",m_etsT1Offset=0);// if is 0, and UseEtsT1, will be treated
347 // as using database time from database.. else, acts as calculating
348 // time_override=etsT1+etsT1Offset;
349
350 if ( m_useEtsT1 )
351 {
352
353 if ( m_etsT1Offset == 0 ) { time = time_etsT1_timelike32 + getRunBeginTime( run ); }
354 else { time = time_etsT1_timelike32 + m_etsT1Offset; }
355 }
356
357 if ( run < 0 ) return 0; // a MC event.
358
359 log << MSG::INFO << "query time " << time << endmsg;
360 log << MSG::INFO << "current boundary " << m_vData.getLowerBoundaryEventTime() << " : "
361 << m_vData.getUpperBoundaryEventTime() << endmsg;
362
363 if ( m_vData.getUpperBoundaryEventTime() < time ||
364 time < m_vData.getLowerBoundaryEventTime() )
365 { // not in cache
366 // 1st time.
367 if ( m_vData.size() == 0 )
368 {
369 char time1str[100];
370 Time_t2str( time, time1str, 100 );
371 log << MSG::INFO << "INFO: MdcHvDropSvc time " << time << " aka " << time1str
372 << " is not in cache yet.\n"
373 << "\tfetching HV info for 1h ago" << time - 3600 << " til fetch Length"
374 << time + m_fetchLength - 3600 << endmsg;
375 fetchBeginTime = time - 3600;
376 }
377 // 2nd time
378 else
379 {
380 Time_t upTimeCachedDBTime =
381 m_vData.getUpperBoundaryEventTime() + m_vData.getOffsetEvt2Db();
382 char time1str[100];
383 Time_t2str( time, time1str, 100 );
384 // time in another fetch interval, thus we choose to fetch new data and append to cache
385 if ( m_vData.getLowerBoundaryEventTime() < time &&
386 time < m_vData.getUpperBoundaryEventTime() + m_fetchLength )
387 {
388
389 log << MSG::INFO << "INFO:MdcHvDropSvc time " << time << " aka " << time1str
390 << " is not in cache yet.\n"
391 << "\tcurrent upperBoundary is " << m_vData.getUpperBoundaryEventTime() << "\n"
392 << "\tfetching HV info for dbTime " << upTimeCachedDBTime
393 << " to fetch Length later" << upTimeCachedDBTime + m_fetchLength << endmsg;
394 fetchBeginTime = upTimeCachedDBTime;
395 }
396 // time not in another fetch interval, and we cannot find a interval to append to cache.
397 else
398 {
399 log << MSG::INFO << "INFO:MdcHvDropSvc time " << time << " aka " << time1str
400 << " is not in cache or canbe fetched in a interval.\n"
401 << "\tcurrent cache boundary is " << m_vData.getLowerBoundaryEventTime() << ":"
402 << m_vData.getUpperBoundaryEventTime() << ".\n"
403 << "\tcurrent fetch interval is " << m_vData.getUpperBoundaryEventTime() << ":"
404 << m_vData.getUpperBoundaryEventTime() + m_fetchLength << endmsg;
405 log << MSG::INFO << "aborted cache and fetching new data.\n"
406 << "\tfetching HV info for 1h ago" << time - 3600 << " til fetch Length"
407 << time + m_fetchLength - 3600 << endmsg;
408 m_vData.clear();
409 fetchBeginTime = time - 3600;
410 }
411 }
412
413 fetchBeginTime += m_vData.getOffsetEvt2Db(); // now db time
414 Time_t time2 = fetchBeginTime + m_fetchLength;
415 if ( !FetchHvInfo( fetchBeginTime - 600, time2 ).isSuccess() )
416 {
417 cout << "ERROR: MdcHvDropSvc failed to fetch HV info\n";
418 return -10000;
419 }
420 }
421 if ( !m_vData.isValid( time ) ) return -9999;
422 if ( m_ignoreLayer_21_24 ) return m_vData.getAvgDropButVeryDrop( time );
423 else return m_vData.getAvgDrop( time );
424}
425
426Time_t MdcHvDropSvc::getRunBeginTime( int runid ) {
427
428 if ( m_run_begin.find( runid ) != m_run_begin.end() ) { return m_run_begin[runid]; }
429 // connect to offline database
430 MYSQL mysql;
431 MYSQL_ROW row;
432 MYSQL_RES* result;
433 mysql_init( &mysql );
434 const Time_t ret_err = 0;
435
436 if ( !mysql_real_connect( &mysql, m_host2.c_str(), m_userName2.c_str(), m_password2.c_str(),
437 m_dbName2.c_str(), m_port2, NULL, 0 ) )
438 {
439 std::cerr << "Connect to database" << m_host << ":" << m_port << " failed\n"
440 << "due to " << mysql_error( &mysql ) << std::endl;
441 return m_run_begin[runid] = ret_err;
442 }
443 char querystring[300];
444 // query is SELECT run_number, startTime, endTime FROM RunParams WHERE
445 // run_number >= %s AND run_number <= %s
446 sprintf( querystring,
447 "SELECT run_number, startTime, endTime FROM RunParams WHERE run_number = %d",
448 runid );
449 if ( mysql_query( &mysql, querystring ) )
450 {
451 std::cerr << "Error! mysql_query failed" << std::endl;
452 return m_run_begin[runid] = ret_err;
453 }
454 else
455 {
456 result = mysql_store_result( &mysql );
457 if ( mysql_num_rows( result ) < 1 )
458 {
459 std::cerr << "Error! mysql_query returns " << mysql_num_rows( result ) << " rows"
460 << std::endl;
461 return m_run_begin[runid] = ret_err;
462 }
463 row = mysql_fetch_row( result );
464 Time_t time = datetimeStr2Time_t( row[1] );
465 mysql_free_result( result );
466 mysql_close( &mysql );
467 std::cout << "got run begin time for run " << runid << " is " << time << std::endl;
468 return m_run_begin[runid] = time;
469 }
470}
DECLARE_COMPONENT(BesBdkRc)
sprintf(cut, "kal_costheta0_em>-0.93&&kal_costheta0_em<0.93&&kal_pxy0_em>=0.05+%d*0.1&&kal_" "pxy0_em<0.15+%d*0.1&&NGch>=2", j, j)
Double_t time
#define min(a, b)
header for main part.
IMessageSvc * msgSvc()
long Time_t
Definition VData.h:28
void handle(const Incident &)
virtual StatusCode initialize()
virtual double queryRelativeHvDrop()
virtual StatusCode finalize()
MdcHvDropSvc(const std::string &name, ISvcLocator *svcloc)