.github
alerting
client
config
controller
core
docs
example
jsonpath
k8s
k8stest
metric
pattern
security
storage
util
vendor
cloud.google.com
github.com
TwinProduction
beorn7
boltdb
bolt
.gitignore
LICENSE
Makefile
README.md
appveyor.yml
bolt_386.go
bolt_amd64.go
bolt_arm.go
bolt_arm64.go
bolt_linux.go
bolt_openbsd.go
bolt_ppc.go
bolt_ppc64.go
bolt_ppc64le.go
bolt_s390x.go
bolt_unix.go
bolt_unix_solaris.go
bolt_windows.go
boltsync_unix.go
bucket.go
cursor.go
db.go
doc.go
errors.go
freelist.go
node.go
page.go
tx.go
cespare
davecgh
go-ping
gogo
golang
google
googleapis
gorilla
imdario
json-iterator
matttproud
miekg
modern-go
prometheus
spf13
golang.org
google.golang.org
gopkg.in
k8s.io
sigs.k8s.io
modules.txt
watchdog
web
.dockerignore
.gitattributes
.gitignore
Dockerfile
LICENSE.md
Makefile
README.md
config.yaml
go.mod
go.sum
main.go
91 lines
2.0 KiB
Go
91 lines
2.0 KiB
Go
package bolt
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// flock acquires an advisory lock on a file descriptor.
|
|
func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
|
|
var t time.Time
|
|
for {
|
|
// If we're beyond our timeout then return an error.
|
|
// This can only occur after we've attempted a flock once.
|
|
if t.IsZero() {
|
|
t = time.Now()
|
|
} else if timeout > 0 && time.Since(t) > timeout {
|
|
return ErrTimeout
|
|
}
|
|
var lock syscall.Flock_t
|
|
lock.Start = 0
|
|
lock.Len = 0
|
|
lock.Pid = 0
|
|
lock.Whence = 0
|
|
lock.Pid = 0
|
|
if exclusive {
|
|
lock.Type = syscall.F_WRLCK
|
|
} else {
|
|
lock.Type = syscall.F_RDLCK
|
|
}
|
|
err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock)
|
|
if err == nil {
|
|
return nil
|
|
} else if err != syscall.EAGAIN {
|
|
return err
|
|
}
|
|
|
|
// Wait for a bit and try again.
|
|
time.Sleep(50 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
// funlock releases an advisory lock on a file descriptor.
|
|
func funlock(db *DB) error {
|
|
var lock syscall.Flock_t
|
|
lock.Start = 0
|
|
lock.Len = 0
|
|
lock.Type = syscall.F_UNLCK
|
|
lock.Whence = 0
|
|
return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock)
|
|
}
|
|
|
|
// mmap memory maps a DB's data file.
|
|
func mmap(db *DB, sz int) error {
|
|
// Map the data file to memory.
|
|
b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Advise the kernel that the mmap is accessed randomly.
|
|
if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil {
|
|
return fmt.Errorf("madvise: %s", err)
|
|
}
|
|
|
|
// Save the original byte slice and convert to a byte array pointer.
|
|
db.dataref = b
|
|
db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
|
|
db.datasz = sz
|
|
return nil
|
|
}
|
|
|
|
// munmap unmaps a DB's data file from memory.
|
|
func munmap(db *DB) error {
|
|
// Ignore the unmap if we have no mapped data.
|
|
if db.dataref == nil {
|
|
return nil
|
|
}
|
|
|
|
// Unmap using the original byte slice.
|
|
err := unix.Munmap(db.dataref)
|
|
db.dataref = nil
|
|
db.data = nil
|
|
db.datasz = 0
|
|
return err
|
|
}
|