From d7b545bbcb2225a33e8c8c5192ab11416a855999 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 13 Oct 2014 18:03:27 +0000 Subject: [PATCH] Further work on balance_nonroot(). FossilOrigin-Name: 6594f9b420e2fa642737722ff8521f756ecef227 --- manifest | 12 +-- manifest.uuid | 2 +- src/btree.c | 265 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 180 insertions(+), 99 deletions(-) diff --git a/manifest b/manifest index 7e782aa82c..9f25f390d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Attempt\sto\sfurther\sreduce\smemcpy()\sin\sbalance_nonroot(). -D 2014-10-11T20:00:24.552 +C Further\swork\son\sbalance_nonroot(). +D 2014-10-13T18:03:27.743 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,7 +172,7 @@ F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5 -F src/btree.c d5f4f74e309f79ace4b4025c433874ead635bed2 +F src/btree.c 63211ca1d4ae867eede39a37901aec4746d904a7 F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btreeInt.h 1bd7957161a1346a914f1f09231610e777a8e58d F src/build.c bde83dd5cf812e310a7e5ad2846790a14745bef4 @@ -1200,7 +1200,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 29304499ea4b72dbb6701e10cc19b5d41f7e5ac9 -R 3235ac37769ff059d7c714947e8a11dd +P fec849dcca3aead2bc2d4ecffeda750684d32fb0 +R 79e5b5564c934fc68257d82dc897cefd U dan -Z 17fdfd7faf788bbb79d2ec9941c17025 +Z ae5b74eee28666050af6baaa639de56c diff --git a/manifest.uuid b/manifest.uuid index 006b3c0008..fcba485229 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fec849dcca3aead2bc2d4ecffeda750684d32fb0 \ No newline at end of file +6594f9b420e2fa642737722ff8521f756ecef227 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 13ec912748..7c9a7228de 100644 --- a/src/btree.c +++ b/src/btree.c @@ -6009,7 +6009,7 @@ static void rebuildPage( assert( szCell[i]==cellSizePtr(pPg, pCell) ); } - pPg->nFree = (pData - pCellptr); + /* The pPg->nFree field is now set incorrectly. The caller will fix it. */ pPg->nCell = nCell; pPg->nOverflow = 0; @@ -6019,6 +6019,106 @@ static void rebuildPage( aData[hdr+7] = 0x00; } +static u8 *pageFindSlot(MemPage *pPg, int nByte){ + const int hdr = pPg->hdrOffset; + u8 * const aData = pPg->aData; + int iAddr; + int pc; + int usableSize = pPg->pBt->usableSize; + + for(iAddr=hdr+1; (pc = get2byte(&aData[iAddr]))>0; iAddr=pc){ + int size; /* Size of the free slot */ + if( pc>usableSize-4 || pc=nByte ){ + int x = size - nByte; + testcase( x==4 ); + testcase( x==3 ); + if( x<4 ){ + if( aData[hdr+7]>=60 ) return 0; + /* Remove the slot from the free-list. Update the number of + ** fragmented bytes within the page. */ + memcpy(&aData[iAddr], &aData[pc], 2); + aData[hdr+7] += (u8)x; + }else if( size+pc > usableSize ){ + return 0; + }else{ + /* The slot remains on the free-list. Reduce its size to account + ** for the portion used by the new allocation. */ + put2byte(&aData[pc+2], x); + } + return &aData[pc + x]; + } + } + + return 0; +} + +static int pageInsertArray( + MemPage *pPg, + u8 *pBegin, + u8 **ppData, + u8 *pCellptr, + int nCell, + u8 **apCell, /* Array of cells */ + u16 *szCell /* Array of cell sizes */ +){ + int i; + u8 *aData = pPg->aData; + u8 *pData = *ppData; + for(i=0; iaData; + u8 * const pEnd = &aData[pPg->pBt->usableSize]; + int nRet = 0; + int i; + u8 *pFree = 0; + int szFree = 0; + + for(i=0; iaData && pCellnFree field is invalid when this function returns. It is the +** responsibility of the caller to set it correctly. +*/ static void editPage( MemPage *pPg, /* Edit this page */ int iOld, /* Index of first cell currently on page */ @@ -6027,113 +6127,93 @@ static void editPage( u8 **apCell, /* Array of cells */ u16 *szCell /* Array of cell sizes */ ){ - - if( 1 ){ - u8 * const aData = pPg->aData; - const int hdr = pPg->hdrOffset; - u8 *pBegin = &pPg->aCellIdx[nNew * 2]; - int nFree = pPg->nFree; /* Free bytes on pPg */ - int nCell = pPg->nCell; /* Cells stored on pPg */ - u8 *pData; - u8 *pCellptr; - int i; - int iOldEnd = iOld + pPg->nCell + pPg->nOverflow; + u8 * const aData = pPg->aData; + const int hdr = pPg->hdrOffset; + u8 *pBegin = &pPg->aCellIdx[nNew * 2]; + int nCell = pPg->nCell; /* Cells stored on pPg */ + u8 *pData; + u8 *pCellptr; + int i; + int iOldEnd = iOld + pPg->nCell + pPg->nOverflow; + int iNewEnd = iNew + nNew; #ifdef SQLITE_DEBUG - u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); - memcpy(pTmp, aData, pPg->pBt->usableSize); + u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); + memcpy(pTmp, aData, pPg->pBt->usableSize); #endif - /* Remove cells from the start and end of the page */ - if( iOldaData && apCell[i]<&aData[pPg->pBt->usableSize] ){ - freeSpace(pPg, apCell[i] - aData, szCell[i]); - nFree += szCell[i] + 2; - nShift++; - } - } - nCell -= nShift; - memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2); - } - for(i=iNew+nNew; iaData && apCell[i]<&aData[pPg->pBt->usableSize] ){ - freeSpace(pPg, apCell[i] - aData, szCell[i]); - nFree += szCell[i] + 2; - nCell--; - } - } - pData = &aData[get2byte(&aData[hdr+5])]; - if( pDataaCellIdx, &pPg->aCellIdx[nShift*2], nCell*2); + nCell -= nShift; + } + if( iNewEnd < iOldEnd ){ + nCell -= pageFreeArray( + pPg, iOldEnd-iNewEnd, &apCell[iNewEnd], &szCell[iNewEnd] + ); + } - /* Add cells to the start of the page */ - if( iNewaCellIdx; - memmove(&pCellptr[(iOld-iNew)*2], pCellptr, nCell*2); - for(i=iNew; iaCellIdx; + memmove(&pCellptr[nAdd*2], pCellptr, nCell*2); + if( pageInsertArray( + pPg, pBegin, &pData, pCellptr, + nAdd, &apCell[iNew], &szCell[iNew] + ) ) goto editpage_fail; + nCell += nAdd; + } + + /* Add any overflow cells */ + for(i=0; inOverflow; i++){ + int iCell = (iOld + pPg->aiOvfl[i]) - iNew; + if( iCell>=0 && iCellaCellIdx[iCell * 2]; + memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); + nCell++; + if( pageInsertArray( + pPg, pBegin, &pData, pCellptr, + 1, &apCell[iCell + iNew], &szCell[iCell + iNew] + ) ) goto editpage_fail; } + } - /* Add any overflow cells */ - for(i=0; inOverflow; i++){ - int iCell = (iOld + pPg->aiOvfl[i]) - iNew; - if( iCell>=0 && iCellaCellIdx[iCell * 2]; - int sz = szCell[iCell+iNew]; - memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); - pData -= sz; - if( pDataaCellIdx[nCell*2]; + if( pageInsertArray( + pPg, pBegin, &pData, pCellptr, + nNew-nCell, &apCell[iNew+nCell], &szCell[iNew+nCell] + ) ) goto editpage_fail; - /* Append cells to the end of the page */ - pCellptr = &pPg->aCellIdx[nCell*2]; - for(i=iNew+nCell; i<(iNew+nNew); i++){ - pData -= szCell[i]; - if( pDatanCell = nNew; + pPg->nOverflow = 0; - pPg->nFree = nFree; - pPg->nCell = nNew; - pPg->nOverflow = 0; - - put2byte(&aData[hdr+3], pPg->nCell); - put2byte(&aData[hdr+5], pData - aData); + put2byte(&aData[hdr+3], pPg->nCell); + put2byte(&aData[hdr+5], pData - aData); #ifdef SQLITE_DEBUG - for(i=0; iaCellIdx[i*2]); - if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ - pCell = &pTmp[pCell - aData]; - } - assert( 0==memcmp(pCell, &aData[iOff], szCell[i+iNew]) ); + for(i=0; iaCellIdx[i*2]); + if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ + pCell = &pTmp[pCell - aData]; } + assert( 0==memcmp(pCell, &aData[iOff], szCell[i+iNew]) ); + } #endif #if 0 - printf("EDIT\n"); +printf("EDIT\n"); #endif - return; - } - + return; editpage_fail: #if 0 printf("REBUILD\n"); @@ -6662,7 +6742,7 @@ static int balance_nonroot( assert( i usableSpace ){ - szNew[k] = subtotal - szCell[i]; + szNew[k] = subtotal - szCell[i] - 2; cntNew[k] = i; if( leafData ){ i--; } subtotal = 0; @@ -7002,6 +7082,7 @@ static int balance_nonroot( editPage(apNew[iPg], iOld, iNew, nNewCell, apCell, szCell); abDone[iPg] = 1; + apNew[iPg]->nFree = usableSpace-szNew[iPg]; assert( apNew[iPg]->nOverflow==0 ); assert( apNew[iPg]->nCell==nNewCell ); }