]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change getAndInitPage() (btree.c) to use only PagerAcquire(), not PagerLookup() and...
authordanielk1977 <danielk1977@noemail.net>
Tue, 21 Jul 2009 19:25:24 +0000 (19:25 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 21 Jul 2009 19:25:24 +0000 (19:25 +0000)
FossilOrigin-Name: 0b41dfc066b60ccabbf1a9ab4db41ebcb73a2799

manifest
manifest.uuid
src/btree.c
src/pager.c
src/pager.h
src/pcache.c
src/test2.c
test/corruptB.test

index 030882357ac03f78a8a4965edd623176dc1cfe0f..1e7fb16882574934928e0d43f632bb0c982b21e4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Additional\ssimplifications\sto\sbtree.c\sin\ssupport\sof\scoverage\stesting.\s(CVS\s6915)
-D 2009-07-21T19:02:21
+C Change\sgetAndInitPage()\s(btree.c)\sto\suse\sonly\sPagerAcquire(),\snot\sPagerLookup()\sand\sPagerAcquire().\s(CVS\s6916)
+D 2009-07-21T19:25:24
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in df9359da7a726ccb67a45db905c5447d5c00c6ef
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -106,7 +106,7 @@ F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025
 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3
 F src/bitvec.c cfbf6af5b0ababb4f06ed3e75c616dadaf47fcbd
 F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
-F src/btree.c abc2ccac9f9cf605888b48689e5886301c0f25c0
+F src/btree.c 710f95cf3816202c64a8639677a8d9691abefa83
 F src/btree.h e53a10fd31d16c60a86f03c9467a6f470aa3683b
 F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
 F src/build.c 867028ee9f63f7bc8eb8d4a720bb98cf9b9a12b4
@@ -147,10 +147,10 @@ F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc
 F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5
 F src/os_unix.c cdb2a08b9ce4aa13b3f7b91d4dd60fb48be9f56a
 F src/os_win.c 725c38a524d168ce280446ad8761d731bc516405
-F src/pager.c ed7cdaac02878f7b74d4de01b36520e5505c9af6
-F src/pager.h 5aec418bf99f568b92ae82816a1463400513726d
+F src/pager.c 9838393b4a5118eb935ac0939621177157a38bc1
+F src/pager.h 5bd96ed838e4156e0effa5ffe746bce4c0112c24
 F src/parse.y bcd46d43fbd23a22b8c020a3eb1806b794794ed5
-F src/pcache.c 7d27635a4bd03c81ce848cb186fea6192706fa1a
+F src/pcache.c 1dae135b70a029f81ed66f6e9b5d0db91480d5d0
 F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
 F src/pcache1.c 6dc833c89feac405dd8b4858232c97e679f182ec
 F src/pragma.c 9eb44ac1d3dc1ac3ea4f444abe1a10ae8acaa16c
@@ -169,7 +169,7 @@ F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
 F src/tclsqlite.c e18e5013dc6bca9f25e6022fbe17ba3ccb821f95
 F src/test1.c c8f9358879876660b721369f576bf6e4ac5b9210
-F src/test2.c d7d7907cec3ed918b3b35e8e44fb3de3709d9509
+F src/test2.c ffb1649b7a33a0acd5bd1a98a376b9c104daa279
 F src/test3.c 2445c2beb5e7a0c91fd8136dc1339ec369a24898
 F src/test4.c f79ab52d27ff49b784b631a42e2ccd52cfd5c84c
 F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288
@@ -291,7 +291,7 @@ F test/corrupt7.test 8bfb08842642b1a598a915b52a7f51fbc0289b62
 F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51
 F test/corrupt9.test 4aa1cb1ef091cb0e13e89a819c72911631b5176a
 F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff
-F test/corruptB.test 267be7fbb7bdb89df40007178437ebdd0cd9c174
+F test/corruptB.test 66b4544104dd03d0f33ea69ddac3fa4a682cd3c2
 F test/corruptC.test 691ed070baef5e1345939caadf270a52837a5064
 F test/corruptD.test 3ae6e2dc6e2226c6935a8a40d4b5ee3eba75f8c0
 F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
@@ -741,7 +741,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
-P 110998f18a7ad1ddaffab048cabef675d882cbb8
-R c2ae620b83a5c070a034b2845bc5bdf6
-U drh
-Z 3dae4d3e2687351a2da40f1b63712770
+P 716fccea58c4c217e68e04e0776e44ae39c11950
+R 1ee5a6818bfe745a7b3a3e753bd0011a
+U danielk1977
+Z 0104982a535ea93c433ad3cd1f268c89
index d20f0abc2496c721b2457936ddc408ced2a49504..750bad557677fc09b957cba63af699818e541bf2 100644 (file)
@@ -1 +1 @@
-716fccea58c4c217e68e04e0776e44ae39c11950
\ No newline at end of file
+0b41dfc066b60ccabbf1a9ab4db41ebcb73a2799
\ No newline at end of file
index 5fdce66622544600fe1e731d092c623847eaacd5..d0ce43417d4c6feec88cdce2df79fc15ec700f44 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.696 2009/07/21 19:02:21 drh Exp $
+** $Id: btree.c,v 1.697 2009/07/21 19:25:24 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -1540,9 +1540,12 @@ static Pgno pagerPagecount(BtShared *pBt){
 }
 
 /*
-** Get a page from the pager and initialize it.  This routine
-** is just a convenience wrapper around separate calls to
-** btreeGetPage() and btreeInitPage().
+** Get a page from the pager and initialize it.  This routine is just a
+** convenience wrapper around separate calls to btreeGetPage() and 
+** btreeInitPage().
+**
+** If an error occurs, then the value *ppPage is set to is undefined. It
+** may remain unchanged, or it may be set to an invalid value.
 */
 static int getAndInitPage(
   BtShared *pBt,          /* The database file */
@@ -1550,39 +1553,25 @@ static int getAndInitPage(
   MemPage **ppPage     /* Write the page pointer here */
 ){
   int rc;
-  MemPage *pPage;
-
+  TESTONLY( Pgno iLastPg = pagerPagecount(pBt); )
   assert( sqlite3_mutex_held(pBt->mutex) );
-  if( pgno==0 ){
-    return SQLITE_CORRUPT_BKPT; 
-  }
 
-  /* It is often the case that the page we want is already in cache.
-  ** If so, get it directly.  This saves us from having to call
-  ** pagerPagecount() to make sure pgno is within limits, which results
-  ** in a measureable performance improvements.
-  */
-  *ppPage = pPage = btreePageLookup(pBt, pgno);
-  if( pPage ){
-    /* Page is already in cache */
-    rc = SQLITE_OK;
-  }else{
-    /* Page not in cache.  Acquire it. */
-    testcase( pgno==pagerPagecount(pBt) );
-    if( pgno>pagerPagecount(pBt) ){
-      return SQLITE_CORRUPT_BKPT; 
+  rc = btreeGetPage(pBt, pgno, ppPage, 0);
+  if( rc==SQLITE_OK ){
+    rc = btreeInitPage(*ppPage);
+    if( rc!=SQLITE_OK ){
+      releasePage(*ppPage);
     }
-    rc = btreeGetPage(pBt, pgno, ppPage, 0);
-    if( rc ) return rc;
-    pPage = *ppPage;
-  }
-  if( !pPage->isInit ){
-    rc = btreeInitPage(pPage);
-  }
-  if( rc!=SQLITE_OK ){
-    releasePage(pPage);
-    *ppPage = 0;
   }
+
+  /* If the requested page number was either 0 or greater than the page
+  ** number of the last page in the database, this function should return
+  ** SQLITE_CORRUPT or some other error (i.e. SQLITE_FULL). Check that this
+  ** is the case.  */
+  assert( (pgno>0 && pgno<=iLastPg) || rc!=SQLITE_OK );
+  testcase( pgno==0 );
+  testcase( pgno==iLastPg );
+
   return rc;
 }
 
@@ -2207,6 +2196,8 @@ static int lockBtree(BtShared *pBt){
 
   assert( sqlite3_mutex_held(pBt->mutex) );
   assert( pBt->pPage1==0 );
+  rc = sqlite3PagerSharedLock(pBt->pPager);
+  if( rc!=SQLITE_OK ) return rc;
   rc = btreeGetPage(pBt, 1, &pPage1, 0);
   if( rc!=SQLITE_OK ) return rc;
 
@@ -5705,7 +5696,7 @@ static int balance_nonroot(
   while( 1 ){
     rc = getAndInitPage(pBt, pgno, &apOld[i]);
     if( rc ){
-      memset(apOld, 0, i*sizeof(MemPage*));
+      memset(apOld, 0, (i+1)*sizeof(MemPage*));
       goto balance_cleanup;
     }
     nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
index 8884b7ad50ce1861a8fceaf0eea5962595a58926..0ef32332631433f49b29b8ece25bcf2e09e5b34a 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.609 2009/07/18 20:01:37 drh Exp $
+** @(#) $Id: pager.c,v 1.610 2009/07/21 19:25:24 danielk1977 Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -1127,7 +1127,7 @@ static void pager_unlock(Pager *pPager){
     /* If the file is unlocked, somebody else might change it. The
     ** values stored in Pager.dbSize etc. might become invalid if
     ** this happens. TODO: Really, this doesn't need to be cleared
-    ** until the change-counter check fails in pagerSharedLock().
+    ** until the change-counter check fails in PagerSharedLock().
     */
     pPager->dbSizeValid = 0;
 
@@ -3545,10 +3545,12 @@ static int readDbPage(PgHdr *pPg){
 }
 
 /*
-** This function is called whenever the upper layer requests a database
-** page is requested, before the cache is checked for a suitable page
-** or any data is read from the database. It performs the following
-** two functions:
+** This function is called to obtain a shared lock on the database file.
+** It is illegal to call sqlite3PagerAcquire() until after this function
+** has been successfully called. If a shared-lock is already held when
+** this function is called, it is a no-op.
+**
+** The following operations are also performed by this function.
 **
 **   1) If the pager is currently in PAGER_UNLOCK state (no lock held
 **      on the database file), then an attempt is made to obtain a
@@ -3574,7 +3576,7 @@ static int readDbPage(PgHdr *pPg){
 ** IO error occurs while locking the database, checking for a hot-journal
 ** file or rolling back a journal file, the IO error code is returned.
 */
-static int pagerSharedLock(Pager *pPager){
+int sqlite3PagerSharedLock(Pager *pPager){
   int rc = SQLITE_OK;                /* Return code */
   int isErrorReset = 0;              /* True if recovering from error state */
 
@@ -3787,11 +3789,6 @@ static void pagerDropPage(DbPage *pPg){
 ** reference has type DbPage*). If the requested reference is 
 ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
 **
-** This function calls pagerSharedLock() to obtain a SHARED lock on
-** the database file if such a lock or greater is not already held.
-** This may cause hot-journal rollback or a cache purge. See comments
-** above function pagerSharedLock() for details.
-**
 ** If the requested page is already in the cache, it is returned. 
 ** Otherwise, a new page object is allocated and populated with data
 ** read from the database file. In some cases, the pcache module may
@@ -3843,62 +3840,65 @@ int sqlite3PagerAcquire(
   DbPage **ppPage,    /* Write a pointer to the page here */
   int noContent       /* Do not bother reading content from disk if true */
 ){
-  PgHdr *pPg = 0;
   int rc;
+  PgHdr *pPg;
 
   assert( assert_pager_state(pPager) );
-  assert( pPager->state==PAGER_UNLOCK 
-       || sqlite3PcacheRefCount(pPager->pPCache)>0 
-       || pgno==1
-  );
+  assert( pPager->state>PAGER_UNLOCK );
 
-  /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
-  ** number greater than this, or zero, is requested.
-  */
-  if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
+  if( pgno==0 ){
     return SQLITE_CORRUPT_BKPT;
   }
 
-  /* Make sure we have not hit any critical errors.
-  */ 
-  assert( pPager!=0 );
-  *ppPage = 0;
-
-  /* If this is the first page accessed, then get a SHARED lock
-  ** on the database file. pagerSharedLock() is a no-op if 
-  ** a database lock is already held.
-  */
-  rc = pagerSharedLock(pPager);
-  if( rc!=SQLITE_OK ){
-    return rc;
+  /* If the pager is in the error state, return an error immediately. 
+  ** Otherwise, request the page from the PCache layer. */
+  if( pPager->errCode!=SQLITE_OK && pPager->errCode!=SQLITE_FULL ){
+    rc = pPager->errCode;
+  }else{
+    rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
   }
-  assert( pPager->state!=PAGER_UNLOCK );
 
-  rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
   if( rc!=SQLITE_OK ){
-    pagerUnlockIfUnused(pPager);
-    return rc;
-  }
-  assert( pPg->pgno==pgno );
-  assert( pPg->pPager==pPager || pPg->pPager==0 );
-  if( pPg->pPager==0 ){
+    /* Either the call to sqlite3PcacheFetch() returned an error or the
+    ** pager was already in the error-state when this function was called.
+    ** Set pPg to 0 and jump to the exception handler.  */
+    pPg = 0;
+    goto pager_acquire_err;
+  }
+  assert( (*ppPage)->pgno==pgno );
+  assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
+
+  if( (*ppPage)->pPager ){
+    /* In this case the pcache already contains an initialized copy of
+    ** the page. Return without further ado.  */
+    PAGER_INCR(pPager->nHit);
+    return SQLITE_OK;
+
+  }else{
     /* The pager cache has created a new page. Its content needs to 
-    ** be initialized.
-    */
+    ** be initialized.  */
     int nMax;
+
     PAGER_INCR(pPager->nMiss);
+    pPg = *ppPage;
     pPg->pPager = pPager;
 
+    /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
+    ** number greater than this, or the unused locking-page, is requested. */
+    if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
+      rc = SQLITE_CORRUPT_BKPT;
+      goto pager_acquire_err;
+    }
+
     rc = sqlite3PagerPagecount(pPager, &nMax);
     if( rc!=SQLITE_OK ){
-      sqlite3PagerUnref(pPg);
-      return rc;
+      goto pager_acquire_err;
     }
 
     if( nMax<(int)pgno || MEMDB || noContent ){
       if( pgno>pPager->mxPgno ){
-        sqlite3PagerUnref(pPg);
-        return SQLITE_FULL;
+       rc = SQLITE_FULL;
+       goto pager_acquire_err;
       }
       if( noContent ){
         /* Failure to set the bits in the InJournal bit-vectors is benign.
@@ -3924,19 +3924,23 @@ int sqlite3PagerAcquire(
       rc = readDbPage(pPg);
       if( rc!=SQLITE_OK ){
         pagerDropPage(pPg);
-        return rc;
+       pPg = 0;
+        goto pager_acquire_err;
       }
     }
 #ifdef SQLITE_CHECK_PAGES
     pPg->pageHash = pager_pagehash(pPg);
 #endif
-  }else{
-    /* The requested page is in the page cache. */
-    PAGER_INCR(pPager->nHit);
   }
 
-  *ppPage = pPg;
   return SQLITE_OK;
+
+pager_acquire_err:
+  assert( rc!=SQLITE_OK );
+  sqlite3PagerUnref(pPg);
+  pagerUnlockIfUnused(pPager);
+  *ppPage = 0;
+  return rc;
 }
 
 /*
index aed165f06ad3aa64ee605d8f9f85a15bc991fea9..6a82fb27566a5b2f997230858f37417cd6da3302 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  The page cache subsystem reads and writes a file a page
 ** at a time and provides a journal for rollback.
 **
-** @(#) $Id: pager.h,v 1.102 2009/06/18 17:22:39 drh Exp $
+** @(#) $Id: pager.h,v 1.103 2009/07/21 19:25:24 danielk1977 Exp $
 */
 
 #ifndef _PAGER_H_
@@ -126,6 +126,7 @@ int sqlite3PagerCommitPhaseTwo(Pager*);
 int sqlite3PagerRollback(Pager*);
 int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
 int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
+int sqlite3PagerSharedLock(Pager *pPager);
 
 /* Functions used to query pager state and configuration. */
 u8 sqlite3PagerIsreadonly(Pager*);
index dd166f8577bc347067a59d8f0cf0cedd445eda65..3b86b188c8ed01c9eac386d9db046ff174eb7348 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file implements that page cache.
 **
-** @(#) $Id: pcache.c,v 1.45 2009/07/16 18:21:18 drh Exp $
+** @(#) $Id: pcache.c,v 1.46 2009/07/21 19:25:24 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -208,6 +208,7 @@ int sqlite3PcacheFetch(
   int eCreate;
 
   assert( pCache!=0 );
+  assert( createFlag==1 || createFlag==0 );
   assert( pgno>0 );
 
   /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
@@ -225,10 +226,7 @@ int sqlite3PcacheFetch(
     pCache->pCache = p;
   }
 
-  eCreate = createFlag ? 1 : 0;
-  if( eCreate && (!pCache->bPurgeable || !pCache->pDirty) ){
-    eCreate = 2;
-  }
+  eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
   if( pCache->pCache ){
     pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate);
   }
index 43859c6d6b3d62fdecf9465613fea58a05c8e6c0..e5fac8b1f5d15a676cfd114414c972c1bcb04db5 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test2.c,v 1.72 2009/07/16 18:21:18 drh Exp $
+** $Id: test2.c,v 1.73 2009/07/21 19:25:24 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -342,7 +342,10 @@ static int page_get(
   }
   pPager = sqlite3TestTextToPtr(argv[1]);
   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
-  rc = sqlite3PagerGet(pPager, pgno, &pPage);
+  rc = sqlite3PagerSharedLock(pPager);
+  if( rc==SQLITE_OK ){
+    rc = sqlite3PagerGet(pPager, pgno, &pPage);
+  }
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
index ceba404394830737ccc2262a649996c5b1c45f0d..7d3740bc61be382c882518066ec9821fea8ba431 100644 (file)
@@ -20,7 +20,7 @@
 # contains a (corrupt) reference to a page greater than the configured
 # maximum page number.
 #
-# $Id: corruptB.test,v 1.3 2009/06/05 17:09:12 drh Exp $
+# $Id: corruptB.test,v 1.4 2009/07/21 19:25:24 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -154,7 +154,7 @@ do_test corruptB-2.1.1 {
 do_test corruptB-2.1.2 {
   sqlite3 db test.db
   catchsql { SELECT * FROM t1 }
-} {1 {database disk image is malformed}}
+} {1 {database or disk is full}}
 
 #---------------------------------------------------------------------------