Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7dddbeb586504de30c64a1e61614da44 |
User & Date: | drh 2003-12-19 08:40:23.000 |
Context
2003-12-19
| ||
12:31 | Makefile updates for the new "test4.c" module. Also disable large file tests for archic TCL versions. (CVS 1139) (check-in: 55e2488912 user: drh tags: trunk) | |
08:40 | 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) (check-in: 7dddbeb586 user: drh tags: trunk) | |
02:52 | Add new thread-testing code and fix locking under Linux threads. Ticket #530. (CVS 1137) (check-in: b36a4bb610 user: drh tags: trunk) | |
Changes
Changes to src/os.c.
︙ | ︙ | |||
164 165 166 167 168 169 170 | ** structure. The fcntl() system call is only invoked to set a ** POSIX lock if the internal lock structure transitions between ** a locked and an unlocked state. */ /* ** An instance of the following structure serves as the key used | | > > > | < | < | | | < | < | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | ** structure. The fcntl() system call is only invoked to set a ** POSIX lock if the internal lock structure transitions between ** a locked and an unlocked state. */ /* ** An instance of the following structure serves as the key used ** 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 lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ pid_t pid; /* Process ID */ }; /* ** An instance of the following structure is allocated for each inode. ** A single inode can have multiple file descriptors, so each OsFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of OsFiles pointing to it. */ struct lockInfo { 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 lockKey structures) into ** pointers to lockInfo structures. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; /* ** Given a file descriptor, locate a lockInfo structure that describes ** that file descriptor. Create a new one if necessary. NULL might ** be returned if malloc() fails. */ static struct lockInfo *findLockInfo(int fd){ int rc; struct lockKey key; struct stat statbuf; struct lockInfo *pInfo; rc = fstat(fd, &statbuf); if( rc!=0 ) return 0; memset(&key, 0, sizeof(key)); key.dev = statbuf.st_dev; key.ino = statbuf.st_ino; key.pid = getpid(); pInfo = (struct lockInfo*)sqliteHashFind(&lockHash, &key, sizeof(key)); if( pInfo==0 ){ struct lockInfo *pOld; pInfo = sqliteMalloc( sizeof(*pInfo) ); if( pInfo==0 ) return 0; pInfo->key = key; pInfo->nRef = 1; |
︙ | ︙ |
Changes to test/thread1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 December 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is multithreading behavior # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2003 December 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is multithreading behavior # # $Id: thread1.test,v 1.2 2003/12/19 08:40:24 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Skip this whole file if the thread testing code is not enabled # |
︙ | ︙ | |||
34 35 36 37 38 39 40 | INSERT INTO t1 SELECT a+2, b||b FROM t1; INSERT INTO t1 SELECT a+4, b||b FROM t1; SELECT count(*), max(length(b)) FROM t1; } } {8 64} # Interleave two threads on read access. Then make sure a third | | > > > > > > > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | INSERT INTO t1 SELECT a+2, b||b FROM t1; INSERT INTO t1 SELECT a+4, b||b FROM t1; SELECT count(*), max(length(b)) FROM t1; } } {8 64} # Interleave two threads on read access. Then make sure a third # 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 thread_create B test.db thread_create C test.db thread_compile A {SELECT a FROM t1} thread_step A |
︙ | ︙ | |||
78 79 80 81 82 83 84 85 86 | thread_step C thread_result C } SQLITE_DONE do_test thread1-1.11 { thread_finalize C thread_result C } SQLITE_OK | > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | thread_step C thread_result C } SQLITE_DONE 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 |