]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make sure that the database size cache in the pager is invalidated whenever
authordrh <drh@noemail.net>
Wed, 3 Jan 2007 15:34:29 +0000 (15:34 +0000)
committerdrh <drh@noemail.net>
Wed, 3 Jan 2007 15:34:29 +0000 (15:34 +0000)
the database is unlocked.  A stale value in the database size cache can
result in database corruption on a heavily loaded system running
autovacuum. (CVS 3548)

FossilOrigin-Name: 6806b9ecb5e3b90e793c5862404e76485df33b25

manifest
manifest.uuid
src/pager.c

index b57f798cffd798f0ff12f109465aeb644a798d4d..25ee259b46b7093d8853a3a0aa9558905ff3a4c8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sthe\svtab_err\stest\sto\scheck\sfor\s-DSQLITE_MEMDEBUG=1\sand\sskip\sthe\stests\nif\smissing.\s\sPager\sis\smore\scareful\sto\sclear\sits\sfile\ssize\scache.\s\sRemove\nan\sassert()\sin\sVDBE\sthat\smight\sfail\son\sa\scorrupt\sdatabase\sfile.\s(CVS\s3547)
-D 2007-01-02T18:41:55
+C Make\ssure\sthat\sthe\sdatabase\ssize\scache\sin\sthe\spager\sis\sinvalidated\swhenever\nthe\sdatabase\sis\sunlocked.\s\sA\sstale\svalue\sin\sthe\sdatabase\ssize\scache\scan\nresult\sin\sdatabase\scorruption\son\sa\sheavily\sloaded\ssystem\srunning\nautovacuum.\s(CVS\s3548)
+D 2007-01-03T15:34:30
 F Makefile.in 63a71177ed4355c829229affe11167bd28c85884
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -85,7 +85,7 @@ F src/os_unix.c d4bc8cbe1c0dc330bd55bf7821db5b7dbfbf183e
 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
 F src/os_win.c ca46001d4ec446885f72d3b7fd6a657136156228
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 5a153277b050b4fe9db3e3ced6b3a7ad7f19561e
+F src/pager.c 4dbd6a12eb43f10a3c870a3006a54a7756768455
 F src/pager.h 2e6d42f4ae004ae748a037b8468112b851c447a7
 F src/parse.y 2f571c5f6219428d7fb08737db3d113742b1cceb
 F src/pragma.c d0891d3504b6291b506a5ec2226bbf79ffcef003
@@ -423,7 +423,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 720189b8fafa61e5b712b409e76c368079b4bf96
-R a594a599c63c21c9d19504b49bbf2e77
+P bf1afd016ad71dac90e58540122108f92e77ce3d
+R ffed07664ab99ec35d86454afb31b5e4
 U drh
-Z 4cc2942b88b80ed65e59fb32451d8d19
+Z 6c9f735d21716c225946d83bfcb229d4
index bf6c1e52fc50aa7e9be9ce8aac38e88a68d04800..a7467853d243c8dacc04213276965f372eec5191 100644 (file)
@@ -1 +1 @@
-bf1afd016ad71dac90e58540122108f92e77ce3d
\ No newline at end of file
+6806b9ecb5e3b90e793c5862404e76485df33b25
\ No newline at end of file
index 9c36c01e19ab4b17435228895b08f993ee50386e..b6fe7f3789dd01d94abc34bfc35db3e1375a8766 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.278 2007/01/02 18:41:55 drh Exp $
+** @(#) $Id: pager.c,v 1.279 2007/01/03 15:34:30 drh Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -850,6 +850,22 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
   return p;
 }
 
+/*
+** Unlock the database file.
+**
+** Once all locks have been removed from the database file, other
+** processes or threads might change the file.  So make sure all of
+** our internal cache is invalidated.
+*/
+static void pager_unlock(Pager *pPager){
+  if( !MEMDB ){
+    sqlite3OsUnlock(pPager->fd, NO_LOCK);
+    pPager->dbSize = -1;
+  }
+  pPager->state = PAGER_UNLOCK;
+}
+
+
 /*
 ** Unlock the database and clear the in-memory cache.  This routine
 ** sets the state of the pager back to what it was when it was first
@@ -874,9 +890,7 @@ static void pager_reset(Pager *pPager){
   if( pPager->state>=PAGER_RESERVED ){
     sqlite3pager_rollback(pPager);
   }
-  sqlite3OsUnlock(pPager->fd, NO_LOCK);
-  pPager->state = PAGER_UNLOCK;
-  pPager->dbSize = -1;
+  pager_unlock(pPager);
   pPager->nRef = 0;
   assert( pPager->journalOpen==0 );
 }
@@ -1425,6 +1439,7 @@ static int pager_stmt_playback(Pager *pPager){
   if( pPager->state>=PAGER_EXCLUSIVE ){
     rc = pager_truncate(pPager, pPager->stmtSize);
   }
+  assert( pPager->state>=PAGER_SHARED );
   pPager->dbSize = pPager->stmtSize;
 
   /* Figure out how many records are in the statement journal.
@@ -1974,9 +1989,15 @@ static void memoryTruncate(Pager *pPager){
 */
 static int pager_wait_on_lock(Pager *pPager, int locktype){
   int rc;
+
+  /* The OS lock values must be the same as the Pager lock values */
   assert( PAGER_SHARED==SHARED_LOCK );
   assert( PAGER_RESERVED==RESERVED_LOCK );
   assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
+
+  /* If the file is currently unlocked then the size must be unknown */
+  assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
+
   if( pPager->state>=locktype ){
     rc = SQLITE_OK;
   }else{
@@ -1995,6 +2016,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
 */
 int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
   int rc;
+  assert( pPager->state>=PAGER_SHARED || MEMDB );
   sqlite3pager_pagecount(pPager);
   if( pPager->errCode ){
     rc = pPager->errCode;
@@ -2064,16 +2086,12 @@ int sqlite3pager_close(Pager *pPager){
       disable_simulated_io_errors();
       sqlite3pager_rollback(pPager);
       enable_simulated_io_errors();
-      if( !MEMDB ){
-        sqlite3OsUnlock(pPager->fd, NO_LOCK);
-      }
+      pager_unlock(pPager);
       assert( pPager->errCode || pPager->journalOpen==0 );
       break;
     }
     case PAGER_SHARED: {
-      if( !MEMDB ){
-        sqlite3OsUnlock(pPager->fd, NO_LOCK);
-      }
+      pager_unlock(pPager);
       break;
     }
     default: {
@@ -2674,8 +2692,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
        */
        rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
        if( rc!=SQLITE_OK ){
-         sqlite3OsUnlock(pPager->fd, NO_LOCK);
-         pPager->state = PAGER_UNLOCK;
+         pager_unlock(pPager);
          return pager_error(pPager, rc);
        }
        pPager->state = PAGER_EXCLUSIVE;
@@ -2690,8 +2707,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
        */
        rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd);
        if( rc!=SQLITE_OK ){
-         sqlite3OsUnlock(pPager->fd, NO_LOCK);
-         pPager->state = PAGER_UNLOCK;
+         pager_unlock(pPager);
          return SQLITE_BUSY;
        }
        pPager->journalOpen = 1;
@@ -2973,8 +2989,7 @@ failed_to_open_journal:
     */
     sqlite3OsDelete(pPager->zJournal);
   }else{
-    sqlite3OsUnlock(pPager->fd, NO_LOCK);
-    pPager->state = PAGER_UNLOCK;
+    pager_unlock(pPager);
   }
   return rc;
 }
@@ -3233,6 +3248,7 @@ int sqlite3pager_write(void *pData){
 
   /* Update the database size and return.
   */
+  assert( pPager->state>=PAGER_SHARED );
   if( pPager->dbSize<(int)pPg->pgno ){
     pPager->dbSize = pPg->pgno;
     if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
@@ -3308,6 +3324,7 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
   assert( pPg!=0 );  /* We never call _dont_write unless the page is in mem */
   pPg->alwaysRollback = 1;
   if( pPg->dirty && !pPager->stmtInUse ){
+    assert( pPager->state>=PAGER_SHARED );
     if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
       /* If this pages is the last page in the file and the file has grown
       ** during the current transaction, then do NOT mark the page as clean.
@@ -3544,6 +3561,7 @@ int sqlite3pager_stmt_begin(Pager *pPager){
   int rc;
   char zTemp[SQLITE_TEMPNAME_SIZE];
   assert( !pPager->stmtInUse );
+  assert( pPager->state>=PAGER_SHARED );
   assert( pPager->dbSize>=0 );
   TRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
   if( MEMDB ){