Leaked source code of windows server 2003
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.
 
 
 
 
 
 

671 lines
13 KiB

#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