mirror of https://github.com/hak5/bolt.git
commit
2b5e440316
88
db.go
88
db.go
|
@ -330,6 +330,26 @@ func (db *DB) removeTransaction(t *Transaction) {
|
|||
}
|
||||
}
|
||||
|
||||
// Do executes a function within the context of a RWTransaction.
|
||||
// If no error is returned from the function then the transaction is committed.
|
||||
// If an error is returned then the entire transaction is rolled back.
|
||||
// Any error that is returned from the function or returned from the commit is
|
||||
// returned from the Do() method.
|
||||
func (db *DB) Do(fn func(*RWTransaction) error) error {
|
||||
t, err := db.RWTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If an error is returned from the function then rollback and return error.
|
||||
if err := fn(t); err != nil {
|
||||
t.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
// Bucket retrieves a reference to a bucket.
|
||||
// This is typically useful for checking the existence of a bucket.
|
||||
func (db *DB) Bucket(name string) (*Bucket, error) {
|
||||
|
@ -355,51 +375,31 @@ func (db *DB) Buckets() ([]*Bucket, error) {
|
|||
// This function can return an error if the bucket already exists, if the name
|
||||
// is blank, or the bucket name is too long.
|
||||
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()
|
||||
return db.Do(func(t *RWTransaction) error {
|
||||
return t.CreateBucket(name)
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteBucket removes a bucket from the database.
|
||||
// Returns an error if the bucket does not exist.
|
||||
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()
|
||||
return db.Do(func(t *RWTransaction) error {
|
||||
return t.DeleteBucket(name)
|
||||
})
|
||||
}
|
||||
|
||||
// NextSequence returns an autoincrementing integer for the bucket.
|
||||
// This function can return an error if the bucket does not exist.
|
||||
func (db *DB) NextSequence(name string) (int, error) {
|
||||
t, err := db.RWTransaction()
|
||||
var seq int
|
||||
err := db.Do(func(t *RWTransaction) error {
|
||||
var err error
|
||||
seq, err = t.NextSequence(name)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
seq, err := t.NextSequence(name)
|
||||
if err != nil {
|
||||
t.Rollback()
|
||||
return 0, err
|
||||
}
|
||||
if err := t.Commit(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return seq, nil
|
||||
}
|
||||
|
||||
|
@ -417,29 +417,17 @@ func (db *DB) Get(name string, key []byte) ([]byte, error) {
|
|||
// Put sets the value for a key in a bucket.
|
||||
// Returns an error if the bucket is not found, if key is blank, if the key is too large, or if the value is too large.
|
||||
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()
|
||||
return db.Do(func(t *RWTransaction) error {
|
||||
return t.Put(name, key, value)
|
||||
})
|
||||
}
|
||||
|
||||
// Delete removes a key from a bucket.
|
||||
// Returns an error if the bucket cannot be found.
|
||||
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()
|
||||
return db.Do(func(t *RWTransaction) error {
|
||||
return t.Delete(name, key)
|
||||
})
|
||||
}
|
||||
|
||||
// Copy writes the entire database to a writer.
|
||||
|
|
18
db_test.go
18
db_test.go
|
@ -178,6 +178,24 @@ func TestDBDelete(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
// Ensure a database can provide a transactional block.
|
||||
func TestDBTransactionBlock(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
err := db.Do(func(txn *RWTransaction) error {
|
||||
txn.CreateBucket("widgets")
|
||||
txn.Put("widgets", []byte("foo"), []byte("bar"))
|
||||
txn.Put("widgets", []byte("baz"), []byte("bat"))
|
||||
txn.Delete("widgets", []byte("foo"))
|
||||
return nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
value, _ := db.Get("widgets", []byte("foo"))
|
||||
assert.Nil(t, value)
|
||||
value, _ = db.Get("widgets", []byte("baz"))
|
||||
assert.Equal(t, value, []byte("bat"))
|
||||
})
|
||||
}
|
||||
|
||||
// Ensure that the database can be copied to a writer.
|
||||
func TestDBCopy(t *testing.T) {
|
||||
t.Skip("pending") // TODO(benbjohnson)
|
||||
|
|
|
@ -60,6 +60,33 @@ func ExampleDB_Delete() {
|
|||
// The value of 'foo' is now: nil
|
||||
}
|
||||
|
||||
func ExampleDB_Do() {
|
||||
// Open the database.
|
||||
var db DB
|
||||
db.Open("/tmp/bolt/db_do.db", 0666)
|
||||
defer db.Close()
|
||||
|
||||
// Execute several commands within a write transaction.
|
||||
err := db.Do(func(t *RWTransaction) error {
|
||||
if err := t.CreateBucket("widgets"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.Put("widgets", []byte("foo"), []byte("bar")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// If our transactional block didn't return an error then our data is saved.
|
||||
if err == nil {
|
||||
value, _ := db.Get("widgets", []byte("foo"))
|
||||
fmt.Printf("The value of 'foo' is: %s\n", string(value))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// The value of 'foo' is: bar
|
||||
}
|
||||
|
||||
func ExampleRWTransaction() {
|
||||
// Open the database.
|
||||
var db DB
|
||||
|
|
Loading…
Reference in New Issue