-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
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
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
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 */
-
- /* TODO: Change to non-recursive version. */
- walMergesort(aContent, aBuffer, aLeft, &nLeft);
- walMergesort(aContent, aBuffer, aRight, &nRight);
-
- 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];
+ struct Sublist {
+ int nList; /* Number of elements in aList */
+ ht_slot *aList; /* Pointer to sub-list content */
+ };
- aBuffer[iOut++] = logpage;
- if( iLeft<nLeft && aContent[aLeft[iLeft]]==dbpage ) iLeft++;
+ 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 */
+
+ memset(aSub, 0, sizeof(aSub));
+ assert( nList<=HASHTABLE_NPAGE && nList>0 );
+ assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) );
+
+ 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);
+ }
+ aSub[iSub].aList = aMerge;
+ aSub[iSub].nList = nMerge;
+ }
- assert( iLeft>=nLeft || aContent[aLeft[iLeft]]>dbpage );
- assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage );
+ 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);
}
- memcpy(aList, aBuffer, sizeof(aList[0])*iOut);
- *pnList = iOut;
}
+ assert( aMerge==aList );
+ *pnList = nMerge;
#ifdef SQLITE_DEBUG
{
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 ){