aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2015-02-16 16:45:58 -0700
committerBen Johnson <benbjohnson@yahoo.com>2015-02-16 16:45:58 -0700
commitc8ecb61df213b389af9da90983fc8bf5133e1007 (patch)
treeed4d491b6bfc44df308777f2ce1c2580caf2d543
parentREADME (diff)
parentFix large mmap resize. (diff)
downloaddedo-c8ecb61df213b389af9da90983fc8bf5133e1007.tar.gz
dedo-c8ecb61df213b389af9da90983fc8bf5133e1007.tar.xz
Merge pull request #304 from benbjohnson/fix-large-resize
Fix large mmap resize
-rw-r--r--db.go4
-rw-r--r--db_test.go61
2 files changed, 63 insertions, 2 deletions
diff --git a/db.go b/db.go
index 773620d..4775850 100644
--- a/db.go
+++ b/db.go
@@ -231,9 +231,9 @@ func (db *DB) mmapSize(size int) (int, error) {
}
// If larger than 1GB then grow by 1GB at a time.
- sz := int64(size) + int64(maxMmapStep)
+ sz := int64(size)
if remainder := sz % int64(maxMmapStep); remainder > 0 {
- sz -= remainder
+ sz += int64(maxMmapStep) - remainder
}
// Ensure that the mmap size is a multiple of the page size.
diff --git a/db_test.go b/db_test.go
index 4f05ad9..ecff7d8 100644
--- a/db_test.go
+++ b/db_test.go
@@ -1,6 +1,7 @@
package bolt_test
import (
+ "encoding/binary"
"errors"
"flag"
"fmt"
@@ -125,6 +126,56 @@ func TestOpen_Size(t *testing.T) {
}
}
+// Ensure that opening a database beyond the max step size does not increase its size.
+// https://github.com/boltdb/bolt/issues/303
+func TestOpen_Size_Large(t *testing.T) {
+ if testing.Short() {
+ t.Skip("short mode")
+ }
+
+ // Open a data file.
+ db := NewTestDB()
+ path := db.Path()
+ defer db.Close()
+
+ // Insert until we get above the minimum 4MB size.
+ var index uint64
+ for i := 0; i < 10000; i++ {
+ ok(t, db.Update(func(tx *bolt.Tx) error {
+ b, _ := tx.CreateBucketIfNotExists([]byte("data"))
+ for j := 0; j < 1000; j++ {
+ ok(t, b.Put(u64tob(index), make([]byte, 50)))
+ index++
+ }
+ return nil
+ }))
+ }
+
+ // Close database and grab the size.
+ db.DB.Close()
+ sz := fileSize(path)
+ if sz == 0 {
+ t.Fatalf("unexpected new file size: %d", sz)
+ } else if sz < (1 << 30) {
+ t.Fatalf("expected larger initial size: %d", sz)
+ }
+
+ // Reopen database, update, and check size again.
+ db0, err := bolt.Open(path, 0666, nil)
+ ok(t, err)
+ ok(t, db0.Update(func(tx *bolt.Tx) error { return tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}) }))
+ ok(t, db0.Close())
+ newSz := fileSize(path)
+ if newSz == 0 {
+ t.Fatalf("unexpected new file size: %d", newSz)
+ }
+
+ // Compare the original size with the new size.
+ if sz != newSz {
+ t.Fatalf("unexpected file growth: %d => %d", sz, newSz)
+ }
+}
+
// Ensure that a re-opened database is consistent.
func TestOpen_Check(t *testing.T) {
path := tempfile()
@@ -699,3 +750,13 @@ func fileSize(path string) int64 {
func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
+
+// u64tob converts a uint64 into an 8-byte slice.
+func u64tob(v uint64) []byte {
+ b := make([]byte, 8)
+ binary.BigEndian.PutUint64(b, v)
+ return b
+}
+
+// btou64 converts an 8-byte slice into an uint64.
+func btou64(b []byte) uint64 { return binary.BigEndian.Uint64(b) }