6 "github.com/golang/groupcache/singleflight"
8 "github.com/vapor/common"
9 "github.com/vapor/protocol/bc"
10 "github.com/vapor/protocol/bc/types"
11 "github.com/vapor/protocol/state"
15 maxCachedBlockHeaders = 4096
16 maxCachedBlockTransactions = 1024
17 maxCachedVoteResults = 128
20 type fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
21 type fillBlockTransactionsFn func(hash *bc.Hash) ([]*types.Tx, error)
22 type fillVoteResultFn func(seq uint64) (*state.VoteResult, error)
24 func newCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn, fillVoteResult fillVoteResultFn) cache {
26 lruBlockHeaders: common.NewCache(maxCachedBlockHeaders),
27 lruBlockTxs: common.NewCache(maxCachedBlockTransactions),
28 lruVoteResults: common.NewCache(maxCachedVoteResults),
30 fillBlockHeaderFn: fillBlockHeader,
31 fillBlockTransactionFn: fillBlockTxs,
32 fillVoteResultFn: fillVoteResult,
37 lruBlockHeaders *common.Cache
38 lruBlockTxs *common.Cache
39 lruVoteResults *common.Cache
41 fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
42 fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error)
43 fillVoteResultFn func(seq uint64) (*state.VoteResult, error)
48 func (c *cache) lookupBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
49 if data, ok := c.lruBlockHeaders.Get(*hash); ok {
50 return data.(*types.BlockHeader), nil
53 blockHeader, err := c.sf.Do("BlockHeader:"+hash.String(), func() (interface{}, error) {
54 blockHeader, err := c.fillBlockHeaderFn(hash, height)
59 c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader)
60 return blockHeader, nil
65 return blockHeader.(*types.BlockHeader), nil
68 func (c *cache) lookupBlockTxs(hash *bc.Hash) ([]*types.Tx, error) {
69 if data, ok := c.lruBlockTxs.Get(*hash); ok {
70 return data.([]*types.Tx), nil
73 blockTxs, err := c.sf.Do("BlockTxs:"+hash.String(), func() (interface{}, error) {
74 blockTxs, err := c.fillBlockTransactionFn(hash)
79 c.lruBlockTxs.Add(hash, blockTxs)
85 return blockTxs.([]*types.Tx), nil
88 func (c *cache) lookupVoteResult(seq uint64) (*state.VoteResult, error) {
89 if data, ok := c.lruVoteResults.Get(seq); ok {
90 return data.(*state.VoteResult).Fork(), nil
93 seqStr := strconv.FormatUint(seq, 10)
94 voteResult, err := c.sf.Do("VoteResult:"+seqStr, func() (interface{}, error) {
95 voteResult, err := c.fillVoteResultFn(seq)
100 c.lruVoteResults.Add(voteResult.Seq, voteResult)
101 return voteResult, nil
106 return voteResult.(*state.VoteResult).Fork(), nil
109 func (c *cache) removeBlockHeader(blockHeader *types.BlockHeader) {
110 c.lruBlockHeaders.Remove(blockHeader.Hash())
113 func (c *cache) removeVoteResult(voteResult *state.VoteResult) {
114 c.lruVoteResults.Remove(voteResult.Seq)