diff options
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs')
-rw-r--r-- | vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go | 32 | ||||
-rw-r--r-- | vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go | 48 | ||||
-rw-r--r-- | vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go | 96 |
3 files changed, 86 insertions, 90 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go index 7d809b223..07de7c3d8 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go @@ -56,16 +56,12 @@ func osAllocate(file *os.File, size int64) error { return file.Truncate(size) } -func osUnlock(file *os.File, start, len int64) _ErrorCode { - err := unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &unix.Flock_t{ - Type: unix.F_UNLCK, - Start: start, - Len: len, - }) - if err != nil { - return _IOERR_UNLOCK - } - return _OK +func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { + return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) +} + +func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { + return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) } func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { @@ -88,10 +84,14 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d return osLockErrorCode(err, def) } -func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) -} - -func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) +func osUnlock(file *os.File, start, len int64) _ErrorCode { + err := unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &unix.Flock_t{ + Type: unix.F_UNLCK, + Start: start, + Len: len, + }) + if err != nil { + return _IOERR_UNLOCK + } + return _OK } 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 f5841fc20..6199c7b00 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go @@ -3,7 +3,6 @@ package vfs import ( - "math/rand" "os" "time" @@ -22,16 +21,12 @@ func osAllocate(file *os.File, size int64) error { return unix.Fallocate(int(file.Fd()), 0, 0, size) } -func osUnlock(file *os.File, start, len int64) _ErrorCode { - err := unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &unix.Flock_t{ - Type: unix.F_UNLCK, - Start: start, - Len: len, - }) - if err != nil { - return _IOERR_UNLOCK - } - return _OK +func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { + return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) +} + +func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { + return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) } func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { @@ -42,31 +37,22 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d } var err error switch { - case timeout == 0: - err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) case timeout < 0: err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLKW, &lock) default: - before := time.Now() - for { - err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) - if errno, _ := err.(unix.Errno); errno != unix.EAGAIN { - break - } - if time.Since(before) > timeout { - break - } - const sleepIncrement = 1024*1024 - 1 // power of two, ~1ms - time.Sleep(time.Duration(rand.Int63() & sleepIncrement)) - } + err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) } return osLockErrorCode(err, def) } -func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) -} - -func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) +func osUnlock(file *os.File, start, len int64) _ErrorCode { + err := unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &unix.Flock_t{ + Type: unix.F_UNLCK, + Start: start, + Len: len, + }) + if err != nil { + return _IOERR_UNLOCK + } + return _OK } 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 2872201b0..0398f4760 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go @@ -45,6 +45,7 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { osUnlock(file, _SHARED_FIRST, _SHARED_SIZE) // Acquire the EXCLUSIVE lock. + // Can't wait here, because the file is not OVERLAPPED. rc := osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) if rc != _OK { @@ -106,64 +107,73 @@ func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { return false, rc } -func osUnlock(file *os.File, start, len uint32) _ErrorCode { - err := windows.UnlockFileEx(windows.Handle(file.Fd()), - 0, len, 0, &windows.Overlapped{Offset: start}) - if err == windows.ERROR_NOT_LOCKED { - return _OK - } - if err != nil { - return _IOERR_UNLOCK - } - return _OK +func osReadLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { + return osLock(file, 0, start, len, timeout, _IOERR_RDLOCK) +} + +func osWriteLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { + return osLock(file, windows.LOCKFILE_EXCLUSIVE_LOCK, start, len, timeout, _IOERR_LOCK) } func osLock(file *os.File, flags, start, len uint32, timeout time.Duration, def _ErrorCode) _ErrorCode { var err error switch { case timeout == 0: - err = osLockEx(file, flags|windows.LOCKFILE_FAIL_IMMEDIATELY, start, len, 0) + err = osLockEx(file, flags|windows.LOCKFILE_FAIL_IMMEDIATELY, start, len) case timeout < 0: - err = osLockEx(file, flags, start, len, 0) + err = osLockEx(file, flags, start, len) default: - var event windows.Handle - event, err = windows.CreateEvent(nil, 1, 0, nil) - if err != nil { - break - } - defer windows.CloseHandle(event) - - err = osLockEx(file, flags, start, len, event) - if err == windows.ERROR_IO_PENDING { - rc, serr := windows.WaitForSingleObject(event, uint32(timeout/time.Millisecond)) - if rc == windows.WAIT_OBJECT_0 { - return _OK - } - if serr != nil { - err = serr - } else { - err = windows.Errno(rc) - } - windows.CancelIo(windows.Handle(file.Fd())) - } + err = osLockExTimeout(file, flags, start, len, timeout) } return osLockErrorCode(err, def) } -func osLockEx(file *os.File, flags, start, len uint32, event windows.Handle) error { - return windows.LockFileEx(windows.Handle(file.Fd()), flags, - 0, len, 0, &windows.Overlapped{ - Offset: start, - HEvent: event, - }) +func osUnlock(file *os.File, start, len uint32) _ErrorCode { + err := windows.UnlockFileEx(windows.Handle(file.Fd()), + 0, len, 0, &windows.Overlapped{Offset: start}) + if err == windows.ERROR_NOT_LOCKED { + return _OK + } + if err != nil { + return _IOERR_UNLOCK + } + return _OK } -func osReadLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { - return osLock(file, 0, start, len, timeout, _IOERR_RDLOCK) +func osLockEx(file *os.File, flags, start, len uint32) error { + return windows.LockFileEx(windows.Handle(file.Fd()), flags, + 0, len, 0, &windows.Overlapped{Offset: start}) } -func osWriteLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { - return osLock(file, windows.LOCKFILE_EXCLUSIVE_LOCK, start, len, timeout, _IOERR_LOCK) +func osLockExTimeout(file *os.File, flags, start, len uint32, timeout time.Duration) error { + event, err := windows.CreateEvent(nil, 1, 0, nil) + if err != nil { + return err + } + defer windows.CloseHandle(event) + + fd := windows.Handle(file.Fd()) + overlapped := &windows.Overlapped{ + Offset: start, + HEvent: event, + } + + err = windows.LockFileEx(fd, flags, 0, len, 0, overlapped) + if err != windows.ERROR_IO_PENDING { + return err + } + + 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 + } + return windows.Errno(rc) } func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { @@ -175,8 +185,8 @@ func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { switch errno { case windows.ERROR_LOCK_VIOLATION, - windows.ERROR_IO_PENDING, windows.ERROR_OPERATION_ABORTED, + windows.ERROR_IO_PENDING, windows.WAIT_TIMEOUT: return _BUSY } |