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.

369 lines
9.6 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 2000 Microsoft Corp. All Rights Reserved.
  4. //
  5. // BTR.H
  6. //
  7. // Repository B-tree classes
  8. //
  9. // raymcc 15-Oct-00 First version
  10. //
  11. //***************************************************************************
  12. #ifndef _BTR_H_
  13. #define _BTR_H_
  14. #define A51_INDEX_FILE_ID 2
  15. class CPageFile;
  16. class CPageSource;
  17. LPVOID WINAPI _BtrMemAlloc(
  18. SIZE_T dwBytes // number of bytes to allocate
  19. );
  20. LPVOID WINAPI _BtrMemReAlloc(
  21. LPVOID pOriginal,
  22. DWORD dwNewBytes
  23. );
  24. BOOL WINAPI _BtrMemFree(LPVOID pMem);
  25. #define ReleaseIfNotNULL(p) if(p) p->Release()
  26. class CBTreeFile
  27. {
  28. DWORD m_dwPageSize;
  29. DWORD m_dwLogicalRoot;
  30. CPageFile* m_pFile;
  31. CPageSource *m_pTransactionManager;
  32. // Methods
  33. DWORD Setup();
  34. DWORD WriteAdminPage();
  35. public:
  36. CBTreeFile();
  37. ~CBTreeFile();
  38. enum { const_DefaultPageSize = 0x2000, const_CurrentVersion = 0x101 };
  39. enum {
  40. PAGE_TYPE_IMPOSSIBLE = 0x0, // Not supposed to happen
  41. PAGE_TYPE_ACTIVE = 0xACCC, // Page is active with data
  42. PAGE_TYPE_DELETED = 0xBADD, // A deleted page on free list
  43. PAGE_TYPE_ADMIN = 0xADDD, // Page zero only
  44. // All pages
  45. OFFSET_PAGE_TYPE = 0, // True for all pages
  46. OFFSET_PAGE_ID = 1, // True for all pages
  47. OFFSET_NEXT_PAGE = 2, // True for all pages (Page continuator)
  48. // Admin Page (page zero) only
  49. OFFSET_LOGICAL_ROOT = 3, // Root of database
  50. };
  51. DWORD Init(
  52. DWORD dwPageSize, // 8k default
  53. LPWSTR pszFilename,
  54. CPageSource* pSource
  55. );
  56. DWORD Shutdown(DWORD dwShutDownFlags);
  57. DWORD GetPage(DWORD dwId, LPVOID *pPage);
  58. DWORD PutPage(LPVOID pPage, DWORD dwType);
  59. DWORD NewPage(LPVOID *pPage);
  60. DWORD FreePage(LPVOID pPage);
  61. DWORD FreePage(DWORD dwId);
  62. DWORD GetPageSize() { return m_dwPageSize; }
  63. DWORD SetRootPage(DWORD dwID);
  64. DWORD GetRootPage() { return m_dwLogicalRoot; }
  65. DWORD ReadAdminPage();
  66. void Dump(FILE *);
  67. };
  68. struct SIdxStringPool
  69. {
  70. DWORD m_dwNumStrings; // Number of strings in pool
  71. WORD *m_pwOffsets; // Offsets into pool of strings
  72. DWORD m_dwOffsetsSize; // Number of elements in above array
  73. LPSTR m_pStringPool; // Pointer to string pool
  74. DWORD m_dwPoolTotalSize; // Total size, used+unused
  75. DWORD m_dwPoolUsed; // Offset of first free position
  76. public:
  77. enum { const_DefaultPoolSize = 0x2200 };
  78. SIdxStringPool() { memset(this, 0, sizeof(SIdxStringPool)); }
  79. ~SIdxStringPool();
  80. DWORD AddStr(LPSTR pszStr, WORD wInsertPos, int *pnAdjuster);
  81. DWORD DeleteStr(WORD wAssignedOffset, int *pnAdjuster);
  82. DWORD GetLastId() { return m_dwNumStrings; }
  83. DWORD FindStr(
  84. IN LPSTR pszSearchKey,
  85. OUT WORD *pwStringNumber,
  86. OUT WORD *pwPoolOffset
  87. );
  88. DWORD GetNumStrings() { return m_dwNumStrings; }
  89. DWORD GetRequiredPageMemory()
  90. {
  91. return m_dwPoolUsed + (m_dwNumStrings * sizeof(WORD)) +
  92. sizeof(m_dwNumStrings) + sizeof(m_dwPoolUsed);
  93. }
  94. DWORD Dump(FILE *f);
  95. LPSTR GetStrById(WORD id) { return m_pStringPool+m_pwOffsets[id]; }
  96. void Empty() { m_dwNumStrings = 0; m_dwPoolUsed = 0; }
  97. DWORD Clone(SIdxStringPool **);
  98. };
  99. class SIdxKeyTable
  100. {
  101. DWORD m_dwRefCount; // Ref count
  102. DWORD m_dwPageId; // Page number
  103. DWORD m_dwParentPageId; // Parent page id <For DEBUGGING only>
  104. DWORD m_dwNumKeys; // Num keys
  105. WORD *m_pwKeyLookup; // Offset of key into key-encoding-table
  106. DWORD m_dwKeyLookupTotalSize; // Elements in array
  107. DWORD *m_pdwUserData; // User DWORD with each key
  108. DWORD *m_pdwChildPageMap; // Child page pointers n=left ptr, n+1=right pointer
  109. WORD *m_pwKeyCodes; // Key encoding table
  110. DWORD m_dwKeyCodesTotalSize; // Total elements in array
  111. DWORD m_dwKeyCodesUsed; // Elements used
  112. SIdxStringPool *m_pStrPool; // The pool associated with this key table
  113. // Methods
  114. SIdxKeyTable();
  115. ~SIdxKeyTable();
  116. public:
  117. enum { const_DefaultArray = 256,
  118. const_DefaultKeyCodeArray = 512
  119. };
  120. static DWORD Create(DWORD dwPageId, SIdxKeyTable **pNew);
  121. static DWORD Create(LPVOID pPage, SIdxKeyTable **pNew);
  122. DWORD AddRef();
  123. DWORD Release();
  124. DWORD AddKey(LPSTR pszStr, WORD ID, DWORD dwUserData);
  125. DWORD RemoveKey(WORD wID);
  126. DWORD FindKey(LPSTR pszStr, WORD *pID);
  127. DWORD GetUserData(WORD wID) { return m_pdwUserData[wID]; }
  128. void SetChildPage(WORD wID, DWORD dwPage) { m_pdwChildPageMap[wID] = dwPage; }
  129. DWORD GetChildPage(WORD wID) { return m_pdwChildPageMap[wID]; }
  130. DWORD GetLastChildPage() { return m_pdwChildPageMap[m_dwNumKeys]; }
  131. DWORD GetLeftSiblingOf(DWORD dwId);
  132. DWORD GetRightSiblingOf(DWORD dwId);
  133. DWORD GetKeyAt(WORD wID, LPSTR *pszKey); // Use _MemFree
  134. DWORD GetNumKeys() { return m_dwNumKeys; }
  135. void SetStringPool(SIdxStringPool *pPool) { m_pStrPool = pPool; }
  136. void FreeMem(LPVOID pMem);
  137. void AdjustKeyCodes(
  138. WORD wID,
  139. int nAdjustment
  140. );
  141. int KeyStrCompare(
  142. LPSTR pszSearchKey,
  143. WORD wID
  144. );
  145. DWORD Cleanup();
  146. DWORD NumKeys() { return m_dwNumKeys; }
  147. DWORD GetRequiredPageMemory();
  148. DWORD Dump(FILE *, DWORD *pdwKeys = 0);
  149. void ZapPage();
  150. DWORD GetPageId() { return m_dwPageId; }
  151. // Sibling/Parent page helpers
  152. DWORD GetKeyOverhead(WORD wID); // Returns total bytes required by new key
  153. BOOL IsLeaf() { return m_pdwChildPageMap[0] == 0; }
  154. DWORD Redist(
  155. SIdxKeyTable *pParent,
  156. SIdxKeyTable *pNewSibling
  157. );
  158. DWORD Collapse(
  159. SIdxKeyTable *pParent,
  160. SIdxKeyTable *pDoomedSibling
  161. );
  162. DWORD StealKeyFromSibling(
  163. SIdxKeyTable *pParent,
  164. SIdxKeyTable *pSibling
  165. );
  166. DWORD MapFromPage(LPVOID pSrc);
  167. DWORD MapToPage(LPVOID pMem);
  168. DWORD Clone(OUT SIdxKeyTable **pCopy);
  169. };
  170. class CBTree;
  171. class CBTreeIterator
  172. {
  173. friend class CBTree;
  174. enum {
  175. const_MaxStack = 1024,
  176. const_PrefetchSize = 64
  177. };
  178. CBTree *m_pTree;
  179. SIdxKeyTable *m_Stack[const_MaxStack];
  180. WORD m_wStack[const_MaxStack];
  181. LONG m_lStackPointer;
  182. LPSTR *m_pPrefetchKeys[const_PrefetchSize];
  183. DWORD m_dwPrefetchData[const_PrefetchSize];
  184. DWORD m_dwPrefetchActive;
  185. ~CBTreeIterator();
  186. // Stack helpers
  187. SIdxKeyTable *Peek() { return m_Stack[m_lStackPointer]; }
  188. WORD PeekId() { return m_wStack[m_lStackPointer]; }
  189. void IncStackId() { m_wStack[m_lStackPointer]++; }
  190. void Pop() { ReleaseIfNotNULL(m_Stack[m_lStackPointer]); m_lStackPointer--; }
  191. BOOL StackFull() { return m_lStackPointer == const_MaxStack - 1; }
  192. void Push(SIdxKeyTable *p, WORD wId) { m_Stack[++m_lStackPointer] = p; m_wStack[m_lStackPointer] = wId; }
  193. DWORD ZapStack();
  194. DWORD PurgeKey(LPSTR pszDoomedKey);
  195. DWORD RebuildStack(LPSTR pszStartKey);
  196. DWORD ExecPrefetch();
  197. static DWORD ZapAllStacks();
  198. static DWORD GlobalPurgeKey(LPSTR pszDoomedKey);
  199. public:
  200. CBTreeIterator() { m_pTree = 0; m_lStackPointer = -1; }
  201. DWORD Init(CBTree *pRoot, LPSTR pszStartKey = 0); // If last parm is null, iterate through all
  202. DWORD Next(LPSTR *ppszStr, DWORD *pdwData = 0);
  203. void FreeString(LPSTR pszStr) { _BtrMemFree(pszStr); }
  204. DWORD Release();
  205. };
  206. class CBTree
  207. {
  208. enum { const_DefaultArray = 256 };
  209. enum { const_MinimumLoad = 33 };
  210. CBTreeFile *m_pSrc;
  211. SIdxKeyTable *m_pRoot;
  212. friend class CBTreeIterator;
  213. LONG m_lGeneration;
  214. // private methods
  215. DWORD ReplaceBySuccessor(
  216. IN SIdxKeyTable *pIdx,
  217. IN WORD wId,
  218. OUT LPSTR *pszSuccessorKey,
  219. OUT BOOL *pbUnderflowDetected,
  220. DWORD Stack[],
  221. LONG &StackPtr
  222. );
  223. DWORD FindSuccessorNode(
  224. IN SIdxKeyTable *pIdx,
  225. IN WORD wId,
  226. OUT SIdxKeyTable **pSuccessor,
  227. OUT DWORD *pdwPredecessorChild,
  228. DWORD Stack[],
  229. LONG &StackPtr
  230. );
  231. DWORD ReadIdxPage(
  232. DWORD dwPage,
  233. SIdxKeyTable **pIdx
  234. );
  235. DWORD WriteIdxPage(
  236. SIdxKeyTable *pIdx
  237. );
  238. DWORD ComputeLoad(
  239. SIdxKeyTable *pKT
  240. );
  241. DWORD InsertPhase2(
  242. SIdxKeyTable *pCurrent,
  243. WORD wID,
  244. LPSTR pszKey,
  245. DWORD dwValue,
  246. DWORD Stack[],
  247. LONG &StackPtr
  248. );
  249. DWORD Search(
  250. IN LPSTR pszKey,
  251. OUT SIdxKeyTable **pRetIdx,
  252. OUT WORD *pwID,
  253. DWORD Stack[],
  254. LONG &StackPtr
  255. );
  256. public:
  257. CBTree();
  258. ~CBTree();
  259. DWORD Init(CBTreeFile *pSrc);
  260. DWORD Shutdown(DWORD dwShutDownFlags);
  261. DWORD InsertKey(
  262. IN LPSTR pszKey,
  263. DWORD dwValue
  264. );
  265. DWORD FindKey(
  266. IN LPSTR pszKey,
  267. DWORD *pdwData
  268. );
  269. DWORD DeleteKey(
  270. IN LPSTR pszKey
  271. );
  272. DWORD BeginEnum(
  273. LPSTR pszStartKey,
  274. OUT CBTreeIterator **pIterator
  275. );
  276. void Dump(FILE *fp);
  277. DWORD InvalidateCache();
  278. DWORD FlushCaches();
  279. };
  280. #endif