Merge pull request #259 from davecgh/jrick_msync

Fix bolt on OpenBSD
pull/34/head
Ben Johnson 2014-09-22 11:53:19 -06:00
commit d285804df1
6 changed files with 51 additions and 17 deletions

View File

@ -1,13 +1,12 @@
package bolt
import (
"os"
"syscall"
)
var odirect = syscall.O_DIRECT
// fdatasync flushes written data to a file descriptor.
func fdatasync(f *os.File) error {
return syscall.Fdatasync(int(f.Fd()))
func fdatasync(db *DB) error {
return syscall.Fdatasync(int(db.file.Fd()))
}

29
bolt_openbsd.go Normal file
View File

@ -0,0 +1,29 @@
package bolt
import (
"syscall"
"unsafe"
)
const (
msAsync = 1 << iota // perform asynchronous writes
msSync // perform synchronous writes
msInvalidate // invalidate cached data
)
var odirect int
func msync(db *DB) error {
_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate)
if errno != 0 {
return errno
}
return nil
}
func fdatasync(db *DB) error {
if db.data != nil {
return msync(db)
}
return db.file.Sync()
}

View File

@ -11,8 +11,8 @@ import (
var odirect int
// fdatasync flushes written data to a file descriptor.
func fdatasync(f *os.File) error {
return f.Sync()
func fdatasync(db *DB) error {
return db.file.Sync()
}
// flock acquires an advisory lock on a file descriptor.

View File

@ -1,14 +1,10 @@
// +build !windows,!plan9,!linux
// +build !windows,!plan9,!linux,!openbsd
package bolt
import (
"os"
)
var odirect int
// fdatasync flushes written data to a file descriptor.
func fdatasync(f *os.File) error {
return f.Sync()
func fdatasync(db *DB) error {
return db.file.Sync()
}

12
db.go
View File

@ -4,6 +4,7 @@ import (
"fmt"
"hash/fnv"
"os"
"runtime"
"runtime/debug"
"strings"
"sync"
@ -23,6 +24,12 @@ const version = 2
// Represents a marker value to indicate that a file is a Bolt DB.
const magic uint32 = 0xED0CDAED
// IgnoreNoSync specifies whether the NoSync field of a DB is ignored when
// syncing changes to a file. This is required as some operating systems,
// such as OpenBSD, do not have a unified buffer cache (UBC) and writes
// must be synchronzied using the msync(2) syscall.
const IgnoreNoSync = runtime.GOOS == "openbsd"
// DB represents a collection of buckets persisted to a file on disk.
// All data access is performed through transactions which can be obtained through the DB.
// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
@ -39,6 +46,9 @@ type DB struct {
// a system failure or database corruption. Do not set this flag for
// normal use.
//
// If the package global IgnoreNoSync constant is true, this value is
// ignored. See the comment on that constant for more details.
//
// THIS IS UNSAFE. PLEASE USE WITH CAUTION.
NoSync bool
@ -263,7 +273,7 @@ func (db *DB) init() error {
if _, err := db.ops.writeAt(buf, 0); err != nil {
return err
}
if err := fdatasync(db.file); err != nil {
if err := fdatasync(db); err != nil {
return err
}

8
tx.go
View File

@ -425,8 +425,8 @@ func (tx *Tx) write() error {
// Update statistics.
tx.stats.Write++
}
if !tx.db.NoSync {
if err := fdatasync(tx.db.file); err != nil {
if !tx.db.NoSync || IgnoreNoSync {
if err := fdatasync(tx.db); err != nil {
return err
}
}
@ -448,8 +448,8 @@ func (tx *Tx) writeMeta() error {
if _, err := tx.db.ops.writeAt(buf, int64(p.id)*int64(tx.db.pageSize)); err != nil {
return err
}
if !tx.db.NoSync {
if err := fdatasync(tx.db.file); err != nil {
if !tx.db.NoSync || IgnoreNoSync {
if err := fdatasync(tx.db); err != nil {
return err
}
}