Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

818 lines
19 KiB

  1. //
  2. // MODULE: COUNTER.CPP
  3. //
  4. // PURPOSE: implementation the counter classes:
  5. // CPeriodicTotals (utility class)
  6. // CAbstractCounter (abstract base class).
  7. // CCounter (simple counter)
  8. // CHourlyCounter (counter with "bins" for each hour of the day)
  9. // CDailyCounter (counter with "bins" for day of the week)
  10. // CHourlyDailyCounter (counter with "bins" for each hour of the day and each day of the week)
  11. //
  12. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  13. //
  14. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  15. //
  16. // AUTHOR: Joe Mabel
  17. //
  18. // ORIGINAL DATE: 7-20-1998
  19. //
  20. // NOTES:
  21. // 1. Right as daylight savings time clicks in, there will be a few anomalies.
  22. // Since this defines "days" to be 24-hour periods, rather than calendar days,
  23. // if you have just gone from standard time to daylight time, "previous days"
  24. // before the switch will begin at 11pm the night before the relevant day;
  25. // if you have just gone from daylight time to standard time, "previous days"
  26. // before the switch will begin at 1am on the relevant day.
  27. //
  28. // Version Date By Comments
  29. //--------------------------------------------------------------------
  30. // V3.0 7-20-98 JM Original
  31. //
  32. //////////////////////////////////////////////////////////////////////
  33. #include "stdafx.h"
  34. #include "event.h"
  35. #include "SafeTime.h"
  36. #include "Counter.h"
  37. #include "CounterMgr.h"
  38. #include "baseexception.h"
  39. #include <new>
  40. #include "CharConv.h"
  41. #include "apiwraps.h"
  42. const long k_secsPerHour = 3600;
  43. const long k_secsPerDay = k_secsPerHour * 24;
  44. const long k_secsPerWeek = k_secsPerDay * 7;
  45. //////////////////////////////////////////////////////////////////////
  46. // CPeriodicTotals
  47. // Utility class, returned to provide an effective table of hourly/daily
  48. // counts.
  49. //////////////////////////////////////////////////////////////////////
  50. CPeriodicTotals::CPeriodicTotals(long nPeriods) :
  51. m_nPeriods(nPeriods),
  52. m_ptime(NULL),
  53. m_pCount(NULL)
  54. {
  55. Reset();
  56. }
  57. CPeriodicTotals::~CPeriodicTotals()
  58. {
  59. ReleaseMem();
  60. }
  61. void CPeriodicTotals::Reset()
  62. {
  63. ReleaseMem();
  64. m_nPeriodsSet = 0;
  65. m_iPeriod = 0;
  66. m_ptime = NULL;
  67. m_pCount = NULL;
  68. try
  69. {
  70. m_ptime = new time_t[m_nPeriods];
  71. m_pCount = new long[m_nPeriods];
  72. }
  73. catch (bad_alloc&)
  74. {
  75. // Set the number of periods to zero, release any allocated memory, and rethrow the exception.
  76. m_nPeriods= 0;
  77. ReleaseMem();
  78. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  79. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  80. SrcLoc.GetSrcFileLineStr(),
  81. _T(""), _T(""), EV_GTS_CANT_ALLOC );
  82. throw;
  83. }
  84. }
  85. void CPeriodicTotals::ReleaseMem()
  86. {
  87. delete [] m_ptime;
  88. delete [] m_pCount;
  89. }
  90. // Set the time & Count values at the current position and increment the position
  91. bool CPeriodicTotals::SetNext(time_t time, long Count)
  92. {
  93. if (m_iPeriod >= m_nPeriods)
  94. return false;
  95. m_ptime[m_iPeriod] = time;
  96. m_pCount[m_iPeriod++] = Count;
  97. m_nPeriodsSet++;
  98. return true;
  99. }
  100. // Format a time and count suitably for HTML or other text use.
  101. // returns a reference of convenience to the same string passed in.
  102. CString & CPeriodicTotals::DisplayPeriod(long i, CString & str) const
  103. {
  104. CString strTime;
  105. {
  106. CSafeTime safe(m_ptime[i]);
  107. str = safe.StrLocalTime();
  108. }
  109. strTime.Format(_T(" %8.8d"), m_pCount[i]);
  110. str += strTime;
  111. return str;
  112. }
  113. //////////////////////////////////////////////////////////////////////
  114. // CHourlyTotals
  115. //////////////////////////////////////////////////////////////////////
  116. CHourlyTotals::CHourlyTotals() :
  117. CPeriodicTotals (24+1)
  118. {
  119. }
  120. CHourlyTotals::~CHourlyTotals()
  121. {
  122. }
  123. // This is strictly for display to operator, so hard-coding English is OK
  124. // returns a reference of convenience to the same string passed in.
  125. CString CHourlyTotals::HTMLDisplay() const
  126. {
  127. CString str, strTemp;
  128. if (m_nPeriodsSet > 1)
  129. {
  130. str += _T("<TR>\n");
  131. str += _T("<TD ROWSPAN=\"24\" ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\">\n");
  132. str += _T("<B>Last 24 hours: </B>");
  133. str += _T("</TD>\n");
  134. for (int i=0; i<24 && i<m_nPeriodsSet-1 ; i++)
  135. {
  136. if (i!=0)
  137. str += _T("<TR>\n");
  138. str+= _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
  139. CPeriodicTotals::DisplayPeriod(i, strTemp);
  140. str += strTemp;
  141. str += _T("</TD>\n");
  142. str += _T("</TR>\n");
  143. }
  144. }
  145. if (m_nPeriodsSet >= 1)
  146. {
  147. str += _T("<TR>\n");
  148. str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\"> \n");
  149. str += _T("<B>Current hour:</B> ");
  150. str += _T("</TD>\n");
  151. str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
  152. CPeriodicTotals::DisplayPeriod(m_nPeriodsSet-1, strTemp);
  153. str += strTemp;
  154. str += _T("</TD>\n");
  155. str += _T("</TR>\n");
  156. }
  157. else
  158. str = _T("<BR>No hourly data.");
  159. return str;
  160. }
  161. //////////////////////////////////////////////////////////////////////
  162. // CDailyTotals
  163. //////////////////////////////////////////////////////////////////////
  164. CDailyTotals::CDailyTotals() :
  165. CPeriodicTotals (7+1)
  166. {
  167. }
  168. CDailyTotals::~CDailyTotals()
  169. {
  170. }
  171. // This is strictly for display to operator, so hard-coding English is OK
  172. // returns a reference of convenience to the same string passed in.
  173. CString CDailyTotals::HTMLDisplay() const
  174. {
  175. CString str, strTemp;
  176. if (m_nPeriodsSet > 1)
  177. {
  178. str = _T("<TR>\n");
  179. str+= _T("<TD ROWSPAN=\"7\" ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\">\n");
  180. str += _T("<B>Last 7 days: </B>");
  181. str += _T("</TD>\n");
  182. for (int i=0; i<7 && i<m_nPeriodsSet-1 ; i++)
  183. {
  184. if (i!=0)
  185. str += _T("<TR>\n");
  186. str+= _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
  187. CPeriodicTotals::DisplayPeriod(i, strTemp);
  188. str += strTemp;
  189. str += _T("</TD>\n");
  190. str += _T("</TR>\n");
  191. }
  192. }
  193. if (m_nPeriodsSet >= 1)
  194. {
  195. str += _T("<TR>\n");
  196. str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\"> \n");
  197. str += _T("<B>Today: </B>");
  198. str += _T("</TD>\n");
  199. str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
  200. CPeriodicTotals::DisplayPeriod(m_nPeriodsSet-1, strTemp);
  201. str += strTemp;
  202. str += _T("</TD>\n");
  203. str += _T("</TR>\n");
  204. }
  205. else
  206. str = _T("<BR>No daily data.");
  207. return str;
  208. }
  209. //////////////////////////////////////////////////////////////////////
  210. // CCounterLocation
  211. //////////////////////////////////////////////////////////////////////
  212. /*static*/ LPCTSTR CCounterLocation::m_GlobalStr = _T("Global");
  213. /*static*/ LPCTSTR CCounterLocation::m_TopicStr = _T("Topic ");
  214. /*static*/ LPCTSTR CCounterLocation::m_ThreadStr = _T("Thread ");
  215. CCounterLocation::CCounterLocation(EId id, LPCTSTR scope /*=m_GlobalStr*/)
  216. : m_Scope(scope),
  217. m_Id(id)
  218. {
  219. }
  220. CCounterLocation::~CCounterLocation()
  221. {
  222. }
  223. //////////////////////////////////////////////////////////////////////
  224. // CAbstractCounter
  225. //////////////////////////////////////////////////////////////////////
  226. CAbstractCounter::CAbstractCounter(EId id /*=eIdGeneric*/, CString scope /*=m_GlobalStr*/)
  227. : CCounterLocation(id, scope)
  228. {
  229. ::Get_g_CounterMgr()->AddSubstitute(*this);
  230. }
  231. CAbstractCounter::~CAbstractCounter()
  232. {
  233. ::Get_g_CounterMgr()->Remove(*this);
  234. }
  235. //////////////////////////////////////////////////////////////////////
  236. // CCounter
  237. // a simple counter
  238. //////////////////////////////////////////////////////////////////////
  239. CCounter::CCounter(EId id /*=eIdGeneric*/, CString scope /*=m_GlobalStr*/)
  240. : CAbstractCounter(id, scope)
  241. {
  242. Clear();
  243. }
  244. CCounter::~CCounter()
  245. {
  246. }
  247. void CCounter::Increment()
  248. {
  249. ::InterlockedIncrement( &m_Count );
  250. }
  251. void CCounter::Clear()
  252. {
  253. ::InterlockedExchange( &m_Count, 0);
  254. }
  255. void CCounter::Init(long count)
  256. {
  257. ::InterlockedExchange( &m_Count, count);
  258. }
  259. long CCounter::Get() const
  260. {
  261. return m_Count;
  262. }
  263. //////////////////////////////////////////////////////////////////////
  264. // CHourlyCounter
  265. // This counter maintains bins to keep track of values on a per-hour basis.
  266. // The code that sets the values can treat this as a CAbstractCounter.
  267. // Additional public functions are available to report results.
  268. //////////////////////////////////////////////////////////////////////
  269. CHourlyCounter::CHourlyCounter() :
  270. m_ThisHour (-1),
  271. m_ThisTime (0)
  272. {
  273. m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
  274. if (!m_hMutex)
  275. {
  276. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  277. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  278. SrcLoc.GetSrcFileLineStr(),
  279. _T("Hourly"),
  280. _T(""),
  281. EV_GTS_ERROR_MUTEX );
  282. }
  283. Clear();
  284. }
  285. CHourlyCounter::~CHourlyCounter()
  286. {
  287. ::CloseHandle(m_hMutex);
  288. }
  289. void CHourlyCounter::Increment()
  290. {
  291. WAIT_INFINITE( m_hMutex );
  292. SetHour();
  293. m_arrCount[m_ThisHour].Increment();
  294. ::ReleaseMutex(m_hMutex);
  295. }
  296. void CHourlyCounter::Clear()
  297. {
  298. WAIT_INFINITE( m_hMutex );
  299. for (long i = 0; i < 24; i++)
  300. m_arrCount[i].Clear();
  301. m_nThisHourYesterday = 0;
  302. ::ReleaseMutex(m_hMutex);
  303. }
  304. void CHourlyCounter::Init(long count)
  305. {
  306. CHourlyCounter::Clear();
  307. WAIT_INFINITE( m_hMutex );
  308. SetHour();
  309. m_arrCount[m_ThisHour].Init(count);
  310. ::ReleaseMutex(m_hMutex);
  311. }
  312. // return a 24-hour total prior to the present hour.
  313. // non-const because it calls SetHour()
  314. long CHourlyCounter::GetDayCount()
  315. {
  316. long DayCount = 0;
  317. WAIT_INFINITE( m_hMutex );
  318. SetHour();
  319. for (long i=0; i<24; i++)
  320. {
  321. if ( i != m_ThisHour )
  322. DayCount += m_arrCount[i].Get();
  323. DayCount += m_nThisHourYesterday;
  324. }
  325. ::ReleaseMutex(m_hMutex);
  326. return DayCount;
  327. }
  328. // non-const because it calls SetHour()
  329. void CHourlyCounter::GetHourlies(CHourlyTotals & totals)
  330. {
  331. WAIT_INFINITE( m_hMutex );
  332. totals.Reset();
  333. SetHour();
  334. time_t time = m_ThisTime - (k_secsPerDay);
  335. totals.SetNext(time, m_nThisHourYesterday);
  336. long i;
  337. for (i=m_ThisHour+1; i<24; i++)
  338. {
  339. time += k_secsPerHour;
  340. totals.SetNext(time, m_arrCount[i].Get());
  341. }
  342. for (i=0; i<=m_ThisHour; i++)
  343. {
  344. time += k_secsPerHour;
  345. totals.SetNext(time, m_arrCount[i].Get());
  346. }
  347. ::ReleaseMutex(m_hMutex);
  348. }
  349. // Based on the present time, shifts to the appropriate bin.
  350. void CHourlyCounter::SetHour()
  351. {
  352. time_t timeNow;
  353. time_t timeStartOfHour;
  354. WAIT_INFINITE( m_hMutex );
  355. time(&timeNow);
  356. timeStartOfHour = (timeNow / k_secsPerHour) * k_secsPerHour;
  357. if (timeStartOfHour > m_ThisTime)
  358. {
  359. // If we get here, hour changed. Typically the last action was the previous
  360. // hour, but the algorithm here does not require that.
  361. long Hour;
  362. {
  363. // minimize how long we use CSafeTime, because it means holding a mutex.
  364. CSafeTime safe(timeStartOfHour);
  365. Hour = safe.LocalTime().tm_hour;
  366. }
  367. if (timeStartOfHour - m_ThisTime > k_secsPerDay)
  368. Clear();
  369. else
  370. {
  371. m_nThisHourYesterday = m_arrCount[Hour].Get();
  372. if (m_ThisHour > Hour)
  373. {
  374. long i;
  375. for (i=m_ThisHour+1; i<24; i++)
  376. {
  377. m_arrCount[i].Clear();
  378. }
  379. for (i=0; i<=Hour; i++)
  380. {
  381. m_arrCount[i].Clear();
  382. }
  383. }
  384. else
  385. {
  386. for (long i=m_ThisHour+1; i<=Hour; i++)
  387. {
  388. m_arrCount[i].Clear();
  389. }
  390. }
  391. }
  392. m_ThisHour = Hour;
  393. m_ThisTime = timeStartOfHour;
  394. }
  395. ::ReleaseMutex(m_hMutex);
  396. return;
  397. }
  398. //////////////////////////////////////////////////////////////////////
  399. // CDailyCounter
  400. // This counter maintains bins to keep track of values on a per-day basis.
  401. // The code that sets the values can treat this as a CAbstractCounter.
  402. // Additional public functions are available to report results.
  403. // This could share more code with CHourlyCounter, but it would be very hard to come up
  404. // with appropriate variable and function names, so we are suffering dual maintenance.
  405. //////////////////////////////////////////////////////////////////////
  406. CDailyCounter::CDailyCounter() :
  407. m_ThisDay (-1),
  408. m_ThisTime (0)
  409. {
  410. m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
  411. if (!m_hMutex)
  412. {
  413. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  414. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  415. SrcLoc.GetSrcFileLineStr(),
  416. _T("Daily"),
  417. _T(""),
  418. EV_GTS_ERROR_MUTEX );
  419. }
  420. Clear();
  421. }
  422. CDailyCounter::~CDailyCounter()
  423. {
  424. ::CloseHandle(m_hMutex);
  425. }
  426. void CDailyCounter::Increment()
  427. {
  428. WAIT_INFINITE( m_hMutex );
  429. SetDay();
  430. m_arrCount[m_ThisDay].Increment();
  431. ::ReleaseMutex(m_hMutex);
  432. }
  433. void CDailyCounter::Clear()
  434. {
  435. WAIT_INFINITE( m_hMutex );
  436. for (long i = 0; i < 7; i++)
  437. m_arrCount[i].Clear();
  438. m_nThisDayLastWeek = 0;
  439. ::ReleaseMutex(m_hMutex);
  440. }
  441. void CDailyCounter::Init(long count)
  442. {
  443. CDailyCounter::Clear();
  444. WAIT_INFINITE( m_hMutex );
  445. SetDay();
  446. m_arrCount[m_ThisDay].Init(count);
  447. ::ReleaseMutex(m_hMutex);
  448. }
  449. // return a 7-day total prior to the present day.
  450. // non-const because it calls SetDay()
  451. long CDailyCounter::GetWeekCount()
  452. {
  453. long WeekCount = 0;
  454. WAIT_INFINITE( m_hMutex );
  455. SetDay();
  456. for (long i=0; i<7; i++)
  457. {
  458. if ( i != m_ThisDay )
  459. WeekCount += m_arrCount[i].Get();
  460. WeekCount += m_nThisDayLastWeek;
  461. }
  462. ::ReleaseMutex(m_hMutex);
  463. return WeekCount;
  464. }
  465. // non-const because it calls SetDay()
  466. void CDailyCounter::GetDailies(CDailyTotals & totals)
  467. {
  468. WAIT_INFINITE( m_hMutex );
  469. totals.Reset();
  470. SetDay();
  471. time_t time = m_ThisTime - (k_secsPerWeek);
  472. totals.SetNext(time, m_nThisDayLastWeek);
  473. long i;
  474. for (i=m_ThisDay+1; i<7; i++)
  475. {
  476. time += k_secsPerDay;
  477. totals.SetNext(time, m_arrCount[i].Get());
  478. }
  479. for (i=0; i<=m_ThisDay; i++)
  480. {
  481. time += k_secsPerDay;
  482. totals.SetNext(time, m_arrCount[i].Get());
  483. }
  484. ::ReleaseMutex(m_hMutex);
  485. }
  486. // Based on the present time, shifts to the appropriate bin.
  487. void CDailyCounter::SetDay()
  488. {
  489. time_t timeNow;
  490. time_t timeStartOfDay;
  491. WAIT_INFINITE( m_hMutex );
  492. time(&timeNow);
  493. // Want to get start of day local time.
  494. // Can't just set timeStartOfDay = (timeNow / k_secsPerDay) * k_secsPerDay
  495. // because that would be the start of the day based on GMT!
  496. long DayOfWeek;
  497. {
  498. // minimize how long we use CSafeTime, because it means holding a mutex.
  499. CSafeTime safe(timeNow);
  500. struct tm tmStartOfDay = safe.LocalTime();
  501. DayOfWeek = tmStartOfDay.tm_wday;
  502. tmStartOfDay.tm_sec = 0;
  503. tmStartOfDay.tm_min = 0;
  504. tmStartOfDay.tm_hour = 0;
  505. timeStartOfDay = mktime(&tmStartOfDay);
  506. }
  507. if (timeStartOfDay > m_ThisTime)
  508. {
  509. // If we get here, day changed. Typically the last action was the previous
  510. // hour, but the algorithm here does not require that.
  511. {
  512. // minimize how long we use CSafeTime, because it means holding a mutex.
  513. CSafeTime safe(timeStartOfDay);
  514. DayOfWeek = safe.LocalTime().tm_wday;
  515. }
  516. if (timeStartOfDay - m_ThisTime > k_secsPerWeek)
  517. Clear();
  518. else
  519. {
  520. m_nThisDayLastWeek = m_arrCount[DayOfWeek].Get();
  521. if (m_ThisDay > DayOfWeek)
  522. {
  523. long i;
  524. for (i=m_ThisDay+1; i<7; i++)
  525. {
  526. m_arrCount[i].Clear();
  527. }
  528. for (i=0; i<=DayOfWeek; i++)
  529. {
  530. m_arrCount[i].Clear();
  531. }
  532. }
  533. else
  534. {
  535. for (long i=m_ThisDay+1; i<=DayOfWeek; i++)
  536. {
  537. m_arrCount[i].Clear();
  538. }
  539. }
  540. }
  541. m_ThisDay = DayOfWeek;
  542. m_ThisTime = timeStartOfDay;
  543. }
  544. ::ReleaseMutex(m_hMutex);
  545. return;
  546. }
  547. //////////////////////////////////////////////////////////////////////
  548. // CHourlyDailyCounter
  549. //////////////////////////////////////////////////////////////////////
  550. CHourlyDailyCounter::CHourlyDailyCounter(EId id /*=eIdGeneric*/, CString scope /*=m_GlobalStr*/)
  551. : CAbstractCounter(id, scope),
  552. m_Total(0),
  553. m_timeFirst(0),
  554. m_timeLast(0),
  555. m_timeCleared(0)
  556. {
  557. m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
  558. if (!m_hMutex)
  559. {
  560. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  561. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  562. SrcLoc.GetSrcFileLineStr(),
  563. _T("HourlyDaily"),
  564. _T(""),
  565. EV_GTS_ERROR_MUTEX );
  566. }
  567. time(&m_timeCreated);
  568. time(&m_timeCleared);
  569. }
  570. CHourlyDailyCounter::~CHourlyDailyCounter()
  571. {
  572. ::CloseHandle(m_hMutex);
  573. }
  574. void CHourlyDailyCounter::Increment()
  575. {
  576. WAIT_INFINITE( m_hMutex );
  577. m_hourly.Increment();
  578. m_daily.Increment();
  579. m_Total++;
  580. time(&m_timeLast);
  581. if (!m_timeFirst)
  582. m_timeFirst = m_timeLast;
  583. ::ReleaseMutex(m_hMutex);
  584. }
  585. void CHourlyDailyCounter::Clear()
  586. {
  587. WAIT_INFINITE( m_hMutex );
  588. m_hourly.Clear();
  589. m_daily.Clear();
  590. m_Total= 0;
  591. m_timeFirst = 0;
  592. m_timeLast = 0;
  593. time(&m_timeCleared);
  594. ::ReleaseMutex(m_hMutex);
  595. }
  596. void CHourlyDailyCounter::Init(long count)
  597. {
  598. CHourlyDailyCounter::Clear();
  599. WAIT_INFINITE( m_hMutex );
  600. m_hourly.Init(count);
  601. m_daily.Init(count);
  602. m_Total = count;
  603. time(&m_timeLast);
  604. if (!m_timeFirst)
  605. m_timeFirst = m_timeLast;
  606. ::ReleaseMutex(m_hMutex);
  607. }
  608. // no need to lock here, because m_hourly does its own locking.
  609. long CHourlyDailyCounter::GetDayCount()
  610. {
  611. return m_hourly.GetDayCount();
  612. }
  613. // no need to lock here, because m_hourly does its own locking.
  614. void CHourlyDailyCounter::GetHourlies(CHourlyTotals & totals)
  615. {
  616. m_hourly.GetHourlies(totals);
  617. }
  618. // no need to lock here, because m_daily does its own locking.
  619. long CHourlyDailyCounter::GetWeekCount()
  620. {
  621. return m_daily.GetWeekCount();
  622. }
  623. // no need to lock here, because m_daily does its own locking.
  624. void CHourlyDailyCounter::GetDailies(CDailyTotals & totals)
  625. {
  626. m_daily.GetDailies(totals);
  627. }
  628. long CHourlyDailyCounter::GetTotal() const
  629. {
  630. WAIT_INFINITE( m_hMutex );
  631. long ret = m_Total;
  632. ::ReleaseMutex(m_hMutex);
  633. return ret;
  634. };
  635. time_t CHourlyDailyCounter::GetTimeFirst() const
  636. {
  637. WAIT_INFINITE( m_hMutex );
  638. time_t ret = m_timeFirst;
  639. ::ReleaseMutex(m_hMutex);
  640. return ret;
  641. };
  642. time_t CHourlyDailyCounter::GetTimeLast() const
  643. {
  644. WAIT_INFINITE( m_hMutex );
  645. time_t ret = m_timeLast;
  646. ::ReleaseMutex(m_hMutex);
  647. return ret;
  648. };
  649. time_t CHourlyDailyCounter::GetTimeCleared() const
  650. {
  651. WAIT_INFINITE( m_hMutex );
  652. time_t ret = m_timeCleared;
  653. ::ReleaseMutex(m_hMutex);
  654. return ret;
  655. };
  656. time_t CHourlyDailyCounter::GetTimeCreated() const
  657. {
  658. WAIT_INFINITE( m_hMutex );
  659. time_t ret = m_timeCreated;
  660. ::ReleaseMutex(m_hMutex);
  661. return ret;
  662. }
  663. time_t CHourlyDailyCounter::GetTimeNow() const
  664. {
  665. // No need to lock mutex on this call.
  666. time_t ret;
  667. time(&ret);
  668. return ret;
  669. }
  670. ////////////////////////////////////////////////////////////////////////////////////
  671. // CDisplayCounter...::Display() implementation
  672. ////////////////////////////////////////////////////////////////////////////////////
  673. #define STATUS_INVALID_NUMBER_STR _T("none")
  674. #define STATUS_INVALID_TIME_STR _T("none")
  675. CString CDisplayCounterTotal::Display()
  676. {
  677. TCHAR buf[128] = {0};
  678. _stprintf(buf, _T("%ld"), long(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTotal()));
  679. return buf;
  680. }
  681. CString CDisplayCounterCurrentDateTime::Display()
  682. {
  683. return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeNow()).StrLocalTime(STATUS_INVALID_TIME_STR);
  684. }
  685. CString CDisplayCounterCreateDateTime::Display()
  686. {
  687. return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeCreated()).StrLocalTime(STATUS_INVALID_TIME_STR);
  688. }
  689. CString CDisplayCounterFirstDateTime::Display()
  690. {
  691. return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeFirst()).StrLocalTime(STATUS_INVALID_TIME_STR);
  692. }
  693. CString CDisplayCounterLastDateTime::Display()
  694. {
  695. return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeLast()).StrLocalTime(STATUS_INVALID_TIME_STR);
  696. }
  697. CString CDisplayCounterDailyHourly::Display()
  698. {
  699. CString ret;
  700. if (m_pDailyTotals) {
  701. ((CHourlyDailyCounter*)m_pAbstractCounter)->GetDailies(*m_pDailyTotals);
  702. ret += m_pDailyTotals->HTMLDisplay();
  703. }
  704. if (m_pHourlyTotals) {
  705. ((CHourlyDailyCounter*)m_pAbstractCounter)->GetHourlies(*m_pHourlyTotals);
  706. ret += m_pHourlyTotals->HTMLDisplay();
  707. }
  708. return ret;
  709. }