Clean up API.

master
Ben Johnson 2014-01-31 12:22:58 -05:00
parent d05191d164
commit a901cf6a25
10 changed files with 126 additions and 58 deletions

View File

@ -1,7 +1,5 @@
package bolt
const MaxBucketNameSize = 255
type Bucket struct {
*bucket
name string

View File

@ -1,8 +1,9 @@
package bolt
const Version = 1
const version = 1
const (
MaxKeySize = 0x8000
MaxDataSize = 0xffffffff
MaxBucketNameSize = 255
MaxKeySize = 32768
MaxDataSize = 4294967295
)

96
db.go
View File

@ -14,12 +14,6 @@ const (
const minPageSize = 0x1000
var (
DatabaseNotOpenError = &Error{"db is not open", nil}
DatabaseAlreadyOpenedError = &Error{"db already open", nil}
TransactionInProgressError = &Error{"writable transaction is already in progress", nil}
)
type DB struct {
sync.Mutex
opened bool
@ -157,9 +151,9 @@ func (db *DB) init() error {
// Initialize the meta page.
m := p.meta()
m.magic = magic
m.version = Version
m.version = version
m.pageSize = uint32(db.pageSize)
m.version = Version
m.version = version
m.free = 2
m.sys = 3
m.pgid = 4
@ -239,6 +233,92 @@ func (db *DB) RWTransaction() (*RWTransaction, error) {
return t, nil
}
// Bucket retrieves a reference to a bucket.
func (db *DB) Bucket(name string) (*Bucket, error) {
t, err := db.Transaction()
if err != nil {
return nil, err
}
defer t.Close()
return t.Bucket(name), nil
}
// Buckets retrieves a list of all buckets in the database.
func (db *DB) Buckets() ([]*Bucket, error) {
t, err := db.Transaction()
if err != nil {
return nil, err
}
defer t.Close()
return t.Buckets(), nil
}
// CreateBucket creates a new bucket in the database.
func (db *DB) CreateBucket(name string) error {
t, err := db.RWTransaction()
if err != nil {
return err
}
if err := t.CreateBucket(name); err != nil {
t.Rollback()
return err
}
return t.Commit()
}
// DeleteBucket removes a bucket from the database.
func (db *DB) DeleteBucket(name string) error {
t, err := db.RWTransaction()
if err != nil {
return err
}
if err := t.DeleteBucket(name); err != nil {
t.Rollback()
return err
}
return t.Commit()
}
// Get retrieves the value for a key in a bucket.
func (db *DB) Get(name string, key []byte) ([]byte, error) {
t, err := db.Transaction()
if err != nil {
return nil, err
}
defer t.Close()
return t.Get(name, key), nil
}
// Put sets the value for a key in a bucket.
func (db *DB) Put(name string, key []byte, value []byte) error {
t, err := db.RWTransaction()
if err != nil {
return err
}
if err := t.Put(name, key, value); err != nil {
t.Rollback()
return err
}
return t.Commit()
}
// Delete removes a key from a bucket.
func (db *DB) Delete(name string, key []byte) error {
t, err := db.RWTransaction()
if err != nil {
return err
}
if err := t.Delete(name, key); err != nil {
t.Rollback()
return err
}
return t.Commit()
}
// page retrieves a page reference from the mmap based on the current page size.
func (db *DB) page(id pgid) *page {
return (*page)(unsafe.Pointer(&db.data[id*pgid(db.pageSize)]))

View File

@ -123,16 +123,16 @@ func TestDBCorruptMeta0(t *testing.T) {
withMockDB(func(db *DB, mockos *mockos, mocksyscall *mocksyscall, path string) {
var m meta
m.magic = magic
m.version = Version
m.version = version
m.pageSize = 0x8000
// Create a file with bad magic.
b := make([]byte, 0x10000)
p0, p1 := (*page)(unsafe.Pointer(&b[0x0000])), (*page)(unsafe.Pointer(&b[0x8000]))
p0.meta().magic = 0
p0.meta().version = Version
p0.meta().version = version
p1.meta().magic = magic
p1.meta().version = Version
p1.meta().version = version
// Mock file access.
file, metafile := &mockfile{}, &mockfile{}

3
doc.go Normal file
View File

@ -0,0 +1,3 @@
package bolt
// TODO(benbjohnson)

View File

@ -1,5 +1,15 @@
package bolt
var (
InvalidError = &Error{"Invalid database", nil}
VersionMismatchError = &Error{"version mismatch", nil}
DatabaseNotOpenError = &Error{"db is not open", nil}
DatabaseAlreadyOpenedError = &Error{"db already open", nil}
TransactionInProgressError = &Error{"writable transaction is already in progress", nil}
InvalidTransactionError = &Error{"txn is invalid", nil}
BucketAlreadyExistsError = &Error{"bucket already exists", nil}
)
type Error struct {
message string
cause error

View File

@ -1,12 +1,6 @@
package bolt
var (
InvalidError = &Error{"Invalid database", nil}
VersionMismatchError = &Error{"version mismatch", nil}
)
const magic uint32 = 0xDEADC0DE
const version uint32 = 1
type meta struct {
magic uint32
@ -22,7 +16,7 @@ type meta struct {
func (m *meta) validate() error {
if m.magic != magic {
return InvalidError
} else if m.version != Version {
} else if m.version != version {
return VersionMismatchError
}
return nil

View File

@ -79,7 +79,7 @@ func (t *RWTransaction) Put(name string, key []byte, value []byte) error {
return nil
}
func (t *RWTransaction) Delete(key []byte) error {
func (t *RWTransaction) Delete(name string, key []byte) error {
// TODO: Traverse to the correct node.
// TODO: If missing, exit.
// TODO: Remove node from page.
@ -116,17 +116,15 @@ func (t *RWTransaction) Commit() error {
return nil
}
func (t *RWTransaction) Rollback() error {
return t.close()
func (t *RWTransaction) Rollback() {
t.close()
}
func (t *RWTransaction) close() error {
func (t *RWTransaction) close() {
// Clear temporary pages.
t.leafs = nil
// TODO: Release writer lock.
return nil
}
// allocate returns a contiguous block of memory starting at a given page.

View File

@ -19,28 +19,12 @@ func TestRWTransaction(t *testing.T) {
func TestTransactionCreateBucket(t *testing.T) {
withOpenDB(func(db *DB, path string) {
// Create a bucket.
txn, _ := db.RWTransaction()
err := txn.CreateBucket("widgets")
err := db.CreateBucket("widgets")
assert.NoError(t, err)
// Commit the transaction.
err = txn.Commit()
// Read the bucket through a separate transaction.
b, err := db.Bucket("widgets")
assert.NotNil(t, b)
assert.NoError(t, err)
// Open a separate read-only transaction.
rtxn, err := db.Transaction()
assert.NotNil(t, txn)
assert.NoError(t, err)
b := rtxn.Bucket("widgets")
assert.NoError(t, err)
if assert.NotNil(t, b) {
assert.Equal(t, b.Name(), "widgets")
}
})
}
// Ensure that an existing bucket cannot be created.
func TestTransactionCreateExistingBucket(t *testing.T) {
t.Skip("pending")
}

View File

@ -1,10 +1,5 @@
package bolt
var (
InvalidTransactionError = &Error{"txn is invalid", nil}
BucketAlreadyExistsError = &Error{"bucket already exists", nil}
)
const (
ps_modify = 1
ps_rootonly = 2
@ -32,9 +27,8 @@ func (t *Transaction) init(db *DB) {
t.sys.read(t.page(t.meta.sys))
}
func (t *Transaction) Close() error {
func (t *Transaction) Close() {
// TODO: Close buckets.
return nil
}
func (t *Transaction) DB() *DB {
@ -56,6 +50,12 @@ func (t *Transaction) Bucket(name string) *Bucket {
}
}
// Buckets retrieves a list of all buckets.
func (t *Transaction) Buckets() []*Bucket {
warn("[pending] Transaction.Buckets()") // TODO
return nil
}
// Cursor creates a cursor associated with a given bucket.
func (t *Transaction) Cursor(name string) *Cursor {
b := t.Bucket(name)
@ -74,8 +74,8 @@ func (t *Transaction) Get(name string, key []byte) []byte {
return c.Get(key)
}
// Stat returns information about a bucket's internal structure.
func (t *Transaction) Stat(name string) *Stat {
// stat returns information about a bucket's internal structure.
func (t *Transaction) stat(name string) *Stat {
// TODO
return nil
}