300 lines
5.8 KiB
C++
300 lines
5.8 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name :
|
||
|
cachehint.cxx
|
||
|
|
||
|
Abstract:
|
||
|
Provides hint to caches about whether or not to cache an entry, based
|
||
|
on usage patterns
|
||
|
|
||
|
Author:
|
||
|
Bilal Alam (balam) 11-Nov-2000
|
||
|
|
||
|
Environment:
|
||
|
Win32 - User Mode
|
||
|
|
||
|
Project:
|
||
|
ULW3.DLL
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.hxx"
|
||
|
#include "cachehint.hxx"
|
||
|
|
||
|
BOOL
|
||
|
CACHE_HINT_ENTRY::QueryIsOkToCache(
|
||
|
DWORD tickCountNow,
|
||
|
DWORD cmsecActivityWindow
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Is it OK to cache entry, given recent activity
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
tickCountNow - Current tick count
|
||
|
cmsecActivityWindow - Maximum window between access to cause caching
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE to cache, FALSE to not cache
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD lastUsageTime;
|
||
|
DWORD timeBetweenUsage;
|
||
|
|
||
|
lastUsageTime = InterlockedExchange( (LPLONG) &_cLastUsageTime,
|
||
|
tickCountNow );
|
||
|
|
||
|
if ( lastUsageTime > tickCountNow )
|
||
|
{
|
||
|
timeBetweenUsage = tickCountNow + ( UINT_MAX - lastUsageTime );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
timeBetweenUsage = tickCountNow - lastUsageTime;
|
||
|
}
|
||
|
|
||
|
if ( timeBetweenUsage < cmsecActivityWindow )
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CACHE_HINT_MANAGER::CACHE_HINT_MANAGER()
|
||
|
: _cConfiguredTTL( 0 ),
|
||
|
_cmsecActivityWindow( 0 ),
|
||
|
_hTimer( NULL )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CACHE_HINT_MANAGER::~CACHE_HINT_MANAGER()
|
||
|
{
|
||
|
if ( _hTimer )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( NULL,
|
||
|
_hTimer,
|
||
|
INVALID_HANDLE_VALUE );
|
||
|
_hTimer = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//static
|
||
|
VOID
|
||
|
WINAPI
|
||
|
CACHE_HINT_MANAGER::ScavengerCallback(
|
||
|
PVOID pParam,
|
||
|
BOOLEAN TimerOrWaitFired
|
||
|
)
|
||
|
{
|
||
|
CACHE_HINT_MANAGER * pHintManager;
|
||
|
|
||
|
pHintManager = (CACHE_HINT_MANAGER*) pParam;
|
||
|
|
||
|
pHintManager->FlushByTTL();
|
||
|
}
|
||
|
|
||
|
//static
|
||
|
LK_PREDICATE
|
||
|
CACHE_HINT_MANAGER::HintFlushByTTL(
|
||
|
CACHE_HINT_ENTRY * pHintEntry,
|
||
|
VOID * pvState
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determine whether given entry should be deleted due to TTL
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCacheEntry - Cache hint entry to check
|
||
|
pvState - Unused
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
LKP_PERFORM - do the delete,
|
||
|
LKP_NO_ACTION - do nothing
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DBG_ASSERT( pHintEntry != NULL );
|
||
|
|
||
|
if ( pHintEntry->QueryIsOkToFlushTTL() )
|
||
|
{
|
||
|
return LKP_PERFORM;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return LKP_NO_ACTION;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CACHE_HINT_MANAGER::FlushByTTL(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Flush hint entries which have expired
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
_hintTable.DeleteIf( HintFlushByTTL, NULL );
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_HINT_MANAGER::Initialize(
|
||
|
CACHE_HINT_CONFIG * pConfig
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initialize cache hint table
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pConfig - Cache hint config table
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
BOOL fRet;
|
||
|
|
||
|
if ( pConfig == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
_cConfiguredTTL = pConfig->cmsecTTL / pConfig->cmsecScavengeTime + 1;
|
||
|
_cmsecActivityWindow = pConfig->cmsecActivityWindow;
|
||
|
|
||
|
fRet = CreateTimerQueueTimer( &_hTimer,
|
||
|
NULL,
|
||
|
CACHE_HINT_MANAGER::ScavengerCallback,
|
||
|
this,
|
||
|
pConfig->cmsecScavengeTime,
|
||
|
pConfig->cmsecScavengeTime,
|
||
|
WT_EXECUTELONGFUNCTION );
|
||
|
if ( !fRet )
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_HINT_MANAGER::ShouldCacheEntry(
|
||
|
CACHE_KEY * pCacheEntryKey,
|
||
|
BOOL * pfShouldCache
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determine whether we the given entry should be cached
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pCacheEntryKey - Entry key in question (must implement QueryHintKey())
|
||
|
pfShouldCache - Set to TRUE if we should cache
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LK_RETCODE lkrc;
|
||
|
CACHE_HINT_ENTRY * pHintEntry = NULL;
|
||
|
DWORD tickCount;
|
||
|
HRESULT hr;
|
||
|
|
||
|
if ( pCacheEntryKey == NULL ||
|
||
|
pfShouldCache == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
*pfShouldCache = FALSE;
|
||
|
|
||
|
DBG_ASSERT( pCacheEntryKey->QueryHintKey() != NULL );
|
||
|
|
||
|
lkrc = _hintTable.FindKey( pCacheEntryKey->QueryHintKey(),
|
||
|
&pHintEntry );
|
||
|
if ( lkrc == LK_SUCCESS )
|
||
|
{
|
||
|
DBG_ASSERT( pHintEntry != NULL );
|
||
|
|
||
|
tickCount = GetTickCount();
|
||
|
|
||
|
if ( pHintEntry->QueryIsOkToCache( tickCount,
|
||
|
_cmsecActivityWindow ) )
|
||
|
{
|
||
|
//
|
||
|
// We can delete this hint entry now
|
||
|
//
|
||
|
|
||
|
_hintTable.DeleteRecord( pHintEntry );
|
||
|
|
||
|
*pfShouldCache = TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Release corresponding to the FindKey
|
||
|
//
|
||
|
pHintEntry->Release();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pHintEntry = new CACHE_HINT_ENTRY( _cConfiguredTTL,
|
||
|
GetTickCount() );
|
||
|
if ( pHintEntry == NULL )
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||
|
}
|
||
|
|
||
|
hr = pHintEntry->SetKey( pCacheEntryKey->QueryHintKey() );
|
||
|
if ( FAILED( hr ) )
|
||
|
{
|
||
|
pHintEntry->Release();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
lkrc = _hintTable.InsertRecord( pHintEntry );
|
||
|
|
||
|
//
|
||
|
// Release the extra reference
|
||
|
//
|
||
|
pHintEntry->Release();
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|