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.

274 lines
10 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. VarObjHeap.H
  5. Abstract:
  6. Implements the storage of variable length objects over the top of of a fixed
  7. length page system. It keeps a set of admin pages for holding the pages active
  8. by this subsystem, along with how much space is used on each. When a page becomes
  9. empty it frees up the page to the page system. It also deals with blocks that span
  10. multiple pages
  11. History:
  12. paulall 02-Feb-2001 Created
  13. --*/
  14. #include <unk.h>
  15. #include <arrtempl.h>
  16. #include <statsync.h>
  17. class CPageFile;
  18. class CPageSource;
  19. #define VAROBJ_VERSION 1
  20. //**************************************************************************************
  21. //VarObjAdminPageEntry - This is a structure that is stored within the
  22. //m_aAdminPages cache. It has an entry for each of the admin pages
  23. //that we cache. It stores the PageId (0 for the first one!),
  24. //pointer to the actual page, and a flag to determine if we need to
  25. //flush it next time around.
  26. //**************************************************************************************
  27. typedef struct _VarObjAdminPageEntry
  28. {
  29. DWORD dwPageId;
  30. BYTE *pbPage;
  31. bool bDirty;
  32. } VarObjAdminPageEntry;
  33. //**************************************************************************************
  34. //VarObjObjOffsetEntry: There is an array of these objects stored at the
  35. //start of the object page to point out where each object is stored.
  36. //If this is a continuation block we do not have one of these, however
  37. //continuation blocks have consecutive pageIds so it should be fairly easy
  38. //to conclude
  39. //**************************************************************************************
  40. typedef struct _VarObjObjOffsetEntry
  41. {
  42. DWORD dwOffsetId;
  43. DWORD dwPhysicalStartOffset;
  44. DWORD dwBlockLength;
  45. DWORD dwCRC;
  46. } VarObjObjOffsetEntry;
  47. //**************************************************************************************
  48. //VarObjHeapAdminPage - This is the header of each of the admin pages
  49. //that are stored in the object file. The version is only relevant
  50. //in the first page (page 0). The last entry is a buffer to make
  51. //it 4-DWORD structure rather than 3. May use it at a later date.
  52. //Should always set it to 0 for now.
  53. //**************************************************************************************
  54. typedef struct _VarObjHeapAdminPage
  55. {
  56. DWORD dwVersion;
  57. DWORD dwNextAdminPage;
  58. DWORD dwNumberEntriesOnPage;
  59. //VarObjHeapFreeList aFreeListEntries[dwNumberEntriesOnPage];
  60. } VarObjHeapAdminPage;
  61. //**************************************************************************************
  62. //VarObjHeapFreeList - This structure follows the admin page header
  63. //and there is an entry for each page we use to store objects. The
  64. //page may not be full, so we do not shuffle items on a second page
  65. //to this page when we delete an entry.
  66. //**************************************************************************************
  67. typedef struct _VarObjHeapFreeList
  68. {
  69. DWORD dwPageId;
  70. DWORD dwFreeSpace;
  71. DWORD dwCRC32;
  72. DWORD dwReserved;
  73. } VarObjHeapFreeList;
  74. //**************************************************************************************
  75. //CVarObjHeap - This is the implementation of the variable sized object store
  76. //over the top of the transacted fixed page manager. It tracks the admin pages
  77. //that hold all pages we use to store objects in (it caches these pages), and
  78. //also manages cases when an object is too big to fit on a single page.
  79. //**************************************************************************************
  80. class CVarObjHeap
  81. {
  82. private:
  83. //Current status of admin page
  84. enum
  85. {
  86. NoError = 0,
  87. AdminPageReadFailure = 1,
  88. RootAdminPageCreationFailure = 2,
  89. AdminPagesNeedReading = 3
  90. } m_dwStatus;
  91. //Pointer to the transacted file for the object storage
  92. CPageFile *m_pObjectFile;
  93. //Page size used within the object storage file.
  94. DWORD m_dwPageSize;
  95. //Admin page structure
  96. CLockableFlexArray<CStaticCritSec> m_aAdminPages;
  97. protected:
  98. //Adds an allocation to the end of the existing allocations
  99. DWORD AllocateFromPage(/* in */ DWORD dwPageId,
  100. /* in */ BYTE *pbPage,
  101. /* in */ ULONG ulBlockSize,
  102. /* in */ const BYTE *pBlock,
  103. /* out*/ ULONG *pdwNewOffset);
  104. //Allocates a multi-page entry in the object file. This requires
  105. //different algorithms to work things out so is a special case
  106. DWORD AllocateMultiPageBuffer(/* in */ ULONG ulBlockSize,
  107. /* in */ const BYTE *pBlock,
  108. /* out */ ULONG *pulPageId,
  109. /* out */ ULONG *pulOffsetId);
  110. //Given and offsetId and a page, calculate the physical pointer to the object and also
  111. //return the size of the block
  112. DWORD OffsetToPointer(/* in */ ULONG ulOffsetId,
  113. /* in */ BYTE *pbPage,
  114. /* out*/ BYTE **pOffsetPointer,
  115. /* out*/ ULONG *pdwBlockSize,
  116. /* out*/ DWORD *pdwCRC32);
  117. //Reads the admin pages into memory and marks them as clean (no changes)
  118. //setting bReReadPages to false has an affect of clearing the pages out
  119. DWORD ReadAdminPages(CPageSource *pTransactionManager, bool bReReadPages);
  120. //Writes each of the changed admin pages back to the object file
  121. DWORD FlushAdminPages();
  122. //Find a page form the admin pages that can accomodate a particular buffer size
  123. DWORD FindPageWithSpace(/* in */ DWORD dwRequiredSize,
  124. /* out*/ DWORD *pdwPageId);
  125. //Allocate a new page for use with objects. A buffer for the new page is passed
  126. //in, however the PageId of this page is passed out
  127. DWORD AllocateNewPage(/* in */ DWORD ulBlockSize,
  128. /* out*/ DWORD *dwPageId,
  129. /* in */ BYTE *pbNewObjectPage);
  130. //Deletes a page, and updates the admin pages as appropriage
  131. DWORD DeletePage(/* in */ DWORD ulPageId);
  132. //DeleteFromPage - removes an object from a specific object page
  133. DWORD RemoveFromPage(/* in */ ULONG ulPageId,
  134. /* in */ ULONG ulOffsetId,
  135. /* in */ BYTE *pbPage,
  136. /* out*/ DWORD *pdwSize);
  137. //MultiPageObject - returns true if the provided page is the first page
  138. //of a multi-page object
  139. bool MultiPageObject(/* in */ BYTE *pbPage) { return ((VarObjObjOffsetEntry*) pbPage)->dwBlockLength > (m_dwPageSize - (sizeof(VarObjObjOffsetEntry) * 2)); }
  140. //DeleteMultiPageBuffer - handles the deletion of an object when it spans
  141. //multiple pages
  142. DWORD DeleteMultiPageBuffer(/* in */ ULONG ulPageId,
  143. /* in */ ULONG ulOffsetId,
  144. /* in */ BYTE *pbPage);
  145. //UpdateAdminPageForAllocate - Updates the admin page to decrement the amount
  146. //of free space on a page by this amount ( + sizeof(VarObjObjOffsetEntry))
  147. DWORD UpdateAdminPageForAllocate(/* in */ ULONG ulPageId,
  148. /* in */ ULONG ulBlockSize,
  149. /* in */ DWORD dwCRC32);
  150. DWORD UpdateAdminPageForAllocate2(/* in */ ULONG ulPageId,
  151. /* in */ ULONG ulFreeSpaceOnPage,
  152. /* in */ DWORD dwCRC32);
  153. //UpdateAdminPageForDelete - Updates the admin page for giving space back. If
  154. //the page is totally empty we should delete the page altogether
  155. DWORD UpdateAdminPageForDelete(/* in */ ULONG ulPageId,
  156. /* in */ ULONG ulBlockSize,
  157. /* in */ DWORD dwCRC32,
  158. /* out */ bool *pbPageDeleted);
  159. //Removes an object page entry from an admin page, removing the
  160. //admin page if it is no longer needed
  161. DWORD RemoveEntryFromAdminPage(/* in */ DWORD dwAdminPageIndex,
  162. /* in */ DWORD dwAdminPageEntry);
  163. //Returns a CRC based on a given block of memory
  164. #define FINALIZE_CRC32(x) (x=~x)
  165. DWORD CreateCRC32(/* in */ const BYTE *pBlock,
  166. /* in */ DWORD dwSize,
  167. /* in */ DWORD dwPreviousCRC = (DWORD) -1); // Must be 0xFFFFFFFF if no previous CRC
  168. //Given a page we validate that there is in fact enough space
  169. //for this block. If there is not it asserts. This implies
  170. //that the admin page is not in sync with the actual pages.
  171. DWORD ValidatePageFreeSpace(/* in */ const BYTE *pbPage,
  172. /* in */ DWORD ulBlockSize,
  173. /* out */ DWORD *pulFreeSpaceLeftOnPage);
  174. #ifdef DBG
  175. //Given a page and a page ID, it validates the amount of free space
  176. //on the page is equal to the amount the admin page thinks is on
  177. //there.
  178. DWORD ValidatePageFreeSpaceWithAdminPage(/* in */ const BYTE *pbPage,
  179. /* in */ DWORD ulPageId);
  180. //Dumps the offset table of a page to the debugger
  181. DWORD DumpPageOffsetTable(/* in */ DWORD dwPageId,
  182. /* in */ const BYTE *pbPage);
  183. //Checks the CRCs of all objects on a page (cannot do this
  184. //for a multi-page object though as we only have the first
  185. //page!)
  186. DWORD ValidateAllCRC32OnPage(/* in */ const BYTE *pbPage);
  187. //Validates the page check-sum with the admin page
  188. DWORD ValidatePageCRCWithAdminPage(/* in */ const BYTE *pbPage,
  189. /* in */ DWORD dwPageId);
  190. #endif /* DBG */
  191. public:
  192. CVarObjHeap();
  193. ~CVarObjHeap();
  194. DWORD Initialize(CPageSource *pPageManager);
  195. DWORD Shutdown(DWORD dwShutdownType);
  196. //Re-read admin pages
  197. DWORD InvalidateCache();
  198. //Discard admin pages
  199. DWORD FlushCaches();
  200. //ReadBuffer pages the virtual page and offset of the block and returns a new[]-ed block
  201. DWORD ReadBuffer(/* in */ ULONG ulPageId,
  202. /* in */ ULONG ulOffsetId,
  203. /* out */ BYTE **ppReturnedBlock,
  204. /* out */ DWORD *pdwBlockSize);
  205. //WriteNewBuffer will write a new page based on size of BYTE *, and return the
  206. //new virtual pageId and offsetId of the block.
  207. DWORD WriteNewBuffer(/* in */ ULONG ulBlockSize,
  208. /* in */ const BYTE *pBlock,
  209. /* out */ ULONG *pulPageId,
  210. /* out */ ULONG *pulOffsetId);
  211. //WriteExistingBuffer will update an existing block with new data. The old virtual page
  212. //and offset are passed in, and new ones are returned. They may or may not be the same
  213. //depending on if it still fits in the page or not.
  214. DWORD WriteExistingBuffer(/* in */ ULONG ulBlockSize,
  215. /* in */ const BYTE *pBlock,
  216. /* in */ ULONG ulOldPageId,
  217. /* in */ ULONG ulOldOffsetId,
  218. /* out */ ULONG *pulNewPageId,
  219. /* out */ ULONG *pulNewOffsetId);
  220. //DeleteBuffer is called to delete the item in the store given the virtual pageId and
  221. //offsetId.
  222. DWORD DeleteBuffer(/* in */ ULONG ulPageId,
  223. /* in */ ULONG ulOffsetId);
  224. };