Leaked source code of windows server 2003
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

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