Source code of Windows XP (NT5)
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.

606 lines
11 KiB

  1. #ifndef _USERCACHE_HXX_
  2. #define _USERCACHE_HXX_
  3. #include <lkrhash.h>
  4. #include <dirmon.h>
  5. #include <reftrace.h>
  6. #define CACHE_INVALIDATION_DIRMON_SPECIFIC 0x1
  7. #define CACHE_INVALIDATION_DIRMON_FLUSH 0x2
  8. #define CACHE_INVALIDATION_METADATA 0x4
  9. //
  10. // Configuration for dir monitoring
  11. //
  12. struct DIRMON_CONFIG
  13. {
  14. HANDLE hToken;
  15. WCHAR * pszDirPath;
  16. };
  17. //
  18. // Key used to lookup any of the caches
  19. //
  20. class CACHE_KEY
  21. {
  22. public:
  23. CACHE_KEY()
  24. {
  25. }
  26. virtual ~CACHE_KEY()
  27. {
  28. }
  29. virtual
  30. WCHAR *
  31. QueryHintKey(
  32. VOID
  33. )
  34. {
  35. return NULL;
  36. }
  37. virtual
  38. DWORD
  39. QueryKeyHash(
  40. VOID
  41. ) const = 0;
  42. virtual
  43. BOOL
  44. QueryIsEqual(
  45. const CACHE_KEY * pCacheCompareKey
  46. ) const = 0;
  47. };
  48. class OBJECT_CACHE;
  49. #define CACHE_ENTRY_SIGNATURE 'STEC'
  50. #define CACHE_ENTRY_SIGNATURE_FREE 'xtec'
  51. class dllexp CACHE_ENTRY
  52. {
  53. public:
  54. CACHE_ENTRY( OBJECT_CACHE * pObjectCache );
  55. VOID
  56. ReferenceCacheEntry(
  57. VOID
  58. );
  59. VOID
  60. DereferenceCacheEntry(
  61. VOID
  62. );
  63. virtual
  64. STRU *
  65. QueryMetadataPath(
  66. VOID
  67. )
  68. {
  69. return NULL;
  70. }
  71. HRESULT
  72. AddDirmonInvalidator(
  73. DIRMON_CONFIG * pDirmonConfig
  74. );
  75. BOOL
  76. QueryIsFlushed(
  77. VOID
  78. ) const
  79. {
  80. return _fFlushed;
  81. }
  82. BOOL
  83. Checkout(
  84. VOID
  85. );
  86. VOID
  87. SetCached(
  88. BOOL fCached
  89. )
  90. {
  91. _fCached = fCached;
  92. }
  93. BOOL
  94. QueryCached(
  95. VOID
  96. ) const
  97. {
  98. return _fCached;
  99. }
  100. VOID
  101. SetFlushed(
  102. VOID
  103. )
  104. {
  105. _fFlushed = TRUE;
  106. }
  107. VOID
  108. LockCacheEntry(
  109. VOID
  110. )
  111. {
  112. _lock.WriteLock();
  113. }
  114. VOID
  115. UnlockCacheEntry(
  116. VOID
  117. )
  118. {
  119. _lock.WriteUnlock();
  120. }
  121. OBJECT_CACHE *
  122. QueryCache(
  123. VOID
  124. ) const
  125. {
  126. return _pObjectCache;
  127. }
  128. virtual
  129. BOOL
  130. QueryIsOkToFlushTTL(
  131. VOID
  132. );
  133. BOOL
  134. QueryIsOkToFlushMetadata(
  135. WCHAR * pszPath,
  136. DWORD cchPath
  137. );
  138. virtual
  139. BOOL
  140. QueryIsOkToFlushDirmon(
  141. WCHAR * pszPath,
  142. DWORD cchPath
  143. )
  144. {
  145. return TRUE;
  146. }
  147. virtual
  148. CACHE_KEY *
  149. QueryCacheKey(
  150. VOID
  151. ) const = 0;
  152. BOOL
  153. CheckSignature(
  154. VOID
  155. ) const
  156. {
  157. return _dwSignature == CACHE_ENTRY_SIGNATURE;
  158. }
  159. protected:
  160. virtual ~CACHE_ENTRY();
  161. private:
  162. DWORD _dwSignature;
  163. LONG _cRefs;
  164. BOOL _fFlushed;
  165. LONG _cTTL;
  166. LONG _cConfiguredTTL;
  167. BOOL _fCached;
  168. CSmallSpinLock _lock;
  169. OBJECT_CACHE * _pObjectCache;
  170. CDirMonitorEntry * _pDirmonInvalidator;
  171. };
  172. class CACHE_ENTRY_HASH : public CTypedHashTable< CACHE_ENTRY_HASH,
  173. CACHE_ENTRY,
  174. CACHE_KEY * >
  175. {
  176. public:
  177. CACHE_ENTRY_HASH() : CTypedHashTable< CACHE_ENTRY_HASH,
  178. CACHE_ENTRY,
  179. CACHE_KEY * >
  180. ( "CACHE_ENTRY_HASH" )
  181. {
  182. }
  183. static CACHE_KEY *
  184. ExtractKey(
  185. const CACHE_ENTRY * pCacheEntry
  186. )
  187. {
  188. return pCacheEntry->QueryCacheKey();
  189. }
  190. static DWORD
  191. CalcKeyHash(
  192. const CACHE_KEY * pCacheKey
  193. )
  194. {
  195. return pCacheKey->QueryKeyHash();
  196. }
  197. static bool
  198. EqualKeys(
  199. const CACHE_KEY * pCacheKey1,
  200. const CACHE_KEY * pCacheKey2
  201. )
  202. {
  203. return pCacheKey1->QueryIsEqual( pCacheKey2 ) ? true : false;
  204. }
  205. static void
  206. AddRefRecord(
  207. CACHE_ENTRY * pCacheEntry,
  208. int nIncr
  209. );
  210. };
  211. struct CACHE_HINT_CONFIG
  212. {
  213. DWORD cmsecTTL;
  214. DWORD cmsecScavengeTime;
  215. DWORD cmsecActivityWindow;
  216. };
  217. class CACHE_HINT_MANAGER;
  218. //
  219. // All caches derive from this abstract class
  220. //
  221. #define OBJECT_CACHE_SIGNATURE 'SCBO'
  222. #define OBJECT_CACHE_SIGNATURE_FREE 'xcbo'
  223. class OBJECT_CACHE
  224. {
  225. public:
  226. dllexp OBJECT_CACHE();
  227. dllexp virtual ~OBJECT_CACHE();
  228. dllexp
  229. HRESULT
  230. SetCacheConfiguration(
  231. DWORD cmsecScavenge,
  232. DWORD cmsecTTL,
  233. DWORD dwSupportedInvalidation,
  234. CACHE_HINT_CONFIG * pCacheHintConfig
  235. );
  236. dllexp
  237. HRESULT
  238. FindCacheEntry(
  239. CACHE_KEY * pCacheKey,
  240. CACHE_ENTRY ** ppCacheEntry,
  241. BOOL * pfShouldCache = NULL
  242. );
  243. dllexp
  244. HRESULT
  245. FlushCacheEntry(
  246. CACHE_KEY * pCacheKey
  247. );
  248. dllexp
  249. HRESULT
  250. AddCacheEntry(
  251. CACHE_ENTRY * pCacheEntry
  252. );
  253. dllexp
  254. HRESULT
  255. AddDirmonInvalidator(
  256. DIRMON_CONFIG * pDirmonConfig,
  257. CDirMonitorEntry ** ppDME
  258. );
  259. VOID
  260. FlushByTTL(
  261. VOID
  262. );
  263. VOID
  264. DoDirmonInvalidationFlush(
  265. WCHAR * pszPath
  266. );
  267. VOID
  268. DoMetadataInvalidationFlush(
  269. WCHAR * pszMetapath
  270. );
  271. VOID
  272. Clear(
  273. VOID
  274. )
  275. {
  276. _hashTable.Clear();
  277. }
  278. BOOL
  279. QuerySupportsDirmonSpecific(
  280. VOID
  281. )
  282. {
  283. return !!( _dwSupportedInvalidation & CACHE_INVALIDATION_DIRMON_SPECIFIC );
  284. }
  285. BOOL
  286. QuerySupportsDirmonFlush(
  287. VOID
  288. )
  289. {
  290. return !!( _dwSupportedInvalidation & CACHE_INVALIDATION_DIRMON_FLUSH );
  291. }
  292. BOOL
  293. QuerySupportsMetadataFlush(
  294. VOID
  295. )
  296. {
  297. return !!( _dwSupportedInvalidation & CACHE_INVALIDATION_METADATA );
  298. }
  299. VOID
  300. DoReferenceTrace(
  301. CACHE_ENTRY * pCacheEntry,
  302. DWORD cRefs
  303. )
  304. {
  305. if ( _pTraceLog != NULL )
  306. {
  307. WriteRefTraceLog( _pTraceLog, cRefs, pCacheEntry );
  308. }
  309. }
  310. virtual
  311. WCHAR *
  312. QueryName(
  313. VOID
  314. ) const = 0;
  315. virtual
  316. VOID
  317. DoDirmonInvalidationSpecific(
  318. WCHAR * pszPath
  319. )
  320. {
  321. }
  322. static
  323. VOID
  324. WINAPI
  325. ScavengerCallback(
  326. PVOID pObjectCache,
  327. BOOLEAN TimerOrWaitFired
  328. );
  329. static
  330. LK_PREDICATE
  331. CacheFlushByTTL(
  332. CACHE_ENTRY * pCacheEntry,
  333. VOID * pvState
  334. );
  335. static
  336. LK_PREDICATE
  337. CacheFlushByDirmon(
  338. CACHE_ENTRY * pCacheEntry,
  339. VOID * pvState
  340. );
  341. static
  342. LK_PREDICATE
  343. CacheFlushByMetadata(
  344. CACHE_ENTRY * pCacheEntry,
  345. VOID * pvState
  346. );
  347. BOOL
  348. CheckSignature(
  349. VOID
  350. ) const
  351. {
  352. return _dwSignature == OBJECT_CACHE_SIGNATURE;
  353. }
  354. BOOL
  355. SupportsInvalidation(
  356. DWORD dwInvalidationType
  357. )
  358. {
  359. return !!( dwInvalidationType & _dwSupportedInvalidation );
  360. }
  361. DWORD
  362. QueryConfiguredTTL(
  363. VOID
  364. )
  365. {
  366. return ( _cmsecTTL / _cmsecScavengeTime ) + 1;
  367. }
  368. VOID
  369. IncHits(
  370. VOID
  371. )
  372. {
  373. InterlockedIncrement( (LPLONG) &_cCacheHits );
  374. InterlockedIncrement( (LPLONG) &_cPerfCacheHits );
  375. }
  376. DWORD
  377. PerfQueryHits(
  378. VOID
  379. )
  380. {
  381. return InterlockedExchange( (LPLONG) &_cPerfCacheHits, 0 );
  382. }
  383. VOID
  384. IncMisses(
  385. VOID
  386. )
  387. {
  388. InterlockedIncrement( (LPLONG) &_cCacheMisses );
  389. InterlockedIncrement( (LPLONG) &_cPerfCacheMisses );
  390. }
  391. DWORD
  392. PerfQueryMisses(
  393. VOID
  394. )
  395. {
  396. return InterlockedExchange( (LPLONG) &_cPerfCacheMisses, 0 );
  397. }
  398. VOID
  399. IncFlushes(
  400. VOID
  401. )
  402. {
  403. InterlockedIncrement( (LPLONG) &_cCacheFlushes );
  404. InterlockedIncrement( (LPLONG) &_cPerfCacheFlushes );
  405. InterlockedIncrement( (LPLONG) &_cActiveFlushedEntries );
  406. }
  407. DWORD
  408. PerfQueryFlushes(
  409. VOID
  410. )
  411. {
  412. return InterlockedExchange( (LPLONG) &_cPerfCacheFlushes, 0 );
  413. }
  414. VOID
  415. DecActiveFlushedEntries(
  416. VOID
  417. )
  418. {
  419. InterlockedDecrement( (LPLONG) &_cActiveFlushedEntries );
  420. }
  421. DWORD
  422. PerfQueryActiveFlushedEntries(
  423. VOID
  424. )
  425. {
  426. return _cActiveFlushedEntries;
  427. }
  428. VOID
  429. IncFlushCalls(
  430. VOID
  431. )
  432. {
  433. InterlockedIncrement( (LPLONG) &_cFlushCalls );
  434. InterlockedIncrement( (LPLONG) &_cPerfFlushCalls );
  435. }
  436. DWORD
  437. PerfQueryFlushCalls(
  438. VOID
  439. )
  440. {
  441. return InterlockedExchange( (LPLONG) &_cPerfFlushCalls, 0 );
  442. }
  443. VOID
  444. IncEntriesCached(
  445. VOID
  446. )
  447. {
  448. InterlockedIncrement( (LPLONG) &_cEntriesCached );
  449. InterlockedIncrement( (LPLONG) &_cTotalEntriesCached );
  450. InterlockedIncrement( (LPLONG) &_cPerfTotalEntriesCached );
  451. }
  452. VOID
  453. DecEntriesCached(
  454. VOID
  455. )
  456. {
  457. InterlockedDecrement( (LPLONG) &_cEntriesCached );
  458. }
  459. DWORD
  460. PerfQueryCurrentEntryCount(
  461. VOID
  462. ) const
  463. {
  464. return _cEntriesCached;
  465. }
  466. DWORD
  467. PerfQueryTotalEntriesCached(
  468. VOID
  469. ) const
  470. {
  471. return InterlockedExchange( (LPLONG) &_cTotalEntriesCached, 0 );
  472. }
  473. private:
  474. DWORD _dwSignature;
  475. CACHE_ENTRY_HASH _hashTable;
  476. LIST_ENTRY _listEntry;
  477. HANDLE _hTimer;
  478. DWORD _cmsecScavengeTime;
  479. DWORD _cmsecTTL;
  480. DWORD _dwSupportedInvalidation;
  481. //
  482. // Some stats
  483. //
  484. DWORD _cCacheHits;
  485. DWORD _cCacheMisses;
  486. DWORD _cCacheFlushes;
  487. DWORD _cActiveFlushedEntries;
  488. DWORD _cFlushCalls;
  489. DWORD _cEntriesCached;
  490. DWORD _cTotalEntriesCached;
  491. //
  492. // Perfmon helper stats (when debugging, ignore these values)
  493. //
  494. DWORD _cPerfCacheHits;
  495. DWORD _cPerfCacheMisses;
  496. DWORD _cPerfCacheFlushes;
  497. DWORD _cPerfFlushCalls;
  498. DWORD _cPerfTotalEntriesCached;
  499. //
  500. // Cache hint manager (if needed)
  501. //
  502. CACHE_HINT_MANAGER * _pHintManager;
  503. //
  504. // Ref tracing for all
  505. //
  506. PTRACE_LOG _pTraceLog;
  507. static LIST_ENTRY sm_CacheListHead;
  508. };
  509. #endif