mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Windows locks.
This commit is contained in:
@@ -15,5 +15,4 @@ Roadmap:
|
||||
- [x] port [`test_demovfs.c`](https://www.sqlite.org/src/doc/trunk/src/test_demovfs.c) to Go
|
||||
- branch [`wasi`](https://github.com/ncruces/go-sqlite3/tree/wasi) uses `test_demovfs.c` directly
|
||||
- [x] come up with a simple, nice API, enough for simple queries
|
||||
- [x] file locking, compatible with SQLite on Unix
|
||||
- [ ] file locking, compatible with SQLite on Windows
|
||||
- [x] file locking, compatible with SQLite on Windows/Unix
|
||||
1
go.mod
1
go.mod
@@ -6,4 +6,5 @@ require (
|
||||
github.com/ncruces/julianday v0.1.4
|
||||
github.com/tetratelabs/wazero v1.0.0-pre.8
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.5.0
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -4,3 +4,5 @@ github.com/tetratelabs/wazero v1.0.0-pre.8 h1:Ir82PWj79WCppH+9ny73eGY2qv+oCnE3Vw
|
||||
github.com/tetratelabs/wazero v1.0.0-pre.8/go.mod h1:u8wrFmpdrykiFK0DFPiFm5a4+0RzsdmXYVtijBKqUVo=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
func Test_vfsLock(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "linux", "darwin", "solaris":
|
||||
case "linux", "darwin", "solaris", "windows":
|
||||
//
|
||||
default:
|
||||
t.Skip()
|
||||
|
||||
@@ -1,33 +1,117 @@
|
||||
package sqlite3
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func deleteOnClose(f *os.File) {}
|
||||
|
||||
func (l *vfsFileLocker) GetShared() xErrorCode {
|
||||
return _OK
|
||||
// A PENDING lock is needed before acquiring a SHARED lock.
|
||||
if rc := l.readLock(_PENDING_BYTE, 1); rc != _OK {
|
||||
return rc
|
||||
}
|
||||
|
||||
// Acquire the SHARED lock.
|
||||
rc := l.readLock(_SHARED_FIRST, _SHARED_SIZE)
|
||||
|
||||
// Drop the temporary PENDING lock.
|
||||
if rc2 := l.unlock(_PENDING_BYTE, 1); rc == _OK {
|
||||
return rc2
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) GetReserved() xErrorCode {
|
||||
return _OK
|
||||
// Acquire the RESERVED lock.
|
||||
return l.writeLock(_RESERVED_BYTE, 1)
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) GetPending() xErrorCode {
|
||||
return _OK
|
||||
// Acquire the PENDING lock.
|
||||
return l.writeLock(_PENDING_BYTE, 1)
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) GetExclusive() xErrorCode {
|
||||
return _OK
|
||||
// Release the SHARED lock.
|
||||
l.unlock(_SHARED_FIRST, _SHARED_SIZE)
|
||||
|
||||
// Acquire the EXCLUSIVE lock.
|
||||
rc := l.writeLock(_SHARED_FIRST, _SHARED_SIZE)
|
||||
|
||||
// Reacquire the SHARED lock.
|
||||
if rc != _OK {
|
||||
l.readLock(_SHARED_FIRST, _SHARED_SIZE)
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) Downgrade() xErrorCode {
|
||||
// Release the SHARED lock.
|
||||
l.unlock(_SHARED_FIRST, _SHARED_SIZE)
|
||||
|
||||
// Reacquire the SHARED lock.
|
||||
if rc := l.readLock(_SHARED_FIRST, _SHARED_SIZE); rc != _OK {
|
||||
// This should never happen.
|
||||
// We should always be able to reacquire the read lock.
|
||||
return IOERR_RDLOCK
|
||||
}
|
||||
|
||||
// Release the PENDING and RESERVED locks.
|
||||
l.unlock(_RESERVED_BYTE, 1)
|
||||
l.unlock(_PENDING_BYTE, 1)
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) Release() xErrorCode {
|
||||
// Release all locks.
|
||||
l.unlock(_SHARED_FIRST, _SHARED_SIZE)
|
||||
l.unlock(_RESERVED_BYTE, 1)
|
||||
l.unlock(_PENDING_BYTE, 1)
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) CheckReserved() (bool, xErrorCode) {
|
||||
return false, _OK
|
||||
// Test the RESERVED lock.
|
||||
rc := l.readLock(_RESERVED_BYTE, 1)
|
||||
if rc == _OK {
|
||||
l.unlock(_RESERVED_BYTE, 1)
|
||||
}
|
||||
return rc != _OK, _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) unlock(start, len uint32) xErrorCode {
|
||||
err := windows.UnlockFileEx(windows.Handle(l.file.Fd()),
|
||||
0, len, 0, &windows.Overlapped{Offset: start})
|
||||
if err != nil {
|
||||
return IOERR_UNLOCK
|
||||
}
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) readLock(start, len uint32) xErrorCode {
|
||||
return l.errorCode(windows.LockFileEx(windows.Handle(l.file.Fd()),
|
||||
windows.LOCKFILE_FAIL_IMMEDIATELY,
|
||||
0, len, 0, &windows.Overlapped{Offset: start}),
|
||||
IOERR_LOCK)
|
||||
}
|
||||
|
||||
func (l *vfsFileLocker) writeLock(start, len uint32) xErrorCode {
|
||||
return l.errorCode(windows.LockFileEx(windows.Handle(l.file.Fd()),
|
||||
windows.LOCKFILE_FAIL_IMMEDIATELY|windows.LOCKFILE_EXCLUSIVE_LOCK,
|
||||
0, len, 0, &windows.Overlapped{Offset: start}),
|
||||
IOERR_LOCK)
|
||||
}
|
||||
|
||||
func (*vfsFileLocker) errorCode(err error, def xErrorCode) xErrorCode {
|
||||
if err == nil {
|
||||
return _OK
|
||||
}
|
||||
if errno, _ := err.(syscall.Errno); errno == windows.ERROR_INVALID_HANDLE {
|
||||
return def
|
||||
}
|
||||
return xErrorCode(BUSY)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user