Clarify error handling in pager code. No functional changes. (CVS 2956)

FossilOrigin-Name: 7b48836214ea3152f46e2dffb097ae7ea14901f4
This commit is contained in:
danielk1977 2006-01-16 11:29:19 +00:00
parent 45bfcfd3fc
commit efaaf57974
6 changed files with 68 additions and 106 deletions

View File

@ -1,5 +1,5 @@
C Version\s3.3.1\s(alpha)\s(CVS\s2953)
D 2006-01-16T02:39:05
C Clarify\serror\shandling\sin\spager\scode.\sNo\sfunctional\schanges.\s(CVS\s2956)
D 2006-01-16T11:29:19
F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -59,18 +59,18 @@ F src/os_unix.c 7daa1720d46bbc31c6138462b35876650eb1885e
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c cd4ca2753aeaad11f5c9b9b6ef28752f45ed4529
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 12da1f38d60a2c44925281d3a1bc2769fa36428b
F src/pager.c 24d4b97c29a6a3d9f4437e6b56debb7e3f3183b2
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
F src/parse.y 83df51fea35f68f7e07384d75dce83d1ed30434c
F src/pragma.c 4496cc77dc35824e1c978c3d1413b8a5a4c777d3
F src/prepare.c 1058dcb102005a880d757551d52a0a2830c05f27
F src/prepare.c 368f5c04755f03dc04353513e6afcebb8ca8d53f
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
F src/select.c 28d449c7762dd580aaba49a9c6c16e93ca951e49
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
F src/sqlite.h.in 492580f7e3ff71eb43193eb7bb98e2d549889ce3
F src/sqliteInt.h ed482d6de58fa79000f9c3bb00d7740126fb55fb
F src/sqliteInt.h 940bb605c7ac9240934f0b866f90be899f5261fc
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
F src/tclsqlite.c d650bea0248fc0a310ddc2cb94273a3a5021fddf
F src/test1.c d21e94ea95e76d8e838792806937332c5693dbf0
@ -90,7 +90,7 @@ F src/vacuum.c 21a3c7f6f7be86bb1182fbc3df416ad702435b9e
F src/vdbe.c 4db1a9000e238e068de56108f5a9708cd4124d55
F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
F src/vdbeInt.h 5451cf71f229e366ac543607c0a17f36e5737ea9
F src/vdbeapi.c afd3837cea0dec93dcb4724d073c84fa0da68e23
F src/vdbeapi.c cac3f5bfb8ab9864ce5cea35eaae3d0d2efdc8ac
F src/vdbeaux.c bfad18ca5d0372a34147ed98ac268b75ccb6858d
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c dd08a0eea4868ac4a2d91fdec32424308b1db772
@ -341,7 +341,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 6591d365d4ba1263c3bc48f5ab47633fae2b2a3a
R 7d7be83f73b610d0efb0d6e55a70818a
U drh
Z 95511deea1a74daa9ad5dc683e2d355c
P bd7c5699939fda2bb792a0e2448df064a1171769
R 24df549afc2503239ffb645fa43166ce
U danielk1977
Z c2d3eab392f302df5565749bb5c35c05

View File

@ -1 +1 @@
bd7c5699939fda2bb792a0e2448df064a1171769
7b48836214ea3152f46e2dffb097ae7ea14901f4

View File

@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.237 2006/01/15 20:28:28 drh Exp $
** @(#) $Id: pager.c,v 1.238 2006/01/16 11:29:19 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
@ -225,6 +225,14 @@ struct PgHistory {
/*
** A open page cache is an instance of the following structure.
**
** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL
** or SQLITE_FULL. Once one of the first three errors occurs, it persists
** and is returned as the result of every major pager API call. The
** SQLITE_FULL return code is slightly different. It persists only until the
** next successful rollback is performed on the pager cache. Also,
** SQLITE_FULL does not affect the sqlite3pager_get() and sqlite3pager_lookup()
** APIs, they may still be used successfully.
*/
struct Pager {
u8 journalOpen; /* True if journal file descriptors is valid */
@ -237,7 +245,7 @@ struct Pager {
u8 noSync; /* Do not sync the journal if true */
u8 fullSync; /* Do extra syncs of the journal for robustness */
u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
u8 errMask; /* One of several kinds of errors */
u8 errCode; /* One of several kinds of errors */
u8 tempFile; /* zFilename is a temporary file */
u8 readOnly; /* True for a read-only database */
u8 needSync; /* True if an fsync() is needed on the journal */
@ -299,39 +307,6 @@ struct Pager {
# define TEST_INCR(x)
#endif
/*
** These are bits that can be set in Pager.errMask.
**
** TODO: Maybe we just want a variable - Pager.errCode. Can we really
** have two simultaneous error conditions?
**
** Recovering from an SQLITE_FULL, SQLITE_LOCK, SQLITE_CORRUPT or
** SQLITE_IOERR error is not a simple matter, particularly if the pager
** cache is shared between multiple connections.
**
** SQLITE_FULL (PAGER_ERR_FULL):
** Cleared when the transaction is rolled back.
**
** SQLITE_CORRUPT (PAGER_ERR_CORRUPT):
** Cannot be cleared. The upper layer must close the current pager
** and open a new one on the same file to continue.
**
** SQLITE_PROTOCOL (PAGER_ERR_LOCK):
** This error only occurs if an internal error occurs or another process
** is not following the sqlite locking protocol (i.e. someone is
** manipulating the database file using something other than sqlite).
** This is handled in the same way as database corruption - the error
** cannot be cleared except by closing the current pager and opening
** a brand new one on the same file.
**
** SQLITE_IOERR (PAGER_ERR_DISK):
** Cleared when the transaction is rolled back.
*/
#define PAGER_ERR_FULL 0x01 /* a write() failed */
#define PAGER_ERR_LOCK 0x02 /* error in the locking protocol */
#define PAGER_ERR_CORRUPT 0x04 /* database or journal corruption */
#define PAGER_ERR_DISK 0x08 /* general disk I/O error - bad hard drive? */
/*
** Journal files begin with the following magic string. The data
** was obtained from /dev/random. It is used only as a sanity check.
@ -480,37 +455,19 @@ static u32 retrieve32bits(PgHdr *p, int offset){
}
/*
** Convert the bits in the pPager->errMask into an approprate
** return code.
*/
static int pager_errcode(Pager *pPager){
int rc = SQLITE_OK;
if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL;
if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR;
if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL;
if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;
return rc;
}
/*
** This function should be called when an error occurs within the pager
** code to set the appropriate bits in Pager.errMask.
** code to set Pager.errCode.
*/
static int pager_error(Pager *pPager, int rc){
switch( rc ){
case SQLITE_PROTOCOL:
pPager->errMask |= PAGER_ERR_LOCK;
break;
case SQLITE_IOERR:
pPager->errMask |= PAGER_ERR_DISK;
break;
case SQLITE_FULL:
pPager->errMask |= PAGER_ERR_FULL;
break;
case SQLITE_CORRUPT:
pPager->errMask |= PAGER_ERR_CORRUPT;
break;
assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK );
if(
rc==SQLITE_FULL ||
rc==SQLITE_IOERR ||
rc==SQLITE_CORRUPT ||
rc==SQLITE_PROTOCOL
){
pPager->errCode = rc;
}
return rc;
}
@ -537,7 +494,7 @@ static u32 pager_pagehash(PgHdr *pPage){
#define CHECK_PAGE(x) checkPage(x)
static void checkPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty ||
assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty ||
pPg->pageHash==pager_pagehash(pPg) );
}
@ -879,7 +836,7 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
*/
static void pager_reset(Pager *pPager){
PgHdr *pPg, *pNext;
if( pPager->errMask ) return;
if( pPager->errCode ) return;
for(pPg=pPager->pAll; pPg; pPg=pNext){
pNext = pPg->pNextAll;
sqliteFree(pPg);
@ -1500,8 +1457,7 @@ static int pager_stmt_playback(Pager *pPager){
end_stmt_playback:
if( rc!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_CORRUPT;
rc = SQLITE_CORRUPT;
rc = pager_error(pPager, SQLITE_CORRUPT);
}else{
pPager->journalOff = szJ;
/* pager_reload_cache(pPager); */
@ -1833,7 +1789,7 @@ int sqlite3pager_pagecount(Pager *pPager){
n = pPager->dbSize;
} else {
if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_DISK;
pager_error(pPager, SQLITE_IOERR);
return 0;
}
if( n>0 && n<pPager->pageSize ){
@ -1979,8 +1935,8 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
int rc;
sqlite3pager_pagecount(pPager);
if( pPager->errMask!=0 ){
rc = pager_errcode(pPager);
if( pPager->errCode ){
rc = pPager->errCode;
return rc;
}
if( nPage>=(unsigned)pPager->dbSize ){
@ -2043,7 +1999,7 @@ int sqlite3pager_close(Pager *pPager){
if( !MEMDB ){
sqlite3OsUnlock(pPager->fd, NO_LOCK);
}
assert( pPager->errMask || pPager->journalOpen==0 );
assert( pPager->errCode || pPager->journalOpen==0 );
break;
}
case PAGER_SHARED: {
@ -2070,7 +2026,7 @@ int sqlite3pager_close(Pager *pPager){
sqliteFree(pPg);
}
TRACE2("CLOSE %d\n", PAGERID(pPager));
assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
if( pPager->journalOpen ){
sqlite3OsClose(&pPager->jfd);
}
@ -2367,7 +2323,7 @@ static int hasHotJournal(Pager *pPager){
** Try to find a page in the cache that can be recycled.
**
** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It
** does not set the pPager->errMask variable.
** does not set the pPager->errCode variable.
*/
static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){
PgHdr *pPg;
@ -2512,7 +2468,7 @@ int sqlite3pager_release_memory(int nReq){
if( rc!=SQLITE_OK ){
/* An error occured whilst writing to the database file or
** journal in pager_recycle(). The error is not returned to the
** caller of this function. Instead, set the Pager.errMask variable.
** caller of this function. Instead, set the Pager.errCode variable.
** The error will be returned to the user (or users, in the case
** of a shared pager cache) of the pager for which the error occured.
*/
@ -2565,8 +2521,8 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
*/
assert( pPager!=0 );
*ppPage = 0;
if( pPager->errMask & ~(PAGER_ERR_FULL) ){
return pager_errcode(pPager);
if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
return pPager->errCode;
}
/* If this is the first page accessed, then get a SHARED lock
@ -2702,9 +2658,9 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
if( pPager->nExtra>0 ){
memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
}
if( pPager->errMask!=0 ){
if( pPager->errCode ){
sqlite3pager_unref(PGHDR_TO_DATA(pPg));
rc = pager_errcode(pPager);
rc = pPager->errCode;
return rc;
}
if( sqlite3pager_pagecount(pPager)<(int)pgno ){
@ -2761,7 +2717,7 @@ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){
assert( pPager!=0 );
assert( pgno!=0 );
if( pPager->errMask & ~(PAGER_ERR_FULL) ){
if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
return 0;
}
pPg = pager_lookup(pPager, pgno);
@ -2859,8 +2815,8 @@ static int pager_open_journal(Pager *pPager){
pPager->needSync = 0;
pPager->alwaysRollback = 0;
pPager->nRec = 0;
if( pPager->errMask!=0 ){
rc = pager_errcode(pPager);
if( pPager->errCode ){
rc = pPager->errCode;
goto failed_to_open_journal;
}
pPager->origDbSize = pPager->dbSize;
@ -2978,8 +2934,8 @@ int sqlite3pager_write(void *pData){
/* Check for errors
*/
if( pPager->errMask ){
return pager_errcode(pPager);
if( pPager->errCode ){
return pPager->errCode;
}
if( pPager->readOnly ){
return SQLITE_PERM;
@ -3053,7 +3009,9 @@ int sqlite3pager_write(void *pData){
*(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved;
if( rc!=SQLITE_OK ){
sqlite3pager_rollback(pPager);
pPager->errMask |= PAGER_ERR_FULL;
if( !pPager->errCode ){
pager_error(pPager, SQLITE_FULL);
}
return rc;
}
pPager->nRec++;
@ -3100,7 +3058,9 @@ int sqlite3pager_write(void *pData){
CODEC(pPager, pData, pPg->pgno, 0);
if( rc!=SQLITE_OK ){
sqlite3pager_rollback(pPager);
pPager->errMask |= PAGER_ERR_FULL;
if( !pPager->errCode ){
pager_error(pPager, SQLITE_FULL);
}
return rc;
}
pPager->stmtNRec++;
@ -3260,15 +3220,15 @@ int sqlite3pager_commit(Pager *pPager){
int rc;
PgHdr *pPg;
if( pPager->errMask==PAGER_ERR_FULL ){
if( pPager->errCode==SQLITE_FULL ){
rc = sqlite3pager_rollback(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
return rc;
}
if( pPager->errMask!=0 ){
rc = pager_errcode(pPager);
if( pPager->errCode ){
rc = pPager->errCode;
return rc;
}
if( pPager->state<PAGER_RESERVED ){
@ -3379,11 +3339,11 @@ int sqlite3pager_rollback(Pager *pPager){
return rc;
}
if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
if( pPager->state>=PAGER_EXCLUSIVE ){
pager_playback(pPager);
}
return pager_errcode(pPager);
return pPager->errCode;
}
if( pPager->state==PAGER_RESERVED ){
int rc2;
@ -3397,7 +3357,7 @@ int sqlite3pager_rollback(Pager *pPager){
}
if( rc!=SQLITE_OK ){
rc = SQLITE_CORRUPT_BKPT;
pPager->errMask |= PAGER_ERR_CORRUPT;
pager_error(pPager, SQLITE_CORRUPT);
}
pPager->dbSize = -1;
return rc;
@ -3421,7 +3381,7 @@ int *sqlite3pager_stats(Pager *pPager){
a[2] = pPager->mxPage;
a[3] = pPager->dbSize;
a[4] = pPager->state;
a[5] = pPager->errMask;
a[5] = pPager->errCode;
#ifdef SQLITE_TEST
a[6] = pPager->nHit;
a[7] = pPager->nMiss;

View File

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.22 2006/01/13 06:33:24 danielk1977 Exp $
** $Id: prepare.c,v 1.23 2006/01/16 11:29:20 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -495,6 +495,7 @@ int sqlite3_prepare(
int rc = SQLITE_OK;
int i;
/* Assert that malloc() has not failed */
assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
assert( ppStmt );

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.467 2006/01/13 06:33:24 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.468 2006/01/16 11:29:20 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -1754,7 +1754,7 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
#endif
void sqlite3MallocClearFailed();
#ifdef NDEBUG
#ifndef SQLITE_MEMDEBUG
#define sqlite3MallocDisallow()
#define sqlite3MallocAllow()
#else

View File

@ -156,7 +156,8 @@ int sqlite3_step(sqlite3_stmt *pStmt){
sqlite3 *db;
int rc;
assert(!sqlite3ThreadDataReadOnly()->mallocFailed);
/* Assert that malloc() has not failed */
assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;