1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Fixes to the OsUnlock() interface. Correctly leave a SHARED lock behind

when requested.  Honor the error code that OsUnlock() returns.
Ticket #913 and #938. (CVS 1997)

FossilOrigin-Name: c4697503d0ad080290b91e96dfc9a1a63f2df7e6
This commit is contained in:
drh
2004-10-02 20:38:28 +00:00
parent 0924bba36c
commit 9c105bb990
5 changed files with 61 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
C make\sdiskfull\stest\swork\son\sWindows;\ssee\scheck-in\s(1994)\s(CVS\s1996) C Fixes\sto\sthe\sOsUnlock()\sinterface.\s\sCorrectly\sleave\sa\sSHARED\slock\sbehind\nwhen\srequested.\s\sHonor\sthe\serror\scode\sthat\sOsUnlock()\sreturns.\nTicket\s#913\sand\s#938.\s(CVS\s1997)
D 2004-10-01T18:21:43 D 2004-10-02T20:38:28
F Makefile.in abdeb5bd9d017822691884935c320037c33f6ee6 F Makefile.in abdeb5bd9d017822691884935c320037c33f6ee6
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -47,11 +47,11 @@ F src/os_mac.c 7367dab0c44ab0b2c4337e73ac6f6f97f171c2cb
F src/os_mac.h 608fdf39eafa1ce25fc8cb223b8b0a073341d4da F src/os_mac.h 608fdf39eafa1ce25fc8cb223b8b0a073341d4da
F src/os_test.c d9a21852d170f20adeae6f224d1beba2cb5af8aa F src/os_test.c d9a21852d170f20adeae6f224d1beba2cb5af8aa
F src/os_test.h 6a26a4978492e4bbdbf385554958418ff02db162 F src/os_test.h 6a26a4978492e4bbdbf385554958418ff02db162
F src/os_unix.c ca7891d1f84994559899ced37b45541a68028282 F src/os_unix.c 5c1f362846afec4232c2291b9f1564f0487e91f4
F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
F src/os_win.c 2b4b103d978daa5efb6ccb11703976429e0aad84 F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 39e0ad16ffb94fecf3dc9fd73bccf3e7445f0e17 F src/pager.c d3688828d314135ef0cd87b4d892805136c4168f
F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71
F src/parse.y 968231351dd13ef6ee544336295db54708c22faf F src/parse.y 968231351dd13ef6ee544336295db54708c22faf
F src/pragma.c 45978cc82fdf91f00d024a8e875c2b679fbce488 F src/pragma.c 45978cc82fdf91f00d024a8e875c2b679fbce488
@@ -248,7 +248,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 44e56f0bba61245d342d6e75510d6c35785efd49 P 4493e287809874fabeddf5ca9045065a30790f2f
R a61ce3be739beac85c756189a58b0ec2 R ebf4aac4c1a61ea57872e563bbdb1393
U dougcurrie U drh
Z 4de85fdbce139eac43154165436a4c4e Z 44aded0ba9c92340348fe0ad36d9356d

View File

@@ -1 +1 @@
4493e287809874fabeddf5ca9045065a30790f2f c4697503d0ad080290b91e96dfc9a1a63f2df7e6

View File

@@ -1021,11 +1021,14 @@ end_lock:
** If the locking level of the file descriptor is already at or below ** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op. ** the requested locking level, this routine is a no-op.
** **
** It is not possible for this routine to fail. ** It is not possible for this routine to fail if the second argument
** is NO_LOCK. If the second argument is SHARED_LOCK, this routine
** might return SQLITE_IOERR instead of SQLITE_OK.
*/ */
int sqlite3OsUnlock(OsFile *id, int locktype){ int sqlite3OsUnlock(OsFile *id, int locktype){
struct lockInfo *pLock; struct lockInfo *pLock;
struct flock lock; struct flock lock;
int rc = SQLITE_OK;
assert( id->isOpen ); assert( id->isOpen );
TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype,
@@ -1040,11 +1043,16 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
assert( pLock->cnt!=0 ); assert( pLock->cnt!=0 );
if( id->locktype>SHARED_LOCK ){ if( id->locktype>SHARED_LOCK ){
assert( pLock->locktype==id->locktype ); assert( pLock->locktype==id->locktype );
lock.l_type = F_RDLCK; if( locktype==SHARED_LOCK ){
lock.l_whence = SEEK_SET; lock.l_type = F_RDLCK;
lock.l_start = SHARED_FIRST; lock.l_whence = SEEK_SET;
lock.l_len = SHARED_SIZE; lock.l_start = SHARED_FIRST;
fcntl(id->h, F_SETLK, &lock); lock.l_len = SHARED_SIZE;
if( fcntl(id->h, F_SETLK, &lock)!=0 ){
/* This should never happen */
rc = SQLITE_IOERR;
}
}
lock.l_type = F_UNLCK; lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET; lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE; lock.l_start = PENDING_BYTE;
@@ -1087,7 +1095,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
} }
sqlite3OsLeaveMutex(); sqlite3OsLeaveMutex();
id->locktype = locktype; id->locktype = locktype;
return SQLITE_OK; return rc;
} }
/* /*

View File

@@ -375,20 +375,23 @@ static int isNT(void){
} }
/* /*
** Acquire a reader lock on the range of bytes from iByte...iByte+nByte-1. ** Acquire a reader lock.
** Different API routines are called depending on whether or not this ** Different API routines are called depending on whether or not this
** is Win95 or WinNT. ** is Win95 or WinNT.
*/ */
static int getReadLock(HANDLE h, unsigned int iByte, unsigned int nByte){ static int getReadLock(OsFile *id){
int res; int res;
if( isNT() ){ if( isNT() ){
OVERLAPPED ovlp; OVERLAPPED ovlp;
ovlp.Offset = iByte; ovlp.Offset = SHARED_FIRST;
ovlp.OffsetHigh = 0; ovlp.OffsetHigh = 0;
ovlp.hEvent = 0; ovlp.hEvent = 0;
res = LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY, 0, nByte, 0, &ovlp); res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp);
}else{ }else{
res = LockFile(h, iByte, 0, nByte, 0); int lk;
sqlite3Randomness(sizeof(lk), &lk);
id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
} }
return res; return res;
} }
@@ -479,14 +482,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
*/ */
if( locktype==SHARED_LOCK && res ){ if( locktype==SHARED_LOCK && res ){
assert( id->locktype==NO_LOCK ); assert( id->locktype==NO_LOCK );
if( isNT() ){ res = getReadLock(id);
res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE);
}else{
int lk;
sqlite3Randomness(sizeof(lk), &lk);
id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
}
if( res ){ if( res ){
newLocktype = SHARED_LOCK; newLocktype = SHARED_LOCK;
} }
@@ -573,10 +569,13 @@ int sqlite3OsCheckReservedLock(OsFile *id){
** If the locking level of the file descriptor is already at or below ** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op. ** the requested locking level, this routine is a no-op.
** **
** It is not possible for this routine to fail. ** It is not possible for this routine to fail if the second argument
** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
** might return SQLITE_IOERR;
*/ */
int sqlite3OsUnlock(OsFile *id, int locktype){ int sqlite3OsUnlock(OsFile *id, int locktype){
int rc, type; int type;
int rc = SQLITE_OK;
assert( id->isOpen ); assert( id->isOpen );
assert( locktype<=SHARED_LOCK ); assert( locktype<=SHARED_LOCK );
TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype,
@@ -584,18 +583,23 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
type = id->locktype; type = id->locktype;
if( type>=EXCLUSIVE_LOCK ){ if( type>=EXCLUSIVE_LOCK ){
UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
if( locktype==SHARED_LOCK && !getReadLock(id) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
rc = SQLITE_IOERR;
}
} }
if( type>=RESERVED_LOCK ){ if( type>=RESERVED_LOCK ){
UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
} }
if( locktype==NO_LOCK && type>=SHARED_LOCK && type<EXCLUSIVE_LOCK ){ if( locktype==NO_LOCK && type>=SHARED_LOCK ){
unlockReadLock(id); unlockReadLock(id);
} }
if( type>=PENDING_LOCK ){ if( type>=PENDING_LOCK ){
UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
} }
id->locktype = locktype; id->locktype = locktype;
return SQLITE_OK; return rc;
} }
/* /*

View File

@@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while ** file simultaneously, or one process from reading the database while
** another is writing. ** another is writing.
** **
** @(#) $Id: pager.c,v 1.165 2004/10/01 02:00:31 drh Exp $ ** @(#) $Id: pager.c,v 1.166 2004/10/02 20:38:28 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@@ -755,6 +755,7 @@ static void pager_reset(Pager *pPager){
*/ */
static int pager_unwritelock(Pager *pPager){ static int pager_unwritelock(Pager *pPager){
PgHdr *pPg; PgHdr *pPg;
int rc;
assert( !pPager->memDb ); assert( !pPager->memDb );
if( pPager->state<PAGER_RESERVED ){ if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK; return SQLITE_OK;
@@ -780,11 +781,11 @@ static int pager_unwritelock(Pager *pPager){
}else{ }else{
assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
} }
sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
pPager->state = PAGER_SHARED; pPager->state = PAGER_SHARED;
pPager->origDbSize = 0; pPager->origDbSize = 0;
pPager->setMaster = 0; pPager->setMaster = 0;
return SQLITE_OK; return rc;
} }
/* /*
@@ -2342,20 +2343,15 @@ static int pager_open_journal(Pager *pPager){
sqlite3pager_pagecount(pPager); sqlite3pager_pagecount(pPager);
pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
if( pPager->aInJournal==0 ){ if( pPager->aInJournal==0 ){
sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); rc = SQLITE_NOMEM;
pPager->state = PAGER_SHARED; goto failed_to_open_journal;
return SQLITE_NOMEM;
} }
rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile);
pPager->journalOff = 0; pPager->journalOff = 0;
pPager->setMaster = 0; pPager->setMaster = 0;
pPager->journalHdr = 0; pPager->journalHdr = 0;
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
sqliteFree(pPager->aInJournal); goto failed_to_open_journal;
pPager->aInJournal = 0;
sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
pPager->state = PAGER_SHARED;
return rc;
} }
sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd); sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd);
pPager->journalOpen = 1; pPager->journalOpen = 1;
@@ -2380,7 +2376,14 @@ static int pager_open_journal(Pager *pPager){
rc = SQLITE_FULL; rc = SQLITE_FULL;
} }
} }
return rc; return rc;
failed_to_open_journal:
sqliteFree(pPager->aInJournal);
pPager->aInJournal = 0;
sqlite3OsUnlock(&pPager->fd, NO_LOCK);
pPager->state = PAGER_UNLOCK;
return rc;
} }
/* /*