|
|
#ifndef _STAPI_H
#define _STAPI_H
// Redirect Asserts in inline code to seem to fire from this file
#define szAssertFilename __FILE__
//---- externs -------------------------------------------------------------
extern CRIT critBuf; extern TRX trxOldest; extern TRX trxNewest; extern CRIT critCommit0;
extern SIG sigBFCleanProc;
//---- IO (io.c) ----------------------------------------------------------
ERR ErrIOInit( VOID ); ERR ErrIOTerm( BOOL fNormal );
/* Reserve first 2 pages of a database.
*/ #define cpageDBReserved 2
STATIC INLINE LONG LOffsetOfPgnoLow( PGNO pgno ) { return ( pgno -1 + cpageDBReserved ) << 12; } STATIC INLINE LONG LOffsetOfPgnoHigh( PGNO pgno ) { return ( pgno -1 + cpageDBReserved ) >> 20; }
VOID IOCloseFile( HANDLE hf ); ERR ErrIONewSize( DBID dbid, CPG cpg );
BOOL FIOFileExists( CHAR *szFileName ); ERR ErrIOLockDbidByNameSz( CHAR *szFileName, DBID *pdbid ); ERR ErrIOLockDbidByDbid( DBID dbid ); ERR ErrIOLockNewDbid( DBID *pdbid, CHAR *szDatabaseName ); ERR ErrIOSetDbid( DBID dbid, CHAR *szDatabaseName ); VOID IOFreeDbid( DBID dbid ); void BFOldestLgpos( LGPOS *plgposCheckPoint ); VOID BFPurge( DBID dbid );
STATIC INLINE BOOL FIODatabaseOpen ( DBID dbid ) { AssertCriticalSection( critJet ); return rgfmp[dbid].hf != handleNil; }
ERR ErrIOOpenDatabase( DBID dbid, CHAR *szDatabaseName, CPG cpg ); VOID IOCloseDatabase( DBID dbid ); ERR ErrIODeleteDatabase( DBID dbid ); BOOL FIODatabaseInUse( DBID dbid ); BOOL FIODatabaseAvailable( DBID dbid );
STATIC INLINE VOID IOUnlockDbid( DBID dbid ) { SgEnterCriticalSection( critBuf ); Assert( FDBIDWait( dbid ) ); DBIDResetWait( dbid ); SgLeaveCriticalSection( critBuf ); }
STATIC INLINE BOOL FIOExclusiveByAnotherSession( DBID dbid, PIB *ppib ) { Assert( FDBIDWait( dbid ) ); return FDBIDExclusiveByAnotherSession( dbid, ppib ); }
STATIC INLINE VOID IOSetExclusive( DBID dbid, PIB *ppib ) { Assert( FDBIDWait( dbid ) ); Assert( !( FDBIDExclusive( dbid ) ) ); DBIDSetExclusive( dbid, ppib ); }
STATIC INLINE VOID IOResetExclusive( DBID dbid ) { Assert( FDBIDWait( dbid ) ); DBIDResetExclusive( dbid ); }
STATIC INLINE BOOL FIOReadOnly( DBID dbid ) { Assert( FDBIDWait( dbid ) ); return FDBIDReadOnly( dbid ); }
STATIC INLINE VOID IOSetReadOnly( DBID dbid ) { Assert( FDBIDWait( dbid ) ); DBIDSetReadOnly( dbid ); }
STATIC INLINE VOID IOResetReadOnly( DBID dbid ) { Assert( FDBIDWait( dbid ) ); DBIDResetReadOnly( dbid ); }
STATIC INLINE BOOL FIOAttached( DBID dbid ) { Assert( FDBIDWait( dbid ) ); return FDBIDAttached( dbid ); }
STATIC INLINE VOID IOSetAttached( DBID dbid ) { Assert( FDBIDWait( dbid ) ); Assert( !( FDBIDAttached( dbid ) ) ); DBIDSetAttached( dbid ); }
STATIC INLINE VOID IOResetAttached( DBID dbid ) { Assert( FDBIDWait( dbid ) ); Assert( FDBIDAttached( dbid ) ); DBIDResetAttached( dbid ); }
//---- BUF (buf.c) ----------------------------------------------------------
typedef struct _lru // LRU List
{ LONG cbfAvail; // clean available buffers in LRU list
struct _bf *pbfLRU; // Least Recently Used buffer
struct _bf *pbfMRU; // Most Recently Used buffer
} LRULIST; typedef struct _bgcb // Buffer Group Control Block
{ struct _bgcb *pbgcbNext; // pointer to the next BCGB
struct _bf *rgbf; // buffer control blocks for group
struct _page *rgpage; // buffer control blocks for group
LONG cbfGroup; // number of bfs in this group
LONG cbfThresholdLow; // threshold to start cleaning buffers
LONG cbfThresholdHigh; // threshold to stop cleaning buffers
LRULIST lrulist; } BGCB;
#define pbgcbNil ((BGCB*)0)
#define PbgcbMEMAlloc() (BGCB*)PbMEMAlloc(iresBGCB)
#ifdef DEBUG /* Debug check for illegal use of freed bgcb */
#define MEMReleasePbgcb(pbgcb) { MEMRelease(iresBGCB, (BYTE*)(pbgcb)); pbgcb = pbgcbNil; }
#else
#define MEMReleasePbgcb(pbgcb) { MEMRelease(iresBGCB, (BYTE*)(pbgcb)); }
#endif
#define BUT INT
#define butBuffer 0
#define butHistory 1
#define ibfNotUsed -1
typedef struct _he { BUT but:2; // must use 2 bits to avoid sign extension when converting to int
INT ibfHashNext:30; // hash table overflow
} HE;
typedef struct _hist { ULONG ulBFTime; PN pn; INT ipbfHISTHeap; } HIST;
typedef struct _bf { struct _page *ppage; // pointer to page buffer
#if defined( _X86_ ) && defined( X86_USE_SEM )
LONG volatile lLock; // num of locks being asked
LONG cSemWait; // num of user waiting for on semaphore
SEM sem; #endif // defined( _X86_ ) && defined( X86_USE_SEM )
PN pn; // physical pn of cached page
ULONG fDirty:1; // indicates page needs to be flushed
// the following flags are mutual exclusive:
ULONG fDirectRead:1; // buffer is being direct read
ULONG fAsyncRead:1; // buffer is being async read
ULONG fSyncRead:1; // buffer is being sync read
ULONG fAsyncWrite:1; // buffer is being async written
ULONG fSyncWrite:1; // buffer is being sync written
ULONG fHold:1; // buffer is in transient state
ULONG fIOError:1; // indicates read/write error
#ifdef DEBUG
ULONG fInHash:1; // BF is currently in hash table
#endif // DEBUG
ULONG fInLRUK:1; // BF is in LRUK heap or LRUK list
ULONG fVeryOld:1; // BF is very old relative to last check point
ULONG fPatch:1; // BF is being written to the patch file
ULONG fNeedPatch:1; // BF need to write patch file after regular write.
LONG ipbfHeap; // index in heap
LONG cWriteLatch; // if cWriteLatch > 0, page cannot be updated by other
LONG cWaitLatch; LONG cPin; // if cPin > 0 then buf cannot be overlayed
#ifdef READ_LATCH
LONG cReadLatch; // if cReadLatch > 0, page cannot be updated
#endif // READ_LATCH
PIB *ppibWriteLatch; // thread with write latch
PIB *ppibWaitLatch; // thread with wait latch
struct _bf *pbfLRU; // pointer to less recently used buffer
struct _bf *pbfMRU; // pointer to more recently used buffer
TRX trxLastRef; // last transaction that referenced us
ULONG ulBFTime1; // last reference time
ULONG ulBFTime2; // previous to last reference time
struct _bf *pbfNextBatchIO; // next BF in BatchIO list
LONG ipageBatchIO; ERR err; // error code for err occurs during the IO
SIG sigIOComplete; // set (if valid) when IO on BF is completed
SIG sigSyncIOComplete; // set (if valid) when sync IO on BF is completed
union { ULONG cpageDirectRead; // count of prior BFs to be flushed
ULONG cDepend; // count of prior BFs to be flushed
}; union { PAGE *ppageDirectRead; struct _bf *pbfDepend; // BF to be flushed after this one
}; LGPOS lgposRC; // log ptr to BeginT of oldest modifying xact
LGPOS lgposModify; // log ptr of entry for last page modify
struct _rce *prceDeferredBINext; // dbl link list for deferred before image.
#ifdef COSTLY_PERF
LONG lClass; // Table Class of which this BF is a member
#endif // COSTLY_PERF
HE rghe[2]; // 0 for buffer, 1 for history.
HIST hist; // borrow the space in bf structure to keep HIST.
#ifdef PCACHE_OPTIMIZATION
//#if !defined( _X86_ ) || !defined( X86_USE_SEM )
// BYTE rgbFiller[32];
//#endif
#ifndef COSTLY_PERF
BYTE rgbFiller2[4]; // pad BF to 32 byte boundary
#endif // !COSTLY_PERF
#endif // PCACHE_OPTIMIZATION
} BF; #define pbfNil ((BF *) 0)
ERR ErrBFInit( VOID ); VOID BFTerm( BOOL fNormal );
#if defined( _X86_ ) && defined( X86_USE_SEM )
VOID BFIEnterCriticalSection( BF *pbf ); VOID BFILeaveCriticalSection( BF *pbf );
STATIC INLINE VOID BFEnterCriticalSection( BF *pbf ) { LONG volatile *plLock = &pbf->lLock;
// use bit test and set instruction
_asm { mov eax, plLock lock inc [eax] // If already set go to busy, otherwise return TRUE
jnz busy } ; return; busy: BFIEnterCriticalSection( pbf ); }
STATIC INLINE VOID BFLeaveCriticalSection( BF *pbf ) { LONG volatile *plLock = &pbf->lLock;
_asm { mov eax, plLock lock dec [eax] jge wake } return; wake: BFILeaveCriticalSection( pbf ); }
#else
extern int ccritBF; extern int critBFHashConst; extern CRIT *rgcritBF; #define IcritHash( ibf ) ((ibf) & critBFHashConst )
#define BFEnterCriticalSection( pbf ) UtilEnterCriticalSection( rgcritBF[ IcritHash((ULONG)((ULONG_PTR)pbf) / sizeof(BF) ) ])
#define BFLeaveCriticalSection( pbf ) UtilLeaveCriticalSection( rgcritBF[ IcritHash((ULONG)((ULONG_PTR)pbf) / sizeof(BF) ) ])
#endif
ERR ErrBFAccessPage( PIB *ppib, BF **ppbf, PN pn ); ERR ErrBFReadAccessPage( FUCB *pfucb, PGNO pgno ); ERR ErrBFWriteAccessPage( FUCB *pfucb, PGNO pgno ); VOID BFAbandon( PIB *ppib, BF *pbf ); VOID BFTossImmediate( PIB *ppib, BF *pbf ); ERR ErrBFAllocPageBuffer( PIB *ppib, BF **ppbf, PN pn, LGPOS lgposRC, BYTE pgtyp ); ERR ErrBFAllocTempBuffer( BF **ppbf ); VOID BFFree( BF *pbf ); VOID BFPreread( PN pn, CPG cpg, CPG *pcpgActual ); VOID BFPrereadList( PN * rgpnPages, CPG *pcpgActual ); ERR ErrBFDirectRead( DBID dbid, PGNO pgnoStart, PAGE *ppage, INT cpage ); VOID BFDeferRemoveDependence( BF *pbf ); #define fBFWait fFalse
#define fBFNoWait fTrue
ERR ErrBFRemoveDependence( PIB *ppib, BF *pbf, BOOL fNoWait ); BOOL FBFCheckDependencyChain( BF *pbf );
/* buffer flush prototype and flags
/**/ #define fBFFlushSome 0
#define fBFFlushAll 1
ERR ErrBFFlushBuffers( DBID dbid, LONG fBFFlush );
STATIC INLINE VOID BFSFree( BF *pbf ) { SgEnterCriticalSection( critBuf ); BFFree( pbf ); SgLeaveCriticalSection( critBuf ); }
/* the following small functions are called too often, */ /* make it as a macros
/**/ DBID DbidOfPn( PN pn ); PGNO PgnoOfPn( PN pn );
#ifdef COSTLY_PERF
extern unsigned long cBFClean[]; extern unsigned long cBFNewDirties[]; #else // !COSTLY_PERF
extern unsigned long cBFClean; extern unsigned long cBFNewDirties; #endif // COSTLY_PERF
#ifdef DEBUG
VOID BFSetDirtyBit( BF *pbf ); #else
STATIC INLINE VOID BFSetDirtyBit( BF *pbf ) { QWORD qwDBTime = QwPMDBTime( pbf->ppage ); BFEnterCriticalSection( pbf ); if ( !fRecovering && qwDBTime > QwDBHDRDBTime( rgfmp[ DbidOfPn(pbf->pn) ].pdbfilehdr ) ) DBHDRSetDBTime( rgfmp[ DbidOfPn(pbf->pn) ].pdbfilehdr, qwDBTime ); if ( !pbf->fDirty ) { #ifdef COSTLY_PERF
cBFClean[pbf->lClass]--; cBFNewDirties[pbf->lClass]++; #else // !COSTLY_PERF
cBFClean--; cBFNewDirties++; #endif // COSTLY_PERF
pbf->fDirty = fTrue; } BFLeaveCriticalSection( pbf ); } #endif
/* resets a BFs dirty flag
/**/
extern BOOL fLogDisabled;
STATIC INLINE VOID BFResetDirtyBit( BF *pbf ) { BFEnterCriticalSection( pbf ); Assert( fRecovering || pbf->fSyncWrite || pbf->cWriteLatch == 0 ); pbf->fVeryOld = fFalse; Assert( fLogDisabled || fRecovering || !rgfmp[DbidOfPn( pbf->pn )].fLogOn || memcmp( &pbf->lgposRC, &lgposMax, sizeof( LGPOS ) ) != 0 );
pbf->lgposRC = lgposMax; if ( pbf->fDirty ) { #ifdef COSTLY_PERF
cBFClean[pbf->lClass]++; #else // !COSTLY_PERF
cBFClean++; #endif // COSTLY_PERF
pbf->fDirty = fFalse; } BFLeaveCriticalSection( pbf ); }
STATIC INLINE VOID BFDirty( BF *pbf ) { DBID dbid = DbidOfPn( pbf->pn );
Assert( !pbf->fHold );
BFSetDirtyBit( pbf );
/* set ulDBTime for logging and also for multiple cursor
/* maintenance, so that cursors can detect a change.
/**/ Assert( fRecovering || dbid == dbidTemp || QwPMDBTime( pbf->ppage ) <= QwDBHDRDBTime( rgfmp[dbid].pdbfilehdr ) );
DBHDRIncDBTime( rgfmp[dbid].pdbfilehdr ); PMSetDBTime( pbf->ppage, QwDBHDRDBTime( rgfmp[dbid].pdbfilehdr ) ); }
/* check if a page is dirty. If it is allocated for temp buffer, whose
* pn must be Null, then no need to check if it is dirty since it will * not be written out. */ #define AssertBFDirty( pbf ) \
Assert( (pbf)->pn == pnNull || \ (pbf) != pbfNil && (pbf)->fDirty == fTrue )
#define AssertBFPin( pbf ) Assert( (pbf)->cPin > 0 )
#define AssertBFWaitLatched( pbf, ppib ) \
Assert( (pbf)->cWaitLatch > 0 \ && (pbf)->cPin > 0 \ && (pbf)->ppibWaitLatch == (ppib) );
STATIC INLINE VOID BFPin( BF *pbf ) { #ifdef DEBUG
BFEnterCriticalSection( pbf ); Assert( pbf != pbfNil ); Assert( !pbf->fSyncRead ); Assert( !pbf->fAsyncRead ); Assert( pbf->cPin >= 0 ); pbf->cPin++; BFLeaveCriticalSection( pbf ); #else // !DEBUG
UtilInterlockedIncrement( &pbf->cPin ); #endif // DEBUG
}
STATIC INLINE VOID BFUnpin( BF *pbf ) { #ifdef DEBUG
BFEnterCriticalSection( pbf ); Assert( pbf != pbfNil ); Assert( !pbf->fSyncRead ); Assert( !pbf->fAsyncRead ); Assert( pbf->cPin > 0 ); pbf->cPin--; BFLeaveCriticalSection( pbf ); #else // !DEBUG
UtilInterlockedDecrement( &pbf->cPin ); #endif // DEBUG
}
STATIC INLINE VOID BFSetReadLatch( BF *pbf, PIB *ppib ) { #ifdef READ_LATCH
BFPin( pbf ); Assert( pbf->cWriteLatch == 0 || pbf->ppibWriteLatch == ppib ); pbf->cReadLatch++; #endif // READ_LATCH
}
STATIC INLINE VOID BFResetReadLatch( BF *pbf, PIB *ppib ) { #ifdef READ_LATCH
Assert( pbf->cReadLatch > 0 ); Assert( pbf->cWriteLatch == 0 || pbf->ppibWriteLatch == ppib ); pbf->cReadLatch--; BFUnpin( pbf ); #endif // READ_LATCH
}
STATIC INLINE BOOL FBFReadLatchConflict( PIB *ppib, BF *pbf ) { #ifdef READ_LATCH
return pbf->cWriteLatch > 0 && pbf->ppibWriteLatch != ppib; #else // !READ_LATCH
return fFalse; #endif // READ_LATCH
}
STATIC INLINE VOID BFSetWriteLatch( BF *pbf, PIB *ppib ) { BFPin( pbf ); #ifdef READ_LATCH
Assert( pbf->cReadLatch == 0 ); #endif // READ_LATCH
Assert( pbf->cWriteLatch == 0 || pbf->ppibWriteLatch == ppib ); pbf->cWriteLatch++; pbf->ppibWriteLatch = ppib; }
STATIC INLINE VOID BFResetWriteLatch( BF *pbf, PIB *ppib ) { #ifdef READ_LATCH
Assert( pbf->cReadLatch == 0 ); #endif // READ_LATCH
Assert( pbf->cWriteLatch > 0 ); Assert( pbf->ppibWriteLatch == ppib ); pbf->cWriteLatch--; BFUnpin( pbf ); }
STATIC INLINE BOOL FBFWriteLatchConflict( PIB *ppib, BF *pbf ) { return #ifdef READ_LATCH
pbf->cReadLatch > 0 || #endif // READ_LATCH
( pbf->cWriteLatch > 0 && pbf->ppibWriteLatch != ppib ); }
STATIC INLINE BOOL FBFWriteLatch( PIB *ppib, BF *pbf ) { return pbf->cWriteLatch > 0 && pbf->ppibWriteLatch == ppib; }
STATIC INLINE VOID BFSetWaitLatch( BF *pbf, PIB *ppib ) { AssertCriticalSection( critJet ); BFSetWriteLatch( pbf, ppib ); Assert( pbf->cWaitLatch == 0 || pbf->ppibWaitLatch == ppib ); pbf->cWaitLatch++; pbf->ppibWaitLatch = ppib; }
STATIC INLINE VOID BFResetWaitLatch( BF *pbf, PIB *ppib ) { AssertCriticalSection( critJet ); Assert( pbf->cWaitLatch > 0 ); Assert( pbf->ppibWaitLatch == ppib ); pbf->cWaitLatch--; BFResetWriteLatch( pbf, ppib ); }
ERR ErrBFDepend( BF *pbf, BF *pbfD );
#ifdef DEBUG
extern ERR ErrLGTrace( PIB *ppib, CHAR *sz ); extern BOOL fDBGTraceBR; #endif
STATIC INLINE VOID BFUndepend( BF *pbf ) { if ( pbf->pbfDepend != pbfNil ) { BF *pbfD = pbf->pbfDepend; #ifdef DEBUG
if ( fDBGTraceBR ) { char sz[256]; sprintf( sz, "UD %ld:%ld->%ld:%ld(%lu)", DbidOfPn( pbf->pn ), PgnoOfPn( pbf->pn ), DbidOfPn( pbf->pbfDepend->pn), PgnoOfPn( pbf->pbfDepend->pn ), pbf->pbfDepend->cDepend ); CallS( ErrLGTrace( ppibNil, sz ) ); } #endif
Assert( pbfD->cDepend > 0 ); BFEnterCriticalSection( pbfD ); pbfD->cDepend--; pbf->pbfDepend = pbfNil; BFLeaveCriticalSection( pbfD ); } }
/*
* When ppib is not Nil and check if a page is in use by checking if it is * Accessible to this PIB. Note that a page is accessible even it is overlay * latched (cPin != 0). This checking accessible is mainly used by BFAccess. * If ppib is nil, basically it is used for freeing a buffer. This is used * by BFClean and BFIAlloc. */
STATIC INLINE BOOL FBFNotAccessible( PIB *ppib, BF *pbf ) { return pbf->fAsyncRead || pbf->fSyncRead || pbf->fAsyncWrite || pbf->fSyncWrite || pbf->fHold || ( pbf->cWaitLatch != 0 && ppib != pbf->ppibWaitLatch ); }
STATIC INLINE BOOL FBFNotAvail( BF *pbf ) { return pbf->fAsyncRead || pbf->fSyncRead || pbf->fAsyncWrite || pbf->fSyncWrite || pbf->fHold || pbf->cPin != 0; }
STATIC INLINE BOOL FBFInUse( PIB *ppib, BF *pbf ) { return ppib != ppibNil ? FBFNotAccessible( ppib, pbf ) : FBFNotAvail( pbf ); }
STATIC INLINE BOOL FBFInUseByOthers( PIB *ppib, BF *pbf ) { return pbf->fAsyncRead || pbf->fSyncRead || pbf->fAsyncWrite || pbf->fSyncWrite || pbf->fHold || pbf->cPin > 1 || ( pbf->cWaitLatch != 0 && ppib != pbf->ppibWaitLatch ) || ( pbf->cWriteLatch != 0 && ppib != pbf->ppibWriteLatch ); }
//---- STORAGE (storage.c) -------------------------------------------------
ERR ErrFMPSetDatabases( PIB *ppib ); extern BOOL fGlobalFMPLoaded; ERR ErrFMPInit( VOID ); VOID FMPTerm( );
#ifdef DEBUG
VOID ITDBGSetConstants(); #endif
ERR ErrITSetConstants( VOID ); ERR ErrITInit( VOID );
#define fTermCleanUp 0x00000001 /* Termination with OLC, Version clean up etc */
#define fTermNoCleanUp 0x00000002 /* Termination without any clean up */
#define fTermError 0x00000004 /* Terminate with error, no OLC clean up, */
/* no flush buffers, db header */
ERR ErrITTerm( INT fTerm );
ERR ErrBFNewPage( FUCB *pfucb, PGNO pgno, PGTYP pgtyp, PGNO pgnoFDP ); VOID BFSleep( unsigned long ulMSecs );
STATIC INLINE PN PnOfDbidPgno( DBID dbid, PGNO pgno ) { return (PN) ( ( (PN) dbid << 24 ) | (PN) pgno ); }
STATIC INLINE DBID DbidOfPn( PN pn ) { return (DBID) ( ( (BYTE *) &pn )[3] ); }
STATIC INLINE PGNO PgnoOfPn( PN pn ) { return (PGNO) ( pn & 0x00FFFFFF ); }
VOID BFReference( BF *pbf, PIB *ppib );
#define FBFReadAccessPage FBFAccessPage
#define FBFWriteAccessPage FBFAccessPage
STATIC INLINE BOOL FBFAccessPage( FUCB *pfucb, PGNO pgno ) { BOOL fAccessible; BF *pbf = pfucb->ssib.pbf;
AssertCriticalSection( critJet ); Assert( pfucb->ppib != ppibNil ); if ( pbf == pbfNil ) return fFalse;
/* if the cached BF's PN is the same and it is accessible and it is in
/* the LRUK heap or list, we can access the page
/**/ BFEnterCriticalSection( pbf ); fAccessible = ( pbf->pn == PnOfDbidPgno( pfucb->dbid, pgno ) && !FBFNotAccessible( pfucb->ppib, pbf ) && pbf->fInLRUK ); BFLeaveCriticalSection( pbf );
#ifdef LRU1
BFReference( pbf, pfucb->ppib ); #else // !LRU1
/* if this is not a correlated access, this counts as a BF reference
/**/ if ( fAccessible && pbf->trxLastRef != pfucb->ppib->trxBegin0 ) BFReference( pbf, pfucb->ppib ); #endif // LRU1
return fAccessible; }
#ifdef DEBUG
#define AssertFBFReadAccessPage AssertFBFAccessPage
#define AssertFBFWriteAccessPage AssertFBFAccessPage
STATIC VOID AssertFBFAccessPage( FUCB *pfucb, PGNO pgno ) { BF *pbf = pfucb->ssib.pbf;
AssertCriticalSection( critJet ); Assert( pfucb->ppib != ppibNil ); Assert( pbf != pbfNil );
/* if the cached BF's PN is the same and it is accessible and it is in
/* the LRUK heap or list, we can access the page
/**/ BFEnterCriticalSection( pbf );
Assert( pbf->pn == PnOfDbidPgno( pfucb->dbid, pgno ) ); Assert( !FBFNotAccessible( pfucb->ppib, pbf ) ); Assert( pbf->fInLRUK );
BFLeaveCriticalSection( pbf ); }
#else // !DEBUG
#define AssertFBFReadAccessPage( pfucbX, pgnoX )
#define AssertFBFWriteAccessPage( pfucbX, pgnoX )
#endif // DEBUG
//---- PAGE (page.c) --------------------------------------------------------
STATIC INLINE QWORD QwSTDBTimePssib( SSIB *pssib ) { return QwPMDBTime( pssib->pbf->ppage ); } STATIC INLINE VOID PMSetQwDBTime( SSIB *pssib, QWORD qw ) { Assert( qw <= QwDBHDRDBTime( rgfmp[DbidOfPn( pssib->pbf->pn )].pdbfilehdr ) ); PMSetDBTime( pssib->pbf->ppage, qw ); }
STATIC INLINE VOID BFSetQwDBTime( BF *pbf, QWORD qw ) { Assert( qw <= QwDBHDRDBTime( rgfmp[DbidOfPn( pbf->pn )].pdbfilehdr ) ); PMSetDBTime( pbf->ppage, qw ); }
#ifdef DEBUG
VOID AssertPMGet( SSIB *pssib, LONG itag ); #else
#define AssertPMGet( pssib, itag )
#endif
// End Assert redirection
#undef szAssertFilename
#endif // _STAPI_H
|