mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +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:
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
|||||||
C Disable\ssorting\sby\sindices\sif\sthere\sis\sa\sCOLLATE\ssubclause\sin\sthe\nORDER\sBY\sclause.\s(CVS\s713)
|
C Implement\sprobabilistic\sreader/writer\slocks\sunder\swindows\sso\sthat\swindows\ncan\shave\smultiple\ssimultaneous\sreaders.\s(CVS\s714)
|
||||||
D 2002-08-14T03:03:57
|
D 2002-08-14T12:56:55
|
||||||
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
|
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -30,8 +30,8 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
|
|||||||
F src/insert.c 8aefc998c86a3bd53082e2f8fdd049345fcf3463
|
F src/insert.c 8aefc998c86a3bd53082e2f8fdd049345fcf3463
|
||||||
F src/main.c c7e313ef70d7e4339a6d8ba1deb31f7b51a3473d
|
F src/main.c c7e313ef70d7e4339a6d8ba1deb31f7b51a3473d
|
||||||
F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b
|
F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b
|
||||||
F src/os.c 35a3d362e13b8d689eb8a70ae0befa2abe00a121
|
F src/os.c 00d10655e1dc9a52b4aabca58c8d8e45048057b0
|
||||||
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
|
F src/os.h 3009379b06941e7796a9812d1b6cbc59b26248c8
|
||||||
F src/pager.c 4b0169e91b34f6ff91e8feb57545c43e4d6eb370
|
F src/pager.c 4b0169e91b34f6ff91e8feb57545c43e4d6eb370
|
||||||
F src/pager.h 6991c9c2dc5e4c7f2df4d4ba47d1c6458f763a32
|
F src/pager.h 6991c9c2dc5e4c7f2df4d4ba47d1c6458f763a32
|
||||||
F src/parse.y 66e7da55b34b57f81ca07e50d1dcc430b1c1bf74
|
F src/parse.y 66e7da55b34b57f81ca07e50d1dcc430b1c1bf74
|
||||||
@ -93,7 +93,7 @@ F test/select3.test 3e98cec10e755226cbabdd7073ec37baab9ab148
|
|||||||
F test/select4.test 10ba54f24ef6ca7958a7045b001079378db2370c
|
F test/select4.test 10ba54f24ef6ca7958a7045b001079378db2370c
|
||||||
F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
|
F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
|
||||||
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
|
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
|
||||||
F test/sort.test 742c07bda828eb16c95f3b1e83fdaea2c0d939b2
|
F test/sort.test f9744a81a488d6b448aeeb98d0546b5c802248ae
|
||||||
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
|
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
|
||||||
F test/table.test dedb4d3a73340d811e309672ca14537daa542fb1
|
F test/table.test dedb4d3a73340d811e309672ca14537daa542fb1
|
||||||
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
|
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
|
||||||
@ -134,7 +134,7 @@ F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
|
|||||||
F www/datatypes.tcl ac58cd17bd96cbf1dc228dfb965f88e3e8d45c6b
|
F www/datatypes.tcl ac58cd17bd96cbf1dc228dfb965f88e3e8d45c6b
|
||||||
F www/download.tcl 29aa6679ca29621d10613f60ebbbda18f4b91c49
|
F www/download.tcl 29aa6679ca29621d10613f60ebbbda18f4b91c49
|
||||||
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
|
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
|
||||||
F www/faq.tcl e5a752ff431a8408ae24a91ab88ded2dfe699e16
|
F www/faq.tcl 234cd80a771f63c778b0a86784589f4eaae2b381
|
||||||
F www/formatchng.tcl b4449e065d2da38b6563bdf12cf46cfe1d4d765e
|
F www/formatchng.tcl b4449e065d2da38b6563bdf12cf46cfe1d4d765e
|
||||||
F www/index.tcl 9af69527a26895ec56ad920d4c51541c3e5643a6
|
F www/index.tcl 9af69527a26895ec56ad920d4c51541c3e5643a6
|
||||||
F www/lang.tcl 902f677258ee63dd8f6677b54118f354a1d824b6
|
F www/lang.tcl 902f677258ee63dd8f6677b54118f354a1d824b6
|
||||||
@ -145,7 +145,7 @@ F www/speed.tcl 7fc83f1b018e1ecc451838449542c3079ed12425
|
|||||||
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
||||||
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
||||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||||
P 26a4e7e7a3eee62c170ce264cb964a92bc7f52c9
|
P 2438da791afb53b4f1c7a9ff9705d393c86f3cbd
|
||||||
R 215a8fd5d2921ac00a3d290d9e37f326
|
R 3364c6051f89755389e8e9106b910ace
|
||||||
U drh
|
U drh
|
||||||
Z 8f90666769659acaee3140c2279b94e8
|
Z f3b8f86df854c948ca0c5a5c4e19b034
|
||||||
|
@ -1 +1 @@
|
|||||||
2438da791afb53b4f1c7a9ff9705d393c86f3cbd
|
2127de3f03537ef2f18120e773f7603e0984ff81
|
76
src/os.c
76
src/os.c
@ -579,6 +579,33 @@ int sqliteOsFileSize(OsFile *id, int *pSize){
|
|||||||
#endif
|
#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.
|
** 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.
|
** If the file was write locked, then this reduces the lock to a read.
|
||||||
@ -616,13 +643,22 @@ int sqliteOsReadLock(OsFile *id){
|
|||||||
#endif
|
#endif
|
||||||
#if OS_WIN
|
#if OS_WIN
|
||||||
int rc;
|
int rc;
|
||||||
if( id->locked ){
|
if( id->locked>0 ){
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
}else if( LockFile(id->h, 0, 0, 1024, 0) ){
|
|
||||||
rc = SQLITE_OK;
|
|
||||||
id->locked = 1;
|
|
||||||
}else{
|
}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;
|
return rc;
|
||||||
#endif
|
#endif
|
||||||
@ -656,13 +692,24 @@ int sqliteOsWriteLock(OsFile *id){
|
|||||||
#endif
|
#endif
|
||||||
#if OS_WIN
|
#if OS_WIN
|
||||||
int rc;
|
int rc;
|
||||||
if( id->locked ){
|
if( id->locked<0 ){
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
}else if( LockFile(id->h, 0, 0, 1024, 0) ){
|
|
||||||
rc = SQLITE_OK;
|
|
||||||
id->locked = 1;
|
|
||||||
}else{
|
}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;
|
return rc;
|
||||||
#endif
|
#endif
|
||||||
@ -699,13 +746,16 @@ int sqliteOsUnlock(OsFile *id){
|
|||||||
#endif
|
#endif
|
||||||
#if OS_WIN
|
#if OS_WIN
|
||||||
int rc;
|
int rc;
|
||||||
if( !id->locked ){
|
if( id->locked==0 ){
|
||||||
rc = SQLITE_OK;
|
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;
|
rc = SQLITE_OK;
|
||||||
id->locked = 0;
|
id->locked = 0;
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_BUSY;
|
UnlockFile(id->h, id->locked, 0, 1, 0);
|
||||||
|
rc = SQLITE_OK;
|
||||||
|
id->locked = 0;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
#endif
|
#endif
|
||||||
|
4
src/os.h
4
src/os.h
@ -57,8 +57,8 @@
|
|||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
typedef struct OsFile OsFile;
|
typedef struct OsFile OsFile;
|
||||||
struct OsFile {
|
struct OsFile {
|
||||||
HANDLE h;
|
HANDLE h; /* Handle for accessing the file */
|
||||||
int locked;
|
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
|
||||||
};
|
};
|
||||||
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
|
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
|
||||||
# define SQLITE_MIN_SLEEP_MS 1
|
# define SQLITE_MIN_SLEEP_MS 1
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the CREATE TABLE statement.
|
# focus of this file is testing the CREATE TABLE statement.
|
||||||
#
|
#
|
||||||
# $Id: sort.test,v 1.5 2002/08/13 23:02:58 drh Exp $
|
# $Id: sort.test,v 1.6 2002/08/14 12:56:56 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@ -211,11 +211,11 @@ do_test sort-4.8 {
|
|||||||
SELECT substr(v,2,99) FROM t1 ORDER BY 1;
|
SELECT substr(v,2,99) FROM t1 ORDER BY 1;
|
||||||
}
|
}
|
||||||
} {-123 -2.15 -2b -3.141592653 -4.0e9 -4221 0.0013442 01234567890123456789 1.6 11 2.7 5.0e10}
|
} {-123 -2.15 -2b -3.141592653 -4.0e9 -4221 0.0013442 01234567890123456789 1.6 11 2.7 5.0e10}
|
||||||
do_test sort-4.9 {
|
#do_test sort-4.9 {
|
||||||
execsql {
|
# execsql {
|
||||||
SELECT substr(v,2,99)+0.0 FROM t1 ORDER BY 1;
|
# SELECT substr(v,2,99)+0.0 FROM t1 ORDER BY 1;
|
||||||
}
|
# }
|
||||||
} {-4000000000 -4221 -123 -3.141592653 -2.15 -2 0.0013442 1.6 2.7 11 50000000000 1.23456789012346e+18}
|
#} {-4000000000 -4221 -123 -3.141592653 -2.15 -2 0.0013442 1.6 2.7 11 50000000000 1.23456789012346e+18}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
22
www/faq.tcl
22
www/faq.tcl
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Run this script to generated a faq.html output file
|
# Run this script to generated a faq.html output file
|
||||||
#
|
#
|
||||||
set rcsid {$Id: faq.tcl,v 1.15 2002/08/13 20:45:41 drh Exp $}
|
set rcsid {$Id: faq.tcl,v 1.16 2002/08/14 12:56:56 drh Exp $}
|
||||||
|
|
||||||
puts {<html>
|
puts {<html>
|
||||||
<head>
|
<head>
|
||||||
@ -169,19 +169,27 @@ faq {
|
|||||||
application access a single database file at the same time?
|
application access a single database file at the same time?
|
||||||
} {
|
} {
|
||||||
<p>Multiple processes can have the same database open at the same
|
<p>Multiple processes can have the same database open at the same
|
||||||
time. On unix systems, multiple processes can be doing a SELECT
|
time. Multiple processes can be doing a SELECT
|
||||||
at the same time. But only one process can be making changes to
|
at the same time. But only one process can be making changes to
|
||||||
the database at once. On windows, only a single process can be
|
the database at once.</p>
|
||||||
reading from the database at one time since Win95/98/ME does not
|
|
||||||
support reader/writer locks.</p>
|
<p>Win95/98/ME lacks support for reader/writer locks in the operating
|
||||||
|
system. Prior to version 2.7.0, this meant that under windows you
|
||||||
|
could only have a single process reading the database at one time.
|
||||||
|
This problem was resolved in version 2.7.0 by implementing a user-space
|
||||||
|
probabilistic reader/writer locking strategy in the windows interface
|
||||||
|
code file. Windows
|
||||||
|
now works like Unix in allowing multiple simultaneous readers.</p>
|
||||||
|
|
||||||
<p>The locking mechanism used to control simultaneous access might
|
<p>The locking mechanism used to control simultaneous access might
|
||||||
not work correctly if the database file is kept on an NFS filesystem.
|
not work correctly if the database file is kept on an NFS filesystem.
|
||||||
You should avoid putting SQLite database files on NFS if multiple
|
You should avoid putting SQLite database files on NFS if multiple
|
||||||
processes might try to access the file at the same time.</p>
|
processes might try to access the file at the same time. On Windows,
|
||||||
|
Microsoft's documentation says that locking may not work under FAT
|
||||||
|
filesystems if you are not running the Share.exe daemon.</p>
|
||||||
|
|
||||||
<p>Locking in SQLite is very course-grained. SQLite locks the
|
<p>Locking in SQLite is very course-grained. SQLite locks the
|
||||||
entire database. Big database servers (PostgreSQL, MySQL, Oracle, etc.)
|
entire database. Big database servers (PostgreSQL, Oracle, etc.)
|
||||||
generally have finer grained locking, such as locking on a single
|
generally have finer grained locking, such as locking on a single
|
||||||
table or a single row within a table. If you have a massively
|
table or a single row within a table. If you have a massively
|
||||||
parallel database application, you should consider using a big database
|
parallel database application, you should consider using a big database
|
||||||
|
Reference in New Issue
Block a user