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.
|
// Bucket retrieves a reference to a bucket.
|
||||||
// This is typically useful for checking the existence of a bucket.
|
// This is typically useful for checking the existence of a bucket.
|
||||||
func (db *DB) Bucket(name string) (*Bucket, error) {
|
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
|
// This function can return an error if the bucket already exists, if the name
|
||||||
// is blank, or the bucket name is too long.
|
// is blank, or the bucket name is too long.
|
||||||
func (db *DB) CreateBucket(name string) error {
|
func (db *DB) CreateBucket(name string) error {
|
||||||
t, err := db.RWTransaction()
|
return db.Do(func(t *RWTransaction) error {
|
||||||
if err != nil {
|
return t.CreateBucket(name)
|
||||||
return err
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if err := t.CreateBucket(name); err != nil {
|
|
||||||
t.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.Commit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBucket removes a bucket from the database.
|
// DeleteBucket removes a bucket from the database.
|
||||||
// Returns an error if the bucket does not exist.
|
// Returns an error if the bucket does not exist.
|
||||||
func (db *DB) DeleteBucket(name string) error {
|
func (db *DB) DeleteBucket(name string) error {
|
||||||
t, err := db.RWTransaction()
|
return db.Do(func(t *RWTransaction) error {
|
||||||
if err != nil {
|
return t.DeleteBucket(name)
|
||||||
return err
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if err := t.DeleteBucket(name); err != nil {
|
|
||||||
t.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.Commit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextSequence returns an autoincrementing integer for the bucket.
|
// NextSequence returns an autoincrementing integer for the bucket.
|
||||||
// This function can return an error if the bucket does not exist.
|
// This function can return an error if the bucket does not exist.
|
||||||
func (db *DB) NextSequence(name string) (int, error) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
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
|
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.
|
// 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.
|
// 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 {
|
func (db *DB) Put(name string, key []byte, value []byte) error {
|
||||||
t, err := db.RWTransaction()
|
return db.Do(func(t *RWTransaction) error {
|
||||||
if err != nil {
|
return t.Put(name, key, value)
|
||||||
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.
|
// Delete removes a key from a bucket.
|
||||||
// Returns an error if the bucket cannot be found.
|
// Returns an error if the bucket cannot be found.
|
||||||
func (db *DB) Delete(name string, key []byte) error {
|
func (db *DB) Delete(name string, key []byte) error {
|
||||||
t, err := db.RWTransaction()
|
return db.Do(func(t *RWTransaction) error {
|
||||||
if err != nil {
|
return t.Delete(name, key)
|
||||||
return err
|
})
|
||||||
}
|
|
||||||
if err := t.Delete(name, key); err != nil {
|
|
||||||
t.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return t.Commit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy writes the entire database to a writer.
|
// 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.
|
// Ensure that the database can be copied to a writer.
|
||||||
func TestDBCopy(t *testing.T) {
|
func TestDBCopy(t *testing.T) {
|
||||||
t.Skip("pending") // TODO(benbjohnson)
|
t.Skip("pending") // TODO(benbjohnson)
|
||||||
|
|
|
@ -60,6 +60,33 @@ func ExampleDB_Delete() {
|
||||||
// The value of 'foo' is now: nil
|
// 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() {
|
func ExampleRWTransaction() {
|
||||||
// Open the database.
|
// Open the database.
|
||||||
var db DB
|
var db DB
|
||||||
|
|
Loading…
Reference in New Issue