mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
core, downloader, handler, sync: make use of mutex-free stats
This commit is contained in:
parent
88202c656f
commit
373f600c7b
5 changed files with 49 additions and 19 deletions
|
|
@ -47,6 +47,10 @@ func (stats *Chainstats) SetNumber(number *big.Int) {
|
||||||
func (stats *Chainstats) GetFastNumber() uint64 {
|
func (stats *Chainstats) GetFastNumber() uint64 {
|
||||||
return stats.currentFastBlockNumber.Load().(*big.Int).Uint64()
|
return stats.currentFastBlockNumber.Load().(*big.Int).Uint64()
|
||||||
}
|
}
|
||||||
|
func (stats *Chainstats) GetNumbers() (uint64, uint64) {
|
||||||
|
return stats.currentBlockNumber.Load().(*big.Int).Uint64(),
|
||||||
|
stats.currentFastBlockNumber.Load().(*big.Int).Uint64()
|
||||||
|
}
|
||||||
func (stats *Chainstats) SetFastNumber(number *big.Int) {
|
func (stats *Chainstats) SetFastNumber(number *big.Int) {
|
||||||
stats.currentFastBlockNumber.Store(number)
|
stats.currentFastBlockNumber.Store(number)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -714,6 +714,24 @@ func (bc *BlockChain) procFutureBlocks() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stats returns the chainstats which can be queried non-blocking for info about difficulty and numbers
|
||||||
|
// These are provided on a best-effort, and it's theoretically possible that two consecutive calls to
|
||||||
|
// number and difficulty return number for X and difficulty for Y, if the stats is updated between the calls
|
||||||
|
func (bc *BlockChain) Stats() *chainstats.Chainstats {
|
||||||
|
return bc.chainStats
|
||||||
|
}
|
||||||
|
func (bc *BlockChain) CurrentNumber() uint64 {
|
||||||
|
return bc.chainStats.GetNumber()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *BlockChain) CurrentFastNumber() uint64 {
|
||||||
|
return bc.chainStats.GetFastNumber()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *BlockChain) CurrentTD() *big.Int {
|
||||||
|
return bc.chainStats.GetTotalDifficulty()
|
||||||
|
}
|
||||||
|
|
||||||
// WriteStatus status of write
|
// WriteStatus status of write
|
||||||
type WriteStatus byte
|
type WriteStatus byte
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,15 @@ type BlockChain interface {
|
||||||
|
|
||||||
// InsertReceiptChain inserts a batch of receipts into the local chain.
|
// InsertReceiptChain inserts a batch of receipts into the local chain.
|
||||||
InsertReceiptChain(types.Blocks, []types.Receipts) (int, error)
|
InsertReceiptChain(types.Blocks, []types.Receipts) (int, error)
|
||||||
|
|
||||||
|
// CurrentNumber retrieves number of the current head block
|
||||||
|
CurrentNumber() uint64
|
||||||
|
|
||||||
|
// CurrentNumber retrieves number of the current head fast block
|
||||||
|
CurrentFastNumber() uint64
|
||||||
|
|
||||||
|
// CurrentTD retrives the total difficulty of the current head block
|
||||||
|
CurrentTD() *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new downloader to fetch hashes and blocks from remote peers.
|
// New creates a new downloader to fetch hashes and blocks from remote peers.
|
||||||
|
|
@ -583,9 +592,9 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
|
||||||
floor, ceil := int64(-1), d.lightchain.CurrentHeader().Number.Uint64()
|
floor, ceil := int64(-1), d.lightchain.CurrentHeader().Number.Uint64()
|
||||||
|
|
||||||
if d.mode == FullSync {
|
if d.mode == FullSync {
|
||||||
ceil = d.blockchain.CurrentBlock().NumberU64()
|
ceil = d.blockchain.CurrentNumber()
|
||||||
} else if d.mode == FastSync {
|
} else if d.mode == FastSync {
|
||||||
ceil = d.blockchain.CurrentFastBlock().NumberU64()
|
ceil = d.blockchain.CurrentFastNumber()
|
||||||
}
|
}
|
||||||
if ceil >= MaxForkAncestry {
|
if ceil >= MaxForkAncestry {
|
||||||
floor = int64(ceil - MaxForkAncestry)
|
floor = int64(ceil - MaxForkAncestry)
|
||||||
|
|
@ -1156,16 +1165,16 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
|
||||||
for i, header := range rollback {
|
for i, header := range rollback {
|
||||||
hashes[i] = header.Hash()
|
hashes[i] = header.Hash()
|
||||||
}
|
}
|
||||||
lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0
|
lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, uint64(0), uint64(0)
|
||||||
if d.mode != LightSync {
|
if d.mode != LightSync {
|
||||||
lastFastBlock = d.blockchain.CurrentFastBlock().Number()
|
lastFastBlock = d.blockchain.CurrentFastNumber()
|
||||||
lastBlock = d.blockchain.CurrentBlock().Number()
|
lastBlock = d.blockchain.CurrentNumber()
|
||||||
}
|
}
|
||||||
d.lightchain.Rollback(hashes)
|
d.lightchain.Rollback(hashes)
|
||||||
curFastBlock, curBlock := common.Big0, common.Big0
|
curFastBlock, curBlock := uint64(0), uint64(0)
|
||||||
if d.mode != LightSync {
|
if d.mode != LightSync {
|
||||||
curFastBlock = d.blockchain.CurrentFastBlock().Number()
|
curFastBlock = d.blockchain.CurrentFastNumber()
|
||||||
curBlock = d.blockchain.CurrentBlock().Number()
|
curBlock = d.blockchain.CurrentNumber()
|
||||||
}
|
}
|
||||||
log.Warn("Rolled back headers", "count", len(hashes),
|
log.Warn("Rolled back headers", "count", len(hashes),
|
||||||
"header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
|
"header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
|
||||||
|
|
@ -1205,8 +1214,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
|
||||||
// L: Request new headers up from 11 (R's TD was higher, it must have something)
|
// L: Request new headers up from 11 (R's TD was higher, it must have something)
|
||||||
// R: Nothing to give
|
// R: Nothing to give
|
||||||
if d.mode != LightSync {
|
if d.mode != LightSync {
|
||||||
head := d.blockchain.CurrentBlock()
|
if !gotHeaders && td.Cmp(d.blockchain.CurrentTD()) > 0 {
|
||||||
if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 {
|
|
||||||
return errStallingPeer
|
return errStallingPeer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
|
||||||
quitSync: make(chan struct{}),
|
quitSync: make(chan struct{}),
|
||||||
}
|
}
|
||||||
// Figure out whether to allow fast sync or not
|
// Figure out whether to allow fast sync or not
|
||||||
if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 {
|
if mode == downloader.FastSync && blockchain.Stats().GetNumber() > 0 {
|
||||||
log.Warn("Blockchain not empty, fast sync disabled")
|
log.Warn("Blockchain not empty, fast sync disabled")
|
||||||
mode = downloader.FullSync
|
mode = downloader.FullSync
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +165,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
|
||||||
return engine.VerifyHeader(blockchain, header, true)
|
return engine.VerifyHeader(blockchain, header, true)
|
||||||
}
|
}
|
||||||
heighter := func() uint64 {
|
heighter := func() uint64 {
|
||||||
return blockchain.CurrentBlock().NumberU64()
|
return blockchain.Stats().GetNumber()
|
||||||
}
|
}
|
||||||
inserter := func(blocks types.Blocks) (int, error) {
|
inserter := func(blocks types.Blocks) (int, error) {
|
||||||
// If fast sync is running, deny importing weird blocks
|
// If fast sync is running, deny importing weird blocks
|
||||||
|
|
@ -647,8 +647,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
||||||
// Schedule a sync if above ours. Note, this will not fire a sync for a gap of
|
// Schedule a sync if above ours. Note, this will not fire a sync for a gap of
|
||||||
// a singe block (as the true TD is below the propagated block), however this
|
// a singe block (as the true TD is below the propagated block), however this
|
||||||
// scenario should easily be covered by the fetcher.
|
// scenario should easily be covered by the fetcher.
|
||||||
currentBlock := pm.blockchain.CurrentBlock()
|
currentTd := pm.blockchain.Stats().GetTotalDifficulty()
|
||||||
if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())) > 0 {
|
if trueTD.Cmp(currentTd) > 0 {
|
||||||
go pm.synchronise(p)
|
go pm.synchronise(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
eth/sync.go
10
eth/sync.go
|
|
@ -167,8 +167,8 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Make sure the peer's TD is higher than our own
|
// Make sure the peer's TD is higher than our own
|
||||||
currentBlock := pm.blockchain.CurrentBlock()
|
currentNumber, currentFastNumber := pm.blockchain.Stats().GetNumbers()
|
||||||
td := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
|
td := pm.blockchain.Stats().GetTotalDifficulty()
|
||||||
|
|
||||||
pHead, pTd := peer.Head()
|
pHead, pTd := peer.Head()
|
||||||
if pTd.Cmp(td) <= 0 {
|
if pTd.Cmp(td) <= 0 {
|
||||||
|
|
@ -179,7 +179,7 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
|
||||||
if atomic.LoadUint32(&pm.fastSync) == 1 {
|
if atomic.LoadUint32(&pm.fastSync) == 1 {
|
||||||
// Fast sync was explicitly requested, and explicitly granted
|
// Fast sync was explicitly requested, and explicitly granted
|
||||||
mode = downloader.FastSync
|
mode = downloader.FastSync
|
||||||
} else if currentBlock.NumberU64() == 0 && pm.blockchain.CurrentFastBlock().NumberU64() > 0 {
|
} else if currentNumber == 0 && currentFastNumber > 0 {
|
||||||
// The database seems empty as the current block is the genesis. Yet the fast
|
// The database seems empty as the current block is the genesis. Yet the fast
|
||||||
// block is ahead, so fast sync was enabled for this node at a certain point.
|
// block is ahead, so fast sync was enabled for this node at a certain point.
|
||||||
// The only scenario where this can happen is if the user manually (or via a
|
// The only scenario where this can happen is if the user manually (or via a
|
||||||
|
|
@ -197,13 +197,13 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
|
||||||
atomic.StoreUint32(&pm.fastSync, 0)
|
atomic.StoreUint32(&pm.fastSync, 0)
|
||||||
}
|
}
|
||||||
atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done
|
atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done
|
||||||
if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 {
|
if pm.blockchain.Stats().GetNumber() > 0 {
|
||||||
// We've completed a sync cycle, notify all peers of new state. This path is
|
// We've completed a sync cycle, notify all peers of new state. This path is
|
||||||
// essential in star-topology networks where a gateway node needs to notify
|
// essential in star-topology networks where a gateway node needs to notify
|
||||||
// all its out-of-date peers of the availability of a new block. This failure
|
// all its out-of-date peers of the availability of a new block. This failure
|
||||||
// scenario will most often crop up in private and hackathon networks with
|
// scenario will most often crop up in private and hackathon networks with
|
||||||
// degenerate connectivity, but it should be healthy for the mainnet too to
|
// degenerate connectivity, but it should be healthy for the mainnet too to
|
||||||
// more reliably update peers or the local TD state.
|
// more reliably update peers or the local TD state.
|
||||||
go pm.BroadcastBlock(head, false)
|
go pm.BroadcastBlock(pm.blockchain.CurrentBlock(), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue