/* node status returned from VERAccess* /**/ typedef enum { nsVersion, nsVerInDB, nsDatabase, nsInvalid } NS; /* version status returned from VERCheck /**/ typedef enum { vsCommitted, vsUncommittedByCaller, vsUncommittedByOther } VS; // =========================================================================== // RCE (Revision Control Entry) /* operation type /**/ typedef UINT OPER; #define operReplace 0 #define operInsert 1 #define operFlagDelete 2 #define operNull 3 // to void an RCE #define operExpungeLink 4 #define operExpungeBackLink 5 #define operWriteLock 6 #define operAllocExt 7 #define operDeferFreeExt 8 #define operDelete 9 // a real delete #define operReplaceWithDeferredBI 10 // recovery only, replace deferred before image. #define operDelta 0x0010 #define operMaskItem 0x0020 #define operInsertItem 0x0020 #define operFlagInsertItem 0x0060 #define operFlagDeleteItem 0x00a0 #define operMaskDDL 0x0100 #define operCreateTable 0x0100 #define operDeleteTable 0x0300 #define operRenameTable 0x0500 #define operAddColumn 0x0700 #define operDeleteColumn 0x0900 #define operRenameColumn 0x0b00 #define operCreateIndex 0x0d00 #define operDeleteIndex 0x0f00 #define operRenameIndex 0x1100 /* create table: table pgnoFDP /* rename table: before image table name /* add column: before image pfdb, NULL if not first DDL at level /* delete column: before image pfdb, NULL if not first DDL at level /* rename column: before image column name /* create index: index pgnoFDP /* delete index: index pfcb /* rename index: before image index name /**/ #define FOperDDL( oper ) ( (oper) & operMaskDDL ) #define FOperItem( oper ) ( (oper) & operMaskItem ) typedef struct _rce { struct _rce *prceHashOverflow; // hash over flow RCE chain struct _rce *prcePrevOfNode; // previous versions for same node, lower trx struct _rce *prcePrevOfSession; // previous RCE of same session struct _rce *prceNextOfSession; // next RCE of same session USHORT ibPrev; // index to prev RCE in bucket // UNDONE: DBID->BYTE and put with level LEVEL level; // current level of RCE, can change BYTE bReserved; // make it aligned. SRID bm; // bookmark of node TRX trxPrev; // time when previous RCE is committed TRX trxCommitted; // time when this RCE is committed FUCB *pfucb; // for undo // UNDONE: OPER should be UINT16 and put with cbData OPER oper; // operation that causes creation of RCE DBID dbid; // database id of node WORD cbData; // length of data portion of node // UNDONE: remove pfcb after unified bucket chain allows // presynchronized version clean up. FCB *pfcb; // for clean up // UNDONE: remove bmTarget and ulDBTime after VR bookmark implementation. // These fields should not be necessary, since version store // will be aware of node movements. SRID bmTarget; // for recovery of undo QWORD qwDBTime; // for recovery of undo struct _bf *pbfDeferredBI; // which page deferred before image is on. struct _rce *prceDeferredBINext; // link list for deferred before image. #ifdef DEBUG QWORD qwDBTimeDeferredBIRemoved; #endif BYTE rgbData[0]; // storing the data portion of a node } RCE; /* first 2 SHORTs of rgbData are used to remember cbMax and cbAdjust for * each replace operation. */ #define cbReplaceRCEOverhead (2 * sizeof(SHORT)) //============================================================================ // bucket #define cbBucketHeader \ ( 2 * sizeof(struct _bucket *) + sizeof(UINT) ) #define cbBucket 16384 // number of bytes in a bucket typedef struct _bucket { struct _bucket *pbucketPrev; // prev bucket for same user struct _bucket *pbucketNext; // next bucket for same user UINT ibNewestRCE; // newest RCE within bucket BYTE rgb[ cbBucket - cbBucketHeader ]; // space for storing RCEs } BUCKET; /* free extent parameter block /**/ typedef struct { PGNO pgnoFDP; PGNO pgnoChildFDP; PGNO pgnoFirst; CPG cpgSize; } VEREXT; /* rename rollback parameter block /**/ typedef struct { CHAR szName[ JET_cbNameMost + 1 ]; CHAR szNameNew[ JET_cbNameMost + 1 ]; } VERRENAME; /* delete column rollback parameter block /**/ typedef struct tagVERCOLUMN { JET_COLTYP coltyp; // column type FID fid; // field id } VERCOLUMN; /* ErrRCEClean flags /**/ #define fRCECleanSession (1<<0) ERR ErrVERInit( VOID ); VOID VERTerm( BOOL fNormal ); VS VsVERCheck( FUCB *pfucb, SRID bm ); NS NsVERAccessNode( FUCB *pfucb, SRID bm ); NS NsVERAccessItem( FUCB *pfucb, SRID bm ); ERR FVERUncommittedVersion( FUCB *pfucb, SRID bm ); ERR FVERDelta( FUCB *pfucb, SRID bm ); ERR ErrVERCreate( FUCB *pfucb, SRID bm, OPER oper, RCE **pprce ); ERR ErrVERModify( FUCB *pfucb, SRID bm, OPER oper, RCE **pprce); BOOL FVERNoVersion( DBID dbid, SRID bm ); ERR ErrRCEClean( PIB *ppib, INT fCleanSession ); ERR ErrVERBeginTransaction( PIB *ppib ); VOID VERPrecommitTransaction( PIB *ppib ); VOID VERCommitTransaction( PIB *ppib, BOOL fCleanSession ); ERR ErrVERRollback(PIB *ppib); RCE *PrceRCEGet( DBID dbid, SRID bm ); #define fDoNotUpdatePage fFalse #define fDoUpdatePage fTrue VOID VERSetCbAdjust(FUCB *pfucb, RCE *prce, INT cbDataNew, INT cbData, BOOL fNotUpdatePage ); INT CbVERGetNodeMax( DBID dbid, SRID bm ); INT CbVERGetNodeReserve( PIB *ppib, DBID dbid, SRID bm, INT cbCurrentData ); INT CbVERUncommittedFreed( BF *pbf ); BOOL FVERCheckUncommittedFreedSpace( BF *pbf, INT cbReq ); BOOL FVERItemVersion( DBID dbid, SRID bm, ITEM item ); BOOL FVERMostRecent( FUCB *pfucb, SRID bm ); VOID VERDeleteFromDeferredBIChain( RCE *prce ); #define ErrVERReplace( pfucb, srid, pprce ) ErrVERModify( pfucb, srid, operReplace, pprce ) #define ErrVERInsert( pfucb, srid ) ErrVERCreate( pfucb, srid, operInsert, pNil ) #define ErrVERFlagDelete( pfucb, srid ) ErrVERModify( pfucb, srid, operFlagDelete, pNil ) #define ErrVERInsertItem( pfucb, srid ) ErrVERCreate( pfucb, srid, operInsertItem, pNil ) #define ErrVERFlagInsertItem( pfucb, srid ) ErrVERModify( pfucb, srid, operFlagInsertItem, pNil ) #define ErrVERFlagDeleteItem( pfucb, srid ) ErrVERModify( pfucb, srid, operFlagDeleteItem, pNil ) #define ErrVERDelta( pfucb, srid ) ErrVERModify( pfucb, srid, operDelta, pNil ) #define ErrRCECleanAllPIB( ) ErrRCEClean( ppibNil, 0 ) #define FVERPotThere( vs, fDelete ) \ ( ( (vs) != vsUncommittedByOther && !(fDelete) ) || \ (vs) == vsUncommittedByOther ) ERR ErrVERFlag( FUCB *pfucb, OPER oper, VOID *pv, INT cb ); VOID VERDeleteRce( RCE *prce ); #define FVERUndoLoggedOper( prce ) \ ( prce->oper == operReplace || \ prce->oper == operInsert || \ prce->oper == operFlagDelete || \ prce->oper == operInsertItem || \ prce->oper == operFlagInsertItem || \ prce->oper == operFlagDeleteItem || \ prce->oper == operDelta ) ERR ErrVERUndo( RCE *prce );