1717package rawdb
1818
1919import (
20+ "errors"
2021 "fmt"
2122 "sync"
22- "sync/atomic"
2323 "time"
2424
2525 "github.com/ethereum/go-ethereum/common"
2626 "github.com/ethereum/go-ethereum/ethdb"
2727 "github.com/ethereum/go-ethereum/log"
28- "github.com/ethereum/go-ethereum/params"
2928)
3029
3130const (
@@ -43,8 +42,6 @@ const (
4342// The background thread will keep moving ancient chain segments from key-value
4443// database to flat files for saving space on live database.
4544type chainFreezer struct {
46- threshold atomic.Uint64 // Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests)
47-
4845 * Freezer
4946 quit chan struct {}
5047 wg sync.WaitGroup
@@ -57,13 +54,11 @@ func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFre
5754 if err != nil {
5855 return nil , err
5956 }
60- cf := chainFreezer {
57+ return & chainFreezer {
6158 Freezer : freezer ,
6259 quit : make (chan struct {}),
6360 trigger : make (chan chan struct {}),
64- }
65- cf .threshold .Store (params .FullImmutabilityThreshold )
66- return & cf , nil
61+ }, nil
6762}
6863
6964// Close closes the chain freezer instance and terminates the background thread.
@@ -77,6 +72,19 @@ func (f *chainFreezer) Close() error {
7772 return f .Freezer .Close ()
7873}
7974
75+ // readFinalized loads the finalized block from database.
76+ func (f * chainFreezer ) readFinalized (db ethdb.KeyValueReader ) (uint64 , common.Hash , error ) {
77+ hash := ReadFinalizedBlockHash (db )
78+ if hash == (common.Hash {}) {
79+ return 0 , common.Hash {}, errors .New ("finalized block is not available" )
80+ }
81+ number := ReadHeaderNumber (db , hash )
82+ if number == nil {
83+ return 0 , common.Hash {}, errors .New ("finalized block number is not available" )
84+ }
85+ return * number , hash , nil
86+ }
87+
8088// freeze is a background thread that periodically checks the blockchain for any
8189// import progress and moves ancient data from the fast database into the freezer.
8290//
@@ -114,60 +122,39 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
114122 return
115123 }
116124 }
117- // Retrieve the freezing threshold.
118- hash := ReadHeadBlockHash (nfdb )
119- if hash == (common.Hash {}) {
120- log .Debug ("Current full block hash unavailable" ) // new chain, empty database
121- backoff = true
125+ finalNumber , finalHash , err := f .readFinalized (nfdb )
126+ if err != nil {
127+ backoff = true // chain is not finalized yet
128+ log .Debug ("Finalized block is not available yet" )
122129 continue
123130 }
124- number := ReadHeaderNumber (nfdb , hash )
125- threshold := f .threshold .Load ()
126131 frozen := f .frozen .Load ()
127- switch {
128- case number == nil :
129- log .Error ("Current full block number unavailable" , "hash" , hash )
130- backoff = true
131- continue
132132
133- case * number < threshold :
134- log .Debug ("Current full block not old enough to freeze" , "number" , * number , "hash" , hash , "delay" , threshold )
135- backoff = true
136- continue
137-
138- case * number - threshold <= frozen :
139- log .Debug ("Ancient blocks frozen already" , "number" , * number , "hash" , hash , "frozen" , frozen )
140- backoff = true
141- continue
142- }
143- head := ReadHeader (nfdb , hash , * number )
144- if head == nil {
145- log .Error ("Current full block unavailable" , "number" , * number , "hash" , hash )
133+ // Short circuit if finalized blocks are already frozen.
134+ if frozen != 0 && frozen - 1 >= finalNumber {
146135 backoff = true
136+ log .Debug ("Ancient blocks frozen already" , "number" , finalNumber , "hash" , finalHash , "frozen" , frozen )
147137 continue
148138 }
149-
150139 // Seems we have data ready to be frozen, process in usable batches
151140 var (
152- start = time .Now ()
153- first , _ = f . Ancients ()
154- limit = * number - threshold
141+ start = time .Now ()
142+ first = frozen
143+ limit = finalNumber
155144 )
156- if limit - first > freezerBatchLimit {
157- limit = first + freezerBatchLimit
145+ if limit - first + 1 > freezerBatchLimit {
146+ limit = freezerBatchLimit + first - 1
158147 }
159148 ancients , err := f .freezeRange (nfdb , first , limit )
160149 if err != nil {
161150 log .Error ("Error in block freeze operation" , "err" , err )
162151 backoff = true
163152 continue
164153 }
165-
166154 // Batch of blocks have been frozen, flush them before wiping from leveldb
167155 if err := f .Sync (); err != nil {
168156 log .Crit ("Failed to flush frozen tables" , "err" , err )
169157 }
170-
171158 // Wipe out all data from the active database
172159 batch := db .NewBatch ()
173160 for i := 0 ; i < len (ancients ); i ++ {
@@ -251,7 +238,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
251238}
252239
253240func (f * chainFreezer ) freezeRange (nfdb * nofreezedb , number , limit uint64 ) (hashes []common.Hash , err error ) {
254- hashes = make ([]common.Hash , 0 , limit - number )
241+ hashes = make ([]common.Hash , 0 , limit - number + 1 )
255242
256243 _ , err = f .ModifyAncients (func (op ethdb.AncientWriteOp ) error {
257244 for ; number <= limit ; number ++ {
@@ -293,11 +280,9 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
293280 if err := op .AppendRaw (ChainFreezerDifficultyTable , number , td ); err != nil {
294281 return fmt .Errorf ("can't write td to Freezer: %v" , err )
295282 }
296-
297283 hashes = append (hashes , hash )
298284 }
299285 return nil
300286 })
301-
302287 return hashes , err
303288}
0 commit comments