From 44ae9086b62768081aeeaf289edb6de41b2b7ed7 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 12 May 2020 17:45:17 +0300 Subject: [PATCH] core: improve and fix locking in storeBlock Getting batch, updating Prometheus metrics and pushing events doesn't require any locking: batch is a local cache batch that no one outside cares about, Prometheus metrics are not critical to be in perfect sync and events are asynchronous anyway. Native contracts also don't require any locks and they should be processed before dumping storage changes. --- pkg/core/blockchain.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 54de3f1bd..7155b7734 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -802,12 +802,6 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { } } } - bc.lock.Lock() - defer bc.lock.Unlock() - - if bc.config.SaveStorageBatch { - bc.lastBatch = cache.DAO.GetBatch() - } for i := range bc.contracts.Contracts { systemInterop := bc.newInteropContext(trigger.Application, cache, block, nil) @@ -816,14 +810,22 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { } } + if bc.config.SaveStorageBatch { + bc.lastBatch = cache.DAO.GetBatch() + } + + bc.lock.Lock() _, err := cache.Persist() if err != nil { + bc.lock.Unlock() return err } bc.topBlock.Store(block) atomic.StoreUint32(&bc.blockHeight, block.Index) - updateBlockHeightMetric(block.Index) bc.memPool.RemoveStale(bc.isTxStillRelevant, bc) + bc.lock.Unlock() + + updateBlockHeightMetric(block.Index) // Genesis block is stored when Blockchain is not yet running, so there // is no one to read this event. And it doesn't make much sense as event // anyway.