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:
drh 2003-12-19 08:40:22 +00:00
parent a6064dcf3b
commit acf01e7ddd
4 changed files with 90 additions and 21 deletions

View File

@ -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

View File

@ -1 +1 @@
b36a4bb61094d539273c21a9e4042384f10a7806
7dddbeb586504de30c64a1e61614da447f18c8ba

View File

@ -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;

View File

@ -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