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.

466 lines
8.4 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. delete _pDirMonitor;
  75. _pDirMonitor = NULL;
  76. }
  77. }
  78. HRESULT
  79. CACHE_MANAGER::AddNewCache(
  80. OBJECT_CACHE * pObjectCache
  81. )
  82. /*++
  83. Routine Description:
  84. Add new cache to be managed
  85. Arguments:
  86. pObjectCache - Object cache to add
  87. Return Value:
  88. HRESULT
  89. --*/
  90. {
  91. DWORD dwInsertPos;
  92. if ( pObjectCache == NULL )
  93. {
  94. DBG_ASSERT( FALSE );
  95. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  96. }
  97. //
  98. // First the first non-NULL entry
  99. //
  100. for ( dwInsertPos = 0; _Caches[ dwInsertPos ] != NULL; dwInsertPos++ )
  101. {
  102. }
  103. //
  104. // Add the new cache
  105. //
  106. _Caches[ dwInsertPos ] = pObjectCache;
  107. return NO_ERROR;
  108. }
  109. HRESULT
  110. CACHE_MANAGER::RemoveCache(
  111. OBJECT_CACHE * pObjectCache
  112. )
  113. /*++
  114. Routine Description:
  115. Cache to remove from list of managed caches
  116. Arguments:
  117. pObjectCache - Object cache to remove
  118. Return Value:
  119. HRESULT
  120. --*/
  121. {
  122. DWORD dwPos;
  123. BOOL fFound = FALSE;
  124. if ( pObjectCache == NULL )
  125. {
  126. DBG_ASSERT( FALSE );
  127. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  128. }
  129. //
  130. // First find the cache to remove
  131. //
  132. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  133. {
  134. if ( _Caches[ dwPos ] == pObjectCache )
  135. {
  136. memmove( _Caches + dwPos,
  137. _Caches + dwPos + 1,
  138. ( MAX_CACHE_COUNT - dwPos - 1 ) * sizeof( OBJECT_CACHE*) );
  139. fFound = TRUE;
  140. break;
  141. }
  142. }
  143. if ( !fFound )
  144. {
  145. return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  146. }
  147. return NO_ERROR;
  148. }
  149. VOID
  150. CACHE_MANAGER::FlushAllCaches(
  151. VOID
  152. )
  153. /*++
  154. Routine Description:
  155. Flush all caches
  156. Arguments:
  157. None
  158. Return Value:
  159. None
  160. --*/
  161. {
  162. DWORD dwPos;
  163. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  164. {
  165. _Caches[ dwPos ]->Clear();
  166. }
  167. //
  168. // Cleanup any dirmon dependencies now since we're about to kill the
  169. // caches
  170. //
  171. _pDirMonitor->Cleanup();
  172. }
  173. HRESULT
  174. CACHE_MANAGER::HandleDirMonitorInvalidation(
  175. WCHAR * pszFilePath,
  176. BOOL fFlushAll
  177. )
  178. /*++
  179. Routine Description:
  180. Invalidate any caches which are interested in dir monitor invalidation
  181. Arguments:
  182. pszFilePath - File name changed
  183. fFlushAll - Should we flush all items prefixed with pszFilePath?
  184. Return Value:
  185. HRESULT
  186. --*/
  187. {
  188. DWORD dwPos;
  189. OBJECT_CACHE * pCache;
  190. if ( pszFilePath == NULL )
  191. {
  192. DBG_ASSERT( FALSE );
  193. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  194. }
  195. //
  196. // Iterate thru all the caches which support dirmon invalidation
  197. //
  198. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  199. {
  200. pCache = _Caches[ dwPos ];
  201. //
  202. // If this cache doesn't support dirmon at all, continue
  203. //
  204. if ( !pCache->QuerySupportsDirmonSpecific() &&
  205. !pCache->QuerySupportsDirmonFlush() )
  206. {
  207. continue;
  208. }
  209. //
  210. // If this is a specific invalidation, check whether the cache
  211. // supports it. If it doesn't, but does support flush, the do a
  212. // flush instead
  213. //
  214. if ( !fFlushAll )
  215. {
  216. if ( pCache->QuerySupportsDirmonSpecific() )
  217. {
  218. pCache->DoDirmonInvalidationSpecific( pszFilePath );
  219. }
  220. else
  221. {
  222. pCache->DoDirmonInvalidationFlush( pszFilePath );
  223. }
  224. }
  225. else
  226. {
  227. pCache->DoDirmonInvalidationFlush( pszFilePath );
  228. }
  229. }
  230. return NO_ERROR;
  231. }
  232. HRESULT
  233. CACHE_MANAGER::HandleMetadataInvalidation(
  234. WCHAR * pszMetaPath
  235. )
  236. /*++
  237. Routine Description:
  238. Invalidate any caches which are interested in metadata invalidation
  239. Arguments:
  240. pszMetaPath - Metabase path which changed
  241. Return Value:
  242. HRESULT
  243. --*/
  244. {
  245. DWORD dwPos;
  246. OBJECT_CACHE * pCache;
  247. if ( pszMetaPath == NULL )
  248. {
  249. DBG_ASSERT( FALSE );
  250. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  251. }
  252. //
  253. // Iterate thru all the caches which support metadata invalidation
  254. //
  255. for ( dwPos = 0; _Caches[ dwPos ] != NULL; dwPos++ )
  256. {
  257. pCache = _Caches[ dwPos ];
  258. if ( pCache->QuerySupportsMetadataFlush() )
  259. {
  260. pCache->DoMetadataInvalidationFlush( pszMetaPath );
  261. }
  262. }
  263. return NO_ERROR;
  264. }
  265. HRESULT
  266. CACHE_MANAGER::MonitorDirectory(
  267. DIRMON_CONFIG * pDirmonConfig,
  268. CDirMonitorEntry ** ppDME
  269. )
  270. /*++
  271. Routine Description:
  272. Monitor given directory
  273. Arguments:
  274. pDirmonConfig - Name of directory and token to impersonate with
  275. ppDME - Set to monitor entry on success
  276. Return Value:
  277. HRESULT
  278. --*/
  279. {
  280. CacheDirMonitorEntry * pDME = NULL;
  281. HRESULT hr = NO_ERROR;
  282. BOOL fRet;
  283. BOOL fImpersonated = FALSE;
  284. if ( ppDME == NULL ||
  285. pDirmonConfig == NULL )
  286. {
  287. DBG_ASSERT( FALSE );
  288. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  289. }
  290. //
  291. // First check if we are already monitoring this directory
  292. //
  293. pDME = (CacheDirMonitorEntry*) _pDirMonitor->FindEntry( pDirmonConfig->pszDirPath );
  294. if ( pDME == NULL )
  295. {
  296. //
  297. // It is not. We'll have to start monitoring
  298. //
  299. pDME = new CacheDirMonitorEntry;
  300. if ( pDME == NULL )
  301. {
  302. return HRESULT_FROM_WIN32( GetLastError() );
  303. }
  304. pDME->AddRef();
  305. if ( pDirmonConfig->hToken != NULL )
  306. {
  307. fRet = SetThreadToken( NULL, pDirmonConfig->hToken );
  308. if ( !fRet )
  309. {
  310. hr = HRESULT_FROM_WIN32( GetLastError() );
  311. pDME->Release();
  312. return hr;
  313. }
  314. fImpersonated = TRUE;
  315. }
  316. fRet = _pDirMonitor->Monitor( pDME,
  317. pDirmonConfig->pszDirPath,
  318. TRUE,
  319. DIR_CHANGE_FILTER );
  320. if ( fImpersonated )
  321. {
  322. RevertToSelf();
  323. fImpersonated = FALSE;
  324. }
  325. if ( !fRet )
  326. {
  327. //
  328. // Note: It is OK if we can't monitor the directory. The error
  329. // will trickle up and the caller will not cache the entry
  330. //
  331. hr = HRESULT_FROM_WIN32( GetLastError() );
  332. pDME->Release();
  333. pDME = NULL;
  334. return hr;
  335. }
  336. }
  337. DBG_ASSERT( pDME != NULL );
  338. *ppDME = (CDirMonitorEntry*) pDME;
  339. return NO_ERROR;
  340. }