@@ -8,6 +8,38 @@ import (
8
8
"unsafe"
9
9
)
10
10
11
+ // LockFileEx code derived from golang build filemutex_windows.go @ v1.5.1
12
+ var (
13
+ modkernel32 = syscall .NewLazyDLL ("kernel32.dll" )
14
+ procLockFileEx = modkernel32 .NewProc ("LockFileEx" )
15
+ procUnlockFileEx = modkernel32 .NewProc ("UnlockFileEx" )
16
+ )
17
+
18
+ const (
19
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
20
+ flagLockExclusive = 2
21
+ flagLockFailImmediately = 1
22
+
23
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
24
+ errLockViolation syscall.Errno = 0x21
25
+ )
26
+
27
+ func lockFileEx (h syscall.Handle , flags , reserved , locklow , lockhigh uint32 , ol * syscall.Overlapped ) (err error ) {
28
+ r , _ , err := procLockFileEx .Call (uintptr (h ), uintptr (flags ), uintptr (reserved ), uintptr (locklow ), uintptr (lockhigh ), uintptr (unsafe .Pointer (ol )))
29
+ if r == 0 {
30
+ return err
31
+ }
32
+ return nil
33
+ }
34
+
35
+ func unlockFileEx (h syscall.Handle , reserved , locklow , lockhigh uint32 , ol * syscall.Overlapped ) (err error ) {
36
+ r , _ , err := procUnlockFileEx .Call (uintptr (h ), uintptr (reserved ), uintptr (locklow ), uintptr (lockhigh ), uintptr (unsafe .Pointer (ol )), 0 )
37
+ if r == 0 {
38
+ return err
39
+ }
40
+ return nil
41
+ }
42
+
11
43
var odirect int
12
44
13
45
// fdatasync flushes written data to a file descriptor.
@@ -16,13 +48,37 @@ func fdatasync(db *DB) error {
16
48
}
17
49
18
50
// flock acquires an advisory lock on a file descriptor.
19
- func flock (f * os.File , _ bool , _ time.Duration ) error {
20
- return nil
51
+ func flock (f * os.File , exclusive bool , timeout time.Duration ) error {
52
+ var t time.Time
53
+ for {
54
+ // If we're beyond our timeout then return an error.
55
+ // This can only occur after we've attempted a flock once.
56
+ if t .IsZero () {
57
+ t = time .Now ()
58
+ } else if timeout > 0 && time .Since (t ) > timeout {
59
+ return ErrTimeout
60
+ }
61
+
62
+ var flag uint32 = flagLockFailImmediately
63
+ if exclusive {
64
+ flag |= flagLockExclusive
65
+ }
66
+
67
+ err := lockFileEx (syscall .Handle (f .Fd ()), flag , 0 , 1 , 0 , & syscall.Overlapped {})
68
+ if err == nil {
69
+ return nil
70
+ } else if err != errLockViolation {
71
+ return err
72
+ }
73
+
74
+ // Wait for a bit and try again.
75
+ time .Sleep (50 * time .Millisecond )
76
+ }
21
77
}
22
78
23
79
// funlock releases an advisory lock on a file descriptor.
24
80
func funlock (f * os.File ) error {
25
- return nil
81
+ return unlockFileEx ( syscall . Handle ( f . Fd ()), 0 , 1 , 0 , & syscall. Overlapped {})
26
82
}
27
83
28
84
// mmap memory maps a DB's data file.
0 commit comments