/* JET API flags /**/ #define FPIBVersion( ppib ) (!((ppib)->grbit & (JET_bitCIMCommitted | JET_bitCIMDirty))) #define FPIBCommitted( ppib ) ((ppib)->grbit & JET_bitCIMCommitted) #define FPIBDirty( ppib ) ((ppib)->grbit & JET_bitCIMDirty) #define FPIBAggregateTransaction( ppib ) ((ppib)->grbit & JET_bitAggregateTransaction) #define FPIBBMClean( ppib ) ((ppib)->fBMCleanProc ) #define PIBSetBMClean( ppib ) ((ppib)->fBMCleanProc = 1 ) #define PIBResetBMClean( ppib ) ((ppib)->fBMCleanProc = 0 ) // // Process Information Block // struct _pib { /* most used field has offset 0 /**/ TRX trxBegin0; // trx id TRX trxCommit0; /* JET API fields /**/ JET_SESID sesid; // JET session id JET_GRBIT grbit; // session flags struct _pib *ppibNext; // PIB list LEVEL level; // transaction level of this session LEVEL levelRollback; // transaction level which must be rolled back struct _dab *pdabList; // list of open DAB's of this thread USHORT rgcdbOpen[dbidMax]; // counter for open databases struct _fucb *pfucb; // list of active fucb of this thread /* logging/recovery fields /**/ PROCID procid; // thread id LGPOS lgposStart; // log time LEVEL levelBegin; // transaction level when first begin transaction operation LEVEL levelDeferBegin; // count of deferred open transactions SIG sigWaitLogFlush; LONG lWaitLogFlush; LONG grbitsCommitDefault; struct _pib *ppibNextWaitFlush; struct _pib *ppibPrevWaitFlush; LGPOS lgposPrecommit0; // level 0 precommit record position. /* flags /**/ BOOL fUserSession:1; // user session BOOL fAfterFirstBT:1; // for redo only BOOL fLGWaiting:1; // waiting for log to flush BOOL fBMCleanProc:1; // session is for doing BMCleanup // BOOL fDeferFreeNodeSpace:1; // session has deferred node free space BOOL fPrecommit:1; // in precommit state? Recovery only BOOL fBegin0Logged:1; // begin transaction has logged BOOL fSetAttachDB:1; // set up attachdb. BOOL fMacroGoing:1; BOOL levelMacro:4; /* version store fields /**/ RCE *prceNewest; // newest RCE of session #ifdef DEBUG DWORD dwLogThreadId; #endif /* counters for the session. */ LONG cAccessPage; // counter of page access. LONG cLatchConflict; // counter of page latch conflicts. LONG cSplitRetry; // counter of split retries. LONG cNeighborPageScanned; // counter of neighboring page scanned. union { struct { // Redo only. BYTE *rgbLogRec; WORD cbLogRecMac; WORD ibLogRecAvail; }; struct { // Do only /* array for internal macro operations. */ struct _bf **rgpbfLatched; // dynamically allocated array WORD cpbfLatchedMac; // for macro operations. WORD ipbfLatchedAvail; // for macro operations. }; }; #ifdef PCACHE_OPTIMIZATION /* pad to multiple of 32 bytes /**/ #ifdef DEBUG BYTE rgbFiller[0]; #else BYTE rgbFiller[4]; #endif #endif }; #define PpibMEMAlloc() (PIB*)PbMEMAlloc(iresPIB) #ifdef DEBUG /* Debug check for illegal use of freed pib */ #define MEMReleasePpib(ppib) { MEMRelease(iresPIB, (BYTE*)(ppib)); ppib = ppibNil; } #else #define MEMReleasePpib(ppib) { MEMRelease(iresPIB, (BYTE*)(ppib)); } #endif extern PIB *ppibGlobal; extern PIB *ppibGlobalMin; extern PIB *ppibGlobalMax; PROCID ProcidPIBOfPpib( PIB *ppib ); STATIC INLINE PROCID ProcidPIBOfPpib( PIB *ppib ) { return (PROCID)(((BYTE *)ppib - (BYTE *)ppibGlobalMin)/sizeof(PIB)); } STATIC INLINE PIB *PpibOfProcid( PROCID procid ) { return ppibGlobalMin + procid; } /* PIB validation /**/ #define ErrPIBCheck( ppib ) \ ( ( ppib >= ppibGlobalMin \ && ppib < ppibGlobalMax \ && ( ( (BYTE *)ppib - (BYTE *)ppibGlobalMin ) % sizeof(PIB) ) == 0 \ && ppib->procid == ProcidPIBOfPpib( ppib ) ) \ ? JET_errSuccess : JET_errInvalidSesid ) #define CheckPIB( ppib ) \ Assert( ErrPIBCheck( ppib ) == JET_errSuccess \ && (ppib)->level < levelMax ) #if 0 #define FPIBDeferFreeNodeSpace( ppib ) ( (ppib)->fDeferFreeNodeSpace ) #define PIBSetDeferFreeNodeSpace( ppib ) ( (ppib)->fDeferFreeNodeSpace = fTrue ) #define PIBResetDeferFreeNodeSpace( ppib ) ( (ppib)->fDeferFreeNodeSpace = fFalse ) #endif #define FPIBActive( ppib ) ( (ppib)->level != levelNil ) #define SesidOfPib( ppib ) ( (ppib)->sesid ) /* prototypes /**/ LONG CppibPIBUserSessions( VOID ); VOID RecalcTrxOldest( ); ERR ErrPIBBeginSession( PIB **pppib, PROCID procid ); VOID PIBEndSession( PIB *ppib ); #ifdef DEBUG VOID PIBPurge( VOID ); #else #define PIBPurge() #endif #define PIBUpdatePrceNewest( ppib, prce ) \ { \ if ( (ppib)->prceNewest == (prce) ) \ { \ Assert( (prce)->prceNextOfSession == prceNil ); \ (ppib)->prceNewest = prceNil; \ } \ } #define PIBSetPrceNewest( ppib, prce ) \ { \ (ppib)->prceNewest = (prce); \ } #define PIBSetLevelRollback( ppib, levelT ) \ { \ Assert( (levelT) > levelMin && \ (levelT) < levelMax ); \ Assert( (ppib)->levelRollback >= levelMin && \ (ppib)->levelRollback < levelMax ); \ if ( levelT < (ppib)->levelRollback ) \ (ppib)->levelRollback = (levelT); \ }