mirror of
https://github.com/taigrr/bitcask
synced 2025-01-18 04:03:17 -08:00
Fix runGC behaviour to correctly delete all expired keys (#229)
Fixes #228 Co-authored-by: James Mills <prologic@shortcircuit.net.au> Reviewed-on: https://git.mills.io/prologic/bitcask/pulls/229 Co-authored-by: James Mills <james@mills.io> Co-committed-by: James Mills <james@mills.io>
This commit is contained in:
parent
3ff8937205
commit
b094cd33d3
16
bitcask.go
16
bitcask.go
@ -349,16 +349,24 @@ func (b *Bitcask) RunGC() error {
|
|||||||
// runGC deletes all keys that are expired
|
// runGC deletes all keys that are expired
|
||||||
// caller function should take care of the locking when calling this method
|
// caller function should take care of the locking when calling this method
|
||||||
func (b *Bitcask) runGC() (err error) {
|
func (b *Bitcask) runGC() (err error) {
|
||||||
|
keysToDelete := art.New()
|
||||||
|
|
||||||
b.ttlIndex.ForEach(func(node art.Node) (cont bool) {
|
b.ttlIndex.ForEach(func(node art.Node) (cont bool) {
|
||||||
if !b.isExpired(node.Key()) {
|
if !b.isExpired(node.Key()) {
|
||||||
|
// later, return false here when the ttlIndex is sorted
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if err = b.delete(node.Key()); err != nil {
|
keysToDelete.Insert(node.Key(), true)
|
||||||
return false
|
//keysToDelete = append(keysToDelete, node.Key())
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return
|
|
||||||
|
keysToDelete.ForEach(func(node art.Node) (cont bool) {
|
||||||
|
b.delete(node.Key())
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fold iterates over all keys in the database calling the function `f` for
|
// Fold iterates over all keys in the database calling the function `f` for
|
||||||
|
@ -1784,7 +1784,38 @@ func TestGetExpiredInsideFold(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.Contains(arr, "skipped")
|
assert.Contains(arr, "skipped")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunGCDeletesAllExpired(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
testdir, err := ioutil.TempDir("", "bitcask")
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
db, err := Open(testdir)
|
||||||
|
assert.NoError(err)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Add a node to the tree that won't expire
|
||||||
|
db.Put([]byte("static"), []byte("static"))
|
||||||
|
|
||||||
|
// Add a node that expires almost immediately to the tree
|
||||||
|
db.PutWithTTL([]byte("shortLived"), []byte("shortLived"), 0)
|
||||||
|
db.PutWithTTL([]byte("longLived"), []byte("longLived"), time.Hour)
|
||||||
|
db.PutWithTTL([]byte("longLived2"), []byte("longLived2"), time.Hour)
|
||||||
|
db.PutWithTTL([]byte("shortLived2"), []byte("shortLived2"), 0)
|
||||||
|
db.PutWithTTL([]byte("shortLived3"), []byte("shortLived3"), 0)
|
||||||
|
db.Put([]byte("static2"), []byte("static2"))
|
||||||
|
|
||||||
|
// Sleep a bit and run the Garbage Collector
|
||||||
|
time.Sleep(3 * time.Millisecond)
|
||||||
|
db.RunGC()
|
||||||
|
|
||||||
|
_ = db.Fold(func(key []byte) error {
|
||||||
|
_, err := db.Get(key)
|
||||||
|
assert.NoError(err)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type benchmarkTestCase struct {
|
type benchmarkTestCase struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user