Skip to content

Commit

Permalink
Add Sequence.Release() (dgraph-io#362)
Browse files Browse the repository at this point in the history
* Add Sequence.Release()

- Add new method `Release() error` on `Sequence`
- Add defer example to readme
- Test release and use after release
  • Loading branch information
nochso authored and manishrjain committed Dec 18, 2017
1 parent 0e668c5 commit 5a6340e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,11 @@ bandwidth provided to `DB.GetSequence`. The frequency at which disk writes are
done is determined by this lease bandwidth and the frequency of `Next`
invocations. Setting a bandwith too low would do more disk writes, setting it
too high would result in wasted integers if Badger is closed or crashes.
To avoid wasted integers, call `Release` before closing Badger.

```go
seq, err := db.GetSequence(key, 1000)
defer seq.Release()
for {
num, err := seq.Next()
}
Expand Down
18 changes: 18 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,24 @@ func (seq *Sequence) Next() (uint64, error) {
return val, nil
}

// Release the leased sequence to avoid wasted integers. This should be done right
// before closing the associated DB. However it is valid to use the sequence after
// it was released, causing a new lease with full bandwidth.
func (seq *Sequence) Release() error {
seq.Lock()
defer seq.Unlock()
err := seq.db.Update(func(txn *Txn) error {
var buf [8]byte
binary.BigEndian.PutUint64(buf[:], seq.next)
return txn.Set(seq.key, buf[:])
})
if err != nil {
return err
}
seq.leased = seq.next
return nil
}

func (seq *Sequence) updateLease() error {
return seq.db.Update(func(txn *Txn) error {
item, err := txn.Get(seq.key)
Expand Down
46 changes: 46 additions & 0 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,52 @@ func TestSequence(t *testing.T) {
})
}

func TestSequence_Release(t *testing.T) {
runBadgerTest(t, nil, func(t *testing.T, db *DB) {
// get sequence, use once and release
key := []byte("key")
seq, err := db.GetSequence(key, 1000)
require.NoError(t, err)
num, err := seq.Next()
require.NoError(t, err)
require.Equal(t, uint64(0), num)
require.NoError(t, seq.Release())

// we used up 0 and 1 should be stored now
err = db.View(func(txn *Txn) error {
item, err := txn.Get(key)
if err != nil {
return err
}
val, err := item.Value()
if err != nil {
return err
}
require.Equal(t, num+1, binary.BigEndian.Uint64(val))
return nil
})
require.NoError(t, err)

// using it again will lease 1+1000
num, err = seq.Next()
require.NoError(t, err)
require.Equal(t, uint64(1), num)
err = db.View(func(txn *Txn) error {
item, err := txn.Get(key)
if err != nil {
return err
}
val, err := item.Value()
if err != nil {
return err
}
require.Equal(t, uint64(1001), binary.BigEndian.Uint64(val))
return nil
})
require.NoError(t, err)
})
}

func ExampleOpen() {
dir, err := ioutil.TempDir("", "badger")
if err != nil {
Expand Down

0 comments on commit 5a6340e

Please sign in to comment.