50
50
)
51
51
52
52
const (
53
- databaseVersion = 1 // reindexed if database version does not match
53
+ databaseVersion = 2 // reindexed if database version does not match
54
54
cachedLastBlocks = 1000 // last block of map pointers
55
55
cachedLvPointers = 1000 // first log value pointer of block pointers
56
56
cachedBaseRows = 100 // groups of base layer filter row data
@@ -244,6 +244,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
244
244
disabledCh : make (chan struct {}),
245
245
exportFileName : config .ExportFileName ,
246
246
Params : params ,
247
+ targetView : initView ,
248
+ indexedView : initView ,
247
249
indexedRange : filterMapsRange {
248
250
initialized : initialized ,
249
251
headIndexed : rs .HeadIndexed ,
@@ -265,16 +267,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
265
267
baseRowsCache : lru.NewCache [uint64 , [][]uint32 ](cachedBaseRows ),
266
268
renderSnapshots : lru.NewCache [uint64 , * renderedMap ](cachedRenderSnapshots ),
267
269
}
270
+ f .checkRevertRange () // revert maps that are inconsistent with the current chain view
268
271
269
- // Set initial indexer target.
270
- f .targetView = initView
271
- if f .indexedRange .initialized {
272
- f .indexedView = f .initChainView (f .targetView )
273
- f .indexedRange .headIndexed = f .indexedRange .blocks .AfterLast () == f .indexedView .HeadNumber ()+ 1
274
- if ! f .indexedRange .headIndexed {
275
- f .indexedRange .headDelimiter = 0
276
- }
277
- }
278
272
if f .indexedRange .hasIndexedBlocks () {
279
273
log .Info ("Initialized log indexer" ,
280
274
"first block" , f .indexedRange .blocks .First (), "last block" , f .indexedRange .blocks .Last (),
@@ -303,29 +297,40 @@ func (f *FilterMaps) Stop() {
303
297
f .closeWg .Wait ()
304
298
}
305
299
306
- // initChainView returns a chain view consistent with both the current target
307
- // view and the current state of the log index as found in the database, based
308
- // on the last block of stored maps.
309
- // Note that the returned view might be shorter than the existing index if
310
- // the latest maps are not consistent with targetView.
311
- func (f * FilterMaps ) initChainView (chainView * ChainView ) * ChainView {
312
- mapIndex := f .indexedRange .maps .AfterLast ()
313
- for {
314
- var ok bool
315
- mapIndex , ok = f .lastMapBoundaryBefore (mapIndex )
316
- if ! ok {
317
- break
300
+ // checkRevertRange checks whether the existing index is consistent with the
301
+ // current indexed view and reverts inconsistent maps if necessary.
302
+ func (f * FilterMaps ) checkRevertRange () {
303
+ if f .indexedRange .maps .Count () == 0 {
304
+ return
305
+ }
306
+ lastMap := f .indexedRange .maps .Last ()
307
+ lastBlockNumber , lastBlockId , err := f .getLastBlockOfMap (lastMap )
308
+ if err != nil {
309
+ log .Error ("Error initializing log index database; resetting log index" , "error" , err )
310
+ f .reset ()
311
+ return
312
+ }
313
+ for lastBlockNumber > f .indexedView .HeadNumber () || f .indexedView .BlockId (lastBlockNumber ) != lastBlockId {
314
+ // revert last map
315
+ if f .indexedRange .maps .Count () == 1 {
316
+ f .reset () // reset database if no rendered maps remained
317
+ return
318
318
}
319
- lastBlockNumber , lastBlockId , err := f .getLastBlockOfMap (mapIndex )
319
+ lastMap --
320
+ newRange := f .indexedRange
321
+ newRange .maps .SetLast (lastMap )
322
+ lastBlockNumber , lastBlockId , err = f .getLastBlockOfMap (lastMap )
320
323
if err != nil {
321
- log .Error ("Could not initialize indexed chain view" , "error" , err )
322
- break
323
- }
324
- if lastBlockNumber <= chainView .HeadNumber () && chainView .BlockId (lastBlockNumber ) == lastBlockId {
325
- return chainView .limitedView (lastBlockNumber )
324
+ log .Error ("Error initializing log index database; resetting log index" , "error" , err )
325
+ f .reset ()
326
+ return
326
327
}
328
+ newRange .blocks .SetAfterLast (lastBlockNumber ) // lastBlockNumber is probably partially indexed
329
+ newRange .headIndexed = false
330
+ newRange .headDelimiter = 0
331
+ // only shorten range and leave map data; next head render will overwrite it
332
+ f .setRange (f .db , f .indexedView , newRange , false )
327
333
}
328
- return chainView .limitedView (0 )
329
334
}
330
335
331
336
// reset un-initializes the FilterMaps structure and removes all related data from
@@ -662,15 +667,11 @@ func (f *FilterMaps) mapRowIndex(mapIndex, rowIndex uint32) uint64 {
662
667
}
663
668
664
669
// getBlockLvPointer returns the starting log value index where the log values
665
- // generated by the given block are located. If blockNumber is beyond the current
666
- // head then the first unoccupied log value index is returned.
670
+ // generated by the given block are located.
667
671
//
668
672
// Note that this function assumes that the indexer read lock is being held when
669
673
// called from outside the indexerLoop goroutine.
670
674
func (f * FilterMaps ) getBlockLvPointer (blockNumber uint64 ) (uint64 , error ) {
671
- if blockNumber >= f .indexedRange .blocks .AfterLast () && f .indexedRange .headIndexed {
672
- return f .indexedRange .headDelimiter + 1 , nil
673
- }
674
675
if lvPointer , ok := f .lvPointerCache .Get (blockNumber ); ok {
675
676
return lvPointer , nil
676
677
}
0 commit comments