6 "github.com/golang/groupcache/singleflight"
8 "github.com/vapor/common"
9 "github.com/vapor/protocol/bc"
10 "github.com/vapor/protocol/bc/types"
14 maxCachedBlockHeaders = 1000
15 maxCachedBlockTransactions = 1000
18 type fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
19 type fillBlockTransactionsFn func(hash *bc.Hash) ([]*types.Tx, error)
21 func newBlockCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn) blockCache {
23 lruBlockHeaders: common.NewCache(maxCachedBlockHeaders),
24 lruBlockTxs: common.NewCache(maxCachedBlockTransactions),
26 fillBlockHeaderFn: fillBlockHeader,
27 fillBlockTransactionFn: fillBlockTxs,
31 type blockCache struct {
32 lruBlockHeaders *common.Cache
33 lruBlockTxs *common.Cache
35 fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
36 fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error)
38 singleBlockHeader singleflight.Group
39 singleBlockTxs singleflight.Group
42 func (c *blockCache) lookupBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
43 if bH, ok := c.getBlockHeader(hash); ok {
47 blockHeader, err := c.singleBlockHeader.Do(hash.String(), func() (interface{}, error) {
48 bH, err := c.fillBlockHeaderFn(hash, height)
54 return nil, fmt.Errorf("There are no blockHeader with given hash %s", hash.String())
63 return blockHeader.(*types.BlockHeader), nil
66 func (c *blockCache) lookupBlockTxs(hash *bc.Hash) ([]*types.Tx, error) {
67 if bTxs, ok := c.getBlockTransactions(hash); ok {
71 blockTransactions, err := c.singleBlockTxs.Do(hash.String(), func() (interface{}, error) {
72 bTxs, err := c.fillBlockTransactionFn(hash)
78 return nil, fmt.Errorf("There are no block transactions with given hash %s", hash.String())
81 c.addBlockTxs(*hash, bTxs)
87 return blockTransactions.([]*types.Tx), nil
90 func (c *blockCache) getBlockHeader(hash *bc.Hash) (*types.BlockHeader, bool) {
91 blockHeader, ok := c.lruBlockHeaders.Get(*hash)
92 if blockHeader == nil {
95 return blockHeader.(*types.BlockHeader), ok
98 func (c *blockCache) getBlockTransactions(hash *bc.Hash) ([]*types.Tx, bool) {
99 txs, ok := c.lruBlockTxs.Get(*hash)
103 return txs.([]*types.Tx), ok
106 func (c *blockCache) addBlockHeader(blockHeader *types.BlockHeader) {
107 c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader)
110 func (c *blockCache) addBlockTxs(hash bc.Hash, txs []*types.Tx) {
111 c.lruBlockTxs.Add(hash, txs)