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