diff options
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs')
6 files changed, 45 insertions, 17 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go index 86a988ae8..5366fdb71 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go @@ -79,16 +79,15 @@ func (f *vfsFile) Lock(lock LockLevel) error { // A PENDING lock is needed before acquiring an EXCLUSIVE lock. if f.lock < LOCK_PENDING { // If we're already RESERVED, we can block indefinitely, - // since only new readers may briefly hold the PENDING lock. + // since only incoming readers may briefly hold the PENDING lock. if rc := osGetPendingLock(f.File, reserved /* block */); rc != _OK { return rc } f.lock = LOCK_PENDING } - // We already have PENDING, so we're just waiting for readers to leave. - // If we were RESERVED, we can wait for a little while, before invoking - // the busy handler; we will only do this once. - if rc := osGetExclusiveLock(f.File, reserved /* wait */); rc != _OK { + // We are now PENDING, so we're just waiting for readers to leave. + // If we were RESERVED, we can block for a bit before invoking the busy handler. + if rc := osGetExclusiveLock(f.File, reserved /* block */); rc != _OK { return rc } f.lock = LOCK_EXCLUSIVE diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go index 7bb78c0af..e163e804d 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go @@ -53,10 +53,11 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d if errno, _ := err.(unix.Errno); errno != unix.EAGAIN { break } - if timeout < time.Since(before) { + if time.Since(before) > timeout { break } - time.Sleep(time.Duration(rand.Int63n(int64(time.Millisecond)))) + const sleepIncrement = 1024*1024 - 1 // power of two, ~1ms + time.Sleep(time.Duration(rand.Int63() & sleepIncrement)) } } return osLockErrorCode(err, def) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go index ffa1f5e19..2616a0f5e 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go @@ -32,9 +32,9 @@ func osGetPendingLock(file *os.File, block bool) _ErrorCode { return osWriteLock(file, _PENDING_BYTE, 1, timeout) } -func osGetExclusiveLock(file *os.File, wait bool) _ErrorCode { +func osGetExclusiveLock(file *os.File, block bool) _ErrorCode { var timeout time.Duration - if wait { + if block { timeout = time.Millisecond } // Acquire the EXCLUSIVE lock. diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go index 7425b5581..4cad777d3 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go @@ -38,9 +38,9 @@ func osGetPendingLock(file *os.File, block bool) _ErrorCode { return osWriteLock(file, _PENDING_BYTE, 1, timeout) } -func osGetExclusiveLock(file *os.File, wait bool) _ErrorCode { +func osGetExclusiveLock(file *os.File, block bool) _ErrorCode { var timeout time.Duration - if wait { + if block { timeout = time.Millisecond } @@ -134,10 +134,11 @@ func osLock(file *os.File, flags, start, len uint32, timeout time.Duration, def if errno, _ := err.(windows.Errno); errno != windows.ERROR_LOCK_VIOLATION { break } - if timeout < time.Since(before) { + if time.Since(before) > timeout { break } - time.Sleep(time.Duration(rand.Int63n(int64(time.Millisecond)))) + const sleepIncrement = 1024*1024 - 1 // power of two, ~1ms + time.Sleep(time.Duration(rand.Int63() & sleepIncrement)) } } return osLockErrorCode(err, def) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go index 7b0d4b677..36f55d0b6 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go @@ -6,6 +6,7 @@ import ( "context" "io" "os" + "time" "github.com/ncruces/go-sqlite3/internal/util" "github.com/tetratelabs/wazero/api" @@ -49,6 +50,7 @@ type vfsShm struct { path string regions []*util.MappedRegion readOnly bool + blocking bool } func (s *vfsShm) shmOpen() _ErrorCode { @@ -76,6 +78,13 @@ func (s *vfsShm) shmOpen() _ErrorCode { if s.readOnly { return _READONLY_CANTINIT } + // Do not use a blocking lock here. + // If the lock cannot be obtained immediately, + // it means some other connection is truncating the file. + // And after it has done so, it will not release its lock, + // but only downgrade it to a shared lock. + // So no point in blocking here. + // The call below to obtain the shared DMS lock may use a blocking lock. if rc := osWriteLock(s.File, _SHM_DMS, 1, 0); rc != _OK { return rc } @@ -83,7 +92,7 @@ func (s *vfsShm) shmOpen() _ErrorCode { return _IOERR_SHMOPEN } } - if rc := osReadLock(s.File, _SHM_DMS, 1, 0); rc != _OK { + if rc := osReadLock(s.File, _SHM_DMS, 1, time.Millisecond); rc != _OK { return rc } return _OK @@ -150,13 +159,18 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { panic(util.AssertErr()) } + var timeout time.Duration + if s.blocking { + timeout = time.Millisecond + } + switch { case flags&_SHM_UNLOCK != 0: return osUnlock(s.File, _SHM_BASE+int64(offset), int64(n)) case flags&_SHM_SHARED != 0: - return osReadLock(s.File, _SHM_BASE+int64(offset), int64(n), 0) + return osReadLock(s.File, _SHM_BASE+int64(offset), int64(n), timeout) case flags&_SHM_EXCLUSIVE != 0: - return osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n), 0) + return osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n), timeout) default: panic(util.AssertErr()) } @@ -181,3 +195,7 @@ func (s *vfsShm) shmUnmap(delete bool) { s.Close() s.File = nil } + +func (s *vfsShm) shmEnableBlocking(block bool) { + s.blocking = block +} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go index 983f28560..eb606bf88 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go @@ -243,6 +243,15 @@ func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _Fcntl return _OK } + case _FCNTL_LOCK_TIMEOUT: + if file, ok := file.(FileSharedMemory); ok { + if iface, ok := file.SharedMemory().(interface{ shmEnableBlocking(bool) }); ok { + if i := util.ReadUint32(mod, pArg); i == 0 || i == 1 { + iface.shmEnableBlocking(i != 0) + } + } + } + case _FCNTL_PERSIST_WAL: if file, ok := file.(FilePersistentWAL); ok { if i := util.ReadUint32(mod, pArg); int32(i) >= 0 { @@ -347,7 +356,7 @@ func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _Fcntl out = err.Error() } if out != "" { - fn := mod.ExportedFunction("malloc") + fn := mod.ExportedFunction("sqlite3_malloc64") stack := [...]uint64{uint64(len(out) + 1)} if err := fn.CallWithStack(ctx, stack[:]); err != nil { panic(err) |