windows-nt/Source/XPSP1/NT/net/jet500/xjet/inc/stapi.h

778 lines
20 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#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