-
Notifications
You must be signed in to change notification settings - Fork 20k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
core/filtermaps: guaranteed valid range
- Loading branch information
1 parent
32c82f0
commit c6c805f
Showing
9 changed files
with
223 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package filtermaps | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/ethereum/go-ethereum/core/types" | ||
) | ||
|
||
// FilterMapsMatcherBackend implements MatcherBackend. | ||
type FilterMapsMatcherBackend struct { | ||
f *FilterMaps | ||
valid, closed bool | ||
firstValid, lastValid uint64 | ||
syncCh chan validRange | ||
} | ||
|
||
type validRange struct { | ||
head *types.Header | ||
// block range indexed according to the given chain head | ||
indexed bool | ||
firstIndexed, lastIndexed uint64 | ||
// block range where the index has not changed since the last matcher sync | ||
// and therefore the set of matches found in this region is guaranteed to | ||
// be valid and complete. | ||
valid bool | ||
firstValid, lastValid uint64 | ||
} | ||
|
||
func (f *FilterMaps) NewMatcherBackend() *FilterMapsMatcherBackend { | ||
f.lock.Lock() | ||
defer f.lock.Unlock() | ||
|
||
fm := &FilterMapsMatcherBackend{ | ||
f: f, | ||
valid: f.initialized, | ||
firstValid: f.tailBlockNumber, | ||
lastValid: f.headBlockNumber, | ||
} | ||
f.matchers[fm] = struct{}{} | ||
return fm | ||
} | ||
|
||
// revert utan automatikusan hivjuk, write lock alatt | ||
func (f *FilterMaps) limitMatcherRange() { | ||
for fm := range f.matchers { | ||
if !f.initialized { | ||
fm.valid = false | ||
} | ||
if !fm.valid { | ||
continue | ||
} | ||
if fm.firstValid < f.tailBlockNumber { | ||
fm.firstValid = f.tailBlockNumber | ||
} | ||
if fm.lastValid > f.headBlockNumber { | ||
fm.lastValid = f.headBlockNumber | ||
} | ||
if fm.firstValid > fm.lastValid { | ||
fm.valid = false | ||
} | ||
} | ||
} | ||
|
||
func (f *FilterMaps) sendMatcherSync(head *types.Header) { | ||
f.lock.Lock() | ||
defer f.lock.Unlock() | ||
|
||
for fm := range f.matchers { | ||
if fm.syncCh == nil { | ||
continue | ||
} | ||
fm.syncCh <- validRange{ | ||
head: head, | ||
valid: fm.valid, | ||
firstValid: fm.firstValid, | ||
lastValid: fm.lastValid, | ||
indexed: f.initialized, | ||
firstIndexed: f.tailBlockNumber, | ||
lastIndexed: f.headBlockNumber, | ||
} | ||
fm.valid = f.initialized | ||
fm.firstValid = f.tailBlockNumber | ||
fm.lastValid = f.headBlockNumber | ||
fm.syncCh = nil | ||
} | ||
} | ||
|
||
func (fm *FilterMapsMatcherBackend) Close() { | ||
fm.f.lock.Lock() | ||
defer fm.f.lock.Unlock() | ||
|
||
if fm.syncCh != nil { | ||
close(fm.syncCh) | ||
fm.syncCh = nil | ||
} | ||
fm.closed = true | ||
delete(fm.f.matchers, fm) | ||
} | ||
|
||
// GetFilterMapRow returns the given row of the given map. If the row is empty | ||
// then a non-nil zero length row is returned. | ||
// Note that the returned slices should not be modified, they should be copied | ||
// on write. | ||
// GetFilterMapRow implements MatcherBackend. | ||
func (fm *FilterMapsMatcherBackend) GetFilterMapRow(ctx context.Context, mapIndex, rowIndex uint32) (FilterRow, error) { | ||
return fm.f.getFilterMapRow(mapIndex, rowIndex) | ||
} | ||
|
||
// GetBlockLvPointer returns the starting log value index where the log values | ||
// generated by the given block are located. If blockNumber is beyond the current | ||
// head then the first unoccupied log value index is returned. | ||
// GetBlockLvPointer implements MatcherBackend. | ||
func (fm *FilterMapsMatcherBackend) GetBlockLvPointer(ctx context.Context, blockNumber uint64) (uint64, error) { | ||
fm.f.lock.RLock() | ||
defer fm.f.lock.RUnlock() | ||
|
||
return fm.f.getBlockLvPointer(blockNumber) | ||
} | ||
|
||
// GetLogByLvIndex returns the log at the given log value index. If the index does | ||
// not point to the first log value entry of a log then no log and no error are | ||
// returned as this can happen when the log value index was a false positive. | ||
// Note that this function assumes that the log index structure is consistent | ||
// with the canonical chain at the point where the given log value index points. | ||
// If this is not the case then an invalid result or an error may be returned. | ||
// GetLogByLvIndex implements MatcherBackend. | ||
func (fm *FilterMapsMatcherBackend) GetLogByLvIndex(ctx context.Context, lvIndex uint64) (*types.Log, error) { | ||
fm.f.lock.RLock() | ||
defer fm.f.lock.RUnlock() | ||
|
||
return fm.f.getLogByLvIndex(lvIndex) | ||
} | ||
|
||
func (fm *FilterMapsMatcherBackend) Sync(ctx context.Context) validRange { | ||
syncCh := make(chan validRange, 1) | ||
fm.f.lock.Lock() | ||
closed := fm.closed | ||
if !closed { | ||
fm.syncCh = syncCh | ||
} | ||
fm.f.lock.Unlock() | ||
if closed { | ||
return validRange{} | ||
} | ||
select { | ||
case fm.f.matcherSyncCh <- struct{}{}: | ||
default: | ||
} | ||
select { | ||
case vr := <-syncCh: | ||
return vr | ||
case <-ctx.Done(): | ||
return validRange{} | ||
} | ||
} |
Oops, something went wrong.