Further work on balance_nonroot().
FossilOrigin-Name: 6594f9b420e2fa642737722ff8521f756ecef227
This commit is contained in:
parent
09c6840153
commit
d7b545bbcb
12
manifest
12
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
|
||||
|
@ -1 +1 @@
|
||||
fec849dcca3aead2bc2d4ecffeda750684d32fb0
|
||||
6594f9b420e2fa642737722ff8521f756ecef227
|
265
src/btree.c
265
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<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 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user