Added support for large field values (up to 4 GB), async and direct I/O on Linux and Solaris, and performed major code cleanup.

git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@213 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
ahodgkinson
2006-03-28 19:25:14 +00:00
parent 0023b51ad8
commit 3eaf791406
197 changed files with 53521 additions and 82897 deletions

View File

@@ -26,15 +26,14 @@
extern FLMBYTE SENLenArray[];
/***************************************************************************
Desc: Compute the number of blocks between two stack positions.
These values may be estimated or actual.
*****************************************************************************/
RCODE FSComputeRecordBlocks( // Returns WERR_OK or FERR_BTREE_ERROR
BTSK_p pFromStack, // [in] - be carefull not to change
BTSK * pFromStack, // [in] - be carefull not to change
// anything in this structure.
BTSK_p pUntilStack, // [in]
BTSK * pUntilStack, // [in]
FLMUINT * puiLeafBlocksBetween, // [out] blocks between the stacks
FLMUINT * puiTotalRecords, // [out]
FLMBOOL * pbTotalsEstimated)// [out] Set to TRUE when estimating.
@@ -80,6 +79,7 @@ RCODE FSComputeRecordBlocks( // Returns WERR_OK or FERR_BTREE_ERROR
}
// Get (or estimate) the number of elements in the parent block.
*pbTotalsEstimated = TRUE;
if( RC_BAD( rc = FSBlockCounts( pFromStack, BH_OVHD,
pFromStack->uiBlkEnd, &uiEstRecordCount, NULL, NULL)))
@@ -179,27 +179,28 @@ Notes: There are two versions for this routine in the way of estimating
the LFILE.
*****************************************************************************/
RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
BTSK_p pFromStack, // [in] - be carefull not to change
// anything in this structure.
BTSK_p pUntilStack, // [in]
FLMUINT * puiLeafBlocksBetween, // [out] blocks between the stacks
FLMUINT * puiTotalKeys, // [out] total number of keys inclusive
FLMUINT * puiTotalRefs, // [out] total references inclusive
FLMBOOL * pbTotalsEstimated)// [out] Set to TRUE when estimating.
BTSK * pFromStack, // [in] - be carefull not to change
// anything in this structure.
BTSK * pUntilStack, // [in]
FLMUINT * puiLeafBlocksBetween, // [out] blocks between the stacks
FLMUINT * puiTotalKeys, // [out] total number of keys inclusive
FLMUINT * puiTotalRefs, // [out] total references inclusive
FLMBOOL * pbTotalsEstimated) // [out] Set to TRUE when estimating.
{
RCODE rc = FERR_OK;
FLMUINT uiTotalKeys,
uiTempKeyCount,
uiEstKeyCount;
FLMUINT uiTotalRefs,
uiTempRefCount,
uiEstRefCount;
FLMUINT uiTotalBlocksBetween,
uiEstBlocksBetween;
FLMUINT uiTotalKeys;
FLMUINT uiTempKeyCount;
FLMUINT uiEstKeyCount;
FLMUINT uiTotalRefs;
FLMUINT uiTempRefCount;
FLMUINT uiEstRefCount;
FLMUINT uiTotalBlocksBetween;
FLMUINT uiEstBlocksBetween;
FLMBYTE * pBlk;
uiTotalBlocksBetween = uiTotalKeys = uiTotalRefs = 0;
*pbTotalsEstimated = FALSE;
// Are the from and until positions in the same block?
if( pFromStack->uiBlkAddr == pUntilStack->uiBlkAddr)
@@ -231,13 +232,12 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
goto Exit;
}
/*
Estimate number of keys/refs in the leaf block.
Estimate using just the left block. The right block may be a right-most
block so will scew the results.
*/
// Estimate number of keys/refs in the leaf block.
// Estimate using just the left block. The right block may be a right-most
// block so will skew the results.
//
// Code for non-leaf child counts is easy - no need to estimate.
if( (pFromStack-1)->uiBlkType != BHT_NON_LEAF_COUNTS)
{
*pbTotalsEstimated = TRUE;
@@ -251,24 +251,29 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
for(;;)
{
FLMUINT uiElementCount, // These are non-leaf elements.
uiTempElementCount,
uiEstElementCount,
uiRefCount;
FLMUINT uiElementCount;
FLMUINT uiTempElementCount;
FLMUINT uiEstElementCount;
FLMUINT uiRefCount;
FLMBYTE * pCounts;
// Go up a b-tree level and check out how far apart the elements are.
pFromStack--;
pUntilStack--;
// Share the same block?
if( pFromStack->uiBlkAddr == pUntilStack->uiBlkAddr)
{
if( RC_BAD( rc = FSBlockCounts( pFromStack, pFromStack->uiCurElm,
pUntilStack->uiCurElm, NULL, &uiElementCount, &uiRefCount)))
{
goto Exit;
}
// Don't count the current element nor the ref counts.
uiElementCount--;
if( pFromStack->uiBlkType == BHT_NON_LEAF_COUNTS)
{
@@ -290,7 +295,7 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
uiTotalKeys += uiEstKeyCount * uiElementCount;
uiTotalRefs += uiEstRefCount * uiElementCount;
}
// DONE !
goto Exit;
}
@@ -298,8 +303,12 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
if( RC_BAD( rc = FSBlockCounts( pFromStack, pFromStack->uiCurElm,
pFromStack->uiBlkEnd, NULL, &uiElementCount, &uiRefCount)))
{
goto Exit;
}
// Don't count the first element.
uiElementCount--;
if( pFromStack->uiBlkType == BHT_NON_LEAF_COUNTS)
@@ -311,12 +320,14 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
if( RC_BAD( rc = FSBlockCounts( pUntilStack, BH_OVHD,
pUntilStack->uiCurElm, NULL, &uiTempElementCount, &uiRefCount)))
{
goto Exit;
}
uiElementCount += uiTempElementCount;
uiTotalBlocksBetween += uiEstBlocksBetween * uiElementCount;
uiTotalKeys += uiEstKeyCount * uiElementCount;
if( pUntilStack->uiBlkType == BHT_NON_LEAF_COUNTS)
{
uiTotalRefs += uiRefCount;
@@ -343,7 +354,9 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
if( RC_BAD( rc = FSBlockCounts( pFromStack, BH_OVHD,
pFromStack->uiBlkEnd, NULL, &uiEstElementCount, NULL)))
{
goto Exit;
}
// Adjust the estimated key/ref count to be the counts from a complete
// (not partial) block starting at this level going to the leaf.
@@ -354,18 +367,22 @@ RCODE FSComputeIndexCounts( // Returns WERR_OK or FERR_BTREE_ERROR
}
Exit:
if( puiLeafBlocksBetween)
{
*puiLeafBlocksBetween = uiTotalBlocksBetween;
}
if( puiTotalKeys)
{
*puiTotalKeys = uiTotalKeys;
}
if( puiTotalRefs)
{
*puiTotalRefs = uiTotalRefs;
}
return( rc);
}
@@ -374,7 +391,7 @@ Desc: Returns the number of first keys (elements with the first flag),
elements and references (for leaf blocks).
*****************************************************************************/
RCODE FSBlockCounts( // Returns WERR_OK currently.
BTSK_p pStack, // [in] - be careful not to change
BTSK * pStack, // [in] - be careful not to change
// anything in this structure.
FLMUINT uiFirstElement, // [in] start at this element
FLMUINT uiLastElement, // [in] Do not include reference counts
@@ -392,7 +409,6 @@ RCODE FSBlockCounts( // Returns WERR_OK currently.
FLMBOOL bHaveNonleafElementCounts;
BTSK tempStack;
// Debug checks.
flmAssert( uiFirstElement <= uiLastElement);
flmAssert( uiLastElement <= pStack->uiBlkEnd);
@@ -409,18 +425,8 @@ RCODE FSBlockCounts( // Returns WERR_OK currently.
(tempStack.uiBlkType == BHT_NON_LEAF_COUNTS) ? TRUE : FALSE;
// Position to uiFirstElement (it could be bogus).
// The while() code is safer but lots slower.
#if 0
while( tempStack.uiCurElm < uiFirstElement)
{
if( FSBlkNextElm( &tempStack) == FERR_BT_END_OF_DATA)
{
break;
}
}
#else
tempStack.uiCurElm = uiFirstElement;
#endif
// Loop gathering the statistics.
@@ -435,6 +441,7 @@ RCODE FSBlockCounts( // Returns WERR_OK currently.
uiFirstKeyCount++;
}
}
if( puiRefCount)
{
if( !bHaveNonleafElementCounts)
@@ -449,21 +456,28 @@ RCODE FSBlockCounts( // Returns WERR_OK currently.
}
// Next element.
if( FSBlkNextElm( &tempStack) == FERR_BT_END_OF_DATA)
{
break;
}
}
if( puiFirstKeyCount)
{
*puiFirstKeyCount = uiFirstKeyCount;
}
if( puiElementCount)
{
*puiElementCount = uiElementCount;
}
if( puiRefCount)
{
*puiRefCount = uiRefCount;
}
return( rc);
}
@@ -471,8 +485,8 @@ RCODE FSBlockCounts( // Returns WERR_OK currently.
Desc: Returns the number of references at the current b-tree element.
Leaf level blocks must be passed in and the block must be usable.
*****************************************************************************/
FLMUINT FSElementRefCount( // Returns the number of references
BTSK_p pStack) // [in]
FLMUINT FSElementRefCount( // Returns the number of references
BTSK * pStack) // [in]
{
FLMUINT uiRefCount;
FLMBYTE * pCurRef; // Points to current reference
@@ -480,14 +494,18 @@ FLMUINT FSElementRefCount( // Returns the number of references
FLMUINT uiRefSize; // Size of the reference set
DIN_STATE tempState;
// Check block type.
// Check block type
if( pStack->uiBlkType != BHT_LEAF)
{
uiRefCount = 0;
goto Exit;
}
uiRefCount = 1;
// Point to the start of the current reference skipping over domain info.
pCurRef = pCurElm = CURRENT_ELM( pStack );
(void) FSGetDomain( &pCurRef, pStack->uiElmOvhd );
uiRefSize = (FLMUINT)(BBE_GET_RL(pCurElm) -
@@ -496,13 +514,14 @@ FLMUINT FSElementRefCount( // Returns the number of references
RESET_DINSTATE( tempState );
// Read the first reference - there must be at least one reference.
(void) DINNextVal( pCurRef, &tempState );
while( tempState.uiOffset < uiRefSize )
{
FLMUINT uiNextLength;
/* Get the current byte to see what kind of item it is */
// Get the current byte to see what kind of item it is
if( (uiNextLength = SENValLen( pCurRef + tempState.uiOffset)) == 0)
{
@@ -514,10 +533,11 @@ FLMUINT FSElementRefCount( // Returns the number of references
uiRefCount++;
}
}
Exit:
return uiRefCount;
}
return (uiRefCount);
}
/***************************************************************************
Desc: Read in the child block and set the counts in the input element.
@@ -540,23 +560,30 @@ RCODE FSUpdateAdjacentBlkCounts(
{
goto Exit;
}
pStack = pBaseStack;
pStack--;
if( RC_BAD( rc = FSBtNextElm( pDb, pLFile, pStack)))
{
if( rc == FERR_BT_END_OF_DATA)
{
rc = RC_SET( FERR_BTREE_ERROR);
}
goto Exit;
}
pStack = pBaseStack;
if( RC_BAD( rc = FSUpdateBlkCounts( pDb, pStack, uiNextBlkCount)))
{
goto Exit;
}
pStack = pBaseStack;
pStack--;
if( RC_BAD( rc = FSBtPrevElm( pDb, pLFile, pStack)))
{
if( rc == FERR_BT_END_OF_DATA)
@@ -567,6 +594,7 @@ RCODE FSUpdateAdjacentBlkCounts(
}
Exit:
return( rc);
}
@@ -602,16 +630,20 @@ RCODE FSUpdateBlkCounts(
bFirstTime = FALSE;
// If the delta is zero there is nothing to do.
if( !iDelta)
{
break;
}
}
// Log the block.
if( RC_BAD( rc = FSLogPhysBlk( pDb, pStack)))
{
goto Exit;
}
// The block should be able to be used.
uiCount = uiCount - iDelta;
@@ -619,6 +651,7 @@ RCODE FSUpdateBlkCounts(
}
Exit:
return( rc);
}
@@ -630,8 +663,8 @@ Desc: For a positioning index update the count in all the parent elements.
*****************************************************************************/
RCODE FSChangeCount(
FDB * pDb,
BTSK_p pStack,
FLMBOOL bAddReference) // If FALSE decrement the referernce
BTSK * pStack,
FLMBOOL bAddReference) // If FALSE, decrement the reference
{
RCODE rc = FERR_OK;
FLMBYTE * pCurElm;
@@ -640,17 +673,21 @@ RCODE FSChangeCount(
while( !BH_IS_ROOT_BLK( pStack->pBlk))
{
// Go to the parent and increment/decrement the counts.
pStack--;
// Log the block.
if( RC_BAD( rc = FSLogPhysBlk( pDb, pStack)))
{
goto Exit;
}
// The block should be able to be used.
pCurElm = pStack->pBlk + pStack->uiCurElm;
uiCount = FB2UD( &pCurElm[ BNE_CHILD_COUNT]);
if( bAddReference)
{
uiCount++;
@@ -658,14 +695,18 @@ RCODE FSChangeCount(
else
{
// Don't allow value to be less than zero.
if( uiCount)
{
uiCount--;
}
}
UD2FBA( uiCount, &pCurElm[ BNE_CHILD_COUNT]);
}
Exit:
return( rc);
}
@@ -686,6 +727,7 @@ RCODE FSChangeBlkCounts(
while( !BH_IS_ROOT_BLK( pStack->pBlk))
{
// Go to the parent and increment/decrement the counts.
pStack--;
pCurElm = pStack->pBlk + pStack->uiCurElm;
@@ -695,16 +737,19 @@ RCODE FSChangeBlkCounts(
? 0 : (FLMUINT) (uiCount + iDelta);
// Log the block.
if( RC_BAD( rc = FSLogPhysBlk( pDb, pStack)))
{
goto Exit;
}
// The block should be able to be used.
UD2FBA( uiCount, &pCurElm[ BNE_CHILD_COUNT]);
}
Exit:
return( rc);
}
@@ -724,7 +769,9 @@ RCODE FSGetBtreeRefPosition(
FLMUINT uiRefCount;
F_UNREFERENCED_PARM( pDb);
// Compute the reference counts before all the current elements up the tree.
if( RC_BAD( rc = FSBlockCounts( pStack, BH_OVHD, pStack->uiCurElm,
NULL, NULL, &uiTotalCount)))
{
@@ -732,6 +779,7 @@ RCODE FSGetBtreeRefPosition(
}
// This must be a one-based number (first reference is 1).
if( !pDinState->uiOffset)
{
uiTotalCount++;
@@ -753,6 +801,7 @@ RCODE FSGetBtreeRefPosition(
(pCurRef - BBE_REC_PTR(pCurElm)));
// Read the first reference - there must be at least one reference.
(void) DINNextVal( pCurRef, &tempState );
while( tempState.uiOffset < pDinState->uiOffset
@@ -760,7 +809,7 @@ RCODE FSGetBtreeRefPosition(
{
FLMUINT uiNextLength;
/* Get the current byte to see what kind of item it is */
// Get the current byte to see what kind of item it is
if( (uiNextLength = SENValLen( pCurRef + tempState.uiOffset)) == 0)
{
@@ -772,17 +821,21 @@ RCODE FSGetBtreeRefPosition(
uiRefCount++;
}
}
if( tempState.uiOffset == pDinState->uiOffset && pDinState->uiOnes)
{
uiRefCount += pDinState->uiOnes;
}
uiTotalCount += uiRefCount;
}
// Go up the stack and keep the count up.
while( !BH_IS_ROOT_BLK( pStack->pBlk))
{
// Go to the parent and increment/decrement the counts.
pStack--;
if( RC_BAD( rc = FSBlockCounts( pStack, BH_OVHD, pStack->uiCurElm,
@@ -790,10 +843,12 @@ RCODE FSGetBtreeRefPosition(
{
goto Exit;
}
uiTotalCount += uiRefCount;
}
Exit:
*puiRefPosition = uiTotalCount;
return( rc);
}
@@ -813,8 +868,8 @@ RCODE FSPositionSearch(
DIN_STATE * pDinState)
{
RCODE rc;
BTSK_p pStack = *ppStack;
FLMBYTE * pKeyBuf = pStack->pKeyBuf;// Used to set key buf on each btsk.
BTSK * pStack = *ppStack;
FLMBYTE * pKeyBuf = pStack->pKeyBuf;
FLMUINT uiBlkAddr;
LFILE TmpLFile;
@@ -841,23 +896,29 @@ RCODE FSPositionSearch(
{
goto Exit;
}
if( !pStack->uiLevel)
{
break;
}
uiBlkAddr = FSChildBlkAddr( pStack );
pStack++;
pStack->pKeyBuf = pKeyBuf;
if( RC_BAD(rc = FSGetBlock( pDb, pLFile, uiBlkAddr, pStack )))
{
goto Exit;
}
}
*ppStack = pStack; // Set the stack return value.
*ppStack = pStack;
Exit:
return( rc);
}
/***************************************************************************
Desc: Position to the element given a position value relative to the block.
*****************************************************************************/
@@ -920,6 +981,7 @@ RCODE FSPositionScan(
else
{
// Copy the key into the key buffer.
if( uiPrevKeyCnt > uiPrevPrevKeyCnt)
{
uiBytesToMove = uiPrevKeyCnt - uiPrevPrevKeyCnt;
@@ -928,6 +990,7 @@ RCODE FSPositionScan(
pPrevKey = pCurElm + uiElmOvhd;
uiTotalElmLen += BBE_GET_RL( pCurElm);
}
if( uiRefCount >= uiRelativePosition)
{
pStack->uiKeyLen = uiElmKeyLen + uiPrevKeyCnt;
@@ -937,23 +1000,28 @@ RCODE FSPositionScan(
if( uiBlkType == BHT_LEAF)
{
// Copy the remaining bytes of the key. pPrevKey is current key.
if( uiElmKeyLen)
{
f_memcpy( &pKeyBuf[ uiPrevKeyCnt], pPrevKey, uiElmKeyLen);
}
if( RC_BAD( rc = FSPositionToRef( pStack, uiRelativePosition,
puiRecordId, puiDomain, pDinState)))
{
goto Exit;
}
uiRelativePosition = 0;
}
break;
}
uiPrevPrevKeyCnt = uiPrevKeyCnt;
uiRelativePosition -= uiRefCount;
pStack->uiCurElm += uiTotalElmLen;
if( pStack->uiCurElm >= pStack->uiBlkEnd)
{
uiRelativePosition = 0;
@@ -963,7 +1031,9 @@ RCODE FSPositionScan(
}
*puiRelativePosInElement = uiRelativePosition;
Exit:
return( rc);
}
@@ -988,7 +1058,7 @@ RCODE FSPositionToRef(
{
uiRecordId = FSRefFirst( pStack, pDinState, puiDomain);
}
else // if( uiRefCount > uiRelativePosition)
else
{
// Find the position within the element.
@@ -998,6 +1068,7 @@ RCODE FSPositionToRef(
DIN_STATE tempState;
// Point to the start of the current reference skipping over domain info.
pCurRef = pCurElm = CURRENT_ELM( pStack );
*puiDomain = FSGetDomain( &pCurRef, pStack->uiElmOvhd) + 1;
uiRefSize = (FLMUINT)(BBE_GET_RL(pCurElm) -
@@ -1011,16 +1082,16 @@ RCODE FSPositionToRef(
uiRecordId -= DINNextVal( pCurRef, pDinState);
uiRelativePosition--;
}
flmAssert( pDinState->uiOffset < uiRefSize);
// Get the last value without moving pDinState.
tempState.uiOffset = pDinState->uiOffset;
tempState.uiOnes = pDinState->uiOnes;
tempState.uiOnes = pDinState->uiOnes;
uiRecordId -= DINNextVal( pCurRef, &tempState );
}
*puiRecordId = uiRecordId;
//Exit:
return( rc);
}