|
|
#ifndef _FILECACHE_HXX_
#define _FILECACHE_HXX_
#include "datetime.hxx"
#include "usercache.hxx"
//
// 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
class W3_FILE_INFO;
//
// The context used for async file reads
//
typedef VOID (* W3_CACHE_CALLBACK_FUNCTION)(PVOID pContext, HRESULT hr);
typedef struct { //
// Callback function to be notified
//
W3_CACHE_CALLBACK_FUNCTION pfnCallback;
//
// Overlapped for async file read
//
OVERLAPPED Overlapped;
//
// The file-info for which this async IO is being done
//
W3_FILE_INFO *pFileInfo;
} FILE_CACHE_ASYNC_CONTEXT;
//
// 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 ), _fUlCacheAllowed( FALSE ), _msLastAttributeCheckTime( 0 ) { _dwSignature = W3_FILE_INFO_SIGNATURE; }
virtual ~W3_FILE_INFO( VOID );
VOID * operator new( #if DBG
size_t size #else
size_t #endif
) { 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; }
virtual BOOL Checkout( CACHE_USER *pOpeningUser );
HRESULT GetFileHandle( HANDLE * phHandle );
PBYTE QueryFileBuffer( VOID ) const { return _pFileBuffer; }
VOID QuerySize( ULARGE_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; }
USHORT QueryETagSize( VOID ) const { return _cchETag; }
DWORD QueryLastAttributeCheckTime( VOID ) const { return _msLastAttributeCheckTime; }
dllexp BOOL SetAssociatedObject( ASSOCIATED_FILE_OBJECT * pObject );
ASSOCIATED_FILE_OBJECT * QueryAssociatedObject( VOID ) { return _pAssociatedObject; }
HRESULT OpenFile( STRU & strFileName, CACHE_USER * pOpeningUser, BOOL fBufferFile );
HRESULT DoAccessCheck( CACHE_USER * pOpeningUser );
HRESULT MakeCacheable( CACHE_USER * pOpeningUser, FILE_CACHE_ASYNC_CONTEXT *pAsyncContext, BOOL *pfHandledSync, BOOL fCheckForExistenceOnly );
VOID AllowUlCache( VOID ) { _fUlCacheAllowed = TRUE; }
BOOL QueryUlCacheAllowed( VOID ) const { return _fUlCacheAllowed; }
BOOL IsUlCacheable( VOID ) const;
BOOL IsCacheable( VOID ) const;
HRESULT CheckIfFileHasChanged( BOOL * pfHasChanged, CACHE_USER * pOpeningUser );
static HRESULT Initialize( VOID );
static VOID Terminate( VOID );
static VOID CALLBACK FileReadCompletion( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped);
private:
W3_FILE_INFO(const W3_FILE_INFO &); void operator=(const W3_FILE_INFO &);
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 ]; USHORT _cchETag;
//
// Last modified time
//
CHAR _achLastModified[ GMT_STRING_SIZE ];
//
// Last SID to access the file
//
BYTE _abLastSid[ 64 ]; PSID _pLastSid;
//
// UL cache status
//
BOOL _fUlCacheAllowed; //
// Associated object (only one is allowed)
//
ASSOCIATED_FILE_OBJECT* _pAssociatedObject;
//
// TickCount since file was last checked for change
//
DWORD _msLastAttributeCheckTime; //
// Lookaside
//
static ALLOC_CACHE_HANDLER * sm_pachW3FileInfo; };
//
// The file cache itself
//
#define DEFAULT_FILE_SIZE_THRESHOLD (256*1024)
#define DEFAULT_FILE_ATTRIBUTE_CHECK_THRESHOLD (5) // in seconds
#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, CACHE_USER * pOpeningUser, BOOL fDoCache, W3_FILE_INFO ** ppFileInfo, FILE_CACHE_ASYNC_CONTEXT *pAsyncContext = NULL, BOOL *pfHandledSync = NULL, BOOL fAllowNoBuffering = FALSE, BOOL fCheckForExistanceOnly = FALSE );
WCHAR * QueryName( VOID ) const { return L"W3_FILE_INFO_CACHE"; }
HRESULT ReadFileIntoMemoryCache( HANDLE hFile, DWORD cbFile, VOID ** ppvFileBuffer, FILE_CACHE_ASYNC_CONTEXT *pAsyncContext, BOOL *pfHandledSync );
HRESULT ReleaseFromMemoryCache( VOID * pFileBuffer, DWORD cbFileBuffer );
VOID DoDirmonInvalidationSpecific( WCHAR * pszPath ); ULONGLONG QueryFileSizeThreshold( VOID ) const { return _cbFileSizeThreshold; } DWORD QueryFileAttributeCheckThreshold( VOID ) const { return _cmsecFileAttributeCheckThreshold; } 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 );
BOOL QueryDoDirmonForUnc() { return _fDoDirmonForUnc; } private:
W3_FILE_INFO_CACHE(const W3_FILE_INFO_CACHE &); void operator=(const W3_FILE_INFO_CACHE &);
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;
//
// Do we do dirmonitoring for UNC files?
//
BOOL _fDoDirmonForUnc; //
// Threshold for attribute checking
//
DWORD _cmsecFileAttributeCheckThreshold; };
#endif
|