diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/os_common.h | 20 | ||||
-rw-r--r-- | src/os_unix.c | 57 | ||||
-rw-r--r-- | src/pager.c | 18 | ||||
-rw-r--r-- | src/test2.c | 5 |
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", |