aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bucket.go2
-rw-r--r--const.go7
-rw-r--r--db.go96
-rw-r--r--db_test.go6
-rw-r--r--doc.go3
-rw-r--r--error.go10
-rw-r--r--meta.go8
-rw-r--r--rwtransaction.go10
-rw-r--r--rwtransaction_test.go24
-rw-r--r--transaction.go18
10 files changed, 126 insertions, 58 deletions
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
}