Introduce a chain state to block manager.
This commit introduces a chain state that is updated as blocks are processed into the block chain instance associated with the block manager. This has been done because btcchain is currently not safe for concurrent access and the block manager is typically quite busy processing block and inventory. This approach allows fast access to most chain information in a concurrent safe fashion.
This commit is contained in:
parent
ee19fd79e4
commit
1d674905e0
1 changed files with 40 additions and 1 deletions
|
@ -83,6 +83,20 @@ type headerNode struct {
|
||||||
sha *btcwire.ShaHash
|
sha *btcwire.ShaHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chainState tracks the state of the best chain as blocks are inserted. This
|
||||||
|
// is done because btcchain is currently not safe for concurrent access and the
|
||||||
|
// block manager is typically quite busy processing block and inventory.
|
||||||
|
// Therefore, requesting this information from chain through the block manager
|
||||||
|
// would not be anywhere near as efficient as simply updating it as each block
|
||||||
|
// is inserted and protecting it with a mutex.
|
||||||
|
type chainState struct {
|
||||||
|
sync.Mutex
|
||||||
|
newestHash *btcwire.ShaHash
|
||||||
|
newestHeight int64
|
||||||
|
pastMedianTime time.Time
|
||||||
|
pastMedianTimeErr error
|
||||||
|
}
|
||||||
|
|
||||||
// blockManager provides a concurrency safe block manager for handling all
|
// blockManager provides a concurrency safe block manager for handling all
|
||||||
// incoming blocks.
|
// incoming blocks.
|
||||||
type blockManager struct {
|
type blockManager struct {
|
||||||
|
@ -99,6 +113,7 @@ type blockManager struct {
|
||||||
processingReqs bool
|
processingReqs bool
|
||||||
syncPeer *peer
|
syncPeer *peer
|
||||||
msgChan chan interface{}
|
msgChan chan interface{}
|
||||||
|
chainState chainState
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
quit chan bool
|
quit chan bool
|
||||||
|
|
||||||
|
@ -125,6 +140,24 @@ func (b *blockManager) resetHeaderState(newestHash *btcwire.ShaHash, newestHeigh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateChainState updates the chain state associated with the block manager.
|
||||||
|
// This allows fast access to chain information since btcchain is currently not
|
||||||
|
// safe for concurrent access and the block manager is typically quite busy
|
||||||
|
// processing block and inventory.
|
||||||
|
func (b *blockManager) updateChainState(newestHash *btcwire.ShaHash, newestHeight int64) {
|
||||||
|
b.chainState.Lock()
|
||||||
|
defer b.chainState.Unlock()
|
||||||
|
|
||||||
|
b.chainState.newestHash = newestHash
|
||||||
|
b.chainState.newestHeight = newestHeight
|
||||||
|
medianTime, err := b.blockChain.CalcPastMedianTime()
|
||||||
|
if err != nil {
|
||||||
|
b.chainState.pastMedianTimeErr = err
|
||||||
|
} else {
|
||||||
|
b.chainState.pastMedianTime = medianTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// findNextHeaderCheckpoint returns the next checkpoint after the passed height.
|
// findNextHeaderCheckpoint returns the next checkpoint after the passed height.
|
||||||
// It returns nil when there is not one either because the height is already
|
// It returns nil when there is not one either because the height is already
|
||||||
// later than the final checkpoint or some other reason such as disabled
|
// later than the final checkpoint or some other reason such as disabled
|
||||||
|
@ -510,10 +543,12 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the block is not an orphan, don't keep track of the peer that
|
// When the block is not an orphan, don't keep track of the peer that
|
||||||
// sent it any longer and log information about it.
|
// sent it any longer, log information about it, and update the chain
|
||||||
|
// state.
|
||||||
if !b.blockChain.IsKnownOrphan(blockSha) {
|
if !b.blockChain.IsKnownOrphan(blockSha) {
|
||||||
delete(b.blockPeer, *blockSha)
|
delete(b.blockPeer, *blockSha)
|
||||||
b.logBlockHeight(bmsg.block)
|
b.logBlockHeight(bmsg.block)
|
||||||
|
b.updateChainState(blockSha, bmsg.block.Height())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync the db to disk.
|
// Sync the db to disk.
|
||||||
|
@ -1158,6 +1193,10 @@ func newBlockManager(s *server) (*blockManager, error) {
|
||||||
}
|
}
|
||||||
bmgrLog.Infof("Block index generation complete")
|
bmgrLog.Infof("Block index generation complete")
|
||||||
|
|
||||||
|
// Initialize the chain state now that the intial block node index has
|
||||||
|
// been generated.
|
||||||
|
bm.updateChainState(newestHash, height)
|
||||||
|
|
||||||
return &bm, nil
|
return &bm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue