Skip to content

Commit 28b2490

Browse files
committed
core/rawdb: introduce flush offset in freezer
1 parent 58cf152 commit 28b2490

14 files changed

+714
-289
lines changed

core/blockchain.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -112,21 +112,28 @@ const (
112112
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
113113
// * the `Bloom` field of receipt is deleted
114114
// * the `BlockIndex` and `TxIndex` fields of txlookup are deleted
115+
//
115116
// - Version 5
116117
// The following incompatible database changes were added:
117118
// * the `TxHash`, `GasCost`, and `ContractAddress` fields are no longer stored for a receipt
118119
// * the `TxHash`, `GasCost`, and `ContractAddress` fields are computed by looking up the
119120
// receipts' corresponding block
121+
//
120122
// - Version 6
121123
// The following incompatible database changes were added:
122124
// * Transaction lookup information stores the corresponding block number instead of block hash
125+
//
123126
// - Version 7
124127
// The following incompatible database changes were added:
125128
// * Use freezer as the ancient database to maintain all ancient data
129+
//
126130
// - Version 8
127131
// The following incompatible database changes were added:
128132
// * New scheme for contract code in order to separate the codes and trie nodes
129-
BlockChainVersion uint64 = 8
133+
//
134+
// - Version 9
135+
// * The metadata structure of freezer is changed by adding 'flushOffset'
136+
BlockChainVersion uint64 = 9
130137
)
131138

132139
// CacheConfig contains the configuration values for the trie database

core/rawdb/accessors_chain_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@ func TestHeadersRLPStorage(t *testing.T) {
879879
t.Fatalf("failed to create database with ancient backend")
880880
}
881881
defer db.Close()
882+
882883
// Create blocks
883884
var chain []*types.Block
884885
var pHash common.Hash
@@ -894,7 +895,7 @@ func TestHeadersRLPStorage(t *testing.T) {
894895
chain = append(chain, block)
895896
pHash = block.Hash()
896897
}
897-
var receipts []types.Receipts = make([]types.Receipts, 100)
898+
receipts := make([]types.Receipts, 100)
898899
// Write first half to ancients
899900
WriteAncientBlocks(db, chain[:50], receipts[:50], big.NewInt(100))
900901
// Write second half to db

core/rawdb/ancient_scheme.go

+31-4
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,25 @@ var chainFreezerNoSnappy = map[string]bool{
5050
ChainFreezerDifficultyTable: true,
5151
}
5252

53-
const (
54-
// stateHistoryTableSize defines the maximum size of freezer data files.
55-
stateHistoryTableSize = 2 * 1000 * 1000 * 1000
53+
// chainFreezerSize configures the maximum size for each freezer table data files.
54+
var chainFreezerSize = map[string]uint32{
55+
// The size of each item's value is roughly 650 bytes, about 2 millions
56+
// items per data file.
57+
ChainFreezerHeaderTable: 2 * 1000 * 1000 * 1000,
58+
59+
// The size of each item’s value is fixed at 32 bytes, 2 millions items
60+
// per data file.
61+
ChainFreezerHashTable: 64 * 1000 * 1000,
62+
63+
// The size of each item’s value is less than 10 bytes, 2 millions items
64+
// per data file.
65+
ChainFreezerDifficultyTable: 20 * 1000 * 1000,
66+
67+
ChainFreezerBodiesTable: 2 * 1000 * 1000 * 1000,
68+
ChainFreezerReceiptTable: 2 * 1000 * 1000 * 1000,
69+
}
5670

71+
const (
5772
// stateHistoryAccountIndex indicates the name of the freezer state history table.
5873
stateHistoryMeta = "history.meta"
5974
stateHistoryAccountIndex = "account.index"
@@ -62,6 +77,7 @@ const (
6277
stateHistoryStorageData = "storage.data"
6378
)
6479

80+
// stateFreezerNoSnappy configures whether compression is disabled for the state freezer.
6581
var stateFreezerNoSnappy = map[string]bool{
6682
stateHistoryMeta: true,
6783
stateHistoryAccountIndex: false,
@@ -70,6 +86,17 @@ var stateFreezerNoSnappy = map[string]bool{
7086
stateHistoryStorageData: false,
7187
}
7288

89+
// stateFreezerSize configures the maximum size for each freezer table data files.
90+
var stateFreezerSize = map[string]uint32{
91+
// The size of each item's value is fixed at 73 bytes, about 2 millions
92+
// items per data file.
93+
stateHistoryMeta: 128 * 1000 * 1000,
94+
stateHistoryAccountIndex: 2 * 1000 * 1000 * 1000,
95+
stateHistoryStorageIndex: 2 * 1000 * 1000 * 1000,
96+
stateHistoryAccountData: 2 * 1000 * 1000 * 1000,
97+
stateHistoryStorageData: 2 * 1000 * 1000 * 1000,
98+
}
99+
73100
// The list of identifiers of ancient stores.
74101
var (
75102
ChainFreezerName = "chain" // the folder name of chain segment ancient store.
@@ -96,5 +123,5 @@ func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.Reset
96123
} else {
97124
name = filepath.Join(ancientDir, MerkleStateFreezerName)
98125
}
99-
return newResettableFreezer(name, "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
126+
return newResettableFreezer(name, "eth/db/state", readOnly, stateFreezerSize, stateFreezerNoSnappy)
100127
}

core/rawdb/ancient_utils.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,13 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
120120
var (
121121
path string
122122
tables map[string]bool
123+
sizes map[string]uint32
123124
)
124125
switch freezerName {
125126
case ChainFreezerName:
126-
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
127+
path, tables, sizes = resolveChainFreezerDir(ancient), chainFreezerNoSnappy, chainFreezerSize
127128
case MerkleStateFreezerName, VerkleStateFreezerName:
128-
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
129+
path, tables, sizes = filepath.Join(ancient, freezerName), stateFreezerNoSnappy, stateFreezerSize
129130
default:
130131
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
131132
}
@@ -137,7 +138,7 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
137138
}
138139
return fmt.Errorf("unknown table, supported ones: %v", names)
139140
}
140-
table, err := newFreezerTable(path, tableName, noSnappy, true)
141+
table, err := newFreezerTable(path, tableName, noSnappy, true, sizes[tableName])
141142
if err != nil {
142143
return err
143144
}

core/rawdb/chain_freezer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFre
6464
if datadir == "" {
6565
freezer = NewMemoryFreezer(readonly, chainFreezerNoSnappy)
6666
} else {
67-
freezer, err = NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
67+
freezer, err = NewFreezer(datadir, namespace, readonly, chainFreezerSize, chainFreezerNoSnappy)
6868
}
6969
if err != nil {
7070
return nil, err

core/rawdb/freezer.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ var (
4949
errSymlinkDatadir = errors.New("symbolic link datadir is not supported")
5050
)
5151

52-
// freezerTableSize defines the maximum size of freezer data files.
53-
const freezerTableSize = 2 * 1000 * 1000 * 1000
54-
5552
// Freezer is an append-only database to store immutable ordered data into
5653
// flat files:
5754
//
@@ -77,7 +74,7 @@ type Freezer struct {
7774
//
7875
// The 'tables' argument defines the data tables. If the value of a map
7976
// entry is true, snappy compression is disabled for the table.
80-
func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*Freezer, error) {
77+
func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize map[string]uint32, tables map[string]bool) (*Freezer, error) {
8178
// Create the initial freezer object
8279
var (
8380
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
@@ -116,7 +113,11 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
116113

117114
// Create the tables.
118115
for name, disableSnappy := range tables {
119-
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, maxTableSize, disableSnappy, readonly)
116+
size, exist := maxTableSize[name]
117+
if !exist {
118+
return nil, fmt.Errorf("table size for %q is not defined", name)
119+
}
120+
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, size, disableSnappy, readonly)
120121
if err != nil {
121122
for _, table := range freezer.tables {
122123
table.Close()

core/rawdb/freezer_batch.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package rawdb
1818

1919
import (
2020
"fmt"
21+
"time"
2122

2223
"github.com/ethereum/go-ethereum/common/math"
2324
"github.com/ethereum/go-ethereum/rlp"
@@ -188,9 +189,6 @@ func (batch *freezerTableBatch) commit() error {
188189
if err != nil {
189190
return err
190191
}
191-
if err := batch.t.head.Sync(); err != nil {
192-
return err
193-
}
194192
dataSize := int64(len(batch.dataBuffer))
195193
batch.dataBuffer = batch.dataBuffer[:0]
196194

@@ -208,6 +206,12 @@ func (batch *freezerTableBatch) commit() error {
208206
// Update metrics.
209207
batch.t.sizeGauge.Inc(dataSize + indexSize)
210208
batch.t.writeMeter.Mark(dataSize + indexSize)
209+
210+
// Periodically sync the table
211+
if time.Since(batch.t.lastSync) > 10*time.Second {
212+
batch.t.lastSync = time.Now()
213+
return batch.t.syncWithNoLock()
214+
}
211215
return nil
212216
}
213217

0 commit comments

Comments
 (0)