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.

250 lines
7.4 KiB

  1. //
  2. //------ Page Structure ---------------------------------------------------
  3. //
  4. #define cbPage 4096 // database logical page size
  5. #define ctagMax 256 // default limit on number of tags
  6. typedef BYTE PGTYP;
  7. // the pragma is bad for efficiency, but we need it here so that the
  8. // THREEBYTES will not be aligned on 4-byte boundary
  9. #pragma pack(1)
  10. typedef struct _pghdr
  11. {
  12. ULONG ulChecksum; // checksum of page, always 1st byte
  13. ULONG ulDBTimeLow; // database time page dirtied
  14. PGNO pgnoFDP; // pgno of FDP which owns this page
  15. SHORT cbFree; // count free bytes
  16. SHORT ibMic; // minimum used byte
  17. SHORT ctagMac; // count tags used
  18. SHORT itagFree; // itag of first free tag
  19. SHORT cbUncommittedFreed; // bytes freed from this page, but *possibly*
  20. // uncommitted (this number will always be
  21. // a subset of cbFree)
  22. THREEBYTES pgnoPrev; // pgno of previous page
  23. THREEBYTES pgnoNext; // pgno of next page
  24. } PGHDR;
  25. typedef struct _pgtrlr
  26. {
  27. PGTYP pgtyp:3;
  28. BYTE bDBTimeHigh:4;
  29. BYTE bitModified:1;
  30. THREEBYTES pgnoThisPage;
  31. } PGTRLR;
  32. typedef struct _tag
  33. {
  34. SHORT cb;
  35. SHORT ib;
  36. } TAG;
  37. /* tag status
  38. /**/
  39. typedef enum { tsLine, tsVacant, tsLink } TS;
  40. typedef struct _page
  41. {
  42. PGHDR;
  43. TAG rgtag[1];
  44. BYTE rgbFiller[ cbPage -
  45. sizeof(PGHDR) - // pghdr
  46. sizeof(TAG) - // rgtag[1]
  47. sizeof(BYTE) - // rgbData[1]
  48. sizeof(PGTRLR) ]; // pgtyp and pgnoThisPage
  49. BYTE rgbData[1];
  50. PGTRLR;
  51. } PAGE;
  52. #pragma pack()
  53. STATIC INLINE VOID PMSetDBTime( PAGE *ppage, QWORD qwDBTime )
  54. {
  55. QWORDX qwx;
  56. qwx.qw = qwDBTime;
  57. ppage->bDBTimeHigh = (BYTE) qwx.h;
  58. ppage->ulDBTimeLow = qwx.l;
  59. }
  60. STATIC INLINE QWORD QwPMDBTime( PAGE *ppage )
  61. {
  62. QWORDX qwx;
  63. qwx.l = ppage->ulDBTimeLow;
  64. qwx.h = (ULONG) ppage->bDBTimeHigh;
  65. return qwx.qw;
  66. }
  67. STATIC INLINE VOID PMIncDBTime( PAGE *ppage )
  68. {
  69. QWORDX qwx;
  70. qwx.qw = QwPMDBTime( ppage );
  71. qwx.qw++;
  72. PMSetDBTime( ppage, qwx.qw );
  73. }
  74. #define bitLink (1L<<31)
  75. #define pgtypFDP ((PGTYP) 0)
  76. #define pgtypRecord ((PGTYP) 1)
  77. #define pgtypIndexNC ((PGTYP) 2)
  78. #define pgtypSort ((PGTYP) 4)
  79. #define PMSetPageType( ppage, pgtypT ) ( (ppage)->pgtyp = pgtypT )
  80. #define PMPageTypeOfPage( ppage ) ( (PGTYP)( (ppage)->pgtyp) )
  81. #ifdef DEBUG
  82. VOID PMSetModified( SSIB *ssib );
  83. VOID PMResetModified( SSIB *pssib );
  84. VOID CheckPgno( PAGE *ppage, PN pn );
  85. #else
  86. #define CheckPgno( ppage, pn )
  87. #define PMSetModified( pssib ) ( (pssib)->pbf->ppage->bitModified = 1 )
  88. #define PMResetModified( pssib ) ( (pssib)->pbf->ppage->bitModified = 0 )
  89. #endif
  90. #define PMPageSetModified( ppage ) ( (ppage)->bitModified = 1 )
  91. #define PMPageResetModified( ppage ) ( (ppage)->bitModified = 0 )
  92. #define FPMPageModified( ppage ) ( (ppage)->bitModified )
  93. #define PMSetPgnoFDP( ppage, pgnoT ) ( (ppage)->pgnoFDP = pgnoT )
  94. #define PgnoPMPgnoFDPOfPage( ppage ) ( (ppage)->pgnoFDP )
  95. #define SetPgno( ppage, pgno ) \
  96. ThreeBytesFromL( &(ppage)->pgnoThisPage, (pgno) )
  97. #define SetPgnoNext( ppage, pgno ) \
  98. ThreeBytesFromL( &(ppage)->pgnoNext, (pgno) )
  99. #define SetPgnoPrev( ppage, pgno ) \
  100. ThreeBytesFromL( &(ppage)->pgnoPrev, (pgno) )
  101. #define PgnoFromPage( ppage, ppgno ) \
  102. LFromThreeBytes( ppgno, &(ppage)->pgnoThisPage )
  103. #ifdef DEBUG
  104. #define PgnoNextFromPage( pssib, ppgno ) \
  105. { CheckSSIB( pssib ); LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoNext ); }
  106. #define PgnoPrevFromPage( pssib, ppgno ) \
  107. { CheckSSIB( (pssib) ); LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoPrev ); }
  108. #else
  109. #define PgnoNextFromPage( pssib, ppgno ) \
  110. LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoNext )
  111. #define PgnoPrevFromPage( pssib, ppgno ) \
  112. LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoPrev )
  113. #endif
  114. #define absdiff( x, y ) ( (x) > (y) ? (x)-(y) : (y)-(x) )
  115. #define pgdiscont( pgno1, pgno2 ) \
  116. ( ( (pgno1) == 0 ) || ( (pgno2) == 0 ) ? 0 \
  117. : absdiff( (pgno1), (pgno2) ) / cpgDiscont )
  118. #define ibPgnoPrevPage ( (INT) (ULONG_PTR)&((PAGE *)0)->pgnoPrev )
  119. #define ibPgnoNextPage ( (INT) (ULONG_PTR)&((PAGE *)0)->pgnoNext )
  120. #define ibCbFreeTotal ( (INT) (ULONG_PTR)&((PAGE *)0)->cbFree )
  121. #define ibCtagMac ( (INT) (ULONG_PTR)&((PAGE *)0)->ctagMac )
  122. #define ibPgtyp ( (INT) (ULONG_PTR)&((PAGE *)0)->pgtyp )
  123. #define CbLastFreeSpace(ppage) \
  124. ( (ppage)->ibMic \
  125. - sizeof(PGHDR) \
  126. - ( sizeof(TAG) * (ppage)->ctagMac ) )
  127. #define IbCbFromPtag( ibP, cbP, ptagP ) \
  128. { TAG *_ptagT = ptagP; \
  129. (ibP) = _ptagT->ib; \
  130. (cbP) = _ptagT->cb; \
  131. }
  132. #define PtagFromIbCb( ptagP, ibP, cbP ) \
  133. { TAG *_ptagT = ptagP; \
  134. _ptagT->ib = (SHORT)(ibP); \
  135. _ptagT->cb = (SHORT)(cbP); \
  136. }
  137. #ifdef DEBUG
  138. #define PMGet( pssib, itagT ) CallS( ErrPMGet( pssib, itagT ) )
  139. #else
  140. #define PMGet( pssib, itagT ) \
  141. { \
  142. PAGE *ppageT_ = (pssib)->pbf->ppage; \
  143. TAG *ptagT_ = &(ppageT_->rgtag[itagT]); \
  144. Assert( itagT >= 0 ); \
  145. Assert( itagT < (pssib)->pbf->ppage->ctagMac ); \
  146. (pssib)->line.pb = (BYTE *)ppageT_ + ptagT_->ib; \
  147. (pssib)->line.cb = ptagT_->cb; \
  148. }
  149. #endif
  150. #define ItagPMMost( ppage ) ((ppage)->ctagMac - 1)
  151. BOOL FPMFreeTag( SSIB *pssib, INT citagReq );
  152. #ifdef DEBUG
  153. // This call does not guarantee the accuracy of cbUncommittedFree.
  154. // If accuracy is needed, call CbNDFreePageSpace() instead.
  155. #define CbPMFreeSpace( pssib ) ( CheckSSIB(pssib), \
  156. ((INT)( (pssib)->pbf->ppage->cbFree - (pssib)->pbf->ppage->cbUncommittedFreed ) ) )
  157. #else
  158. #define CbPMFreeSpace( pssib ) \
  159. ((INT)( (pssib)->pbf->ppage->cbFree - (pssib)->pbf->ppage->cbUncommittedFreed ) )
  160. #endif
  161. #if 0 // No longer needed with uncommitted freed page space count
  162. #define PMAllocFreeSpace( pssib, cb ) \
  163. { \
  164. Assert( (INT)(pssib)->pbf->ppage->cbFree >= cb ); \
  165. (pssib)->pbf->ppage->cbFree -= cb; \
  166. }
  167. #define PMFreeFreeSpace( pssib, cb ) \
  168. { \
  169. Assert( (INT)(pssib)->pbf->ppage->cbFree >= 0 ); \
  170. (pssib)->pbf->ppage->cbFree += cb; \
  171. Assert( (INT)(pssib)->pbf->ppage->cbFree < cbPage ); \
  172. }
  173. #endif
  174. #ifdef DEBUG
  175. #define AssertBTFOP(pssib) \
  176. Assert( PMPageTypeOfPage((pssib)->pbf->ppage) == pgtypSort || \
  177. PMPageTypeOfPage((pssib)->pbf->ppage) == pgtypFDP || \
  178. (pssib)->itag != 0 || \
  179. ( CbNDKey( (pssib)->line.pb ) == 0 && \
  180. !FNDBackLink( *(pssib)->line.pb ) ) \
  181. )
  182. #else
  183. #define AssertBTFOP( pssib )
  184. #endif
  185. #define PbPMGetChunk(pssib, ib) &(((BYTE *)((pssib)->pbf->ppage))[ib])
  186. INT CbPMLinkSpace( SSIB *pssib );
  187. TS TsPMTagstatus( PAGE *ppage, INT itag );
  188. VOID PMInitPage( PAGE *ppage, PGNO pgno, PGTYP pgtyp, PGNO pgnoFDP );
  189. INT ItagPMQueryNextItag( SSIB *pssib );
  190. ERR ErrPMInsert( SSIB *pssib, LINE *rgline, INT cline );
  191. VOID PMDelete( SSIB *ssib );
  192. ERR ErrPMReplace( SSIB *pssib, LINE *rgline, INT cline );
  193. ERR ErrPMGet( SSIB *pssib, INT itag );
  194. VOID PMGetLink( SSIB *pssib, INT itag, LINK *plink );
  195. VOID PMExpungeLink( SSIB *pssib );
  196. VOID PMReplaceWithLink( SSIB *pssib, SRID srid );
  197. VOID PMReplaceLink( SSIB *pssib, SRID srid );
  198. INT CPMIFreeTag( PAGE *ppage );
  199. BOOL FPMEmptyPage( SSIB *pssib );
  200. BOOL FPMLastNode( SSIB *pssib );
  201. BOOL FPMLastNodeWithLinks( SSIB *pssib );
  202. VOID PMDirty( SSIB *pssib );
  203. VOID PMReadAsync( PIB *ppib, PN pn );
  204. ERR ErrPMAccessPage( FUCB *pfucb, PGNO pgno );
  205. #ifdef DEBUG
  206. VOID PageConsistent( PAGE *ppage );
  207. #endif