blockcache: add blockcache package
This commit adds a new blockcache package along with the GetBlock method to be used along with the blockcache.
This commit is contained in:
1 parent
d771ed7616
commit
275d55c9e6
2 files changed
+258
No files matched your search
@@ -0,0 +1,70 @@
|
||||
package blockcache
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightninglabs/neutrino/cache"
|
||||
"github.com/lightninglabs/neutrino/cache/lru"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/multimutex"
|
||||
)
|
||||
|
||||
// BlockCache is an lru cache for blocks.
|
||||
type BlockCache struct {
|
||||
Cache *lru.Cache
|
||||
HashMutex *multimutex.HashMutex
|
||||
}
|
||||
|
||||
// NewBlockCache creates a new BlockCache with the given maximum capacity.
|
||||
func NewBlockCache(capacity uint64) *BlockCache {
|
||||
return &BlockCache{
|
||||
Cache: lru.NewCache(capacity),
|
||||
HashMutex: multimutex.NewHashMutex(),
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlock first checks to see if the BlockCache already contains the block
|
||||
// with the given hash. If it does then the block is fetched from the cache and
|
||||
// returned. Otherwise the getBlockImpl function is used in order to fetch the
|
||||
// new block and then it is stored in the block cache and returned.
|
||||
func (bc *BlockCache) GetBlock(hash *chainhash.Hash,
|
||||
getBlockImpl func(hash *chainhash.Hash) (*wire.MsgBlock,
|
||||
error)) (*wire.MsgBlock, error) {
|
||||
|
||||
bc.HashMutex.Lock(lntypes.Hash(*hash))
|
||||
defer bc.HashMutex.Unlock(lntypes.Hash(*hash))
|
||||
|
||||
// Create an inv vector for getting the block.
|
||||
inv := wire.NewInvVect(wire.InvTypeWitnessBlock, hash)
|
||||
|
||||
// Check if the block corresponding to the given hash is already
|
||||
// stored in the blockCache and return it if it is.
|
||||
cacheBlock, err := bc.Cache.Get(*inv)
|
||||
if err != nil && err != cache.ErrElementNotFound {
|
||||
return nil, err
|
||||
}
|
||||
if cacheBlock != nil {
|
||||
return cacheBlock.(*cache.CacheableBlock).MsgBlock(), nil
|
||||
}
|
||||
|
||||
// Fetch the block from the chain backends.
|
||||
block, err := getBlockImpl(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add the new block to blockCache. If the Cache is at its maximum
|
||||
// capacity then the LFU item will be evicted in favour of this new
|
||||
// block.
|
||||
_, err = bc.Cache.Put(
|
||||
*inv, &cache.CacheableBlock{
|
||||
Block: btcutil.NewBlock(block),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return block, nil
|
||||
}
|
||||
Reference in new issue
Block a user