mirror of https://github.com/etcd-io/bbolt.git
Add bucket sequence.
parent
af5b9182f1
commit
e68bc0b453
|
@ -13,6 +13,7 @@ type Bucket struct {
|
|||
// bucket represents the on-file representation of a bucket.
|
||||
type bucket struct {
|
||||
root pgid
|
||||
sequence uint64
|
||||
}
|
||||
|
||||
// Name returns the name of the bucket.
|
||||
|
|
|
@ -63,7 +63,10 @@ func (b *buckets) read(p *page) {
|
|||
|
||||
// Associate keys and items.
|
||||
for index, key := range keys {
|
||||
b.items[key] = &bucket{items[index].root}
|
||||
b.items[key] = &bucket{
|
||||
root: items[index].root,
|
||||
sequence: items[index].sequence,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
19
db.go
19
db.go
|
@ -384,6 +384,25 @@ func (db *DB) DeleteBucket(name string) error {
|
|||
return t.Commit()
|
||||
}
|
||||
|
||||
// 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()
|
||||
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
|
||||
}
|
||||
|
||||
// Get retrieves the value for a key in a bucket.
|
||||
// Returns an error if the key does not exist.
|
||||
func (db *DB) Get(name string, key []byte) ([]byte, error) {
|
||||
|
|
|
@ -66,6 +66,20 @@ func (t *RWTransaction) DeleteBucket(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// NextSequence returns an autoincrementing integer for the bucket.
|
||||
func (t *RWTransaction) NextSequence(name string) (int, error) {
|
||||
// Check if bucket already exists.
|
||||
b := t.Bucket(name)
|
||||
if b == nil {
|
||||
return 0, BucketNotFoundError
|
||||
}
|
||||
|
||||
// Increment and return the sequence.
|
||||
b.bucket.sequence++
|
||||
|
||||
return int(b.bucket.sequence), nil
|
||||
}
|
||||
|
||||
// Put sets the value for a key inside of the named bucket.
|
||||
// If the key exist then its previous value will be overwritten.
|
||||
// Returns an error if the bucket is not found, if the key is blank, if the key is too large, or if the value is too large.
|
||||
|
|
|
@ -72,6 +72,32 @@ func TestRWTransactionDeleteBucket(t *testing.T) {
|
|||
t.Skip("pending") // TODO(benbjohnson)
|
||||
}
|
||||
|
||||
// Ensure that a bucket can return an autoincrementing sequence.
|
||||
func TestRWTransactionNextSequence(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.CreateBucket("widgets")
|
||||
db.CreateBucket("woojits")
|
||||
|
||||
// Make sure sequence increments.
|
||||
seq, err := db.NextSequence("widgets")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, seq, 1)
|
||||
seq, err = db.NextSequence("widgets")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, seq, 2)
|
||||
|
||||
// Buckets should be separate.
|
||||
seq, err = db.NextSequence("woojits")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, seq, 1)
|
||||
|
||||
// Missing buckets return an error.
|
||||
seq, err = db.NextSequence("no_such_bucket")
|
||||
assert.Equal(t, err, BucketNotFoundError)
|
||||
assert.Equal(t, seq, 0)
|
||||
})
|
||||
}
|
||||
|
||||
// Ensure that an error is returned when inserting into a bucket that doesn't exist.
|
||||
func TestRWTransactionPutBucketNotFound(t *testing.T) {
|
||||
t.Skip("pending") // TODO(benbjohnson)
|
||||
|
|
Loading…
Reference in New Issue