Skip to content

Commit

Permalink
fix comments and add doc
Browse files Browse the repository at this point in the history
  • Loading branch information
alexgao001 committed Jul 24, 2024
1 parent 62889b2 commit ac8c7e2
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 333 deletions.
332 changes: 42 additions & 290 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/blockarchiver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ type BlockArchiverConfig struct {
}

var DefaultBlockArchiverConfig = BlockArchiverConfig{
BlockCacheSize: 5000,
BlockCacheSize: 50000,
}
44 changes: 21 additions & 23 deletions core/blockarchiver/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
)

const (
GetBlockRetry = 3
GetBlockRetryInterval = 2 * time.Second
RPCTimeout = 10 * time.Second
GetBlockTimeout = 5 * time.Second

RPCTimeout = 30 * time.Second
)

var _ BlockArchiver = (*BlockArchiverService)(nil)
Expand Down Expand Up @@ -89,8 +89,7 @@ func (c *BlockArchiverService) GetLatestHeader() (*types.Header, error) {

// GetBlockByNumber returns the block by number
func (c *BlockArchiverService) GetBlockByNumber(number uint64) (*types.Body, *types.Header, error) {
log.Info("get block by number", "number", number)
// check if the block is in the cache
log.Debug("get block by number", "number", number)
hash, found := c.hashCache.Get(number)
if found {
log.Debug("GetBlockByNumber found in cache", number)
Expand All @@ -105,25 +104,26 @@ func (c *BlockArchiverService) GetBlockByNumber(number uint64) (*types.Body, *ty

// getBlockByNumber returns the block by number
func (c *BlockArchiverService) getBlockByNumber(number uint64) (*types.Body, *types.Header, error) {
// to avoid concurrent fetching of the same bundle of blocks(), rangeCache applies here,
// to avoid concurrent fetching of the same bundle of blocks, requestLock applies here
// if the number is within any of the ranges, should not fetch the bundle from the block archiver service but
// wait for a while and fetch from the cache
if c.requestLock.IsWithinAnyRange(number) {
log.Info("getBlockByNumber is within any range", number)
// wait for a while, and fetch from the cache
for retry := 0; retry < GetBlockRetry; retry++ {
hash, found := c.hashCache.Get(number)
if found {
body, foundB := c.bodyCache.Get(hash)
header, foundH := c.headerCache.Get(hash)
if foundB && foundH {
return body, header, nil
log.Debug("getBlockByNumber is within any range", number)
if blockRange := c.requestLock.GetRangeForNumber(number); blockRange != nil {
select {
case <-blockRange.done:
hash, found := c.hashCache.Get(number)
if found {
body, foundB := c.bodyCache.Get(hash)
header, foundH := c.headerCache.Get(hash)
if foundB && foundH {
return body, header, nil
}
}
case <-time.After(GetBlockTimeout):
return nil, nil, errors.New("block not found")
}
time.Sleep(GetBlockRetryInterval)
}
// if still not found
return nil, nil, errors.New("block not found")
}
// fetch the bundle range
log.Info("fetching bundle of blocks", "number", number)
Expand Down Expand Up @@ -155,7 +155,7 @@ func (c *BlockArchiverService) getBlockByNumber(number uint64) (*types.Body, *ty
var body *types.Body
var header *types.Header

log.Info("populating block cache", "start", start, "end", end)
log.Debug("populating block cache", "start", start, "end", end)
for _, b := range blocks {
block, err := convertBlock(b)
if err != nil {
Expand All @@ -175,9 +175,7 @@ func (c *BlockArchiverService) getBlockByNumber(number uint64) (*types.Body, *ty

// GetBlockByHash returns the block by hash
func (c *BlockArchiverService) GetBlockByHash(hash common.Hash) (*types.Body, *types.Header, error) {
log.Info("get block by hash", "hash", hash.Hex())
log.Info(hash.Hex())
// check if the block is in the cach
log.Debug("get block by hash", "hash", hash.Hex())
body, foundB := c.bodyCache.Get(hash)
header, foundH := c.headerCache.Get(hash)
if foundB && foundH {
Expand All @@ -203,7 +201,7 @@ func (c *BlockArchiverService) GetBlockByHash(hash common.Hash) (*types.Body, *t
}

func (c *BlockArchiverService) cacheStats() {
for range time.NewTicker(10 * time.Second).C {
for range time.NewTicker(1 * time.Minute).C {
log.Info("block archiver cache stats", "bodyCache", c.bodyCache.Len(), "headerCache", c.headerCache.Len(), "hashCache", c.hashCache.Len())
}
}
60 changes: 42 additions & 18 deletions core/blockarchiver/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,49 +110,73 @@ type GeneralBlock struct {
type Range struct {
from uint64
to uint64
// done is a channel closed when the range is removed
done chan struct{}
}

// RequestLock is a lock for making sure we don't fetch the same bundle concurrently
type RequestLock struct {
rangeMap map[uint64]Range
lookupMap map[uint64]bool
// TODO
// there is tradeoff between using a Map or List of ranges, in this case, the lookup needs to be populated every
// time a new range is added, but the lookup is faster. If we use a list, we need to iterate over the list to check
// if the number is within any of the ranges, but we don't need to populate the lookup every time a new range is added.
rangeMap map[uint64]*Range
lookupMap map[uint64]*Range
mu sync.RWMutex
}

// NewRequestLock creates a new RequestLock
func NewRequestLock() *RequestLock {
return &RequestLock{
rangeMap: make(map[uint64]Range),
lookupMap: make(map[uint64]bool),
rangeMap: make(map[uint64]*Range),
lookupMap: make(map[uint64]*Range),
}
}

// IsWithinAnyRange checks if the number is within any of the cached ranges
func (rc *RequestLock) IsWithinAnyRange(num uint64) bool {
rc.mu.RLock()
defer rc.mu.RUnlock()
_, exists := rc.lookupMap[num]
func (rl *RequestLock) IsWithinAnyRange(num uint64) bool {
rl.mu.RLock()
defer rl.mu.RUnlock()
_, exists := rl.lookupMap[num]
return exists
}

// AddRange adds a new range to the cache
func (rc *RequestLock) AddRange(from, to uint64) {
rc.mu.Lock()
defer rc.mu.Unlock()
rc.rangeMap[from] = Range{from, to}
func (rl *RequestLock) AddRange(from, to uint64) {
rl.mu.Lock()
defer rl.mu.Unlock()
newRange := &Range{
from: from,
to: to,
done: make(chan struct{}),
}
rl.rangeMap[from] = newRange
// provide fast lookup
for i := from; i <= to; i++ {
rc.lookupMap[i] = true
rl.lookupMap[i] = newRange
}
}

// RemoveRange removes a range from the cache
func (rc *RequestLock) RemoveRange(from, to uint64) {
rc.mu.Lock()
defer rc.mu.Unlock()
delete(rc.rangeMap, from)
func (rl *RequestLock) RemoveRange(from, to uint64) {
rl.mu.Lock()
defer rl.mu.Unlock()

r, exists := rl.rangeMap[from]
if !exists {
return
}
delete(rl.rangeMap, from)
for i := from; i <= to; i++ {
delete(rc.lookupMap, i)
delete(rl.lookupMap, i)
}
close(r.done)
}

func (rl *RequestLock) GetRangeForNumber(number uint64) *Range {
rl.mu.RLock()
defer rl.mu.RUnlock()
return rl.lookupMap[number]
}

func ParseBundleName(bundleName string) (uint64, uint64, error) {
Expand Down
2 changes: 1 addition & 1 deletion eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var FullNodeGPO = gasprice.Config{

// Defaults contains default settings for use on the BSC main net.
var Defaults = Config{
SyncMode: downloader.SnapSync,
SyncMode: downloader.NoSync,
NetworkId: 0, // enable auto configuration of networkID == chainID
TxLookupLimit: 2350000,
TransactionHistory: 2350000,
Expand Down
Binary file added resource/greenfield-peer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ac8c7e2

Please sign in to comment.