Add bucket sequence.

pull/34/head
Ben Johnson 2014-02-15 10:23:00 -07:00
parent af5b9182f1
commit e68bc0b453
5 changed files with 64 additions and 1 deletions

View File

@ -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.

View File

@ -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
View File

@ -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) {

View File

@ -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.

View File

@ -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)