mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-04 05:58:40 +00:00
triedb, core: polish code
This commit is contained in:
parent
e67fa13e34
commit
133ee263c8
7 changed files with 60 additions and 74 deletions
|
|
@ -90,16 +90,17 @@ const (
|
||||||
stateHistoryStorageData = "storage.data"
|
stateHistoryStorageData = "storage.data"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StateHistoryTailGroup is the tail group shared by all state history tables.
|
// DefaultHistoryGroup is the tail group shared by all state/trienode history
|
||||||
const StateHistoryTailGroup = "history"
|
// tables with tail pruning enabled.
|
||||||
|
const DefaultHistoryGroup = "history"
|
||||||
|
|
||||||
// stateFreezerTableConfigs configures the settings for tables in the state freezer.
|
// stateFreezerTableConfigs configures the settings for tables in the state freezer.
|
||||||
var stateFreezerTableConfigs = map[string]freezerTableConfig{
|
var stateFreezerTableConfigs = map[string]freezerTableConfig{
|
||||||
stateHistoryMeta: {noSnappy: true, tailGroup: StateHistoryTailGroup},
|
stateHistoryMeta: {noSnappy: true, tailGroup: DefaultHistoryGroup},
|
||||||
stateHistoryAccountIndex: {noSnappy: false, tailGroup: StateHistoryTailGroup},
|
stateHistoryAccountIndex: {noSnappy: false, tailGroup: DefaultHistoryGroup},
|
||||||
stateHistoryStorageIndex: {noSnappy: false, tailGroup: StateHistoryTailGroup},
|
stateHistoryStorageIndex: {noSnappy: false, tailGroup: DefaultHistoryGroup},
|
||||||
stateHistoryAccountData: {noSnappy: false, tailGroup: StateHistoryTailGroup},
|
stateHistoryAccountData: {noSnappy: false, tailGroup: DefaultHistoryGroup},
|
||||||
stateHistoryStorageData: {noSnappy: false, tailGroup: StateHistoryTailGroup},
|
stateHistoryStorageData: {noSnappy: false, tailGroup: DefaultHistoryGroup},
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -108,18 +109,15 @@ const (
|
||||||
trienodeHistoryValueSectionTable = "trienode.value"
|
trienodeHistoryValueSectionTable = "trienode.value"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TrienodeHistoryTailGroup is the tail group shared by all trienode history tables.
|
|
||||||
const TrienodeHistoryTailGroup = "history"
|
|
||||||
|
|
||||||
// trienodeFreezerTableConfigs configures the settings for tables in the trienode freezer.
|
// trienodeFreezerTableConfigs configures the settings for tables in the trienode freezer.
|
||||||
var trienodeFreezerTableConfigs = map[string]freezerTableConfig{
|
var trienodeFreezerTableConfigs = map[string]freezerTableConfig{
|
||||||
trienodeHistoryHeaderTable: {noSnappy: false, tailGroup: TrienodeHistoryTailGroup},
|
trienodeHistoryHeaderTable: {noSnappy: false, tailGroup: DefaultHistoryGroup},
|
||||||
|
|
||||||
// Disable snappy compression to allow efficient partial read.
|
// Disable snappy compression to allow efficient partial read.
|
||||||
trienodeHistoryKeySectionTable: {noSnappy: true, tailGroup: TrienodeHistoryTailGroup},
|
trienodeHistoryKeySectionTable: {noSnappy: true, tailGroup: DefaultHistoryGroup},
|
||||||
|
|
||||||
// Disable snappy compression to allow efficient partial read.
|
// Disable snappy compression to allow efficient partial read.
|
||||||
trienodeHistoryValueSectionTable: {noSnappy: true, tailGroup: TrienodeHistoryTailGroup},
|
trienodeHistoryValueSectionTable: {noSnappy: true, tailGroup: DefaultHistoryGroup},
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of identifiers of ancient stores.
|
// The list of identifiers of ancient stores.
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ const freezerTableSize = 2 * 1000 * 1000 * 1000
|
||||||
// - The in-order data ensures that disk reads are always optimized.
|
// - The in-order data ensures that disk reads are always optimized.
|
||||||
type Freezer struct {
|
type Freezer struct {
|
||||||
datadir string
|
datadir string
|
||||||
head atomic.Uint64 // Number of items stored (including items removed from tail)
|
head atomic.Uint64 // Number of items stored (including items removed from tail)
|
||||||
|
tails map[string]*atomic.Uint64 // Per-group tail cache, keyed by tail group name
|
||||||
|
|
||||||
// This lock synchronizes writers and the truncate operation, as well as
|
// This lock synchronizes writers and the truncate operation, as well as
|
||||||
// the "atomic" (batched) read operations.
|
// the "atomic" (batched) read operations.
|
||||||
|
|
@ -117,6 +118,7 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
|
||||||
datadir: datadir,
|
datadir: datadir,
|
||||||
readonly: readonly,
|
readonly: readonly,
|
||||||
tables: make(map[string]*freezerTable),
|
tables: make(map[string]*freezerTable),
|
||||||
|
tails: make(map[string]*atomic.Uint64),
|
||||||
instanceLock: lock,
|
instanceLock: lock,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,32 +218,18 @@ func (f *Freezer) Ancients() (uint64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tail returns the lowest accessible item index for the given tail group.
|
// Tail returns the lowest accessible item index for the given tail group.
|
||||||
// All tables sharing this group must agree on the tail; an empty group name
|
// All tables sharing this group agree on the tail; an empty group name
|
||||||
// refers to non-prunable tables and always returns 0.
|
// refers to non-prunable tables and always returns 0. Unknown groups return
|
||||||
|
// an error.
|
||||||
func (f *Freezer) Tail(group string) (uint64, error) {
|
func (f *Freezer) Tail(group string) (uint64, error) {
|
||||||
if group == "" {
|
if group == "" {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
var (
|
tail, ok := f.tails[group]
|
||||||
tail uint64
|
if !ok {
|
||||||
found bool
|
|
||||||
)
|
|
||||||
for _, table := range f.tables {
|
|
||||||
if table.config.tailGroup != group {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
h := table.itemHidden.Load()
|
|
||||||
if !found {
|
|
||||||
tail = h
|
|
||||||
found = true
|
|
||||||
} else if h != tail {
|
|
||||||
return 0, fmt.Errorf("inconsistent tail in group %q: %d vs %d", group, h, tail)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return 0, fmt.Errorf("unknown tail group: %q", group)
|
return 0, fmt.Errorf("unknown tail group: %q", group)
|
||||||
}
|
}
|
||||||
return tail, nil
|
return tail.Load(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AncientSize returns the ancient size of the specified category.
|
// AncientSize returns the ancient size of the specified category.
|
||||||
|
|
@ -333,25 +321,14 @@ func (f *Freezer) TruncateTail(group string, tail uint64) (uint64, error) {
|
||||||
if group == "" {
|
if group == "" {
|
||||||
return 0, errors.New("empty tail group")
|
return 0, errors.New("empty tail group")
|
||||||
}
|
}
|
||||||
|
cached, ok := f.tails[group]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("unknown tail group: %q", group)
|
||||||
|
}
|
||||||
f.writeLock.Lock()
|
f.writeLock.Lock()
|
||||||
defer f.writeLock.Unlock()
|
defer f.writeLock.Unlock()
|
||||||
|
|
||||||
var (
|
prev := cached.Load()
|
||||||
prev uint64
|
|
||||||
found bool
|
|
||||||
)
|
|
||||||
for _, table := range f.tables {
|
|
||||||
if table.config.tailGroup != group {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
prev = table.itemHidden.Load()
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return 0, fmt.Errorf("unknown tail group: %q", group)
|
|
||||||
}
|
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
if table.config.tailGroup != group {
|
if table.config.tailGroup != group {
|
||||||
continue
|
continue
|
||||||
|
|
@ -360,6 +337,9 @@ func (f *Freezer) TruncateTail(group string, tail uint64) (uint64, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if tail > prev {
|
||||||
|
cached.Store(tail)
|
||||||
|
}
|
||||||
// Update the head if the requested tail exceeds the current head.
|
// Update the head if the requested tail exceeds the current head.
|
||||||
if f.head.Load() < tail {
|
if f.head.Load() < tail {
|
||||||
f.head.Store(tail)
|
f.head.Store(tail)
|
||||||
|
|
@ -388,11 +368,12 @@ func (f *Freezer) validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
head uint64
|
head uint64
|
||||||
headSet bool
|
headSet bool
|
||||||
groupTails = make(map[string]uint64)
|
tails = make(map[string]uint64)
|
||||||
)
|
)
|
||||||
for kind, table := range f.tables {
|
for kind, table := range f.tables {
|
||||||
|
// Validate the table head
|
||||||
items := table.items.Load()
|
items := table.items.Load()
|
||||||
if !headSet {
|
if !headSet {
|
||||||
head = items
|
head = items
|
||||||
|
|
@ -400,6 +381,7 @@ func (f *Freezer) validate() error {
|
||||||
} else if items != head {
|
} else if items != head {
|
||||||
return fmt.Errorf("freezer table %s has a differing head: %d != %d", kind, items, head)
|
return fmt.Errorf("freezer table %s has a differing head: %d != %d", kind, items, head)
|
||||||
}
|
}
|
||||||
|
// Validate the table tail
|
||||||
if table.config.tailGroup == "" {
|
if table.config.tailGroup == "" {
|
||||||
if table.itemHidden.Load() != 0 {
|
if table.itemHidden.Load() != 0 {
|
||||||
return fmt.Errorf("non-prunable freezer table '%s' has a non-zero tail: %d", kind, table.itemHidden.Load())
|
return fmt.Errorf("non-prunable freezer table '%s' has a non-zero tail: %d", kind, table.itemHidden.Load())
|
||||||
|
|
@ -407,15 +389,21 @@ func (f *Freezer) validate() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
hidden := table.itemHidden.Load()
|
hidden := table.itemHidden.Load()
|
||||||
if t, ok := groupTails[table.config.tailGroup]; ok {
|
if t, ok := tails[table.config.tailGroup]; ok {
|
||||||
if t != hidden {
|
if t != hidden {
|
||||||
return fmt.Errorf("freezer table %s has differing tail in group %q: %d != %d", kind, table.config.tailGroup, hidden, t)
|
return fmt.Errorf("freezer table %s has differing tail in group %q: %d != %d", kind, table.config.tailGroup, hidden, t)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
groupTails[table.config.tailGroup] = hidden
|
tails[table.config.tailGroup] = hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.head.Store(head)
|
f.head.Store(head)
|
||||||
|
|
||||||
|
for group, tail := range tails {
|
||||||
|
counter := new(atomic.Uint64)
|
||||||
|
counter.Store(tail)
|
||||||
|
f.tails[group] = counter
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,7 +451,7 @@ func (f *Freezer) repair() error {
|
||||||
}
|
}
|
||||||
// Per-group tail alignment: take the maximum tail in each group and apply
|
// Per-group tail alignment: take the maximum tail in each group and apply
|
||||||
// it to all members. Non-prunable tables must remain at tail 0.
|
// it to all members. Non-prunable tables must remain at tail 0.
|
||||||
groupTails := make(map[string]uint64)
|
tails := make(map[string]uint64)
|
||||||
for kind, table := range f.tables {
|
for kind, table := range f.tables {
|
||||||
if table.config.tailGroup == "" {
|
if table.config.tailGroup == "" {
|
||||||
if table.itemHidden.Load() != 0 {
|
if table.itemHidden.Load() != 0 {
|
||||||
|
|
@ -472,18 +460,24 @@ func (f *Freezer) repair() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
hidden := table.itemHidden.Load()
|
hidden := table.itemHidden.Load()
|
||||||
if t, ok := groupTails[table.config.tailGroup]; !ok || hidden > t {
|
if t, ok := tails[table.config.tailGroup]; !ok || hidden > t {
|
||||||
groupTails[table.config.tailGroup] = hidden
|
tails[table.config.tailGroup] = hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
if table.config.tailGroup == "" {
|
if table.config.tailGroup == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := table.truncateTail(groupTails[table.config.tailGroup]); err != nil {
|
if err := table.truncateTail(tails[table.config.tailGroup]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.head.Store(head)
|
f.head.Store(head)
|
||||||
|
|
||||||
|
for group, tail := range tails {
|
||||||
|
counter := new(atomic.Uint64)
|
||||||
|
counter.Store(tail)
|
||||||
|
f.tails[group] = counter
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ func (dl *diskLayer) writeHistory(typ historyType, diff *diffLayer) (bool, error
|
||||||
if limit == 0 {
|
if limit == 0 {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
tail, err := freezer.Tail(rawdb.StateHistoryTailGroup)
|
tail, err := freezer.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} // firstID = tail+1
|
} // firstID = tail+1
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ func truncateFromHead(store ethdb.AncientStore, typ historyType, nhead uint64) (
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
otail, err := store.Tail(rawdb.StateHistoryTailGroup)
|
otail, err := store.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -303,13 +303,7 @@ func truncateFromTail(store ethdb.AncientStore, typ historyType, ntail uint64) (
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
var group string
|
otail, err := store.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if typ == typeStateHistory {
|
|
||||||
group = rawdb.StateHistoryTailGroup
|
|
||||||
} else {
|
|
||||||
group = rawdb.TrienodeHistoryTailGroup
|
|
||||||
}
|
|
||||||
otail, err := store.Tail(group)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -321,7 +315,7 @@ func truncateFromTail(store ethdb.AncientStore, typ historyType, ntail uint64) (
|
||||||
if otail == ntail {
|
if otail == ntail {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
otail, err = store.TruncateTail(group, ntail)
|
otail, err = store.TruncateTail(rawdb.DefaultHistoryGroup, ntail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -436,7 +430,7 @@ func repairHistory(db ethdb.Database, isUBT bool, readOnly bool, stateID uint64,
|
||||||
truncTo = min(truncTo, thead)
|
truncTo = min(truncTo, thead)
|
||||||
} else {
|
} else {
|
||||||
if thead == 0 {
|
if thead == 0 {
|
||||||
_, err = trienodes.TruncateTail(rawdb.TrienodeHistoryTailGroup, stateID)
|
_, err = trienodes.TruncateTail(rawdb.DefaultHistoryGroup, stateID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -542,7 +542,7 @@ func (i *indexIniter) run(recover bool) {
|
||||||
|
|
||||||
// next returns the ID of the next state history to be indexed.
|
// next returns the ID of the next state history to be indexed.
|
||||||
func (i *indexIniter) next() (uint64, error) {
|
func (i *indexIniter) next() (uint64, error) {
|
||||||
tail, err := i.freezer.Tail(rawdb.StateHistoryTailGroup)
|
tail, err := i.freezer.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ type HistoryStats struct {
|
||||||
// sanitizeRange limits the given range to fit within the local history store.
|
// sanitizeRange limits the given range to fit within the local history store.
|
||||||
func sanitizeRange(start, end uint64, freezer ethdb.AncientReader) (uint64, uint64, error) {
|
func sanitizeRange(start, end uint64, freezer ethdb.AncientReader) (uint64, uint64, error) {
|
||||||
// Load the id of the first history object in local store.
|
// Load the id of the first history object in local store.
|
||||||
tail, err := freezer.Tail(rawdb.StateHistoryTailGroup)
|
tail, err := freezer.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -133,7 +133,7 @@ func storageHistory(freezer ethdb.AncientReader, address common.Address, slot co
|
||||||
// historyRange returns the block number range of local state histories.
|
// historyRange returns the block number range of local state histories.
|
||||||
func historyRange(freezer ethdb.AncientReader) (uint64, uint64, error) {
|
func historyRange(freezer ethdb.AncientReader) (uint64, uint64, error) {
|
||||||
// Load the id of the first history object in local store.
|
// Load the id of the first history object in local store.
|
||||||
tail, err := freezer.Tail(rawdb.StateHistoryTailGroup)
|
tail, err := freezer.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -470,7 +470,7 @@ func checkStateAvail(state stateIdent, exptyp historyType, freezer ethdb.Ancient
|
||||||
return 0, fmt.Errorf("unsupported history type: %d, want: %v", toHistoryType(state.typ), exptyp)
|
return 0, fmt.Errorf("unsupported history type: %d, want: %v", toHistoryType(state.typ), exptyp)
|
||||||
}
|
}
|
||||||
// firstID = tail+1
|
// firstID = tail+1
|
||||||
tail, err := freezer.Tail(rawdb.StateHistoryTailGroup)
|
tail, err := freezer.Tail(rawdb.DefaultHistoryGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue