mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 15:47:21 +00:00
Merge 8f4deb0636 into 2a45272408
This commit is contained in:
commit
22437cf5be
2 changed files with 70 additions and 2 deletions
|
|
@ -17,6 +17,8 @@
|
|||
package rawdb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
)
|
||||
|
||||
|
|
@ -272,6 +274,16 @@ func (r *tableReplayer) Delete(key []byte) error {
|
|||
return r.w.Delete(trimmed)
|
||||
}
|
||||
|
||||
// DeleteRange implements the interface KeyValueRangeDeleter.
|
||||
func (r *tableReplayer) DeleteRange(start, end []byte) error {
|
||||
trimmedStart := start[len(r.prefix):]
|
||||
trimmedEnd := end[len(r.prefix):]
|
||||
if rangeDeleter, ok := r.w.(ethdb.KeyValueRangeDeleter); ok {
|
||||
return rangeDeleter.DeleteRange(trimmedStart, trimmedEnd)
|
||||
}
|
||||
return errors.New("ethdb.KeyValueWriter does not implement DeleteRange")
|
||||
}
|
||||
|
||||
// Replay replays the batch contents.
|
||||
func (b *tableBatch) Replay(w ethdb.KeyValueWriter) error {
|
||||
return b.batch.Replay(&tableReplayer{w: w, prefix: b.prefix})
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ func TestTableDatabase(t *testing.T) { testTableDatabase(t, "prefix")
|
|||
func TestEmptyPrefixTableDatabase(t *testing.T) { testTableDatabase(t, "") }
|
||||
|
||||
type testReplayer struct {
|
||||
puts [][]byte
|
||||
dels [][]byte
|
||||
puts [][]byte
|
||||
dels [][]byte
|
||||
delRanges [][2][]byte
|
||||
}
|
||||
|
||||
func (r *testReplayer) Put(key []byte, value []byte) error {
|
||||
|
|
@ -41,6 +42,11 @@ func (r *testReplayer) Delete(key []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *testReplayer) DeleteRange(start, end []byte) error {
|
||||
r.delRanges = append(r.delRanges, [2][]byte{start, end})
|
||||
return nil
|
||||
}
|
||||
|
||||
func testTableDatabase(t *testing.T, prefix string) {
|
||||
db := NewTable(NewMemoryDatabase(), prefix)
|
||||
|
||||
|
|
@ -126,6 +132,56 @@ func testTableDatabase(t *testing.T, prefix string) {
|
|||
check(db.NewIterator([]byte{0xee}, nil), 0, 0)
|
||||
check(db.NewIterator(nil, []byte{0x00}), 6, 0)
|
||||
|
||||
// Test batch replayer with DeleteRange
|
||||
db2 := NewTable(NewMemoryDatabase(), prefix)
|
||||
for _, entry := range entries {
|
||||
db2.Put(entry.key, entry.value)
|
||||
}
|
||||
batch2 := db2.NewBatch()
|
||||
batch2.Put([]byte{0x07, 0x08}, []byte{0x10, 0x11})
|
||||
batch2.DeleteRange([]byte{0x01, 0x02}, []byte{0x05, 0x06})
|
||||
batch2.Delete([]byte{0xff, 0xff, 0x03})
|
||||
|
||||
// Replay into another batch (tests tableReplayer.DeleteRange via batch-to-batch)
|
||||
batch3 := db2.NewBatch()
|
||||
if err := batch2.Replay(batch3); err != nil {
|
||||
t.Fatalf("Failed to replay batch with DeleteRange: %v", err)
|
||||
}
|
||||
if err := batch3.Write(); err != nil {
|
||||
t.Fatalf("Failed to write replayed batch: %v", err)
|
||||
}
|
||||
// Keys in range [0x01,0x02 .. 0x05,0x06) should be deleted
|
||||
for _, key := range [][]byte{{0x01, 0x02}, {0x03, 0x04}} {
|
||||
if _, err := db2.Get(key); err == nil {
|
||||
t.Fatalf("Key %x should be deleted after replayed DeleteRange", key)
|
||||
}
|
||||
}
|
||||
// Key 0x05,0x06 should still exist (exclusive end)
|
||||
if _, err := db2.Get([]byte{0x05, 0x06}); err != nil {
|
||||
t.Fatalf("Key 0x0506 should exist (exclusive end): %v", err)
|
||||
}
|
||||
// New key should exist
|
||||
if _, err := db2.Get([]byte{0x07, 0x08}); err != nil {
|
||||
t.Fatalf("Key 0x0708 should exist after replay: %v", err)
|
||||
}
|
||||
// Deleted single key should be gone
|
||||
if _, err := db2.Get([]byte{0xff, 0xff, 0x03}); err == nil {
|
||||
t.Fatal("Key 0xffff03 should be deleted after replay")
|
||||
}
|
||||
|
||||
// Replay into a testReplayer to verify prefix stripping
|
||||
r2 := &testReplayer{}
|
||||
batch2.Replay(r2)
|
||||
if len(r2.delRanges) != 1 {
|
||||
t.Fatalf("Expected 1 DeleteRange in replay, got %d", len(r2.delRanges))
|
||||
}
|
||||
if !bytes.Equal(r2.delRanges[0][0], []byte{0x01, 0x02}) {
|
||||
t.Fatalf("DeleteRange start mismatch: want=%x, got=%x", []byte{0x01, 0x02}, r2.delRanges[0][0])
|
||||
}
|
||||
if !bytes.Equal(r2.delRanges[0][1], []byte{0x05, 0x06}) {
|
||||
t.Fatalf("DeleteRange end mismatch: want=%x, got=%x", []byte{0x05, 0x06}, r2.delRanges[0][1])
|
||||
}
|
||||
|
||||
// Test range deletion
|
||||
db.DeleteRange(nil, nil)
|
||||
for _, entry := range entries {
|
||||
|
|
|
|||
Loading…
Reference in a new issue