X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=database%2Fcache.go;h=a24ac8a7c7cf5dd3ea159c0789795b2dfa992d59;hb=fcabd65126a77e94ad23387f91b018255aeeb5c8;hp=7668d9c8e1dbe88c75e707912c77cbf0983d8a68;hpb=418514c6c8d60e61c57c171178a3d84596c6d4fe;p=bytom%2Fvapor.git diff --git a/database/cache.go b/database/cache.go index 7668d9c8..a24ac8a7 100644 --- a/database/cache.go +++ b/database/cache.go @@ -1,7 +1,6 @@ package database import ( - "fmt" "strconv" "github.com/golang/groupcache/singleflight" @@ -13,58 +12,64 @@ import ( ) const ( - maxCachedBlockHeaders = 1000 - maxCachedBlockTransactions = 1000 - maxCachedVoteResults = 144 // int(60 * 60 * 24 * 1000 / consensus.BlockTimeInterval / consensus.RoundVoteBlockNums) + maxCachedBlockHeaders = 4096 + maxCachedBlockTransactions = 1024 + maxCachedBlockHashes = 8192 + maxCachedMainChainHashes = 8192 + maxCachedConsensusResults = 128 ) -type fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error) +type fillBlockHeaderFn func(hash *bc.Hash) (*types.BlockHeader, error) type fillBlockTransactionsFn func(hash *bc.Hash) ([]*types.Tx, error) -type fillVoteResultFn func(seq uint64) (*state.VoteResult, error) - -func newBlockCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn, fillVoteResult fillVoteResultFn) blockCache { - return blockCache{ - lruBlockHeaders: common.NewCache(maxCachedBlockHeaders), - lruBlockTxs: common.NewCache(maxCachedBlockTransactions), - lruVoteResults: common.NewCache(maxCachedVoteResults), +type fillBlockHashesFn func(height uint64) ([]*bc.Hash, error) +type fillMainChainHashFn func(height uint64) (*bc.Hash, error) +type fillConsensusResultFn func(seq uint64) (*state.ConsensusResult, error) + +func newCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn, fillBlockHashes fillBlockHashesFn, fillMainChainHash fillMainChainHashFn, fillConsensusResult fillConsensusResultFn) cache { + return cache{ + lruBlockHeaders: common.NewCache(maxCachedBlockHeaders), + lruBlockTxs: common.NewCache(maxCachedBlockTransactions), + lruBlockHashes: common.NewCache(maxCachedBlockHashes), + lruMainChainHashes: common.NewCache(maxCachedMainChainHashes), + lruConsensusResults: common.NewCache(maxCachedConsensusResults), fillBlockHeaderFn: fillBlockHeader, fillBlockTransactionFn: fillBlockTxs, - fillVoteResultFn: fillVoteResult, + fillBlockHashesFn: fillBlockHashes, + fillMainChainHashFn: fillMainChainHash, + fillConsensusResultFn: fillConsensusResult, } } -type blockCache struct { - lruBlockHeaders *common.Cache - lruBlockTxs *common.Cache - lruVoteResults *common.Cache +type cache struct { + lruBlockHeaders *common.Cache + lruBlockTxs *common.Cache + lruBlockHashes *common.Cache + lruMainChainHashes *common.Cache + lruConsensusResults *common.Cache - fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error) + fillBlockHeaderFn func(hash *bc.Hash) (*types.BlockHeader, error) fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error) - fillVoteResultFn func(seq uint64) (*state.VoteResult, error) + fillBlockHashesFn func(uint64) ([]*bc.Hash, error) + fillMainChainHashFn func(uint64) (*bc.Hash, error) + fillConsensusResultFn func(seq uint64) (*state.ConsensusResult, error) - singleBlockHeader singleflight.Group - singleBlockTxs singleflight.Group - singleVoteResult singleflight.Group + sf singleflight.Group } -func (c *blockCache) lookupBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) { - if bH, ok := c.getBlockHeader(hash); ok { - return bH, nil +func (c *cache) lookupBlockHeader(hash *bc.Hash) (*types.BlockHeader, error) { + if data, ok := c.lruBlockHeaders.Get(*hash); ok { + return data.(*types.BlockHeader), nil } - blockHeader, err := c.singleBlockHeader.Do(hash.String(), func() (interface{}, error) { - bH, err := c.fillBlockHeaderFn(hash, height) + blockHeader, err := c.sf.Do("BlockHeader:"+hash.String(), func() (interface{}, error) { + blockHeader, err := c.fillBlockHeaderFn(hash) if err != nil { return nil, err } - if bH == nil { - return nil, fmt.Errorf("There are no blockHeader with given hash %s", hash.String()) - } - - c.addBlockHeader(bH) - return bH, nil + c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader) + return blockHeader, nil }) if err != nil { return nil, err @@ -72,87 +77,101 @@ func (c *blockCache) lookupBlockHeader(hash *bc.Hash, height uint64) (*types.Blo return blockHeader.(*types.BlockHeader), nil } -func (c *blockCache) lookupBlockTxs(hash *bc.Hash) ([]*types.Tx, error) { - if bTxs, ok := c.getBlockTransactions(hash); ok { - return bTxs, nil +func (c *cache) lookupBlockTxs(hash *bc.Hash) ([]*types.Tx, error) { + if data, ok := c.lruBlockTxs.Get(*hash); ok { + return data.([]*types.Tx), nil } - blockTransactions, err := c.singleBlockTxs.Do(hash.String(), func() (interface{}, error) { - bTxs, err := c.fillBlockTransactionFn(hash) + blockTxs, err := c.sf.Do("BlockTxs:"+hash.String(), func() (interface{}, error) { + blockTxs, err := c.fillBlockTransactionFn(hash) if err != nil { return nil, err } - if bTxs == nil { - return nil, fmt.Errorf("There are no block transactions with given hash %s", hash.String()) - } - - c.addBlockTxs(*hash, bTxs) - return bTxs, nil + c.lruBlockTxs.Add(*hash, blockTxs) + return blockTxs, nil }) if err != nil { return nil, err } - return blockTransactions.([]*types.Tx), nil + return blockTxs.([]*types.Tx), nil } -func (c *blockCache) lookupVoteResult(seq uint64) (*state.VoteResult, error) { - if vr, ok := c.getVoteResult(seq); ok { - return vr.Fork(), nil +func (c *cache) lookupConsensusResult(seq uint64) (*state.ConsensusResult, error) { + if data, ok := c.lruConsensusResults.Get(seq); ok { + return data.(*state.ConsensusResult).Fork(), nil } seqStr := strconv.FormatUint(seq, 10) - voteResult, err := c.singleVoteResult.Do(seqStr, func() (interface{}, error) { - v, err := c.fillVoteResultFn(seq) + consensusResult, err := c.sf.Do("ConsensusResult:"+seqStr, func() (interface{}, error) { + consensusResult, err := c.fillConsensusResultFn(seq) if err != nil { return nil, err } - if v == nil { - return nil, fmt.Errorf("There are no vote result with given seq %s", seqStr) + c.lruConsensusResults.Add(consensusResult.Seq, consensusResult) + return consensusResult, nil + }) + if err != nil { + return nil, err + } + return consensusResult.(*state.ConsensusResult).Fork(), nil +} + +func (c *cache) lookupMainChainHash(height uint64) (*bc.Hash, error) { + if hash, ok := c.lruMainChainHashes.Get(height); ok { + return hash.(*bc.Hash), nil + } + + heightStr := strconv.FormatUint(height, 10) + hash, err := c.sf.Do("BlockHashByHeight:"+heightStr, func() (interface{}, error) { + hash, err := c.fillMainChainHashFn(height) + if err != nil { + return nil, err } - c.addVoteResult(v) - return v, nil + c.lruMainChainHashes.Add(height, hash) + return hash, nil }) if err != nil { return nil, err } - return voteResult.(*state.VoteResult).Fork(), nil + return hash.(*bc.Hash), nil } -func (c *blockCache) getBlockHeader(hash *bc.Hash) (*types.BlockHeader, bool) { - blockHeader, ok := c.lruBlockHeaders.Get(*hash) - if blockHeader == nil { - return nil, ok +func (c *cache) lookupBlockHashesByHeight(height uint64) ([]*bc.Hash, error) { + if hashes, ok := c.lruBlockHashes.Get(height); ok { + return hashes.([]*bc.Hash), nil } - return blockHeader.(*types.BlockHeader), ok -} -func (c *blockCache) getBlockTransactions(hash *bc.Hash) ([]*types.Tx, bool) { - txs, ok := c.lruBlockTxs.Get(*hash) - if txs == nil { - return nil, ok + heightStr := strconv.FormatUint(height, 10) + hashes, err := c.sf.Do("BlockHashesByHeight:"+heightStr, func() (interface{}, error) { + hashes, err := c.fillBlockHashesFn(height) + if err != nil { + return nil, err + } + + c.lruBlockHashes.Add(height, hashes) + return hashes, nil + }) + if err != nil { + return nil, err } - return txs.([]*types.Tx), ok + return hashes.([]*bc.Hash), nil } -func (c *blockCache) getVoteResult(seq uint64) (*state.VoteResult, bool) { - voteResult, ok := c.lruVoteResults.Get(seq) - if voteResult == nil { - return nil, ok - } - return voteResult.(*state.VoteResult), ok +func (c *cache) removeBlockHeader(blockHeader *types.BlockHeader) { + c.lruBlockHeaders.Remove(blockHeader.Hash()) } -func (c *blockCache) addBlockHeader(blockHeader *types.BlockHeader) { - c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader) +func (c *cache) removeBlockHashes(height uint64) { + c.lruBlockHashes.Remove(height) } -func (c *blockCache) addBlockTxs(hash bc.Hash, txs []*types.Tx) { - c.lruBlockTxs.Add(hash, txs) +func (c *cache) removeMainChainHash(height uint64) { + c.lruMainChainHashes.Remove(height) } -func (c *blockCache) addVoteResult(voteResult *state.VoteResult) { - c.lruVoteResults.Add(voteResult.Seq, voteResult) +func (c *cache) removeConsensusResult(consensusResult *state.ConsensusResult) { + c.lruConsensusResults.Remove(consensusResult.Seq) }