mirror of https://github.com/hak5/bolt.git
commit
d1b21e619d
|
@ -476,6 +476,7 @@ func (b *Bucket) spill() error {
|
|||
b.rootNode = b.rootNode.root()
|
||||
|
||||
// Update the root node for this bucket.
|
||||
_assert(b.rootNode.pgid < b.tx.meta.pgid, "pgid (%d) above high water mark (%d)", b.rootNode.pgid, b.tx.meta.pgid)
|
||||
b.root = b.rootNode.pgid
|
||||
|
||||
return nil
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
// Info prints basic information about a database.
|
||||
func Info(path string) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
fatal(err)
|
||||
return
|
||||
}
|
||||
|
||||
db, err := bolt.Open(path, 0600)
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Print basic database info.
|
||||
var info = db.Info()
|
||||
printf("Page Size: %d", info.PageSize)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package main_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
. "github.com/boltdb/bolt/cmd/bolt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Ensure that a database info can be printed.
|
||||
func TestInfo(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
open(func(db *bolt.DB, path string) {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucket([]byte("widgets"))
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
b.Put([]byte("foo"), []byte("0000"))
|
||||
return nil
|
||||
})
|
||||
db.Close()
|
||||
output := run("info", path)
|
||||
assert.Equal(t, `Page Size: 4096`, output)
|
||||
})
|
||||
}
|
||||
|
||||
// Ensure that an error is reported if the database is not found.
|
||||
func TestInfo_NotFound(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
output := run("info", "no/such/db")
|
||||
assert.Equal(t, "stat no/such/db: no such file or directory", output)
|
||||
}
|
|
@ -25,6 +25,14 @@ func NewApp() *cli.App {
|
|||
app.Usage = "BoltDB toolkit"
|
||||
app.Version = fmt.Sprintf("0.1.0 (%s %s)", branch, commit)
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "info",
|
||||
Usage: "Print basic information about a database",
|
||||
Action: func(c *cli.Context) {
|
||||
path := c.Args().Get(0)
|
||||
Info(path)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "get",
|
||||
Usage: "Retrieve a value for given key in a bucket",
|
||||
|
|
4
db.go
4
db.go
|
@ -705,6 +705,10 @@ func (m *meta) copy(dest *meta) {
|
|||
|
||||
// write writes the meta onto a page.
|
||||
func (m *meta) write(p *page) {
|
||||
|
||||
_assert(m.root.root < m.pgid, "root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid)
|
||||
_assert(m.freelist < m.pgid, "freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid)
|
||||
|
||||
// Page id is either going to be 0 or 1 which we can determine by the transaction ID.
|
||||
p.id = pgid(m.txid % 2)
|
||||
p.flags |= metaPageFlag
|
||||
|
|
3
node.go
3
node.go
|
@ -96,6 +96,7 @@ func (n *node) prevSibling() *node {
|
|||
|
||||
// put inserts a key/value.
|
||||
func (n *node) put(oldKey, newKey, value []byte, pgid pgid, flags uint32) {
|
||||
_assert(pgid < n.bucket.tx.meta.pgid, "pgid (%d) above high water mark (%d)", pgid, n.bucket.tx.meta.pgid)
|
||||
_assert(len(oldKey) > 0, "put: zero-length old key")
|
||||
_assert(len(newKey) > 0, "put: zero-length new key")
|
||||
|
||||
|
@ -284,6 +285,7 @@ func (n *node) spill() error {
|
|||
}
|
||||
|
||||
// Write the node.
|
||||
_assert(p.id < tx.meta.pgid, "pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid)
|
||||
node.pgid = p.id
|
||||
node.write(p)
|
||||
|
||||
|
@ -314,6 +316,7 @@ func (n *node) spill() error {
|
|||
}
|
||||
|
||||
// Write the new root.
|
||||
_assert(p.id < tx.meta.pgid, "pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid)
|
||||
parent.pgid = p.id
|
||||
parent.write(p)
|
||||
}
|
||||
|
|
10
node_test.go
10
node_test.go
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// Ensure that a node can insert a key/value.
|
||||
func TestNode_put(t *testing.T) {
|
||||
n := &node{inodes: make(inodes, 0)}
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}}
|
||||
n.put([]byte("baz"), []byte("baz"), []byte("2"), 0, 0)
|
||||
n.put([]byte("foo"), []byte("foo"), []byte("0"), 0, 0)
|
||||
n.put([]byte("bar"), []byte("bar"), []byte("1"), 0, 0)
|
||||
|
@ -58,7 +58,7 @@ func TestNode_read_LeafPage(t *testing.T) {
|
|||
// Ensure that a node can serialize into a leaf page.
|
||||
func TestNode_write_LeafPage(t *testing.T) {
|
||||
// Create a node.
|
||||
n := &node{isLeaf: true, inodes: make(inodes, 0)}
|
||||
n := &node{isLeaf: true, inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}}
|
||||
n.put([]byte("susy"), []byte("susy"), []byte("que"), 0, 0)
|
||||
n.put([]byte("ricki"), []byte("ricki"), []byte("lake"), 0, 0)
|
||||
n.put([]byte("john"), []byte("john"), []byte("johnson"), 0, 0)
|
||||
|
@ -85,7 +85,7 @@ func TestNode_write_LeafPage(t *testing.T) {
|
|||
// Ensure that a node can split into appropriate subgroups.
|
||||
func TestNode_split(t *testing.T) {
|
||||
// Create a node.
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{}}}
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}}
|
||||
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
||||
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
||||
n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
|
||||
|
@ -104,7 +104,7 @@ func TestNode_split(t *testing.T) {
|
|||
// Ensure that a page with the minimum number of inodes just returns a single node.
|
||||
func TestNode_split_MinKeys(t *testing.T) {
|
||||
// Create a node.
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{}}}
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}}
|
||||
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
||||
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
||||
|
||||
|
@ -116,7 +116,7 @@ func TestNode_split_MinKeys(t *testing.T) {
|
|||
// Ensure that a node that has keys that all fit on a page just returns one leaf.
|
||||
func TestNode_split_SinglePage(t *testing.T) {
|
||||
// Create a node.
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{}}}
|
||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}}
|
||||
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
||||
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
||||
n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
|
||||
|
|
Loading…
Reference in New Issue