mirror of https://github.com/hak5/bolt.git
Clean up API.
parent
d05191d164
commit
a901cf6a25
|
@ -1,7 +1,5 @@
|
|||
package bolt
|
||||
|
||||
const MaxBucketNameSize = 255
|
||||
|
||||
type Bucket struct {
|
||||
*bucket
|
||||
name string
|
||||
|
|
7
const.go
7
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
|
||||
)
|
||||
|
|
96
db.go
96
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)]))
|
||||
|
|
|
@ -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{}
|
||||
|
|
10
error.go
10
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
|
||||
|
|
8
meta.go
8
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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue