diff --git a/core/rawdb/ancienttest/testsuite.go b/core/rawdb/ancienttest/testsuite.go index 7512c1f44b..5d8c01cc87 100644 --- a/core/rawdb/ancienttest/testsuite.go +++ b/core/rawdb/ancienttest/testsuite.go @@ -260,6 +260,24 @@ func basicWrite(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) { if err != nil { t.Fatalf("Failed to write ancient data %v", err) } + + // Write should work after truncating from tail but over the head + db.TruncateTail(200) + _, err = db.ModifyAncients(func(op ethdb.AncientWriteOp) error { + offset := uint64(200) + for i := 0; i < 100; i++ { + if err := op.AppendRaw("a", offset+uint64(i), dataA[i]); err != nil { + return err + } + if err := op.AppendRaw("b", offset+uint64(i), dataB[i]); err != nil { + return err + } + } + return nil + }) + if err != nil { + t.Fatalf("Failed to write ancient data %v", err) + } } func nonMutable(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) { diff --git a/core/rawdb/freezer_memory.go b/core/rawdb/freezer_memory.go index a0d308f896..6aed41f203 100644 --- a/core/rawdb/freezer_memory.go +++ b/core/rawdb/freezer_memory.go @@ -113,7 +113,7 @@ func (t *memoryTable) truncateTail(items uint64) error { return nil } if t.items < items { - return errors.New("truncation above head") + return t.reset(items) } for i := uint64(0); i < items-t.offset; i++ { if t.size > uint64(len(t.data[i])) { @@ -127,6 +127,16 @@ func (t *memoryTable) truncateTail(items uint64) error { return nil } +// reset clears the entire table and sets both the head and tail to the given +// value. It assumes the caller holds the lock and that tail > t.items. +func (t *memoryTable) reset(offset uint64) error { + t.size = 0 + t.data = nil + t.items = offset + t.offset = offset + return nil +} + // commit merges the given item batch into table. It's presumed that the // batch is ordered and continuous with table. func (t *memoryTable) commit(batch [][]byte) error {