aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2014-06-11 11:11:21 -0600
committerBen Johnson <benbjohnson@yahoo.com>2014-06-11 11:11:21 -0600
commitc2577db1c22e0bb64ea3df16e9424e6dce1d55ab (patch)
tree4deb66bd7914dd52129b62bfb99ee2238e76af66
parentMerge pull request #189 from benbjohnson/increase-max-nodes-per-page (diff)
downloaddedo-c2577db1c22e0bb64ea3df16e9424e6dce1d55ab.tar.gz
dedo-c2577db1c22e0bb64ea3df16e9424e6dce1d55ab.tar.xz
Add Windows support.
-rw-r--r--bolt.go13
-rw-r--r--bolt_darwin.go33
-rw-r--r--bolt_linux.go21
-rw-r--r--bolt_windows.go60
-rw-r--r--db.go14
5 files changed, 123 insertions, 18 deletions
diff --git a/bolt.go b/bolt.go
deleted file mode 100644
index a3f1eac..0000000
--- a/bolt.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !linux
-
-package bolt
-
-import (
- "os"
-)
-
-var odirect int
-
-func fdatasync(f *os.File) error {
- return f.Sync()
-}
diff --git a/bolt_darwin.go b/bolt_darwin.go
new file mode 100644
index 0000000..557de72
--- /dev/null
+++ b/bolt_darwin.go
@@ -0,0 +1,33 @@
+package bolt
+
+import (
+ "os"
+ "syscall"
+)
+
+var odirect int
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(f *os.File) error {
+ return f.Sync()
+}
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(f *os.File) error {
+ return syscall.Flock(int(f.Fd()), syscall.LOCK_EX)
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(f *os.File) error {
+ return syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
+}
+
+// mmap memory maps a file to a byte slice.
+func mmap(f *os.File, sz int) ([]byte, error) {
+ return syscall.Mmap(int(f.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED)
+}
+
+// munmap unmaps a pointer from a file.
+func munmap(b []byte) error {
+ return syscall.Munmap(b)
+}
diff --git a/bolt_linux.go b/bolt_linux.go
index 4351db5..9aba955 100644
--- a/bolt_linux.go
+++ b/bolt_linux.go
@@ -7,6 +7,27 @@ import (
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()))
}
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(f *os.File) error {
+ return syscall.Flock(int(f.Fd()), syscall.LOCK_EX)
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(f *os.File) error {
+ return syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
+}
+
+// mmap memory maps a file to a byte slice.
+func mmap(f *os.File, sz int) ([]byte, error) {
+ return syscall.Mmap(int(f.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED)
+}
+
+// munmap unmaps a pointer from a file.
+func munmap(b []byte) error {
+ return syscall.Munmap(b)
+}
diff --git a/bolt_windows.go b/bolt_windows.go
new file mode 100644
index 0000000..9962f03
--- /dev/null
+++ b/bolt_windows.go
@@ -0,0 +1,60 @@
+package bolt
+
+import (
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+var odirect int
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(f *os.File) error {
+ return f.Sync()
+}
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(f *os.File) error {
+ return nil
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(f *os.File) error {
+ return nil
+}
+
+// mmap memory maps a file to a byte slice.
+// Based on: https://github.com/edsrzf/mmap-go
+func mmap(f *os.File, sz int) ([]byte, error) {
+ // Open a file mapping handle.
+ sizelo, sizehi := uint32(sz>>32), uint32(sz&0xffffffff)
+ h, errno := syscall.CreateFileMapping(syscall.Handle(f.Fd()), nil, syscall.PAGE_READONLY, sizehi, sizelo, nil)
+ if h == 0 {
+ return nil, os.NewSyscallError("CreateFileMapping", errno)
+ }
+
+ // Create the memory map.
+ addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz))
+ if addr == 0 {
+ return nil, os.NewSyscallError("MapViewOfFile", errno)
+ }
+
+ // Close mapping handle.
+ if err := syscall.CloseHandle(syscall.Handle(h)); err != nil {
+ return nil, os.NewSyscallError("CloseHandle", err)
+ }
+
+ // Convert to a byte slice.
+ b := ((*[0xFFFFFFF]byte)(unsafe.Pointer(addr)))[0:sz]
+ return b, nil
+}
+
+// munmap unmaps a pointer from a file.
+// Based on: https://github.com/edsrzf/mmap-go
+func munmap(b []byte) error {
+ addr := (uintptr)(unsafe.Pointer(&b[0]))
+ if err := syscall.UnmapViewOfFile(addr); err != nil {
+ return os.NewSyscallError("UnmapViewOfFile", err)
+ }
+ return nil
+}
diff --git a/db.go b/db.go
index d759b1b..2132f9c 100644
--- a/db.go
+++ b/db.go
@@ -6,7 +6,6 @@ import (
"hash/fnv"
"os"
"sync"
- "syscall"
"unsafe"
)
@@ -120,7 +119,7 @@ func Open(path string, mode os.FileMode) (*DB, error) {
// Lock file so that other processes using Bolt cannot use the database
// at the same time. This would cause corruption since the two processes
// would write meta pages and free pages separately.
- if err := syscall.Flock(int(db.file.Fd()), syscall.LOCK_EX); err != nil {
+ if err := flock(db.file); err != nil {
_ = db.close()
return nil, err
}
@@ -192,8 +191,13 @@ func (db *DB) mmap(minsz int) error {
}
size = db.mmapSize(size)
+ // Truncate the database to the size of the mmap.
+ if err := db.file.Truncate(int64(size)); err != nil {
+ return fmt.Errorf("truncate: %s", err)
+ }
+
// Memory-map the data file as a byte slice.
- if db.data, err = syscall.Mmap(int(db.file.Fd()), 0, size, syscall.PROT_READ, syscall.MAP_SHARED); err != nil {
+ if db.data, err = mmap(db.file, size); err != nil {
return err
}
@@ -215,7 +219,7 @@ func (db *DB) mmap(minsz int) error {
// munmap unmaps the data file from memory.
func (db *DB) munmap() error {
if db.data != nil {
- if err := syscall.Munmap(db.data); err != nil {
+ if err := munmap(db.data); err != nil {
return fmt.Errorf("unmap error: " + err.Error())
}
db.data = nil
@@ -314,7 +318,7 @@ func (db *DB) close() error {
// Close file handles.
if db.file != nil {
// Unlock the file.
- _ = syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN)
+ _ = funlock(db.file)
// Close the file descriptor.
if err := db.file.Close(); err != nil {