OSDN Git Service

embed vote result cache in blockCache
authorChengcheng Zhang <943420582@qq.com>
Mon, 17 Jun 2019 03:10:24 +0000 (11:10 +0800)
committerChengcheng Zhang <943420582@qq.com>
Mon, 17 Jun 2019 03:10:24 +0000 (11:10 +0800)
database/cache.go
database/cache_test.go
database/store.go

index 97e3b7d..53d3588 100644 (file)
@@ -3,9 +3,7 @@ package database
 import (
        "fmt"
        "strconv"
-       "sync"
 
-       "github.com/golang/groupcache/lru"
        "github.com/golang/groupcache/singleflight"
 
        "github.com/vapor/common"
@@ -22,26 +20,32 @@ const (
 
 type fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*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) blockCache {
+func newBlockCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn, fillVoteResult fillVoteResultFn) blockCache {
        return blockCache{
                lruBlockHeaders: common.NewCache(maxCachedBlockHeaders),
                lruBlockTxs:     common.NewCache(maxCachedBlockTransactions),
+               lruVoteResults:  common.NewCache(maxCachedVoteResults),
 
                fillBlockHeaderFn:      fillBlockHeader,
                fillBlockTransactionFn: fillBlockTxs,
+               fillVoteResultFn:       fillVoteResult,
        }
 }
 
 type blockCache struct {
        lruBlockHeaders *common.Cache
        lruBlockTxs     *common.Cache
+       lruVoteResults  *common.Cache
 
        fillBlockHeaderFn      func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
        fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error)
+       fillVoteResultFn       func(seq uint64) (*state.VoteResult, error)
 
        singleBlockHeader singleflight.Group
        singleBlockTxs    singleflight.Group
+       singleVoteResult  singleflight.Group
 }
 
 func (c *blockCache) lookupBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
@@ -92,52 +96,14 @@ func (c *blockCache) lookupBlockTxs(hash *bc.Hash) ([]*types.Tx, error) {
        return blockTransactions.([]*types.Tx), nil
 }
 
-func (c *blockCache) getBlockHeader(hash *bc.Hash) (*types.BlockHeader, bool) {
-       blockHeader, ok := c.lruBlockHeaders.Get(*hash)
-       if blockHeader == nil {
-               return nil, ok
-       }
-       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
-       }
-       return txs.([]*types.Tx), ok
-}
-
-func (c *blockCache) addBlockHeader(blockHeader *types.BlockHeader) {
-       c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader)
-}
-
-func (c *blockCache) addBlockTxs(hash bc.Hash, txs []*types.Tx) {
-       c.lruBlockTxs.Add(hash, txs)
-}
-
-func newVoteResultCache(fillFn func(seq uint64) (*state.VoteResult, error)) voteResultCache {
-       return voteResultCache{
-               lru:    lru.New(maxCachedVoteResults),
-               fillFn: fillFn,
-       }
-}
-
-type voteResultCache struct {
-       mu     sync.Mutex
-       lru    *lru.Cache
-       fillFn func(seq uint64) (*state.VoteResult, error)
-       single singleflight.Group
-}
-
-func (vrc *voteResultCache) lookup(seq uint64) (*state.VoteResult, error) {
-       if voteResult, ok := vrc.get(seq); ok {
-               return voteResult, nil
+func (c *blockCache) lookupVoteResult(seq uint64) (*state.VoteResult, error) {
+       if vr, ok := c.getVoteResult(seq); ok {
+               return vr, nil
        }
 
        seqStr := strconv.FormatUint(seq, 10)
-       voteResult, err := vrc.single.Do(seqStr, func() (interface{}, error) {
-               v, err := vrc.fillFn(seq)
+       voteResult, err := c.singleVoteResult.Do(seqStr, func() (interface{}, error) {
+               v, err := c.fillVoteResultFn(seq)
                if err != nil {
                        return nil, err
                }
@@ -146,7 +112,7 @@ func (vrc *voteResultCache) lookup(seq uint64) (*state.VoteResult, error) {
                        return nil, fmt.Errorf("There are no vote result with given seq %s", seqStr)
                }
 
-               vrc.add(v)
+               c.addVoteResult(v)
                return v, nil
        })
        if err != nil {
@@ -155,18 +121,52 @@ func (vrc *voteResultCache) lookup(seq uint64) (*state.VoteResult, error) {
        return voteResult.(*state.VoteResult), nil
 }
 
-func (vrc *voteResultCache) get(seq uint64) (*state.VoteResult, bool) {
-       vrc.mu.Lock()
-       voteResult, ok := vrc.lru.Get(seq)
-       vrc.mu.Unlock()
+func (c *blockCache) getBlockHeader(hash *bc.Hash) (*types.BlockHeader, bool) {
+       blockHeader, ok := c.lruBlockHeaders.Get(*hash)
+       if blockHeader == nil {
+               return nil, ok
+       }
+       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
+       }
+       return txs.([]*types.Tx), ok
+}
+
+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 (vrc *voteResultCache) add(voteResult *state.VoteResult) {
-       vrc.mu.Lock()
-       vrc.lru.Add(voteResult.Seq, voteResult)
-       vrc.mu.Unlock()
+func (c *blockCache) addBlockHeader(blockHeader *types.BlockHeader) {
+       c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader)
 }
+
+func (c *blockCache) addBlockTxs(hash bc.Hash, txs []*types.Tx) {
+       c.lruBlockTxs.Add(hash, txs)
+}
+
+func (c *blockCache) addVoteResult(voteResult *state.VoteResult) {
+       c.lruVoteResults.Add(voteResult.Seq, voteResult)
+}
+
+// func newVoteResultCache(fillFn func(seq uint64) (*state.VoteResult, error)) voteResultCache {
+//     return voteResultCache{
+//             lru:    lru.New(maxCachedVoteResults),
+//             fillFn: fillFn,
+//     }
+// }
+
+// type voteResultCache struct {
+//     mu     sync.Mutex
+//     lru    *lru.Cache
+//     fillFn func(seq uint64) (*state.VoteResult, error)
+//     single singleflight.Group
+// }
index 9b1629b..9e71dc2 100644 (file)
@@ -16,11 +16,21 @@ func TestBlockCache(t *testing.T) {
                        },
                }
        }
+       newVoteResult := func(seq uint64) *state.VoteResult {
+               return &state.VoteResult{
+                       Seq: seq,
+               }
+       }
        blocks := make(map[bc.Hash]*types.Block)
        for i := 0; i < maxCachedBlockHeaders+10; i++ {
                block := newBlock(uint64(i))
                blocks[block.Hash()] = block
        }
+       voteResults := make(map[uint64]*state.VoteResult)
+       for i := 0; i < maxCachedVoteResults+10; i++ {
+               voteResult := newVoteResult(uint64(i))
+               voteResults[voteResult.Seq] = voteResult
+       }
 
        fillBlockHeaderFn := func(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
                return &blocks[*hash].BlockHeader, nil
@@ -30,7 +40,11 @@ func TestBlockCache(t *testing.T) {
                return blocks[*hash].Transactions, nil
        }
 
-       cache := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn)
+       fillVoteResultFn := func(seq uint64) (*state.VoteResult, error) {
+               return voteResults[seq], nil
+       }
+
+       cache := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn, fillVoteResultFn)
 
        for i := 0; i < maxCachedBlockHeaders+10; i++ {
                block := newBlock(uint64(i))
@@ -53,39 +67,22 @@ func TestBlockCache(t *testing.T) {
                        t.Fatalf("can't find new block")
                }
        }
-}
-
-func TestVoteResultCache(t *testing.T) {
-       newVoteResult := func(seq uint64) *state.VoteResult {
-               return &state.VoteResult{
-                       Seq: seq,
-               }
-       }
-       voteResults := make(map[uint64]*state.VoteResult)
-       for i := 0; i < maxCachedVoteResults+10; i++ {
-               voteResult := newVoteResult(uint64(i))
-               voteResults[voteResult.Seq] = voteResult
-       }
-
-       cache := newVoteResultCache(func(seq uint64) (*state.VoteResult, error) {
-               return voteResults[seq], nil
-       })
 
        for i := 0; i < maxCachedVoteResults+10; i++ {
                voteResult := newVoteResult(uint64(i))
-               cache.lookup(voteResult.Seq)
+               cache.lookupVoteResult(voteResult.Seq)
        }
 
        for i := 0; i < 10; i++ {
                voteResult := newVoteResult(uint64(i))
-               if v, _ := cache.get(voteResult.Seq); v != nil {
+               if v, _ := cache.getVoteResult(voteResult.Seq); v != nil {
                        t.Fatalf("find old vote result")
                }
        }
 
        for i := 10; i < maxCachedVoteResults+10; i++ {
                voteResult := newVoteResult(uint64(i))
-               if v, _ := cache.get(voteResult.Seq); v == nil {
+               if v, _ := cache.getVoteResult(voteResult.Seq); v == nil {
                        t.Fatalf("can't find new vote result")
                }
        }
index bbc55f8..300a22a 100644 (file)
@@ -44,9 +44,8 @@ func loadBlockStoreStateJSON(db dbm.DB) *protocol.BlockStoreState {
 // It satisfies the interface protocol.Store, and provides additional
 // methods for querying current data.
 type Store struct {
-       db  dbm.DB
-       bc  blockCache
-       vrc voteResultCache
+       db     dbm.DB
+       bCache blockCache
 }
 
 func calcBlockHeaderKey(height uint64, hash *bc.Hash) []byte {
@@ -120,14 +119,13 @@ func NewStore(db dbm.DB) *Store {
        fillBlockTxsFn := func(hash *bc.Hash) ([]*types.Tx, error) {
                return GetBlockTransactions(db, hash)
        }
-       bc := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn)
-       vrc := newVoteResultCache(func(seq uint64) (*state.VoteResult, error) {
+       fillVoteResultFn := func(seq uint64) (*state.VoteResult, error) {
                return GetVoteResult(db, seq)
-       })
+       }
+       bc := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn, fillVoteResultFn)
        return &Store{
-               db:  db,
-               bc:  bc,
-               vrc: vrc,
+               db:     db,
+               bCache: bc,
        }
 }
 
@@ -138,7 +136,7 @@ func (s *Store) GetUtxo(hash *bc.Hash) (*storage.UtxoEntry, error) {
 
 // BlockExist check if the block is stored in disk
 func (s *Store) BlockExist(hash *bc.Hash, height uint64) bool {
-       blockHeader, err := s.bc.lookupBlockHeader(hash, height)
+       blockHeader, err := s.bCache.lookupBlockHeader(hash, height)
        return err == nil && blockHeader != nil
 }
 
@@ -162,7 +160,7 @@ func (s *Store) GetBlock(hash *bc.Hash, height uint64) (*types.Block, error) {
 
 // GetBlockHeader return the BlockHeader by given hash
 func (s *Store) GetBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
-       blockHeader, err := s.bc.lookupBlockHeader(hash, height)
+       blockHeader, err := s.bCache.lookupBlockHeader(hash, height)
        if err != nil {
                return nil, err
        }
@@ -171,7 +169,7 @@ func (s *Store) GetBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader
 
 // GetBlockTransactions return the Block transactions by given hash
 func (s *Store) GetBlockTransactions(hash *bc.Hash) ([]*types.Tx, error) {
-       txs, err := s.bc.lookupBlockTxs(hash)
+       txs, err := s.bCache.lookupBlockTxs(hash)
        if err != nil {
                return nil, err
        }
@@ -204,7 +202,7 @@ func (s *Store) GetStoreStatus() *protocol.BlockStoreState {
 
 // GetVoteResult retrive the voting result in specified vote sequence
 func (s *Store) GetVoteResult(seq uint64) (*state.VoteResult, error) {
-       return s.vrc.lookup(seq)
+       return s.bCache.lookupVoteResult(seq)
 }
 
 func (s *Store) LoadBlockIndex(stateBestHeight uint64) (*state.BlockIndex, error) {