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.
606 lines
12 KiB
606 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name :
|
|
ulcache.cxx
|
|
|
|
Abstract:
|
|
UL cache entries
|
|
|
|
Author:
|
|
Bilal Alam (balam) 11-Nov-2000
|
|
|
|
Environment:
|
|
Win32 - User Mode
|
|
|
|
Project:
|
|
ULW3.DLL
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
ALLOC_CACHE_HANDLER * UL_RESPONSE_CACHE_ENTRY::sm_pachUlResponseCache;
|
|
|
|
HRESULT
|
|
UL_RESPONSE_CACHE_KEY::CreateCacheKey(
|
|
WCHAR * pszKey,
|
|
DWORD cchKey,
|
|
BOOL fCopy
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Setup a UL response cache key
|
|
|
|
Arguments:
|
|
|
|
pszKey - URL of cache key
|
|
cchKey - size of URL
|
|
fCopy - Set to TRUE if we should copy the URL, else we just keep a ref
|
|
|
|
Return:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( fCopy )
|
|
{
|
|
hr = _strKey.Copy( pszKey );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
_pszKey = _strKey.QueryStr();
|
|
_cchKey = _strKey.QueryCCH();
|
|
}
|
|
else
|
|
{
|
|
_pszKey = pszKey;
|
|
_cchKey = cchKey;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//static
|
|
HRESULT
|
|
UL_RESPONSE_CACHE_ENTRY::Initialize(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
UL_RESPONSE_CACHE_ENTRY lookaside initialization
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
ALLOC_CACHE_CONFIGURATION acConfig;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Initialize allocation lookaside
|
|
//
|
|
|
|
acConfig.nConcurrency = 1;
|
|
acConfig.nThreshold = 100;
|
|
acConfig.cbSize = sizeof( UL_RESPONSE_CACHE_ENTRY );
|
|
|
|
DBG_ASSERT( sm_pachUlResponseCache == NULL );
|
|
|
|
sm_pachUlResponseCache = new ALLOC_CACHE_HANDLER( "UL_RESPONSE_CACHE_ENTRY",
|
|
&acConfig );
|
|
|
|
if ( sm_pachUlResponseCache == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Error initializing sm_pachUlResponseCache. hr = 0x%x\n",
|
|
hr ));
|
|
|
|
return hr;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//static
|
|
VOID
|
|
UL_RESPONSE_CACHE_ENTRY::Terminate(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
UL_RESPONSE_CACHE_ENTRY lookaside cleanup
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if ( sm_pachUlResponseCache != NULL )
|
|
{
|
|
delete sm_pachUlResponseCache;
|
|
sm_pachUlResponseCache = NULL;
|
|
}
|
|
}
|
|
|
|
UL_RESPONSE_CACHE_ENTRY::~UL_RESPONSE_CACHE_ENTRY()
|
|
{
|
|
_dwSignature = UL_RESPONSE_CACHE_ENTRY_SIGNATURE_FREE;
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Invalidating URL %ws\n",
|
|
_strInvalidationUrl.QueryStr() ));
|
|
|
|
UlAtqFlushUlCache( _strInvalidationUrl.QueryStr() );
|
|
}
|
|
|
|
HRESULT
|
|
UL_RESPONSE_CACHE_ENTRY::Create(
|
|
STRU & strMetadataPath,
|
|
STRU * pstrPhysicalPath,
|
|
STRU & strInvalidationUrl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize a ul response cache entry
|
|
|
|
Arguments:
|
|
|
|
strMetadataPath - Metadata path associated with this response
|
|
strPhysicalPath - Physical path to dir monitor
|
|
strInvalidationUrl - Exact URL used to flush the UL response cache
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
hr = _cacheKey.CreateCacheKey( strMetadataPath.QueryStr(),
|
|
strMetadataPath.QueryCCH(),
|
|
TRUE );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pstrPhysicalPath != NULL)
|
|
{
|
|
hr = _strPhysicalPath.Copy( *pstrPhysicalPath );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = _strInvalidationUrl.Copy( strInvalidationUrl );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
BOOL
|
|
UL_RESPONSE_CACHE_ENTRY::QueryIsOkToFlushDirmon(
|
|
WCHAR * pszPath,
|
|
DWORD cchPath
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Is it OK to flush this entry based on the given file which has changed
|
|
|
|
Arguments:
|
|
|
|
pszPath - Path that changed
|
|
cchPath - Length of path
|
|
|
|
Return:
|
|
|
|
TRUE if we should flush, else FALSE
|
|
|
|
--*/
|
|
{
|
|
if ( _wcsnicmp( _strPhysicalPath.QueryStr(),
|
|
pszPath,
|
|
cchPath ) == 0 )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
UL_RESPONSE_CACHE::UL_RESPONSE_CACHE()
|
|
: _fUlCacheEnabled( TRUE )
|
|
{
|
|
}
|
|
|
|
UL_RESPONSE_CACHE::~UL_RESPONSE_CACHE()
|
|
{
|
|
}
|
|
|
|
HRESULT
|
|
UL_RESPONSE_CACHE::SetupUlCachedResponse(
|
|
W3_CONTEXT * pW3Context,
|
|
STRU & strFullUrl,
|
|
BOOL fAddDirmonInvalidator,
|
|
STRU * pstrPhysicalPath,
|
|
DWORD cTTLOverride
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build (if necessary) a cache entry which controls the invalidation of
|
|
a UL cached response
|
|
|
|
Arguments:
|
|
|
|
pW3Context - Context
|
|
strFullUrl - Exact URL used to flush the UL response cache
|
|
fAddDirmonInvalidator - Should we use dirmon to flush the response
|
|
pstrPhysicalPath - Physical path to dir monitor
|
|
cTTLOverride - Override the default TTL for UL_CACHE_ENTRY and hence for
|
|
the response in http.sys cache itself
|
|
|
|
Return Value:
|
|
|
|
HRESULT (if FAILED, then we should not UL cache the response)
|
|
|
|
--*/
|
|
{
|
|
UL_RESPONSE_CACHE_KEY ulKey;
|
|
UL_RESPONSE_CACHE_ENTRY * pEntry = NULL;
|
|
HRESULT hr;
|
|
W3_METADATA * pMetaData;
|
|
W3_URL_INFO * pUrlInfo;
|
|
|
|
if ( pW3Context == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
DBG_ASSERT( pW3Context->QueryUrlContext() != NULL );
|
|
|
|
pMetaData = pW3Context->QueryUrlContext()->QueryMetaData();
|
|
DBG_ASSERT( pMetaData != NULL );
|
|
|
|
pUrlInfo = pW3Context->QueryUrlContext()->QueryUrlInfo();
|
|
DBG_ASSERT( pUrlInfo != NULL );
|
|
|
|
//
|
|
// Setup key to lookup whether we already have this response cached
|
|
//
|
|
|
|
hr = ulKey.CreateCacheKey( pUrlInfo->QueryMetadataPath()->QueryStr(),
|
|
pUrlInfo->QueryMetadataPath()->QueryCCH(),
|
|
FALSE );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Find a response entry
|
|
//
|
|
|
|
hr = FindCacheEntry( &ulKey,
|
|
(CACHE_ENTRY**) &pEntry );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
DBG_ASSERT( pEntry != NULL );
|
|
|
|
//
|
|
// Ok. We already have a UL cached entry. Just release it
|
|
// and return success
|
|
//
|
|
|
|
pEntry->DereferenceCacheEntry();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Ok. Try to add an entry
|
|
//
|
|
|
|
pEntry = new UL_RESPONSE_CACHE_ENTRY( this, cTTLOverride );
|
|
if ( pEntry == NULL )
|
|
{
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
|
|
hr = pEntry->Create( *(pUrlInfo->QueryMetadataPath()),
|
|
pstrPhysicalPath,
|
|
strFullUrl );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
pEntry->DereferenceCacheEntry();
|
|
return hr;
|
|
}
|
|
|
|
if (fAddDirmonInvalidator)
|
|
{
|
|
//
|
|
// Start monitoring the appropriate directory for changes
|
|
//
|
|
|
|
hr = pEntry->AddDirmonInvalidator( pMetaData->QueryDirmonConfig() );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
pEntry->DereferenceCacheEntry();
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add the cache entry
|
|
//
|
|
|
|
hr = AddCacheEntry( pEntry );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
pEntry->DereferenceCacheEntry();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Hash table owns a reference now. Just release and return success
|
|
//
|
|
|
|
pEntry->DereferenceCacheEntry();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
BOOL
|
|
UL_RESPONSE_CACHE::CheckUlCacheability(
|
|
W3_CONTEXT * pW3Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine whether the response for the given context appears cacheable
|
|
in UL.
|
|
|
|
Arguments:
|
|
|
|
pW3Context - Context describing request
|
|
|
|
Return Value:
|
|
|
|
TRUE if response seems ul cachable
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = NO_ERROR;
|
|
W3_METADATA * pMetaData = NULL;
|
|
URL_CONTEXT * pUrlContext = NULL;
|
|
|
|
if ( pW3Context == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return FALSE;
|
|
}
|
|
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
if ( pUrlContext == NULL )
|
|
{
|
|
//
|
|
// We have no metadata (must be a fatal error)
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
pMetaData = pUrlContext->QueryMetaData();
|
|
DBG_ASSERT( pMetaData != NULL );
|
|
|
|
//
|
|
// If UL cache is disabled, then response is not UL cacheable (duh!)
|
|
//
|
|
|
|
if ( !QueryUlCacheEnabled() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !pW3Context->QueryIsUlCacheable() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Only UL cache 200 responses
|
|
//
|
|
|
|
if ( pW3Context->QueryResponse()->QueryStatusCode() !=
|
|
HttpStatusOk.statusCode )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Is dynamic compression enabled? Since dynamic compression
|
|
// is done later in W3_RESPONSE object, we need to do check now
|
|
//
|
|
|
|
if ( pMetaData->QueryDoDynamicCompression() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Is this a child request?
|
|
//
|
|
|
|
if ( pW3Context->QueryParentContext() != NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Is there a current handler which is UL friendly?
|
|
//
|
|
|
|
if ( pW3Context->QueryHandler() == NULL ||
|
|
!pW3Context->QueryHandler()->QueryIsUlCacheable() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Are there filters installed which are not cache aware?
|
|
//
|
|
|
|
if ( !pW3Context->QuerySite()->QueryFilterList()->QueryIsUlFriendly() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Is this request accessible anonymously?
|
|
//
|
|
|
|
if ( !( pMetaData->QueryAuthentication() & MD_AUTH_ANONYMOUS ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Are we doing custom logging?
|
|
//
|
|
|
|
if ( pW3Context->QueryDoCustomLogging() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Do we have special SSL requirements?
|
|
//
|
|
|
|
if ( pMetaData->QueryAccessPerms() &
|
|
( VROOT_MASK_NEGO_CERT |
|
|
VROOT_MASK_NEGO_MANDATORY |
|
|
VROOT_MASK_MAP_CERT |
|
|
VROOT_MASK_SSL128 ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If we got to here, then we believe we can use the UL cache
|
|
//
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT
|
|
UL_RESPONSE_CACHE::Initialize(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the cache managing invalidation of the UL cache
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwData;
|
|
DWORD dwType;
|
|
DWORD cbData = sizeof( DWORD );
|
|
HKEY hKey;
|
|
|
|
//
|
|
// First determine how UL is configured by reading UL registry config
|
|
//
|
|
|
|
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Services\\http\\Parameters",
|
|
0,
|
|
KEY_READ,
|
|
&hKey ) == ERROR_SUCCESS )
|
|
{
|
|
DBG_ASSERT( hKey != NULL );
|
|
|
|
//
|
|
// Is the UL cache enabled?
|
|
//
|
|
|
|
if ( RegQueryValueEx( hKey,
|
|
L"UriEnableCache",
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) &dwData,
|
|
&cbData ) == ERROR_SUCCESS &&
|
|
dwType == REG_DWORD )
|
|
{
|
|
_fUlCacheEnabled = !!dwData;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
//
|
|
// Setup cache configuration
|
|
//
|
|
|
|
hr = SetCacheConfiguration( 60 * 1000,
|
|
INFINITE,
|
|
CACHE_INVALIDATION_METADATA |
|
|
CACHE_INVALIDATION_DIRMON_FLUSH,
|
|
NULL );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return UL_RESPONSE_CACHE_ENTRY::Initialize();
|
|
}
|