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.
689 lines
13 KiB
689 lines
13 KiB
#ifndef _USERCACHE_HXX_
|
|
#define _USERCACHE_HXX_
|
|
|
|
#include <lkrhash.h>
|
|
#include <dirmon.h>
|
|
#include <reftrace.h>
|
|
|
|
#ifndef W3CACHE_DLLEXP
|
|
# ifdef DLL_IMPLEMENTATION
|
|
# define W3CACHE_DLLEXP __declspec(dllexport)
|
|
# ifdef IMPLEMENTATION_EXPORT
|
|
# define W3CACHE_EXPIMP
|
|
# else
|
|
# undef W3CACHE_EXPIMP
|
|
# endif
|
|
# elif defined LIB_IMPLEMENTATION
|
|
# define W3CACHE_DLLEXP
|
|
# define W3CACHE_EXPIMP extern
|
|
# else
|
|
# define W3CACHE_DLLEXP __declspec(dllimport)
|
|
# define W3CACHE_EXPIMP extern
|
|
# endif // !DLL_IMPLEMENTATION
|
|
#endif // !W3CACHE_DLLEXP
|
|
|
|
#define CACHE_INVALIDATION_DIRMON_SPECIFIC 0x1
|
|
#define CACHE_INVALIDATION_DIRMON_FLUSH 0x2
|
|
#define CACHE_INVALIDATION_METADATA 0x4
|
|
|
|
//
|
|
// Configuration for dir monitoring
|
|
//
|
|
|
|
struct DIRMON_CONFIG
|
|
{
|
|
HANDLE hToken;
|
|
WCHAR * pszDirPath;
|
|
};
|
|
|
|
//
|
|
// When accessing file cache, file cache user describes the user trying to
|
|
// access the file (it is either a token or token/sid)
|
|
//
|
|
|
|
class CACHE_USER
|
|
{
|
|
public:
|
|
CACHE_USER()
|
|
: _hToken( NULL ),
|
|
_pSid( NULL )
|
|
{
|
|
}
|
|
|
|
HANDLE _hToken;
|
|
PSID _pSid;
|
|
};
|
|
|
|
//
|
|
// Key used to lookup any of the caches
|
|
//
|
|
|
|
class CACHE_KEY
|
|
{
|
|
public:
|
|
|
|
CACHE_KEY()
|
|
{
|
|
}
|
|
|
|
virtual ~CACHE_KEY()
|
|
{
|
|
}
|
|
|
|
virtual
|
|
WCHAR *
|
|
QueryHintKey(
|
|
VOID
|
|
)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
virtual
|
|
DWORD
|
|
QueryKeyHash(
|
|
VOID
|
|
) const = 0;
|
|
|
|
virtual
|
|
BOOL
|
|
QueryIsEqual(
|
|
const CACHE_KEY * pCacheCompareKey
|
|
) const = 0;
|
|
};
|
|
|
|
class OBJECT_CACHE;
|
|
|
|
#define CACHE_ENTRY_SIGNATURE 'STEC'
|
|
#define CACHE_ENTRY_SIGNATURE_FREE 'xtec'
|
|
|
|
class W3CACHE_DLLEXP CACHE_ENTRY
|
|
{
|
|
public:
|
|
|
|
CACHE_ENTRY(
|
|
OBJECT_CACHE * pObjectCache,
|
|
DWORD cTTLOverride = 0
|
|
);
|
|
|
|
VOID
|
|
ReferenceCacheEntry(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
DereferenceCacheEntry(
|
|
VOID
|
|
);
|
|
|
|
virtual
|
|
STRU *
|
|
QueryMetadataPath(
|
|
VOID
|
|
)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT
|
|
AddDirmonInvalidator(
|
|
DIRMON_CONFIG * pDirmonConfig
|
|
);
|
|
|
|
BOOL
|
|
QueryIsFlushed(
|
|
VOID
|
|
) const
|
|
{
|
|
return _fFlushed;
|
|
}
|
|
|
|
virtual
|
|
BOOL
|
|
Checkout(
|
|
CACHE_USER *pOpeningUser
|
|
);
|
|
|
|
VOID
|
|
SetCached(
|
|
BOOL fCached
|
|
)
|
|
{
|
|
_fCached = fCached;
|
|
}
|
|
|
|
BOOL
|
|
QueryCached(
|
|
VOID
|
|
) const
|
|
{
|
|
return _fCached;
|
|
}
|
|
|
|
VOID
|
|
SetFlushed(
|
|
VOID
|
|
)
|
|
{
|
|
_fFlushed = TRUE;
|
|
}
|
|
|
|
VOID
|
|
LockCacheEntry(
|
|
VOID
|
|
)
|
|
{
|
|
_lock.WriteLock();
|
|
}
|
|
|
|
VOID
|
|
UnlockCacheEntry(
|
|
VOID
|
|
)
|
|
{
|
|
_lock.WriteUnlock();
|
|
}
|
|
|
|
OBJECT_CACHE *
|
|
QueryCache(
|
|
VOID
|
|
) const
|
|
{
|
|
return _pObjectCache;
|
|
}
|
|
|
|
virtual
|
|
BOOL
|
|
QueryIsOkToFlushTTL(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
QueryIsOkToFlushMetadata(
|
|
WCHAR * pszPath,
|
|
DWORD cchPath
|
|
);
|
|
|
|
virtual
|
|
BOOL
|
|
QueryIsOkToFlushDirmon(
|
|
WCHAR *,
|
|
DWORD
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
virtual
|
|
CACHE_KEY *
|
|
QueryCacheKey(
|
|
VOID
|
|
) const = 0;
|
|
|
|
BOOL
|
|
CheckSignature(
|
|
VOID
|
|
) const
|
|
{
|
|
return _dwSignature == CACHE_ENTRY_SIGNATURE;
|
|
}
|
|
|
|
LIST_ENTRY _listEntry;
|
|
|
|
protected:
|
|
|
|
virtual ~CACHE_ENTRY();
|
|
|
|
private:
|
|
|
|
DWORD _dwSignature;
|
|
LONG _cRefs;
|
|
BOOL _fFlushed;
|
|
LONG _cTTL;
|
|
LONG _cConfiguredTTL;
|
|
BOOL _fCached;
|
|
CSmallSpinLock _lock;
|
|
OBJECT_CACHE * _pObjectCache;
|
|
CDirMonitorEntry * _pDirmonInvalidator;
|
|
};
|
|
|
|
class CACHE_ENTRY_HASH : public CTypedHashTable< CACHE_ENTRY_HASH,
|
|
CACHE_ENTRY,
|
|
CACHE_KEY * >
|
|
{
|
|
public:
|
|
|
|
CACHE_ENTRY_HASH() : CTypedHashTable< CACHE_ENTRY_HASH,
|
|
CACHE_ENTRY,
|
|
CACHE_KEY * >
|
|
( "CACHE_ENTRY_HASH" )
|
|
{
|
|
}
|
|
|
|
static CACHE_KEY *
|
|
ExtractKey(
|
|
const CACHE_ENTRY * pCacheEntry
|
|
)
|
|
{
|
|
return pCacheEntry->QueryCacheKey();
|
|
}
|
|
|
|
static DWORD
|
|
CalcKeyHash(
|
|
const CACHE_KEY * pCacheKey
|
|
)
|
|
{
|
|
return pCacheKey->QueryKeyHash();
|
|
}
|
|
|
|
static bool
|
|
EqualKeys(
|
|
const CACHE_KEY * pCacheKey1,
|
|
const CACHE_KEY * pCacheKey2
|
|
)
|
|
{
|
|
return pCacheKey1->QueryIsEqual( pCacheKey2 ) ? true : false;
|
|
}
|
|
|
|
static void
|
|
AddRefRecord(
|
|
CACHE_ENTRY * pCacheEntry,
|
|
int nIncr
|
|
);
|
|
|
|
private:
|
|
|
|
CACHE_ENTRY_HASH(
|
|
const CACHE_ENTRY_HASH &
|
|
);
|
|
|
|
VOID operator=(
|
|
const CACHE_ENTRY_HASH &
|
|
);
|
|
};
|
|
|
|
struct CACHE_HINT_CONFIG
|
|
{
|
|
DWORD cmsecTTL;
|
|
DWORD cmsecScavengeTime;
|
|
DWORD cmsecActivityWindow;
|
|
};
|
|
|
|
class CACHE_HINT_MANAGER;
|
|
|
|
//
|
|
// All caches derive from this abstract class
|
|
//
|
|
|
|
#define OBJECT_CACHE_SIGNATURE 'SCBO'
|
|
#define OBJECT_CACHE_SIGNATURE_FREE 'xcbo'
|
|
|
|
class OBJECT_CACHE
|
|
{
|
|
public:
|
|
|
|
W3CACHE_DLLEXP OBJECT_CACHE();
|
|
|
|
W3CACHE_DLLEXP virtual ~OBJECT_CACHE();
|
|
|
|
W3CACHE_DLLEXP
|
|
HRESULT
|
|
SetCacheConfiguration(
|
|
DWORD cmsecScavenge,
|
|
DWORD cmsecTTL,
|
|
DWORD dwSupportedInvalidation,
|
|
CACHE_HINT_CONFIG * pCacheHintConfig
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
HRESULT
|
|
FindCacheEntry(
|
|
CACHE_KEY * pCacheKey,
|
|
CACHE_ENTRY ** ppCacheEntry,
|
|
BOOL * pfShouldCache = NULL
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
HRESULT
|
|
FlushCacheEntry(
|
|
CACHE_KEY * pCacheKey
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
HRESULT
|
|
AddCacheEntry(
|
|
CACHE_ENTRY * pCacheEntry
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
HRESULT
|
|
AddDirmonInvalidator(
|
|
DIRMON_CONFIG * pDirmonConfig,
|
|
CDirMonitorEntry ** ppDME
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
VOID
|
|
CleanupCacheEntryListItems(
|
|
LIST_ENTRY * pListHead
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
VOID
|
|
UnregisterScavenger(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
FlushByTTL(
|
|
LIST_ENTRY * pListHead
|
|
);
|
|
|
|
W3CACHE_DLLEXP
|
|
VOID
|
|
FlushByRegChange(
|
|
LIST_ENTRY * pListHead
|
|
);
|
|
|
|
VOID
|
|
DoDirmonInvalidationFlush(
|
|
WCHAR * pszPath
|
|
);
|
|
|
|
VOID
|
|
DoMetadataInvalidationFlush(
|
|
WCHAR * pszMetapath
|
|
);
|
|
|
|
VOID
|
|
Clear(
|
|
VOID
|
|
)
|
|
{
|
|
_hashTable.Clear();
|
|
}
|
|
|
|
BOOL
|
|
QuerySupportsDirmonSpecific(
|
|
VOID
|
|
)
|
|
{
|
|
return !!( _dwSupportedInvalidation & CACHE_INVALIDATION_DIRMON_SPECIFIC );
|
|
}
|
|
|
|
BOOL
|
|
QuerySupportsDirmonFlush(
|
|
VOID
|
|
)
|
|
{
|
|
return !!( _dwSupportedInvalidation & CACHE_INVALIDATION_DIRMON_FLUSH );
|
|
}
|
|
|
|
BOOL
|
|
QuerySupportsMetadataFlush(
|
|
VOID
|
|
)
|
|
{
|
|
return !!( _dwSupportedInvalidation & CACHE_INVALIDATION_METADATA );
|
|
}
|
|
|
|
VOID
|
|
DoReferenceTrace(
|
|
CACHE_ENTRY * pCacheEntry,
|
|
DWORD cRefs
|
|
)
|
|
{
|
|
if ( _pTraceLog != NULL )
|
|
{
|
|
WriteRefTraceLog( _pTraceLog, cRefs, pCacheEntry );
|
|
}
|
|
}
|
|
|
|
virtual
|
|
WCHAR *
|
|
QueryName(
|
|
VOID
|
|
) const = 0;
|
|
|
|
virtual
|
|
VOID
|
|
DoDirmonInvalidationSpecific(
|
|
WCHAR *
|
|
)
|
|
{
|
|
}
|
|
|
|
static
|
|
VOID
|
|
WINAPI
|
|
ScavengerCallback(
|
|
PVOID pObjectCache,
|
|
BOOLEAN TimerOrWaitFired
|
|
);
|
|
|
|
static
|
|
LK_PREDICATE
|
|
CacheFlushByRegChange(
|
|
CACHE_ENTRY * pCacheEntry,
|
|
VOID * pvState
|
|
);
|
|
|
|
static
|
|
LK_PREDICATE
|
|
CacheFlushByTTL(
|
|
CACHE_ENTRY * pCacheEntry,
|
|
VOID * pvState
|
|
);
|
|
|
|
static
|
|
LK_PREDICATE
|
|
CacheFlushByDirmon(
|
|
CACHE_ENTRY * pCacheEntry,
|
|
VOID * pvState
|
|
);
|
|
|
|
static
|
|
LK_PREDICATE
|
|
CacheFlushByMetadata(
|
|
CACHE_ENTRY * pCacheEntry,
|
|
VOID * pvState
|
|
);
|
|
|
|
BOOL
|
|
CheckSignature(
|
|
VOID
|
|
) const
|
|
{
|
|
return _dwSignature == OBJECT_CACHE_SIGNATURE;
|
|
}
|
|
|
|
BOOL
|
|
SupportsInvalidation(
|
|
DWORD dwInvalidationType
|
|
)
|
|
{
|
|
return !!( dwInvalidationType & _dwSupportedInvalidation );
|
|
}
|
|
|
|
DWORD
|
|
QueryConfiguredTTL(
|
|
VOID
|
|
)
|
|
{
|
|
if ( _cmsecTTL == 0 || _cmsecScavengeTime == 0 )
|
|
{
|
|
return INFINITE;
|
|
}
|
|
else
|
|
{
|
|
return ( _cmsecTTL / _cmsecScavengeTime ) + 1;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
IncHits(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedIncrement( (LPLONG) &_cCacheHits );
|
|
InterlockedIncrement( (LPLONG) &_cPerfCacheHits );
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryHits(
|
|
VOID
|
|
)
|
|
{
|
|
return InterlockedExchange( (LPLONG) &_cPerfCacheHits, 0 );
|
|
}
|
|
|
|
VOID
|
|
IncMisses(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedIncrement( (LPLONG) &_cCacheMisses );
|
|
InterlockedIncrement( (LPLONG) &_cPerfCacheMisses );
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryMisses(
|
|
VOID
|
|
)
|
|
{
|
|
return InterlockedExchange( (LPLONG) &_cPerfCacheMisses, 0 );
|
|
}
|
|
|
|
VOID
|
|
IncFlushes(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedIncrement( (LPLONG) &_cCacheFlushes );
|
|
InterlockedIncrement( (LPLONG) &_cPerfCacheFlushes );
|
|
InterlockedIncrement( (LPLONG) &_cActiveFlushedEntries );
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryFlushes(
|
|
VOID
|
|
)
|
|
{
|
|
return InterlockedExchange( (LPLONG) &_cPerfCacheFlushes, 0 );
|
|
}
|
|
|
|
VOID
|
|
DecActiveFlushedEntries(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedDecrement( (LPLONG) &_cActiveFlushedEntries );
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryActiveFlushedEntries(
|
|
VOID
|
|
)
|
|
{
|
|
return _cActiveFlushedEntries;
|
|
}
|
|
|
|
VOID
|
|
IncFlushCalls(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedIncrement( (LPLONG) &_cFlushCalls );
|
|
InterlockedIncrement( (LPLONG) &_cPerfFlushCalls );
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryFlushCalls(
|
|
VOID
|
|
)
|
|
{
|
|
return InterlockedExchange( (LPLONG) &_cPerfFlushCalls, 0 );
|
|
}
|
|
|
|
VOID
|
|
IncEntriesCached(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedIncrement( (LPLONG) &_cEntriesCached );
|
|
InterlockedIncrement( (LPLONG) &_cTotalEntriesCached );
|
|
InterlockedIncrement( (LPLONG) &_cPerfTotalEntriesCached );
|
|
}
|
|
|
|
VOID
|
|
DecEntriesCached(
|
|
VOID
|
|
)
|
|
{
|
|
InterlockedDecrement( (LPLONG) &_cEntriesCached );
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryCurrentEntryCount(
|
|
VOID
|
|
) const
|
|
{
|
|
return _cEntriesCached;
|
|
}
|
|
|
|
DWORD
|
|
PerfQueryTotalEntriesCached(
|
|
VOID
|
|
) const
|
|
{
|
|
return InterlockedExchange( (LPLONG) &_cTotalEntriesCached, 0 );
|
|
}
|
|
|
|
private:
|
|
|
|
DWORD _dwSignature;
|
|
CACHE_ENTRY_HASH _hashTable;
|
|
LIST_ENTRY _listEntry;
|
|
HANDLE _hTimer;
|
|
DWORD _cmsecScavengeTime;
|
|
DWORD _cmsecTTL;
|
|
DWORD _dwSupportedInvalidation;
|
|
|
|
//
|
|
// Some stats
|
|
//
|
|
|
|
DWORD _cCacheHits;
|
|
DWORD _cCacheMisses;
|
|
DWORD _cCacheFlushes;
|
|
DWORD _cActiveFlushedEntries;
|
|
DWORD _cFlushCalls;
|
|
DWORD _cEntriesCached;
|
|
DWORD _cTotalEntriesCached;
|
|
|
|
//
|
|
// Perfmon helper stats (when debugging, ignore these values)
|
|
//
|
|
|
|
DWORD _cPerfCacheHits;
|
|
DWORD _cPerfCacheMisses;
|
|
DWORD _cPerfCacheFlushes;
|
|
DWORD _cPerfFlushCalls;
|
|
DWORD _cPerfTotalEntriesCached;
|
|
|
|
//
|
|
// Cache hint manager (if needed)
|
|
//
|
|
|
|
CACHE_HINT_MANAGER * _pHintManager;
|
|
|
|
//
|
|
// Ref tracing for all
|
|
//
|
|
|
|
PTRACE_LOG _pTraceLog;
|
|
|
|
static LIST_ENTRY sm_CacheListHead;
|
|
};
|
|
|
|
#endif
|