mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
ethdb: removed DeleteRange support on batches
This commit is contained in:
parent
5660e57a41
commit
f596f79f61
7 changed files with 74 additions and 133 deletions
|
|
@ -129,7 +129,8 @@ func (t *table) Delete(key []byte) error {
|
||||||
return t.db.Delete(append([]byte(t.prefix), key...))
|
return t.db.Delete(append([]byte(t.prefix), key...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange removes all keys in the range [start,end) from the database.
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
|
// (inclusive on start, exclusive on end).
|
||||||
func (t *table) DeleteRange(start, end []byte) error {
|
func (t *table) DeleteRange(start, end []byte) error {
|
||||||
return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...))
|
return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...))
|
||||||
}
|
}
|
||||||
|
|
@ -216,10 +217,9 @@ func (b *tableBatch) Delete(key []byte) error {
|
||||||
return b.batch.Delete(append([]byte(b.prefix), key...))
|
return b.batch.Delete(append([]byte(b.prefix), key...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange inserts the removal all of the keys in the range [start,end) into
|
// DeleteRange implements KeyValueWriter (not supported on batches).
|
||||||
// the batch for later committing.
|
|
||||||
func (b *tableBatch) DeleteRange(start, end []byte) error {
|
func (b *tableBatch) DeleteRange(start, end []byte) error {
|
||||||
return b.batch.DeleteRange(append([]byte(b.prefix), start...), append([]byte(b.prefix), end...))
|
panic("DeleteRange is not supported on batches")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ type KeyValueWriter interface {
|
||||||
// Delete removes the key from the key-value data store.
|
// Delete removes the key from the key-value data store.
|
||||||
Delete(key []byte) error
|
Delete(key []byte) error
|
||||||
|
|
||||||
// DeleteRange removes all keys in the range [start,end) from the key-value store.
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
|
// (inclusive on start, exclusive on end).
|
||||||
DeleteRange(start, end []byte) error
|
DeleteRange(start, end []byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -349,89 +349,58 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
|
||||||
db := New()
|
db := New()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
test := func(addToBatch, deleteFromBatch bool) {
|
addRange := func(start, stop int) {
|
||||||
var batch ethdb.Batch
|
for i := start; i <= stop; i++ {
|
||||||
addRange := func(start, stop int) {
|
db.Put([]byte(strconv.Itoa(i)), nil)
|
||||||
if addToBatch {
|
|
||||||
batch = db.NewBatch()
|
|
||||||
}
|
|
||||||
for i := start; i <= stop; i++ {
|
|
||||||
if addToBatch {
|
|
||||||
batch.Put([]byte(strconv.Itoa(i)), nil)
|
|
||||||
} else {
|
|
||||||
db.Put([]byte(strconv.Itoa(i)), nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if addToBatch && !deleteFromBatch {
|
|
||||||
batch.Write()
|
|
||||||
batch = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteRange := func(start, end []byte) {
|
|
||||||
if deleteFromBatch {
|
|
||||||
if batch == nil {
|
|
||||||
batch = db.NewBatch()
|
|
||||||
}
|
|
||||||
batch.DeleteRange(start, end)
|
|
||||||
batch.Write()
|
|
||||||
batch = nil
|
|
||||||
} else {
|
|
||||||
db.DeleteRange(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkRange := func(start, stop int, exp bool) {
|
|
||||||
for i := start; i <= stop; i++ {
|
|
||||||
has, _ := db.Has([]byte(strconv.Itoa(i)))
|
|
||||||
if has && !exp {
|
|
||||||
t.Fatalf("unexpected key %d", i)
|
|
||||||
}
|
|
||||||
if !has && exp {
|
|
||||||
t.Fatalf("missing expected key %d", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addRange(1, 9)
|
|
||||||
deleteRange([]byte("9"), []byte("1"))
|
|
||||||
checkRange(1, 9, true)
|
|
||||||
deleteRange([]byte("5"), []byte("5"))
|
|
||||||
checkRange(1, 9, true)
|
|
||||||
deleteRange([]byte("5"), []byte("50"))
|
|
||||||
checkRange(1, 4, true)
|
|
||||||
checkRange(5, 5, false)
|
|
||||||
checkRange(6, 9, true)
|
|
||||||
deleteRange([]byte(""), []byte("a"))
|
|
||||||
checkRange(1, 9, false)
|
|
||||||
|
|
||||||
addRange(1, 999)
|
|
||||||
deleteRange([]byte("12345"), []byte("54321"))
|
|
||||||
checkRange(1, 1, true)
|
|
||||||
checkRange(2, 5, false)
|
|
||||||
checkRange(6, 12, true)
|
|
||||||
checkRange(13, 54, false)
|
|
||||||
checkRange(55, 123, true)
|
|
||||||
checkRange(124, 543, false)
|
|
||||||
checkRange(544, 999, true)
|
|
||||||
|
|
||||||
addRange(1, 999)
|
|
||||||
deleteRange([]byte("3"), []byte("7"))
|
|
||||||
checkRange(1, 2, true)
|
|
||||||
checkRange(3, 6, false)
|
|
||||||
checkRange(7, 29, true)
|
|
||||||
checkRange(30, 69, false)
|
|
||||||
checkRange(70, 299, true)
|
|
||||||
checkRange(300, 699, false)
|
|
||||||
checkRange(700, 999, true)
|
|
||||||
|
|
||||||
deleteRange([]byte(""), []byte("a"))
|
|
||||||
checkRange(1, 999, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test(false, false)
|
checkRange := func(start, stop int, exp bool) {
|
||||||
test(false, true)
|
for i := start; i <= stop; i++ {
|
||||||
test(true, true)
|
has, _ := db.Has([]byte(strconv.Itoa(i)))
|
||||||
|
if has && !exp {
|
||||||
|
t.Fatalf("unexpected key %d", i)
|
||||||
|
}
|
||||||
|
if !has && exp {
|
||||||
|
t.Fatalf("missing expected key %d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addRange(1, 9)
|
||||||
|
db.DeleteRange([]byte("9"), []byte("1"))
|
||||||
|
checkRange(1, 9, true)
|
||||||
|
db.DeleteRange([]byte("5"), []byte("5"))
|
||||||
|
checkRange(1, 9, true)
|
||||||
|
db.DeleteRange([]byte("5"), []byte("50"))
|
||||||
|
checkRange(1, 4, true)
|
||||||
|
checkRange(5, 5, false)
|
||||||
|
checkRange(6, 9, true)
|
||||||
|
db.DeleteRange([]byte(""), []byte("a"))
|
||||||
|
checkRange(1, 9, false)
|
||||||
|
|
||||||
|
addRange(1, 999)
|
||||||
|
db.DeleteRange([]byte("12345"), []byte("54321"))
|
||||||
|
checkRange(1, 1, true)
|
||||||
|
checkRange(2, 5, false)
|
||||||
|
checkRange(6, 12, true)
|
||||||
|
checkRange(13, 54, false)
|
||||||
|
checkRange(55, 123, true)
|
||||||
|
checkRange(124, 543, false)
|
||||||
|
checkRange(544, 999, true)
|
||||||
|
|
||||||
|
addRange(1, 999)
|
||||||
|
db.DeleteRange([]byte("3"), []byte("7"))
|
||||||
|
checkRange(1, 2, true)
|
||||||
|
checkRange(3, 6, false)
|
||||||
|
checkRange(7, 29, true)
|
||||||
|
checkRange(30, 69, false)
|
||||||
|
checkRange(70, 299, true)
|
||||||
|
checkRange(300, 699, false)
|
||||||
|
checkRange(700, 999, true)
|
||||||
|
|
||||||
|
db.DeleteRange([]byte(""), []byte("a"))
|
||||||
|
checkRange(1, 999, false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,46 +32,21 @@ var ErrTooManyKeys = errors.New("too many keys in deleted range")
|
||||||
// finally succeeds.
|
// finally succeeds.
|
||||||
func DeleteRangeWithIterator(db KeyValueStore, start, end []byte) error {
|
func DeleteRangeWithIterator(db KeyValueStore, start, end []byte) error {
|
||||||
batch := db.NewBatch()
|
batch := db.NewBatch()
|
||||||
if err := deleteRangeWithIterator(batch, db, start, end); err != nil {
|
it := db.NewIterator(nil, start)
|
||||||
return err
|
defer it.Release()
|
||||||
}
|
|
||||||
return batch.Write()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRangeFromBatch is a fallback method for deleting a key range in a batch
|
|
||||||
// from a database that does not natively support range deletion.
|
|
||||||
func DeleteRangeFromBatch(target Batch, source Iteratee, start, end []byte) error {
|
|
||||||
deleteRangeWithIterator(target, source, start, end)
|
|
||||||
var keys [][]byte
|
|
||||||
writer := HookedBatch{
|
|
||||||
Batch: target,
|
|
||||||
OnPut: func(key []byte, value []byte) {
|
|
||||||
if bytes.Compare(start, key) <= 0 && bytes.Compare(end, key) > 0 {
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
target.Replay(writer)
|
|
||||||
for _, key := range keys {
|
|
||||||
if err := target.Delete(key); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteRangeWithIterator(target KeyValueWriter, source Iteratee, start, end []byte) error {
|
|
||||||
it := source.NewIterator(nil, start)
|
|
||||||
var count int
|
var count int
|
||||||
for it.Next() && bytes.Compare(end, it.Key()) > 0 {
|
for it.Next() && bytes.Compare(end, it.Key()) > 0 {
|
||||||
count++
|
count++
|
||||||
if count > 10000 { // should not block for more than a second
|
if count > 10000 { // should not block for more than a second
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return ErrTooManyKeys
|
return ErrTooManyKeys
|
||||||
}
|
}
|
||||||
if err := target.Delete(it.Key()); err != nil {
|
if err := batch.Delete(it.Key()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it.Release()
|
return batch.Write()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,8 @@ func (db *Database) Delete(key []byte) error {
|
||||||
return db.db.Delete(key, nil)
|
return db.db.Delete(key, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange removes all keys in the range [start,end) from the key-value store.
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
|
// (inclusive on start, exclusive on end).
|
||||||
func (db *Database) DeleteRange(start, end []byte) error {
|
func (db *Database) DeleteRange(start, end []byte) error {
|
||||||
return ethdb.DeleteRangeWithIterator(db, start, end)
|
return ethdb.DeleteRangeWithIterator(db, start, end)
|
||||||
}
|
}
|
||||||
|
|
@ -440,10 +441,9 @@ func (b *batch) Delete(key []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange inserts the removal all of the keys in the range [start,end) into
|
// DeleteRange implements KeyValueWriter (not supported on batches).
|
||||||
// the batch for later committing.
|
|
||||||
func (b *batch) DeleteRange(start, end []byte) error {
|
func (b *batch) DeleteRange(start, end []byte) error {
|
||||||
return ethdb.DeleteRangeFromBatch(b, b.wrappedDb, start, end)
|
panic("DeleteRange is not supported on batches")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,8 @@ func (db *Database) Delete(key []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange removes all keys in the range [start,end) from the key-value store.
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
|
// (inclusive on start, exclusive on end).
|
||||||
func (db *Database) DeleteRange(start, end []byte) error {
|
func (db *Database) DeleteRange(start, end []byte) error {
|
||||||
return ethdb.DeleteRangeWithIterator(db, start, end)
|
return ethdb.DeleteRangeWithIterator(db, start, end)
|
||||||
}
|
}
|
||||||
|
|
@ -228,10 +229,9 @@ func (b *batch) Delete(key []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange inserts the removal all of the keys in the range [start,end) into
|
// DeleteRange implements KeyValueWriter (not supported on batches).
|
||||||
// the batch for later committing.
|
|
||||||
func (b *batch) DeleteRange(start, end []byte) error {
|
func (b *batch) DeleteRange(start, end []byte) error {
|
||||||
return ethdb.DeleteRangeFromBatch(b, b.db, start, end)
|
panic("DeleteRange is not supported on batches")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,8 @@ func (d *Database) Delete(key []byte) error {
|
||||||
return d.db.Delete(key, nil)
|
return d.db.Delete(key, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange removes all keys in the range [start,end) from the key-value store.
|
// DeleteRange deletes all of the keys (and values) in the range [start,end)
|
||||||
|
// (inclusive on start, exclusive on end).
|
||||||
func (d *Database) DeleteRange(start, end []byte) error {
|
func (d *Database) DeleteRange(start, end []byte) error {
|
||||||
d.quitLock.RLock()
|
d.quitLock.RLock()
|
||||||
defer d.quitLock.RUnlock()
|
defer d.quitLock.RUnlock()
|
||||||
|
|
@ -549,14 +550,9 @@ func (b *batch) Delete(key []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRange inserts the removal all of the keys in the range [start,end) into
|
// DeleteRange implements KeyValueWriter (not supported on batches).
|
||||||
// the batch for later committing.
|
|
||||||
func (b *batch) DeleteRange(start, end []byte) error {
|
func (b *batch) DeleteRange(start, end []byte) error {
|
||||||
if err := b.b.DeleteRange(start, end, nil); err != nil {
|
panic("DeleteRange is not supported on batches")
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.size += len(start) + len(end)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueSize retrieves the amount of data queued up for writing.
|
// ValueSize retrieves the amount of data queued up for writing.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue