diff --git a/internal/db/namespaced.go b/internal/db/namespaced.go index 39b155c2f..9cb14900a 100644 --- a/internal/db/namespaced.go +++ b/internal/db/namespaced.go @@ -11,6 +11,7 @@ import ( "time" "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/util" ) // NamespacedKV is a simple key-value store using a specific namespace within @@ -29,6 +30,27 @@ func NewNamespacedKV(db *leveldb.DB, prefix string) *NamespacedKV { } } +// Reset removes all entries in this namespace. +func (n *NamespacedKV) Reset() { + it := n.db.NewIterator(util.BytesPrefix(n.prefix), nil) + defer it.Release() + batch := new(leveldb.Batch) + for it.Next() { + batch.Delete(it.Key()) + if batch.Len() > batchFlushSize { + if err := n.db.Write(batch, nil); err != nil { + panic(err) + } + batch.Reset() + } + } + if batch.Len() > 0 { + if err := n.db.Write(batch, nil); err != nil { + panic(err) + } + } +} + // PutInt64 stores a new int64. Any existing value (even if of another type) // is overwritten. func (n *NamespacedKV) PutInt64(key string, val int64) { diff --git a/internal/db/namespaced_test.go b/internal/db/namespaced_test.go index 22b274977..b55a21ef0 100644 --- a/internal/db/namespaced_test.go +++ b/internal/db/namespaced_test.go @@ -90,3 +90,38 @@ func TestNamespacedString(t *testing.T) { t.Errorf("Incorrect return v %q != \"yo\" || ok %v != true", v, ok) } } + +func TestNamespacedReset(t *testing.T) { + ldb, err := leveldb.Open(storage.NewMemStorage(), nil) + if err != nil { + t.Fatal(err) + } + + n1 := NewNamespacedKV(ldb, "foo") + + n1.PutString("test1", "yo1") + n1.PutString("test2", "yo2") + n1.PutString("test3", "yo3") + + if v, ok := n1.String("test1"); v != "yo1" || !ok { + t.Errorf("Incorrect return v %q != \"yo1\" || ok %v != true", v, ok) + } + if v, ok := n1.String("test2"); v != "yo2" || !ok { + t.Errorf("Incorrect return v %q != \"yo2\" || ok %v != true", v, ok) + } + if v, ok := n1.String("test3"); v != "yo3" || !ok { + t.Errorf("Incorrect return v %q != \"yo3\" || ok %v != true", v, ok) + } + + n1.Reset() + + if v, ok := n1.String("test1"); v != "" || ok { + t.Errorf("Incorrect return v %q != \"\" || ok %v != false", v, ok) + } + if v, ok := n1.String("test2"); v != "" || ok { + t.Errorf("Incorrect return v %q != \"\" || ok %v != false", v, ok) + } + if v, ok := n1.String("test3"); v != "" || ok { + t.Errorf("Incorrect return v %q != \"\" || ok %v != false", v, ok) + } +}