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

Implement probabilistic reader/writer locks under windows so that windows

can have multiple simultaneous readers. (CVS 714)

FossilOrigin-Name: 2127de3f03537ef2f18120e773f7603e0984ff81
This commit is contained in:
drh
2002-08-14 12:56:54 +00:00
parent c330af1dca
commit d1efac52d5
6 changed files with 96 additions and 38 deletions

View File

@@ -579,6 +579,33 @@ int sqliteOsFileSize(OsFile *id, int *pSize){
#endif
}
/*
** Windows file locking notes:
**
** We cannot use LockFileEx() or UnlockFileEx() because those functions
** are not available under Win95/98/ME. So we use only LockFile() and
** UnlockFile().
**
** A read lock is obtained by locking a single random byte in the
** range of 1 to MX_LOCKBYTE. The lock byte is obtained at random so
** two separate readers can probably access the file at the same time,
** unless they are unlucky and choose the same lock byte. A write lock
** is obtained by locking all bytes in the range of 1 to MX_LOCKBYTE.
** There can only be one writer.
**
** A lock is obtained on byte 0 before acquiring either a read lock or
** a write lock. This prevents two processes from attempting to get a
** lock at a same time. The semantics of sqliteOsReadLock() require that
** if there is already a write lock, that lock is converted into a read
** lock atomically. The lock on byte 0 allows us to drop the old write
** lock and get the read lock without another process jumping into the
** middle and messing us up. The same argument applies to sqliteOsWriteLock().
**
** There are a finite number of read locks under windows. That number
** is determined by the following variable:
*/
#define MX_LOCKBYTE 10240
/*
** Change the status of the lock on the file "id" to be a readlock.
** If the file was write locked, then this reduces the lock to a read.
@@ -616,13 +643,22 @@ int sqliteOsReadLock(OsFile *id){
#endif
#if OS_WIN
int rc;
if( id->locked ){
if( id->locked>0 ){
rc = SQLITE_OK;
}else if( LockFile(id->h, 0, 0, 1024, 0) ){
rc = SQLITE_OK;
id->locked = 1;
}else{
rc = SQLITE_BUSY;
int lk = (sqliteRandomInteger() & 0x7ffffff)%MX_LOCKBYTE + 1;
int res;
if( (res = LockFile(id->h, 0, 0, 1, 0))!=0 ){
UnlockFile(id->h, 1, 0, MX_LOCKBYTE, 0);
res = LockFile(id->h, lk, 0, 1, 0);
UnlockFile(id->h, 0, 0, 1, 0);
}
if( res ){
id->locked = lk;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
}
return rc;
#endif
@@ -656,13 +692,24 @@ int sqliteOsWriteLock(OsFile *id){
#endif
#if OS_WIN
int rc;
if( id->locked ){
if( id->locked<0 ){
rc = SQLITE_OK;
}else if( LockFile(id->h, 0, 0, 1024, 0) ){
rc = SQLITE_OK;
id->locked = 1;
}else{
rc = SQLITE_BUSY;
int res;
if( (res = LockFile(id->h, 0, 0, 1, 0))!=0 ){
if( id->locked==0 || UnlockFile(id->h, id->locked, 0, 1, 0) ){
res = LockFile(id->h, 1, 0, MX_LOCKBYTE, 0);
}else{
res = 0;
}
UnlockFile(id->h, 0, 0, 1, 0);
}
if( res ){
id->locked = -1;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
}
return rc;
#endif
@@ -699,13 +746,16 @@ int sqliteOsUnlock(OsFile *id){
#endif
#if OS_WIN
int rc;
if( !id->locked ){
if( id->locked==0 ){
rc = SQLITE_OK;
}else if( UnlockFile(id->h, 0, 0, 1024, 0) ){
}else if( id->locked<0 ){
UnlockFile(id->h, 1, 0, MX_LOCKBYTE, 0);
rc = SQLITE_OK;
id->locked = 0;
}else{
rc = SQLITE_BUSY;
UnlockFile(id->h, id->locked, 0, 1, 0);
rc = SQLITE_OK;
id->locked = 0;
}
return rc;
#endif