Skip to content

Commit

Permalink
Add Windows support.
Browse files Browse the repository at this point in the history
  • Loading branch information
benbjohnson committed Jun 11, 2014
1 parent 5e9ce18 commit c2577db
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 18 deletions.
13 changes: 0 additions & 13 deletions bolt.go

This file was deleted.

33 changes: 33 additions & 0 deletions bolt_darwin.go
Original file line number Diff line number Diff line change
@@ -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)
}
21 changes: 21 additions & 0 deletions bolt_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
60 changes: 60 additions & 0 deletions bolt_windows.go
Original file line number Diff line number Diff line change
@@ -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
}
14 changes: 9 additions & 5 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"hash/fnv"
"os"
"sync"
"syscall"
"unsafe"
)

Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit c2577db

Please sign in to comment.