]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Modify the merge-sort in wal.c so that it does not use recursion.
authordan <dan@noemail.net>
Fri, 25 Jun 2010 11:35:52 +0000 (11:35 +0000)
committerdan <dan@noemail.net>
Fri, 25 Jun 2010 11:35:52 +0000 (11:35 +0000)
FossilOrigin-Name: daea6c054cee3564d8460d876b78a325ebc382dd

manifest
manifest.uuid
src/wal.c

index b53c0711807e6bf762078d75537b53d2c88aa372..d82e932aea179a3d7f8b46339d372173044ccfc6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 35ecaf6fcdac298100a53c437290a775065f7ccf..2c14a71f4ce379c6315e961020847268556ce8a0 100644 (file)
@@ -1 +1 @@
-4941e437d2638f36ac8510d4a5b4c780afc798bb
\ No newline at end of file
+daea6c054cee3564d8460d876b78a325ebc382dd
\ No newline at end of file
index 3f976329f62f5b045cb1963b7b7a1974f410ff94..30ec85906b85c4ccaec21ccd7f188ab61fd6735c 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -1287,49 +1287,95 @@ 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 */
-
-    /* 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
   {
@@ -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 ){