mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
core/filtermaps: un-embedded matcher processing
This commit is contained in:
parent
8f2f37da67
commit
25b51f2940
2 changed files with 102 additions and 78 deletions
|
|
@ -737,7 +737,6 @@ func (l *logIterator) next() error {
|
||||||
l.skipToBoundary = false
|
l.skipToBoundary = false
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
if l.finished {
|
if l.finished {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ type SyncRange struct {
|
||||||
// Also note that the returned list may contain false positives.
|
// Also note that the returned list may contain false positives.
|
||||||
func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock, lastBlock uint64, addresses []common.Address, topics [][]common.Hash) ([]*types.Log, error) {
|
func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock, lastBlock uint64, addresses []common.Address, topics [][]common.Hash) ([]*types.Log, error) {
|
||||||
params := backend.GetParams()
|
params := backend.GetParams()
|
||||||
var getLogStats runtimeStats
|
|
||||||
// find the log value index range to search
|
// find the log value index range to search
|
||||||
firstIndex, err := backend.GetBlockLvPointer(ctx, firstBlock)
|
firstIndex, err := backend.GetBlockLvPointer(ctx, firstBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -88,8 +87,6 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
if lastIndex > 0 {
|
if lastIndex > 0 {
|
||||||
lastIndex--
|
lastIndex--
|
||||||
}
|
}
|
||||||
firstMap, lastMap := uint32(firstIndex>>params.logValuesPerMap), uint32(lastIndex>>params.logValuesPerMap)
|
|
||||||
firstEpoch, lastEpoch := firstMap>>params.logMapsPerEpoch, lastMap>>params.logMapsPerEpoch
|
|
||||||
|
|
||||||
// build matcher according to the given filter criteria
|
// build matcher according to the given filter criteria
|
||||||
matchers := make([]matcher, len(topics)+1)
|
matchers := make([]matcher, len(topics)+1)
|
||||||
|
|
@ -117,45 +114,45 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
// matchers signal a match for consecutive log value indices.
|
// matchers signal a match for consecutive log value indices.
|
||||||
matcher := newMatchSequence(params, matchers)
|
matcher := newMatchSequence(params, matchers)
|
||||||
|
|
||||||
// processEpoch returns the potentially matching logs from the given epoch.
|
m := &matcherEnv{
|
||||||
processEpoch := func(epochIndex uint32) ([]*types.Log, error) {
|
ctx: ctx,
|
||||||
var logs []*types.Log
|
backend: backend,
|
||||||
// create a list of map indices to process
|
params: params,
|
||||||
fm, lm := epochIndex<<params.logMapsPerEpoch, (epochIndex+1)<<params.logMapsPerEpoch-1
|
matcher: matcher,
|
||||||
if fm < firstMap {
|
firstIndex: firstIndex,
|
||||||
fm = firstMap
|
lastIndex: lastIndex,
|
||||||
}
|
firstMap: uint32(firstIndex >> params.logValuesPerMap),
|
||||||
if lm > lastMap {
|
lastMap: uint32(lastIndex >> params.logValuesPerMap),
|
||||||
lm = lastMap
|
|
||||||
}
|
|
||||||
//
|
|
||||||
mapIndices := make([]uint32, lm+1-fm)
|
|
||||||
for i := range mapIndices {
|
|
||||||
mapIndices[i] = fm + uint32(i)
|
|
||||||
}
|
|
||||||
// find potential matches
|
|
||||||
matches, err := getAllMatches(ctx, matcher, mapIndices)
|
|
||||||
if err != nil {
|
|
||||||
return logs, err
|
|
||||||
}
|
|
||||||
// get the actual logs located at the matching log value indices
|
|
||||||
var st int
|
|
||||||
getLogStats.setState(&st, stGetLog)
|
|
||||||
defer getLogStats.setState(&st, stNone)
|
|
||||||
for _, m := range matches {
|
|
||||||
if m == nil {
|
|
||||||
return nil, ErrMatchAll
|
|
||||||
}
|
|
||||||
mlogs, err := getLogsFromMatches(ctx, backend, firstIndex, lastIndex, m)
|
|
||||||
if err != nil {
|
|
||||||
return logs, err
|
|
||||||
}
|
|
||||||
logs = append(logs, mlogs...)
|
|
||||||
}
|
|
||||||
getLogStats.addAmount(st, int64(len(logs)))
|
|
||||||
return logs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
res, err := m.process()
|
||||||
|
|
||||||
|
if doRuntimeStats {
|
||||||
|
log.Info("Log search finished", "elapsed", time.Since(start))
|
||||||
|
for i, ma := range matchers {
|
||||||
|
for j, m := range ma.(matchAny) {
|
||||||
|
log.Info("Single matcher stats", "matchSequence", i, "matchAny", j)
|
||||||
|
m.(*singleMatcher).stats.print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("Get log stats")
|
||||||
|
m.getLogStats.print()
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type matcherEnv struct {
|
||||||
|
ctx context.Context
|
||||||
|
backend MatcherBackend
|
||||||
|
params *Params
|
||||||
|
matcher matcher
|
||||||
|
getLogStats runtimeStats
|
||||||
|
firstIndex, lastIndex uint64
|
||||||
|
firstMap, lastMap uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *matcherEnv) process() ([]*types.Log, error) {
|
||||||
type task struct {
|
type task struct {
|
||||||
epochIndex uint32
|
epochIndex uint32
|
||||||
logs []*types.Log
|
logs []*types.Log
|
||||||
|
|
@ -175,18 +172,18 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
if task == nil {
|
if task == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
task.logs, task.err = processEpoch(task.epochIndex)
|
task.logs, task.err = m.processEpoch(task.epochIndex)
|
||||||
close(task.done)
|
close(task.done)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go worker()
|
go worker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstEpoch, lastEpoch := m.firstMap>>m.params.logMapsPerEpoch, m.lastMap>>m.params.logMapsPerEpoch
|
||||||
var logs []*types.Log
|
var logs []*types.Log
|
||||||
// startEpoch is the next task to send whenever a worker can accept it.
|
// startEpoch is the next task to send whenever a worker can accept it.
|
||||||
// waitEpoch is the next task we are waiting for to finish in order to append
|
// waitEpoch is the next task we are waiting for to finish in order to append
|
||||||
|
|
@ -220,30 +217,58 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if doRuntimeStats {
|
return logs, nil
|
||||||
log.Info("Log search finished", "elapsed", time.Since(start))
|
}
|
||||||
for i, ma := range matchers {
|
|
||||||
for j, m := range ma.(matchAny) {
|
// processEpoch returns the potentially matching logs from the given epoch.
|
||||||
log.Info("Single matcher stats", "matchSequence", i, "matchAny", j)
|
func (m *matcherEnv) processEpoch(epochIndex uint32) ([]*types.Log, error) {
|
||||||
m.(*singleMatcher).stats.print()
|
var logs []*types.Log
|
||||||
}
|
// create a list of map indices to process
|
||||||
}
|
fm, lm := epochIndex<<m.params.logMapsPerEpoch, (epochIndex+1)<<m.params.logMapsPerEpoch-1
|
||||||
log.Info("Get log stats")
|
if fm < m.firstMap {
|
||||||
getLogStats.print()
|
fm = m.firstMap
|
||||||
}
|
}
|
||||||
|
if lm > m.lastMap {
|
||||||
|
lm = m.lastMap
|
||||||
|
}
|
||||||
|
//
|
||||||
|
mapIndices := make([]uint32, lm+1-fm)
|
||||||
|
for i := range mapIndices {
|
||||||
|
mapIndices[i] = fm + uint32(i)
|
||||||
|
}
|
||||||
|
// find potential matches
|
||||||
|
matches, err := m.getAllMatches(mapIndices)
|
||||||
|
if err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
// get the actual logs located at the matching log value indices
|
||||||
|
var st int
|
||||||
|
m.getLogStats.setState(&st, stGetLog)
|
||||||
|
defer m.getLogStats.setState(&st, stNone)
|
||||||
|
for _, match := range matches {
|
||||||
|
if match == nil {
|
||||||
|
return nil, ErrMatchAll
|
||||||
|
}
|
||||||
|
mlogs, err := m.getLogsFromMatches(match)
|
||||||
|
if err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
logs = append(logs, mlogs...)
|
||||||
|
}
|
||||||
|
m.getLogStats.addAmount(st, int64(len(logs)))
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLogsFromMatches returns the list of potentially matching logs located at
|
// getLogsFromMatches returns the list of potentially matching logs located at
|
||||||
// the given list of matching log indices. Matches outside the firstIndex to
|
// the given list of matching log indices. Matches outside the firstIndex to
|
||||||
// lastIndex range are not returned.
|
// lastIndex range are not returned.
|
||||||
func getLogsFromMatches(ctx context.Context, backend MatcherBackend, firstIndex, lastIndex uint64, matches potentialMatches) ([]*types.Log, error) {
|
func (m *matcherEnv) getLogsFromMatches(matches potentialMatches) ([]*types.Log, error) {
|
||||||
var logs []*types.Log
|
var logs []*types.Log
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
if match < firstIndex || match > lastIndex {
|
if match < m.firstIndex || match > m.lastIndex {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log, err := backend.GetLogByLvIndex(ctx, match)
|
log, err := m.backend.GetLogByLvIndex(m.ctx, match)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logs, fmt.Errorf("failed to retrieve log at index %d: %v", match, err)
|
return logs, fmt.Errorf("failed to retrieve log at index %d: %v", match, err)
|
||||||
}
|
}
|
||||||
|
|
@ -254,6 +279,28 @@ func getLogsFromMatches(ctx context.Context, backend MatcherBackend, firstIndex,
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAllMatches creates an instance for a given matcher and set of map indices,
|
||||||
|
// iterates through mapping layers and collects all results, then returns all
|
||||||
|
// results in the same order as the map indices were specified.
|
||||||
|
func (m *matcherEnv) getAllMatches(mapIndices []uint32) ([]potentialMatches, error) {
|
||||||
|
instance := m.matcher.newInstance(mapIndices)
|
||||||
|
resultsMap := make(map[uint32]potentialMatches)
|
||||||
|
for layerIndex := uint32(0); len(resultsMap) < len(mapIndices); layerIndex++ {
|
||||||
|
results, err := instance.getMatchesForLayer(m.ctx, layerIndex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, result := range results {
|
||||||
|
resultsMap[result.mapIndex] = result.matches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matches := make([]potentialMatches, len(mapIndices))
|
||||||
|
for i, mapIndex := range mapIndices {
|
||||||
|
matches[i] = resultsMap[mapIndex]
|
||||||
|
}
|
||||||
|
return matches, nil
|
||||||
|
}
|
||||||
|
|
||||||
// matcher defines a general abstraction for any matcher configuration that
|
// matcher defines a general abstraction for any matcher configuration that
|
||||||
// can instantiate a matcherInstance.
|
// can instantiate a matcherInstance.
|
||||||
type matcher interface {
|
type matcher interface {
|
||||||
|
|
@ -281,28 +328,6 @@ type matcherResult struct {
|
||||||
matches potentialMatches
|
matches potentialMatches
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAllMatches creates an instance for a given matcher and set of map indices,
|
|
||||||
// iterates through mapping layers and collects all results, then returns all
|
|
||||||
// results in the same order as the map indices were specified.
|
|
||||||
func getAllMatches(ctx context.Context, matcher matcher, mapIndices []uint32) ([]potentialMatches, error) {
|
|
||||||
instance := matcher.newInstance(mapIndices)
|
|
||||||
resultsMap := make(map[uint32]potentialMatches)
|
|
||||||
for layerIndex := uint32(0); len(resultsMap) < len(mapIndices); layerIndex++ {
|
|
||||||
results, err := instance.getMatchesForLayer(ctx, layerIndex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, result := range results {
|
|
||||||
resultsMap[result.mapIndex] = result.matches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matches := make([]potentialMatches, len(mapIndices))
|
|
||||||
for i, mapIndex := range mapIndices {
|
|
||||||
matches[i] = resultsMap[mapIndex]
|
|
||||||
}
|
|
||||||
return matches, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// singleMatcher implements matcher by returning matches for a single log value hash.
|
// singleMatcher implements matcher by returning matches for a single log value hash.
|
||||||
type singleMatcher struct {
|
type singleMatcher struct {
|
||||||
backend MatcherBackend
|
backend MatcherBackend
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue