/*++ Copyright (C) 2000-2001 Microsoft Corporation --*/ #ifndef __WMI_A51__HIECACHE__H_ #define __WMI_A51__HIECACHE__H_ // // NOTE: it is critical that things be marked in the cache while the repository // lock is held! Otherwise, invalidation/completion logic will break // #include #include #include #include "a51tools.h" class wcscless : public binary_function { public: bool operator()(const LPCWSTR& wcs1, const LPCWSTR& wcs2) const {return wcscmp(wcs1, wcs2) < 0;} }; class CClassRecord { protected: long m_lRef; LPWSTR m_wszClassName; WCHAR m_wszHash[MAX_HASH_LEN+1]; _IWmiObject* m_pClassDef; DWORD m_dwClassDefSize; CClassRecord* m_pParent; bool m_bIsKeyed; CPointerArray m_apChildren; bool m_bTreeComplete; bool m_bChildrenComplete; LONGLONG m_lLastChildInvalidationIndex; DWORD m_dwLastUsed; CClassRecord* m_pMoreRecentlyUsed; CClassRecord* m_pLessRecentlyUsed; int m_nStatus; __int64 m_nClassDefCachedTime; bool m_bRead; public: CClassRecord(LPCWSTR wszClassName, LPCWSTR wszHash); ~CClassRecord(); void AddRef() {InterlockedIncrement(&m_lRef);} void Release() {if(InterlockedDecrement(&m_lRef) == 0) delete this;} HRESULT EnsureChild(CClassRecord* pChild); HRESULT RemoveChild(CClassRecord* pChild); friend class CHierarchyCache; friend class CForestCache; }; class CForestCache; class CHierarchyCache { protected: long m_lRef; typedef std::map TMap; typedef TMap::iterator TIterator; CForestCache* m_pForest; CCritSec m_cs; TMap m_map; LONGLONG m_lNextInvalidationIndex; HRESULT m_hresError; public: CHierarchyCache(CForestCache* pForest); ~CHierarchyCache(); long AddRef() {return InterlockedIncrement(&m_lRef);} long Release() {return InterlockedDecrement(&m_lRef);} HRESULT AssertClass(_IWmiObject* pClass, LPCWSTR wszClassName, bool bClone, __int64 nTime); HRESULT InvalidateClass(LPCWSTR wszClassName); HRESULT DoneWithChildren(LPCWSTR wszClassName, bool bRecursive, LONGLONG lStartingIndex, CClassRecord* pRecord = NULL); HRESULT DoneWithChildrenByHash(LPCWSTR wszHash, bool bRecursive, LONGLONG lStartIndex); LONGLONG GetLastInvalidationIndex() {return m_lNextInvalidationIndex-1;} void SetError(HRESULT hresError); HRESULT GetError(); public: RELEASE_ME _IWmiObject* GetClassDef(LPCWSTR wszClassName, bool bClone, __int64* pnTime = NULL, bool* pbRead = NULL); HRESULT EnumChildren(LPCWSTR wszClassName, bool bRecursive, CWStringArray& awsChildren); HRESULT EnumChildKeysByKey(LPCWSTR wszClassKey, CWStringArray& awsChildKeys); HRESULT GetKeyRootByKey(LPCWSTR wszKey, TEMPFREE_ME LPWSTR* pwszKeyRoot); HRESULT GetKeyRoot(LPCWSTR wszClassName, TEMPFREE_ME LPWSTR* pwszKeyRoot); HRESULT GetKeyRootByRecord(CClassRecord* pRecord, TEMPFREE_ME LPWSTR* pwszKeyRoot); DELETE_ME LPWSTR GetParent(LPCWSTR wszClassName); RELEASE_ME _IWmiObject* GetClassDefByHash(LPCWSTR wszHash, bool bClone, __int64* pnTime = NULL, bool* pbRead = NULL); protected: INTERNAL CClassRecord* FindClass(LPCWSTR wszClassName); INTERNAL CClassRecord* FindClassByKey(LPCWSTR wszKey); RELEASE_ME _IWmiObject* GetClassDefFromRecord(CClassRecord* pRecord, bool bClone); INTERNAL CClassRecord* EnsureClass(LPCWSTR wszClassName); HRESULT EnumChildrenInternal(CClassRecord* pRecord, bool bRecursive, CWStringArray& awsChildren); HRESULT InvalidateClassInternal(CClassRecord* pRecord); HRESULT DoneWithChildrenByRecord(CClassRecord* pRecord, bool bRecursive, LONGLONG lStartIndex); static void MakeKey(LPCWSTR wszClassName, LPWSTR wszKey); }; class CForestCache { protected: CCritSec m_cs; CClassRecord* m_pMostRecentlyUsed; CClassRecord* m_pLeastRecentlyUsed; DWORD m_dwMaxMemory; DWORD m_dwMaxAgeMs; DWORD m_dwTotalMemory; HANDLE m_hTimerQueue; HANDLE m_hCurrentTimer; HANDLE m_hCompletionEvent; typedef std::map TMap; typedef TMap::iterator TIterator; TMap m_map; long m_lRef; public: CForestCache() : m_dwMaxMemory(0xFFFFFFFF), m_dwTotalMemory(0), m_pMostRecentlyUsed(NULL), m_pLeastRecentlyUsed(NULL), m_dwMaxAgeMs(0), m_hTimerQueue(NULL), m_hCurrentTimer(NULL), m_hCompletionEvent(NULL), m_lRef(0) { } ~CForestCache(); HRESULT Initialize(); void SetMaxMemory(DWORD dwMaxMemory, DWORD dwMaxAgeMs); bool MakeRoom(DWORD dwSize); bool Flush(); void MakeMostRecentlyUsed(CClassRecord* pRecord); void Add(CClassRecord* pRecord); void RemoveRecord(CClassRecord* pRecord); public: CHierarchyCache* GetNamespaceCache(LPCWSTR wszNamespace); void ReleaseNamespaceCache(LPCWSTR wszNamespace, CHierarchyCache* pCache); long AddRef() {return InterlockedIncrement(&m_lRef);} long Release() {long lRet = InterlockedDecrement(&m_lRef); if (!lRet) delete this; return lRet;} protected: CCritSec* GetLock() {return &m_cs;} bool Test(); void Untie(CClassRecord* pRecord); void TimerCallback(); static void staticTimerCallback(VOID* pParam, BOOLEAN); friend class CHierarchyCache; }; #endif