Further work on balance_nonroot().

FossilOrigin-Name: 6594f9b420e2fa642737722ff8521f756ecef227
This commit is contained in:
dan 2014-10-13 18:03:27 +00:00
parent 09c6840153
commit d7b545bbcb
3 changed files with 180 additions and 99 deletions

View File

@ -1,5 +1,5 @@
C Attempt\sto\sfurther\sreduce\smemcpy()\sin\sbalance_nonroot(). C Further\swork\son\sbalance_nonroot().
D 2014-10-11T20:00:24.552 D 2014-10-13T18:03:27.743
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -172,7 +172,7 @@ F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5 F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
F src/btree.c d5f4f74e309f79ace4b4025c433874ead635bed2 F src/btree.c 63211ca1d4ae867eede39a37901aec4746d904a7
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
F src/btreeInt.h 1bd7957161a1346a914f1f09231610e777a8e58d F src/btreeInt.h 1bd7957161a1346a914f1f09231610e777a8e58d
F src/build.c bde83dd5cf812e310a7e5ad2846790a14745bef4 F src/build.c bde83dd5cf812e310a7e5ad2846790a14745bef4
@ -1200,7 +1200,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 29304499ea4b72dbb6701e10cc19b5d41f7e5ac9 P fec849dcca3aead2bc2d4ecffeda750684d32fb0
R 3235ac37769ff059d7c714947e8a11dd R 79e5b5564c934fc68257d82dc897cefd
U dan U dan
Z 17fdfd7faf788bbb79d2ec9941c17025 Z ae5b74eee28666050af6baaa639de56c

View File

@ -1 +1 @@
fec849dcca3aead2bc2d4ecffeda750684d32fb0 6594f9b420e2fa642737722ff8521f756ecef227

View File

@ -6009,7 +6009,7 @@ static void rebuildPage(
assert( szCell[i]==cellSizePtr(pPg, pCell) ); 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->nCell = nCell;
pPg->nOverflow = 0; pPg->nOverflow = 0;
@ -6019,6 +6019,106 @@ static void rebuildPage(
aData[hdr+7] = 0x00; 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<iAddr+4 ) return 0;
size = get2byte(&aData[pc+2]);
if( size>=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; i<nCell; i++){
int sz = szCell[i];
u8 *pSlot;
if( (pSlot = pageFindSlot(pPg, sz))==0 ){
pData -= sz;
if( pData<pBegin ) return 1;
pSlot = pData;
}
memcpy(pSlot, apCell[i], sz);
put2byte(pCellptr, (pSlot - aData));
pCellptr += 2;
}
*ppData = pData;
return 0;
}
static int pageFreeArray(
MemPage *pPg, /* Page to edit */
int nCell, /* Cells to delete */
u8 **apCell, /* Array of cells */
u16 *szCell /* Array of cell sizes */
){
u8 * const aData = pPg->aData;
u8 * const pEnd = &aData[pPg->pBt->usableSize];
int nRet = 0;
int i;
u8 *pFree = 0;
int szFree = 0;
for(i=0; i<nCell; i++){
u8 *pCell = apCell[i];
if( pCell>aData && pCell<pEnd ){
int sz = szCell[i];
if( pFree!=(pCell + sz) ){
if( pFree ) freeSpace(pPg, pFree - aData, szFree);
pFree = pCell;
szFree = sz;
}else{
pFree = pCell;
szFree += sz;
}
nRet++;
}
}
if( pFree ) freeSpace(pPg, pFree - aData, szFree);
return nRet;
}
/*
** The pPg->nFree field is invalid when this function returns. It is the
** responsibility of the caller to set it correctly.
*/
static void editPage( static void editPage(
MemPage *pPg, /* Edit this page */ MemPage *pPg, /* Edit this page */
int iOld, /* Index of first cell currently on page */ int iOld, /* Index of first cell currently on page */
@ -6027,17 +6127,15 @@ static void editPage(
u8 **apCell, /* Array of cells */ u8 **apCell, /* Array of cells */
u16 *szCell /* Array of cell sizes */ u16 *szCell /* Array of cell sizes */
){ ){
if( 1 ){
u8 * const aData = pPg->aData; u8 * const aData = pPg->aData;
const int hdr = pPg->hdrOffset; const int hdr = pPg->hdrOffset;
u8 *pBegin = &pPg->aCellIdx[nNew * 2]; u8 *pBegin = &pPg->aCellIdx[nNew * 2];
int nFree = pPg->nFree; /* Free bytes on pPg */
int nCell = pPg->nCell; /* Cells stored on pPg */ int nCell = pPg->nCell; /* Cells stored on pPg */
u8 *pData; u8 *pData;
u8 *pCellptr; u8 *pCellptr;
int i; int i;
int iOldEnd = iOld + pPg->nCell + pPg->nOverflow; int iOldEnd = iOld + pPg->nCell + pPg->nOverflow;
int iNewEnd = iNew + nNew;
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
@ -6046,40 +6144,31 @@ static void editPage(
/* Remove cells from the start and end of the page */ /* Remove cells from the start and end of the page */
if( iOld<iNew ){ if( iOld<iNew ){
int nShift = 0; int nShift = pageFreeArray(
for(i=iOld; i<iNew; i++){ pPg, iNew-iOld, &apCell[iOld], &szCell[iOld]
if( apCell[i]>aData && 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); memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
nCell -= nShift;
} }
for(i=iNew+nNew; i<iOldEnd; i++){ if( iNewEnd < iOldEnd ){
if( apCell[i]>aData && apCell[i]<&aData[pPg->pBt->usableSize] ){ nCell -= pageFreeArray(
freeSpace(pPg, apCell[i] - aData, szCell[i]); pPg, iOldEnd-iNewEnd, &apCell[iNewEnd], &szCell[iNewEnd]
nFree += szCell[i] + 2; );
nCell--;
}
} }
pData = &aData[get2byte(&aData[hdr+5])]; pData = &aData[get2byte(&aData[hdr+5])];
if( pData<pBegin ) goto editpage_fail; if( pData<pBegin ) goto editpage_fail;
/* Add cells to the start of the page */ /* Add cells to the start of the page */
if( iNew<iOld ){ if( iNew<iOld ){
int nAdd = iOld-iNew;
pCellptr = pPg->aCellIdx; pCellptr = pPg->aCellIdx;
memmove(&pCellptr[(iOld-iNew)*2], pCellptr, nCell*2); memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
for(i=iNew; i<iOld; i++){ if( pageInsertArray(
pData -= szCell[i]; pPg, pBegin, &pData, pCellptr,
if( pData<pBegin ) goto editpage_fail; nAdd, &apCell[iNew], &szCell[iNew]
memcpy(pData, apCell[i], szCell[i]); ) ) goto editpage_fail;
put2byte(pCellptr, (pData - aData)); nCell += nAdd;
pCellptr += 2;
nFree -= (szCell[i] + 2);
nCell++;
}
} }
/* Add any overflow cells */ /* Add any overflow cells */
@ -6087,29 +6176,22 @@ static void editPage(
int iCell = (iOld + pPg->aiOvfl[i]) - iNew; int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){ if( iCell>=0 && iCell<nNew ){
u8 *pCellptr = &pPg->aCellIdx[iCell * 2]; u8 *pCellptr = &pPg->aCellIdx[iCell * 2];
int sz = szCell[iCell+iNew];
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
pData -= sz;
if( pData<pBegin ) goto editpage_fail;
memcpy(pData, apCell[iCell+iNew], sz);
put2byte(pCellptr, (pData - aData));
nFree -= (sz + 2);
nCell++; nCell++;
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
1, &apCell[iCell + iNew], &szCell[iCell + iNew]
) ) goto editpage_fail;
} }
} }
/* Append cells to the end of the page */ /* Append cells to the end of the page */
pCellptr = &pPg->aCellIdx[nCell*2]; pCellptr = &pPg->aCellIdx[nCell*2];
for(i=iNew+nCell; i<(iNew+nNew); i++){ if( pageInsertArray(
pData -= szCell[i]; pPg, pBegin, &pData, pCellptr,
if( pData<pBegin ) goto editpage_fail; nNew-nCell, &apCell[iNew+nCell], &szCell[iNew+nCell]
memcpy(pData, apCell[i], szCell[i]); ) ) goto editpage_fail;
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
nFree -= (szCell[i] + 2);
}
pPg->nFree = nFree;
pPg->nCell = nNew; pPg->nCell = nNew;
pPg->nOverflow = 0; pPg->nOverflow = 0;
@ -6132,8 +6214,6 @@ static void editPage(
#endif #endif
return; return;
}
editpage_fail: editpage_fail:
#if 0 #if 0
printf("REBUILD\n"); printf("REBUILD\n");
@ -6662,7 +6742,7 @@ static int balance_nonroot(
assert( i<nMaxCells ); assert( i<nMaxCells );
subtotal += szCell[i] + 2; subtotal += szCell[i] + 2;
if( subtotal > usableSpace ){ if( subtotal > usableSpace ){
szNew[k] = subtotal - szCell[i]; szNew[k] = subtotal - szCell[i] - 2;
cntNew[k] = i; cntNew[k] = i;
if( leafData ){ i--; } if( leafData ){ i--; }
subtotal = 0; subtotal = 0;
@ -7002,6 +7082,7 @@ static int balance_nonroot(
editPage(apNew[iPg], iOld, iNew, nNewCell, apCell, szCell); editPage(apNew[iPg], iOld, iNew, nNewCell, apCell, szCell);
abDone[iPg] = 1; abDone[iPg] = 1;
apNew[iPg]->nFree = usableSpace-szNew[iPg];
assert( apNew[iPg]->nOverflow==0 ); assert( apNew[iPg]->nOverflow==0 );
assert( apNew[iPg]->nCell==nNewCell ); assert( apNew[iPg]->nCell==nNewCell );
} }