//------------------------------------------------------------------------------ // Desc: Header file for the B-Tree class definitions // // Tabs: 3 // // Copyright (c) 2002-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id$ //------------------------------------------------------------------------------ #ifndef F_BTREE_H #define F_BTREE_H // Represent the maximum size for data & key before needing two bytes to // store the length. #define ONE_BYTE_SIZE 0xFF // Flag definitions - BT_LEAF_DATA #define BTE_LEAF_DATA_OVHD 7 // Offset (2) Flags (1) OA Data (4) #define BTE_FLAG 0 // Offset to the FLAGS field #define BTE_FLAG_LAST_ELEMENT 0x04 #define BTE_FLAG_FIRST_ELEMENT 0x08 #define BTE_FLAG_DATA_BLOCK 0x10 // Data is stored in a Data-only Block #define BTE_FLAG_OA_DATA_LEN 0x20 // Overall data length #define BTE_FLAG_DATA_LEN 0x40 #define BTE_FLAG_KEY_LEN 0x80 // BT_LEAF (no data) #define BTE_LEAF_OVHD 4 // Offset (2) KeyLen (2) #define BTE_KEY_LEN 0 #define BTE_KEY_START 2 // BT_NON_LEAF_DATA #define BTE_NON_LEAF_OVHD 8 // Offset (2) Child Blk Addr (4) KeyLen (2) #define BTE_NL_CHILD_BLOCK_ADDR 0 #define BTE_NL_KEY_LEN 4 #define BTE_NL_KEY_START 6 // BT_NON_LEAF_COUNTS #define BTE_NON_LEAF_COUNTS_OVHD 12 // Offset (2) Child Blk Addr (4) Counts (4) KeyLen (2) #define BTE_NLC_CHILD_BLOCK_ADDR 0 #define BTE_NLC_COUNTS 4 #define BTE_NLC_KEY_LEN 8 #define BTE_NLC_KEY_START 10 // Low water mark for coalescing blocks (as a percentage) #define BT_LOW_WATER_MARK 65 FINLINE FLMBOOL bteKeyLenFlag( FLMBYTE * pucEntry) { return( (pucEntry[ BTE_FLAG] & BTE_FLAG_KEY_LEN) ? TRUE : FALSE); } FINLINE FLMBOOL bteDataLenFlag( FLMBYTE * pucEntry) { return( (pucEntry[ BTE_FLAG] & BTE_FLAG_DATA_LEN) ? TRUE : FALSE); } FINLINE FLMBOOL bteOADataLenFlag( FLMBYTE * pucEntry) { return( (pucEntry[ BTE_FLAG] & BTE_FLAG_OA_DATA_LEN) ? TRUE : FALSE); } FINLINE FLMBOOL bteDataBlockFlag( FLMBYTE * pucEntry) { return( (pucEntry[ BTE_FLAG] & BTE_FLAG_DATA_BLOCK) ? TRUE : FALSE); } FINLINE FLMBOOL bteFirstElementFlag( FLMBYTE * pucEntry) { return( (pucEntry[ BTE_FLAG] & BTE_FLAG_FIRST_ELEMENT) ? TRUE : FALSE); } FINLINE FLMBOOL bteLastElementFlag( FLMBYTE * pucEntry) { return( (pucEntry[ BTE_FLAG] & BTE_FLAG_LAST_ELEMENT) ? TRUE : FALSE); } FINLINE FLMUINT32 bteGetBlkAddr( const FLMBYTE * pucEntry) { return( FB2UD( pucEntry)); } FINLINE void bteSetEntryOffset( FLMUINT16 * pui16OffsetArray, FLMUINT uiOffsetIndex, FLMUINT16 ui16Offset) { UW2FBA( ui16Offset, (FLMBYTE *)&pui16OffsetArray[ uiOffsetIndex]); } FINLINE FLMUINT16 bteGetEntryOffset( const FLMUINT16 * pui16OffsetArray, FLMUINT uiOffsetIndex) { return( FB2UW( (FLMBYTE *)&pui16OffsetArray[ uiOffsetIndex])); } typedef struct F_BTSK { F_BTREE_BLK_HDR * pBlkHdr; F_CachedBlock * pSCache; const FLMBYTE * pucKeyBuf; FLMUINT uiKeyLen; FLMUINT uiCurOffset; FLMUINT uiLevel; FLMUINT16 * pui16OffsetArray; FLMUINT32 ui32BlkAddr; } F_BTSK; typedef enum { ELM_INSERT_DO, ELM_INSERT, ELM_REPLACE_DO, ELM_REPLACE, ELM_REMOVE, ELM_BLK_MERGE, ELM_DONE } F_ELM_UPD_ACTION; FINLINE FLMBYTE * BtEntry( FLMBYTE * pBlk, FLMUINT uiIndex) { FLMBYTE * pucOffsetArray = pBlk + sizeofBTreeBlkHdr( (F_BTREE_BLK_HDR *)pBlk) + (uiIndex * 2); // 2 byte offset entries. return( pBlk + FB2UW( pucOffsetArray)); } FINLINE FLMBYTE * BtLastEntry( FLMBYTE * pBlk ) { return BtEntry( pBlk, ((F_BTREE_BLK_HDR *)pBlk)->ui16NumKeys - 1); } FINLINE FLMUINT getBlkType( FLMBYTE * pBlk) { return (FLMUINT)((F_BLK_HDR *)pBlk)->ui8BlkType; } FINLINE FLMUINT16 * BtOffsetArray( FLMBYTE * pBlk, FLMUINT uiIndex) { return (FLMUINT16 *) (pBlk + sizeofBTreeBlkHdr( (F_BTREE_BLK_HDR *)pBlk) + (uiIndex * sizeof( FLMUINT16))); } // Returns the address of the first entry in the block. i.e. the first non-blank // address after the offset array. FINLINE FLMBYTE * getBlockEnd( F_BTREE_BLK_HDR * pBlkHdr) { return ((FLMBYTE *)pBlkHdr + sizeofBTreeBlkHdr( pBlkHdr) + (pBlkHdr->ui16NumKeys * 2) + pBlkHdr->ui16HeapSize); } // This inline function takes the parameter returned from getEntrySize which // adds 2 for the offset. FINLINE FLMUINT actualEntrySize( FLMUINT uiEntrySize) { return uiEntrySize - 2; } // Error information returned by btCheck() enum BTREE_ERR_TYPE { NO_ERR = 0, // FYI: Visual Studio already defines NOERROR BT_HEADER, KEY_ORDER, DUPLICATE_KEYS, INFINITY_MARKER, CHILD_BLOCK_ADDRESS, SCA_GET_BLOCK_FAILED, MISSING_OVERALL_DATA_LENGTH, NOT_DATA_ONLY_BLOCK, BAD_DO_BLOCK_LENGTHS, BAD_COUNTS, CATASTROPHIC_FAILURE = 999 }; typedef struct { FLMUINT uiKeyCnt; FLMUINT uiFirstKeyCnt; FLMUINT uiBlkCnt; FLMUINT uiBytesUsed; FLMUINT uiDOBlkCnt; FLMUINT uiDOBytesUsed; } BTREE_LEVEL_STATS; typedef struct { FLMUINT uiBlkAddr; FLMUINT uiBlockSize; FLMUINT uiBlocksChecked; FLMUINT uiAvgFreeSpace; FLMUINT uiLevels; FLMUINT uiNumKeys; FLMUINT64 ui64FreeSpace; BTREE_LEVEL_STATS LevelStats[ BH_MAX_LEVELS]; char szMsg[ 64]; BTREE_ERR_TYPE type; } BTREE_ERR_STRUCT; typedef struct { FLMUINT uiParentLevel; FLMUINT uiParentKeyLen; FLMUINT uiParentChildBlkAddr; FLMUINT uiNewKeyLen; FLMUINT uiChildBlkAddr; FLMUINT uiCounts; void * pPrev; FLMBYTE pucParentKey[ SFLM_MAX_KEY_SIZE]; FLMBYTE pucNewKey[ SFLM_MAX_KEY_SIZE]; } BTREE_REPLACE_STRUCT; class F_BtPool; class F_Btree : public F_Object { public: F_Btree( void); ~F_Btree( void); RCODE btCreate( F_Db * pDb, LFILE * pLFile, FLMBOOL bCounts, FLMBOOL bData); RCODE btOpen( F_Db * pDb, LFILE * pLFile, FLMBOOL bCounts, FLMBOOL bData, IF_ResultSetCompare * pCompare = NULL); void btClose( void); RCODE btDeleteTree( IF_DeleteStatus * ifpDeleteStatus); RCODE btGetBlockChains( FLMUINT * puiBlockChains, FLMUINT * puiNumLevels); RCODE btRemoveEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen); RCODE btInsertEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucData, FLMUINT uiDataLen, FLMBOOL bFirst, FLMBOOL bLast, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btReplaceEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucData, FLMUINT uiDataLen, FLMBOOL bFirst, FLMBOOL bLast, FLMBOOL bTruncate = TRUE, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btLocateEntry( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen, FLMUINT uiMatch, FLMUINT * puiPosition = NULL, FLMUINT * puiDataLength = NULL, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btGetEntry( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT uiKeyLen, FLMBYTE * pucData, FLMUINT uiDataBufSize, FLMUINT * puiDataLen); RCODE btNextEntry( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen, FLMUINT * puiDataLength = NULL, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btPrevEntry( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen, FLMUINT * puiDataLength = NULL, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btFirstEntry( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen, FLMUINT * puiDataLength = NULL, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btLastEntry( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen, FLMUINT * puiDataLength = NULL, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE btSetReadPosition( FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMUINT uiPosition); RCODE btGetReadPosition( FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMUINT * puiPosition); RCODE btPositionTo( FLMUINT uiPosition, FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen); RCODE btGetPosition( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiPosition); RCODE btCheck( BTREE_ERR_STRUCT * pErrStruct); RCODE btRewind( FLMBYTE * pucKey, FLMUINT uiKeyBufSize, FLMUINT * puiKeyLen); FINLINE void btGetTransInfo( FLMUINT64 * pui64LowTransId, FLMBOOL * pbMostCurrent) { *pui64LowTransId = m_ui64LowTransId; *pbMostCurrent = m_bMostCurrent; } FINLINE void btRelease( void) { releaseBlocks( TRUE); } FINLINE void btResetBtree( void) { releaseBlocks( TRUE); m_bSetupForRead = FALSE; m_bSetupForWrite = FALSE; m_bSetupForReplace = FALSE; m_bOrigInDOBlocks = FALSE; m_bDataOnlyBlock = FALSE; m_ui32PrimaryBlkAddr = 0; m_ui32CurBlkAddr = 0; m_uiPrimaryOffset = 0; m_uiCurOffset = 0; m_uiDataLength = 0; m_uiPrimaryDataLen = 0; m_uiOADataLength = 0; m_uiDataRemaining = 0; m_uiOADataRemaining = 0; m_uiOffsetAtStart = 0; m_ui64CurrTransID = 0; m_ui64LastBlkTransId = 0; m_ui64PrimaryBlkTransId = 0; m_uiBlkChangeCnt = 0; m_uiSearchLevel = BH_MAX_LEVELS; } RCODE btComputeCounts( F_Btree * pUntilBtree, FLMUINT64 * pui64BlkCount, FLMUINT64 * pui64KeyCount, FLMBOOL * pbTotalsEstimated, FLMUINT uiAvgBlkFullness); FINLINE void btSetSearchLevel( FLMUINT uiSearchLevel) { flmAssert( uiSearchLevel <= BH_MAX_LEVELS); btResetBtree(); m_uiSearchLevel = uiSearchLevel; } RCODE btMoveBlock( FLMUINT32 ui32FromBlkAddr, FLMUINT32 ui32ToBlkAddr); FINLINE FLMBOOL btHasCounts( void) { return m_bCounts; } FINLINE FLMBOOL btHasData( void) { return m_bData; } FINLINE FLMBOOL btDbIsOpen( void) { return m_bOpened; } FINLINE FLMBOOL btIsSetupForRead( void) { return m_bSetupForRead; } FINLINE FLMBOOL btIsSetupForWrite( void) { return m_bSetupForWrite; } FINLINE FLMBOOL btIsSetupForReplace( void) { return m_bSetupForReplace; } private: FINLINE FLMUINT calcEntrySize( FLMUINT uiBlkType, FLMUINT uiFlags, FLMUINT uiKeyLen, FLMUINT uiDataLen, FLMUINT uiOADataLen) { switch( uiBlkType) { case BT_LEAF: { return( uiKeyLen + 2); } case BT_LEAF_DATA: { return( 1 + // Flags (uiKeyLen > ONE_BYTE_SIZE ? 2 : 1) + // KeyLen (uiDataLen > ONE_BYTE_SIZE ? 2 : 1) + // DataLen (uiOADataLen && // OA DataLen (uiFlags & BTE_FLAG_FIRST_ELEMENT) ? 4 : 0) + uiKeyLen + uiDataLen); } case BT_NON_LEAF: case BT_NON_LEAF_COUNTS: { return( 4 + // Child block address (uiBlkType == BT_NON_LEAF_COUNTS ? 4 : 0) + // Counts 2 + // Key length uiKeyLen); } } return( 0); } RCODE computeCounts( F_BTSK * pFromStack, F_BTSK * pUntilStack, FLMUINT64 * pui64BlockCount, FLMUINT64 * pui64KeyCount, FLMBOOL * pbTotalsEstimated, FLMUINT uiAvgBlkFullness); RCODE blockCounts( F_BTSK * pStack, FLMUINT uiFirstOffset, FLMUINT uiLastOffset, FLMUINT * puiKeyCount, FLMUINT * puiElementCount); RCODE getStoredCounts( F_BTSK * pFromStack, F_BTSK * pUntilStack, FLMUINT64 * pui64BlockCount, FLMUINT64 * pui64KeyCount, FLMBOOL * pbTotalsEstimated, FLMUINT uiAvgBlkFullness); RCODE getCacheBlocks( F_BTSK * pStack1, F_BTSK * pStack2); FINLINE FLMUINT getAvgKeyCount( F_BTSK * pFromStack, F_BTSK * pUntilStack, FLMUINT uiAvgBlkFullness); FINLINE void updateTransInfo( FLMUINT64 ui64LowTransID, FLMUINT64 ui64HighTransID ) { if (m_ui64LowTransId > ui64LowTransID) { m_ui64LowTransId = ui64LowTransID; } if (!m_bMostCurrent) { m_bMostCurrent = (ui64HighTransID == FLM_MAX_UINT64) ? TRUE : FALSE; } } FINLINE FLMUINT getBlkEntryCount( FLMBYTE * pBlk ) { return ((F_BTREE_BLK_HDR *)pBlk)->ui16NumKeys; } FINLINE FLMUINT getBlkAvailSpace( FLMBYTE * pBlk ) { return ((F_BLK_HDR *)pBlk)->ui16BlkBytesAvail; } FLMUINT getEntryKeyLength( FLMBYTE * pucEntry, FLMUINT uiBlockType, const FLMBYTE ** ppucKeyRV); FLMUINT getEntrySize( FLMBYTE * pBlk, FLMUINT uiOffset, FLMBYTE ** ppucEntry = NULL); RCODE calcNewEntrySize( FLMUINT uiKeyLen, FLMUINT uiDataLen, FLMUINT * puiEntrySize, FLMBOOL * pbHaveRoom, FLMBOOL * pbDefragBlk); RCODE extractEntryData( FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMBYTE * pucBuffer, FLMUINT uiBufSiz, FLMUINT * puiDataLen); RCODE updateEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, F_ELM_UPD_ACTION eAction, FLMBOOL bTruncate = TRUE); RCODE insertEntry( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, F_ELM_UPD_ACTION * peAction); RCODE storeEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT uiOADataLen, FLMUINT uiChildBlkAddr, FLMUINT uiCounts, FLMUINT uiEntrySize, FLMBOOL * pbLastEntry); RCODE removeEntry( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, FLMBOOL * pbMoreToRemove, F_ELM_UPD_ACTION * peAction); RCODE remove( FLMBOOL bDeleteDOBlocks); RCODE removeRange( FLMUINT uiStartElm, FLMUINT uiEndElm, FLMBOOL bDeleteDOBlocks); RCODE findEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMUINT uiMatch, FLMUINT * puiPosition = NULL, FLMUINT32 * pui32BlkAddr = NULL, FLMUINT * puiOffsetIndex = NULL); RCODE findInBlock( const FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMUINT uiMatch, FLMUINT * uiPosition, FLMUINT32 * ui32BlkAddr, FLMUINT * uiOffsetIndex); RCODE scanBlock( F_BTSK * pStack, FLMUINT uiMatch); RCODE compareKeys( const FLMBYTE * pucKey1, FLMUINT uiKeyLen1, const FLMBYTE * pucKey2, FLMUINT uiKeyLen2, FLMINT * piCompare); FINLINE RCODE compareBlkKeys( const FLMBYTE * pucBlockKey, FLMUINT uiBlockKeyLen, const FLMBYTE * pucTargetKey, FLMUINT uiTargetKeyLen, FLMINT * piCompare) { flmAssert( uiBlockKeyLen); if( !m_pCompare && uiBlockKeyLen == uiTargetKeyLen) { *piCompare = f_memcmp( pucBlockKey, pucTargetKey, uiBlockKeyLen); return( NE_SFLM_OK); } return( compareKeys( pucBlockKey, uiBlockKeyLen, pucTargetKey, uiTargetKeyLen, piCompare)); } RCODE positionToEntry( FLMUINT uiPosition); RCODE searchBlock( F_BTREE_BLK_HDR * pBlkHdr, FLMUINT * puiPrevCounts, FLMUINT uiPosition, FLMUINT * puiOffset); RCODE defragmentBlock( F_CachedBlock ** ppSCache); RCODE advanceToNextElement( FLMBOOL bAdvanceStack); RCODE backupToPrevElement( FLMBOOL bBackupStack); RCODE replaceEntry( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, F_ELM_UPD_ACTION * peAction, FLMBOOL bTruncate = TRUE); RCODE replaceOldEntry( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT uiOADataLen, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, F_ELM_UPD_ACTION * peAction, FLMBOOL bTruncate = TRUE); RCODE replaceByInsert( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, const FLMBYTE * pucDataValue, FLMUINT uiDataLen, FLMUINT uiOADataLen, FLMUINT uiFlags, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, F_ELM_UPD_ACTION * peAction); RCODE replace( FLMBYTE * pucEntry, FLMUINT uiEntrySize, FLMBOOL * pbLastEntry); RCODE buildAndStoreEntry( FLMUINT uiBlkType, FLMUINT uiFlags, const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucData, FLMUINT uiDataLen, FLMUINT uiOADataLen, FLMUINT uiChildBlkAddr, FLMUINT uiCounts, FLMBYTE * pucBuffer, FLMUINT uiBufferSize, FLMUINT * puiEntrySize); RCODE moveEntriesToPrevBlk( FLMUINT uiNewEntrySize, F_CachedBlock ** ppPrevSCache, FLMBOOL * pbEntriesWereMoved); RCODE moveEntriesToNextBlk( FLMUINT uiEntrySize, FLMBOOL * pbEntriesWereMoved); RCODE splitBlock( const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT uiOADataLen, FLMUINT uiChildBlkAddr, FLMUINT uiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, FLMBOOL * pbBlockSplit); RCODE createNewLevel( void); RCODE storeDataOnlyBlocks( const FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMBOOL bSaveKey, const FLMBYTE * pucData, FLMUINT uiDataLen); RCODE replaceDataOnlyBlocks( const FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMBOOL bSaveKey, const FLMBYTE * pucData, FLMUINT uiDataLen, FLMBOOL bLast, FLMBOOL bTruncate = TRUE); RCODE moveToPrev( FLMUINT uiStart, FLMUINT uiFinish, F_CachedBlock ** ppPrevSCache); RCODE moveToNext( FLMUINT uiStart, FLMUINT uiFinish, F_CachedBlock ** ppNextSCache); RCODE updateParentCounts( F_CachedBlock * pChildSCache, F_CachedBlock ** ppParentSCache, FLMUINT uiParentElm); FLMUINT countKeys( FLMBYTE * pBlk); FLMUINT countRangeOfKeys( F_BTSK * pFromStack, FLMUINT uiFromOffset, FLMUINT uiUntilOffset); RCODE moveStackToPrev( F_CachedBlock * pPrevSCache); RCODE moveStackToNext( F_CachedBlock * pSCache, FLMBOOL bReleaseCurrent = TRUE); RCODE calcOptimalDataLength( FLMUINT uiKeyLen, FLMUINT uiDataLen, FLMUINT uiBytesAvail, FLMUINT * puiNewDataLen); // Performs an integrity check on a chain of data-only blocks RCODE verifyDOBlkChain( FLMUINT uiDOAddr, FLMUINT uiDataLength, BTREE_ERR_STRUCT * localErrStruct); // Performs a check to verify that the counts in the DB match. RCODE verifyCounts( BTREE_ERR_STRUCT * pErrStruct); void releaseBlocks( FLMBOOL bResetStack); void releaseBtree( void); RCODE saveReplaceInfo( const FLMBYTE * pucKey, FLMUINT uiKeyLen); RCODE restoreReplaceInfo( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts); FINLINE RCODE setReturnKey( FLMBYTE * pucEntry, FLMUINT uiBlockType, FLMBYTE * pucKey, FLMUINT * puiKeyLen, FLMUINT uiKeyBufSize); RCODE setupReadState( F_BLK_HDR * pBlkHdr, FLMBYTE * pucEntry); RCODE removeRemainingEntries( const FLMBYTE * pucKey, FLMUINT uiKeyLen); RCODE deleteEmptyBlock( void); RCODE removeDOBlocks( FLMUINT32 ui32OrigDOAddr); RCODE replaceMultiples( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, const FLMBYTE * pucDataValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, F_ELM_UPD_ACTION * peAction); RCODE replaceMultiNoTruncate( const FLMBYTE ** ppucKey, FLMUINT * puiKeyLen, const FLMBYTE * pucDataValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT * puiChildBlkAddr, FLMUINT * puiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, F_ELM_UPD_ACTION * peAction); FINLINE RCODE getNextBlock( F_CachedBlock ** ppSCache); FINLINE RCODE getPrevBlock( F_CachedBlock ** ppSCache); FLMBOOL checkContinuedEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, FLMBOOL * pbLastElement, FLMBYTE * pucEntry, FLMUINT uiBlkType); RCODE updateCounts( void); RCODE storePartialEntry( const FLMBYTE * pucKey, FLMUINT uiKeyLen, const FLMBYTE * pucValue, FLMUINT uiLen, FLMUINT uiFlags, FLMUINT uiChildBlkAddr, FLMUINT uiCounts, const FLMBYTE ** ppucRemainingValue, FLMUINT * puiRemainingLen, FLMBOOL bNewBlock = FALSE); RCODE mergeBlocks( FLMBOOL bLastEntry, FLMBOOL * pbMergedWithPrev, FLMBOOL * pbMergedWithNext, F_ELM_UPD_ACTION * peAction); RCODE merge( F_CachedBlock ** ppFromSCache, F_CachedBlock ** ppToSCache); RCODE checkDownLinks( void); RCODE verifyChildLinks( F_CachedBlock * pParentSCache); RCODE combineEntries( F_BTREE_BLK_HDR * pSrcBlkHdr, FLMUINT uiSrcOffset, F_BTREE_BLK_HDR * pDstBlkHdr, FLMUINT uiDstOffset, FLMBOOL * pbEntriesCombined, FLMUINT * puiEntrySize); RCODE moveBtreeBlock( FLMUINT32 ui32FromBlkAddr, FLMUINT32 ui32ToBlkAddr); RCODE moveDOBlock( FLMUINT32 ui32FromBlkAddr, FLMUINT32 ui32ToBlkAddr); // Member variables FLMBOOL m_bCounts; // BT_NON_LEAF_COUNTS FLMBOOL m_bData; // BT_LEAF_DATA FLMBOOL m_bSetupForRead; FLMBOOL m_bSetupForWrite; FLMBOOL m_bSetupForReplace; FLMBOOL m_bOpened; FLMBOOL m_bMostCurrent; FLMBOOL m_bDataOnlyBlock; FLMBOOL m_bOrigInDOBlocks; FLMBOOL m_bFirstRead; FLMBOOL m_bStackSetup; LFILE * m_pLFile; F_Db * m_pDb; FLMBOOL m_bTempDb; F_BTSK * m_pStack; // Used for traversing the B-Tree FLMBYTE * m_pucTempBlk; FLMBYTE * m_pucTempDefragBlk; BTREE_REPLACE_STRUCT * m_pReplaceInfo; BTREE_REPLACE_STRUCT * m_pReplaceStruct; const FLMBYTE * m_pucDataPtr; F_CachedBlock * m_pSCache; F_BTREE_BLK_HDR * m_pBlkHdr; FLMBYTE * m_pucBuffer; // Buffer used during moves FLMUINT m_uiBufferSize; // Size of the buffer FLMUINT m_uiBlockSize; FLMUINT m_uiDefragThreshold; FLMUINT m_uiOverflowThreshold; FLMUINT m_uiStackLevels; FLMUINT m_uiRootLevel; FLMUINT m_uiReplaceLevels; FLMUINT m_uiBlkChangeCnt; FLMUINT m_uiDataLength; FLMUINT m_uiPrimaryDataLen; FLMUINT m_uiOADataLength; FLMUINT m_uiDataRemaining; FLMUINT m_uiOADataRemaining; FLMUINT m_uiPrimaryOffset; // Offset into primary block FLMUINT m_uiCurOffset; // Offset into current block FLMUINT m_uiSearchLevel; FLMUINT m_uiOffsetAtStart; // Offset into the current // element at the beginning of // the entry. An element may // span multiple entries. FLMUINT32 m_ui32PrimaryBlkAddr;// Primary block address FLMUINT32 m_ui32DOBlkAddr; // Address of first DO Block FLMUINT32 m_ui32CurBlkAddr; // Current block being read FLMUINT64 m_ui64LowTransId; FLMUINT64 m_ui64LastBlkTransId; FLMUINT64 m_ui64PrimaryBlkTransId; FLMUINT64 m_ui64CurrTransID; F_BTSK m_Stack[ BH_MAX_LEVELS]; // The m_pNext field is only used by the btPool object. F_Btree * m_pNext; IF_ResultSetCompare * m_pCompare; friend class F_BtPool; friend class F_Db; friend class F_Rfl; }; RCODE btFreeBlockChain( F_Db * pDb, LFILE * pLFile, FLMUINT uiStartAddr, FLMUINT uiBlocksToFree, FLMUINT * puiBlocksFreed, FLMUINT * puiEndAddr, IF_DeleteStatus * ifpDeleteStatus); #endif