467 lines
8.4 KiB
C++
467 lines
8.4 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name :
|
||
|
cachemanager.cxx
|
||
|
|
||
|
Abstract:
|
||
|
Manages a list of all the caches and handles invalidation of them
|
||
|
|
||
|
Author:
|
||
|
Bilal Alam (balam) 11-Nov-2000
|
||
|
|
||
|
Environment:
|
||
|
Win32 - User Mode
|
||
|
|
||
|
Project:
|
||
|
ULW3.DLL
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.hxx"
|
||
|
|
||
|
#define DIR_CHANGE_FILTER (FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS)
|
||
|
|
||
|
CACHE_MANAGER * g_pCacheManager;
|
||
|
|
||
|
CACHE_MANAGER::CACHE_MANAGER()
|
||
|
{
|
||
|
_pDirMonitor = NULL;
|
||
|
ZeroMemory( &_Caches, sizeof( _Caches ) );
|
||
|
}
|
||
|
|
||
|
CACHE_MANAGER::~CACHE_MANAGER()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_MANAGER::Initialize(
|
||
|
IMSAdminBase * pAdminBase
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initialize cache manager
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pAdminBase - Admin base object pointer
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Initialize dir monitor
|
||
|
//
|
||
|
|
||
|
DBG_ASSERT( _pDirMonitor == NULL );
|
||
|
|
||
|
_pDirMonitor = new CDirMonitor;
|
||
|
if ( _pDirMonitor == NULL )
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Keep a pointer to the admin base object
|
||
|
//
|
||
|
|
||
|
_pAdminBase = pAdminBase;
|
||
|
_pAdminBase->AddRef();
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CACHE_MANAGER::Terminate(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Cleanup the cache manager
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if ( _pAdminBase != NULL )
|
||
|
{
|
||
|
_pAdminBase->Release();
|
||
|
_pAdminBase = NULL;
|
||
|
}
|
||
|
|
||
|
if ( _pDirMonitor != NULL )
|
||
|
{
|
||
|
delete _pDirMonitor;
|
||
|
_pDirMonitor = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_MANAGER::AddNewCache(
|
||
|
OBJECT_CACHE * pObjectCache
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Add new cache to be managed
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pObjectCache - Object cache to add
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwInsertPos;
|
||
|
|
||
|
if ( pObjectCache == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First the first non-NULL entry
|
||
|
//
|
||
|
|
||
|
for ( dwInsertPos = 0; _Caches[ dwInsertPos ] != NULL; dwInsertPos++ )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add the new cache
|
||
|
//
|
||
|
|
||
|
_Caches[ dwInsertPos ] = pObjectCache;
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_MANAGER::RemoveCache(
|
||
|
OBJECT_CACHE * pObjectCache
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Cache to remove from list of managed caches
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pObjectCache - Object cache to remove
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwPos;
|
||
|
BOOL fFound = FALSE;
|
||
|
|
||
|
if ( pObjectCache == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First find the cache to remove
|
||
|
//
|
||
|
|
||
|
for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
|
||
|
{
|
||
|
if ( _Caches[ dwPos ] == pObjectCache )
|
||
|
{
|
||
|
memmove( _Caches + dwPos,
|
||
|
_Caches + dwPos + 1,
|
||
|
( MAX_CACHE_COUNT - dwPos - 1 ) * sizeof( OBJECT_CACHE*) );
|
||
|
|
||
|
fFound = TRUE;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !fFound )
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CACHE_MANAGER::FlushAllCaches(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Flush all caches
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwPos;
|
||
|
|
||
|
for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
|
||
|
{
|
||
|
_Caches[ dwPos ]->Clear();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Cleanup any dirmon dependencies now since we're about to kill the
|
||
|
// caches
|
||
|
//
|
||
|
|
||
|
_pDirMonitor->Cleanup();
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_MANAGER::HandleDirMonitorInvalidation(
|
||
|
WCHAR * pszFilePath,
|
||
|
BOOL fFlushAll
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Invalidate any caches which are interested in dir monitor invalidation
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pszFilePath - File name changed
|
||
|
fFlushAll - Should we flush all items prefixed with pszFilePath?
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwPos;
|
||
|
OBJECT_CACHE * pCache;
|
||
|
|
||
|
if ( pszFilePath == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Iterate thru all the caches which support dirmon invalidation
|
||
|
//
|
||
|
|
||
|
for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
|
||
|
{
|
||
|
pCache = _Caches[ dwPos ];
|
||
|
|
||
|
//
|
||
|
// If this cache doesn't support dirmon at all, continue
|
||
|
//
|
||
|
|
||
|
if ( !pCache->QuerySupportsDirmonSpecific() &&
|
||
|
!pCache->QuerySupportsDirmonFlush() )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If this is a specific invalidation, check whether the cache
|
||
|
// supports it. If it doesn't, but does support flush, the do a
|
||
|
// flush instead
|
||
|
//
|
||
|
|
||
|
if ( !fFlushAll )
|
||
|
{
|
||
|
if ( pCache->QuerySupportsDirmonSpecific() )
|
||
|
{
|
||
|
pCache->DoDirmonInvalidationSpecific( pszFilePath );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pCache->DoDirmonInvalidationFlush( pszFilePath );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pCache->DoDirmonInvalidationFlush( pszFilePath );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_MANAGER::HandleMetadataInvalidation(
|
||
|
WCHAR * pszMetaPath
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Invalidate any caches which are interested in metadata invalidation
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pszMetaPath - Metabase path which changed
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwPos;
|
||
|
OBJECT_CACHE * pCache;
|
||
|
|
||
|
if ( pszMetaPath == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Iterate thru all the caches which support metadata invalidation
|
||
|
//
|
||
|
|
||
|
for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
|
||
|
{
|
||
|
pCache = _Caches[ dwPos ];
|
||
|
|
||
|
if ( pCache->QuerySupportsMetadataFlush() )
|
||
|
{
|
||
|
pCache->DoMetadataInvalidationFlush( pszMetaPath );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CACHE_MANAGER::MonitorDirectory(
|
||
|
DIRMON_CONFIG * pDirmonConfig,
|
||
|
CDirMonitorEntry ** ppDME
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Monitor given directory
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pDirmonConfig - Name of directory and token to impersonate with
|
||
|
ppDME - Set to monitor entry on success
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
CacheDirMonitorEntry * pDME = NULL;
|
||
|
HRESULT hr = NO_ERROR;
|
||
|
BOOL fRet;
|
||
|
BOOL fImpersonated = FALSE;
|
||
|
|
||
|
if ( ppDME == NULL ||
|
||
|
pDirmonConfig == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( FALSE );
|
||
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First check if we are already monitoring this directory
|
||
|
//
|
||
|
|
||
|
pDME = (CacheDirMonitorEntry*) _pDirMonitor->FindEntry( pDirmonConfig->pszDirPath );
|
||
|
if ( pDME == NULL )
|
||
|
{
|
||
|
//
|
||
|
// It is not. We'll have to start monitoring
|
||
|
//
|
||
|
|
||
|
pDME = new CacheDirMonitorEntry;
|
||
|
if ( pDME == NULL )
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||
|
}
|
||
|
|
||
|
pDME->AddRef();
|
||
|
|
||
|
if ( pDirmonConfig->hToken != NULL )
|
||
|
{
|
||
|
fRet = SetThreadToken( NULL, pDirmonConfig->hToken );
|
||
|
if ( !fRet )
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
||
|
pDME->Release();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
fImpersonated = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
fRet = _pDirMonitor->Monitor( pDME,
|
||
|
pDirmonConfig->pszDirPath,
|
||
|
TRUE,
|
||
|
DIR_CHANGE_FILTER );
|
||
|
|
||
|
if ( fImpersonated )
|
||
|
{
|
||
|
RevertToSelf();
|
||
|
fImpersonated = FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !fRet )
|
||
|
{
|
||
|
//
|
||
|
// Note: It is OK if we can't monitor the directory. The error
|
||
|
// will trickle up and the caller will not cache the entry
|
||
|
//
|
||
|
|
||
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
||
|
|
||
|
pDME->Release();
|
||
|
pDME = NULL;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DBG_ASSERT( pDME != NULL );
|
||
|
|
||
|
*ppDME = (CDirMonitorEntry*) pDME;
|
||
|
return NO_ERROR;
|
||
|
}
|