mirror of https://github.com/etcd-io/bbolt.git
set slice capacity
This commit sets the capacity on slices returned from `Bucket.Get()` to match the slice length. Previously the capacity would be the size of the mmap max size. This does not cause any backwards compatibility issues, however, it does allow users to `append()` to the returned slice since that will cause Go to realloc a new slice on the heap. Fixes #544pull/24/head
parent
c2610ee091
commit
2b4a0e2894
|
@ -80,6 +80,46 @@ func TestBucket_Get_IncompatibleValue(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that a slice returned from a bucket has a capacity equal to its length.
|
||||||
|
// This also allows slices to be appended to since it will require a realloc by Go.
|
||||||
|
//
|
||||||
|
// https://github.com/boltdb/bolt/issues/544
|
||||||
|
func TestBucket_Get_Capacity(t *testing.T) {
|
||||||
|
db := MustOpenDB()
|
||||||
|
defer db.MustClose()
|
||||||
|
|
||||||
|
// Write key to a bucket.
|
||||||
|
if err := db.Update(func(tx *bolt.Tx) error {
|
||||||
|
b, err := tx.CreateBucket([]byte("bucket"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return b.Put([]byte("key"), []byte("val"))
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve value and attempt to append to it.
|
||||||
|
if err := db.Update(func(tx *bolt.Tx) error {
|
||||||
|
k, v := tx.Bucket([]byte("bucket")).Cursor().First()
|
||||||
|
|
||||||
|
// Verify capacity.
|
||||||
|
if len(k) != cap(k) {
|
||||||
|
t.Fatalf("unexpected key slice capacity: %d", cap(k))
|
||||||
|
} else if len(v) != cap(v) {
|
||||||
|
t.Fatalf("unexpected value slice capacity: %d", cap(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure slice can be appended to without a segfault.
|
||||||
|
k = append(k, []byte("123")...)
|
||||||
|
v = append(v, []byte("123")...)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that a bucket can write a key/value.
|
// Ensure that a bucket can write a key/value.
|
||||||
func TestBucket_Put(t *testing.T) {
|
func TestBucket_Put(t *testing.T) {
|
||||||
db := MustOpenDB()
|
db := MustOpenDB()
|
||||||
|
|
4
page.go
4
page.go
|
@ -111,13 +111,13 @@ type leafPageElement struct {
|
||||||
// key returns a byte slice of the node key.
|
// key returns a byte slice of the node key.
|
||||||
func (n *leafPageElement) key() []byte {
|
func (n *leafPageElement) key() []byte {
|
||||||
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
||||||
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize]
|
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize]
|
||||||
}
|
}
|
||||||
|
|
||||||
// value returns a byte slice of the node value.
|
// value returns a byte slice of the node value.
|
||||||
func (n *leafPageElement) value() []byte {
|
func (n *leafPageElement) value() []byte {
|
||||||
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
||||||
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize]
|
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize]
|
||||||
}
|
}
|
||||||
|
|
||||||
// PageInfo represents human readable information about a page.
|
// PageInfo represents human readable information about a page.
|
||||||
|
|
Loading…
Reference in New Issue