forked from mirror/go-sqlite3
Add support for sqlite3_unlock_notify
This commit is contained in:
parent
05548ff555
commit
cf9f5ca0ef
|
@ -0,0 +1,5 @@
|
|||
void _unlock_notify_callback(void *arg, int argc)
|
||||
{
|
||||
extern void unlock_notify_callback(void *, int);
|
||||
unlock_notify_callback(arg, argc);
|
||||
}
|
34
callback.go
34
callback.go
|
@ -20,6 +20,8 @@ package sqlite3
|
|||
|
||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s);
|
||||
void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l);
|
||||
|
||||
void _unlock_notify_callback(void *arg, int argc);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
|
@ -362,3 +364,35 @@ func callbackSyntheticForTests(v reflect.Value, err error) callbackArgConverter
|
|||
return v, err
|
||||
}
|
||||
}
|
||||
|
||||
type unlockNotification struct {
|
||||
notify chan struct{}
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
//export unlock_notify_callback
|
||||
func unlock_notify_callback(pargv unsafe.Pointer, argc C.int) {
|
||||
argv := *(*uintptr)(pargv)
|
||||
v := (*[1 << 30]uintptr)(unsafe.Pointer(argv))
|
||||
for i := 0; i < int(argc); i++ {
|
||||
un := lookupHandle(v[i]).(unlockNotification)
|
||||
un.notify <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
var notifyMutex sync.Mutex
|
||||
|
||||
//export unlock_notify_wait
|
||||
func unlock_notify_wait(db *C.sqlite3) C.int {
|
||||
var un unlockNotification
|
||||
|
||||
un.notify = make(chan struct{})
|
||||
defer close(un.notify)
|
||||
|
||||
argv := [1]uintptr{newHandle(nil, un)}
|
||||
if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C._unlock_notify_callback), unsafe.Pointer(&argv)); rv != C.SQLITE_OK {
|
||||
return rv
|
||||
}
|
||||
<-un.notify
|
||||
return C.SQLITE_OK
|
||||
}
|
||||
|
|
34
sqlite3.go
34
sqlite3.go
|
@ -11,6 +11,7 @@ package sqlite3
|
|||
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
|
||||
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
|
||||
#cgo CFLAGS: -DSQLITE_DISABLE_INTRINSIC
|
||||
#cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
#cgo CFLAGS: -Wno-deprecated-declarations
|
||||
#ifndef USE_LIBSQLITE3
|
||||
#include <sqlite3-binding.h>
|
||||
|
@ -70,8 +71,25 @@ _sqlite3_exec(sqlite3* db, const char* pcmd, long long* rowid, long long* change
|
|||
static int
|
||||
_sqlite3_step(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
||||
{
|
||||
int rv = sqlite3_step(stmt);
|
||||
extern int unlock_notify_wait(sqlite3 *db);
|
||||
int rv;
|
||||
sqlite3* db = sqlite3_db_handle(stmt);
|
||||
|
||||
for (;;) {
|
||||
rv = sqlite3_step(stmt);
|
||||
if (rv!=SQLITE_LOCKED) {
|
||||
break;
|
||||
}
|
||||
if (sqlite3_extended_errcode(db)!=SQLITE_LOCKED_SHAREDCACHE) {
|
||||
break;
|
||||
}
|
||||
rv = unlock_notify_wait(db);
|
||||
if (rv != SQLITE_OK) {
|
||||
break;
|
||||
}
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
|
||||
*rowid = (long long) sqlite3_last_insert_rowid(db);
|
||||
*changes = (long long) sqlite3_changes(db);
|
||||
return rv;
|
||||
|
@ -814,7 +832,19 @@ func (c *SQLiteConn) prepare(ctx context.Context, query string) (driver.Stmt, er
|
|||
defer C.free(unsafe.Pointer(pquery))
|
||||
var s *C.sqlite3_stmt
|
||||
var tail *C.char
|
||||
rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &tail)
|
||||
var rv C.int
|
||||
for {
|
||||
rv = C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &tail)
|
||||
if rv == C.SQLITE_OK {
|
||||
break
|
||||
}
|
||||
if rv == C.SQLITE_LOCKED {
|
||||
rv = unlock_notify_wait(c.db)
|
||||
if rv != C.SQLITE_OK {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if rv != C.SQLITE_OK {
|
||||
return nil, c.lastError()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue