Modify the merge-sort in wal.c so that it does not use recursion.

FossilOrigin-Name: daea6c054cee3564d8460d876b78a325ebc382dd
This commit is contained in:
dan 2010-06-25 11:35:52 +00:00
parent ec6ffc1a6a
commit f544b4c4b8
3 changed files with 88 additions and 39 deletions

View File

@ -1,5 +1,5 @@
C Add\stest\scases\sto\spager1.test\sand\spagerfault.test.
D 2010-06-24T19:16:06
C Modify\sthe\smerge-sort\sin\swal.c\sso\sthat\sit\sdoes\snot\suse\srecursion.
D 2010-06-25T11:35:52
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -226,7 +226,7 @@ F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
F src/wal.c 40e6d0acde18a0d4796310db4d6382a12340388c
F src/wal.c a6648b66a8990439d5d5c124191590b00929b9e4
F src/wal.h 4ace25262452d17e7d3ec970c89ee17794004008
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 1c895bef33d0dfc7ed90fb1f74120435d210ea56
@ -825,7 +825,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 7d83fbae9802a56b2121d0775de54fccd743d971
R 43cdd6cd887c3657632da5d79f140434
P 4941e437d2638f36ac8510d4a5b4c780afc798bb
R 758d45a862d61942569f7b92d886b198
U dan
Z 18163dae6e1dc526dfe07de5a30526c2
Z 787d6dd7a1ce6e802a68550ea5002b17

View File

@ -1 +1 @@
4941e437d2638f36ac8510d4a5b4c780afc798bb
daea6c054cee3564d8460d876b78a325ebc382dd

113
src/wal.c
View File

@ -1287,50 +1287,96 @@ static int walIteratorNext(
return (iRet==0xFFFFFFFF);
}
/*
** This function merges two sorted lists into a single sorted list.
*/
static void walMerge(
u32 *aContent, /* Pages in wal */
ht_slot *aLeft, /* IN: Left hand input list */
int nLeft, /* IN: Elements in array *paLeft */
ht_slot **paRight, /* IN/OUT: Right hand input list */
int *pnRight, /* IN/OUT: Elements in *paRight */
ht_slot *aTmp /* Temporary buffer */
){
int iLeft = 0; /* Current index in aLeft */
int iRight = 0; /* Current index in aRight */
int iOut = 0; /* Current index in output buffer */
int nRight = *pnRight;
ht_slot *aRight = *paRight;
assert( nLeft>0 && nRight>0 );
while( iRight<nRight || iLeft<nLeft ){
ht_slot logpage;
Pgno dbpage;
if( (iLeft<nLeft)
&& (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
){
logpage = aLeft[iLeft++];
}else{
logpage = aRight[iRight++];
}
dbpage = aContent[logpage];
aTmp[iOut++] = logpage;
if( iLeft<nLeft && aContent[aLeft[iLeft]]==dbpage ) iLeft++;
assert( iLeft>=nLeft || aContent[aLeft[iLeft]]>dbpage );
assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage );
}
*paRight = aLeft;
*pnRight = iOut;
memcpy(aLeft, aTmp, sizeof(aTmp[0])*iOut);
}
/*
** Sort the elements in list aList, removing any duplicates.
*/
static void walMergesort(
u32 *aContent, /* Pages in wal */
ht_slot *aBuffer, /* Buffer of at least *pnList items to use */
ht_slot *aList, /* IN/OUT: List to sort */
int *pnList /* IN/OUT: Number of elements in aList[] */
){
int nList = *pnList;
if( nList>1 ){
int nLeft = nList / 2; /* Elements in left list */
int nRight = nList - nLeft; /* Elements in right list */
int iLeft = 0; /* Current index in aLeft */
int iRight = 0; /* Current index in aright */
int iOut = 0; /* Current index in output buffer */
ht_slot *aLeft = aList; /* Left list */
ht_slot *aRight = aList+nLeft;/* Right list */
struct Sublist {
int nList; /* Number of elements in aList */
ht_slot *aList; /* Pointer to sub-list content */
};
/* TODO: Change to non-recursive version. */
walMergesort(aContent, aBuffer, aLeft, &nLeft);
walMergesort(aContent, aBuffer, aRight, &nRight);
const int nList = *pnList; /* Size of input list */
int nMerge; /* Number of elements in list aMerge */
ht_slot *aMerge; /* List to be merged */
int iList; /* Index into input list */
int iSub; /* Index into aSub array */
struct Sublist aSub[13]; /* Array of sub-lists */
while( iRight<nRight || iLeft<nLeft ){
ht_slot logpage;
Pgno dbpage;
memset(aSub, 0, sizeof(aSub));
assert( nList<=HASHTABLE_NPAGE && nList>0 );
assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) );
if( (iLeft<nLeft)
&& (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
){
logpage = aLeft[iLeft++];
}else{
logpage = aRight[iRight++];
}
dbpage = aContent[logpage];
aBuffer[iOut++] = logpage;
if( iLeft<nLeft && aContent[aLeft[iLeft]]==dbpage ) iLeft++;
assert( iLeft>=nLeft || aContent[aLeft[iLeft]]>dbpage );
assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage );
for(iList=0; iList<nList; iList++){
nMerge = 1;
aMerge = &aList[iList];
for(iSub=0; iList & (1<<iSub); iSub++){
struct Sublist *p = &aSub[iSub];
assert( p->aList && p->nList<=(1<<iSub) );
walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
}
memcpy(aList, aBuffer, sizeof(aList[0])*iOut);
*pnList = iOut;
aSub[iSub].aList = aMerge;
aSub[iSub].nList = nMerge;
}
for(iSub++; iSub<ArraySize(aSub); iSub++){
if( nList & (1<<iSub) ){
struct Sublist *p = &aSub[iSub];
assert( p->nList<=(2<<iSub) );
walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
}
}
assert( aMerge==aList );
*pnList = nMerge;
#ifdef SQLITE_DEBUG
{
int i;
@ -1474,11 +1520,14 @@ static int walCheckpoint(
int i; /* Loop counter */
volatile WalCkptInfo *pInfo; /* The checkpoint status information */
if( pWal->hdr.mxFrame==0 ) return SQLITE_OK;
/* Allocate the iterator */
rc = walIteratorInit(pWal, &pIter);
if( rc!=SQLITE_OK || pWal->hdr.mxFrame==0 ){
if( rc!=SQLITE_OK ){
goto walcheckpoint_out;
}
assert( pIter );
/*** TODO: Move this test out to the caller. Make it an assert() here ***/
if( pWal->hdr.szPage!=nBuf ){