Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Do not invoke the busy callback when trying to promote a lock from SHARED to RESERVED. This avoids a deadlock. (CVS 1879) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d33771a303d9c20dd477b1a973024ff7 |
User & Date: | drh 2004-08-07 23:54:48.000 |
Context
2004-08-08
| ||
19:43 | Attempting to open a locked table for writing should fail immediately. Ticket #842. (CVS 1880) (check-in: fc879a9b1d user: drh tags: trunk) | |
2004-08-07
| ||
23:54 | Do not invoke the busy callback when trying to promote a lock from SHARED to RESERVED. This avoids a deadlock. (CVS 1879) (check-in: d33771a303 user: drh tags: trunk) | |
2004-08-06
| ||
17:00 | Fix a bug in the logic that converts numbers into strings inside the VM. Ticket #844 (CVS 1878) (check-in: 863540be24 user: drh tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.154 2004/08/07 23:54:48 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 | assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); if( pPager->memDb ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ int busy = 1; do { rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK); }while( rc==SQLITE_BUSY && pPager->pBusyHandler && pPager->pBusyHandler->xFunc && pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++) ); if( rc!=SQLITE_OK ){ return rc; } pPager->state = PAGER_RESERVED; pPager->dirtyCache = 0; TRACE2("TRANSACTION %d\n", pPager->fd.h); if( pPager->useJournal && !pPager->tempFile ){ rc = pager_open_journal(pPager); | > > > > > > > > > > | 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 | assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); if( pPager->memDb ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ #if 0 int busy = 1; do { rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK); }while( rc==SQLITE_BUSY && pPager->pBusyHandler && pPager->pBusyHandler->xFunc && pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++) ); #endif rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK); if( rc!=SQLITE_OK ){ /* We do not call the busy handler when we fail to get a reserved lock. ** The only reason we might fail is because another process is holding ** the reserved lock. But the other process will not be able to ** release its reserved lock until this process releases its shared ** lock. So we might as well fail in this process, let it release ** its shared lock so that the other process can commit. */ return rc; } pPager->state = PAGER_RESERVED; pPager->dirtyCache = 0; TRACE2("TRANSACTION %d\n", pPager->fd.h); if( pPager->useJournal && !pPager->tempFile ){ rc = pager_open_journal(pPager); |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.314 2004/08/07 23:54:48 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "config.h" #include "sqlite3.h" #include "hash.h" |
︙ | ︙ | |||
169 170 171 172 173 174 175 | /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) | < < < < < < < < < < < < | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) /* ** If memory allocation problems are found, recompile with ** ** -DSQLITE_DEBUG=1 ** ** to enable some sanity checking on malloc() and free(). To ** check for memory leaks, recompile with |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.407 2004/08/07 23:54:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
2076 2077 2078 2079 2080 2081 2082 | nHdr += sqlite3VarintLen(serial_type); } /* Add the initial header varint and total the size */ nHdr += sqlite3VarintLen(nHdr); nByte = nHdr+nData; | < < < < < | 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 | nHdr += sqlite3VarintLen(serial_type); } /* Add the initial header varint and total the size */ nHdr += sqlite3VarintLen(nHdr); nByte = nHdr+nData; /* Allocate space for the new record. */ if( nByte>sizeof(zTemp) ){ zNewRecord = sqliteMallocRaw(nByte); if( !zNewRecord ){ goto no_mem; } }else{ |
︙ | ︙ |
Changes to test/bigrow.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is stressing the library by putting large amounts # of data in a single row of a table. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is stressing the library by putting large amounts # of data in a single row of a table. # # $Id: bigrow.test,v 1.5 2004/08/07 23:54:48 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Make a big string that we can use for test data # do_test bigrow-1.0 { |
︙ | ︙ | |||
201 202 203 204 205 206 207 | UPDATE t1 SET b=b||b; SELECT a,length(b),c FROM t1; } } "one $sz hi" incr i } do_test bigrow-5.3 { | | < | > > > > > > > > > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | UPDATE t1 SET b=b||b; SELECT a,length(b),c FROM t1; } } "one $sz hi" incr i } do_test bigrow-5.3 { catchsql {UPDATE t1 SET b=b||b} } {0 {}} do_test bigrow-5.4 { execsql {SELECT length(b) FROM t1} } 1966080 do_test bigrow-5.5 { catchsql {UPDATE t1 SET b=b||b} } {0 {}} do_test bigrow-5.6 { execsql {SELECT length(b) FROM t1} } 3932160 do_test bigrow-5.99 { execsql {DROP TABLE t1} } {} finish_test |
Changes to test/lock.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # 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 database locks. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # 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 database locks. # # $Id: lock.test,v 1.27 2004/08/07 23:54:48 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create an alternative connection to the database # |
︙ | ︙ | |||
166 167 168 169 170 171 172 | # A thread can read when another has a RESERVED lock. # do_test lock-2.2 { catchsql {SELECT * FROM t2} db2 } {0 {9 8}} # If the other thread (the one that does not hold the transaction with | | | | < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < | | 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 223 | # A thread can read when another has a RESERVED lock. # do_test lock-2.2 { catchsql {SELECT * FROM t2} db2 } {0 {9 8}} # If the other thread (the one that does not hold the transaction with # a RESERVED lock) tries to get a RESERVED lock, we do not get a busy callback. # do_test lock-2.3 { proc callback {count} { set ::callback_value $count break } set ::callback_value {} db2 busy callback set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg] lappend r $msg lappend r $::callback_value } {1 {database is locked} {}} do_test lock-2.4 { proc callback {count} { lappend ::callback_value $count if {$count>4} break } set ::callback_value {} db2 busy callback set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg] lappend r $msg lappend r $::callback_value } {1 {database is locked} {}} do_test lock-2.5 { proc callback {count} { lappend ::callback_value $count if {$count>4} break } set ::callback_value {} db2 busy callback set r [catch {execsql {SELECT * FROM t1} db2} msg] lappend r $msg lappend r $::callback_value } {0 {2 1} {}} execsql {ROLLBACK} # Test the built-in busy timeout handler # do_test lock-2.8 { db2 timeout 400 execsql BEGIN execsql {UPDATE t1 SET a = 0 WHERE 0} # catchsql BEGIN db2 catchsql {UPDATE t1 SET a = 0 WHERE 0} db2 } {1 {database is locked}} do_test lock-2.9 { db2 timeout 0 execsql COMMIT } {} integrity_check lock-2.10 |
︙ | ︙ | |||
285 286 287 288 289 290 291 | proc callback {count} { lappend ::callback_value $count if {$count>4} break } db2 busy callback set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg] lappend rc $msg $::callback_value | | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | proc callback {count} { lappend ::callback_value $count if {$count>4} break } db2 busy callback set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg] lappend rc $msg $::callback_value } {1 {database is locked} {}} execsql {ROLLBACK} # When one thread is writing, other threads cannot read. Except if the # writing thread is writing to its temporary tables, the other threads # can still read. -> Not so in 3.0. One thread can read while another # holds a RESERVED lock. # |
︙ | ︙ |