2025-04-27 07:49:33 -04:00

297 lines
6.2 KiB
C++

// ccm.cpp : Implementation of CCM, the Central Counter Manager
// that persists as long as this DLL is loaded. It manages the loading and
// updating of the Hit Count Data file.
#include "stdafx.h"
#include "ccm.h"
#include "debug.h"
#include "critsec.h"
#include <stdio.h>
extern CMonitor* g_pMonitor;
//---------------------------------------------------------------------------
// CRegNotify
//---------------------------------------------------------------------------
CRegNotify::CRegNotify()
: m_dwSaveCount(HITCNT_DFLT_SAVE)
{
GetFileName();
GetSaveCount();
}
void
CRegNotify::Notify()
{
GetFileName();
GetSaveCount();
}
String
CRegNotify::FileName()
{
CAutoLeaveCritSec l(m_cs);
return m_strFileName;
}
DWORD
CRegNotify::SaveCount()
{
return m_dwSaveCount;
}
bool
CRegNotify::GetFileName()
{
bool rc = false;
//Open the HitCnt Key
CRegKey regKey;
long retValue = regKey.Open(HITCNT_HKEY, HITCNT_KEYNAME, KEY_READ);
DWORD dwType = REG_EXPAND_SZ;
TCHAR tszTemp[MAX_PATH];
DWORD dwSize = sizeof(tszTemp);
if(retValue == ERROR_SUCCESS)
{
//Get the File_Location from the Registry
retValue = RegQueryValueEx(regKey,
HITCNT_FILELOCN,
NULL,
&dwType,
(LPBYTE) tszTemp,
&dwSize);
}
// If there's an error, use the default
if(retValue != ERROR_SUCCESS
|| (dwType != REG_EXPAND_SZ && dwType != REG_SZ))
{
_tcscpy(tszTemp, HITCNT_DFLT_FILE);
}
//tszTemp contains an embedded environment variable (%windir%),
//so expand it
TCHAR tszFileName[MAX_PATH];
ExpandEnvironmentStrings(tszTemp, tszFileName, ARRAYSIZE(tszFileName));
// lock the object, and copy it into the permenant string
CAutoLeaveCritSec l(m_cs);
m_strFileName = tszFileName;
ATLTRACE(_T("GetFileName %s\n"), m_strFileName.c_str());
return TRUE;
}
//Get the threshold for updating the persistent data from the registry
bool
CRegNotify::GetSaveCount()
{
//Open the HitCnt Key
CRegKey regKey;
long retValue = regKey.Open(HITCNT_HKEY, HITCNT_KEYNAME, KEY_READ);
if(retValue == ERROR_SUCCESS)
{
DWORD dwType, dwSaveCount, dwSize = sizeof(dwSaveCount);
//Get the Save_Count from the Registry
retValue = RegQueryValueEx(regKey,
HITCNT_SAVECNT,
NULL,
&dwType,
(LPBYTE)&dwSaveCount,
&dwSize);
if(retValue == ERROR_SUCCESS && dwType == REG_DWORD && dwSaveCount > 0)
{
::InterlockedExchange(
reinterpret_cast<long*>(&m_dwSaveCount),
static_cast<long>(dwSaveCount) );
return true;
}
}
//Registry Lookup Failed so set Default to HITCNT_DFLT_SAVE
::InterlockedExchange( reinterpret_cast<long*>(&m_dwSaveCount), HITCNT_DFLT_SAVE );
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
CCM::CCM()
: m_cUnsavedHits(0),
m_bInitialized( false )
{
}
CCM::~CCM()
{
}
//Initialize Page Counter Component
BOOL CCM::Initialize()
{
BOOL Result = FALSE;
if ( m_bInitialized )
{
// do nothing
Result = TRUE;
}
else
{
CAutoLeaveCritSec l(m_critsec);
// re-check, in case it was inited while we were gaining a lock
if ( !m_bInitialized )
{
m_pRegKey = new CRegNotify();
if ( _Module.Monitor() )
{
_Module.Monitor()->MonitorRegKey( HITCNT_HKEY, HITCNT_KEYNAME, m_pRegKey );
}
//Read File
Result = LoadData() && Result;
m_bInitialized = true;
}
}
return Result;
}
////////////////// Start Object Methods //////////////////
DWORD CCM::IncrementAndGetHits(const BSTR bstrURL)
{
Initialize();
CAutoLeaveCritSec alcs(m_critsec);
UINT retval = m_pages.IncrementPage(bstrURL);
if (retval == BAD_HITS)
retval = 0;
if(++m_cUnsavedHits >= m_pRegKey->SaveCount() )
{
if (!Persist())
retval = 0; //failure
m_cUnsavedHits = 0;
}
return retval;
}
LONG CCM::GetHits (const BSTR bstrURL)
{
Initialize();
CAutoLeaveCritSec alcs(m_critsec);
LONG retval = m_pages.GetHits(bstrURL);
if (retval == BAD_HITS)
retval = 0;
return retval;
}
void CCM::Reset (const BSTR bstrURL)
{
Initialize();
CAutoLeaveCritSec alcs(m_critsec);
m_pages.Reset(bstrURL);
}
////////////////// Helper Methods //////////////////
//Load URLs and Hit Counts from Disk
BOOL CCM::LoadData()
{
String strFileName = m_pRegKey->FileName();
ATLTRACE(_T("LoadData(%s)\n"), strFileName.c_str() );
BOOL retval = TRUE;
//Attempt to Open File
FILE* fp = _tfopen(strFileName.c_str(), _T("r"));
if(fp == NULL)
return FALSE;
for (;;)
{
char buffer[1024+15];
UINT Hits;
if (fgets(buffer, sizeof buffer, fp) == NULL)
{
// fgets returns NULL both on error and on EOF
retval = (feof(fp) != 0);
break;
}
if (sscanf(buffer, "%u%1024s", &Hits, buffer) != 2)
{
retval = FALSE;
break;
}
USES_CONVERSION; //needed by A2OLE
if (m_pages.AddPage(A2OLE(buffer), Hits) == BAD_HITS)
{
retval = FALSE;
break;
};
}
fclose(fp);
return retval;
}
//Write out URLs and Hit Counts to Disk
BOOL CCM::Persist()
{
Initialize();
String strFileName = m_pRegKey->FileName();
ATLTRACE(_T("Persist(%s)\n"), strFileName.c_str());
//Attempt to Open File
FILE* fp = _tfopen(strFileName.c_str(), _T("w+"));
if(fp == NULL)
return TRUE;
// BOOL retval = TRUE;
for(UINT count = 0; count < m_pages.Size(); count++)
{
USES_CONVERSION;
int cch = fprintf(fp, "%i\t%s\n", m_pages[count].GetHits(),
OLE2CA(m_pages[count].GetURL()));
if (cch < 0)
{
// retval = FALSE;
}
}
fclose(fp);
return TRUE;
}