You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
10 KiB
261 lines
10 KiB
//============== 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 );
|
|
|