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

379 lines
12 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#ifdef FCB_INCLUDED
#error fcb.h already included
#endif /* FCB_INCLUDED */
#define FCB_INCLUDED
/* unique sequential key
/**/
typedef ULONG DBK;
#define FFCBDeletePending( pfcb ) ( (pfcb)->fFCBDeletePending )
#define FCBSetDeletePending( pfcb ) ( (pfcb)->fFCBDeletePending = 1 )
#define FCBResetDeletePending( pfcb ) ( (pfcb)->fFCBDeletePending = 0 )
#define FFCBOLCStatsAvail( pfcb ) ( (pfcb)->fFCBOLCStatsAvail )
#define FCBSetOLCStatsAvail( pfcb ) ( (pfcb)->fFCBOLCStatsAvail = 1 )
#define FCBResetOLCStatsAvail( pfcb ) ( (pfcb)->fFCBOLCStatsAvail = 0 )
#define FFCBOLCStatsChange( pfcb ) ( (pfcb)->fFCBOLCStatsChange )
#define FCBSetOLCStatsChange( pfcb ) ( (pfcb)->fFCBOLCStatsChange = 1 )
#define FCBResetOLCStatsChange( pfcb ) ( (pfcb)->fFCBOLCStatsChange = 0 )
#define FFCBTemporaryTable( pfcb ) ( (pfcb)->fFCBTemporaryTable )
#define FCBSetTemporaryTable( pfcb ) ( (pfcb)->fFCBTemporaryTable = 1 )
#define FCBResetTemporaryTable( pfcb ) ( (pfcb)->fFCBTemporaryTable = 0 )
#define FFCBSystemTable( pfcb ) \
( UtilCmpName( (pfcb)->szFileName, szScTable ) == 0 || \
UtilCmpName( (pfcb)->szFileName, szSiTable ) == 0 || \
UtilCmpName( (pfcb)->szFileName, szSoTable ) == 0 )
#define FFCBClusteredIndex( pfcb ) ( (pfcb)->fFCBClusteredIndex )
#define FCBSetClusteredIndex( pfcb ) ( (pfcb)->fFCBClusteredIndex = 1 )
#define FCBResetClusteredIndex( pfcb ) ( (pfcb)->fFCBClusteredIndex = 0 )
#define FFCBDomainDenyWrite( pfcb ) ( (pfcb)->crefDomainDenyWrite > 0 )
#define FCBSetDomainDenyWrite( pfcb ) ( (pfcb)->crefDomainDenyWrite++ )
#define FCBResetDomainDenyWrite( pfcb ) \
{ \
Assert( (pfcb)->crefDomainDenyWrite > 0 ); \
--(pfcb)->crefDomainDenyWrite; \
}
#define FFCBDomainDenyRead( pfcb, ppib ) ( (pfcb)->fFCBDomainDenyRead && (ppib) != (pfcb)->ppibDomainDenyRead )
#define FCBSetDomainDenyRead( pfcb, ppib ) \
{ \
if ( (pfcb)->crefDomainDenyRead++ == 0 ) \
{ \
Assert( (pfcb)->ppibDomainDenyRead == ppibNil ); \
(pfcb)->ppibDomainDenyRead = (ppib); \
(pfcb)->fFCBDomainDenyRead = 1; \
} \
else \
{ \
Assert( (pfcb)->ppibDomainDenyRead == (ppib) ); \
Assert( (pfcb)->fFCBDomainDenyRead ); \
} \
}
#define FCBResetDomainDenyRead( pfcb ) \
{ \
Assert( (pfcb)->crefDomainDenyRead > 0 ); \
Assert( (pfcb)->ppibDomainDenyRead != ppibNil ); \
Assert( (pfcb)->fFCBDomainDenyRead ); \
if ( --(pfcb)->crefDomainDenyRead == 0 ) \
{ \
(pfcb)->fFCBDomainDenyRead = 0; \
(pfcb)->ppibDomainDenyRead = ppibNil; \
} \
}
#define FFCBDomainDenyReadByUs( pfcb, ppib ) ( (pfcb)->fFCBDomainDenyRead && (ppib) == (pfcb)->ppibDomainDenyRead )
// Don't have an explicit fSort flag, but we can tell if it's a sort FCB by
// examining certain fields.
#define FFCBSort( pfcb ) ( (pfcb)->pgnoFDP > pgnoSystemRoot && \
(pfcb)->pfdb == pfdbNil && \
(pfcb)->pfcbNextIndex == pfcbNil && \
(pfcb)->pfcbTable == pfcbNil && \
(pfcb)->pidb == pidbNil && \
(pfcb)->dbid == dbidTemp && \
!FFCBTemporaryTable( pfcb ) && \
!FFCBClusteredIndex( pfcb ) )
#define FFCBReadLatch( pfcb ) ( (pfcb)->crefReadLatch > 0 )
#define FCBSetReadLatch( pfcb ) \
{ \
Assert( FFCBClusteredIndex( pfcb ) || \
( (pfcb)->pgnoFDP == pgnoSystemRoot ) || \
FFCBSort( pfcb ) ); \
(pfcb)->crefReadLatch++; \
}
#define FCBResetReadLatch( pfcb ) \
{ \
Assert( (pfcb)->crefReadLatch > 0 ); \
--(pfcb)->crefReadLatch; \
}
#define FFCBSentinel( pfcb ) ( (pfcb)->fFCBSentinel )
#define FCBSetSentinel( pfcb ) ( (pfcb)->fFCBSentinel = 1 )
#define FCBResetSentinel( pfcb ) ( (pfcb)->fFCBSentinel = 0 )
#define FFCBWriteLatch( pfcb, ppib ) ( (pfcb)->crefWriteLatch > 0 && (ppib) != (pfcb)->ppibWriteLatch )
#define FFCBWriteLatchByUs( pfcb, ppib ) ( (pfcb)->crefWriteLatch > 0 && (ppib) == (pfcb)->ppibWriteLatch )
#define FCBSetWriteLatch( pfcb, ppib ) \
{ \
Assert( FFCBClusteredIndex( pfcb ) || \
FFCBSentinel( pfcb ) ); \
if ( (pfcb)->crefWriteLatch++ == 0 ) \
{ \
Assert( (pfcb)->ppibWriteLatch == ppibNil ); \
(pfcb)->ppibWriteLatch = (ppib); \
} \
else \
{ \
Assert( (pfcb)->ppibWriteLatch == ppib ); \
} \
}
#define FCBResetWriteLatch( pfcb, ppib ) \
{ \
Assert( FFCBWriteLatchByUs( pfcb, ppib ) ); \
Assert( (pfcb)->crefWriteLatch > 0 ); \
Assert( (pfcb)->ppibWriteLatch != ppibNil ); \
if ( --(pfcb)->crefWriteLatch == 0 ) \
{ \
(pfcb)->ppibWriteLatch = ppibNil; \
} \
}
#define FFCBWait( pfcb ) ( (pfcb)->fFCBWait )
#define FCBSetWait( pfcb ) \
{ \
Assert( !FFCBWait( pfcb ) ); \
(pfcb)->fFCBWait = 1; \
}
#define FCBResetWait( pfcb ) \
{ \
Assert( FFCBWait( pfcb ) ); \
(pfcb)->fFCBWait = 0; \
}
#define FFCBInLRU( pfcb ) ( (pfcb)->fFCBInLRU )
#define FCBSetInLRU( pfcb ) \
{ \
Assert( !FFCBInLRU( pfcb ) ); \
(pfcb)->fFCBInLRU = 1; \
}
#define FCBResetInLRU( pfcb ) \
{ \
Assert( FFCBInLRU( pfcb ) ); \
(pfcb)->fFCBInLRU = 0; \
}
#define CVersionFCB( pfcb ) (pfcb)->cVersion
#define FCBVersionIncrement( pfcb ) (pfcb)->cVersion++;
#define FCBVersionDecrement( pfcb ) \
{ \
if ( (pfcb) != pfcbNil ) \
{ \
Assert( cVersion-- > 0 ); \
Assert( (pfcb)->cVersion > 0 ); \
(pfcb)->cVersion--; \
(pfcb) = pfcbNil; \
} \
}
// File Control Block
//
typedef struct _fcb
{
//--------------------USED BY DATA & INDEX FCB---------------------
struct _fdb volatile *pfdb; // field descriptors
struct _fcb *pfcbNextIndex; // chain of indexes for this file
struct _fcb *pfcbLRU; // next LRU FCB in global LRU list
struct _fcb *pfcbMRU; // previous LRU FCB in global LRU list
INT fFCBInLRU : 1; // in LRU list
struct _fcb *pfcbNextInHashBucket;
struct _fcb *pfcbTable; // points to FCB of table for an index FCB
struct _idb *pidb; // index info (NULL if "seq." file)
FUCB *pfucb; // chain of FUCBs open on this file
PGNO pgnoFDP; // FDP of this file/index
DBID dbid; // which database
SHORT cbDensityFree; // loading density parameter:
// # of bytes free w/o using new page
INT wRefCnt; // # of FUCBs for this file/index
INT volatile cVersion; // # of RCEs for this file/index
INT crefDomainDenyRead; // # of FUCBs with deny read flag
INT crefDomainDenyWrite;// # of FUCBs with deny write flag
INT crefReadLatch; // # of read latch on this FCB.
INT crefWriteLatch; // # of FUCB ( of the same ppib ) with write
// latch on this FCB.
PIB *ppibWriteLatch; // ppib of process updating index/adding column
PIB *ppibDomainDenyRead;// ppib of process holding exclusive lock
/* flags for FCB
/**/
union {
ULONG ulFlags;
struct {
INT fFCBTemporaryTable : 1; // This is a temporary file
INT fFCBClusteredIndex : 1; // This FCB is for data records.
INT fFCBDomainDenyRead : 1; // no other session can read domain
INT fFCBSentinel : 1; // FCB is only flag holder
INT fFCBWait : 1; // wait flag
INT fFCBOLCStatsAvail : 1; // are OLC Stats available?
INT fFCBOLCStatsChange : 1; // have OLC Stats changed since last open?
INT fFCBDeletePending : 1; // is a delete pending on this table/index?
};
};
//--------------------USED ONLY BY FCB OF DATA---------------------
CHAR *szFileName; // name of file (for GetTableInfo)
DBK dbkMost; // greatest DBK in use
ULONG ulLongIdMax; // max long field id
BYTE rgbitAllIndex[32]; // used for clustered index FCB only
//-------------------------INSTRUMENTATION----------------------------
ULONG cpgCompactFreed;
P_OLC_DATA olc_data;
/* PCACHE_OPTIMIZATION pads to multiple of 32 bytes.
/* We're currently 4 bytes short, so even if COSTLY_PERF is disabled, add
/* lClass anyways to pad to our requisite 32-byte boundary.
/**/
#if defined( COSTLY_PERF ) || defined( PCACHE_OPTIMIZATION )
ULONG lClass; // table stats class (for BF performance)
#endif
BYTE rgbFiller[20];
} FCB;
/* hash table for FCB
/**/
#define cFCBBuckets 256
FCB* pfcbHash[cFCBBuckets];
#define FCBHashInit() \
{ \
Assert( pfcbNil == (FCB *) 0 ); \
memset( pfcbHash, '\0', sizeof( pfcbHash ) ); \
}
#define FCBInitFCB( pfcb ) \
{ \
memset( pfcb, '\0', sizeof(FCB) ); \
}
#define PfcbMEMAlloc() ( (FCB *)PbMEMAlloc( iresFCB ) )
#define PfcbMEMPreferredThreshold() ( (FCB *)PbMEMPreferredThreshold( iresFCB ) )
#define PfcbMEMMax() ( (FCB *)PbMEMMax( iresFCB ) )
#ifdef DEBUG /* Debug check for illegal use of freed fcb */
#define MEMReleasePfcb(pfcb) \
{ \
Assert( PfcbFCBGet( (pfcb)->dbid, (pfcb)->pgnoFDP ) != pfcb ); \
Assert( (pfcb)->pfdb == pfdbNil ); \
MEMRelease( iresFCB, (BYTE*)(pfcb) ); \
(pfcb) = pfcbNil; \
}
#else
#define MEMReleasePfcb(pfcb) \
{ \
MEMRelease( iresFCB, (BYTE*)(pfcb) ); \
}
#endif
ERR ErrFCBISetMode( PIB *ppib, FCB *pfcb, JET_GRBIT grbit );
/* 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.
/**/
INLINE LOCAL ERR ErrFCBSetMode( PIB *ppib, FCB *pfcb, ULONG grbit )
{
if ( ( grbit & ( JET_bitTableDenyRead | JET_bitTableDenyWrite ) ) == 0 )
{
// No read/write restrictions. Ensure no other session has any locks.
if ( !( FFCBWriteLatch( pfcb, ppib ) ||
FFCBDomainDenyRead( pfcb, ppib ) ||
FFCBDomainDenyWrite( pfcb ) ||
FFCBDeletePending( pfcb ) ) )
return JET_errSuccess;
}
return ErrFCBISetMode( ppib, pfcb, grbit );
}
/* reset DDL is same as reset Delete. Both use deny read flags
/* or sentinel.
/**/
#define FCBResetRenameTable FCBResetDeleteTable
extern BYTE * rgfcb;
extern FCB * pfcbGlobalMRU;
extern CRIT critGlobalFCBList;
/* outstanding versions may be on non-clustered index and not on
/* table FCB, so must check all non-clustered indexes before
/* freeing table FCBs.
/**/
STATIC INLINE BOOL FFCBINoVersion( FCB *pfcbTable )
{
FCB *pfcbT;
for ( pfcbT = pfcbTable; pfcbT != pfcbNil; pfcbT = pfcbT->pfcbNextIndex )
{
if ( pfcbT->cVersion > 0 )
{
return fFalse;
}
}
return fTrue;
}
#define FFCBAvail( pfcb, ppib ) \
( pfcb->wRefCnt == 0 && \
pfcb->pgnoFDP != 1 && \
!FFCBReadLatch( pfcb ) && \
!FFCBSentinel( pfcb ) && \
!FFCBDomainDenyRead( pfcb, ppib ) && \
!FFCBWait( pfcb ) && \
FFCBINoVersion( pfcb ) )
VOID FCBTerm( VOID );
VOID FCBInsert( FCB *pfcb );
VOID FCBLink( FUCB *pfucb, FCB *pfcb );
VOID FCBInsertHashTable( FCB *pfcb );
VOID FCBDeleteHashTable( 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 );
VOID FCBResetMode( PIB *ppib, FCB *pfcb, JET_GRBIT grbit );
ERR ErrFCBSetDeleteTable( PIB *ppib, DBID dbid, PGNO pgnoFDP );
VOID FCBResetDeleteTable( FCB *pfcb );
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 );
INLINE STATIC VOID FCBLinkClusteredIdx( FCB *pfcbClustered )
{
FCB *pfcbIdx;
for ( pfcbIdx = pfcbClustered->pfcbNextIndex; pfcbIdx != pfcbNil; pfcbIdx = pfcbIdx->pfcbNextIndex )
{
pfcbIdx->pfcbTable = pfcbClustered;
}
}