From a901cf6a25d301c6c67da3f8f1e51ca2f9c25bd4 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Fri, 31 Jan 2014 12:22:58 -0500 Subject: [PATCH] Clean up API. --- bucket.go | 2 - const.go | 7 ++-- db.go | 96 +++++++++++++++++++++++++++++++++++++++---- db_test.go | 6 +-- doc.go | 3 ++ error.go | 10 +++++ meta.go | 8 +--- rwtransaction.go | 10 ++--- rwtransaction_test.go | 24 ++--------- transaction.go | 18 ++++---- 10 files changed, 126 insertions(+), 58 deletions(-) create mode 100644 doc.go diff --git a/bucket.go b/bucket.go index 15dc6ac..6cfe1ca 100644 --- a/bucket.go +++ b/bucket.go @@ -1,7 +1,5 @@ package bolt -const MaxBucketNameSize = 255 - type Bucket struct { *bucket name string diff --git a/const.go b/const.go index 58640ee..fce1051 100644 --- a/const.go +++ b/const.go @@ -1,8 +1,9 @@ package bolt -const Version = 1 +const version = 1 const ( - MaxKeySize = 0x8000 - MaxDataSize = 0xffffffff + MaxBucketNameSize = 255 + MaxKeySize = 32768 + MaxDataSize = 4294967295 ) diff --git a/db.go b/db.go index 7ffbe09..646c31b 100644 --- a/db.go +++ b/db.go @@ -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)])) diff --git a/db_test.go b/db_test.go index dd5c8ba..53988b7 100644 --- a/db_test.go +++ b/db_test.go @@ -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{} diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..ea75951 --- /dev/null +++ b/doc.go @@ -0,0 +1,3 @@ +package bolt + +// TODO(benbjohnson) diff --git a/error.go b/error.go index 40877dc..b5302ad 100644 --- a/error.go +++ b/error.go @@ -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 diff --git a/meta.go b/meta.go index 659bfa7..1ef9ffc 100644 --- a/meta.go +++ b/meta.go @@ -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 diff --git a/rwtransaction.go b/rwtransaction.go index 1667609..145e0cf 100644 --- a/rwtransaction.go +++ b/rwtransaction.go @@ -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. diff --git a/rwtransaction_test.go b/rwtransaction_test.go index 2bcf252..b6e971e 100644 --- a/rwtransaction_test.go +++ b/rwtransaction_test.go @@ -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") -} diff --git a/transaction.go b/transaction.go index 0dfb240..e479dfb 100644 --- a/transaction.go +++ b/transaction.go @@ -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 }