core/rawdb: don't check different lenghts in freezer

This commit is contained in:
Marius van der Wijden 2025-03-12 17:50:55 +01:00 committed by Felix Lange
parent f9f1172d59
commit b22bb9869c

View file

@ -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