|
|
@@ -16,6 +16,8 @@ var (
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
+ lockExt = ".lock"
|
|
|
+
|
|
|
// see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
|
|
|
flagLockExclusive = 2
|
|
|
flagLockFailImmediately = 1
|
|
|
@@ -46,7 +48,16 @@ func fdatasync(db *DB) error {
|
|
|
}
|
|
|
|
|
|
// flock acquires an advisory lock on a file descriptor.
|
|
|
-func flock(f *os.File, exclusive bool, timeout time.Duration) error {
|
|
|
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
|
|
|
+ // Create a separate lock file on windows because a process
|
|
|
+ // cannot share an exclusive lock on the same file. This is
|
|
|
+ // needed during Tx.WriteTo().
|
|
|
+ f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ db.lockfile = f
|
|
|
+
|
|
|
var t time.Time
|
|
|
for {
|
|
|
// If we're beyond our timeout then return an error.
|
|
|
@@ -62,7 +73,7 @@ func flock(f *os.File, exclusive bool, timeout time.Duration) error {
|
|
|
flag |= flagLockExclusive
|
|
|
}
|
|
|
|
|
|
- err := lockFileEx(syscall.Handle(f.Fd()), flag, 0, 1, 0, &syscall.Overlapped{})
|
|
|
+ err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{})
|
|
|
if err == nil {
|
|
|
return nil
|
|
|
} else if err != errLockViolation {
|
|
|
@@ -75,8 +86,11 @@ func flock(f *os.File, exclusive bool, timeout time.Duration) error {
|
|
|
}
|
|
|
|
|
|
// funlock releases an advisory lock on a file descriptor.
|
|
|
-func funlock(f *os.File) error {
|
|
|
- return unlockFileEx(syscall.Handle(f.Fd()), 0, 1, 0, &syscall.Overlapped{})
|
|
|
+func funlock(db *DB) error {
|
|
|
+ err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{})
|
|
|
+ db.lockfile.Close()
|
|
|
+ os.Remove(db.path+lockExt)
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
// mmap memory maps a DB's data file.
|