Skip to content

Commit 3853f50

Browse files
authored
trie/triedb/pathdb, core/rawdb: enhance error message in freezer (#28198)
This PR adds more error message for debugging purpose.
1 parent 062598b commit 3853f50

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed

core/rawdb/freezer_resettable.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"sync"
2323

2424
"github.com/ethereum/go-ethereum/ethdb"
25+
"github.com/ethereum/go-ethereum/log"
2526
)
2627

2728
const tmpSuffix = ".tmp"
@@ -224,6 +225,7 @@ func cleanup(path string) error {
224225
}
225226
for _, name := range names {
226227
if name == filepath.Base(path)+tmpSuffix {
228+
log.Info("Removed leftover freezer directory", "name", name)
227229
return os.RemoveAll(filepath.Join(parent, name))
228230
}
229231
}

core/rawdb/freezer_table.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,12 @@ func (t *freezerTable) repair() error {
257257
t.index.ReadAt(buffer, offsetsSize-indexEntrySize)
258258
lastIndex.unmarshalBinary(buffer)
259259
}
260+
// Print an error log if the index is corrupted due to an incorrect
261+
// last index item. While it is theoretically possible to have a zero offset
262+
// by storing all zero-size items, it is highly unlikely to occur in practice.
263+
if lastIndex.offset == 0 && offsetsSize%indexEntrySize > 1 {
264+
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "items", offsetsSize%indexEntrySize-1)
265+
}
260266
if t.readonly {
261267
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
262268
} else {
@@ -349,7 +355,7 @@ func (t *freezerTable) repair() error {
349355
return err
350356
}
351357
if verbose {
352-
t.logger.Info("Chain freezer table opened", "items", t.items.Load(), "size", t.headBytes)
358+
t.logger.Info("Chain freezer table opened", "items", t.items.Load(), "deleted", t.itemOffset.Load(), "hidden", t.itemHidden.Load(), "tailId", t.tailId, "headId", t.headId, "size", t.headBytes)
353359
} else {
354360
t.logger.Debug("Chain freezer table opened", "items", t.items.Load(), "size", common.StorageSize(t.headBytes))
355361
}
@@ -522,6 +528,10 @@ func (t *freezerTable) truncateTail(items uint64) error {
522528
if err := t.meta.Sync(); err != nil {
523529
return err
524530
}
531+
// Close the index file before shorten it.
532+
if err := t.index.Close(); err != nil {
533+
return err
534+
}
525535
// Truncate the deleted index entries from the index file.
526536
err = copyFrom(t.index.Name(), t.index.Name(), indexEntrySize*(newDeleted-deleted+1), func(f *os.File) error {
527537
tailIndex := indexEntry{
@@ -535,13 +545,14 @@ func (t *freezerTable) truncateTail(items uint64) error {
535545
return err
536546
}
537547
// Reopen the modified index file to load the changes
538-
if err := t.index.Close(); err != nil {
539-
return err
540-
}
541548
t.index, err = openFreezerFileForAppend(t.index.Name())
542549
if err != nil {
543550
return err
544551
}
552+
// Sync the file to ensure changes are flushed to disk
553+
if err := t.index.Sync(); err != nil {
554+
return err
555+
}
545556
// Release any files before the current tail
546557
t.tailId = newTailId
547558
t.itemOffset.Store(newDeleted)
@@ -774,7 +785,7 @@ func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []i
774785
return fmt.Errorf("missing data file %d", fileId)
775786
}
776787
if _, err := dataFile.ReadAt(output[len(output)-length:], int64(start)); err != nil {
777-
return err
788+
return fmt.Errorf("%w, fileid: %d, start: %d, length: %d", err, fileId, start, length)
778789
}
779790
return nil
780791
}

trie/triedb/pathdb/history.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,16 @@ func truncateFromHead(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, nhead
581581
if err != nil {
582582
return 0, err
583583
}
584-
if ohead <= nhead {
584+
otail, err := freezer.Tail()
585+
if err != nil {
586+
return 0, err
587+
}
588+
// Ensure that the truncation target falls within the specified range.
589+
if ohead < nhead || nhead < otail {
590+
return 0, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", otail, ohead, nhead)
591+
}
592+
// Short circuit if nothing to truncate.
593+
if ohead == nhead {
585594
return 0, nil
586595
}
587596
// Load the meta objects in range [nhead+1, ohead]
@@ -610,11 +619,20 @@ func truncateFromHead(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, nhead
610619
// truncateFromTail removes the extra state histories from the tail with the given
611620
// parameters. It returns the number of items removed from the tail.
612621
func truncateFromTail(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, ntail uint64) (int, error) {
622+
ohead, err := freezer.Ancients()
623+
if err != nil {
624+
return 0, err
625+
}
613626
otail, err := freezer.Tail()
614627
if err != nil {
615628
return 0, err
616629
}
617-
if otail >= ntail {
630+
// Ensure that the truncation target falls within the specified range.
631+
if otail > ntail || ntail > ohead {
632+
return 0, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", otail, ohead, ntail)
633+
}
634+
// Short circuit if nothing to truncate.
635+
if otail == ntail {
618636
return 0, nil
619637
}
620638
// Load the meta objects in range [otail+1, ntail]

trie/triedb/pathdb/history_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,50 @@ func TestTruncateTailHistories(t *testing.T) {
224224
}
225225
}
226226

227+
func TestTruncateOutOfRange(t *testing.T) {
228+
var (
229+
hs = makeHistories(10)
230+
db = rawdb.NewMemoryDatabase()
231+
freezer, _ = openFreezer(t.TempDir(), false)
232+
)
233+
defer freezer.Close()
234+
235+
for i := 0; i < len(hs); i++ {
236+
accountData, storageData, accountIndex, storageIndex := hs[i].encode()
237+
rawdb.WriteStateHistory(freezer, uint64(i+1), hs[i].meta.encode(), accountIndex, storageIndex, accountData, storageData)
238+
rawdb.WriteStateID(db, hs[i].meta.root, uint64(i+1))
239+
}
240+
truncateFromTail(db, freezer, uint64(len(hs)/2))
241+
242+
// Ensure of-out-range truncations are rejected correctly.
243+
head, _ := freezer.Ancients()
244+
tail, _ := freezer.Tail()
245+
246+
cases := []struct {
247+
mode int
248+
target uint64
249+
expErr error
250+
}{
251+
{0, head, nil}, // nothing to delete
252+
{0, head + 1, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", tail, head, head+1)},
253+
{0, tail - 1, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", tail, head, tail-1)},
254+
{1, tail, nil}, // nothing to delete
255+
{1, head + 1, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", tail, head, head+1)},
256+
{1, tail - 1, fmt.Errorf("out of range, tail: %d, head: %d, target: %d", tail, head, tail-1)},
257+
}
258+
for _, c := range cases {
259+
var gotErr error
260+
if c.mode == 0 {
261+
_, gotErr = truncateFromHead(db, freezer, c.target)
262+
} else {
263+
_, gotErr = truncateFromTail(db, freezer, c.target)
264+
}
265+
if !reflect.DeepEqual(gotErr, c.expErr) {
266+
t.Errorf("Unexpected error, want: %v, got: %v", c.expErr, gotErr)
267+
}
268+
}
269+
}
270+
227271
// openFreezer initializes the freezer instance for storing state histories.
228272
func openFreezer(datadir string, readOnly bool) (*rawdb.ResettableFreezer, error) {
229273
return rawdb.NewStateFreezer(datadir, readOnly)

0 commit comments

Comments
 (0)