Fix WAL flakiness on Windows (#253)

This commit is contained in:
Nuno Cruces
2025-03-26 02:13:30 +00:00
committed by GitHub
parent 0ba393199a
commit a67165eb09
9 changed files with 43 additions and 165 deletions

View File

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

View File

@@ -8,8 +8,8 @@ import (
)
const (
isUnix = false
_O_NOFOLLOW = 0
canSyncDirs = false
)
func osAccess(path string, flags AccessFlag) error {

View File

@@ -10,8 +10,8 @@ import (
)
const (
isUnix = true
_O_NOFOLLOW = unix.O_NOFOLLOW
canSyncDirs = true
)
func osAccess(path string, flags AccessFlag) error {

View File

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

View File

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