819 lines
19 KiB
C++
819 lines
19 KiB
C++
//
|
|
// MODULE: COUNTER.CPP
|
|
//
|
|
// PURPOSE: implementation the counter classes:
|
|
// CPeriodicTotals (utility class)
|
|
// CAbstractCounter (abstract base class).
|
|
// CCounter (simple counter)
|
|
// CHourlyCounter (counter with "bins" for each hour of the day)
|
|
// CDailyCounter (counter with "bins" for day of the week)
|
|
// CHourlyDailyCounter (counter with "bins" for each hour of the day and each day of the week)
|
|
//
|
|
// PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
|
|
//
|
|
// COMPANY: Saltmine Creative, Inc. (206)-284-7511 support@saltmine.com
|
|
//
|
|
// AUTHOR: Joe Mabel
|
|
//
|
|
// ORIGINAL DATE: 7-20-1998
|
|
//
|
|
// NOTES:
|
|
// 1. Right as daylight savings time clicks in, there will be a few anomalies.
|
|
// Since this defines "days" to be 24-hour periods, rather than calendar days,
|
|
// if you have just gone from standard time to daylight time, "previous days"
|
|
// before the switch will begin at 11pm the night before the relevant day;
|
|
// if you have just gone from daylight time to standard time, "previous days"
|
|
// before the switch will begin at 1am on the relevant day.
|
|
//
|
|
// Version Date By Comments
|
|
//--------------------------------------------------------------------
|
|
// V3.0 7-20-98 JM Original
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "event.h"
|
|
#include "SafeTime.h"
|
|
#include "Counter.h"
|
|
#include "CounterMgr.h"
|
|
#include "baseexception.h"
|
|
#include <new>
|
|
#include "CharConv.h"
|
|
#include "apiwraps.h"
|
|
|
|
const long k_secsPerHour = 3600;
|
|
const long k_secsPerDay = k_secsPerHour * 24;
|
|
const long k_secsPerWeek = k_secsPerDay * 7;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CPeriodicTotals
|
|
// Utility class, returned to provide an effective table of hourly/daily
|
|
// counts.
|
|
//////////////////////////////////////////////////////////////////////
|
|
CPeriodicTotals::CPeriodicTotals(long nPeriods) :
|
|
m_nPeriods(nPeriods),
|
|
m_ptime(NULL),
|
|
m_pCount(NULL)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
CPeriodicTotals::~CPeriodicTotals()
|
|
{
|
|
ReleaseMem();
|
|
}
|
|
|
|
void CPeriodicTotals::Reset()
|
|
{
|
|
ReleaseMem();
|
|
|
|
m_nPeriodsSet = 0;
|
|
m_iPeriod = 0;
|
|
m_ptime = NULL;
|
|
m_pCount = NULL;
|
|
|
|
try
|
|
{
|
|
m_ptime = new time_t[m_nPeriods];
|
|
|
|
m_pCount = new long[m_nPeriods];
|
|
}
|
|
catch (bad_alloc&)
|
|
{
|
|
// Set the number of periods to zero, release any allocated memory, and rethrow the exception.
|
|
m_nPeriods= 0;
|
|
ReleaseMem();
|
|
CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
|
|
CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
|
|
SrcLoc.GetSrcFileLineStr(),
|
|
_T(""), _T(""), EV_GTS_CANT_ALLOC );
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void CPeriodicTotals::ReleaseMem()
|
|
{
|
|
delete [] m_ptime;
|
|
delete [] m_pCount;
|
|
}
|
|
|
|
|
|
// Set the time & Count values at the current position and increment the position
|
|
bool CPeriodicTotals::SetNext(time_t time, long Count)
|
|
{
|
|
if (m_iPeriod >= m_nPeriods)
|
|
return false;
|
|
|
|
m_ptime[m_iPeriod] = time;
|
|
m_pCount[m_iPeriod++] = Count;
|
|
m_nPeriodsSet++;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Format a time and count suitably for HTML or other text use.
|
|
// returns a reference of convenience to the same string passed in.
|
|
CString & CPeriodicTotals::DisplayPeriod(long i, CString & str) const
|
|
{
|
|
CString strTime;
|
|
{
|
|
CSafeTime safe(m_ptime[i]);
|
|
str = safe.StrLocalTime();
|
|
}
|
|
strTime.Format(_T(" %8.8d"), m_pCount[i]);
|
|
str += strTime;
|
|
return str;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CHourlyTotals
|
|
//////////////////////////////////////////////////////////////////////
|
|
CHourlyTotals::CHourlyTotals() :
|
|
CPeriodicTotals (24+1)
|
|
{
|
|
}
|
|
|
|
CHourlyTotals::~CHourlyTotals()
|
|
{
|
|
}
|
|
|
|
// This is strictly for display to operator, so hard-coding English is OK
|
|
// returns a reference of convenience to the same string passed in.
|
|
CString CHourlyTotals::HTMLDisplay() const
|
|
{
|
|
CString str, strTemp;
|
|
|
|
if (m_nPeriodsSet > 1)
|
|
{
|
|
str += _T("<TR>\n");
|
|
str += _T("<TD ROWSPAN=\"24\" ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\">\n");
|
|
str += _T("<B>Last 24 hours: </B>");
|
|
str += _T("</TD>\n");
|
|
for (int i=0; i<24 && i<m_nPeriodsSet-1 ; i++)
|
|
{
|
|
if (i!=0)
|
|
str += _T("<TR>\n");
|
|
str+= _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
|
|
CPeriodicTotals::DisplayPeriod(i, strTemp);
|
|
str += strTemp;
|
|
str += _T("</TD>\n");
|
|
str += _T("</TR>\n");
|
|
}
|
|
}
|
|
|
|
if (m_nPeriodsSet >= 1)
|
|
{
|
|
str += _T("<TR>\n");
|
|
str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\"> \n");
|
|
str += _T("<B>Current hour:</B> ");
|
|
str += _T("</TD>\n");
|
|
str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
|
|
CPeriodicTotals::DisplayPeriod(m_nPeriodsSet-1, strTemp);
|
|
str += strTemp;
|
|
str += _T("</TD>\n");
|
|
str += _T("</TR>\n");
|
|
}
|
|
else
|
|
str = _T("<BR>No hourly data.");
|
|
|
|
return str;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CDailyTotals
|
|
//////////////////////////////////////////////////////////////////////
|
|
CDailyTotals::CDailyTotals() :
|
|
CPeriodicTotals (7+1)
|
|
{
|
|
}
|
|
|
|
CDailyTotals::~CDailyTotals()
|
|
{
|
|
}
|
|
|
|
// This is strictly for display to operator, so hard-coding English is OK
|
|
// returns a reference of convenience to the same string passed in.
|
|
CString CDailyTotals::HTMLDisplay() const
|
|
{
|
|
CString str, strTemp;
|
|
if (m_nPeriodsSet > 1)
|
|
{
|
|
str = _T("<TR>\n");
|
|
str+= _T("<TD ROWSPAN=\"7\" ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\">\n");
|
|
str += _T("<B>Last 7 days: </B>");
|
|
str += _T("</TD>\n");
|
|
for (int i=0; i<7 && i<m_nPeriodsSet-1 ; i++)
|
|
{
|
|
if (i!=0)
|
|
str += _T("<TR>\n");
|
|
str+= _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
|
|
CPeriodicTotals::DisplayPeriod(i, strTemp);
|
|
str += strTemp;
|
|
str += _T("</TD>\n");
|
|
str += _T("</TR>\n");
|
|
}
|
|
}
|
|
|
|
if (m_nPeriodsSet >= 1)
|
|
{
|
|
str += _T("<TR>\n");
|
|
str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\"> \n");
|
|
str += _T("<B>Today: </B>");
|
|
str += _T("</TD>\n");
|
|
str += _T("<TD ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\">\n");
|
|
CPeriodicTotals::DisplayPeriod(m_nPeriodsSet-1, strTemp);
|
|
str += strTemp;
|
|
str += _T("</TD>\n");
|
|
str += _T("</TR>\n");
|
|
}
|
|
else
|
|
str = _T("<BR>No daily data.");
|
|
|
|
return str;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CCounterLocation
|
|
//////////////////////////////////////////////////////////////////////
|
|
/*static*/ LPCTSTR CCounterLocation::m_GlobalStr = _T("Global");
|
|
/*static*/ LPCTSTR CCounterLocation::m_TopicStr = _T("Topic ");
|
|
/*static*/ LPCTSTR CCounterLocation::m_ThreadStr = _T("Thread ");
|
|
|
|
CCounterLocation::CCounterLocation(EId id, LPCTSTR scope /*=m_GlobalStr*/)
|
|
: m_Scope(scope),
|
|
m_Id(id)
|
|
{
|
|
}
|
|
|
|
CCounterLocation::~CCounterLocation()
|
|
{
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CAbstractCounter
|
|
//////////////////////////////////////////////////////////////////////
|
|
CAbstractCounter::CAbstractCounter(EId id /*=eIdGeneric*/, CString scope /*=m_GlobalStr*/)
|
|
: CCounterLocation(id, scope)
|
|
{
|
|
::Get_g_CounterMgr()->AddSubstitute(*this);
|
|
}
|
|
|
|
CAbstractCounter::~CAbstractCounter()
|
|
{
|
|
::Get_g_CounterMgr()->Remove(*this);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CCounter
|
|
// a simple counter
|
|
//////////////////////////////////////////////////////////////////////
|
|
CCounter::CCounter(EId id /*=eIdGeneric*/, CString scope /*=m_GlobalStr*/)
|
|
: CAbstractCounter(id, scope)
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
CCounter::~CCounter()
|
|
{
|
|
}
|
|
|
|
void CCounter::Increment()
|
|
{
|
|
::InterlockedIncrement( &m_Count );
|
|
}
|
|
|
|
void CCounter::Clear()
|
|
{
|
|
::InterlockedExchange( &m_Count, 0);
|
|
}
|
|
|
|
void CCounter::Init(long count)
|
|
{
|
|
::InterlockedExchange( &m_Count, count);
|
|
}
|
|
|
|
long CCounter::Get() const
|
|
{
|
|
return m_Count;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CHourlyCounter
|
|
// This counter maintains bins to keep track of values on a per-hour basis.
|
|
// The code that sets the values can treat this as a CAbstractCounter.
|
|
// Additional public functions are available to report results.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CHourlyCounter::CHourlyCounter() :
|
|
m_ThisHour (-1),
|
|
m_ThisTime (0)
|
|
{
|
|
m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
|
|
if (!m_hMutex)
|
|
{
|
|
CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
|
|
CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
|
|
SrcLoc.GetSrcFileLineStr(),
|
|
_T("Hourly"),
|
|
_T(""),
|
|
EV_GTS_ERROR_MUTEX );
|
|
}
|
|
Clear();
|
|
}
|
|
|
|
CHourlyCounter::~CHourlyCounter()
|
|
{
|
|
::CloseHandle(m_hMutex);
|
|
}
|
|
|
|
void CHourlyCounter::Increment()
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
SetHour();
|
|
m_arrCount[m_ThisHour].Increment();
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
void CHourlyCounter::Clear()
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
for (long i = 0; i < 24; i++)
|
|
m_arrCount[i].Clear();
|
|
m_nThisHourYesterday = 0;
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
void CHourlyCounter::Init(long count)
|
|
{
|
|
CHourlyCounter::Clear();
|
|
WAIT_INFINITE( m_hMutex );
|
|
SetHour();
|
|
m_arrCount[m_ThisHour].Init(count);
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
// return a 24-hour total prior to the present hour.
|
|
// non-const because it calls SetHour()
|
|
long CHourlyCounter::GetDayCount()
|
|
{
|
|
long DayCount = 0;
|
|
WAIT_INFINITE( m_hMutex );
|
|
SetHour();
|
|
for (long i=0; i<24; i++)
|
|
{
|
|
if ( i != m_ThisHour )
|
|
DayCount += m_arrCount[i].Get();
|
|
DayCount += m_nThisHourYesterday;
|
|
}
|
|
::ReleaseMutex(m_hMutex);
|
|
|
|
return DayCount;
|
|
}
|
|
|
|
// non-const because it calls SetHour()
|
|
void CHourlyCounter::GetHourlies(CHourlyTotals & totals)
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
|
|
totals.Reset();
|
|
|
|
SetHour();
|
|
|
|
time_t time = m_ThisTime - (k_secsPerDay);
|
|
|
|
totals.SetNext(time, m_nThisHourYesterday);
|
|
|
|
long i;
|
|
for (i=m_ThisHour+1; i<24; i++)
|
|
{
|
|
time += k_secsPerHour;
|
|
totals.SetNext(time, m_arrCount[i].Get());
|
|
}
|
|
|
|
for (i=0; i<=m_ThisHour; i++)
|
|
{
|
|
time += k_secsPerHour;
|
|
totals.SetNext(time, m_arrCount[i].Get());
|
|
}
|
|
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
// Based on the present time, shifts to the appropriate bin.
|
|
void CHourlyCounter::SetHour()
|
|
{
|
|
time_t timeNow;
|
|
time_t timeStartOfHour;
|
|
|
|
WAIT_INFINITE( m_hMutex );
|
|
|
|
time(&timeNow);
|
|
timeStartOfHour = (timeNow / k_secsPerHour) * k_secsPerHour;
|
|
|
|
if (timeStartOfHour > m_ThisTime)
|
|
{
|
|
// If we get here, hour changed. Typically the last action was the previous
|
|
// hour, but the algorithm here does not require that.
|
|
long Hour;
|
|
{
|
|
// minimize how long we use CSafeTime, because it means holding a mutex.
|
|
CSafeTime safe(timeStartOfHour);
|
|
Hour = safe.LocalTime().tm_hour;
|
|
}
|
|
|
|
if (timeStartOfHour - m_ThisTime > k_secsPerDay)
|
|
Clear();
|
|
else
|
|
{
|
|
m_nThisHourYesterday = m_arrCount[Hour].Get();
|
|
if (m_ThisHour > Hour)
|
|
{
|
|
long i;
|
|
for (i=m_ThisHour+1; i<24; i++)
|
|
{
|
|
m_arrCount[i].Clear();
|
|
}
|
|
for (i=0; i<=Hour; i++)
|
|
{
|
|
m_arrCount[i].Clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long i=m_ThisHour+1; i<=Hour; i++)
|
|
{
|
|
m_arrCount[i].Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_ThisHour = Hour;
|
|
m_ThisTime = timeStartOfHour;
|
|
}
|
|
::ReleaseMutex(m_hMutex);
|
|
return;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CDailyCounter
|
|
// This counter maintains bins to keep track of values on a per-day basis.
|
|
// The code that sets the values can treat this as a CAbstractCounter.
|
|
// Additional public functions are available to report results.
|
|
// This could share more code with CHourlyCounter, but it would be very hard to come up
|
|
// with appropriate variable and function names, so we are suffering dual maintenance.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CDailyCounter::CDailyCounter() :
|
|
m_ThisDay (-1),
|
|
m_ThisTime (0)
|
|
{
|
|
m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
|
|
if (!m_hMutex)
|
|
{
|
|
CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
|
|
CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
|
|
SrcLoc.GetSrcFileLineStr(),
|
|
_T("Daily"),
|
|
_T(""),
|
|
EV_GTS_ERROR_MUTEX );
|
|
}
|
|
Clear();
|
|
}
|
|
|
|
CDailyCounter::~CDailyCounter()
|
|
{
|
|
::CloseHandle(m_hMutex);
|
|
}
|
|
|
|
void CDailyCounter::Increment()
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
SetDay();
|
|
m_arrCount[m_ThisDay].Increment();
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
void CDailyCounter::Clear()
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
for (long i = 0; i < 7; i++)
|
|
m_arrCount[i].Clear();
|
|
m_nThisDayLastWeek = 0;
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
void CDailyCounter::Init(long count)
|
|
{
|
|
CDailyCounter::Clear();
|
|
WAIT_INFINITE( m_hMutex );
|
|
SetDay();
|
|
m_arrCount[m_ThisDay].Init(count);
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
// return a 7-day total prior to the present day.
|
|
// non-const because it calls SetDay()
|
|
long CDailyCounter::GetWeekCount()
|
|
{
|
|
long WeekCount = 0;
|
|
WAIT_INFINITE( m_hMutex );
|
|
SetDay();
|
|
for (long i=0; i<7; i++)
|
|
{
|
|
if ( i != m_ThisDay )
|
|
WeekCount += m_arrCount[i].Get();
|
|
WeekCount += m_nThisDayLastWeek;
|
|
}
|
|
::ReleaseMutex(m_hMutex);
|
|
|
|
return WeekCount;
|
|
}
|
|
|
|
// non-const because it calls SetDay()
|
|
void CDailyCounter::GetDailies(CDailyTotals & totals)
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
|
|
totals.Reset();
|
|
|
|
SetDay();
|
|
|
|
time_t time = m_ThisTime - (k_secsPerWeek);
|
|
|
|
totals.SetNext(time, m_nThisDayLastWeek);
|
|
|
|
long i;
|
|
for (i=m_ThisDay+1; i<7; i++)
|
|
{
|
|
time += k_secsPerDay;
|
|
totals.SetNext(time, m_arrCount[i].Get());
|
|
}
|
|
|
|
for (i=0; i<=m_ThisDay; i++)
|
|
{
|
|
time += k_secsPerDay;
|
|
totals.SetNext(time, m_arrCount[i].Get());
|
|
}
|
|
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
// Based on the present time, shifts to the appropriate bin.
|
|
void CDailyCounter::SetDay()
|
|
{
|
|
time_t timeNow;
|
|
time_t timeStartOfDay;
|
|
|
|
WAIT_INFINITE( m_hMutex );
|
|
|
|
time(&timeNow);
|
|
|
|
// Want to get start of day local time.
|
|
// Can't just set timeStartOfDay = (timeNow / k_secsPerDay) * k_secsPerDay
|
|
// because that would be the start of the day based on GMT!
|
|
long DayOfWeek;
|
|
{
|
|
// minimize how long we use CSafeTime, because it means holding a mutex.
|
|
CSafeTime safe(timeNow);
|
|
struct tm tmStartOfDay = safe.LocalTime();
|
|
DayOfWeek = tmStartOfDay.tm_wday;
|
|
tmStartOfDay.tm_sec = 0;
|
|
tmStartOfDay.tm_min = 0;
|
|
tmStartOfDay.tm_hour = 0;
|
|
timeStartOfDay = mktime(&tmStartOfDay);
|
|
}
|
|
|
|
if (timeStartOfDay > m_ThisTime)
|
|
{
|
|
// If we get here, day changed. Typically the last action was the previous
|
|
// hour, but the algorithm here does not require that.
|
|
{
|
|
// minimize how long we use CSafeTime, because it means holding a mutex.
|
|
CSafeTime safe(timeStartOfDay);
|
|
DayOfWeek = safe.LocalTime().tm_wday;
|
|
}
|
|
|
|
if (timeStartOfDay - m_ThisTime > k_secsPerWeek)
|
|
Clear();
|
|
else
|
|
{
|
|
m_nThisDayLastWeek = m_arrCount[DayOfWeek].Get();
|
|
if (m_ThisDay > DayOfWeek)
|
|
{
|
|
long i;
|
|
for (i=m_ThisDay+1; i<7; i++)
|
|
{
|
|
m_arrCount[i].Clear();
|
|
}
|
|
for (i=0; i<=DayOfWeek; i++)
|
|
{
|
|
m_arrCount[i].Clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long i=m_ThisDay+1; i<=DayOfWeek; i++)
|
|
{
|
|
m_arrCount[i].Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_ThisDay = DayOfWeek;
|
|
m_ThisTime = timeStartOfDay;
|
|
}
|
|
::ReleaseMutex(m_hMutex);
|
|
return;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CHourlyDailyCounter
|
|
//////////////////////////////////////////////////////////////////////
|
|
CHourlyDailyCounter::CHourlyDailyCounter(EId id /*=eIdGeneric*/, CString scope /*=m_GlobalStr*/)
|
|
: CAbstractCounter(id, scope),
|
|
m_Total(0),
|
|
m_timeFirst(0),
|
|
m_timeLast(0),
|
|
m_timeCleared(0)
|
|
{
|
|
m_hMutex = ::CreateMutex(NULL, FALSE, NULL);
|
|
if (!m_hMutex)
|
|
{
|
|
CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
|
|
CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
|
|
SrcLoc.GetSrcFileLineStr(),
|
|
_T("HourlyDaily"),
|
|
_T(""),
|
|
EV_GTS_ERROR_MUTEX );
|
|
}
|
|
|
|
time(&m_timeCreated);
|
|
time(&m_timeCleared);
|
|
}
|
|
|
|
CHourlyDailyCounter::~CHourlyDailyCounter()
|
|
{
|
|
::CloseHandle(m_hMutex);
|
|
}
|
|
|
|
void CHourlyDailyCounter::Increment()
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
m_hourly.Increment();
|
|
m_daily.Increment();
|
|
m_Total++;
|
|
time(&m_timeLast);
|
|
if (!m_timeFirst)
|
|
m_timeFirst = m_timeLast;
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
void CHourlyDailyCounter::Clear()
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
m_hourly.Clear();
|
|
m_daily.Clear();
|
|
m_Total= 0;
|
|
m_timeFirst = 0;
|
|
m_timeLast = 0;
|
|
time(&m_timeCleared);
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
void CHourlyDailyCounter::Init(long count)
|
|
{
|
|
CHourlyDailyCounter::Clear();
|
|
WAIT_INFINITE( m_hMutex );
|
|
m_hourly.Init(count);
|
|
m_daily.Init(count);
|
|
m_Total = count;
|
|
time(&m_timeLast);
|
|
if (!m_timeFirst)
|
|
m_timeFirst = m_timeLast;
|
|
::ReleaseMutex(m_hMutex);
|
|
}
|
|
|
|
// no need to lock here, because m_hourly does its own locking.
|
|
long CHourlyDailyCounter::GetDayCount()
|
|
{
|
|
return m_hourly.GetDayCount();
|
|
}
|
|
|
|
// no need to lock here, because m_hourly does its own locking.
|
|
void CHourlyDailyCounter::GetHourlies(CHourlyTotals & totals)
|
|
{
|
|
m_hourly.GetHourlies(totals);
|
|
}
|
|
|
|
// no need to lock here, because m_daily does its own locking.
|
|
long CHourlyDailyCounter::GetWeekCount()
|
|
{
|
|
return m_daily.GetWeekCount();
|
|
}
|
|
|
|
// no need to lock here, because m_daily does its own locking.
|
|
void CHourlyDailyCounter::GetDailies(CDailyTotals & totals)
|
|
{
|
|
m_daily.GetDailies(totals);
|
|
}
|
|
|
|
long CHourlyDailyCounter::GetTotal() const
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
long ret = m_Total;
|
|
::ReleaseMutex(m_hMutex);
|
|
return ret;
|
|
};
|
|
|
|
time_t CHourlyDailyCounter::GetTimeFirst() const
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
time_t ret = m_timeFirst;
|
|
::ReleaseMutex(m_hMutex);
|
|
return ret;
|
|
};
|
|
|
|
time_t CHourlyDailyCounter::GetTimeLast() const
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
time_t ret = m_timeLast;
|
|
::ReleaseMutex(m_hMutex);
|
|
return ret;
|
|
};
|
|
|
|
time_t CHourlyDailyCounter::GetTimeCleared() const
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
time_t ret = m_timeCleared;
|
|
::ReleaseMutex(m_hMutex);
|
|
return ret;
|
|
};
|
|
|
|
time_t CHourlyDailyCounter::GetTimeCreated() const
|
|
{
|
|
WAIT_INFINITE( m_hMutex );
|
|
time_t ret = m_timeCreated;
|
|
::ReleaseMutex(m_hMutex);
|
|
return ret;
|
|
}
|
|
|
|
time_t CHourlyDailyCounter::GetTimeNow() const
|
|
{
|
|
// No need to lock mutex on this call.
|
|
time_t ret;
|
|
time(&ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// CDisplayCounter...::Display() implementation
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
#define STATUS_INVALID_NUMBER_STR _T("none")
|
|
#define STATUS_INVALID_TIME_STR _T("none")
|
|
|
|
CString CDisplayCounterTotal::Display()
|
|
{
|
|
TCHAR buf[128] = {0};
|
|
_stprintf(buf, _T("%ld"), long(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTotal()));
|
|
return buf;
|
|
}
|
|
|
|
CString CDisplayCounterCurrentDateTime::Display()
|
|
{
|
|
return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeNow()).StrLocalTime(STATUS_INVALID_TIME_STR);
|
|
}
|
|
|
|
CString CDisplayCounterCreateDateTime::Display()
|
|
{
|
|
return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeCreated()).StrLocalTime(STATUS_INVALID_TIME_STR);
|
|
}
|
|
|
|
CString CDisplayCounterFirstDateTime::Display()
|
|
{
|
|
return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeFirst()).StrLocalTime(STATUS_INVALID_TIME_STR);
|
|
}
|
|
|
|
CString CDisplayCounterLastDateTime::Display()
|
|
{
|
|
return CSafeTime(((CHourlyDailyCounter*)m_pAbstractCounter)->GetTimeLast()).StrLocalTime(STATUS_INVALID_TIME_STR);
|
|
}
|
|
|
|
CString CDisplayCounterDailyHourly::Display()
|
|
{
|
|
CString ret;
|
|
|
|
if (m_pDailyTotals) {
|
|
((CHourlyDailyCounter*)m_pAbstractCounter)->GetDailies(*m_pDailyTotals);
|
|
ret += m_pDailyTotals->HTMLDisplay();
|
|
}
|
|
if (m_pHourlyTotals) {
|
|
((CHourlyDailyCounter*)m_pAbstractCounter)->GetHourlies(*m_pHourlyTotals);
|
|
ret += m_pHourlyTotals->HTMLDisplay();
|
|
}
|
|
|
|
return ret;
|
|
}
|