Skip to content

Commit 3bae1d7

Browse files
committed
SQLITE_FCNTL_BUSYHANDLER.
1 parent 8887036 commit 3bae1d7

File tree

7 files changed

+64
-4
lines changed

7 files changed

+64
-4
lines changed

embed/exports.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ sqlite3_get_autocommit
7777
sqlite3_get_auxdata
7878
sqlite3_hard_heap_limit64
7979
sqlite3_interrupt
80+
sqlite3_invoke_busy_handler_go
8081
sqlite3_last_insert_rowid
8182
sqlite3_limit
8283
sqlite3_malloc64

sqlite3/vfs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,10 @@ int sqlite3_os_init() {
162162
return SQLITE_OK;
163163
}
164164

165+
int sqlite3_invoke_busy_handler_go(sqlite3_int64 token) {
166+
void **ap = (void **)&token;
167+
return ((int(*)(void *))(ap[0]))(ap[1]);
168+
}
169+
165170
static_assert(offsetof(sqlite3_vfs, zName) == 16, "Unexpected offset");
166171
static_assert(offsetof(struct go_file, handle) == 4, "Unexpected offset");

util/vfsutil/wrap.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ func WrapPersistWAL(f vfs.File) bool {
4646
return false
4747
}
4848

49-
// WrapSetPersistentWAL helps wrap [vfs.FilePersistWAL].
50-
func WrapSetPersistentWAL(f vfs.File, keepWAL bool) {
49+
// WrapSetPersistWAL helps wrap [vfs.FilePersistWAL].
50+
func WrapSetPersistWAL(f vfs.File, keepWAL bool) {
5151
if f, ok := f.(vfs.FilePersistWAL); ok {
5252
f.SetPersistWAL(keepWAL)
5353
}
@@ -99,6 +99,14 @@ func WrapOverwrite(f vfs.File) error {
9999
return sqlite3.NOTFOUND
100100
}
101101

102+
// WrapSyncSuper helps wrap [vfs.FileSync].
103+
func WrapSyncSuper(f vfs.File, super string) error {
104+
if f, ok := f.(vfs.FileSync); ok {
105+
return f.SyncSuper(super)
106+
}
107+
return sqlite3.NOTFOUND
108+
}
109+
102110
// WrapCommitPhaseTwo helps wrap [vfs.FileCommitPhaseTwo].
103111
func WrapCommitPhaseTwo(f vfs.File) error {
104112
if f, ok := f.(vfs.FileCommitPhaseTwo); ok {
@@ -153,6 +161,13 @@ func WrapPragma(f vfs.File, name, value string) (string, error) {
153161
return "", sqlite3.NOTFOUND
154162
}
155163

164+
// WrapBusyHandler helps wrap [vfs.FilePragma].
165+
func WrapBusyHandler(f vfs.File, handler func() bool) {
166+
if f, ok := f.(vfs.FileBusyHandler); ok {
167+
f.BusyHandler(handler)
168+
}
169+
}
170+
156171
// WrapSharedMemory helps wrap [vfs.FileSharedMemory].
157172
func WrapSharedMemory(f vfs.File) vfs.SharedMemory {
158173
if f, ok := f.(vfs.FileSharedMemory); ok {

vfs/adiantum/hbsh.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ func (h *hbshFile) PersistentWAL() bool {
242242
}
243243

244244
func (h *hbshFile) SetPersistentWAL(keepWAL bool) {
245-
vfsutil.WrapSetPersistentWAL(h.File, keepWAL) // notest
245+
vfsutil.WrapSetPersistWAL(h.File, keepWAL) // notest
246246
}
247247

248248
func (h *hbshFile) HasMoved() (bool, error) {
@@ -253,6 +253,10 @@ func (h *hbshFile) Overwrite() error {
253253
return vfsutil.WrapOverwrite(h.File) // notest
254254
}
255255

256+
func (h *hbshFile) SyncSuper(super string) error {
257+
return vfsutil.WrapSyncSuper(h.File, super) // notest
258+
}
259+
256260
func (h *hbshFile) CommitPhaseTwo() error {
257261
return vfsutil.WrapCommitPhaseTwo(h.File) // notest
258262
}
@@ -276,3 +280,7 @@ func (h *hbshFile) CheckpointStart() {
276280
func (h *hbshFile) CheckpointDone() {
277281
vfsutil.WrapCheckpointDone(h.File) // notest
278282
}
283+
284+
func (h *hbshFile) BusyHandler(handler func() bool) {
285+
vfsutil.WrapBusyHandler(h.File, handler) // notest
286+
}

vfs/api.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ type FilePragma interface {
171171
Pragma(name, value string) (string, error)
172172
}
173173

174+
// FileBusyHandler extends File to implement the
175+
// SQLITE_FCNTL_BUSYHANDLER file control opcode.
176+
//
177+
// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlbusyhandler
178+
type FileBusyHandler interface {
179+
File
180+
BusyHandler(func() bool)
181+
}
182+
174183
// FileSharedMemory extends File to possibly implement
175184
// shared-memory for the WAL-index.
176185
// The same shared-memory instance must be returned

vfs/vfs.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,20 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
379379
return ret
380380
}
381381

382+
case _FCNTL_BUSYHANDLER:
383+
if file, ok := file.(FileBusyHandler); ok {
384+
arg := util.ReadUint64(mod, pArg)
385+
fn := mod.ExportedFunction("sqlite3_invoke_busy_handler_go")
386+
file.BusyHandler(func() bool {
387+
stack := [...]uint64{arg}
388+
if err := fn.CallWithStack(ctx, stack[:]); err != nil {
389+
panic(err)
390+
}
391+
return uint32(stack[0]) != 0
392+
})
393+
return _OK
394+
}
395+
382396
case _FCNTL_LOCK_TIMEOUT:
383397
if file, ok := file.(FileSharedMemory); ok {
384398
if shm, ok := file.SharedMemory().(blockingSharedMemory); ok {

vfs/xts/xts.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func (x *xtsFile) PersistentWAL() bool {
238238
}
239239

240240
func (x *xtsFile) SetPersistentWAL(keepWAL bool) {
241-
vfsutil.WrapSetPersistentWAL(x.File, keepWAL) // notest
241+
vfsutil.WrapSetPersistWAL(x.File, keepWAL) // notest
242242
}
243243

244244
func (x *xtsFile) HasMoved() (bool, error) {
@@ -249,6 +249,10 @@ func (x *xtsFile) Overwrite() error {
249249
return vfsutil.WrapOverwrite(x.File) // notest
250250
}
251251

252+
func (x *xtsFile) SyncSuper(super string) error {
253+
return vfsutil.WrapSyncSuper(x.File, super) // notest
254+
}
255+
252256
func (x *xtsFile) CommitPhaseTwo() error {
253257
return vfsutil.WrapCommitPhaseTwo(x.File) // notest
254258
}
@@ -272,3 +276,7 @@ func (x *xtsFile) CheckpointStart() {
272276
func (x *xtsFile) CheckpointDone() {
273277
vfsutil.WrapCheckpointDone(x.File) // notest
274278
}
279+
280+
func (x *xtsFile) BusyHandler(handler func() bool) {
281+
vfsutil.WrapBusyHandler(x.File, handler) // notest
282+
}

0 commit comments

Comments
 (0)