/*----------------------------------------------------------------------------- Microsoft Denali Microsoft Confidential Copyright 1996 Microsoft Corporation. All Rights Reserved. Component: Template Cache Manager File: CacheMgr.h Owner: DGottner Template cache manager definition -----------------------------------------------------------------------------*/ #ifndef _CACHEMGR_H #define _CACHEMGR_H // Includes ------------------------------------------------------------------- #include "Template.h" #include "lkrhash.h" #include "aspdmon.h" class CHitObj; #define MAX_CLEANUP_THREADS 32 // Types and Constants -------------------------------------------------------- #define CTEMPLATEBUCKETS 1021 // size of CTemplate hash table #define CINCFILEBUCKETS 89 // size of CIncFile hash table /* **************************************************************************** Class: CTemplateCacheManager Synopsis: A CCacheManager that manages a cache of Denali templates */ class CTemplateCacheManager { private: class CTemplateHashTable; friend class CTemplateHashTable; // since there is only one CTemplateCacheManager object ever available, namely // g_TemplateCache, this is safe to call these two members static. static BOOL m_fFailedToInitPersistCache; static char m_szPersistCacheDir[MAX_PATH]; HANDLE m_hOnInitCleanupThread; HANDLE m_hCleanupThreads[MAX_CLEANUP_THREADS]; DWORD m_cCleanupThreads; // The type for a hash table of CTemplates keyed on instance id + name // // since we provide new methods, make parent methods uncallable class CTemplateHashTable : private CTypedHashTable { private: CDblLink m_listMemoryTemplates; CDblLink m_listPersistTemplates; DWORD m_dwInMemoryTemplates; DWORD m_dwPersistedTemplates; public: // export some methods DWORD InMemoryTemplates() { return m_dwInMemoryTemplates; }; //CTypedHashTable::Size; // test to see if the template can be persisted... BOOL CanPersistTemplate(CTemplate *pTemplate); // trim some number of templates from the persist cache... BOOL TrimPersistCache(DWORD dwTrimCount); VOID ScavengePersistCache(); // new methods CTemplateHashTable() : CTypedHashTable("ASP Template Cache") { m_dwInMemoryTemplates = 0; m_dwPersistedTemplates = 0; } static const CTemplateKey *ExtractKey(const CTemplate *pTemplate) { return pTemplate->ExtractHashKey(); } // NOTE: We don't hash the pTemplateKey->nInstanceID because it can be wildcarded. // if we were to include in the hash, the wildcard won't hash to the same key // static DWORD CalcKeyHash(const CTemplateKey *pTemplateKey) { return HashString(pTemplateKey->szPathTranslated, 0); } static bool EqualKeys(const CTemplateKey *pKey1, const CTemplateKey *pKey2) { return (_tcscmp(pKey1->szPathTranslated, pKey2->szPathTranslated) == 0) && (pKey1->dwInstanceID == pKey2->dwInstanceID || pKey1->dwInstanceID == MATCH_ALL_INSTANCE_IDS || pKey2->dwInstanceID == MATCH_ALL_INSTANCE_IDS); } // NOTE: In theory, the LKHash can help solve our ref. counting problems, by // automatic addref/release. However, since prior code uses non-refcounting // data structure, it's safer to leave old code alaone in this respect, and // no-op the AddRefRecord method. // static void AddRefRecord(CTemplate *pTemplate, int nIncr) { } // Provide new methods to automatically manage the LRU ordering. // NOTE: We used to override the methods but ran into inconsistencies (bugs?) // in VC compiler. Sometimes it would call derived & sometimes the base class // given the same arguemt datatypes. // LK_RETCODE InsertTemplate(CTemplate *pTemplate); LK_RETCODE RemoveTemplate(CTemplate *pTemplate, BOOL fPersist = FALSE, BOOL fScavengePersistCache = TRUE); // NOTE: Template signature also requires const ptr to const data LK_RETCODE FindTemplate(const CTemplateKey &rTemplateKey, CTemplate **ppTemplate, BOOL* pfNeedsCheck = NULL); // accessor methods for hidden LRU cache bool FMemoryTemplatesIsEmpty() const { return m_listMemoryTemplates.FIsEmpty(); } // you CANNOT compare LRU nodes to NULL to know if you are at the end // of the list! Instead use this member. // BOOL FMemoryTemplatesDblLinkAtEnd(CDblLink *pElem) { pElem->AssertValid(); return pElem == &m_listMemoryTemplates; } CDblLink *MemoryTemplatesBegin() // return pointer to last referenced item { return m_listMemoryTemplates.PNext(); } CDblLink *MemoryTemplatesEnd() // return pointer to least recently accessed item { return m_listMemoryTemplates.PPrev(); } // accessor methods for hidden LRU cache bool FPersistTemplatesIsEmpty() const { return m_listPersistTemplates.FIsEmpty(); } // you CANNOT compare LRU nodes to NULL to know if you are at the end // of the list! Instead use this member. // BOOL FPersistTemplatesDblLinkAtEnd(CDblLink *pElem) { pElem->AssertValid(); return pElem == &m_listPersistTemplates; } CDblLink *PersistTemplatesBegin() // return pointer to last referenced item { return m_listPersistTemplates.PNext(); } CDblLink *PersistTemplatesEnd() // return pointer to least recently accessed item { return m_listPersistTemplates.PPrev(); } }; CRITICAL_SECTION m_csUpdate; // CS for updating the data structures CTemplateHashTable *m_pHashTemplates; // the cache data structure DWORD m_dwTemplateCacheTag; // Cache Tag to for cache consistency verification // Initialize the persistant template cache BOOL InitPersistCache(CIsapiReqInfo *pIReq); // static methods primarily used from a seperate thread to flush // the template cache out of band from the FCN thread notification. static void FlushHashTable(CTemplateHashTable *pTable); static DWORD __stdcall FlushHashTableThread(VOID *pArg); // Spawned at FirstInit to cleanup leftover old cache directories static DWORD OnInitCleanup(VOID *p); public: CTemplateCacheManager(); ~CTemplateCacheManager(); inline void LockTemplateCache() { EnterCriticalSection(&m_csUpdate); } inline void UnLockTemplateCache() { LeaveCriticalSection(&m_csUpdate); } HRESULT Init(); HRESULT UnInit(); DWORD GetCacheTag() { return m_dwTemplateCacheTag;} HRESULT FirstHitInit(CIsapiReqInfo *pIReq) { InitPersistCache(pIReq); return S_OK; } // Find in cache (don't load) -- for look-aheads ///// HRESULT FindCached(const TCHAR *szFile, DWORD dwInstanceID, CTemplate **ppTemplate); // Get a template from the cache, or load it into cache ///// HRESULT Load(BOOL fRunGlobalAsp, const TCHAR *szFile, DWORD dwInstanceID, CHitObj *pHitObj, CTemplate **ppTemplate, BOOL *pfTemplateInCache); // Remove a template from the cache // for backward compatibility, "nInstanceID" can be omitted, in which case all instance ID // templates are flushed. ///// void Flush(const TCHAR *szFile, DWORD dwInstanceID); // Remove templates from the cache that have a common prefix // Instance ID is ignored. ///// void FlushFiles(const TCHAR *szFilePrefix); // Remove all templates from the cache ///// //void FlushAll(VOID); void FlushAll(BOOL fDoLazyFlush = FALSE); // Add all templates that form an application to the debugger's list of // running documents ///// void AddApplicationToDebuggerUI(CAppln *pAppln); // Remove all templates that form an application from the debugger's list of // running documents ///// void RemoveApplicationFromDebuggerUI(CAppln *pAppln); // Get directory change notification on directories used by template BOOL RegisterTemplateForChangeNotification(CTemplate *pTemplate, CAppln *pApplication); // Get directory change notification for applications BOOL RegisterApplicationForChangeNotification(CTemplate *pTemplate, CAppln *pApplication); // Stop getting change notification for changes to templates in the cache. BOOL ShutdownCacheChangeNotification(); }; /* **************************************************************************** Class: CIncFileMap Synopsis: A database mapping template include files to a list of their users */ class CIncFileMap { CRITICAL_SECTION m_csUpdate; // CS for updating the data structures CHashTable m_mpszIncFile; // the cache data structure public: CIncFileMap(); ~CIncFileMap(); inline void LockIncFileCache() { EnterCriticalSection(&m_csUpdate); } inline void UnLockIncFileCache() { LeaveCriticalSection(&m_csUpdate); } HRESULT Init(); HRESULT UnInit(); HRESULT GetIncFile(const TCHAR *szIncFile, CIncFile **ppIncFile); void Flush(const TCHAR *szIncFile); void FlushFiles(const TCHAR *szIncFilePrefix); }; /* **************************************************************************** Non-class support functions */ BOOL FFileChangedSinceCached(const TCHAR *szFile, HANDLE hFile, FILETIME& ftPrevWriteTime); // Globals -------------------------------------------------------------------- extern CTemplateCacheManager g_TemplateCache; extern CIncFileMap g_IncFileMap; inline void LockTemplateAndIncFileCaches() { g_TemplateCache.LockTemplateCache(); g_IncFileMap.LockIncFileCache(); } inline void UnLockTemplateAndIncFileCaches() { g_TemplateCache.UnLockTemplateCache(); g_IncFileMap.UnLockIncFileCache(); } // Prototypes ----------------------------------------------------------------- #endif // _CACHEMGR_H