/*++ 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 #include #include "a51tools.h" class wcscless : public binary_function { public: bool operator()(const LPCWSTR& wcs1, const LPCWSTR& wcs2) const {return wcscmp(wcs1, wcs2) < 0;} }; typedef enum {e_KeynessUnknown, e_Keyed, e_NotKeyed} EKeyNess; class CClassRecord { protected: static long s_nRecords; long m_lRef; CClassRecord* m_pMoreRecentlyUsed; CClassRecord* m_pLessRecentlyUsed; LPWSTR m_wszClassName; WCHAR m_wszHash[MAX_HASH_LEN+1]; _IWmiObject* m_pClassDef; DWORD m_dwClassDefSize; CClassRecord* m_pParent; EKeyNess m_eIsKeyed; CPointerArray m_apChildren; bool m_bTreeComplete; bool m_bChildrenComplete; LONGLONG m_lLastChildInvalidationIndex; DWORD m_dwLastUsed; int m_nStatus; __int64 m_nClassDefCachedTime; bool m_bRead; bool m_bSystemClass; public: CClassRecord(LPCWSTR wszClassName, LPCWSTR wszHash); virtual ~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: static long s_nCaches; long m_lRef; typedef std::map > TMap; typedef TMap::iterator TIterator; CForestCache* m_pForest; TMap m_map; LONGLONG m_lNextInvalidationIndex; HRESULT m_hresError; public: CHierarchyCache(CForestCache* pForest); virtual ~CHierarchyCache(); long AddRef() {return InterlockedIncrement(&m_lRef);} long Release() { long lRet = InterlockedDecrement(&m_lRef); if (0 == lRet) delete this; return lRet; } HRESULT AssertClass(_IWmiObject* pClass, LPCWSTR wszClassName, bool bClone, __int64 nTime, bool bSystemClass); 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(); void Clear(); 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, bool *pbSystemClass = 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: CriticalSection m_cs; CClassRecord* m_pMostRecentlyUsed; CClassRecord* m_pLeastRecentlyUsed; DWORD m_dwMaxMemory; DWORD m_dwMaxAgeMs; DWORD m_dwTotalMemory; HANDLE m_hCurrentTimer; long m_lRef; BOOL m_bInit; typedef std::map > TMap; typedef TMap::iterator TIterator; TMap m_map; bool m_bAssertedInTransaction; public: CForestCache() : m_dwMaxMemory(0xFFFFFFFF), m_dwTotalMemory(0), m_pMostRecentlyUsed(NULL), m_pLeastRecentlyUsed(NULL), m_dwMaxAgeMs(0), m_hCurrentTimer(NULL), m_lRef(1), m_bInit(FALSE), m_bAssertedInTransaction(false), m_cs(THROW_LOCK,0x80000000 | 400L) { } ~CForestCache(); HRESULT Initialize(); HRESULT Deinitialize(); void SetMaxMemory(DWORD dwMaxMemory, DWORD dwMaxAgeMs); bool MakeRoom(DWORD dwSize); bool Flush(); void MakeMostRecentlyUsed(CClassRecord* pRecord); void Add(CClassRecord* pRecord); void RemoveRecord(CClassRecord* pRecord); void BeginTransaction(); bool MarkAsserted(CHierarchyCache* pCache, LPCWSTR wszClassName); void CommitTransaction(); void AbortTransaction(); 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;} void Clear(); protected: CriticalSection & GetLock() {return m_cs;} bool Test(); void Untie(CClassRecord* pRecord); void TimerCallback(); static void staticTimerCallback(VOID* pParam, BOOLEAN); friend class CHierarchyCache; }; #endif