//============== 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 ) ) )