Windows locks.

This commit is contained in:
Nuno Cruces
2023-02-08 15:58:36 +00:00
parent f0a14030e5
commit ecc25a651f
5 changed files with 95 additions and 9 deletions

View File

@@ -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
View File

@@ -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
View File

@@ -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=

View File

@@ -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()

View File

@@ -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)
}