mirror of https://github.com/hak5/bolt.git
Make DB/Tx API more consistent.
I consolidated the DB.Tx() and DB.RWTx() calls into a single DB.Begin(writable bool) call. This is more consistent with the database/sql library. I also changed the DB.Do() and DB.With() call to DB.Update() and DB.View(), respectively. This is more intuitive and more inline with other database verbiage.master
parent
0866abf733
commit
f8ad21bad3
|
@ -16,7 +16,7 @@ import (
|
|||
// Ensure that a bucket that gets a non-existent key returns nil.
|
||||
func TestBucketGetNonExistent(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
value := tx.Bucket("widgets").Get([]byte("foo"))
|
||||
assert.Nil(t, value)
|
||||
|
@ -28,7 +28,7 @@ func TestBucketGetNonExistent(t *testing.T) {
|
|||
// Ensure that a bucket can read a value that is not flushed yet.
|
||||
func TestBucketGetFromNode(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
b.Put([]byte("foo"), []byte("bar"))
|
||||
|
@ -42,7 +42,7 @@ func TestBucketGetFromNode(t *testing.T) {
|
|||
// Ensure that a bucket can write a key/value.
|
||||
func TestBucketPut(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
err := tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
assert.NoError(t, err)
|
||||
|
@ -56,11 +56,11 @@ func TestBucketPut(t *testing.T) {
|
|||
// Ensure that setting a value on a read-only bucket returns an error.
|
||||
func TestBucketPutReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
return nil
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
err := b.Put([]byte("foo"), []byte("bar"))
|
||||
assert.Equal(t, err, ErrBucketNotWritable)
|
||||
|
@ -72,7 +72,7 @@ func TestBucketPutReadOnly(t *testing.T) {
|
|||
// Ensure that a bucket can delete an existing key.
|
||||
func TestBucketDelete(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
err := tx.Bucket("widgets").Delete([]byte("foo"))
|
||||
|
@ -87,11 +87,11 @@ func TestBucketDelete(t *testing.T) {
|
|||
// Ensure that deleting a key on a read-only bucket returns an error.
|
||||
func TestBucketDeleteReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
return nil
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
err := b.Delete([]byte("foo"))
|
||||
assert.Equal(t, err, ErrBucketNotWritable)
|
||||
|
@ -103,7 +103,7 @@ func TestBucketDeleteReadOnly(t *testing.T) {
|
|||
// Ensure that a bucket can return an autoincrementing sequence.
|
||||
func TestBucketNextSequence(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.CreateBucket("woojits")
|
||||
|
||||
|
@ -127,11 +127,11 @@ func TestBucketNextSequence(t *testing.T) {
|
|||
// Ensure that retrieving the next sequence on a read-only bucket returns an error.
|
||||
func TestBucketNextSequenceReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
return nil
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
i, err := b.NextSequence()
|
||||
assert.Equal(t, i, 0)
|
||||
|
@ -144,11 +144,11 @@ func TestBucketNextSequenceReadOnly(t *testing.T) {
|
|||
// Ensure that incrementing past the maximum sequence number will return an error.
|
||||
func TestBucketNextSequenceOverflow(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
return nil
|
||||
})
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
b.bucket.sequence = uint64(maxInt)
|
||||
seq, err := b.NextSequence()
|
||||
|
@ -162,7 +162,7 @@ func TestBucketNextSequenceOverflow(t *testing.T) {
|
|||
// Ensure a database can loop over all key/value pairs in a bucket.
|
||||
func TestBucketForEach(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("0000"))
|
||||
tx.Bucket("widgets").Put([]byte("baz"), []byte("0001"))
|
||||
|
@ -194,7 +194,7 @@ func TestBucketForEach(t *testing.T) {
|
|||
// Ensure a database can stop iteration early.
|
||||
func TestBucketForEachShortCircuit(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("bar"), []byte("0000"))
|
||||
tx.Bucket("widgets").Put([]byte("baz"), []byte("0000"))
|
||||
|
@ -218,7 +218,7 @@ func TestBucketForEachShortCircuit(t *testing.T) {
|
|||
// Ensure that an error is returned when inserting with an empty key.
|
||||
func TestBucketPutEmptyKey(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
err := tx.Bucket("widgets").Put([]byte(""), []byte("bar"))
|
||||
assert.Equal(t, err, ErrKeyRequired)
|
||||
|
@ -232,7 +232,7 @@ func TestBucketPutEmptyKey(t *testing.T) {
|
|||
// Ensure that an error is returned when inserting with a key that's too large.
|
||||
func TestBucketPutKeyTooLarge(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
err := tx.Bucket("widgets").Put(make([]byte, 32769), []byte("bar"))
|
||||
assert.Equal(t, err, ErrKeyTooLarge)
|
||||
|
@ -248,7 +248,7 @@ func TestBucketStat(t *testing.T) {
|
|||
}
|
||||
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
// Add bucket with lots of keys.
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
|
@ -271,7 +271,7 @@ func TestBucketStat(t *testing.T) {
|
|||
|
||||
return nil
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
stat := b.Stat()
|
||||
assert.Equal(t, stat.BranchPageCount, 15)
|
||||
|
@ -312,11 +312,11 @@ func TestBucketPutSingle(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
m := make(map[string][]byte)
|
||||
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
for _, item := range items {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
if err := tx.Bucket("widgets").Put(item.Key, item.Value); err != nil {
|
||||
panic("put error: " + err.Error())
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ func TestBucketPutSingle(t *testing.T) {
|
|||
})
|
||||
|
||||
// Verify all key/values so far.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
i := 0
|
||||
for k, v := range m {
|
||||
value := tx.Bucket("widgets").Get([]byte(k))
|
||||
|
@ -359,10 +359,10 @@ func TestBucketPutMultiple(t *testing.T) {
|
|||
f := func(items testdata) bool {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Bulk insert all values.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
err := db.Do(func(tx *Tx) error {
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
for _, item := range items {
|
||||
assert.NoError(t, b.Put(item.Key, item.Value))
|
||||
|
@ -372,7 +372,7 @@ func TestBucketPutMultiple(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// Verify all items exist.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
for _, item := range items {
|
||||
value := b.Get(item.Key)
|
||||
|
@ -402,10 +402,10 @@ func TestBucketDeleteQuick(t *testing.T) {
|
|||
f := func(items testdata) bool {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Bulk insert all values.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
err := db.Do(func(tx *Tx) error {
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
for _, item := range items {
|
||||
assert.NoError(t, b.Put(item.Key, item.Value))
|
||||
|
@ -416,13 +416,13 @@ func TestBucketDeleteQuick(t *testing.T) {
|
|||
|
||||
// Remove items one at a time and check consistency.
|
||||
for i, item := range items {
|
||||
err := db.Do(func(tx *Tx) error {
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Delete(item.Key)
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Anything before our deletion index should be nil.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
for j, exp := range items {
|
||||
if j > i {
|
||||
|
|
|
@ -66,7 +66,7 @@ func GetCommand(c *cli.Context) {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.With(func(tx *bolt.Tx) error {
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
// Find bucket.
|
||||
b := tx.Bucket(name)
|
||||
if b == nil {
|
||||
|
@ -105,7 +105,7 @@ func SetCommand(c *cli.Context) {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Do(func(tx *bolt.Tx) error {
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
// Find bucket.
|
||||
b := tx.Bucket(name)
|
||||
if b == nil {
|
||||
|
@ -137,7 +137,7 @@ func KeysCommand(c *cli.Context) {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.With(func(tx *bolt.Tx) error {
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
// Find bucket.
|
||||
b := tx.Bucket(name)
|
||||
if b == nil {
|
||||
|
@ -172,7 +172,7 @@ func BucketsCommand(c *cli.Context) {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.With(func(tx *bolt.Tx) error {
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
for _, b := range tx.Buckets() {
|
||||
println(b.Name())
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ func PagesCommand(c *cli.Context) {
|
|||
println("ID TYPE ITEMS OVRFLW")
|
||||
println("======== ========== ====== ======")
|
||||
|
||||
db.Do(func(tx *bolt.Tx) error {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
var id int
|
||||
for {
|
||||
p, err := tx.Page(id)
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
func TestGet(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
open(func(db *bolt.DB) {
|
||||
db.Do(func(tx *bolt.Tx) error {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
return nil
|
||||
|
@ -45,7 +45,7 @@ func TestGetBucketNotFound(t *testing.T) {
|
|||
func TestGetKeyNotFound(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
open(func(db *bolt.DB) {
|
||||
db.Do(func(tx *bolt.Tx) error {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
output := run("get", db.Path(), "widgets", "foo")
|
||||
|
@ -57,7 +57,7 @@ func TestGetKeyNotFound(t *testing.T) {
|
|||
func TestSet(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
open(func(db *bolt.DB) {
|
||||
db.Do(func(tx *bolt.Tx) error {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
return nil
|
||||
})
|
||||
|
@ -86,7 +86,7 @@ func TestSetBucketNotFound(t *testing.T) {
|
|||
func TestKeys(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
open(func(db *bolt.DB) {
|
||||
db.Do(func(tx *bolt.Tx) error {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("0002"), []byte(""))
|
||||
tx.Bucket("widgets").Put([]byte("0001"), []byte(""))
|
||||
|
@ -118,7 +118,7 @@ func TestKeysBucketNotFound(t *testing.T) {
|
|||
func TestBuckets(t *testing.T) {
|
||||
SetTestMode(true)
|
||||
open(func(db *bolt.DB) {
|
||||
db.Do(func(tx *bolt.Tx) error {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucket("woojits")
|
||||
tx.CreateBucket("widgets")
|
||||
tx.CreateBucket("whatchits")
|
||||
|
|
44
db.go
44
db.go
|
@ -293,11 +293,22 @@ func (db *DB) close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Tx creates a read-only transaction.
|
||||
// Multiple read-only transactions can be used concurrently.
|
||||
// Begin starts a new transaction.
|
||||
// Multiple read-only transactions can be used concurrently but only one
|
||||
// write transaction can be used at a time. Starting multiple write transactions
|
||||
// will cause the calls to block and be serialized until the current write
|
||||
// transaction finishes.
|
||||
//
|
||||
// IMPORTANT: You must close the transaction after you are finished or else the database will not reclaim old pages.
|
||||
func (db *DB) Tx() (*Tx, error) {
|
||||
// IMPORTANT: You must close read-only transactions after you are finished or
|
||||
// else the database will not reclaim old pages.
|
||||
func (db *DB) Begin(writable bool) (*Tx, error) {
|
||||
if writable {
|
||||
return db.beginRWTx()
|
||||
}
|
||||
return db.beginTx()
|
||||
}
|
||||
|
||||
func (db *DB) beginTx() (*Tx, error) {
|
||||
db.metalock.Lock()
|
||||
defer db.metalock.Unlock()
|
||||
|
||||
|
@ -321,10 +332,7 @@ func (db *DB) Tx() (*Tx, error) {
|
|||
return t, nil
|
||||
}
|
||||
|
||||
// RWTx creates a read/write transaction.
|
||||
// Only one read/write transaction is allowed at a time.
|
||||
// You must call Commit() or Rollback() on the transaction to close it.
|
||||
func (db *DB) RWTx() (*Tx, error) {
|
||||
func (db *DB) beginRWTx() (*Tx, error) {
|
||||
db.metalock.Lock()
|
||||
defer db.metalock.Unlock()
|
||||
|
||||
|
@ -373,15 +381,15 @@ func (db *DB) removeTx(t *Tx) {
|
|||
}
|
||||
}
|
||||
|
||||
// Do executes a function within the context of a read-write managed transaction.
|
||||
// Update executes a function within the context of a read-write managed transaction.
|
||||
// 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.
|
||||
// returned from the Update() method.
|
||||
//
|
||||
// Attempting to manually commit or rollback within the function will cause a panic.
|
||||
func (db *DB) Do(fn func(*Tx) error) error {
|
||||
t, err := db.RWTx()
|
||||
func (db *DB) Update(fn func(*Tx) error) error {
|
||||
t, err := db.Begin(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -400,12 +408,12 @@ func (db *DB) Do(fn func(*Tx) error) error {
|
|||
return t.Commit()
|
||||
}
|
||||
|
||||
// With executes a function within the context of a managed transaction.
|
||||
// Any error that is returned from the function is returned from the With() method.
|
||||
// View executes a function within the context of a managed read-only transaction.
|
||||
// Any error that is returned from the function is returned from the View() method.
|
||||
//
|
||||
// Attempting to manually rollback within the function will cause a panic.
|
||||
func (db *DB) With(fn func(*Tx) error) error {
|
||||
t, err := db.Tx()
|
||||
func (db *DB) View(fn func(*Tx) error) error {
|
||||
t, err := db.Begin(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -433,7 +441,7 @@ func (db *DB) With(fn func(*Tx) error) error {
|
|||
// using the database while a copy is in progress.
|
||||
func (db *DB) Copy(w io.Writer) error {
|
||||
// Maintain a reader transaction so pages don't get reclaimed.
|
||||
t, err := db.Tx()
|
||||
t, err := db.Begin(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -492,7 +500,7 @@ func (db *DB) Stat() (*Stat, error) {
|
|||
db.mmaplock.RUnlock()
|
||||
db.metalock.Unlock()
|
||||
|
||||
err := db.Do(func(t *Tx) error {
|
||||
err := db.Update(func(t *Tx) error {
|
||||
s.PageCount = int(t.meta.pgid)
|
||||
s.FreePageCount = len(db.freelist.all())
|
||||
s.PageSize = db.pageSize
|
||||
|
|
42
db_test.go
42
db_test.go
|
@ -116,16 +116,16 @@ func TestDBCorruptMeta0(t *testing.T) {
|
|||
// Ensure that a database cannot open a transaction when it's not open.
|
||||
func TestDBTxErrDatabaseNotOpen(t *testing.T) {
|
||||
withDB(func(db *DB, path string) {
|
||||
tx, err := db.Tx()
|
||||
tx, err := db.Begin(false)
|
||||
assert.Nil(t, tx)
|
||||
assert.Equal(t, err, ErrDatabaseNotOpen)
|
||||
})
|
||||
}
|
||||
|
||||
// Ensure that a read-write transaction can be retrieved.
|
||||
func TestDBRWTx(t *testing.T) {
|
||||
func TestDBBeginRW(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
tx, err := db.RWTx()
|
||||
tx, err := db.Begin(true)
|
||||
assert.NotNil(t, tx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tx.DB(), db)
|
||||
|
@ -136,7 +136,7 @@ func TestDBRWTx(t *testing.T) {
|
|||
// Ensure that opening a transaction while the DB is closed returns an error.
|
||||
func TestDBRWTxOpenWithClosedDB(t *testing.T) {
|
||||
withDB(func(db *DB, path string) {
|
||||
tx, err := db.RWTx()
|
||||
tx, err := db.Begin(true)
|
||||
assert.Equal(t, err, ErrDatabaseNotOpen)
|
||||
assert.Nil(t, tx)
|
||||
})
|
||||
|
@ -145,7 +145,7 @@ func TestDBRWTxOpenWithClosedDB(t *testing.T) {
|
|||
// Ensure a database can provide a transactional block.
|
||||
func TestDBTxBlock(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
err := db.Do(func(tx *Tx) error {
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
b.Put([]byte("foo"), []byte("bar"))
|
||||
|
@ -154,7 +154,7 @@ func TestDBTxBlock(t *testing.T) {
|
|||
return nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
err = db.With(func(tx *Tx) error {
|
||||
err = db.View(func(tx *Tx) error {
|
||||
assert.Nil(t, tx.Bucket("widgets").Get([]byte("foo")))
|
||||
assert.Equal(t, []byte("bat"), tx.Bucket("widgets").Get([]byte("baz")))
|
||||
return nil
|
||||
|
@ -166,7 +166,7 @@ func TestDBTxBlock(t *testing.T) {
|
|||
// Ensure a closed database returns an error while running a transaction block
|
||||
func TestDBTxBlockWhileClosed(t *testing.T) {
|
||||
withDB(func(db *DB, path string) {
|
||||
err := db.Do(func(tx *Tx) error {
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
return nil
|
||||
})
|
||||
|
@ -177,13 +177,13 @@ func TestDBTxBlockWhileClosed(t *testing.T) {
|
|||
// Ensure a panic occurs while trying to commit a managed transaction.
|
||||
func TestDBTxBlockWithManualCommitAndRollback(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
assert.Panics(t, func() { tx.Commit() })
|
||||
assert.Panics(t, func() { tx.Rollback() })
|
||||
return nil
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
assert.Panics(t, func() { tx.Commit() })
|
||||
assert.Panics(t, func() { tx.Rollback() })
|
||||
return nil
|
||||
|
@ -194,7 +194,7 @@ func TestDBTxBlockWithManualCommitAndRollback(t *testing.T) {
|
|||
// Ensure that the database can be copied to a file path.
|
||||
func TestDBCopyFile(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
tx.Bucket("widgets").Put([]byte("baz"), []byte("bat"))
|
||||
|
@ -207,7 +207,7 @@ func TestDBCopyFile(t *testing.T) {
|
|||
assert.NoError(t, db2.Open("/tmp/bolt.copyfile.db", 0666))
|
||||
defer db2.Close()
|
||||
|
||||
db2.With(func(tx *Tx) error {
|
||||
db2.View(func(tx *Tx) error {
|
||||
assert.Equal(t, []byte("bar"), tx.Bucket("widgets").Get([]byte("foo")))
|
||||
assert.Equal(t, []byte("bat"), tx.Bucket("widgets").Get([]byte("baz")))
|
||||
return nil
|
||||
|
@ -218,7 +218,7 @@ func TestDBCopyFile(t *testing.T) {
|
|||
// Ensure the database can return stats about itself.
|
||||
func TestDBStat(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
for i := 0; i < 10000; i++ {
|
||||
|
@ -228,17 +228,17 @@ func TestDBStat(t *testing.T) {
|
|||
})
|
||||
|
||||
// Delete some keys.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Delete([]byte("10"))
|
||||
})
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Delete([]byte("1000"))
|
||||
})
|
||||
|
||||
// Open some readers.
|
||||
t0, _ := db.Tx()
|
||||
t1, _ := db.Tx()
|
||||
t2, _ := db.Tx()
|
||||
t0, _ := db.Begin(false)
|
||||
t1, _ := db.Begin(false)
|
||||
t2, _ := db.Begin(false)
|
||||
t2.Rollback()
|
||||
|
||||
// Obtain stats.
|
||||
|
@ -293,11 +293,11 @@ func TestDBString(t *testing.T) {
|
|||
func BenchmarkDBPutSequential(b *testing.B) {
|
||||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
for i := 0; i < b.N; i++ {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Put([]byte(strconv.Itoa(i)), value)
|
||||
})
|
||||
}
|
||||
|
@ -309,11 +309,11 @@ func BenchmarkDBPutRandom(b *testing.B) {
|
|||
indexes := rand.Perm(b.N)
|
||||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
for i := 0; i < b.N; i++ {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Put([]byte(strconv.Itoa(indexes[i])), value)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ func init() {
|
|||
os.MkdirAll("/tmp/bolt", 0777)
|
||||
}
|
||||
|
||||
func ExampleDB_Do() {
|
||||
func ExampleDB_Update() {
|
||||
// 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(tx *Tx) error {
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
if err := tx.CreateBucket("widgets"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func ExampleDB_Do() {
|
|||
|
||||
// If our transactional block didn't return an error then our data is saved.
|
||||
if err == nil {
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
value := tx.Bucket("widgets").Get([]byte("foo"))
|
||||
fmt.Printf("The value of 'foo' is: %s\n", string(value))
|
||||
return nil
|
||||
|
@ -41,14 +41,14 @@ func ExampleDB_Do() {
|
|||
// The value of 'foo' is: bar
|
||||
}
|
||||
|
||||
func ExampleDB_With() {
|
||||
func ExampleDB_View() {
|
||||
// Open the database.
|
||||
var db DB
|
||||
db.Open("/tmp/bolt/db_with.db", 0666)
|
||||
defer db.Close()
|
||||
|
||||
// Insert data into a bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("people")
|
||||
tx.Bucket("people").Put([]byte("john"), []byte("doe"))
|
||||
tx.Bucket("people").Put([]byte("susy"), []byte("que"))
|
||||
|
@ -56,7 +56,7 @@ func ExampleDB_With() {
|
|||
})
|
||||
|
||||
// Access data from within a read-only transactional block.
|
||||
db.With(func(t *Tx) error {
|
||||
db.View(func(t *Tx) error {
|
||||
v := t.Bucket("people").Get([]byte("john"))
|
||||
fmt.Printf("John's last name is %s.\n", string(v))
|
||||
return nil
|
||||
|
@ -73,7 +73,7 @@ func ExampleTx_Put() {
|
|||
defer db.Close()
|
||||
|
||||
// Start a write transaction.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
// Create a bucket.
|
||||
tx.CreateBucket("widgets")
|
||||
|
||||
|
@ -83,7 +83,7 @@ func ExampleTx_Put() {
|
|||
})
|
||||
|
||||
// Read value back in a different read-only transaction.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
value := tx.Bucket("widgets").Get([]byte("foo"))
|
||||
fmt.Printf("The value of 'foo' is: %s\n", string(value))
|
||||
return nil
|
||||
|
@ -100,7 +100,7 @@ func ExampleTx_Delete() {
|
|||
defer db.Close()
|
||||
|
||||
// Start a write transaction.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
// Create a bucket.
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
|
@ -115,12 +115,12 @@ func ExampleTx_Delete() {
|
|||
})
|
||||
|
||||
// Delete the key in a different write transaction.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Delete([]byte("foo"))
|
||||
})
|
||||
|
||||
// Retrieve the key again.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
value := tx.Bucket("widgets").Get([]byte("foo"))
|
||||
if value == nil {
|
||||
fmt.Printf("The value of 'foo' is now: nil\n")
|
||||
|
@ -140,7 +140,7 @@ func ExampleTx_ForEach() {
|
|||
defer db.Close()
|
||||
|
||||
// Insert data into a bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("animals")
|
||||
b := tx.Bucket("animals")
|
||||
b.Put([]byte("dog"), []byte("fun"))
|
||||
|
@ -161,19 +161,19 @@ func ExampleTx_ForEach() {
|
|||
// A liger is awesome.
|
||||
}
|
||||
|
||||
func ExampleTx() {
|
||||
func ExampleBegin_ReadOnly() {
|
||||
// Open the database.
|
||||
var db DB
|
||||
db.Open("/tmp/bolt/tx.db", 0666)
|
||||
defer db.Close()
|
||||
|
||||
// Create a bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
|
||||
// Create several keys in a transaction.
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
b := tx.Bucket("widgets")
|
||||
b.Put([]byte("john"), []byte("blue"))
|
||||
b.Put([]byte("abby"), []byte("red"))
|
||||
|
@ -181,7 +181,7 @@ func ExampleTx() {
|
|||
tx.Commit()
|
||||
|
||||
// Iterate over the values in sorted key order.
|
||||
tx, _ = db.Tx()
|
||||
tx, _ = db.Begin(false)
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
fmt.Printf("%s likes %s\n", string(k), string(v))
|
||||
|
@ -201,23 +201,23 @@ func ExampleTx_rollback() {
|
|||
defer db.Close()
|
||||
|
||||
// Create a bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
|
||||
// Set a value for a key.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
})
|
||||
|
||||
// Update the key but rollback the transaction so it never saves.
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
b := tx.Bucket("widgets")
|
||||
b.Put([]byte("foo"), []byte("baz"))
|
||||
tx.Rollback()
|
||||
|
||||
// Ensure that our original value is still set.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
value := tx.Bucket("widgets").Get([]byte("foo"))
|
||||
fmt.Printf("The value for 'foo' is still: %s\n", string(value))
|
||||
return nil
|
||||
|
@ -234,7 +234,7 @@ func ExampleDB_CopyFile() {
|
|||
defer db.Close()
|
||||
|
||||
// Create a bucket and a key.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
return nil
|
||||
|
@ -249,7 +249,7 @@ func ExampleDB_CopyFile() {
|
|||
defer db2.Close()
|
||||
|
||||
// Ensure that the key exists in the copy.
|
||||
db2.With(func(tx *Tx) error {
|
||||
db2.View(func(tx *Tx) error {
|
||||
value := tx.Bucket("widgets").Get([]byte("foo"))
|
||||
fmt.Printf("The value for 'foo' in the clone is: %s\n", string(value))
|
||||
return nil
|
||||
|
|
|
@ -28,7 +28,7 @@ func TestParallelTxs(t *testing.T) {
|
|||
var current testdata
|
||||
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
|
||||
|
@ -51,7 +51,7 @@ func TestParallelTxs(t *testing.T) {
|
|||
go func() {
|
||||
mutex.RLock()
|
||||
local := current
|
||||
tx, err := db.Tx()
|
||||
tx, err := db.Begin(false)
|
||||
mutex.RUnlock()
|
||||
if err == ErrDatabaseNotOpen {
|
||||
wg.Done()
|
||||
|
@ -89,7 +89,7 @@ func TestParallelTxs(t *testing.T) {
|
|||
pending = pending[currentBatchSize:]
|
||||
|
||||
// Start write transaction.
|
||||
tx, err := db.RWTx()
|
||||
tx, err := db.Begin(true)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
|
92
tx_test.go
92
tx_test.go
|
@ -16,7 +16,7 @@ import (
|
|||
// Ensure that committing a closed transaction returns an error.
|
||||
func TestTxCommitClosed(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
tx.CreateBucket("foo")
|
||||
assert.NoError(t, tx.Commit())
|
||||
assert.Equal(t, tx.Commit(), ErrTxClosed)
|
||||
|
@ -26,7 +26,7 @@ func TestTxCommitClosed(t *testing.T) {
|
|||
// Ensure that rolling back a closed transaction returns an error.
|
||||
func TestTxRollbackClosed(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
assert.NoError(t, tx.Rollback())
|
||||
assert.Equal(t, tx.Rollback(), ErrTxClosed)
|
||||
})
|
||||
|
@ -35,7 +35,7 @@ func TestTxRollbackClosed(t *testing.T) {
|
|||
// Ensure that committing a read-only transaction returns an error.
|
||||
func TestTxCommitReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
tx, _ := db.Tx()
|
||||
tx, _ := db.Begin(false)
|
||||
assert.Equal(t, tx.Commit(), ErrTxNotWritable)
|
||||
})
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestTxCommitReadOnly(t *testing.T) {
|
|||
// Ensure that the database can retrieve a list of buckets.
|
||||
func TestTxBuckets(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("foo")
|
||||
tx.CreateBucket("bar")
|
||||
tx.CreateBucket("baz")
|
||||
|
@ -61,7 +61,7 @@ func TestTxBuckets(t *testing.T) {
|
|||
// Ensure that creating a bucket with a read-only transaction returns an error.
|
||||
func TestTxCreateBucketReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
assert.Equal(t, tx.CreateBucket("foo"), ErrTxNotWritable)
|
||||
return nil
|
||||
})
|
||||
|
@ -71,7 +71,7 @@ func TestTxCreateBucketReadOnly(t *testing.T) {
|
|||
// Ensure that creating a bucket on a closed transaction returns an error.
|
||||
func TestTxCreateBucketClosed(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
tx.Commit()
|
||||
assert.Equal(t, tx.CreateBucket("foo"), ErrTxClosed)
|
||||
})
|
||||
|
@ -80,7 +80,7 @@ func TestTxCreateBucketClosed(t *testing.T) {
|
|||
// Ensure that a Tx can retrieve a bucket.
|
||||
func TestTxBucket(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
if assert.NotNil(t, b) {
|
||||
|
@ -94,7 +94,7 @@ func TestTxBucket(t *testing.T) {
|
|||
// Ensure that a Tx retrieving a non-existent key returns nil.
|
||||
func TestTxGetMissing(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
value := tx.Bucket("widgets").Get([]byte("no_such_key"))
|
||||
|
@ -107,12 +107,12 @@ func TestTxGetMissing(t *testing.T) {
|
|||
// Ensure that retrieving all buckets returns writable buckets.
|
||||
func TestTxWritableBuckets(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.CreateBucket("woojits")
|
||||
return nil
|
||||
})
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
buckets := tx.Buckets()
|
||||
assert.Equal(t, len(buckets), 2)
|
||||
assert.Equal(t, buckets[0].Name(), "widgets")
|
||||
|
@ -121,7 +121,7 @@ func TestTxWritableBuckets(t *testing.T) {
|
|||
buckets[1].Put([]byte("bar"), []byte("0001"))
|
||||
return nil
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
assert.Equal(t, []byte("0000"), tx.Bucket("widgets").Get([]byte("foo")))
|
||||
assert.Equal(t, []byte("0001"), tx.Bucket("woojits").Get([]byte("bar")))
|
||||
return nil
|
||||
|
@ -133,13 +133,13 @@ func TestTxWritableBuckets(t *testing.T) {
|
|||
func TestTxCreateBucket(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Create a bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket("widgets"))
|
||||
return nil
|
||||
})
|
||||
|
||||
// Read the bucket through a separate transaction.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
assert.NotNil(t, b)
|
||||
return nil
|
||||
|
@ -150,7 +150,7 @@ func TestTxCreateBucket(t *testing.T) {
|
|||
// Ensure that a bucket can be created if it doesn't already exist.
|
||||
func TestTxCreateBucketIfNotExists(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucketIfNotExists("widgets"))
|
||||
assert.NoError(t, tx.CreateBucketIfNotExists("widgets"))
|
||||
assert.Equal(t, tx.CreateBucketIfNotExists(""), ErrBucketNameRequired)
|
||||
|
@ -158,7 +158,7 @@ func TestTxCreateBucketIfNotExists(t *testing.T) {
|
|||
})
|
||||
|
||||
// Read the bucket through a separate transaction.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
b := tx.Bucket("widgets")
|
||||
assert.NotNil(t, b)
|
||||
return nil
|
||||
|
@ -170,13 +170,13 @@ func TestTxCreateBucketIfNotExists(t *testing.T) {
|
|||
func TestTxRecreateBucket(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Create a bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket("widgets"))
|
||||
return nil
|
||||
})
|
||||
|
||||
// Create the same bucket again.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.Equal(t, ErrBucketExists, tx.CreateBucket("widgets"))
|
||||
return nil
|
||||
})
|
||||
|
@ -186,7 +186,7 @@ func TestTxRecreateBucket(t *testing.T) {
|
|||
// Ensure that a bucket is created with a non-blank name.
|
||||
func TestTxCreateBucketWithoutName(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.Equal(t, ErrBucketNameRequired, tx.CreateBucket(""))
|
||||
return nil
|
||||
})
|
||||
|
@ -196,7 +196,7 @@ func TestTxCreateBucketWithoutName(t *testing.T) {
|
|||
// Ensure that a bucket name is not too long.
|
||||
func TestTxCreateBucketWithLongName(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket(strings.Repeat("X", 255)))
|
||||
assert.Equal(t, ErrBucketNameTooLarge, tx.CreateBucket(strings.Repeat("X", 256)))
|
||||
return nil
|
||||
|
@ -208,7 +208,7 @@ func TestTxCreateBucketWithLongName(t *testing.T) {
|
|||
func TestTxDeleteBucket(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Create a bucket and add a value.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
|
||||
return nil
|
||||
|
@ -216,19 +216,19 @@ func TestTxDeleteBucket(t *testing.T) {
|
|||
|
||||
// Save root page id.
|
||||
var root pgid
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
root = tx.Bucket("widgets").root
|
||||
return nil
|
||||
})
|
||||
|
||||
// Delete the bucket and make sure we can't get the value.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.DeleteBucket("widgets"))
|
||||
assert.Nil(t, tx.Bucket("widgets"))
|
||||
return nil
|
||||
})
|
||||
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
// Verify that the bucket's page is free.
|
||||
assert.Equal(t, []pgid{root}, db.freelist.all())
|
||||
|
||||
|
@ -243,7 +243,7 @@ func TestTxDeleteBucket(t *testing.T) {
|
|||
// Ensure that deleting a bucket on a closed transaction returns an error.
|
||||
func TestTxDeleteBucketClosed(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
tx.Commit()
|
||||
assert.Equal(t, tx.DeleteBucket("foo"), ErrTxClosed)
|
||||
})
|
||||
|
@ -252,7 +252,7 @@ func TestTxDeleteBucketClosed(t *testing.T) {
|
|||
// Ensure that deleting a bucket with a read-only transaction returns an error.
|
||||
func TestTxDeleteBucketReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
assert.Equal(t, tx.DeleteBucket("foo"), ErrTxNotWritable)
|
||||
return nil
|
||||
})
|
||||
|
@ -262,7 +262,7 @@ func TestTxDeleteBucketReadOnly(t *testing.T) {
|
|||
// Ensure that an error is returned when deleting from a bucket that doesn't exist.
|
||||
func TestTxDeleteBucketNotFound(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.Equal(t, ErrBucketNotFound, tx.DeleteBucket("widgets"))
|
||||
return nil
|
||||
})
|
||||
|
@ -272,10 +272,10 @@ func TestTxDeleteBucketNotFound(t *testing.T) {
|
|||
// Ensure that a Tx cursor can iterate over an empty bucket without error.
|
||||
func TestTxCursorEmptyBucket(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
k, v := c.First()
|
||||
assert.Nil(t, k)
|
||||
|
@ -288,10 +288,10 @@ func TestTxCursorEmptyBucket(t *testing.T) {
|
|||
// Ensure that a Tx cursor can reverse iterate over an empty bucket without error.
|
||||
func TestCursorEmptyBucketReverse(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
k, v := c.Last()
|
||||
assert.Nil(t, k)
|
||||
|
@ -304,14 +304,14 @@ func TestCursorEmptyBucketReverse(t *testing.T) {
|
|||
// Ensure that a Tx cursor can iterate over a single root with a couple elements.
|
||||
func TestTxCursorLeafRoot(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("baz"), []byte{})
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte{0})
|
||||
tx.Bucket("widgets").Put([]byte("bar"), []byte{1})
|
||||
return nil
|
||||
})
|
||||
tx, _ := db.Tx()
|
||||
tx, _ := db.Begin(false)
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
|
||||
k, v := c.First()
|
||||
|
@ -341,14 +341,14 @@ func TestTxCursorLeafRoot(t *testing.T) {
|
|||
// Ensure that a Tx cursor can iterate in reverse over a single root with a couple elements.
|
||||
func TestTxCursorLeafRootReverse(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("baz"), []byte{})
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte{0})
|
||||
tx.Bucket("widgets").Put([]byte("bar"), []byte{1})
|
||||
return nil
|
||||
})
|
||||
tx, _ := db.Tx()
|
||||
tx, _ := db.Begin(false)
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
|
||||
k, v := c.Last()
|
||||
|
@ -378,14 +378,14 @@ func TestTxCursorLeafRootReverse(t *testing.T) {
|
|||
// Ensure that a Tx cursor can restart from the beginning.
|
||||
func TestTxCursorRestart(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
tx.Bucket("widgets").Put([]byte("bar"), []byte{})
|
||||
tx.Bucket("widgets").Put([]byte("foo"), []byte{})
|
||||
return nil
|
||||
})
|
||||
|
||||
tx, _ := db.Tx()
|
||||
tx, _ := db.Begin(false)
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
|
||||
k, _ := c.First()
|
||||
|
@ -413,7 +413,7 @@ func TestTxCursorIterate(t *testing.T) {
|
|||
f := func(items testdata) bool {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Bulk insert all values.
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
for _, item := range items {
|
||||
|
@ -426,7 +426,7 @@ func TestTxCursorIterate(t *testing.T) {
|
|||
|
||||
// Iterate over all items and check consistency.
|
||||
var index = 0
|
||||
tx, _ = db.Tx()
|
||||
tx, _ = db.Begin(false)
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
for k, v := c.First(); k != nil && index < len(items); k, v = c.Next() {
|
||||
assert.Equal(t, k, items[index].Key)
|
||||
|
@ -454,7 +454,7 @@ func TestTxCursorIterateReverse(t *testing.T) {
|
|||
f := func(items testdata) bool {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Bulk insert all values.
|
||||
tx, _ := db.RWTx()
|
||||
tx, _ := db.Begin(true)
|
||||
tx.CreateBucket("widgets")
|
||||
b := tx.Bucket("widgets")
|
||||
for _, item := range items {
|
||||
|
@ -467,7 +467,7 @@ func TestTxCursorIterateReverse(t *testing.T) {
|
|||
|
||||
// Iterate over all items and check consistency.
|
||||
var index = 0
|
||||
tx, _ = db.Tx()
|
||||
tx, _ = db.Begin(false)
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
for k, v := c.Last(); k != nil && index < len(items); k, v = c.Prev() {
|
||||
assert.Equal(t, k, items[index].Key)
|
||||
|
@ -493,7 +493,7 @@ func BenchmarkTxCursor(b *testing.B) {
|
|||
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
// Write data to bucket.
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket("widgets")
|
||||
bucket := tx.Bucket("widgets")
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
@ -504,7 +504,7 @@ func BenchmarkTxCursor(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
// Iterate over bucket using cursor.
|
||||
db.With(func(tx *Tx) error {
|
||||
db.View(func(tx *Tx) error {
|
||||
count := 0
|
||||
c := tx.Bucket("widgets").Cursor()
|
||||
for k, _ := c.First(); k != nil; k, _ = c.Next() {
|
||||
|
@ -523,7 +523,7 @@ func BenchmarkTxPutRandom(b *testing.B) {
|
|||
indexes := rand.Perm(b.N)
|
||||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
var tx *Tx
|
||||
|
@ -533,7 +533,7 @@ func BenchmarkTxPutRandom(b *testing.B) {
|
|||
if tx != nil {
|
||||
tx.Commit()
|
||||
}
|
||||
tx, _ = db.RWTx()
|
||||
tx, _ = db.Begin(true)
|
||||
bucket = tx.Bucket("widgets")
|
||||
}
|
||||
bucket.Put([]byte(strconv.Itoa(indexes[i])), value)
|
||||
|
@ -546,10 +546,10 @@ func BenchmarkTxPutRandom(b *testing.B) {
|
|||
func BenchmarkTxPutSequential(b *testing.B) {
|
||||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket("widgets")
|
||||
})
|
||||
db.Do(func(tx *Tx) error {
|
||||
db.Update(func(tx *Tx) error {
|
||||
bucket := tx.Bucket("widgets")
|
||||
for i := 0; i < b.N; i++ {
|
||||
bucket.Put([]byte(strconv.Itoa(i)), value)
|
||||
|
|
Loading…
Reference in New Issue