windows-nt/Source/XPSP1/NT/net/jet500/jet/dae/inc/stapi.h
2020-09-26 16:20:57 +08:00

452 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//============== DAE: OS/2 Database Access Engine =====================
//============== stapi.h: Storage System API =====================
//---- externs -------------------------------------------------------------
extern SEM __near semST;
extern RES __near rgres[];
extern TRX __near trxOldest;
extern TRX __near trxNewest;
extern SIG __near sigBFCleanProc;
//---- IO (io.c) ----------------------------------------------------------
#define LOffsetOfPgnoLow( pgno ) ( ((pgno) - 1) << 12 )
#define LOffsetOfPgnoHigh( pgno ) ( ((pgno) - 1) >> 20 )
#define fioqeOpenFile 1 /* for Opening File */
#define fioqeCloseFile 2 /* for Closing File */
#define fioqeDeleteFile 3 /* for deleting file */
#define fioqeNewSize 4 /* for resize file */
typedef struct _ioqe /* IO queue element */
{
struct _ioqe *pioqePrev; /* double linked IO queue list */
struct _ioqe *pioqeNext;
SIG sigIO; /* signal to wait for IO completion */
ERR err; /* error code for err occurs during the IO */
INT fioqe; /* use up to 16 bits only */
} IOQE;
#define fioqefileReadOnly fTrue
#define fioqefileReadWrite fFalse
typedef struct _ioqefile
{
IOQE;
struct {
BOOL fioqefile; /* open file for read only or not */
HANDLE hf; /* file handle */
char *sz; /* fioqe = fioqeOpenFile, CloseFile, ExtFile */
struct {
ULONG cb; /* how long the file is */
ULONG cbHigh;
};
};
} IOQEFILE;
VOID IOInitFMP();
ERR ErrInitFileMap( PIB *ppib );
BOOL FFileExists( CHAR *szFileName );
ERR ErrIOOpenFile( HANDLE *phf, CHAR *szDatabaseName, ULONG cb, BOOL fioqefile );
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, PGNO pgnoFDP );
#define FIODatabaseOpen( dbid ) ( rgfmp[dbid].hf != handleNil )
ERR ErrIOOpenDatabase( DBID dbid, CHAR *szDatabaseName, CPG cpg );
VOID IOCloseDatabase( DBID dbid );
VOID IODeleteDatabase( DBID dbid );
BOOL FIODatabaseInUse( DBID dbid );
BOOL FIODatabaseAvailable( DBID dbid );
#define FDatabaseLocked( dbid ) (rgfmp[dbid].fXOpen)
#define IOUnlockDbid( dbid ) \
{ \
SgSemRequest( semST ); \
Assert( FDBIDWait( dbid ) ); \
DBIDResetWait( dbid ); \
SgSemRelease( semST ); \
}
#ifdef DEBUG
#define IOSetDatabaseVersion( dbid, ulVersion ) \
{ \
Assert( ulVersion == ulDAEPrevVersion || \
ulVersion == ulDAEVersion ); \
rgfmp[dbid].fPrevVersion = ( ulVersion == ulDAEPrevVersion );\
}
#else /* !DEBUG */
#define IOSetDatabaseVersion( dbid, ulVersion )
#endif /* !DEBUG */
#define FIOExclusiveByAnotherSession( dbid, ppib ) \
( Assert( FDBIDWait( dbid ) ), FDBIDExclusiveByAnotherSession( dbid, ppib ) )
#define IOSetExclusive( dbid, ppib ) \
{ \
Assert( FDBIDWait( dbid ) ); \
Assert( !( FDBIDExclusive( dbid ) ) ); \
DBIDSetExclusive( dbid, ppib ); \
}
#define IOResetExclusive( dbid ) \
{ \
Assert( FDBIDWait( dbid ) ); \
DBIDResetExclusive( dbid ); \
}
#define FIOReadOnly( dbid ) \
( Assert( FDBIDWait( dbid ) ), FDBIDReadOnly( dbid ) )
#define IOSetReadOnly( dbid ) \
{ \
Assert( FDBIDWait( dbid ) ); \
DBIDSetReadOnly( dbid ); \
}
#define IOResetReadOnly( dbid ) \
{ \
Assert( FDBIDWait( dbid ) ); \
DBIDResetReadOnly( dbid ); \
}
#define FIOAttached( dbid ) \
( Assert( FDBIDWait( dbid ) ), FDBIDAttached( dbid ) )
#define IOSetAttached( dbid ) \
{ \
Assert( FDBIDWait( dbid ) ); \
Assert( !( FDBIDAttached( dbid ) ) ); \
DBIDSetAttached( dbid ); \
}
#define IOResetAttached( dbid ) \
{ \
Assert( FDBIDWait( dbid ) ); \
Assert( FDBIDAttached( dbid ) ); \
DBIDResetAttached( dbid ); \
}
//---- PAGE (page.c) --------------------------------------------------------
// Max # of lines to update at once with ErrSTReplace
#define clineMax 6
#define UlSTDBTimePssib( pssib ) ( (pssib)->pbf->ppage->pghdr.ulDBTime )
#define PMSetUlDBTime( pssib, ul ) \
( Assert( (ul) <= rgfmp[DbidOfPn((pssib)->pbf->pn)].ulDBTime ), \
(pssib)->pbf->ppage->pghdr.ulDBTime = (ul) ) \
#define BFSetUlDBTime( pbf, ul ) \
( Assert( (ul) <= rgfmp[DbidOfPn((pbf)->pn)].ulDBTime ), \
(pbf)->ppage->pghdr.ulDBTime = (ul) ) \
#ifdef DEBUG
VOID AssertPMGet( SSIB *pssib, INT itag );
#else
#define AssertPMGet( pssib, itag )
#endif
//---- BUF (buf.c) ----------------------------------------------------------
#define LRU_K 1
CRIT __near critLRU;
typedef struct _lru
{
INT 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
INT cbfGroup; // number of bfs in this group
INT cbfThresholdLow; // threshold to start cleaning buffers
INT 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
typedef struct _bf
{
struct _page *ppage; // pointer to page buffer
struct _bf *pbfNext; // hash table overflow
struct _bf *pbfLRU; // pointer to Less Recently Used Buffer
struct _bf *pbfMRU; // pointer to More Recently Used Buffer
PIB *ppibWriteLatch; /* thread with Wait Latch */
PIB *ppibWaitLatch; /* thread with Wait Latch */
CRIT critBF; /* for setting fPreread/fRead/fWrite/fHold */
OLP olp; /* for ssync IO, to wait for IO completion */
HANDLE hf; /* for assync IO */
struct _bf *pbfNextBatchIO; /* next BF in BatchIO list */
INT ipageBatchIOFirst;
ERR err; /* error code for err occurs during the IO */
PN pn; // physical pn of cached page
UINT cPin; // if cPin > 0 then buf cannot be overlayed
UINT cReadLatch; // if cReadLatch > 0, page cannot be updated
UINT cWriteLatch; // if cWriteLatch > 0, page cannot be updated by other
UINT cWaitLatch;
UINT fDirty:1; // indicates page needs to be flushed
// the following flags are mutual exclusive:
UINT fPreread:1; // indicates page is being prefetched
UINT fRead:1; // indicates page is being read/written
UINT fWrite:1; //
UINT fHold:1; // indicates buf is in transient state.
UINT fIOError:1; // indicates read/write error
UINT fInHash:1; // BF is currently in hash table
ULONG ulBFTime1;
ULONG ulBFTime2;
INT ipbfHeap; // index in heap
UINT cDepend; // count of prior BF's to be flushed
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
#ifdef WIN16
HANDLE hpage; // handle to the page buffer
#endif
// UINT fWaiting:1; // someone is waiting to reference page
// INT wNumberPages; // number of contiguous pages to read
} BF;
#define pbfNil ((BF *) 0)
ERR ErrBFAccessPage( PIB *ppib, BF **ppbf, PN pn );
BF* PbfBFMostUsed( void );
VOID BFAbandon( 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 BFReadAsync( PN pn, INT cpage );
BF * PbfBFdMostUsed( void );
VOID BFRemoveDependence( PIB *ppib, BF *pbf );
/* buffer flush prototype and flags
/**/
#define fBFFlushSome 0
#define fBFFlushAll 1
ERR ErrBFFlushBuffers( DBID dbid, INT fBFFlush );
#define BFSFree( pbf ) \
{ \
SgSemRequest( semST ); \
BFFree( pbf ); \
SgSemRelease( semST ); \
}
#define FBFDirty( pbf ) ((pbf)->fDirty)
/* the following small functions are called too often, */
/* make it as a macros */
#ifdef DEBUG
VOID BFSetDirtyBit( BF *pbf );
#else
#define BFSetDirtyBit( pbf ) (pbf)->fDirty = fTrue
#endif
VOID BFDirty( BF *pbf );
/* 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) );
#define BFPin( pbf ) \
{ \
EnterCriticalSection( (pbf)->critBF ); \
Assert( (pbf) != pbfNil ); \
Assert( !(pbf)->fWrite ); \
Assert( !(pbf)->fRead ); \
(pbf)->cPin++; \
LeaveCriticalSection( (pbf)->critBF ); \
}
#define BFUnpin( pbf ) \
{ \
EnterCriticalSection( (pbf)->critBF ); \
Assert( (pbf) != pbfNil ); \
Assert( !(pbf)->fWrite ); \
Assert( !(pbf)->fRead ); \
Assert( (pbf)->cPin > 0 ); \
(pbf)->cPin--; \
LeaveCriticalSection( (pbf)->critBF ); \
}
#define BFSetReadLatch( pbf, ppibT ) \
{ \
Assert( (pbf)->cPin > 0 ); \
Assert( (pbf)->cWriteLatch == 0 || \
(pbf)->ppibWriteLatch == (ppibT) ); \
(pbf)->cReadLatch++; \
}
#define BFResetReadLatch( pbf, ppibT ) \
{ \
Assert( (pbf)->cPin > 0 ); \
Assert( (pbf)->cReadLatch > 0 ); \
Assert( (pbf)->cWriteLatch == 0 || \
(pbf)->ppibWriteLatch == (ppibT) ); \
(pbf)->cReadLatch--; \
}
#define FBFReadLatchConflict( ppibT, pbf ) \
( (pbf)->cWriteLatch > 0 && \
(pbf)->ppibWriteLatch != (ppibT) )
#define BFSetWriteLatch( pbf, ppibT ) \
{ \
Assert( (pbf)->cPin > 0 ); \
Assert( (pbf)->cReadLatch == 0 ); \
Assert( (pbf)->cWriteLatch == 0 || \
(pbf)->ppibWriteLatch == (ppibT) ); \
(pbf)->cWriteLatch++; \
(pbf)->ppibWriteLatch = (ppibT); \
}
#define BFResetWriteLatch( pbf, ppibT ) \
{ \
Assert( (pbf)->cPin > 0 ); \
Assert( (pbf)->cReadLatch == 0 ); \
Assert( (pbf)->cWriteLatch > 0 ); \
Assert( (pbf)->ppibWriteLatch == (ppibT) ); \
if ( --(pbf)->cWriteLatch == 0 ) \
{ \
(pbf)->ppibWriteLatch = ppibNil; \
Assert( (pbf)->cWaitLatch == 0 ); \
} \
}
#define FBFWriteLatch( ppibT, pbf ) \
((pbf)->cPin > 0 && \
(pbf)->cWriteLatch > 0 && \
(pbf)->ppibWriteLatch == (ppibT))
#define FBFWriteLatchConflict( ppibT, pbf ) \
( (pbf)->cReadLatch > 0 || \
( (pbf)->cWriteLatch > 0 && \
(pbf)->ppibWriteLatch != (ppibT) ) )
#define BFSetWaitLatch( pbf, ppib ) \
{ \
Assert( ( pbf )->cPin > 0 ); \
Assert( ( pbf )->cWriteLatch > 0 ); \
Assert( (pbf)->ppibWriteLatch == (ppib) ); \
if ( pbf->cWaitLatch++ > 0 ) \
Assert( (pbf)->ppibWaitLatch == (ppib) ); \
(pbf)->ppibWaitLatch = ppib; \
}
#define BFResetWaitLatch( pbf, ppibT ) \
{ \
Assert( (pbf)->cPin > 0 ); \
Assert( ( pbf )->cWriteLatch > 0 ); \
Assert( (pbf)->cWaitLatch > 0 ); \
Assert( (pbf)->ppibWaitLatch == (ppibT) ); \
if ( --(pbf)->cWaitLatch == 0 ) \
{ \
(pbf)->ppibWaitLatch = ppibNil; \
SignalSend( (pbf)->olp.sigIO ); \
} \
}
ERR ErrBFDepend( BF *pbf, BF *pbfD );
#define BFUndepend( pbf ) \
{ \
if ( (pbf)->pbfDepend != pbfNil ) \
{ \
BF *pbfD = (pbf)->pbfDepend; \
Assert( pbfD->cDepend > 0 ); \
EnterCriticalSection( pbfD->critBF ); \
pbfD->cDepend--; \
(pbf)->pbfDepend = pbfNil; \
LeaveCriticalSection( pbfD->critBF ); \
} \
}
//---- STORAGE (storage.c) -------------------------------------------------
ERR ErrFMPSetDatabases( PIB *ppib );
ERR ErrFMPInit( VOID );
VOID FMPTerm( );
ERR ErrSTSetIntrinsicConstants( VOID );
ERR ErrSTInit( VOID );
ERR ErrSTTerm( VOID );
// Transaction support
ERR ErrSTBeginTransaction( PIB *ppib );
ERR ErrSTRollback( PIB *ppib );
ERR ErrSTCommitTransaction( PIB *ppib );
ERR ErrSTInitOpenSysDB();
ERR ErrBFNewPage( FUCB *pfucb, PGNO pgno, PGTYP pgtyp, PGNO pgnoFDP );
VOID BFSleep( unsigned long ulMSecs );
// Modes for Storage System
#define modeRead 0
#define modeWrite 1
#define modeRIW 2
#define PnOfDbidPgno( dbid, pgno ) ( ( (LONG) (dbid) )<<24 | (pgno) )
#define DbidOfPn( pn ) ( (DBID)( (pn)>>24 ) )
#define PgnoOfPn( pn ) ( (pn) & 0x00ffffff )
#define ErrSTReadAccessPage ErrSTAccessPage
#define ErrSTWriteAccessPage ErrSTAccessPage
#define FReadAccessPage FAccessPage
#define FWriteAccessPage FAccessPage
BOOL FBFAccessPage( FUCB *pfucb, PGNO pgno );
#define FAccessPage( pfucb, pgno ) FBFAccessPage( pfucb, pgno )
// UNDONE: this should be in SgSemRequest( semST )
#define ErrSTAccessPage( pfucb, pgnoT ) \
( ErrBFAccessPage( pfucb->ppib, &(pfucb)->ssib.pbf, PnOfDbidPgno( (pfucb)->dbid, pgnoT ) ) )