mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
ethclient/lightclient: requestMap.close()
This commit is contained in:
parent
238e47e78a
commit
2d485d5972
6 changed files with 65 additions and 18 deletions
|
|
@ -173,7 +173,6 @@ loop:
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
client.Close()
|
||||||
client.Stop()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ const recentCanonicalLength = 256
|
||||||
type canonicalChainFields struct {
|
type canonicalChainFields struct {
|
||||||
chainLock sync.Mutex
|
chainLock sync.Mutex
|
||||||
head, finality *btypes.ExecutionHeader
|
head, finality *btypes.ExecutionHeader
|
||||||
recent map[uint64]common.Hash // nil until initialized
|
recent map[uint64]common.Hash // nil while head == nil
|
||||||
recentTail uint64 // if recent != nil then recent hashes are available from recentTail to head
|
recentTail uint64 // if recent != nil then recent hashes are available from recentTail to head
|
||||||
tailFetchCh chan struct{}
|
tailFetchCh chan struct{}
|
||||||
finalized *lru.Cache[uint64, common.Hash] // finalized but not recent hashes
|
finalized *lru.Cache[uint64, common.Hash] // finalized but not recent hashes
|
||||||
|
|
@ -53,6 +53,10 @@ func (c *Client) initCanonicalChain() {
|
||||||
go c.tailFetcher()
|
go c.tailFetcher()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) closeCanonicalChain() {
|
||||||
|
c.requests.close()
|
||||||
|
}
|
||||||
|
|
||||||
// Process implements request.Module in order to get notified about new heads.
|
// Process implements request.Module in order to get notified about new heads.
|
||||||
func (c *Client) Process(requester request.Requester, events []request.Event) {
|
func (c *Client) Process(requester request.Requester, events []request.Event) {
|
||||||
if finality, ok := c.headTracker.ValidatedFinality(); ok {
|
if finality, ok := c.headTracker.ValidatedFinality(); ok {
|
||||||
|
|
@ -268,6 +272,11 @@ func (c *Client) initBlocksAndHeaders() {
|
||||||
c.blockRequests = newRequestMap[common.Hash, *types.Block](c.requestBlock)
|
c.blockRequests = newRequestMap[common.Hash, *types.Block](c.requestBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) closeBlocksAndHeaders() {
|
||||||
|
c.headerRequests.close()
|
||||||
|
c.blockRequests.close()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) requestHeader(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
func (c *Client) requestHeader(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
var header *types.Header
|
var header *types.Header
|
||||||
log.Debug("Starting RPC request", "type", "eth_getBlockByHash", "hash", hash, "full", false)
|
log.Debug("Starting RPC request", "type", "eth_getBlockByHash", "hash", hash, "full", false)
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,11 @@ func (c *Client) Start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Stop() {
|
func (c *Client) Close() {
|
||||||
|
c.closeBlocksAndHeaders()
|
||||||
|
c.closeCanonicalChain()
|
||||||
|
c.closeTxAndReceipts()
|
||||||
|
c.closeLightState()
|
||||||
c.scheduler.Stop()
|
c.scheduler.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,29 @@ package lightclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type requestMap[K comparable, V any] struct {
|
type requestMap[K comparable, V any] struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
closed bool
|
||||||
requestFn func(context.Context, K) (V, error)
|
requestFn func(context.Context, K) (V, error)
|
||||||
requests map[K]*mappedRequest[K, V]
|
requests map[K]*mappedRequest[K, V]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mappedRequest[K comparable, V any] struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
rm *requestMap[K, V]
|
||||||
|
key K
|
||||||
|
refCount int
|
||||||
|
delivered, closed bool
|
||||||
|
deliveredCh chan struct{}
|
||||||
|
cancelFn func() // called when delivered || closed || refCount == 0 becomes true
|
||||||
|
result V
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
func newRequestMap[K comparable, V any](requestFn func(context.Context, K) (V, error)) *requestMap[K, V] {
|
func newRequestMap[K comparable, V any](requestFn func(context.Context, K) (V, error)) *requestMap[K, V] {
|
||||||
return &requestMap[K, V]{
|
return &requestMap[K, V]{
|
||||||
requestFn: requestFn,
|
requestFn: requestFn,
|
||||||
|
|
@ -34,6 +48,22 @@ func newRequestMap[K comparable, V any](requestFn func(context.Context, K) (V, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rm *requestMap[K, V]) close() {
|
||||||
|
rm.lock.Lock()
|
||||||
|
defer rm.lock.Unlock()
|
||||||
|
|
||||||
|
if rm.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, req := range rm.requests {
|
||||||
|
if !req.delivered && req.refCount != 0 {
|
||||||
|
req.cancelFn()
|
||||||
|
req.closed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rm.closed = true
|
||||||
|
}
|
||||||
|
|
||||||
func (rm *requestMap[K, V]) request(key K) *mappedRequest[K, V] {
|
func (rm *requestMap[K, V]) request(key K) *mappedRequest[K, V] {
|
||||||
rm.lock.Lock()
|
rm.lock.Lock()
|
||||||
defer rm.lock.Unlock()
|
defer rm.lock.Unlock()
|
||||||
|
|
@ -53,6 +83,14 @@ func (rm *requestMap[K, V]) request(key K) *mappedRequest[K, V] {
|
||||||
cancelFn: cancelFn,
|
cancelFn: cancelFn,
|
||||||
}
|
}
|
||||||
rm.requests[key] = r
|
rm.requests[key] = r
|
||||||
|
if rm.closed {
|
||||||
|
// return a closed dummy request for simplicity
|
||||||
|
r.closed = true
|
||||||
|
r.cancelFn()
|
||||||
|
var null V
|
||||||
|
r.deliver(null, errors.New("request map is closed"))
|
||||||
|
return r
|
||||||
|
}
|
||||||
if rm.requestFn != nil {
|
if rm.requestFn != nil {
|
||||||
go func() {
|
go func() {
|
||||||
result, err := rm.requestFn(ctx, key)
|
result, err := rm.requestFn(ctx, key)
|
||||||
|
|
@ -91,25 +129,13 @@ func (rm *requestMap[K, V]) tryDeliver(key K, result V) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type mappedRequest[K comparable, V any] struct {
|
|
||||||
lock sync.Mutex
|
|
||||||
rm *requestMap[K, V]
|
|
||||||
key K
|
|
||||||
refCount int
|
|
||||||
delivered bool
|
|
||||||
deliveredCh chan struct{}
|
|
||||||
cancelFn func() // called when delivered || refCount == 0 becomes true
|
|
||||||
result V
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *mappedRequest[K, V]) deliver(result V, err error) {
|
func (r *mappedRequest[K, V]) deliver(result V, err error) {
|
||||||
r.lock.Lock()
|
r.lock.Lock()
|
||||||
if !r.delivered {
|
if !r.delivered {
|
||||||
r.result, r.err = result, err
|
r.result, r.err = result, err
|
||||||
r.delivered = true
|
r.delivered = true
|
||||||
close(r.deliveredCh)
|
close(r.deliveredCh)
|
||||||
if r.refCount != 0 {
|
if !r.closed && r.refCount != 0 {
|
||||||
r.cancelFn()
|
r.cancelFn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,7 +159,7 @@ func (r *mappedRequest[K, V]) release() {
|
||||||
r.refCount--
|
r.refCount--
|
||||||
if r.refCount == 0 {
|
if r.refCount == 0 {
|
||||||
delete(r.rm.requests, r.key)
|
delete(r.rm.requests, r.key)
|
||||||
if !r.delivered {
|
if !r.delivered && !r.closed {
|
||||||
r.cancelFn()
|
r.cancelFn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,11 @@ func (c *Client) initLightState() {
|
||||||
c.codeRequests = newRequestMap[codeRequest, []byte](c.requestCode)
|
c.codeRequests = newRequestMap[codeRequest, []byte](c.requestCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) closeLightState() {
|
||||||
|
c.proofRequests.close()
|
||||||
|
c.codeRequests.close()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) fetchProof(ctx context.Context, req proofRequest) (*gethclient.AccountResult, error) {
|
func (c *Client) fetchProof(ctx context.Context, req proofRequest) (*gethclient.AccountResult, error) {
|
||||||
if proof, ok := c.proofCache.Get(req); ok {
|
if proof, ok := c.proofCache.Get(req); ok {
|
||||||
return proof, nil
|
return proof, nil
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,10 @@ func (c *Client) initTxAndReceipts() {
|
||||||
c.receiptsRequests = newRequestMap[common.Hash, types.Receipts](c.requestBlockReceipts)
|
c.receiptsRequests = newRequestMap[common.Hash, types.Receipts](c.requestBlockReceipts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) closeTxAndReceipts() {
|
||||||
|
c.receiptsRequests.close()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) getTxByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) {
|
func (c *Client) getTxByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) {
|
||||||
if pos, ok := c.txPosCache.Get(txHash); ok {
|
if pos, ok := c.txPosCache.Get(txHash); ok {
|
||||||
if hash, ok := c.getCachedHash(pos.blockNumber); ok && hash == pos.blockHash {
|
if hash, ok := c.getCachedHash(pos.blockNumber); ok && hash == pos.blockHash {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue