]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Auto-vacuum bug: Correctly manipulate page cache hash-table entries in sqlite3pager_m...
authordanielk1977 <danielk1977@noemail.net>
Wed, 3 Nov 2004 08:44:05 +0000 (08:44 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Wed, 3 Nov 2004 08:44:05 +0000 (08:44 +0000)
FossilOrigin-Name: 719c1b79671c8cd7c5a6b5967ad4265b65e433d3

manifest
manifest.uuid
src/pager.c

index e289ceb2e61a47cfc83a949889575e147f5dcc32..1d01247464a8f7ad540e54fe45ef627a58175a77 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C The\smakefile\snow\sruns\smkkeywordhash.c.\s\sKeywords\sthat\sare\sunused\sare\nomitted\sfrom\sthe\skeyword\shash\stable.\s(CVS\s2045)
-D 2004-11-03T03:59:57
+C Auto-vacuum\sbug:\sCorrectly\smanipulate\spage\scache\shash-table\sentries\sin\ssqlite3pager_movepage().\s(CVS\s2046)
+D 2004-11-03T08:44:06
 F Makefile.in c4d2416860f472a1e3393714d0372074197565df
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -52,7 +52,7 @@ F src/os_unix.c 5824b22ba41fe9d514ef9169aac1b5fde73af229
 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
 F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 6b00c0d5aac601b9f556b8fdba25e69438245f1a
+F src/pager.c 9ce238f9540eb56b21fef085dc038dffca75835b
 F src/pager.h cbe4ba356d9dd3f30260f322b3dc77408164df14
 F src/parse.y 625750bf4b01a7c2b4c15e5367a7539a66e6c909
 F src/pragma.c 44e192eb5928157bdb015926f858a7c6e3ef6c98
@@ -252,7 +252,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
-P bd50fbb5fecd1829c87e8ca72c458c71f590274b
-R c93f4ae3ede116e4f0e25ff57fd95e47
-U drh
-Z 2a91aed8200460991cb047467354dda3
+P 007aec11333432e08d1091b728773011e9078bc3
+R 745d17de8251e17a5bf338dbe0b72b9d
+U danielk1977
+Z 2233bf7f9ac4fbde946c01ae92386ee6
index 0b8c94064b67b9d5bb70053ae6899bc459f73598..ba1f11921536216a46711a8ec108d24153de8f38 100644 (file)
@@ -1 +1 @@
-007aec11333432e08d1091b728773011e9078bc3
\ No newline at end of file
+719c1b79671c8cd7c5a6b5967ad4265b65e433d3
\ No newline at end of file
index e6ab35b4a5af3a76d965807e7c8537694febdbdf..fcbd407c3567a595c506aafa6d150ce899d06be8 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.170 2004/11/02 12:56:41 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.171 2004/11/03 08:44:06 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1635,6 +1635,33 @@ int sqlite3pager_pagecount(Pager *pPager){
 static int syncJournal(Pager*);
 
 
+/*
+** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate
+** that the page is not part of any hash chain. This is required because the
+** sqlite3pager_movepage() routine can leave a page in the 
+** pNextFree/pPrevFree list that is not a part of any hash-chain.
+*/
+static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
+  if( pPg->pgno==0 ){
+    /* If the page number is zero, then this page is not in any hash chain. */
+    return;
+  }
+  if( pPg->pNextHash ){
+    pPg->pNextHash->pPrevHash = pPg->pPrevHash;
+  }
+  if( pPg->pPrevHash ){
+    assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );
+    pPg->pPrevHash->pNextHash = pPg->pNextHash;
+  }else{
+    int h = pager_hash(pPg->pgno);
+    assert( pPager->aHash[h]==pPg );
+    pPager->aHash[h] = pPg->pNextHash;
+  }
+
+  pPg->pgno = 0;
+  pPg->pNextHash = pPg->pPrevHash = 0;
+}
+
 /*
 ** Unlink a page from the free list (the list of all pages where nRef==0)
 ** and from its hash collision chain.
@@ -1665,6 +1692,8 @@ static void unlinkPage(PgHdr *pPg){
   pPg->pNextFree = pPg->pPrevFree = 0;
 
   /* Unlink from the pgno hash table */
+  unlinkHashChain(pPager, pPg);
+/*
   if( pPg->pNextHash ){
     pPg->pNextHash->pPrevHash = pPg->pPrevHash;
   }
@@ -1676,6 +1705,7 @@ static void unlinkPage(PgHdr *pPg){
     pPager->aHash[h] = pPg->pNextHash;
   }
   pPg->pNextHash = pPg->pPrevHash = 0;
+*/
 }
 
 /*
@@ -3215,6 +3245,7 @@ sync_exit:
 }
 
 #ifndef SQLITE_OMIT_AUTOVACUUM
+
 /*
 ** Move the page identified by pData to location pgno in the file. 
 **
@@ -3233,55 +3264,35 @@ sync_exit:
 int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
   PgHdr *pPg = DATA_TO_PGHDR(pData);
   PgHdr *pPgOld; 
+  int h;
 
   assert( !pPager->stmtInUse );
-  /* assert( pPg->pNextFree==0 && pPg->pPrevFree==0 && pPg->nRef>0 ); */
   assert( pPg->nRef>0 );
 
   /* Unlink pPg from it's hash-chain */
-  if( pPg->pNextHash ){
-    pPg->pNextHash->pPrevHash = pPg->pPrevHash;
-  }
-  if( pPg->pPrevHash ){
-    pPg->pPrevHash->pNextHash = pPg->pNextHash;
-  }else{
-    int h = pager_hash(pPg->pgno);
-    assert( pPager->aHash[h]==pPg );
-    pPager->aHash[h] = pPg->pNextHash;
-  }
-
-  /* Change the page number for pPg */
-  pPg->pgno = pgno;
+  unlinkHashChain(pPager, pPg);
 
+  /* If the cache contains a page with page-number pgno exists, remove it
+  ** from it's hash chain.
+  */
   pPgOld = pager_lookup(pPager, pgno);
   if( pPgOld ){
-    /* Remove pPgOld from the page number hash-chain and insert pPg. */
-    assert(pPgOld->nRef==0 && !pPgOld->pNextStmt && !pPgOld->pPrevStmt );
-    if( pPgOld->pNextHash ){
-      pPgOld->pNextHash->pPrevHash = pPg;
-    }
-    if( pPgOld->pPrevHash ){
-      pPgOld->pPrevHash->pNextHash = pPg;
-    }else{
-      int h = pager_hash(pgno);
-      assert( pPager->aHash[h]==pPgOld );
-      pPager->aHash[h] = pPg;
-    }
-    pPgOld->pNextHash = pPgOld->pPrevHash = 0;
-  }else{
-    /* Insert pPg into it's new hash-chain. */
-    int h = pager_hash(pgno);
-    if( pPager->aHash[h] ){
-      pPager->aHash[h]->pNextHash = pPg;
-    }
-    pPg->pNextHash = pPager->aHash[h];
-    pPg->pPrevHash = 0;
+    assert( pPgOld->nRef==0 );
+    unlinkHashChain(pPager, pPgOld);
+    pPgOld->dirty = 0;
   }
 
-  /* Don't write the old page when sqlite3pager_sync() is called. Do write
-  ** the new one. 
-  */
-  pPgOld->dirty = 0;
+  /* Change the page number for pPg and insert it into the new hash-chain. */
+  pPg->pgno = pgno;
+  h = pager_hash(pgno);
+  if( pPager->aHash[h] ){
+    assert( pPager->aHash[h]->pPrevHash==0 );
+    pPager->aHash[h]->pPrevHash = pPg;
+  }
+  pPg->pNextHash = pPager->aHash[h];
+  pPager->aHash[h] = pPg;
+  pPg->pPrevHash = 0;
+
   pPg->dirty = 1;
   pPager->dirtyCache = 1;