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.
293 lines
5.9 KiB
293 lines
5.9 KiB
/*++
|
|
|
|
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
|
|
)
|
|
{
|
|
CACHE_HINT_MANAGER * pHintManager;
|
|
|
|
pHintManager = (CACHE_HINT_MANAGER*) pParam;
|
|
|
|
pHintManager->FlushByTTL();
|
|
}
|
|
|
|
//static
|
|
LK_PREDICATE
|
|
CACHE_HINT_MANAGER::HintFlushByTTL(
|
|
CACHE_HINT_ENTRY * pHintEntry,
|
|
VOID *
|
|
)
|
|
/*++
|
|
|
|
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 ) )
|
|
{
|
|
*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;
|
|
}
|
|
|