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.

470 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name :
  4. cachemanager.cxx
  5. Abstract:
  6. Manages a list of all the caches and handles invalidation of them
  7. Author:
  8. Bilal Alam (balam) 11-Nov-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. #define DIR_CHANGE_FILTER (FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS)
  16. CACHE_MANAGER * g_pCacheManager;
  17. CACHE_MANAGER::CACHE_MANAGER()
  18. {
  19. _pDirMonitor = NULL;
  20. ZeroMemory( &_Caches, sizeof( _Caches ) );
  21. }
  22. CACHE_MANAGER::~CACHE_MANAGER()
  23. {
  24. }
  25. HRESULT
  26. CACHE_MANAGER::Initialize(
  27. IMSAdminBase * pAdminBase
  28. )
  29. /*++
  30. Routine Description:
  31. Initialize cache manager
  32. Arguments:
  33. pAdminBase - Admin base object pointer
  34. Return Value:
  35. HRESULT
  36. --*/
  37. {
  38. //
  39. // Initialize dir monitor
  40. //
  41. DBG_ASSERT( _pDirMonitor == NULL );
  42. _pDirMonitor = new CDirMonitor;
  43. if ( _pDirMonitor == NULL )
  44. {
  45. return HRESULT_FROM_WIN32( GetLastError() );
  46. }
  47. //
  48. // Keep a pointer to the admin base object
  49. //
  50. _pAdminBase = pAdminBase;
  51. _pAdminBase->AddRef();
  52. return NO_ERROR;
  53. }
  54. VOID
  55. CACHE_MANAGER::Terminate(
  56. VOID
  57. )
  58. /*++
  59. Routine Description:
  60. Cleanup the cache manager
  61. Arguments:
  62. None
  63. Return Value:
  64. HRESULT
  65. --*/
  66. {
  67. if ( _pAdminBase != NULL )
  68. {
  69. _pAdminBase->Release();
  70. _pAdminBase = NULL;
  71. }
  72. if ( _pDirMonitor != NULL )
  73. {
  74. _pDirMonitor->Cleanup();
  75. delete _pDirMonitor;
  76. _pDirMonitor = NULL;
  77. }
  78. }
  79. HRESULT
  80. CACHE_MANAGER::AddNewCache(
  81. OBJECT_CACHE * pObjectCache
  82. )
  83. /*++
  84. Routine Description:
  85. Add new cache to be managed
  86. Arguments:
  87. pObjectCache - Object cache to add
  88. Return Value:
  89. HRESULT
  90. --*/
  91. {
  92. DWORD dwInsertPos;
  93. if ( pObjectCache == NULL )
  94. {
  95. DBG_ASSERT( FALSE );
  96. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  97. }
  98. //
  99. // First the first non-NULL entry
  100. //
  101. for ( dwInsertPos = 0; _Caches[ dwInsertPos ] != NULL; dwInsertPos++ )
  102. {
  103. }
  104. //
  105. // Add the new cache
  106. //
  107. _Caches[ dwInsertPos ] = pObjectCache;
  108. return NO_ERROR;
  109. }
  110. HRESULT
  111. CACHE_MANAGER::RemoveCache(
  112. OBJECT_CACHE * pObjectCache
  113. )
  114. /*++
  115. Routine Description:
  116. Cache to remove from list of managed caches
  117. Arguments:
  118. pObjectCache - Object cache to remove
  119. Return Value:
  120. HRESULT
  121. --*/
  122. {
  123. DWORD dwPos;
  124. BOOL fFound = FALSE;
  125. if ( pObjectCache == NULL )
  126. {
  127. DBG_ASSERT( FALSE );
  128. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  129. }
  130. //
  131. // First find the cache to remove
  132. //
  133. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  134. {
  135. if ( _Caches[ dwPos ] == pObjectCache )
  136. {
  137. memmove( _Caches + dwPos,
  138. _Caches + dwPos + 1,
  139. ( MAX_CACHE_COUNT - dwPos - 1 ) * sizeof( OBJECT_CACHE*) );
  140. fFound = TRUE;
  141. break;
  142. }
  143. }
  144. if ( !fFound )
  145. {
  146. return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  147. }
  148. return NO_ERROR;
  149. }
  150. VOID
  151. CACHE_MANAGER::FlushAllCaches(
  152. VOID
  153. )
  154. /*++
  155. Routine Description:
  156. Flush all caches
  157. Arguments:
  158. None
  159. Return Value:
  160. None
  161. --*/
  162. {
  163. DWORD dwPos;
  164. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  165. {
  166. //
  167. // Clear the cache
  168. //
  169. _Caches[ dwPos ]->Clear();
  170. //
  171. // Wait for scavengers to go away
  172. //
  173. _Caches[ dwPos ]->UnregisterScavenger();
  174. }
  175. }
  176. HRESULT
  177. CACHE_MANAGER::HandleDirMonitorInvalidation(
  178. WCHAR * pszFilePath,
  179. BOOL fFlushAll
  180. )
  181. /*++
  182. Routine Description:
  183. Invalidate any caches which are interested in dir monitor invalidation
  184. Arguments:
  185. pszFilePath - File name changed
  186. fFlushAll - Should we flush all items prefixed with pszFilePath?
  187. Return Value:
  188. HRESULT
  189. --*/
  190. {
  191. DWORD dwPos;
  192. OBJECT_CACHE * pCache;
  193. if ( pszFilePath == NULL )
  194. {
  195. DBG_ASSERT( FALSE );
  196. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  197. }
  198. //
  199. // Iterate thru all the caches which support dirmon invalidation
  200. //
  201. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  202. {
  203. pCache = _Caches[ dwPos ];
  204. //
  205. // If this cache doesn't support dirmon at all, continue
  206. //
  207. if ( !pCache->QuerySupportsDirmonSpecific() &&
  208. !pCache->QuerySupportsDirmonFlush() )
  209. {
  210. continue;
  211. }
  212. //
  213. // If this is a specific invalidation, check whether the cache
  214. // supports it. If it doesn't, but does support flush, the do a
  215. // flush instead
  216. //
  217. if ( !fFlushAll )
  218. {
  219. if ( pCache->QuerySupportsDirmonSpecific() )
  220. {
  221. pCache->DoDirmonInvalidationSpecific( pszFilePath );
  222. }
  223. else
  224. {
  225. pCache->DoDirmonInvalidationFlush( pszFilePath );
  226. }
  227. }
  228. else
  229. {
  230. pCache->DoDirmonInvalidationFlush( pszFilePath );
  231. }
  232. }
  233. return NO_ERROR;
  234. }
  235. HRESULT
  236. CACHE_MANAGER::HandleMetadataInvalidation(
  237. WCHAR * pszMetaPath
  238. )
  239. /*++
  240. Routine Description:
  241. Invalidate any caches which are interested in metadata invalidation
  242. Arguments:
  243. pszMetaPath - Metabase path which changed
  244. Return Value:
  245. HRESULT
  246. --*/
  247. {
  248. DWORD dwPos;
  249. OBJECT_CACHE * pCache;
  250. if ( pszMetaPath == NULL )
  251. {
  252. DBG_ASSERT( FALSE );
  253. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  254. }
  255. //
  256. // Iterate thru all the caches which support metadata invalidation
  257. //
  258. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  259. {
  260. pCache = _Caches[ dwPos ];
  261. if ( pCache->QuerySupportsMetadataFlush() )
  262. {
  263. pCache->DoMetadataInvalidationFlush( pszMetaPath );
  264. }
  265. }
  266. return NO_ERROR;
  267. }
  268. HRESULT
  269. CACHE_MANAGER::MonitorDirectory(
  270. DIRMON_CONFIG * pDirmonConfig,
  271. CDirMonitorEntry ** ppDME
  272. )
  273. /*++
  274. Routine Description:
  275. Monitor given directory
  276. Arguments:
  277. pDirmonConfig - Name of directory and token to impersonate with
  278. ppDME - Set to monitor entry on success
  279. Return Value:
  280. HRESULT
  281. --*/
  282. {
  283. CacheDirMonitorEntry * pDME = NULL;
  284. HRESULT hr = NO_ERROR;
  285. BOOL fRet;
  286. BOOL fImpersonated = FALSE;
  287. if ( ppDME == NULL ||
  288. pDirmonConfig == NULL )
  289. {
  290. DBG_ASSERT( FALSE );
  291. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  292. }
  293. //
  294. // First check if we are already monitoring this directory
  295. //
  296. pDME = (CacheDirMonitorEntry*) _pDirMonitor->FindEntry( pDirmonConfig->pszDirPath );
  297. if ( pDME == NULL )
  298. {
  299. //
  300. // It is not. We'll have to start monitoring
  301. //
  302. pDME = new CacheDirMonitorEntry;
  303. if ( pDME == NULL )
  304. {
  305. return HRESULT_FROM_WIN32( GetLastError() );
  306. }
  307. pDME->AddRef();
  308. if ( pDirmonConfig->hToken != NULL )
  309. {
  310. fRet = SetThreadToken( NULL, pDirmonConfig->hToken );
  311. if ( !fRet )
  312. {
  313. hr = HRESULT_FROM_WIN32( GetLastError() );
  314. pDME->Release();
  315. return hr;
  316. }
  317. fImpersonated = TRUE;
  318. }
  319. fRet = _pDirMonitor->Monitor( pDME,
  320. pDirmonConfig->pszDirPath,
  321. TRUE,
  322. DIR_CHANGE_FILTER );
  323. if ( fImpersonated )
  324. {
  325. RevertToSelf();
  326. fImpersonated = FALSE;
  327. }
  328. if ( !fRet )
  329. {
  330. //
  331. // Note: It is OK if we can't monitor the directory. The error
  332. // will trickle up and the caller will not cache the entry
  333. //
  334. hr = HRESULT_FROM_WIN32( GetLastError() );
  335. pDME->Release();
  336. pDME = NULL;
  337. return hr;
  338. }
  339. }
  340. DBG_ASSERT( pDME != NULL );
  341. *ppDME = (CDirMonitorEntry*) pDME;
  342. return NO_ERROR;
  343. }