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 package bolt
import ( import (
"os"
"syscall" "syscall"
) )
var odirect = syscall.O_DIRECT var odirect = syscall.O_DIRECT
// fdatasync flushes written data to a file descriptor. // fdatasync flushes written data to a file descriptor.
func fdatasync(f *os.File) error { func fdatasync(db *DB) error {
return syscall.Fdatasync(int(f.Fd())) 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 var odirect int
// fdatasync flushes written data to a file descriptor. // fdatasync flushes written data to a file descriptor.
func fdatasync(f *os.File) error { func fdatasync(db *DB) error {
return f.Sync() return db.file.Sync()
} }
// flock acquires an advisory lock on a file descriptor. // 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 package bolt
import (
"os"
)
var odirect int var odirect int
// fdatasync flushes written data to a file descriptor. // fdatasync flushes written data to a file descriptor.
func fdatasync(f *os.File) error { func fdatasync(db *DB) error {
return f.Sync() return db.file.Sync()
} }

12
db.go
View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"hash/fnv" "hash/fnv"
"os" "os"
"runtime"
"runtime/debug" "runtime/debug"
"strings" "strings"
"sync" "sync"
@ -23,6 +24,12 @@ const version = 2
// Represents a marker value to indicate that a file is a Bolt DB. // Represents a marker value to indicate that a file is a Bolt DB.
const magic uint32 = 0xED0CDAED 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. // 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 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. // 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 // a system failure or database corruption. Do not set this flag for
// normal use. // 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. // THIS IS UNSAFE. PLEASE USE WITH CAUTION.
NoSync bool NoSync bool
@ -263,7 +273,7 @@ func (db *DB) init() error {
if _, err := db.ops.writeAt(buf, 0); err != nil { if _, err := db.ops.writeAt(buf, 0); err != nil {
return err return err
} }
if err := fdatasync(db.file); err != nil { if err := fdatasync(db); err != nil {
return err return err
} }

8
tx.go
View File

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