1717package core
1818
1919import (
20- "errors"
2120 "fmt"
21+ "sync/atomic"
2222
2323 "github.com/CortexFoundation/CortexTheseus/common"
2424 "github.com/CortexFoundation/CortexTheseus/core/rawdb"
@@ -46,27 +46,38 @@ type txIndexer struct {
4646 // * N: means the latest N blocks [HEAD-N+1, HEAD] should be indexed
4747 // and all others shouldn't.
4848 limit uint64
49+ // The current head of blockchain for transaction indexing. This field
50+ // is accessed by both the indexer and the indexing progress queries.
51+ head atomic.Uint64
52+
53+ // The current tail of the indexed transactions, null indicates
54+ // that no transactions have been indexed yet.
55+ //
56+ // This field is accessed by both the indexer and the indexing
57+ // progress queries.
58+ tail atomic.Pointer [uint64 ]
4959
5060 // cutoff denotes the block number before which the chain segment should
5161 // be pruned and not available locally.
52- cutoff uint64
53- db ctxcdb.Database
54- progress chan chan TxIndexProgress
55- term chan chan struct {}
56- closed chan struct {}
62+ cutoff uint64
63+ db ctxcdb.Database
64+ term chan chan struct {}
65+ closed chan struct {}
5766}
5867
5968// newTxIndexer initializes the transaction indexer.
6069func newTxIndexer (limit uint64 , chain * BlockChain ) * txIndexer {
6170 cutoff , _ := chain .HistoryPruningCutoff ()
6271 indexer := & txIndexer {
63- limit : limit ,
64- cutoff : cutoff ,
65- db : chain .db ,
66- progress : make (chan chan TxIndexProgress ),
67- term : make (chan chan struct {}),
68- closed : make (chan struct {}),
72+ limit : limit ,
73+ cutoff : cutoff ,
74+ db : chain .db ,
75+ term : make (chan chan struct {}),
76+ closed : make (chan struct {}),
6977 }
78+ indexer .head .Store (indexer .resolveHead ())
79+ indexer .tail .Store (rawdb .ReadTxIndexTail (chain .db ))
80+
7081 go indexer .loop (chain )
7182
7283 var msg string
@@ -154,6 +165,7 @@ func (indexer *txIndexer) repair(head uint64) {
154165 // A crash may occur between the two delete operations,
155166 // potentially leaving dangling indexes in the database.
156167 // However, this is considered acceptable.
168+ indexer .tail .Store (nil )
157169 rawdb .DeleteTxIndexTail (indexer .db )
158170 rawdb .DeleteAllTxLookupEntries (indexer .db , nil )
159171 log .Warn ("Purge transaction indexes" , "head" , head , "tail" , * tail )
@@ -174,6 +186,7 @@ func (indexer *txIndexer) repair(head uint64) {
174186 // Traversing the database directly within the transaction
175187 // index namespace might be slow and expensive, but we
176188 // have no choice.
189+ indexer .tail .Store (nil )
177190 rawdb .DeleteTxIndexTail (indexer .db )
178191 rawdb .DeleteAllTxLookupEntries (indexer .db , nil )
179192 log .Warn ("Purge transaction indexes" , "head" , head , "cutoff" , indexer .cutoff )
@@ -187,6 +200,7 @@ func (indexer *txIndexer) repair(head uint64) {
187200 // A crash may occur between the two delete operations,
188201 // potentially leaving dangling indexes in the database.
189202 // However, this is considered acceptable.
203+ indexer .tail .Store (& indexer .cutoff )
190204 rawdb .WriteTxIndexTail (indexer .db , indexer .cutoff )
191205 rawdb .DeleteAllTxLookupEntries (indexer .db , func (txhash common.Hash , blob []byte ) bool {
192206 n := rawdb .DecodeTxLookupEntry (blob , indexer .db )
@@ -216,16 +230,16 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
216230
217231 // Listening to chain events and manipulate the transaction indexes.
218232 var (
219- stop chan struct {} // Non-nil if background routine is active
220- done chan struct {} // Non-nil if background routine is active
221- head = indexer .resolveHead () // The latest announced chain head
233+ stop chan struct {} // Non-nil if background routine is active
234+ done chan struct {} // Non-nil if background routine is active
222235
223236 headCh = make (chan ChainHeadEvent )
224237 sub = chain .SubscribeChainHeadEvent (headCh )
225238 )
226239 defer sub .Unsubscribe ()
227240
228241 // Validate the transaction indexes and repair if necessary
242+ head := indexer .head .Load ()
229243 indexer .repair (head )
230244
231245 // Launch the initial processing if chain is not empty (head != genesis).
@@ -238,17 +252,16 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
238252 for {
239253 select {
240254 case h := <- headCh :
255+ indexer .head .Store (h .Header .Number .Uint64 ())
241256 if done == nil {
242257 stop = make (chan struct {})
243258 done = make (chan struct {})
244259 go indexer .run (h .Header .Number .Uint64 (), stop , done )
245260 }
246- head = h .Header .Number .Uint64 ()
247261 case <- done :
248262 stop = nil
249263 done = nil
250- case ch := <- indexer .progress :
251- ch <- indexer .report (head )
264+ indexer .tail .Store (rawdb .ReadTxIndexTail (indexer .db ))
252265 case ch := <- indexer .term :
253266 if stop != nil {
254267 close (stop )
@@ -264,7 +277,7 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
264277}
265278
266279// report returns the tx indexing progress.
267- func (indexer * txIndexer ) report (head uint64 ) TxIndexProgress {
280+ func (indexer * txIndexer ) report (head uint64 , tail * uint64 ) TxIndexProgress {
268281 // Special case if the head is even below the cutoff,
269282 // nothing to index.
270283 if head < indexer .cutoff {
@@ -284,7 +297,6 @@ func (indexer *txIndexer) report(head uint64) TxIndexProgress {
284297 }
285298 // Compute how many blocks have been indexed
286299 var indexed uint64
287- tail := rawdb .ReadTxIndexTail (indexer .db )
288300 if tail != nil {
289301 indexed = head - * tail + 1
290302 }
@@ -302,14 +314,8 @@ func (indexer *txIndexer) report(head uint64) TxIndexProgress {
302314
303315// txIndexProgress retrieves the tx indexing progress, or an error if the
304316// background tx indexer is already stopped.
305- func (indexer * txIndexer ) txIndexProgress () (TxIndexProgress , error ) {
306- ch := make (chan TxIndexProgress , 1 )
307- select {
308- case indexer .progress <- ch :
309- return <- ch , nil
310- case <- indexer .closed :
311- return TxIndexProgress {}, errors .New ("indexer is closed" )
312- }
317+ func (indexer * txIndexer ) txIndexProgress () TxIndexProgress {
318+ return indexer .report (indexer .head .Load (), indexer .tail .Load ())
313319}
314320
315321// close shutdown the indexer. Safe to be called for multiple times.
0 commit comments