...
1
2
3
4 package bbolt
5
6 import (
7 "fmt"
8 "syscall"
9 "time"
10 "unsafe"
11
12 "golang.org/x/sys/unix"
13 )
14
15
16 func flock(db *DB, exclusive bool, timeout time.Duration) error {
17 var t time.Time
18 if timeout != 0 {
19 t = time.Now()
20 }
21 fd := db.file.Fd()
22 var lockType int16
23 if exclusive {
24 lockType = syscall.F_WRLCK
25 } else {
26 lockType = syscall.F_RDLCK
27 }
28 for {
29
30 lock := syscall.Flock_t{Type: lockType}
31 err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
32 if err == nil {
33 return nil
34 } else if err != syscall.EAGAIN {
35 return err
36 }
37
38
39 if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
40 return ErrTimeout
41 }
42
43
44 time.Sleep(flockRetryTimeout)
45 }
46 }
47
48
49 func funlock(db *DB) error {
50 var lock syscall.Flock_t
51 lock.Start = 0
52 lock.Len = 0
53 lock.Type = syscall.F_UNLCK
54 lock.Whence = 0
55 return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock)
56 }
57
58
59 func mmap(db *DB, sz int) error {
60
61 b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
62 if err != nil {
63 return err
64 }
65
66
67 if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil {
68 return fmt.Errorf("madvise: %s", err)
69 }
70
71
72 db.dataref = b
73 db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
74 db.datasz = sz
75 return nil
76 }
77
78
79 func munmap(db *DB) error {
80
81 if db.dataref == nil {
82 return nil
83 }
84
85
86 err := unix.Munmap(db.dataref)
87 db.dataref = nil
88 db.data = nil
89 db.datasz = 0
90 return err
91 }
92
View as plain text