6 "github.com/golang/groupcache/singleflight"
8 "github.com/bytom/vapor/common"
9 "github.com/bytom/vapor/protocol/bc"
10 "github.com/bytom/vapor/protocol/bc/types"
11 "github.com/bytom/vapor/protocol/state"
15 maxCachedBlockHeaders = 4096
16 maxCachedBlockTransactions = 1024
17 maxCachedBlockHashes = 8192
18 maxCachedMainChainHashes = 8192
19 maxCachedConsensusResults = 128
22 type fillBlockHeaderFn func(hash *bc.Hash) (*types.BlockHeader, error)
23 type fillBlockTransactionsFn func(hash *bc.Hash) ([]*types.Tx, error)
24 type fillBlockHashesFn func(height uint64) ([]*bc.Hash, error)
25 type fillMainChainHashFn func(height uint64) (*bc.Hash, error)
26 type fillConsensusResultFn func(seq uint64) (*state.ConsensusResult, error)
28 func newCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn, fillBlockHashes fillBlockHashesFn, fillMainChainHash fillMainChainHashFn, fillConsensusResult fillConsensusResultFn) *cache {
30 lruBlockHeaders: common.NewCache(maxCachedBlockHeaders),
31 lruBlockTxs: common.NewCache(maxCachedBlockTransactions),
32 lruBlockHashes: common.NewCache(maxCachedBlockHashes),
33 lruMainChainHashes: common.NewCache(maxCachedMainChainHashes),
34 lruConsensusResults: common.NewCache(maxCachedConsensusResults),
36 fillBlockHeaderFn: fillBlockHeader,
37 fillBlockTransactionFn: fillBlockTxs,
38 fillBlockHashesFn: fillBlockHashes,
39 fillMainChainHashFn: fillMainChainHash,
40 fillConsensusResultFn: fillConsensusResult,
45 lruBlockHeaders *common.Cache
46 lruBlockTxs *common.Cache
47 lruBlockHashes *common.Cache
48 lruMainChainHashes *common.Cache
49 lruConsensusResults *common.Cache
51 fillBlockHeaderFn func(hash *bc.Hash) (*types.BlockHeader, error)
52 fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error)
53 fillBlockHashesFn func(uint64) ([]*bc.Hash, error)
54 fillMainChainHashFn func(uint64) (*bc.Hash, error)
55 fillConsensusResultFn func(seq uint64) (*state.ConsensusResult, error)
60 func (c *cache) lookupBlockHeader(hash *bc.Hash) (*types.BlockHeader, error) {
61 if data, ok := c.lruBlockHeaders.Get(*hash); ok {
62 return data.(*types.BlockHeader), nil
65 blockHeader, err := c.sf.Do("BlockHeader:"+hash.String(), func() (interface{}, error) {
66 blockHeader, err := c.fillBlockHeaderFn(hash)
71 c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader)
72 return blockHeader, nil
77 return blockHeader.(*types.BlockHeader), nil
80 func (c *cache) lookupBlockTxs(hash *bc.Hash) ([]*types.Tx, error) {
81 if data, ok := c.lruBlockTxs.Get(*hash); ok {
82 return data.([]*types.Tx), nil
85 blockTxs, err := c.sf.Do("BlockTxs:"+hash.String(), func() (interface{}, error) {
86 blockTxs, err := c.fillBlockTransactionFn(hash)
91 c.lruBlockTxs.Add(*hash, blockTxs)
97 return blockTxs.([]*types.Tx), nil
100 func (c *cache) lookupConsensusResult(seq uint64) (*state.ConsensusResult, error) {
101 if data, ok := c.lruConsensusResults.Get(seq); ok {
102 return data.(*state.ConsensusResult).Fork(), nil
105 seqStr := strconv.FormatUint(seq, 10)
106 consensusResult, err := c.sf.Do("ConsensusResult:"+seqStr, func() (interface{}, error) {
107 consensusResult, err := c.fillConsensusResultFn(seq)
112 c.lruConsensusResults.Add(consensusResult.Seq, consensusResult)
113 return consensusResult, nil
118 return consensusResult.(*state.ConsensusResult).Fork(), nil
121 func (c *cache) lookupMainChainHash(height uint64) (*bc.Hash, error) {
122 if hash, ok := c.lruMainChainHashes.Get(height); ok {
123 return hash.(*bc.Hash), nil
126 heightStr := strconv.FormatUint(height, 10)
127 hash, err := c.sf.Do("BlockHashByHeight:"+heightStr, func() (interface{}, error) {
128 hash, err := c.fillMainChainHashFn(height)
133 c.lruMainChainHashes.Add(height, hash)
139 return hash.(*bc.Hash), nil
142 func (c *cache) lookupBlockHashesByHeight(height uint64) ([]*bc.Hash, error) {
143 if hashes, ok := c.lruBlockHashes.Get(height); ok {
144 return hashes.([]*bc.Hash), nil
147 heightStr := strconv.FormatUint(height, 10)
148 hashes, err := c.sf.Do("BlockHashesByHeight:"+heightStr, func() (interface{}, error) {
149 hashes, err := c.fillBlockHashesFn(height)
154 c.lruBlockHashes.Add(height, hashes)
160 return hashes.([]*bc.Hash), nil
163 func (c *cache) removeBlockHeader(blockHeader *types.BlockHeader) {
164 c.lruBlockHeaders.Remove(blockHeader.Hash())
167 func (c *cache) removeBlockHashes(height uint64) {
168 c.lruBlockHashes.Remove(height)
171 func (c *cache) removeMainChainHash(height uint64) {
172 c.lruMainChainHashes.Remove(height)
175 func (c *cache) removeConsensusResult(consensusResult *state.ConsensusResult) {
176 c.lruConsensusResults.Remove(consensusResult.Seq)