diff --git a/core/rawdb/table.go b/core/rawdb/table.go index 9a342a8217..3fe6c522d2 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -223,6 +223,11 @@ func (b *tableBatch) Delete(key []byte) error { return b.batch.Delete(append([]byte(b.prefix), key...)) } +// DeleteRange removes all keys in the range [start, end) from the batch for later committing. +func (b *tableBatch) DeleteRange(start, end []byte) error { + return b.batch.DeleteRange(append([]byte(b.prefix), start...), append([]byte(b.prefix), end...)) +} + // ValueSize retrieves the amount of data queued up for writing. func (b *tableBatch) ValueSize() int { return b.batch.ValueSize() diff --git a/ethdb/batch.go b/ethdb/batch.go index f3c2ca555c..45b3781cb0 100644 --- a/ethdb/batch.go +++ b/ethdb/batch.go @@ -24,10 +24,7 @@ const IdealBatchSize = 100 * 1024 // when Write is called. A batch cannot be used concurrently. type Batch interface { KeyValueWriter - - // DeleteRange deletes all of the keys (and values) in the range [start,end) - // (inclusive on start, exclusive on end). - DeleteRange(start, end []byte) error + KeyValueRangeDeleter // ValueSize retrieves the amount of data queued up for writing. ValueSize() int diff --git a/ethdb/database.go b/ethdb/database.go index 2b9cba4e69..0d752cc8d7 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -38,7 +38,12 @@ type KeyValueWriter interface { // Delete removes the key from the key-value data store. Delete(key []byte) error +} +var ErrTooManyKeys = errors.New("too many keys in deleted range") + +// KeyValueRangeDeleter wraps the DeleteRange method of a backing data store. +type KeyValueRangeDeleter interface { // DeleteRange deletes all of the keys (and values) in the range [start,end) // (inclusive on start, exclusive on end). // Some implementations of DeleteRange may return ErrTooManyKeys after @@ -46,8 +51,6 @@ type KeyValueWriter interface { DeleteRange(start, end []byte) error } -var ErrTooManyKeys = errors.New("too many keys in deleted range") - // KeyValueStater wraps the Stat method of a backing data store. type KeyValueStater interface { // Stat returns the statistic data of the database. @@ -80,6 +83,7 @@ type KeyValueStore interface { KeyValueWriter KeyValueStater KeyValueSyncer + KeyValueRangeDeleter Batcher Iteratee Compacter diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index 173a0660db..c1523aba1f 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -574,7 +574,12 @@ func (r *replayer) DeleteRange(start, end []byte) { if r.failure != nil { return } - r.failure = r.writer.DeleteRange(start, end) + // Check if the writer also supports range deletion + if rangeDeleter, ok := r.writer.(ethdb.KeyValueRangeDeleter); ok { + r.failure = rangeDeleter.DeleteRange(start, end) + } else { + r.failure = fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") + } } // bytesPrefixRange returns key range that satisfy diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go index 436c045f15..eb49ddbd7b 100644 --- a/ethdb/memorydb/memorydb.go +++ b/ethdb/memorydb/memorydb.go @@ -19,6 +19,7 @@ package memorydb import ( "errors" + "fmt" "sort" "strconv" "strings" @@ -362,8 +363,12 @@ func (b *batch) Replay(w ethdb.KeyValueWriter) error { } } else if keyvalue.rangeFrom != "" || keyvalue.rangeTo != "" { // Range deletion - if err := w.DeleteRange([]byte(keyvalue.rangeFrom), []byte(keyvalue.rangeTo)); err != nil { - return err + if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok { + if err := rangeDeleter.DeleteRange([]byte(keyvalue.rangeFrom), []byte(keyvalue.rangeTo)); err != nil { + return err + } + } else { + return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") } } continue diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index 3a026508de..c92718d0d6 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -670,8 +670,12 @@ func (b *batch) Replay(w ethdb.KeyValueWriter) error { } } else if kind == pebble.InternalKeyKindRangeDelete { // For range deletion, k is the start key and v is the end key - if err = w.DeleteRange(k, v); err != nil { - return err + if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok { + if err = rangeDeleter.DeleteRange(k, v); err != nil { + return err + } + } else { + return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") } } else { return fmt.Errorf("unhandled operation, keytype: %v", kind) diff --git a/trie/trie_test.go b/trie/trie_test.go index 91fde6dbf2..b806ae6b0c 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -876,6 +876,7 @@ func (b *spongeBatch) Put(key, value []byte) error { return nil } func (b *spongeBatch) Delete(key []byte) error { panic("implement me") } +func (b *spongeBatch) DeleteRange(start, end []byte) error { panic("implement me") } func (b *spongeBatch) ValueSize() int { return 100 } func (b *spongeBatch) Write() error { return nil } func (b *spongeBatch) Reset() {}