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().
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

View File

@ -1 +1 @@
fec849dcca3aead2bc2d4ecffeda750684d32fb0
6594f9b420e2fa642737722ff8521f756ecef227

View File

@ -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<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(
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( iOld<iNew ){
int nShift = 0;
for(i=iOld; i<iNew; i++){
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);
}
for(i=iNew+nNew; i<iOldEnd; i++){
if( apCell[i]>aData && 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( pData<pBegin ) goto editpage_fail;
/* Remove cells from the start and end of the page */
if( iOld<iNew ){
int nShift = pageFreeArray(
pPg, iNew-iOld, &apCell[iOld], &szCell[iOld]
);
memmove(pPg->aCellIdx, &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( iNew<iOld ){
pCellptr = pPg->aCellIdx;
memmove(&pCellptr[(iOld-iNew)*2], pCellptr, nCell*2);
for(i=iNew; i<iOld; i++){
pData -= szCell[i];
if( pData<pBegin ) goto editpage_fail;
memcpy(pData, apCell[i], szCell[i]);
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
nFree -= (szCell[i] + 2);
nCell++;
}
pData = &aData[get2byte(&aData[hdr+5])];
if( pData<pBegin ) goto editpage_fail;
/* Add cells to the start of the page */
if( iNew<iOld ){
int nAdd = iOld-iNew;
pCellptr = pPg->aCellIdx;
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; i<pPg->nOverflow; i++){
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){
u8 *pCellptr = &pPg->aCellIdx[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; i<pPg->nOverflow; i++){
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){
u8 *pCellptr = &pPg->aCellIdx[iCell * 2];
int sz = szCell[iCell+iNew];
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++;
}
}
/* Append cells to the end of the page */
pCellptr = &pPg->aCellIdx[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( pData<pBegin ) goto editpage_fail;
memcpy(pData, apCell[i], szCell[i]);
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
nFree -= (szCell[i] + 2);
}
pPg->nCell = 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; i<nNew; i++){
u8 *pCell = apCell[i+iNew];
int iOff = get2byte(&pPg->aCellIdx[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; i<nNew; i++){
u8 *pCell = apCell[i+iNew];
int iOff = get2byte(&pPg->aCellIdx[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<nMaxCells );
subtotal += szCell[i] + 2;
if( subtotal > 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 );
}