|
|
//
//------ Page Structure ---------------------------------------------------
//
#define cbPage 4096 // database logical page size
#define ctagMax 256 // default limit on number of tags
typedef BYTE PGTYP;
// the pragma is bad for efficiency, but we need it here so that the
// THREEBYTES will not be aligned on 4-byte boundary
#pragma pack(1)
typedef struct _pghdr { ULONG ulChecksum; // checksum of page, always 1st byte
ULONG ulDBTimeLow; // database time page dirtied
PGNO pgnoFDP; // pgno of FDP which owns this page
SHORT cbFree; // count free bytes
SHORT ibMic; // minimum used byte
SHORT ctagMac; // count tags used
SHORT itagFree; // itag of first free tag
SHORT cbUncommittedFreed; // bytes freed from this page, but *possibly*
// uncommitted (this number will always be
// a subset of cbFree)
THREEBYTES pgnoPrev; // pgno of previous page
THREEBYTES pgnoNext; // pgno of next page
} PGHDR;
typedef struct _pgtrlr { PGTYP pgtyp:3; BYTE bDBTimeHigh:4; BYTE bitModified:1; THREEBYTES pgnoThisPage; } PGTRLR;
typedef struct _tag { SHORT cb; SHORT ib; } TAG;
/* tag status
/**/ typedef enum { tsLine, tsVacant, tsLink } TS;
typedef struct _page { PGHDR; TAG rgtag[1]; BYTE rgbFiller[ cbPage - sizeof(PGHDR) - // pghdr
sizeof(TAG) - // rgtag[1]
sizeof(BYTE) - // rgbData[1]
sizeof(PGTRLR) ]; // pgtyp and pgnoThisPage
BYTE rgbData[1];
PGTRLR; } PAGE;
#pragma pack()
STATIC INLINE VOID PMSetDBTime( PAGE *ppage, QWORD qwDBTime ) { QWORDX qwx; qwx.qw = qwDBTime; ppage->bDBTimeHigh = (BYTE) qwx.h; ppage->ulDBTimeLow = qwx.l; }
STATIC INLINE QWORD QwPMDBTime( PAGE *ppage ) { QWORDX qwx; qwx.l = ppage->ulDBTimeLow; qwx.h = (ULONG) ppage->bDBTimeHigh; return qwx.qw; }
STATIC INLINE VOID PMIncDBTime( PAGE *ppage ) { QWORDX qwx; qwx.qw = QwPMDBTime( ppage ); qwx.qw++; PMSetDBTime( ppage, qwx.qw ); }
#define bitLink (1L<<31)
#define pgtypFDP ((PGTYP) 0)
#define pgtypRecord ((PGTYP) 1)
#define pgtypIndexNC ((PGTYP) 2)
#define pgtypSort ((PGTYP) 4)
#define PMSetPageType( ppage, pgtypT ) ( (ppage)->pgtyp = pgtypT )
#define PMPageTypeOfPage( ppage ) ( (PGTYP)( (ppage)->pgtyp) )
#ifdef DEBUG
VOID PMSetModified( SSIB *ssib ); VOID PMResetModified( SSIB *pssib ); VOID CheckPgno( PAGE *ppage, PN pn ); #else
#define CheckPgno( ppage, pn )
#define PMSetModified( pssib ) ( (pssib)->pbf->ppage->bitModified = 1 )
#define PMResetModified( pssib ) ( (pssib)->pbf->ppage->bitModified = 0 )
#endif
#define PMPageSetModified( ppage ) ( (ppage)->bitModified = 1 )
#define PMPageResetModified( ppage ) ( (ppage)->bitModified = 0 )
#define FPMPageModified( ppage ) ( (ppage)->bitModified )
#define PMSetPgnoFDP( ppage, pgnoT ) ( (ppage)->pgnoFDP = pgnoT )
#define PgnoPMPgnoFDPOfPage( ppage ) ( (ppage)->pgnoFDP )
#define SetPgno( ppage, pgno ) \
ThreeBytesFromL( &(ppage)->pgnoThisPage, (pgno) ) #define SetPgnoNext( ppage, pgno ) \
ThreeBytesFromL( &(ppage)->pgnoNext, (pgno) ) #define SetPgnoPrev( ppage, pgno ) \
ThreeBytesFromL( &(ppage)->pgnoPrev, (pgno) )
#define PgnoFromPage( ppage, ppgno ) \
LFromThreeBytes( ppgno, &(ppage)->pgnoThisPage ) #ifdef DEBUG
#define PgnoNextFromPage( pssib, ppgno ) \
{ CheckSSIB( pssib ); LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoNext ); } #define PgnoPrevFromPage( pssib, ppgno ) \
{ CheckSSIB( (pssib) ); LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoPrev ); } #else
#define PgnoNextFromPage( pssib, ppgno ) \
LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoNext ) #define PgnoPrevFromPage( pssib, ppgno ) \
LFromThreeBytes( ppgno, &(pssib)->pbf->ppage->pgnoPrev ) #endif
#define absdiff( x, y ) ( (x) > (y) ? (x)-(y) : (y)-(x) )
#define pgdiscont( pgno1, pgno2 ) \
( ( (pgno1) == 0 ) || ( (pgno2) == 0 ) ? 0 \ : absdiff( (pgno1), (pgno2) ) / cpgDiscont )
#define ibPgnoPrevPage ( (INT) (ULONG_PTR)&((PAGE *)0)->pgnoPrev )
#define ibPgnoNextPage ( (INT) (ULONG_PTR)&((PAGE *)0)->pgnoNext )
#define ibCbFreeTotal ( (INT) (ULONG_PTR)&((PAGE *)0)->cbFree )
#define ibCtagMac ( (INT) (ULONG_PTR)&((PAGE *)0)->ctagMac )
#define ibPgtyp ( (INT) (ULONG_PTR)&((PAGE *)0)->pgtyp )
#define CbLastFreeSpace(ppage) \
( (ppage)->ibMic \ - sizeof(PGHDR) \ - ( sizeof(TAG) * (ppage)->ctagMac ) )
#define IbCbFromPtag( ibP, cbP, ptagP ) \
{ TAG *_ptagT = ptagP; \ (ibP) = _ptagT->ib; \ (cbP) = _ptagT->cb; \ }
#define PtagFromIbCb( ptagP, ibP, cbP ) \
{ TAG *_ptagT = ptagP; \ _ptagT->ib = (SHORT)(ibP); \ _ptagT->cb = (SHORT)(cbP); \ }
#ifdef DEBUG
#define PMGet( pssib, itagT ) CallS( ErrPMGet( pssib, itagT ) )
#else
#define PMGet( pssib, itagT ) \
{ \ PAGE *ppageT_ = (pssib)->pbf->ppage; \ TAG *ptagT_ = &(ppageT_->rgtag[itagT]); \ Assert( itagT >= 0 ); \ Assert( itagT < (pssib)->pbf->ppage->ctagMac ); \ (pssib)->line.pb = (BYTE *)ppageT_ + ptagT_->ib; \ (pssib)->line.cb = ptagT_->cb; \ } #endif
#define ItagPMMost( ppage ) ((ppage)->ctagMac - 1)
BOOL FPMFreeTag( SSIB *pssib, INT citagReq );
#ifdef DEBUG
// This call does not guarantee the accuracy of cbUncommittedFree.
// If accuracy is needed, call CbNDFreePageSpace() instead.
#define CbPMFreeSpace( pssib ) ( CheckSSIB(pssib), \
((INT)( (pssib)->pbf->ppage->cbFree - (pssib)->pbf->ppage->cbUncommittedFreed ) ) ) #else
#define CbPMFreeSpace( pssib ) \
((INT)( (pssib)->pbf->ppage->cbFree - (pssib)->pbf->ppage->cbUncommittedFreed ) ) #endif
#if 0 // No longer needed with uncommitted freed page space count
#define PMAllocFreeSpace( pssib, cb ) \
{ \ Assert( (INT)(pssib)->pbf->ppage->cbFree >= cb ); \ (pssib)->pbf->ppage->cbFree -= cb; \ }
#define PMFreeFreeSpace( pssib, cb ) \
{ \ Assert( (INT)(pssib)->pbf->ppage->cbFree >= 0 ); \ (pssib)->pbf->ppage->cbFree += cb; \ Assert( (INT)(pssib)->pbf->ppage->cbFree < cbPage ); \ } #endif
#ifdef DEBUG
#define AssertBTFOP(pssib) \
Assert( PMPageTypeOfPage((pssib)->pbf->ppage) == pgtypSort || \ PMPageTypeOfPage((pssib)->pbf->ppage) == pgtypFDP || \ (pssib)->itag != 0 || \ ( CbNDKey( (pssib)->line.pb ) == 0 && \ !FNDBackLink( *(pssib)->line.pb ) ) \ ) #else
#define AssertBTFOP( pssib )
#endif
#define PbPMGetChunk(pssib, ib) &(((BYTE *)((pssib)->pbf->ppage))[ib])
INT CbPMLinkSpace( SSIB *pssib ); TS TsPMTagstatus( PAGE *ppage, INT itag ); VOID PMInitPage( PAGE *ppage, PGNO pgno, PGTYP pgtyp, PGNO pgnoFDP ); INT ItagPMQueryNextItag( SSIB *pssib ); ERR ErrPMInsert( SSIB *pssib, LINE *rgline, INT cline ); VOID PMDelete( SSIB *ssib ); ERR ErrPMReplace( SSIB *pssib, LINE *rgline, INT cline ); ERR ErrPMGet( SSIB *pssib, INT itag ); VOID PMGetLink( SSIB *pssib, INT itag, LINK *plink ); VOID PMExpungeLink( SSIB *pssib ); VOID PMReplaceWithLink( SSIB *pssib, SRID srid ); VOID PMReplaceLink( SSIB *pssib, SRID srid ); INT CPMIFreeTag( PAGE *ppage ); BOOL FPMEmptyPage( SSIB *pssib ); BOOL FPMLastNode( SSIB *pssib ); BOOL FPMLastNodeWithLinks( SSIB *pssib );
VOID PMDirty( SSIB *pssib ); VOID PMReadAsync( PIB *ppib, PN pn ); ERR ErrPMAccessPage( FUCB *pfucb, PGNO pgno );
#ifdef DEBUG
VOID PageConsistent( PAGE *ppage ); #endif
|