|
|
#ifndef _FILECACHE_HXX_
#define _FILECACHE_HXX_
#include "datetime.hxx"
#include "usercache.hxx"
//
// When accessing file cache, file cache user describes the user trying to
// access the file (it is either a token or token/sid)
//
class FILE_CACHE_USER { public: FILE_CACHE_USER() : _hToken( NULL ), _pSid( NULL ) { } HANDLE _hToken; PSID _pSid; };
//
// Users of the file cache can associate (1) object with a cache entry which
// will get cleaned up (by calling the Cleanup() method) when the object
// is flushed
//
class ASSOCIATED_FILE_OBJECT { public:
virtual VOID Cleanup( VOID ) = 0; };
class W3_FILE_INFO_KEY : public CACHE_KEY { public:
W3_FILE_INFO_KEY() : _strFileKey( _achFileKey, sizeof( _achFileKey ) ), _pszFileKey( NULL ), _cchFileKey( 0 ) { } virtual ~W3_FILE_INFO_KEY() { } WCHAR * QueryHintKey( VOID ) { return _pszFileKey; }
HRESULT CreateCacheKey( WCHAR * pszFileKey, DWORD cchFileKey, BOOL fCopy );
DWORD QueryKeyHash( VOID ) const { return HashString( _pszFileKey ); } BOOL QueryIsEqual( const CACHE_KEY * pCacheCompareKey ) const { W3_FILE_INFO_KEY * pFileKey = (W3_FILE_INFO_KEY*) pCacheCompareKey;
return _cchFileKey == pFileKey->_cchFileKey && !wcscmp( _pszFileKey, pFileKey->_pszFileKey ); } WCHAR _achFileKey[ 64 ]; STRU _strFileKey; WCHAR * _pszFileKey; DWORD _cchFileKey; };
// The maximum length of an ETag is 16 chars for the last modified time plus
// one char for the colon plus 2 chars for the quotes plus 8 chars for the
// system change notification number plus two for the optional prefix W/ and
// one for the trailing NULL, for a total of 30 chars.
#define MAX_ETAG_BUFFER_LENGTH 30
//
// Embedded security descriptor used for cache hits
//
#define SECURITY_DESC_DEFAULT_SIZE 256
//
// File cache entry object
//
#define W3_FILE_INFO_SIGNATURE ((DWORD)'IF3W')
#define W3_FILE_INFO_SIGNATURE_FREE ((DWORD)'if3w')
class W3_FILE_INFO : public CACHE_ENTRY { public: W3_FILE_INFO( OBJECT_CACHE * pObjectCache ) : CACHE_ENTRY( pObjectCache ), _hFile( INVALID_HANDLE_VALUE ), _pFileBuffer( NULL ), _dwFileAttributes( 0 ), _nFileSizeLow( 0 ), _nFileSizeHigh( 0 ), _bufSecDesc( _abSecDesc, sizeof( _abSecDesc ) ), _cchETag( 0 ), _pAssociatedObject( NULL ), _pLastSid( NULL ) { _dwSignature = W3_FILE_INFO_SIGNATURE; } virtual ~W3_FILE_INFO( VOID );
VOID * operator new( size_t size ) { DBG_ASSERT( size == sizeof( W3_FILE_INFO ) ); DBG_ASSERT( sm_pachW3FileInfo != NULL ); return sm_pachW3FileInfo->Alloc(); } VOID operator delete( VOID * pW3FileInfo ) { DBG_ASSERT( pW3FileInfo != NULL ); DBG_ASSERT( sm_pachW3FileInfo != NULL ); DBG_REQUIRE( sm_pachW3FileInfo->Free( pW3FileInfo ) ); } CACHE_KEY * QueryCacheKey( VOID ) const { return (CACHE_KEY*) &_cacheKey; } BOOL QueryIsOkToFlushDirmon( WCHAR * pszPath, DWORD cchPath ); BOOL CheckSignature( VOID ) const { return _dwSignature == W3_FILE_INFO_SIGNATURE; } HRESULT GetFileHandle( HANDLE * phHandle ); PBYTE QueryFileBuffer( VOID ) const { return _pFileBuffer; } VOID QuerySize( LARGE_INTEGER * pliSize ) const { DBG_ASSERT( pliSize != NULL ); pliSize->LowPart = _nFileSizeLow; pliSize->HighPart = _nFileSizeHigh; } WCHAR * QueryPhysicalPath( VOID ) { return _cacheKey._pszFileKey; }
DWORD QueryAttributes( VOID ) const { return _dwFileAttributes; } PSECURITY_DESCRIPTOR QuerySecDesc( VOID );
PSID QueryLastSid( VOID ) { return _pLastSid; }
VOID QueryLastWriteTime( FILETIME * pFileTime ) const { DBG_ASSERT( pFileTime != NULL );
memcpy( pFileTime, &_CastratedLastWriteTime, sizeof( *pFileTime ) ); }
CHAR * QueryLastModifiedString( VOID ) { return _achLastModified; }
BOOL QueryIsWeakETag( VOID ) const { return _achETag[ 0 ] == 'W' && _achETag[ 1 ] == '/'; } HANDLE QueryFileHandle( VOID ) { return _hFile; }
CHAR * QueryETag( VOID ) { return _achETag; } DWORD QueryETagSize( VOID ) const { return _cchETag; } dllexp BOOL SetAssociatedObject( ASSOCIATED_FILE_OBJECT * pObject ); ASSOCIATED_FILE_OBJECT * QueryAssociatedObject( VOID ) { return _pAssociatedObject; }
HRESULT OpenFile( STRU & strFileName, FILE_CACHE_USER * pOpeningUser ); HRESULT DoAccessCheck( FILE_CACHE_USER * pOpeningUser );
BOOL IsCacheable( VOID ) const; HRESULT MakeCacheable( FILE_CACHE_USER * pOpeningUser );
static HRESULT Initialize( VOID ); static VOID Terminate( VOID ); private:
HRESULT ReadSecurityDescriptor( VOID );
HRESULT GenerateETag( VOID );
HRESULT GenerateLastModifiedTimeString( VOID );
DWORD _dwSignature;
W3_FILE_INFO_KEY _cacheKey; //
// File info data
//
HANDLE _hFile; PBYTE _pFileBuffer; FILETIME _ftLastWriteTime; FILETIME _CastratedLastWriteTime; DWORD _dwFileAttributes; ULONG _nFileSizeLow; ULONG _nFileSizeHigh;
//
// Security descriptor stuff
//
BYTE _abSecDesc[ SECURITY_DESC_DEFAULT_SIZE ]; BUFFER _bufSecDesc;
//
// ETag
//
CHAR _achETag[ MAX_ETAG_BUFFER_LENGTH ]; DWORD _cchETag;
//
// Last modified time
//
CHAR _achLastModified[ GMT_STRING_SIZE ];
//
// Last SID to access the file
//
BYTE _abLastSid[ 64 ]; PSID _pLastSid;
//
// Associated object (only one is allowed)
//
ASSOCIATED_FILE_OBJECT* _pAssociatedObject; //
// Lookaside
//
static ALLOC_CACHE_HANDLER * sm_pachW3FileInfo; };
//
// The file cache itself
//
#define DEFAULT_FILE_SIZE_THRESHOLD (256*1024)
#define DEFAULT_W3_FILE_INFO_CACHE_TTL (30)
#define DEFAULT_W3_FILE_INFO_CACHE_ACTIVITY (10)
class W3_FILE_INFO_CACHE : public OBJECT_CACHE { public:
W3_FILE_INFO_CACHE(); virtual ~W3_FILE_INFO_CACHE();
dllexp HRESULT GetFileInfo( STRU & strFileName, DIRMON_CONFIG * pDirmonConfig, FILE_CACHE_USER * pOpeningUser, BOOL fDoCache, W3_FILE_INFO ** ppFileInfo ); WCHAR * QueryName( VOID ) const { return L"W3_FILE_INFO_CACHE"; } HRESULT ReadFileIntoMemoryCache( HANDLE hFile, DWORD cbFile, VOID ** ppvFileBuffer ); HRESULT ReleaseFromMemoryCache( VOID * pFileBuffer, DWORD cbFileBuffer );
VOID DoDirmonInvalidationSpecific( WCHAR * pszPath ); ULONGLONG QueryFileSizeThreshold( VOID ) const { return _cbFileSizeThreshold; } BOOL QueryCacheEnabled( VOID ) const { return _fEnableCache; } BOOL QueryElementLimitExceeded( VOID ) { return _cMaxFileEntries && _cMaxFileEntries <= PerfQueryCurrentEntryCount(); } ULONGLONG PerfQueryCurrentMemCacheSize( VOID ) const { return _cbMemCacheCurrentSize; } ULONGLONG PerfQueryMaxMemCacheSize( VOID ) const { return _cbMaxMemCacheSize; } HRESULT Initialize( VOID ); VOID Terminate( VOID ); dllexp static W3_FILE_INFO_CACHE * GetFileCache( VOID ); private:
HRESULT InitializeMemoryCache( VOID );
VOID TerminateMemoryCache( VOID ); static VOID MemoryCacheAdjustor( PVOID pFileCache, BOOLEAN TimerOrWaitFired );
ULONGLONG _cbFileSizeThreshold; ULONGLONG _cbMemoryCacheSize; DWORD _cMaxFileEntries; BOOL _fEnableCache; //
// Memcache stuff
//
CRITICAL_SECTION _csMemCache; ULONGLONG _cbMemCacheLimit; ULONGLONG _cbMemCacheCurrentSize; ULONGLONG _cbMaxMemCacheSize; HANDLE _hMemCacheHeap; HANDLE _hTimer; };
#endif
|