From b22bb9869c1544292539e88bdc8dbbba1cbb72ad Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 12 Mar 2025 17:50:55 +0100 Subject: [PATCH] core/rawdb: don't check different lenghts in freezer --- core/rawdb/freezer.go | 115 +++++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index c5a72eff7e..984352f922 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -336,33 +336,68 @@ func (f *Freezer) Sync() error { return nil } +// splitTables splits tables in header and non-header tables +func splitTables(tables map[string]*freezerTable) (map[string]*freezerTable, map[string]*freezerTable) { + var ( + headTables = make(map[string]*freezerTable) + otherTables = make(map[string]*freezerTable) + ) + for kind, table := range tables { + if kind == ChainFreezerHeaderTable || kind == ChainFreezerHashTable { + headTables[kind] = table + } else { + otherTables[kind] = table + } + } + return headTables, otherTables +} + // validate checks that every table has the same boundary. // Used instead of `repair` in readonly mode. func (f *Freezer) validate() error { if len(f.tables) == 0 { return nil } - var ( - head uint64 - tail uint64 - name string - ) - // Hack to get boundary of any table - for kind, table := range f.tables { - head = table.items.Load() - tail = table.itemHidden.Load() - name = kind - break - } - // Now check every table against those boundaries. - for kind, table := range f.tables { - if head != table.items.Load() { - return fmt.Errorf("freezer tables %s and %s have differing head: %d != %d", kind, name, table.items.Load(), head) + + check := func(tables map[string]*freezerTable) (uint64, uint64, error) { + var ( + head uint64 + tail uint64 + name string + ) + // Hack to get boundary of any table + for kind, table := range tables { + head = table.items.Load() + tail = table.itemHidden.Load() + name = kind + break } - if tail != table.itemHidden.Load() { - return fmt.Errorf("freezer tables %s and %s have differing tail: %d != %d", kind, name, table.itemHidden.Load(), tail) + // Now check every table against those boundaries. + for kind, table := range tables { + if head != table.items.Load() { + return 0, 0, fmt.Errorf("freezer tables %s and %s have differing head: %d != %d", kind, name, table.items.Load(), head) + } + if tail != table.itemHidden.Load() { + return 0, 0, fmt.Errorf("freezer tables %s and %s have differing tail: %d != %d", kind, name, table.itemHidden.Load(), tail) + } + } + return head, tail, nil + } + + headTables, otherTables := splitTables(f.tables) + // verify that all the non-header tables have the same size + head, tail, err := check(otherTables) + if err != nil { + return err + } + // verify that the header tables have the same size + if len(headTables) != 0 { + head, tail, err = check(headTables) + if err != nil { + return err } } + f.frozen.Store(head) f.tail.Store(tail) return nil @@ -370,28 +405,40 @@ func (f *Freezer) validate() error { // repair truncates all data tables to the same length. func (f *Freezer) repair() error { - var ( - head = uint64(math.MaxUint64) - tail = uint64(0) - ) - for _, table := range f.tables { - items := table.items.Load() - if head > items { - head = items + repair := func(tables map[string]*freezerTable) (uint64, uint64, error) { + var ( + head = uint64(math.MaxUint64) + tail = uint64(0) + ) + for _, table := range tables { + head = min(head, table.items.Load()) + tail = max(tail, table.itemHidden.Load()) } - hidden := table.itemHidden.Load() - if hidden > tail { - tail = hidden + for _, table := range tables { + if err := table.truncateHead(head); err != nil { + return 0, 0, err + } + if err := table.truncateTail(tail); err != nil { + return 0, 0, err + } } + return head, tail, nil } - for _, table := range f.tables { - if err := table.truncateHead(head); err != nil { - return err - } - if err := table.truncateTail(tail); err != nil { + + headTables, otherTables := splitTables(f.tables) + // verify that all the non-header tables have the same size + head, tail, err := repair(otherTables) + if err != nil { + return err + } + // verify that the header tables have the same size + if len(headTables) != 0 { + head, tail, err = repair(headTables) + if err != nil { return err } } + f.frozen.Store(head) f.tail.Store(tail) return nil