]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the sqlite3_unlock_notify() interface so that when the callback is NULL
authordrh <drh@noemail.net>
Tue, 7 Apr 2009 22:06:57 +0000 (22:06 +0000)
committerdrh <drh@noemail.net>
Tue, 7 Apr 2009 22:06:57 +0000 (22:06 +0000)
it simply cancels any outstanding callbacks. (CVS 6467)

FossilOrigin-Name: 9ccfcb760745df28b04e746355b1b6dec49a93de

manifest
manifest.uuid
src/notify.c
src/sqliteInt.h
test/notify1.test

index 215eda81d5e743934b5e0e40b9115915a0160055..fb51e4ef2cfe60249cb53aef869dd4ceb67c67de 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\stwo\sunused\stests\sfrom\sthe\sintegrity_check\spragma\slogic.\s(CVS\s6466)
-D 2009-04-07T22:05:43
+C Fix\sthe\ssqlite3_unlock_notify()\sinterface\sso\sthat\swhen\sthe\scallback\sis\sNULL\nit\ssimply\scancels\sany\soutstanding\scallbacks.\s(CVS\s6467)
+D 2009-04-07T22:06:57
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -136,7 +136,7 @@ F src/mutex_noop.c f5a07671f25a1a9bd7c10ad7107bc2585446200f
 F src/mutex_os2.c 6b5a74f812082a8483c3df05b47bbaac2424b9a0
 F src/mutex_unix.c 2f936339dfef1a4c142db290d575a3509b77315f
 F src/mutex_w32.c f4b6a4a48f1dfff7f0089cba9b5a371691f17b8b
-F src/notify.c da6f6b999dce9203d24280fa01b4ffbd2d9ba79b
+F src/notify.c 0127121816d8a861deb0dfd111b495346bf233db
 F src/os.c c2aa4a7d8bb845222e5c37f56cde377b20c3b087
 F src/os.h fa3f4aa0119ff721a2da4b47ffd74406ac864c05
 F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc
@@ -159,7 +159,7 @@ F src/select.c 462d9671e91accd983110fa38674be0d2a3daa66
 F src/shell.c 0a11f831603f17fea20ca97133c0f64e716af4a7
 F src/sqlite.h.in 718a026b4cf3c766fc7ac5ff582faa60324b116c
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 3754c3c7f8549db259909882d3484250d77488cb
+F src/sqliteInt.h 7b341ab7d570b271e8566e7e7ed6993453f84964
 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3
@@ -479,7 +479,7 @@ F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
 F test/mutex1.test ebd54720401fafe854799dc86b7bf60b75631935
 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
 F test/nan.test c627d79b3d36ea892563fd67584b3e8a18f0618a
-F test/notify1.test 099191b6f450a7cc3208bdf826532572bdd9a204
+F test/notify1.test 533cf60a81f59c1c88a99ce46b1c14f47d14c32c
 F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
 F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
 F test/null.test a8b09b8ed87852742343b33441a9240022108993
@@ -715,7 +715,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 2c1f59834ab7a16066ee12cb8a8342d438c23ce9
-R da69fda516423dc915653709b87d09f0
+P 22999d31418aa9ecb17ab5d135b206b967889614
+R 8662e3a26c19cc89676dfbf43f445945
 U drh
-Z 1ffc7b542098adaaa0308f19da4f52e8
+Z 7764f7e6b16bc4d3ac70136f1d1dcce8
index e07c64be3a9f50e6717c832a3a37f5bff928396f..456cf47b70c45a7fee27b0284e4581805f5717ac 100644 (file)
@@ -1 +1 @@
-22999d31418aa9ecb17ab5d135b206b967889614
\ No newline at end of file
+9ccfcb760745df28b04e746355b1b6dec49a93de
\ No newline at end of file
index 67bb227300681cf4c49c6dcb983d85870ff58b3a..afa762629046559eb1e5436544c8b71bf45ba6ad 100644 (file)
@@ -13,7 +13,7 @@
 ** This file contains the implementation of the sqlite3_unlock_notify()
 ** API method and its associated functionality.
 **
-** $Id: notify.c,v 1.3 2009/04/07 11:21:29 danielk1977 Exp $
+** $Id: notify.c,v 1.4 2009/04/07 22:06:57 drh Exp $
 */
 #include "sqliteInt.h"
 #include "btreeInt.h"
@@ -128,6 +128,24 @@ static void leaveMutex(void){
 
 /*
 ** Register an unlock-notify callback.
+**
+** This is called after connection "db" has attempted some operation
+** but has received an SQLITE_LOCKED error because another connection
+** (call it pOther) in the same process was busy using the same shared
+** cache.  pOther is found by looking at db->pBlockingConnection.
+**
+** If there is no blocking connection, the callback is invoked immediately,
+** before this routine returns.
+**
+** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
+** a deadlock.
+**
+** Otherwise, make arrangements to invoke xNotify when pOther drops
+** its locks.
+**
+** Each call to this routine overrides any prior callbacks registered
+** on the same "db".  If xNotify==0 then any prior callbacks are immediately
+** cancelled.
 */
 int sqlite3_unlock_notify(
   sqlite3 *db,
@@ -139,7 +157,12 @@ int sqlite3_unlock_notify(
   sqlite3_mutex_enter(db->mutex);
   enterMutex();
 
-  if( 0==db->pBlockingConnection ){
+  if( xNotify==0 ){
+    removeFromBlockedList(db);
+    db->pUnlockConnection = 0;
+    db->xUnlockNotify = 0;
+    db->pUnlockArg = 0;
+  }else if( 0==db->pBlockingConnection ){
     /* The blocking transaction has been concluded. Or there never was a 
     ** blocking transaction. In either case, invoke the notify callback
     ** immediately. 
@@ -148,7 +171,7 @@ int sqlite3_unlock_notify(
   }else{
     sqlite3 *p;
 
-    for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection);
+    for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){}
     if( p ){
       rc = SQLITE_LOCKED;              /* Deadlock detected. */
     }else{
@@ -183,7 +206,8 @@ void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
 }
 
 /*
-** The transaction opened by database db has just finished. Locks held 
+** This function is called when
+** the transaction opened by database db has just finished. Locks held 
 ** by database connection db have been released.
 **
 ** This function loops through each entry in the blocked connections
@@ -204,11 +228,11 @@ void sqlite3ConnectionUnlocked(sqlite3 *db){
   void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
   int nArg = 0;                            /* Number of entries in aArg[] */
   sqlite3 **pp;                            /* Iterator variable */
+  void **aArg;               /* Arguments to the unlock callback */
+  void **aDyn = 0;           /* Dynamically allocated space for aArg[] */
+  void *aStatic[16];         /* Starter space for aArg[].  No malloc required */
 
-  void *aStatic[16];
-  void **aArg = aStatic;
-  void **aDyn = 0;
-
+  aArg = aStatic;
   enterMutex();         /* Enter STATIC_MASTER mutex */
 
   /* This loop runs once for each entry in the blocked-connections list. */
index 625c2e1ffb76733ed6d6e83aa3c4302ff6833620..a66bb3a4f539768c503a7c8a06749ba6400f958b 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.852 2009/04/07 14:14:22 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.853 2009/04/07 22:06:57 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -836,6 +836,13 @@ struct sqlite3 {
 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
   /* The following variables are all protected by the STATIC_MASTER 
   ** mutex, not by sqlite3.mutex. They are used by code in notify.c. 
+  **
+  ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
+  ** unlock so that it can proceed.
+  **
+  ** When X.pBlockingConnection==Y, that means that something that X tried
+  ** tried to do recently failed with an SQLITE_LOCKED error due to locks
+  ** held by Y.
   */
   sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
   sqlite3 *pUnlockConnection;           /* Connection to watch for unlock */
index 1b11bda7b5a702e17e639fd7871bf1ec3d53bc44..1b6c516a48b597424c9dd99a615918f2223e28a3 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the sqlite3_unlock_notify() API.
 #
-# $Id: notify1.test,v 1.2 2009/03/25 15:43:09 danielk1977 Exp $
+# $Id: notify1.test,v 1.3 2009/04/07 22:06:57 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -55,6 +55,38 @@ do_test notify1-1.5 {
   execsql { SELECT * FROM t1 }
 } {1 2 3 4}
 
+#-------------------------------------------------------------------------
+# Verify that invoking the "unlock_notify" method with no arguments
+# (which is the equivalent of invoking sqlite3_unlock_notify() with
+# a NULL xNotify argument) cancels a pending notify callback.
+#
+do_test notify1-1.11 {
+  execsql { DROP TABLE t1; CREATE TABLE t1(a, b) }
+} {}
+do_test notify1-1.12 {
+  execsql {
+    BEGIN;
+    INSERT INTO t1 VALUES(1, 2);
+  }
+  catchsql { INSERT INTO t1 VALUES(3, 4) } db2
+} {1 {database table is locked}}
+do_test notify1-1.13 {
+  set zScript ""
+  db2 unlock_notify {
+    set zScript "db2 eval { INSERT INTO t1 VALUES(3, 4) }"
+  }
+  execsql { SELECT * FROM t1 }
+} {1 2}
+do_test notify1-1.14 {
+  set zScript
+} {}
+do_test notify1-1.15 {
+  db2 unlock_notify
+  execsql { COMMIT }
+  eval $zScript
+  execsql { SELECT * FROM t1 }
+} {1 2}
+
 #-------------------------------------------------------------------------
 # The following tests, notify1-2.*, test that deadlock is detected 
 # correctly.