A better fix for ticket #530 - one that is likely to work on unix
implementations in addition to linux. Also more tests for multi-thread locking added. (CVS 1138) FossilOrigin-Name: 7dddbeb586504de30c64a1e61614da447f18c8ba
This commit is contained in:
parent
a6064dcf3b
commit
acf01e7ddd
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Add\snew\sthread-testing\scode\sand\sfix\slocking\sunder\sLinux\sthreads.\s\sTicket\s#530.\s(CVS\s1137)
|
||||
D 2003-12-19T02:52:06
|
||||
C A\sbetter\sfix\sfor\sticket\s#530\s-\sone\sthat\sis\slikely\sto\swork\son\sunix\nimplementations\sin\saddition\sto\slinux.\s\sAlso\smore\stests\sfor\smulti-thread\nlocking\sadded.\s(CVS\s1138)
|
||||
D 2003-12-19T08:40:23
|
||||
F Makefile.in 5cb273b7d0e945d47ee8b9ad1c2a04ce79927d2d
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -38,7 +38,7 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
|
||||
F src/insert.c 01f66866f35c986eab4a57373ca689a3255ef2df
|
||||
F src/main.c 3dd3cae00bade294011da5a3cf9ff660a610c545
|
||||
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
||||
F src/os.c 000b62b95cad6e3518cb7b71ba9376be192b19dc
|
||||
F src/os.c 3460bc83541eb276a69723d8babb533559b09344
|
||||
F src/os.h 729395fefcca4b81ae056aa9ff67b72bb40dd9e0
|
||||
F src/pager.c ca24fced1ca4c2b8ea519d5fe8ec69a2d846276f
|
||||
F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
|
||||
@ -130,7 +130,7 @@ F test/tableapi.test d881e787779a175238b72f55b5e50d3a85ab47a6
|
||||
F test/tclsqlite.test f141303e0f2e9a616b551813e2b21bd38c5dca50
|
||||
F test/temptable.test c82bd6f800f10e8cf96921af6315e5f1c21e2692
|
||||
F test/tester.tcl 2671536d3650c29e7c105219f277568b0884cb58
|
||||
F test/thread1.test e98de6574910978017a621d0851fda13e257763d
|
||||
F test/thread1.test 0c1fcc2f9bdd887225e56f48db8ddfbb3d0794ba
|
||||
F test/trans.test 75e7a171b5d2d94ee56766459113e2ad0e5f809d
|
||||
F test/trigger1.test 3fe06daecf8334df840025e154e95fd4727600d7
|
||||
F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263
|
||||
@ -179,7 +179,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
|
||||
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
P 80b1e277123c07b2db7441a9e600dd69ef55a0da
|
||||
R ea1fab6d3d994f942c20af002987010c
|
||||
P b36a4bb61094d539273c21a9e4042384f10a7806
|
||||
R de39b8252b64bbe001153a824a71610f
|
||||
U drh
|
||||
Z b3907cc74f1a3c0fe5cfc79f0eafa427
|
||||
Z 22268d4d15b83af3c4ce1b4c3335ae45
|
||||
|
@ -1 +1 @@
|
||||
b36a4bb61094d539273c21a9e4042384f10a7806
|
||||
7dddbeb586504de30c64a1e61614da447f18c8ba
|
21
src/os.c
21
src/os.c
@ -168,14 +168,15 @@ static unsigned int elapse;
|
||||
|
||||
/*
|
||||
** An instance of the following structure serves as the key used
|
||||
** to locate a particular lockInfo structure given its inode.
|
||||
** to locate a particular lockInfo structure given its inode. Note
|
||||
** that we have to include the process ID as part of the key. On some
|
||||
** threading implementations (ex: linux), each thread has a separate
|
||||
** process ID.
|
||||
*/
|
||||
struct inodeKey {
|
||||
struct lockKey {
|
||||
dev_t dev; /* Device number */
|
||||
ino_t ino; /* Inode number */
|
||||
#ifdef SQLITE_UNIX_THREADS
|
||||
pthread_t thread_id; /* Which thread are we */
|
||||
#endif
|
||||
pid_t pid; /* Process ID */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -185,13 +186,13 @@ struct inodeKey {
|
||||
** object keeps a count of the number of OsFiles pointing to it.
|
||||
*/
|
||||
struct lockInfo {
|
||||
struct inodeKey key; /* The lookup key */
|
||||
struct lockKey key; /* The lookup key */
|
||||
int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */
|
||||
int nRef; /* Number of pointers to this structure */
|
||||
};
|
||||
|
||||
/*
|
||||
** This hash table maps inodes (in the form of inodeKey structures) into
|
||||
** This hash table maps inodes (in the form of lockKey structures) into
|
||||
** pointers to lockInfo structures.
|
||||
*/
|
||||
static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
|
||||
@ -203,7 +204,7 @@ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
|
||||
*/
|
||||
static struct lockInfo *findLockInfo(int fd){
|
||||
int rc;
|
||||
struct inodeKey key;
|
||||
struct lockKey key;
|
||||
struct stat statbuf;
|
||||
struct lockInfo *pInfo;
|
||||
rc = fstat(fd, &statbuf);
|
||||
@ -211,9 +212,7 @@ static struct lockInfo *findLockInfo(int fd){
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.dev = statbuf.st_dev;
|
||||
key.ino = statbuf.st_ino;
|
||||
#ifdef SQLITE_UNIX_THREADS
|
||||
key.thread_id = pthread_self();
|
||||
#endif
|
||||
key.pid = getpid();
|
||||
pInfo = (struct lockInfo*)sqliteHashFind(&lockHash, &key, sizeof(key));
|
||||
if( pInfo==0 ){
|
||||
struct lockInfo *pOld;
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is multithreading behavior
|
||||
#
|
||||
# $Id: thread1.test,v 1.1 2003/12/19 02:52:09 drh Exp $
|
||||
# $Id: thread1.test,v 1.2 2003/12/19 08:40:24 drh Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@ -38,7 +38,15 @@ do_test thread1-1.1 {
|
||||
} {8 64}
|
||||
|
||||
# Interleave two threads on read access. Then make sure a third
|
||||
# thread can write the database.
|
||||
# thread can write the database. In other words:
|
||||
#
|
||||
# read-lock A
|
||||
# read-lock B
|
||||
# unlock A
|
||||
# unlock B
|
||||
# write-lock C
|
||||
#
|
||||
# At one point, the write-lock of C would fail on Linux.
|
||||
#
|
||||
do_test thread1-1.2 {
|
||||
thread_create A test.db
|
||||
@ -82,7 +90,69 @@ do_test thread1-1.11 {
|
||||
thread_finalize C
|
||||
thread_result C
|
||||
} SQLITE_OK
|
||||
do_test thread1-1.12 {
|
||||
catchsql {SELECT name FROM sqlite_master}
|
||||
execsql {SELECT name FROM sqlite_master}
|
||||
} {t1 t2}
|
||||
|
||||
|
||||
# Under this scenario:
|
||||
#
|
||||
# read-lock A
|
||||
# read-lock B
|
||||
# unlock A
|
||||
# write-lock C
|
||||
#
|
||||
# Make sure the write-lock fails with SQLITE_BUSY
|
||||
#
|
||||
do_test thread1-2.1 {
|
||||
thread_halt *
|
||||
thread_create A test.db
|
||||
thread_compile A {SELECT a FROM t1}
|
||||
thread_step A
|
||||
thread_result A
|
||||
} SQLITE_ROW
|
||||
do_test thread1-2.2 {
|
||||
thread_create B test.db
|
||||
thread_compile B {SELECT b FROM t1}
|
||||
thread_step B
|
||||
thread_result B
|
||||
} SQLITE_ROW
|
||||
do_test thread1-2.3 {
|
||||
thread_create C test.db
|
||||
thread_compile C {INSERT INTO t2 VALUES(98,99)}
|
||||
thread_step C
|
||||
thread_result C
|
||||
} SQLITE_BUSY
|
||||
do_test thread1-2.4 {
|
||||
execsql {SELECT * FROM t2}
|
||||
} {}
|
||||
do_test thread1-2.5 {
|
||||
thread_finalize A
|
||||
thread_result A
|
||||
} SQLITE_OK
|
||||
do_test thread1-2.6 {
|
||||
thread_step C
|
||||
thread_result C
|
||||
} SQLITE_BUSY
|
||||
do_test thread1-2.7 {
|
||||
execsql {SELECT * FROM t2}
|
||||
} {}
|
||||
do_test thread1-2.8 {
|
||||
thread_finalize B
|
||||
thread_result B
|
||||
} SQLITE_OK
|
||||
do_test thread1-2.9 {
|
||||
thread_step C
|
||||
thread_result C
|
||||
} SQLITE_DONE
|
||||
do_test thread1-2.10 {
|
||||
execsql {SELECT * FROM t2}
|
||||
} {98 99}
|
||||
do_test thread1-2.11 {
|
||||
thread_finalize C
|
||||
thread_result C
|
||||
} SQLITE_OK
|
||||
|
||||
thread_halt *
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user