|
|
//============== DAE: OS/2 Database Access Engine ===================
//============== fcb.h: File Control Block ===================
#ifdef FCB_INCLUDED
#error fcb.h already included
#endif /* FCB_INCLUDED */
#define FCB_INCLUDED
// Database Key
typedef ULONG DBK;
// Flags for FCB
#define fFCBTemporaryTable (1<<0) // This is a temporary file
#define fFCBClusteredIndex (1<<1) // This FCB is for data records.
#define fFCBDenyRead (1<<2) // no other session can read domain
// #define fFCBDenyWrite (1<<3) // no other session can write domain
#define fFCBSentinel (1<<4) // FCB is only flag holder
// #define fFCBDenyDDL (1<<5) // no other transaction can update/delete/replace domain
#define fFCBWait (1<<6) // wait flag
#define fFCBOLCStatsAvail (1<<7) // are OLC Stats available?
#define fFCBOLCStatsChange (1<<8) // have OLC Stats changed since last open?
#define fFCBDeletePending (1<<9) // is a delete pending on this table/index?
#define fFCBDomainOperation (1<<10) // is used to synchronize bm cleanup
// index creation, index deletion and table deletion
#define FFCBDomainOperation( pfcb ) ( (pfcb)->wFlags & fFCBDomainOperation )
#define FCBSetDomainOperation( pfcb ) ( (pfcb)->wFlags |= fFCBDomainOperation )
#define FCBResetDomainOperation( pfcb ) ( (pfcb)->wFlags &= ~(fFCBDomainOperation) )
#define FFCBDeletePending( pfcb ) ( (pfcb)->wFlags & fFCBDeletePending )
#define FCBSetDeletePending( pfcb ) ( (pfcb)->wFlags |= fFCBDeletePending )
#define FCBResetDeletePending( pfcb ) ( (pfcb)->wFlags &= ~(fFCBDeletePending) )
#define FFCBOLCStatsAvail( pfcb ) ( (pfcb)->wFlags & fFCBOLCStatsAvail )
#define FCBSetOLCStatsAvail( pfcb ) ( (pfcb)->wFlags |= fFCBOLCStatsAvail )
#define FCBResetOLCStatsAvail( pfcb ) ( (pfcb)->wFlags &= ~(fFCBOLCStatsAvail) )
#define FFCBOLCStatsChange( pfcb ) ( (pfcb)->wFlags & fFCBOLCStatsChange )
#define FCBSetOLCStatsChange( pfcb ) ( (pfcb)->wFlags |= fFCBOLCStatsChange )
#define FCBResetOLCStatsChange( pfcb ) ( (pfcb)->wFlags &= ~(fFCBOLCStatsChange) )
#define FFCBTemporaryTable( pfcb ) ( (pfcb)->wFlags & fFCBTemporaryTable )
#define FCBSetTemporaryTable( pfcb ) ( (pfcb)->wFlags |= fFCBTemporaryTable )
#define FCBResetTemporaryTable( pfcb ) ( (pfcb)->wFlags &= ~(fFCBTemporaryTable) )
#define FFCBClusteredIndex( pfcb ) ( (pfcb)->wFlags & fFCBClusteredIndex )
#define FCBSetClusteredIndex( pfcb ) ( (pfcb)->wFlags |= fFCBClusteredIndex )
#define FCBResetClusteredIndex( pfcb ) ( (pfcb)->wFlags &= ~(fFCBClusteredIndex) )
#define FFCBDenyWrite( pfcb ) ( (pfcb)->crefDenyWrite > 0 )
#define FCBSetDenyWrite( pfcb ) ( (pfcb)->crefDenyWrite++ )
#define FCBResetDenyWrite( pfcb ) \
{ \ Assert( (pfcb)->crefDenyWrite > 0 ); \ --(pfcb)->crefDenyWrite; \ }
#define FFCBDenyRead( pfcb, ppib ) ( (pfcb)->wFlags & fFCBDenyRead && (ppib) != (pfcb)->ppibDenyRead )
#define FCBSetDenyRead( pfcb, ppib ) \
{ \ if ( (pfcb)->crefDenyRead++ == 0 ) \ { \ Assert( (pfcb)->ppibDenyRead == ppibNil ); \ (pfcb)->ppibDenyRead = (ppib); \ (pfcb)->wFlags |= fFCBDenyRead; \ } \ }
#define FCBResetDenyRead( pfcb ) \
{ \ Assert( (pfcb)->crefDenyRead > 0 ); \ Assert( (pfcb)->ppibDenyRead != ppibNil ); \ if ( --(pfcb)->crefDenyRead == 0 ) \ { \ (pfcb)->wFlags &= ~(fFCBDenyRead); \ (pfcb)->ppibDenyRead = ppibNil; \ } \ }
#define FFCBDenyReadByUs( pfcb, ppib ) ( (pfcb)->wFlags & fFCBDenyRead && (ppib) == (pfcb)->ppibDenyRead )
#define FFCBSentinel( pfcb ) ( (pfcb)->wFlags & fFCBSentinel )
#define FCBSetSentinel( pfcb ) ( (pfcb)->wFlags |= fFCBSentinel )
#define FCBResetSentinel( pfcb ) ( (pfcb)->wFlags &= ~(fFCBSentinel) )
#define FFCBDenyDDL( pfcb, ppib ) ( (pfcb)->crefDenyDDL > 0 && (ppib) != (pfcb)->ppibDDL )
#define FFCBDenyDDLByUs( pfcb, ppib ) ( (pfcb)->crefDenyDDL > 0 && (ppib) == (pfcb)->ppibDDL )
#define FCBSetDenyDDL( pfcb, ppib ) \
{ \ if ( (pfcb)->crefDenyDDL++ == 0 ) \ { \ Assert( (pfcb)->ppibDDL == ppibNil ); \ (pfcb)->ppibDDL = (ppib); \ } \ }
#define FCBResetDenyDDL( pfcb ) \
{ \ Assert( (pfcb)->crefDenyDDL > 0 ); \ Assert( (pfcb)->ppibDDL != ppibNil ); \ if ( --(pfcb)->crefDenyDDL == 0 ) \ { \ (pfcb)->ppibDDL = ppibNil; \ } \ }
#define FFCBWait( pfcb ) ( (pfcb)->wFlags & fFCBWait )
#define FCBSetWait( pfcb ) \
{ \ Assert( !FFCBWait( pfcb ) ); \ (pfcb)->wFlags |= fFCBWait; \ }
#define FCBResetWait( pfcb ) \
{ \ Assert( FFCBWait( pfcb ) ); \ (pfcb)->wFlags &= ~(fFCBWait); \ }
#define FCBVersionIncrement( pfcb ) (pfcb)->cVersion++;
#define FCBVersionDecrement( pfcb ) \
{ \ Assert( (pfcb)->cVersion > 0 ); \ (pfcb)->cVersion--; \ } #define CVersionFCB( pfcb ) (pfcb)->cVersion
/* hash table for FCB's -- only FCB's for tables and db's are hashed
/**/ #define cFCBBuckets 256
FCB* pfcbHash[cFCBBuckets];
#define FCBHashInit() \
{ \ Assert( pfcbNil == (FCB *) 0 ); \ memset( pfcbHash, '\0', sizeof( pfcbHash ) ); \ }
#define FFCBAvail( pfcb, ppib ) \
( pfcb->wRefCnt == 0 && \ pfcb->pgnoFDP != 1 && \ !FFCBSentinel( pfcb ) && \ !FFCBDenyRead( pfcb, ppib ) && \ !FFCBWait( pfcb ) && \ ( pfcb->dbid == dbidTemp || FFCBINoVersion( pfcb ) ) )
// File Control Block
//
struct _fcb { //--------------------USED BY DATA & INDEX FCB---------------------
struct _fcb *pfcbNextIndex; // chain of indexes for this file
struct _fcb *pfcbNextInHashBucket; struct _fdb volatile *pfdb; // field descriptors
struct _idb *pidb; // index info (NULL if "seq." file)
FUCB *pfucb; // chain of FUCBs open on this file
PIB *ppibDDL; // ppib of process updating index/adding column
PIB *ppibDenyRead; // ppib of process holding exclusive lock
CRIT critSplit; // per domain split MUTEX
PGNO pgnoFDP; // FDP of this file/index
PGNO pgnoRoot; // pgno of the root of the domain
SRID bmRoot; // bm of root of the domain
// -- useful if Root is movable, e.g, DATA
DBID dbid; // which database
INT itagRoot; // itag of the root of the domain
INT cbDensityFree; // loading density parameter:
// # of bytes free w/o using new page
INT wFlags; // flags for this FCB
INT wRefCnt; // # of FUCBs for this file/index
INT volatile cVersion; // # of RCEs for this file/index
INT crefDenyRead; // # of FUCBs with deny read flag
INT crefDenyWrite; // # of FUCBs with deny write flag
INT crefDenyDDL; // # of FUCBs with deny DDL flag
ULONG cpgCompactFreed; PERS_OLCSTAT olcStat; //--------------------USED ONLY BY FCB OF DATA---------------------
CHAR *szFileName; // name of file (for GetTableInfo)
struct _fcb *pfcbNext; // Next data FCB in global list
DBK dbkMost; // Greatest DBK in use
// (if "sequential" file)
ULONG ulLongIdMax; // max long field id
BYTE rgbitAllIndex[32]; // used for clustered index FCB only
BOOL fAllIndexTagged; // used for clustered index FCB only
};
#define FCBInit( pfcb ) \
{ \ memset( pfcb, '\0', sizeof( FCB ) ); \ }
#define PfcbMEMAlloc() (FCB*)PbMEMAlloc(iresFCB)
#ifdef DEBUG /* Debug check for illegal use of freed fcb */
#define MEMReleasePfcb(pfcb) \
{ \ Assert( PfcbFCBGet( pfcb->dbid, pfcb->pgnoFDP ) != pfcb ); \ MEMRelease( iresFCB, (BYTE*)(pfcb) ); \ pfcb = pfcbNil; \ } #else
#define MEMReleasePfcb(pfcb) \
{ \ Assert( PfcbFCBGet( pfcb->dbid, pfcb->pgnoFDP ) != pfcb ); \ MEMRelease( iresFCB, (BYTE*)(pfcb) ); \ } #endif
/* if opening domain for read, write or read write, and not with
/* deny read or deny write, and domain does not have deny read or
/* deny write set, then return JET_errSuccess, else call
/* ErrFCBISetMode to determine if lock is by other session or to
/* put lock on domain.
/**/ #define ErrFCBSetMode( ppib, pfcb, grbit ) \
( ( ( ( grbit & ( JET_bitTableDenyRead | JET_bitTableDenyWrite ) ) == 0 ) && \ ( ( FFCBDenyDDL( pfcb, ppib ) || FFCBDenyRead( pfcb, ppib ) || FFCBDenyWrite( pfcb ) ) == fFalse ) ) ? \ JET_errSuccess : ErrFCBISetMode( ppib, pfcb, grbit ) )
/* reset DDL is same as reset Delete. Both use deny read flags
/* or sentinel.
/**/ #define FCBResetRenameTable FCBResetDeleteTable
extern BYTE * __near rgfcb; extern FCB * __near pfcbGlobalList; extern SEM __near semGlobalFCBList; extern SEM __near semLinkUnlink;
VOID FCBLink( FUCB *pfucb, FCB *pfcb ); VOID FCBRegister( FCB *pfcb ); VOID FCBDiscard( FCB *pfcb ); VOID FCBUnlink( FUCB *pfucb ); FCB *PfcbFCBGet( DBID dbid, PGNO pgnoFDP ); ERR ErrFCBAlloc( PIB *ppib, FCB **ppfcb ); VOID FCBPurgeDatabase( DBID dbid ); VOID FCBPurgeTable( DBID dbid, PGNO pgnoFDP ); ERR ErrFCBNew( PIB *ppib, DBID dbid, PGNO pgno, FCB **ppfcb ); ERR ErrFCBISetMode( PIB *ppib, FCB *pfcb, JET_GRBIT grbit ); VOID FCBResetMode( PIB *ppib, FCB *pfcb, JET_GRBIT grbit ); ERR ErrFCBSetDeleteTable( PIB *ppib, DBID dbid, PGNO pgnoFDP ); VOID FCBResetDeleteTable( DBID dbid, PGNO pgnoFDP ); ERR ErrFCBSetRenameTable( PIB *ppib, DBID dbid, PGNO pgno ); FCB *FCBResetAfterRedo( void ); BOOL FFCBTableOpen ( DBID dbid, PGNO pgno );
VOID FCBLinkIndex( FCB *pfcbTable, FCB *pfcbIndex ); VOID FCBUnlinkIndex( FCB *pfcbTable, FCB *pfcbIndex ); BOOL FFCBUnlinkIndexIfFound( FCB *pfcbTable, FCB *pfcbIndex ); FCB *PfcbFCBUnlinkIndexByName( FCB *pfcb, CHAR *szIndex ); ERR ErrFCBSetDeleteIndex( PIB *ppib, FCB *pfcbTable, CHAR *szIndex ); VOID FCBResetDeleteIndex( FCB *pfcbIndex );
|