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.

376 lines
10 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1998
  5. //
  6. // File: PhyStr.hxx
  7. //
  8. // Contents: Buffer/Index package
  9. //
  10. // Classes:
  11. //
  12. // History: 09-Jan-96 KyleP Lifted from CIndex directory
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #include <pstore.hxx>
  17. #include <pmmstrm.hxx>
  18. class PStorageObject;
  19. class PStorage;
  20. class PSaveProgressTracker;
  21. //+-------------------------------------------------------------------------
  22. //
  23. // Class: CPhysBuffer
  24. //
  25. // Purpose: Encapsulates a reference counted 'buffer'.
  26. //
  27. // History: 07-Mar-92 KyleP Created
  28. // 21-Apr-93 BartoszM Rewrote to use memory mapped files
  29. //
  30. // Notes: Physical buffers are managed objects. They are created
  31. // by physical indexes and property caches.
  32. //
  33. //--------------------------------------------------------------------------
  34. class CPhysBuffer
  35. {
  36. public:
  37. CPhysBuffer( PMmStream& stream,
  38. ULONG PageNo,
  39. BOOL fWrite,
  40. BOOL fIntentToWrite,
  41. BOOL fMap );
  42. ~CPhysBuffer();
  43. CPhysBuffer *Next() { return _pphysNext; }
  44. void Link( CPhysBuffer * pphysbuf ) { _pphysNext = pphysbuf; }
  45. void SetIntentToWrite()
  46. {
  47. Win4Assert( _fWrite );
  48. _fNeedToFlush = TRUE;
  49. }
  50. BOOL RequiresFlush() const { return _fNeedToFlush; }
  51. void Reference()
  52. {
  53. InterlockedIncrement( &_cRef );
  54. }
  55. void DeReference( unsigned usn )
  56. {
  57. Win4Assert( 0 != _cRef );
  58. InterlockedDecrement( &_cRef );
  59. _usn = usn;
  60. }
  61. BOOL IsReferenced()
  62. {
  63. return ( 0 != InterlockedCompareExchange( &_cRef,
  64. 0,
  65. 0 ) );
  66. }
  67. BOOL IsRefCountOne()
  68. {
  69. return ( 1 == _cRef );
  70. }
  71. ULONG PageNumber() { return _PageNo; }
  72. unsigned GetUSN() { return _usn; }
  73. ULONG * GetPage( ULONG nPage )
  74. {
  75. ULONG cpageIntoBuf = nPage & ( PAGES_PER_COMMON_PAGE - 1 );
  76. Win4Assert( ( nPage % PAGES_PER_COMMON_PAGE ) ==
  77. ( nPage & ( PAGES_PER_COMMON_PAGE - 1 ) ) );
  78. BYTE * pbBase = (BYTE *) ( _fMap ? _strmBuf.Get() : _xBuffer.Get() );
  79. return (ULONG*)( pbBase + CI_PAGE_SIZE * cpageIntoBuf );
  80. }
  81. void Flush( BOOL fFailFlush );
  82. BOOL IsWritable() { return _fWrite; }
  83. #ifdef CIEXTMODE
  84. void CiExtDump(void *ciExtSelf);
  85. #endif
  86. private:
  87. ULONG _PageNo;
  88. CMmStreamBuf _strmBuf;
  89. PMmStream & _stream;
  90. long _cRef;
  91. unsigned _usn;
  92. CPhysBuffer * _pphysNext;
  93. BOOL _fNeedToFlush; // Is flush required for writable buffers?
  94. BOOL _fWrite;
  95. BOOL _fMap; // TRUE if mapped, FALSE if Read/WriteFile
  96. XArrayVirtual<BYTE> _xBuffer; // buffer to use if not mapped
  97. };
  98. //+-------------------------------------------------------------------------
  99. //
  100. // Class: CBufferCache
  101. //
  102. // Purpose: A cache of buffers
  103. //
  104. // History: 17-Mar-93 BartoszM Created
  105. //
  106. //--------------------------------------------------------------------------
  107. class CBufferCache
  108. {
  109. friend class CBufferCacheIter;
  110. public:
  111. CBufferCache( unsigned cHash );
  112. ~CBufferCache();
  113. void Free( BOOL fFailFlush = TRUE );
  114. void Add( CPhysBuffer * pphysBuf, ULONG hash );
  115. CPhysBuffer * Search( ULONG hash, ULONG commonPage );
  116. void Destroy ( ULONG ulPage, BOOL fFailFlush = TRUE );
  117. void Flush( ULONG nHighPage, BOOL fLeaveFlushFlagAlone = FALSE );
  118. void TryToRemoveBuffers( unsigned cLimit );
  119. BOOL MinPageInUse( ULONG & minPage );
  120. unsigned Count() { return _cBuffers; }
  121. #ifdef CIEXTMODE
  122. void CiExtDump(void *ciExtSelf);
  123. #endif
  124. ULONG hash(ULONG nPage)
  125. {
  126. return (nPage/PAGES_PER_COMMON_PAGE) % _cHash;
  127. }
  128. private:
  129. unsigned _cBuffers;
  130. unsigned _cHash;
  131. XArray<CPhysBuffer *> _aPhysBuf;
  132. #if CIDBG == 1
  133. unsigned _cCacheHits;
  134. unsigned _cCacheMisses;
  135. #endif // DBG==1 || CIDBG==1
  136. };
  137. //+-------------------------------------------------------------------------
  138. //
  139. // Class: CBufferCacheIterator
  140. //
  141. // Purpose: Iterates over the cache of buffers
  142. //
  143. // History: 17-Mar-93 BartoszM Created
  144. //
  145. //--------------------------------------------------------------------------
  146. class CBufferCacheIter
  147. {
  148. public:
  149. CBufferCacheIter ( CBufferCache& cache );
  150. BOOL AtEnd() { return _pBuf == 0; }
  151. void operator++();
  152. CPhysBuffer* Get() { return _pBuf; }
  153. private:
  154. CPhysBuffer** _pPhysBuf;
  155. unsigned _idx;
  156. CPhysBuffer* _pBuf;
  157. unsigned _cHash;
  158. };
  159. //+-------------------------------------------------------------------------
  160. //
  161. // Class: CPhysStorage
  162. //
  163. // Purpose: Provides physical access to index pages
  164. //
  165. // History: 07-Mar-92 KyleP Created
  166. // 21-Apr-93 BartoszM Rewrote to use memory mapped files
  167. // 17-Feb-94 KyleP Subclass for PhysIndex / PhysHash
  168. // 10-Apr-94 SrikantS Added the ability to reopen for write
  169. // from read and also to provide support
  170. // for restarting a master merge.
  171. //
  172. //--------------------------------------------------------------------------
  173. const LONGLONG eSigPhysStorage = 0x45524f5453594850i64; // "PHYSTORE"
  174. class CPhysStorage
  175. {
  176. public:
  177. virtual ~CPhysStorage();
  178. void Close();
  179. void Reopen( BOOL fWritable = FALSE );
  180. ULONG * BorrowNewBuffer(ULONG nPage);
  181. ULONG * BorrowBuffer( ULONG nPage,
  182. BOOL fWritable=FALSE,
  183. BOOL fWriteIntent = FALSE );
  184. void ReturnBuffer( ULONG nPage,
  185. BOOL fFlush = FALSE,
  186. BOOL fFailFlush = TRUE );
  187. BOOL RequiresFlush( ULONG nPage );
  188. inline ULONG * BorrowNewLargeBuffer( ULONG nLargePage );
  189. inline ULONG * BorrowLargeBuffer( ULONG nLargePage,
  190. BOOL fWritable = TRUE,
  191. BOOL fWriteIntent = TRUE );
  192. inline void ReturnLargeBuffer( ULONG nLargePage );
  193. ULONG PageSize() const { return _cpageFileSize; }
  194. ULONG PagesInUse() const { return _cpageUsedFileSize; }
  195. WORKID ObjectId() const { return _objectId; }
  196. void Flush( BOOL fLeaveFlushFlagAlone = FALSE );
  197. void SetUsedPagesCount(ULONG cPage)
  198. {
  199. Win4Assert( cPage <= _cpageFileSize );
  200. _cpageUsedFileSize = cPage;
  201. }
  202. BOOL MinPageInUse( ULONG &minPage );
  203. ULONG ShrinkFromFront( ULONG ulFirstPage, ULONG ulNumPages );
  204. void ShrinkToFit();
  205. void UpdatePageCount( CPhysStorage & storage )
  206. {
  207. _cpageFileSize = storage._cpageFileSize;
  208. _cpageUsedFileSize = storage._cpageUsedFileSize;
  209. }
  210. void SetPageGrowth( ULONG cpageGrowth )
  211. {
  212. Win4Assert( cpageGrowth > 0 );
  213. _cpageGrowth = cpageGrowth;
  214. }
  215. void * GetLargePagePointer( ULONG nLargePage );
  216. BOOL WouldLargePageGrowMapping( ULONG nLargePage );
  217. void MakeBackupCopy( CPhysStorage & dst,
  218. PSaveProgressTracker & progressTracker );
  219. WCHAR const * GetPath() { return _stream->GetPath(); }
  220. BOOL IsWritable() const { return _fWritable; }
  221. PStorage & GetStorage() { return _storage; }
  222. #ifdef CIEXTMODE
  223. void CiExtDump(void *ciExtSelf);
  224. #endif
  225. protected:
  226. CPhysStorage( PStorage & storage,
  227. PStorageObject& obj,
  228. WORKID objectId,
  229. unsigned cpageReqSize,
  230. PMmStream * stream,
  231. BOOL fThrowCorruptErrorOnFailures,
  232. unsigned cCachedItems = 0,
  233. BOOL fAllowReadAhead = TRUE );
  234. CPhysStorage( PStorage & storage,
  235. PStorageObject& obj,
  236. WORKID objectId,
  237. PMmStream * stream,
  238. PStorage::EOpenMode mode,
  239. BOOL fThrowCorruptErrorOnFailures,
  240. unsigned cCachedItems = 0,
  241. BOOL fAllowReadAhead = FALSE );
  242. virtual void ReOpenStream() = 0;
  243. const LONGLONG _sigPhysStorage;
  244. PStorage& _storage;
  245. PStorageObject& _obj;
  246. XPtr<PMmStream> _stream;
  247. BOOL _fWritable;
  248. private:
  249. ULONG * LokBorrowOrAddBuffer( ULONG hash,
  250. ULONG commonPage,
  251. ULONG nPage,
  252. BOOL fAdd,
  253. BOOL fWritable,
  254. BOOL fIntentToWrite );
  255. ULONG * LokBorrowNewBuffer( ULONG hash,
  256. ULONG commonPage,
  257. ULONG nPage );
  258. void _GrowFile( ULONG cpageSize );
  259. unsigned _usnGen; // usns for pages
  260. unsigned _cMaxCachedBuffers; // # pages to cache
  261. ULONG _cpageFileSize; // File size on disk
  262. ULONG _cpageUsedFileSize; // # pages in use in file
  263. ULONG _cpageGrowth; // # pages to grow file size
  264. ULONG _iFirstNonShrunkPage; // first page not shrunk
  265. BOOL _fAllowReadAhead; // TRUE if non-mapped IO ok
  266. WORKID _objectId;
  267. BOOL _fThrowCorruptErrorOnFailures; // Should errors during opening
  268. // be marked as catalog corruption ?
  269. XPtr<CMutexSem> _xMutex;
  270. XPtr<CReadWriteAccess> _xRWAccess;
  271. CBufferCache _cache;
  272. };
  273. inline ULONG * CPhysStorage::BorrowNewLargeBuffer( ULONG nLargePage )
  274. {
  275. ULONG *pBuffer = BorrowNewBuffer( nLargePage * PAGES_PER_COMMON_PAGE );
  276. RtlZeroMemory( pBuffer, COMMON_PAGE_SIZE );
  277. return pBuffer;
  278. }
  279. inline ULONG * CPhysStorage::BorrowLargeBuffer(
  280. ULONG nLargePage,
  281. BOOL fWritable,
  282. BOOL fWriteIntent )
  283. {
  284. return BorrowBuffer( nLargePage * PAGES_PER_COMMON_PAGE,
  285. fWritable,
  286. fWriteIntent );
  287. }
  288. inline void CPhysStorage::ReturnLargeBuffer( ULONG nLargePage )
  289. {
  290. ReturnBuffer( nLargePage * PAGES_PER_COMMON_PAGE );
  291. }