Skip to content

Commit 846d13a

Browse files
hadvprpehrjl493456442
authored
ethdb: Implement DeleteRange in batch (#31947)
implement #31945 --------- Co-authored-by: prpeh <[email protected]> Co-authored-by: Gary Rong <[email protected]>
1 parent f26b565 commit 846d13a

File tree

9 files changed

+591
-20
lines changed

9 files changed

+591
-20
lines changed

core/rawdb/table.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ func (t *table) Delete(key []byte) error {
126126
// DeleteRange deletes all of the keys (and values) in the range [start,end)
127127
// (inclusive on start, exclusive on end).
128128
func (t *table) DeleteRange(start, end []byte) error {
129+
// The nilness will be lost by adding the prefix, explicitly converting it
130+
// to a special flag representing the end of key range.
131+
if end == nil {
132+
end = ethdb.MaximumKey
133+
}
129134
return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...))
130135
}
131136

@@ -217,6 +222,16 @@ func (b *tableBatch) Delete(key []byte) error {
217222
return b.batch.Delete(append([]byte(b.prefix), key...))
218223
}
219224

225+
// DeleteRange removes all keys in the range [start, end) from the batch for later committing.
226+
func (b *tableBatch) DeleteRange(start, end []byte) error {
227+
// The nilness will be lost by adding the prefix, explicitly converting it
228+
// to a special flag representing the end of key range.
229+
if end == nil {
230+
end = ethdb.MaximumKey
231+
}
232+
return b.batch.DeleteRange(append([]byte(b.prefix), start...), append([]byte(b.prefix), end...))
233+
}
234+
220235
// ValueSize retrieves the amount of data queued up for writing.
221236
func (b *tableBatch) ValueSize() int {
222237
return b.batch.ValueSize()

core/rawdb/table_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,28 @@ func testTableDatabase(t *testing.T, prefix string) {
125125
// Test iterators with prefix and start point
126126
check(db.NewIterator([]byte{0xee}, nil), 0, 0)
127127
check(db.NewIterator(nil, []byte{0x00}), 6, 0)
128+
129+
// Test range deletion
130+
db.DeleteRange(nil, nil)
131+
for _, entry := range entries {
132+
_, err := db.Get(entry.key)
133+
if err == nil {
134+
t.Fatal("Unexpected item after deletion")
135+
}
136+
}
137+
// Test range deletion by batch
138+
batch = db.NewBatch()
139+
for _, entry := range entries {
140+
batch.Put(entry.key, entry.value)
141+
}
142+
batch.Write()
143+
batch.Reset()
144+
batch.DeleteRange(nil, nil)
145+
batch.Write()
146+
for _, entry := range entries {
147+
_, err := db.Get(entry.key)
148+
if err == nil {
149+
t.Fatal("Unexpected item after deletion")
150+
}
151+
}
128152
}

ethdb/batch.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const IdealBatchSize = 100 * 1024
2424
// when Write is called. A batch cannot be used concurrently.
2525
type Batch interface {
2626
KeyValueWriter
27+
KeyValueRangeDeleter
2728

2829
// ValueSize retrieves the amount of data queued up for writing.
2930
ValueSize() int
@@ -53,8 +54,9 @@ type Batcher interface {
5354
type HookedBatch struct {
5455
Batch
5556

56-
OnPut func(key []byte, value []byte) // Callback if a key is inserted
57-
OnDelete func(key []byte) // Callback if a key is deleted
57+
OnPut func(key []byte, value []byte) // Callback if a key is inserted
58+
OnDelete func(key []byte) // Callback if a key is deleted
59+
OnDeleteRange func(start, end []byte) // Callback if a range of keys is deleted
5860
}
5961

6062
// Put inserts the given value into the key-value data store.
@@ -72,3 +74,11 @@ func (b HookedBatch) Delete(key []byte) error {
7274
}
7375
return b.Batch.Delete(key)
7476
}
77+
78+
// DeleteRange removes all keys in the range [start, end) from the key-value data store.
79+
func (b HookedBatch) DeleteRange(start, end []byte) error {
80+
if b.OnDeleteRange != nil {
81+
b.OnDeleteRange(start, end)
82+
}
83+
return b.Batch.DeleteRange(start, end)
84+
}

ethdb/database.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,23 @@
1818
package ethdb
1919

2020
import (
21+
"bytes"
2122
"errors"
2223
"io"
2324
)
2425

26+
var (
27+
// MaximumKey is a special marker representing the largest possible key
28+
// in the database.
29+
//
30+
// All prefixed database entries will be smaller than this marker.
31+
// For trie nodes in hash mode, we use a 32-byte slice filled with 0xFF
32+
// because there may be shared prefixes starting with multiple 0xFF bytes.
33+
// Using 32 bytes ensures that only a hash collision could potentially
34+
// match or exceed it.
35+
MaximumKey = bytes.Repeat([]byte{0xff}, 32)
36+
)
37+
2538
// KeyValueReader wraps the Has and Get method of a backing data store.
2639
type KeyValueReader interface {
2740
// Has retrieves if a key is present in the key-value data store.
@@ -46,6 +59,11 @@ var ErrTooManyKeys = errors.New("too many keys in deleted range")
4659
type KeyValueRangeDeleter interface {
4760
// DeleteRange deletes all of the keys (and values) in the range [start,end)
4861
// (inclusive on start, exclusive on end).
62+
//
63+
// A nil start is treated as a key before all keys in the data store; a nil
64+
// end is treated as a key after all keys in the data store. If both is nil
65+
// then the entire data store will be purged.
66+
//
4967
// Some implementations of DeleteRange may return ErrTooManyKeys after
5068
// partially deleting entries in the given range.
5169
DeleteRange(start, end []byte) error

0 commit comments

Comments
 (0)