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.

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