-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
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
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
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
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
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
-716fccea58c4c217e68e04e0776e44ae39c11950
\ No newline at end of file
+0b41dfc066b60ccabbf1a9ab4db41ebcb73a2799
\ No newline at end of file
** 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.
}
/*
-** 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 */
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;
}
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;
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;
** 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"
/* 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;
}
/*
-** 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
** 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 */
** 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
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.
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;
}
/*
** 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_
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*);
*************************************************************************
** 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"
int eCreate;
assert( pCache!=0 );
+ assert( createFlag==1 || createFlag==0 );
assert( pgno>0 );
/* If the pluggable cache (sqlite3_pcache*) has not been allocated,
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);
}
** 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"
}
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;
# 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
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}}
#---------------------------------------------------------------------------