aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/os_common.h20
-rw-r--r--src/os_unix.c57
-rw-r--r--src/pager.c18
-rw-r--r--src/test2.c5
4 files changed, 66 insertions, 34 deletions
diff --git a/src/os_common.h b/src/os_common.h
index 1efc61c53..26ea7d6af 100644
--- a/src/os_common.h
+++ b/src/os_common.h
@@ -86,19 +86,22 @@ static unsigned int elapse;
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
-int sqlite3_io_error_hit = 0;
-int sqlite3_io_error_pending = 0;
-int sqlite3_io_error_persist = 0;
+int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+int sqlite3_io_error_benign = 0; /* True if errors are benign */
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
#define SimulateIOError(CODE) \
- if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
- if( sqlite3_io_error_pending-- == 1 \
- || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
- { local_ioerr(); CODE; }
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+ || sqlite3_io_error_pending-- == 1 ) \
+ { local_ioerr(); CODE; }
static void local_ioerr(){
IOTRACE(("IOERR\n"));
- sqlite3_io_error_hit = 1;
+ sqlite3_io_error_hit++;
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
}
#define SimulateDiskfullError(CODE) \
if( sqlite3_diskfull_pending ){ \
@@ -112,6 +115,7 @@ static void local_ioerr(){
} \
}
#else
+#define SimulateIOErrorBenign(X)
#define SimulateIOError(A)
#define SimulateDiskfullError(A)
#endif
diff --git a/src/os_unix.c b/src/os_unix.c
index df30a1cc2..47f3020c7 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1326,6 +1326,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
struct flock lock;
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
+ int h;
assert( pFile );
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
@@ -1339,17 +1340,20 @@ static int unixUnlock(sqlite3_file *id, int locktype){
return SQLITE_MISUSE;
}
enterMutex();
+ h = pFile->h;
pLock = pFile->pLock;
assert( pLock->cnt!=0 );
if( pFile->locktype>SHARED_LOCK ){
assert( pLock->locktype==pFile->locktype );
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
if( locktype==SHARED_LOCK ){
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){
- /* This should never happen */
+ if( fcntl(h, F_SETLK, &lock)==(-1) ){
rc = SQLITE_IOERR_RDLOCK;
}
}
@@ -1357,10 +1361,10 @@ static int unixUnlock(sqlite3_file *id, int locktype){
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
- if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
+ if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = SHARED_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK;
}
}
if( locktype==NO_LOCK ){
@@ -1375,10 +1379,14 @@ static int unixUnlock(sqlite3_file *id, int locktype){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
- if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
+ if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = NO_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK;
+ pLock->cnt = 1;
}
}
@@ -1386,21 +1394,23 @@ static int unixUnlock(sqlite3_file *id, int locktype){
** count reaches zero, close any other file descriptors whose close
** was deferred because of outstanding locks.
*/
- pOpen = pFile->pOpen;
- pOpen->nLock--;
- assert( pOpen->nLock>=0 );
- if( pOpen->nLock==0 && pOpen->nPending>0 ){
- int i;
- for(i=0; i<pOpen->nPending; i++){
- close(pOpen->aPending[i]);
+ if( rc==SQLITE_OK ){
+ pOpen = pFile->pOpen;
+ pOpen->nLock--;
+ assert( pOpen->nLock>=0 );
+ if( pOpen->nLock==0 && pOpen->nPending>0 ){
+ int i;
+ for(i=0; i<pOpen->nPending; i++){
+ close(pOpen->aPending[i]);
+ }
+ free(pOpen->aPending);
+ pOpen->nPending = 0;
+ pOpen->aPending = 0;
}
- free(pOpen->aPending);
- pOpen->nPending = 0;
- pOpen->aPending = 0;
}
}
leaveMutex();
- pFile->locktype = locktype;
+ if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
@@ -1454,8 +1464,8 @@ static int unixClose(sqlite3_file *id){
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
- unsigned long long sharedLockByte; /* Byte offset of shared lock byte */
- const char *filePath; /* Name of the file */
+ unsigned long long sharedLockByte;
+ char *filePath;
};
struct ByteRangeLockPB2
@@ -1752,7 +1762,9 @@ static int afpUnixClose(sqlite3_file *id) {
sqlite3_free(pFile->lockingContext);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
@@ -1843,7 +1855,10 @@ static int flockUnixClose(sqlite3_file *id) {
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
@@ -1953,7 +1968,9 @@ static int dotlockUnixClose(sqlite3_file *id) {
sqlite3_free(pFile->lockingContext);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
@@ -1989,7 +2006,9 @@ static int nolockUnixClose(sqlite3_file *id) {
if( !pFile ) return SQLITE_OK;
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
diff --git a/src/pager.c b/src/pager.c
index 9f0030aa1..18fcda129 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.412 2008/02/26 18:40:12 drh Exp $
+** @(#) $Id: pager.c,v 1.413 2008/03/07 19:51:14 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
@@ -1241,9 +1241,8 @@ static void pager_reset(Pager *pPager){
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
if( !MEMDB ){
- if( pPager->fd->pMethods ){
- osUnlock(pPager->fd, NO_LOCK);
- }
+ int rc = osUnlock(pPager->fd, NO_LOCK);
+ if( rc ) pager_error(pPager, rc);
pPager->dbSize = -1;
IOTRACE(("UNLOCK %p\n", pPager))
@@ -1252,7 +1251,7 @@ static void pager_unlock(Pager *pPager){
** cache can be discarded and the error code safely cleared.
*/
if( pPager->errCode ){
- pPager->errCode = SQLITE_OK;
+ if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
pager_reset(pPager);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
@@ -3384,7 +3383,14 @@ static int pagerSharedLock(Pager *pPager){
}
if( rc!=SQLITE_OK ){
pager_unlock(pPager);
- return ((rc==SQLITE_NOMEM||rc==SQLITE_IOERR_NOMEM)?rc:SQLITE_BUSY);
+ switch( rc ){
+ case SQLITE_NOMEM:
+ case SQLITE_IOERR_UNLOCK:
+ case SQLITE_IOERR_NOMEM:
+ return rc;
+ default:
+ return SQLITE_BUSY;
+ }
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
diff --git a/src/test2.c b/src/test2.c
index 4d7031dbc..153806cde 100644
--- a/src/test2.c
+++ b/src/test2.c
@@ -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.53 2008/02/18 14:47:34 drh Exp $
+** $Id: test2.c,v 1.54 2008/03/07 19:51:14 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -666,6 +666,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
extern int sqlite3_io_error_persist;
extern int sqlite3_io_error_pending;
extern int sqlite3_io_error_hit;
+ extern int sqlite3_io_error_hardhit;
extern int sqlite3_diskfull_pending;
extern int sqlite3_diskfull;
extern int sqlite3_pager_n_sort_bucket;
@@ -708,6 +709,8 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
(char*)&sqlite3_io_error_persist, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_io_error_hit",
(char*)&sqlite3_io_error_hit, TCL_LINK_INT);
+ Tcl_LinkVar(interp, "sqlite_io_error_hardhit",
+ (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_diskfull_pending",
(char*)&sqlite3_diskfull_pending, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_diskfull",