Add bucket reclamation.

After RWTransaction.DeleteBucket() is called, all pages related to the
bucket are moved to the freelist for that transaction.
pull/34/head
Ben Johnson 2014-02-27 11:55:44 -07:00
parent 0209ad2ed4
commit 9abced434f
2 changed files with 12 additions and 2 deletions

View File

@ -63,14 +63,18 @@ func (t *RWTransaction) CreateBucketIfNotExists(name string) error {
// DeleteBucket deletes a bucket.
// Returns an error if the bucket cannot be found.
func (t *RWTransaction) DeleteBucket(name string) error {
if b := t.Bucket(name); b == nil {
b := t.Bucket(name)
if b == nil {
return ErrBucketNotFound
}
// Remove from buckets page.
t.buckets.del(name)
// TODO(benbjohnson): Free all pages.
// Free all pages.
t.forEachPage(b.root, 0, func(p *page, depth int) {
t.db.freelist.free(t.id(), p)
})
return nil
}

View File

@ -66,6 +66,7 @@ func TestRWTransactionCreateBucketIfNotExists(t *testing.T) {
withOpenDB(func(db *DB, path string) {
assert.NoError(t, db.CreateBucketIfNotExists("widgets"))
assert.NoError(t, db.CreateBucketIfNotExists("widgets"))
assert.Equal(t, db.CreateBucketIfNotExists(""), ErrBucketNameRequired)
// Read the bucket through a separate transaction.
b, err := db.Bucket("widgets")
@ -113,12 +114,17 @@ func TestRWTransactionDeleteBucket(t *testing.T) {
db.CreateBucket("widgets")
db.Put("widgets", []byte("foo"), []byte("bar"))
b, _ := db.Bucket("widgets")
// Delete the bucket and make sure we can't get the value.
assert.NoError(t, db.DeleteBucket("widgets"))
value, err := db.Get("widgets", []byte("foo"))
assert.Equal(t, err, ErrBucketNotFound)
assert.Nil(t, value)
// Verify that the bucket's page is free.
assert.Equal(t, db.freelist.all(), []pgid{b.root})
// Create the bucket again and make sure there's not a phantom value.
assert.NoError(t, db.CreateBucket("widgets"))
value, err = db.Get("widgets", []byte("foo"))