mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Fix WAL flakiness on Windows (#253)
This commit is contained in:
24
vfs/file.go
24
vfs/file.go
@@ -6,9 +6,8 @@ import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/util/osutil"
|
||||
)
|
||||
|
||||
type vfsOS struct{}
|
||||
@@ -40,7 +39,7 @@ func (vfsOS) Delete(path string, syncDir bool) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if canSyncDirs && syncDir {
|
||||
if isUnix && syncDir {
|
||||
f, err := os.Open(filepath.Dir(path))
|
||||
if err != nil {
|
||||
return _OK
|
||||
@@ -96,7 +95,7 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
|
||||
if name == nil {
|
||||
f, err = os.CreateTemp(os.Getenv("SQLITE_TMPDIR"), "*.db")
|
||||
} else {
|
||||
f, err = osutil.OpenFile(name.String(), oflags, 0666)
|
||||
f, err = os.OpenFile(name.String(), oflags, 0666)
|
||||
}
|
||||
if err != nil {
|
||||
if name == nil {
|
||||
@@ -118,7 +117,7 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
|
||||
return nil, flags, _IOERR_FSTAT
|
||||
}
|
||||
}
|
||||
if flags&OPEN_DELETEONCLOSE != 0 {
|
||||
if isUnix && flags&OPEN_DELETEONCLOSE != 0 {
|
||||
os.Remove(f.Name())
|
||||
}
|
||||
|
||||
@@ -127,7 +126,8 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
|
||||
psow: true,
|
||||
atomic: osBatchAtomic(f),
|
||||
readOnly: flags&OPEN_READONLY != 0,
|
||||
syncDir: canSyncDirs && isCreate && isJournl,
|
||||
syncDir: isUnix && isCreate && isJournl,
|
||||
delete: !isUnix && flags&OPEN_DELETEONCLOSE != 0,
|
||||
shm: NewSharedMemory(name.String()+"-shm", flags),
|
||||
}
|
||||
return &file, flags, nil
|
||||
@@ -141,6 +141,7 @@ type vfsFile struct {
|
||||
keepWAL bool
|
||||
syncDir bool
|
||||
atomic bool
|
||||
delete bool
|
||||
psow bool
|
||||
}
|
||||
|
||||
@@ -154,6 +155,9 @@ var (
|
||||
)
|
||||
|
||||
func (f *vfsFile) Close() error {
|
||||
if f.delete {
|
||||
defer os.Remove(f.Name())
|
||||
}
|
||||
if f.shm != nil {
|
||||
f.shm.Close()
|
||||
}
|
||||
@@ -177,7 +181,7 @@ func (f *vfsFile) Sync(flags SyncFlag) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if canSyncDirs && f.syncDir {
|
||||
if isUnix && f.syncDir {
|
||||
f.syncDir = false
|
||||
d, err := os.Open(filepath.Dir(f.File.Name()))
|
||||
if err != nil {
|
||||
@@ -208,6 +212,9 @@ func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic {
|
||||
if f.psow {
|
||||
ret |= IOCAP_POWERSAFE_OVERWRITE
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
ret |= IOCAP_UNDELETABLE_WHEN_OPEN
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -216,6 +223,9 @@ func (f *vfsFile) SizeHint(size int64) error {
|
||||
}
|
||||
|
||||
func (f *vfsFile) HasMoved() (bool, error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
return false, nil
|
||||
}
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
isUnix = false
|
||||
_O_NOFOLLOW = 0
|
||||
canSyncDirs = false
|
||||
)
|
||||
|
||||
func osAccess(path string, flags AccessFlag) error {
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
isUnix = true
|
||||
_O_NOFOLLOW = unix.O_NOFOLLOW
|
||||
canSyncDirs = true
|
||||
)
|
||||
|
||||
func osAccess(path string, flags AccessFlag) error {
|
||||
|
||||
@@ -179,14 +179,13 @@ func osLockExTimeout(file *os.File, flags, start, len uint32, timeout time.Durat
|
||||
if err != windows.ERROR_IO_PENDING {
|
||||
return err
|
||||
}
|
||||
defer windows.CancelIoEx(fd, overlapped)
|
||||
|
||||
ms := (timeout + time.Millisecond - 1) / time.Millisecond
|
||||
rc, err := windows.WaitForSingleObject(event, uint32(ms))
|
||||
if rc == windows.WAIT_OBJECT_0 {
|
||||
return nil
|
||||
}
|
||||
defer windows.CancelIoEx(fd, overlapped)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,14 +7,12 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/ncruces/go-sqlite3/util/osutil"
|
||||
)
|
||||
|
||||
type vfsShm struct {
|
||||
@@ -33,7 +31,7 @@ type vfsShm struct {
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// var _ blockingSharedMemory = &vfsShm{}
|
||||
var _ blockingSharedMemory = &vfsShm{}
|
||||
|
||||
func (s *vfsShm) Close() error {
|
||||
// Unmap regions.
|
||||
@@ -48,12 +46,19 @@ func (s *vfsShm) Close() error {
|
||||
|
||||
func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
if s.File == nil {
|
||||
f, err := osutil.OpenFile(s.path,
|
||||
os.O_RDWR|os.O_CREATE|syscall.O_NONBLOCK, 0666)
|
||||
path, err := windows.UTF16PtrFromString(s.path)
|
||||
if err != nil {
|
||||
return _CANTOPEN
|
||||
}
|
||||
s.File = f
|
||||
h, err := windows.CreateFile(path,
|
||||
windows.GENERIC_READ|windows.GENERIC_WRITE,
|
||||
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE,
|
||||
nil, windows.OPEN_ALWAYS,
|
||||
windows.FILE_ATTRIBUTE_NORMAL|windows.FILE_FLAG_OVERLAPPED, 0)
|
||||
if err != nil {
|
||||
return _CANTOPEN
|
||||
}
|
||||
s.File = os.NewFile(uintptr(h), s.path)
|
||||
}
|
||||
if s.fileLock {
|
||||
return _OK
|
||||
@@ -185,6 +190,6 @@ func (s *vfsShm) shmUnmap(delete bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// func (s *vfsShm) shmEnableBlocking(block bool) {
|
||||
// s.blocking = block
|
||||
// }
|
||||
func (s *vfsShm) shmEnableBlocking(block bool) {
|
||||
s.blocking = block
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user