diff options
author | Ben Johnson <benbjohnson@yahoo.com> | 2014-02-15 10:23:00 -0700 |
---|---|---|
committer | Ben Johnson <benbjohnson@yahoo.com> | 2014-02-15 10:23:00 -0700 |
commit | e68bc0b4530475503afb34956dfb915673af919c (patch) | |
tree | c1747819b8499d03e4a5348b1f42d1c22b73e3f2 | |
parent | Merge pull request #30 from benbjohnson/examples (diff) | |
download | dedo-e68bc0b4530475503afb34956dfb915673af919c.tar.gz dedo-e68bc0b4530475503afb34956dfb915673af919c.tar.xz |
Add bucket sequence.
-rw-r--r-- | bucket.go | 1 | ||||
-rw-r--r-- | buckets.go | 5 | ||||
-rw-r--r-- | db.go | 19 | ||||
-rw-r--r-- | rwtransaction.go | 14 | ||||
-rw-r--r-- | rwtransaction_test.go | 26 |
5 files changed, 64 insertions, 1 deletions
@@ -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, + } } } @@ -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) { diff --git a/rwtransaction.go b/rwtransaction.go index 92d05a8..568960a 100644 --- a/rwtransaction.go +++ b/rwtransaction.go @@ -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. diff --git a/rwtransaction_test.go b/rwtransaction_test.go index 1ce3f70..fa254d8 100644 --- a/rwtransaction_test.go +++ b/rwtransaction_test.go @@ -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) |