649 lines
19 KiB
C
649 lines
19 KiB
C
/**********************************************************
|
|
/************** DIR STRUCTURES and CONSTANTS **************
|
|
/**********************************************************
|
|
/**/
|
|
|
|
#include "node.h"
|
|
|
|
/************** DIR API defines and types ******************
|
|
/***********************************************************
|
|
/**/
|
|
typedef struct {
|
|
ULONG ulLT;
|
|
ULONG ulTotal;
|
|
} FRAC;
|
|
|
|
typedef INT POS;
|
|
#define posFirst 0
|
|
#define posLast 1
|
|
#define posDown 2
|
|
#define posFrac 3
|
|
|
|
#define fDIRNull 0
|
|
#define fDIRPurgeParent (1<<0)
|
|
#define fDIRBackToFather (1<<1)
|
|
#define fDIRNeighborKey (1<<2)
|
|
#define fDIRPotentialNode (1<<3)
|
|
#define fDIRAllNode (1<<4)
|
|
#define fDIRAllPage (1<<5)
|
|
#define fDIRReplace (1<<6)
|
|
#define fDIRReplaceDuplicate (1<<7)
|
|
#define fDIRDuplicate (1<<8)
|
|
#define fDIRSpace (1<<9)
|
|
#define fDIRVersion (1<<10)
|
|
#define fDIRAppendItem (1<<12)
|
|
#define fDIRDeleteItem (1<<13)
|
|
#define fDIRLogColumnDiffs (1<<14)
|
|
#define fDIRLogChunkDiffs (1<<15)
|
|
#define fDIRNoLog (1<<16)
|
|
#define fDIRNoVersion 0
|
|
#define fDIRNoMPLRegister (1<<17)
|
|
|
|
/* item list nodes not versioned
|
|
/**/
|
|
#define fDIRItemList fDIRPotentialNode
|
|
|
|
struct _dib {
|
|
POS pos;
|
|
KEY *pkey;
|
|
INT fFlags;
|
|
};
|
|
|
|
#define itagOWNEXT 1
|
|
#define itagAVAILEXT 2
|
|
#define itagDATA 3
|
|
#define itagLONG 4
|
|
#define itagAUTOINC 5
|
|
|
|
#define PgnoFDPOfPfucb(pfucb) ((pfucb)->u.pfcb->pgnoFDP)
|
|
#define PgnoRootOfPfucb(pfucb) ((pfucb)->u.pfcb->pgnoFDP)
|
|
#define ItagRootOfPfucb(pfucb) itagDATA
|
|
|
|
#define ErrDIRGetBookmark( pfucb, psrid ) \
|
|
( PcsrCurrent( pfucb )->csrstat == csrstatOnCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatDeferGotoBookmark ? \
|
|
( *psrid = PcsrCurrent( pfucb )->bm, JET_errSuccess ) : \
|
|
ErrERRCheck( JET_errNoCurrentRecord ) )
|
|
|
|
#define DIRGetBookmark( pfucb, psrid ) \
|
|
( *((SRID *)psrid) = PcsrCurrent( pfucb )->bm )
|
|
|
|
#define DIRGotoBookmark DIRDeferGotoBookmark
|
|
|
|
#ifdef PREREAD
|
|
|
|
#define DIRDeferGotoBookmark( pfucb, bmT ) \
|
|
{ \
|
|
FUCBResetPreread( pfucb ); \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatDeferGotoBookmark; \
|
|
PcsrCurrent( pfucb )->bm = bmT; \
|
|
( pfucb )->sridFather = sridNull; \
|
|
DIRSetRefresh( pfucb ); \
|
|
}
|
|
|
|
#else
|
|
|
|
#define DIRDeferGotoBookmark( pfucb, bmT ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatDeferGotoBookmark; \
|
|
PcsrCurrent( pfucb )->bm = bmT; \
|
|
( pfucb )->sridFather = sridNull; \
|
|
DIRSetRefresh( pfucb ); \
|
|
}
|
|
|
|
#endif // PREREAD
|
|
|
|
#define DIRGotoBookmarkItem( pfucb, bmT, itemT ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatDeferGotoBookmark; \
|
|
PcsrCurrent( pfucb )->bm = bmT; \
|
|
PcsrCurrent( pfucb )->item = itemT; \
|
|
( pfucb )->sridFather = sridNull; \
|
|
DIRSetRefresh( pfucb ); \
|
|
}
|
|
|
|
#define DIRGotoPgnoItag( pfucb, pgnoT, itagT ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatOnCurNode; \
|
|
PcsrCurrent( pfucb )->bm = SridOfPgnoItag( (pgnoT), (itagT) ); \
|
|
PcsrCurrent( pfucb )->pgno = (pgnoT); \
|
|
PcsrCurrent( pfucb )->itag = (itagT); \
|
|
( pfucb )->sridFather = sridNull; \
|
|
DIRSetRefresh( pfucb ); \
|
|
}
|
|
|
|
#define DIRGotoFDPRoot( pfucb ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatOnFDPNode; \
|
|
PcsrCurrent( pfucb )->bm = \
|
|
SridOfPgnoItag( PgnoFDPOfPfucb( pfucb ), itagFOP ); \
|
|
PcsrCurrent( pfucb )->pgno = PgnoFDPOfPfucb( pfucb ); \
|
|
PcsrCurrent( pfucb )->itag = itagFOP; \
|
|
PcsrCurrent( pfucb )->itagFather = itagFOP; \
|
|
( pfucb )->sridFather = sridNull; \
|
|
if ( !FBFReadAccessPage( pfucb, PcsrCurrent( pfucb )->pgno ) ) \
|
|
{ \
|
|
if ( ErrBFReadAccessPage( pfucb, \
|
|
PcsrCurrent( pfucb )->pgno ) < 0 ) \
|
|
{ \
|
|
DIRSetRefresh( pfucb ); \
|
|
} \
|
|
else \
|
|
{ \
|
|
NDGet( pfucb, PcsrCurrent( pfucb )->itag ); \
|
|
DIRSetFresh( pfucb ); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define DIRGotoOWNEXT( pfucb, pgnoT ) \
|
|
{ \
|
|
DIRGotoPgnoItag( pfucb, pgnoT, itagOWNEXT ); \
|
|
Assert( ( pfucb )->sridFather == sridNull ); \
|
|
PcsrCurrent( pfucb )->itagFather = itagFOP; \
|
|
}
|
|
|
|
#define DIRGotoAVAILEXT( pfucb, pgnoT ) \
|
|
{ \
|
|
DIRGotoPgnoItag( pfucb, pgnoT, itagAVAILEXT ); \
|
|
PcsrCurrent( pfucb )->itagFather = itagFOP; \
|
|
}
|
|
|
|
#define DIRGotoLongRoot( pfucb ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatOnCurNode; \
|
|
PcsrCurrent( pfucb )->bm = \
|
|
SridOfPgnoItag( PgnoFDPOfPfucb( pfucb ), itagLONG ); \
|
|
PcsrCurrent( pfucb )->pgno = PgnoFDPOfPfucb( pfucb ); \
|
|
PcsrCurrent( pfucb )->itag = itagLONG; \
|
|
PcsrCurrent( pfucb )->itagFather = itagNull; \
|
|
( pfucb )->sridFather = sridNull; \
|
|
if ( !FBFReadAccessPage( pfucb, PcsrCurrent( pfucb )->pgno ) ) \
|
|
{ \
|
|
if ( ErrBFReadAccessPage( pfucb, \
|
|
PcsrCurrent( pfucb )->pgno ) < 0 ) \
|
|
{ \
|
|
DIRSetRefresh( pfucb ); \
|
|
} \
|
|
else \
|
|
{ \
|
|
NDGet( pfucb, PcsrCurrent( pfucb )->itag ); \
|
|
DIRSetFresh( pfucb ); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define DIRGotoDataRoot( pfucb ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatOnCurNode; \
|
|
PcsrCurrent( pfucb )->bm = \
|
|
SridOfPgnoItag( PgnoFDPOfPfucb( pfucb ), itagDATA ); \
|
|
PcsrCurrent( pfucb )->pgno = PgnoFDPOfPfucb( pfucb ); \
|
|
PcsrCurrent( pfucb )->itag = itagDATA; \
|
|
PcsrCurrent( pfucb )->itagFather = itagNull; \
|
|
( pfucb )->sridFather = sridNull; \
|
|
if ( !FBFReadAccessPage( pfucb, PcsrCurrent( pfucb )->pgno ) ) \
|
|
{ \
|
|
if ( ErrBFReadAccessPage( pfucb, \
|
|
PcsrCurrent( pfucb )->pgno ) < 0 ) \
|
|
{ \
|
|
DIRSetRefresh( pfucb ); \
|
|
} \
|
|
else \
|
|
{ \
|
|
NDGet( pfucb, PcsrCurrent( pfucb )->itag ); \
|
|
DIRSetFresh( pfucb ); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define FDIRDataRootRoot( pfucb, pcsr ) \
|
|
( (pcsr)->pgno == PgnoFDPOfPfucb( pfucb ) && \
|
|
(pcsr)->itag == ItagRootOfPfucb( pfucb ) )
|
|
|
|
#define DIRDeferMoveFirst( pfucb ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->csrstat = csrstatDeferMoveFirst; \
|
|
DIRSetRefresh( pfucb ); \
|
|
}
|
|
|
|
#define DIRSetIndexRange FUCBSetIndexRange
|
|
#define DIRResetIndexRange FUCBResetIndexRange
|
|
|
|
ERR ErrDIROpen( PIB *ppib, FCB *pfcb, DBID dbid, FUCB **ppfucb );
|
|
VOID DIRClose( FUCB *pfucb );
|
|
ERR ErrDIRDown( FUCB *pfucb, DIB *pdib );
|
|
ERR ErrDIRDownFromDATA( FUCB *pfucb, KEY *pkey );
|
|
VOID DIRUp( FUCB *pfucb, INT ccsr );
|
|
ERR ErrDIRNext( FUCB *pfucb, DIB *pdib );
|
|
ERR ErrDIRPrev( FUCB *pfucb, DIB *pdib );
|
|
ERR ErrDIRGet( FUCB *pfucb );
|
|
ERR ErrDIRCheckIndexRange( FUCB *pfucb );
|
|
ERR ErrDIRGetBMOfItemList( FUCB *pfucb, SRID *pbmItemList );
|
|
|
|
ERR ErrDIRGetWriteLock( FUCB *pfucb );
|
|
|
|
ERR ErrDIRInsert( FUCB *pfucb, LINE *pline, KEY *pkey, INT fFlags );
|
|
ERR ErrDIRInitAppendItem( FUCB *pfucb );
|
|
ERR ErrDIRAppendItem( FUCB *pfucb, LINE *pline, KEY *pkey, SRID sridPrev );
|
|
ERR ErrDIRTermAppendItem( FUCB *pfucb );
|
|
|
|
ERR ErrDIRCreateDirectory( FUCB *pfucb, CPG cpgMin, PGNO *ppgnoFDP );
|
|
#define ErrDIRDeleteDirectory( pfucb, pgnoFDP ) ErrSPFreeFDP( pfucb, pgnoFDP )
|
|
|
|
ERR ErrDIRDelete( FUCB *pfucb, INT fFlags );
|
|
ERR ErrDIRReplace( FUCB *pfucb, LINE *pline, INT fFlags );
|
|
ERR ErrDIRReplaceKey( FUCB *pfucb, KEY *pkeyTo, INT fFlags );
|
|
|
|
ERR ErrDIRDownKeyBookmark( FUCB *pfucb, KEY *pkey, SRID srid );
|
|
ERR ErrDIRGetPosition( FUCB *pfucb, ULONG *pulLT, ULONG *pulTotal );
|
|
ERR ErrDIRGotoPosition( FUCB *pfucb, ULONG ulLT, ULONG ulTotal );
|
|
ERR ErrDIRIndexRecordCount( FUCB *pfucb, ULONG *pulCount, ULONG ulCountMost, BOOL fNext );
|
|
ERR ErrDIRComputeStats( FUCB *pfucb, INT *pcitem, INT *pckey, INT *pcpage );
|
|
|
|
ERR ErrDIRDelta( FUCB *pfucb, INT iDelta, INT fFlags );
|
|
|
|
ERR ErrDIRBeginTransaction( PIB *ppib );
|
|
ERR ErrDIRRefreshTransaction( PIB *ppib );
|
|
ERR ErrDIRCommitTransaction( PIB *ppib, JET_GRBIT grbit );
|
|
VOID DIRPurge( PIB *ppib );
|
|
ERR ErrDIRRollback( PIB *ppib );
|
|
|
|
#define DIRBeforeFirst( pfucb ) ( PcsrCurrent(pfucb)->csrstat = csrstatBeforeFirst )
|
|
#define DIRAfterLast( pfucb ) ( PcsrCurrent(pfucb)->csrstat = csrstatAfterLast )
|
|
#define FDIRMostRecent FBTMostRecent
|
|
#define FDIRDelta FVERDelta
|
|
|
|
ERR ErrDIRDump( FUCB *pfucb, INT cchIndent );
|
|
|
|
|
|
/**********************************************************
|
|
/******************* DIR Internal *************************
|
|
/**********************************************************
|
|
/**/
|
|
#define itagFOP 0
|
|
#define cbSonMax 256
|
|
#define qwDBTimeNull 0xffffffffffffffff
|
|
#define itagDIRDVSplitL 1
|
|
#define itagDIRDVSplitR 2
|
|
|
|
/* maximum node data size for nodes which ErrNDDelta can be used on.
|
|
/* Specifically this minimally supports long value root nodes.
|
|
/**/
|
|
#define cbMaxCounterNode 8
|
|
|
|
/* Offset of data field to counter. for long field reference counter.
|
|
**/
|
|
#define ibCounter 0
|
|
|
|
/* non-clustered index cursors already have item stored.
|
|
/**/
|
|
#ifdef DEBUG
|
|
|
|
#define CheckCSR( pfucb ) Assert( fRecovering || \
|
|
(PcsrCurrent(pfucb) == pcsrNil || \
|
|
PcsrCurrent(pfucb)->pcsrPath == pcsrNil || \
|
|
PcsrCurrent(pfucb)->pgno != PcsrCurrent(pfucb)->pcsrPath->pgno || \
|
|
PcsrCurrent(pfucb)->itag != PcsrCurrent(pfucb)->pcsrPath->itag ) );
|
|
|
|
#define DIRSetFresh( pfucb ) \
|
|
{ \
|
|
Assert( PcsrCurrent( pfucb )->csrstat == csrstatOnCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatBeforeCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatAfterCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatOnFDPNode ); \
|
|
AssertNDGet( pfucb, PcsrCurrent( pfucb )->itag ); \
|
|
PcsrCurrent( pfucb )->qwDBTime = QwSTDBTimePssib( &(pfucb)->ssib ); \
|
|
}
|
|
|
|
#define DIRSetRefresh( pfucb ) \
|
|
{ \
|
|
Assert( PcsrCurrent( pfucb )->csrstat == csrstatOnCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatBeforeCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatAfterCurNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatOnFDPNode || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatDeferGotoBookmark || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatDeferMoveFirst || \
|
|
PcsrCurrent( pfucb )->csrstat == csrstatOnDataRoot ); \
|
|
PcsrCurrent( pfucb )->qwDBTime = qwDBTimeNull; \
|
|
}
|
|
|
|
#else
|
|
|
|
#define CheckCSR( pfucb )
|
|
|
|
#define DIRSetFresh( pfucb ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->qwDBTime = QwSTDBTimePssib( &(pfucb)->ssib ); \
|
|
}
|
|
|
|
#define DIRSetRefresh( pfucb ) \
|
|
{ \
|
|
PcsrCurrent( pfucb )->qwDBTime = qwDBTimeNull; \
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/**********************************************************
|
|
/********************* BTREE API **************************
|
|
/**********************************************************
|
|
/**/
|
|
#define sridMin 0
|
|
#define sridMax 0xffffffff
|
|
|
|
/* must be on node, i.e. on current node, before node or after node.
|
|
/* Node must be in line cache.
|
|
/**/
|
|
#define DIRISetBookmark( pfucb, pcsr ) \
|
|
{ \
|
|
AssertFBFReadAccessPage( (pfucb), (pcsr)->pgno ); \
|
|
\
|
|
if ( FNDBackLink( *( (pfucb)->ssib.line.pb ) ) ) \
|
|
(pcsr)->bm = *(SRID UNALIGNED *)PbNDBackLink( (pfucb)->ssib.line.pb ); \
|
|
else \
|
|
(pcsr)->bm = SridOfPgnoItag( (pcsr)->pgno, (pcsr)->itag ); \
|
|
}
|
|
|
|
|
|
BOOL FBTMostRecent( FUCB *pfucb );
|
|
|
|
#define ErrBTNext( pfucb, pdib ) \
|
|
( ErrBTNextPrev( pfucb, PcsrCurrent(pfucb), fTrue, pdib, NULL ) )
|
|
#define ErrBTPrev( pfucb, pdib ) \
|
|
( ErrBTNextPrev( pfucb, PcsrCurrent(pfucb), fFalse, pdib, NULL ) )
|
|
#define BTUp( pfucb ) FUCBFreeCSR( pfucb )
|
|
|
|
ERR ErrBTGet( FUCB *pfucb, CSR *pcsr );
|
|
ERR ErrBTGetNode( FUCB *pfucb, CSR *pcsr );
|
|
#ifdef DEBUG
|
|
VOID AssertBTGetNode( FUCB *pfucb, CSR *pcsr );
|
|
#else
|
|
#define AssertBTGetNode
|
|
#endif
|
|
ERR ErrBTSetNodeHeader( FUCB *pfucb, BYTE bHeader );
|
|
ERR ErrBTReplaceKey( FUCB *pfucb, KEY *pkey, INT fFlags );
|
|
ERR ErrBTDown( FUCB *pfucb, DIB *pdib );
|
|
ERR ErrBTDownFromDATA( FUCB *pfucb, KEY *pkey );
|
|
ERR ErrBTNextPrev( FUCB *pfucb, CSR *pcsr, INT fNext, DIB *pdib, BOOL *pfEmptyPage );
|
|
ERR ErrBTSeekForUpdate( FUCB *pfucb, KEY *pkey, PGNO pgno, INT itag, INT fDIRFlags );
|
|
ERR ErrBTInsert( FUCB *pfucb, INT fHeader, KEY *pkey,
|
|
LINE *pline, INT fDIRFlags, BOOL *pfCleaned );
|
|
ERR ErrBTReplace( FUCB *pfucb, LINE *pline,
|
|
INT fFlags, BOOL *pfCleaned );
|
|
ERR ErrBTDelete( FUCB *pfucb, INT fFlags );
|
|
ERR ErrBTMakeRoom( FUCB *pfucb, CSR *pcsrRoot, INT cbReq );
|
|
ERR ErrBTGetPosition( FUCB *pfucb, ULONG *pulLT, ULONG *pulTotal );
|
|
ERR ErrBTGotoBookmark( FUCB *pfucb, SRID srid );
|
|
ERR ErrBTGetInvisiblePagePtr( FUCB *pfucb, SRID sridFather );
|
|
#ifdef DEBUG
|
|
ERR ErrBTCheckInvisiblePagePtr( FUCB *pfucb, SRID sridFather );
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
VOID BTCheckSplit( FUCB *pfucb, CSR *pcsr );
|
|
#else
|
|
#define BTCheckSplit( pfucb, pcsr )
|
|
#endif
|
|
|
|
|
|
/**********************************************************
|
|
/*********************** BT Split *************************
|
|
/**********************************************************
|
|
/**/
|
|
typedef enum {
|
|
splittNull,
|
|
splittVertical,
|
|
splittDoubleVertical,
|
|
splittLeft,
|
|
splittRight,
|
|
splittAppend
|
|
} SPLITT;
|
|
|
|
typedef enum {
|
|
opReplace,
|
|
opInsert
|
|
} OPERATION;
|
|
|
|
typedef struct {
|
|
PN pn;
|
|
QWORD qwDBTime;
|
|
} LFINFO; /* leaf split info */
|
|
|
|
|
|
typedef struct
|
|
{
|
|
SRID sridNew;
|
|
SRID sridBackLink;
|
|
} BKLNK;
|
|
|
|
|
|
typedef struct _split {
|
|
PIB *ppib;
|
|
PGNO pgnoSplit;
|
|
PGNO pgnoNew;
|
|
PGNO pgnoNew2;
|
|
PGNO pgnoNew3;
|
|
PGNO pgnoSibling;
|
|
|
|
BF *pbfSplit; /* BF of page being split */
|
|
BF *pbfNew; /* BF of new page of this split */
|
|
BF *pbfNew2; /* BF of new page of this split */
|
|
BF *pbfNew3; /* BF of new page of this split */
|
|
BF *pbfSibling; /* BF of sibling page of this H split */
|
|
BF *pbfPagePtr;
|
|
|
|
BOOL fNoRedoNew; /* no need to redo new page */
|
|
BOOL fNoRedoNew2; /* no need to redo new page 2 */
|
|
BOOL fNoRedoNew3; /* no need to redo new page 3 */
|
|
|
|
BF **rgpbf; /* BF of backlink page. */
|
|
INT cpbf;
|
|
INT cpbfMax;
|
|
|
|
BKLNK *rgbklnk; /* SRID of backlinks. */
|
|
INT cbklnk;
|
|
INT cbklnkAlloc;
|
|
INT cbklnkMax;
|
|
|
|
QWORD qwDBTimeRedo; /* redo timestamp */
|
|
|
|
INT itagSplit;
|
|
INT ibSon;
|
|
KEY key;
|
|
KEY keyMac;
|
|
|
|
SPLITT splitt;
|
|
BOOL fLeaf;
|
|
OPERATION op;
|
|
BOOL fFDP;
|
|
DBID dbid;
|
|
INT itagNew;
|
|
INT itagPagePointer;
|
|
|
|
BYTE rgbSonSplit[cbSonMax];
|
|
BYTE rgbSonNew[cbSonMax];
|
|
|
|
BYTE rgbkeyMac[JET_cbKeyMost];
|
|
BYTE rgbKey[JET_cbKeyMost];
|
|
|
|
/* mapping from old to new tags for use in MCM
|
|
/**/
|
|
BYTE mpitag[ctagMax];
|
|
INT ipcsrMac; /* preallocated resource for csr */
|
|
#define ipcsrSplitMax 4
|
|
CSR *rgpcsr[ipcsrSplitMax];
|
|
} SPLIT;
|
|
|
|
|
|
typedef struct _rmpage {
|
|
PIB *ppib;
|
|
|
|
QWORD qwDBTimeRedo; /* redo timestamp */
|
|
|
|
BF *pbfLeft;
|
|
BF *pbfRight;
|
|
BF *pbfFather;
|
|
|
|
BKLNK **rgbklnk; /* latched buffers required for rmpage */
|
|
INT cbklnk;
|
|
INT cbklnkMax;
|
|
|
|
BF **rgpbf; /* latched buffers required for rmpage */
|
|
INT cpbf;
|
|
INT cpbfMax;
|
|
|
|
PGNO pgnoRemoved;
|
|
PGNO pgnoLeft;
|
|
PGNO pgnoRight;
|
|
PGNO pgnoFather;
|
|
INT itagPgptr;
|
|
INT itagFather;
|
|
INT ibSon;
|
|
DBID dbid;
|
|
} RMPAGE;
|
|
|
|
#define CbFreeDensity(pfucb) \
|
|
( (pfucb)->u.pfcb != pfcbNil ? (INT)(pfucb)->u.pfcb->cbDensityFree : 0 )
|
|
|
|
/* protypes for split used by recovery of split operations.
|
|
/**/
|
|
ERR ErrBTStoreBackLinkBuffer( SPLIT *psplit, BF *pbf, BOOL *pfAlreadyLatched );
|
|
ERR ErrBTSplit( FUCB *pfucb, INT cbNode, INT cbReq, KEY *pkey, INT fFlags );
|
|
ERR ErrBTSplitPage( FUCB *pfucb, CSR *pcsr, CSR *pcsrRoot,
|
|
KEY keySplit, INT cbNode, INT cbReq, BOOL fReplace, BOOL fAppendPage );
|
|
BOOL FBTSplit( SSIB *pssib, INT cbReq, INT citagReq );
|
|
BOOL FBTAppendPage( FUCB *pfucb, CSR *pcsr, INT cbReq, INT cbPageAdjust, INT cbFreeDensity, INT citagReq );
|
|
INT CbBTFree( FUCB *pfucb, INT cbFreeDensity );
|
|
|
|
#define fAllocBufOnly fTrue
|
|
#define fDoMove fFalse
|
|
|
|
ERR ErrBTSplitVMoveNodes(
|
|
FUCB *pfucb,
|
|
FUCB *pfucbNew,
|
|
SPLIT *psplit,
|
|
CSR *pcsr,
|
|
BYTE *rgb,
|
|
BOOL fNoMove);
|
|
ERR ErrBTSplitDoubleVMoveNodes(
|
|
FUCB *pfucb,
|
|
FUCB *pfucbNew,
|
|
FUCB *pfucbNew2,
|
|
FUCB *pfucbNew3,
|
|
SPLIT *psplit,
|
|
CSR *pcsr,
|
|
BYTE *rgb,
|
|
BOOL fNoMove);
|
|
ERR ErrBTSplitHMoveNodes(
|
|
FUCB *pfucb,
|
|
FUCB *pfucbNew,
|
|
SPLIT *psplit,
|
|
BYTE *rgb,
|
|
BOOL fNoMove);
|
|
ERR ErrBTInsertPagePointer( FUCB *pfucb, CSR *pcsrPagePointer, SPLIT *psplit, BYTE *rgb );
|
|
ERR ErrBTCorrectLinks(
|
|
SPLIT *psplit,
|
|
FUCB *pfucb,
|
|
SSIB *pssib,
|
|
SSIB *pssibNew);
|
|
VOID BTReleaseSplitBfs ( BOOL fRedo, SPLIT *psplit, ERR err );
|
|
VOID BTReleaseRmpageBfs( BOOL fRedo, RMPAGE *prmpage );
|
|
|
|
ERR ErrBTMoveSons( SPLIT *psplit,
|
|
FUCB *pfucb,
|
|
FUCB *pfucbNew,
|
|
INT itagSonTable,
|
|
BYTE *rgbSon,
|
|
BOOL fVisibleSons,
|
|
BOOL fNoMove,
|
|
BKLNK *pbklnk,
|
|
INT cbklnk );
|
|
|
|
ERR ErrBTSetUpSplitPages( FUCB *pfucb, FUCB *pfucbNew,
|
|
FUCB *pfucbNew2, FUCB *pfucbNew3, SPLIT *psplit,
|
|
PGTYP pgtyp, BOOL fAppend, BOOL fSkipMoves );
|
|
|
|
ERR ErrBTAbandonEmptyPage( FUCB *pfucb, KEY *pkey );
|
|
|
|
/**********************************************************
|
|
/********** MCM STRUCTURES, CONSTANTS and API *************
|
|
/**********************************************************
|
|
/**/
|
|
#define opInsertItem 0
|
|
#define opDeleteItem 1
|
|
#define opSplitItemList 2
|
|
|
|
#define opInsertSon 0
|
|
#define opReplaceSon 1
|
|
#define opDeleteSon 2
|
|
|
|
#define opHorizontalRightSplitPage 0
|
|
#define opHorizontalLeftSplitPage 1
|
|
|
|
#define opVerticalSplitPage 0
|
|
|
|
VOID MCMRightHorizontalPageSplit( FUCB *pfucb,
|
|
PGNO pgnoSplit, PGNO pgnoRight, INT ibSonSplit, BYTE *mpitag );
|
|
VOID MCMLeftHorizontalPageSplit( FUCB *pfucb,
|
|
PGNO pgnoSplit, PGNO pgnoNew, INT ibSonSplit, BYTE *mpitag );
|
|
VOID MCMVerticalPageSplit(
|
|
FUCB *pfucb,
|
|
BYTE *mpitag,
|
|
PGNO pgnoSplit,
|
|
INT itagSplit,
|
|
PGNO pgnoNew,
|
|
SPLIT *psplit );
|
|
VOID MCMDoubleVerticalPageSplit(
|
|
FUCB *pfucb,
|
|
BYTE *mpitag,
|
|
PGNO pgnoSplit,
|
|
INT itagSplit,
|
|
INT ibSonDivision,
|
|
PGNO pgnoNew,
|
|
PGNO pgnoNew2,
|
|
PGNO pgnoNew3,
|
|
SPLIT *psplit );
|
|
VOID MCMInsertPagePointer( FUCB *pfucb, PGNO pgnoFather, INT itagFather );
|
|
VOID MCMBurstIntrinsic( FUCB *pfucb, PGNO pgnoFather, INT itagFather, PGNO pgnoNew, INT itagNew );
|
|
|
|
#define FFUCBRecordCursor( pfucb ) ( \
|
|
( pfucb )->u.pfcb != pfcbNil ? \
|
|
FFCBClusteredIndex( ( pfucb )->u.pfcb ) : fFalse )
|
|
|
|
#ifdef NOLOG /* logging disabled */
|
|
|
|
#define ErrLGSplitL( ppib, pcsrPagePointer, psplit, pgtyp ) 0
|
|
#define ErrLGSplitR( ppib, pcsrPagePointer, psplit, pgtyp ) 0
|
|
#define ErrLGSplitV( ppib, psplit, pgtyp ) 0
|
|
#define ErrLGAddendR( pfucb, pcsrPagePointer, psplit, newpagetype ) 0
|
|
|
|
#else
|
|
|
|
ERR ErrLGSplitL(
|
|
FUCB *pfucb,
|
|
CSR *pcsrPagePointer,
|
|
SPLIT *psplit,
|
|
PGTYP newpagetype );
|
|
|
|
ERR ErrLGSplitR(
|
|
FUCB *pfucb,
|
|
CSR *pcsrPagePointer,
|
|
SPLIT *psplit,
|
|
PGTYP newpagetype );
|
|
|
|
ERR ErrLGSplitV(
|
|
FUCB *pfucb,
|
|
SPLIT *psplit,
|
|
PGTYP newpagetype );
|
|
|
|
ERR ErrLGAddendR(
|
|
FUCB *pfucb,
|
|
CSR *pcsrPagePointer,
|
|
SPLIT *psplit,
|
|
PGTYP newpagetype );
|
|
|
|
#endif
|
|
|
|
|