OSDN Git Service

fix conflicts
authorChengcheng Zhang <943420582@qq.com>
Sat, 15 Jun 2019 10:21:56 +0000 (18:21 +0800)
committerChengcheng Zhang <943420582@qq.com>
Sat, 15 Jun 2019 10:21:56 +0000 (18:21 +0800)
1  2 
database/cache.go
database/cache_test.go
database/store.go

@@@ -2,26 -2,29 +2,34 @@@ package databas
  
  import (
        "fmt"
 +      "strconv"
 +      "sync"
  
 +      "github.com/golang/groupcache/lru"
        "github.com/golang/groupcache/singleflight"
  
+       "github.com/vapor/common"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
 +      "github.com/vapor/protocol/state"
  )
  
  const (
-       maxCachedBlocks      = 30
-       maxCachedVoteResults = 144 // int(60 * 60 * 24 * 1000 / consensus.BlockTimeInterval / consensus.RoundVoteBlockNums)
+       maxCachedBlockHeaders      = 1000
+       maxCachedBlockTransactions = 1000
++      maxCachedVoteResults       = 144 // int(60 * 60 * 24 * 1000 / consensus.BlockTimeInterval / consensus.RoundVoteBlockNums)
  )
  
- func newBlockCache(fillFn func(hash *bc.Hash) (*types.Block, error)) blockCache {
+ type fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
+ type fillBlockTransactionsFn func(hash *bc.Hash) ([]*types.Tx, error)
+ func newBlockCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn) blockCache {
        return blockCache{
-               lru:    lru.New(maxCachedBlocks),
-               fillFn: fillFn,
+               lruBlockHeaders: common.NewCache(maxCachedBlockHeaders),
+               lruBlockTxs:     common.NewCache(maxCachedBlockTransactions),
+               fillBlockHeaderFn:      fillBlockHeader,
+               fillBlockTransactionFn: fillBlockTxs,
        }
  }
  
@@@ -53,76 -84,29 +89,84 @@@ func (c *blockCache) lookupBlockTxs(has
        if err != nil {
                return nil, err
        }
-       return block.(*types.Block), nil
+       return blockTransactions.([]*types.Tx), nil
  }
  
- func (c *blockCache) get(hash *bc.Hash) (*types.Block, bool) {
-       c.mu.Lock()
-       block, ok := c.lru.Get(*hash)
-       c.mu.Unlock()
-       if block == nil {
+ func (c *blockCache) getBlockHeader(hash *bc.Hash) (*types.BlockHeader, bool) {
+       blockHeader, ok := c.lruBlockHeaders.Get(*hash)
+       if blockHeader == nil {
                return nil, ok
        }
-       return block.(*types.Block), 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) add(block *types.Block) {
-       c.mu.Lock()
-       c.lru.Add(block.Hash(), block)
-       c.mu.Unlock()
+ 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
 +      }
 +
 +      seqStr := strconv.FormatUint(seq, 10)
 +      voteResult, err := vrc.single.Do(seqStr, func() (interface{}, error) {
 +              v, err := vrc.fillFn(seq)
 +              if err != nil {
 +                      return nil, err
 +              }
 +
 +              if v == nil {
 +                      return nil, fmt.Errorf("There are no vote result with given seq %s", seqStr)
 +              }
 +
 +              vrc.add(v)
 +              return v, nil
 +      })
 +      if err != nil {
 +              return nil, err
 +      }
 +      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()
 +      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()
 +}
Simple merge
@@@ -44,15 -44,10 +44,11 @@@ func loadBlockStoreStateJSON(db dbm.DB
  // It satisfies the interface protocol.Store, and provides additional
  // methods for querying current data.
  type Store struct {
 -      db    dbm.DB
 -      cache blockCache
 +      db  dbm.DB
 +      bc  blockCache
 +      vrc voteResultCache
  }
  
- func calcBlockKey(hash *bc.Hash) []byte {
-       return append(blockPrefix, hash.Bytes()...)
- }
  func calcBlockHeaderKey(height uint64, hash *bc.Hash) []byte {
        buf := [8]byte{}
        binary.BigEndian.PutUint64(buf[:], height)
@@@ -70,44 -69,48 +70,64 @@@ func calcVoteResultKey(seq uint64) []by
        return append(voteResultPrefix, buf[:]...)
  }
  
- // GetBlock return the block by given hash
- func GetBlock(db dbm.DB, hash *bc.Hash) (*types.Block, error) {
-       bytez := db.Get(calcBlockKey(hash))
-       if bytez == nil {
-               return nil, nil // why return err nil???
+ // GetBlockHeader return the block header by given hash and height
+ func GetBlockHeader(db dbm.DB, hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
+       block := &types.Block{}
+       binaryBlockHeader := db.Get(calcBlockHeaderKey(height, hash))
+       if binaryBlockHeader == nil {
+               return nil, nil
        }
+       if err := block.UnmarshalText(binaryBlockHeader); err != nil {
+               return nil, err
+       }
+       return &block.BlockHeader, nil
+ }
  
+ // GetBlockTransactions return the block transactions by given hash
+ func GetBlockTransactions(db dbm.DB, hash *bc.Hash) ([]*types.Tx, error) {
        block := &types.Block{}
-       err := block.UnmarshalText(bytez)
-       return block, err
+       binaryBlockTxs := db.Get(calcBlockTransactionsKey(hash))
+       if binaryBlockTxs == nil {
+               return nil, errors.New("The transactions in the block is empty")
+       }
+       if err := block.UnmarshalText(binaryBlockTxs); err != nil {
+               return nil, err
+       }
+       return block.Transactions, nil
  }
  
 +// GetVoteResult return the vote result by given sequence
 +func GetVoteResult(db dbm.DB, seq uint64) (*state.VoteResult, error) {
 +      data := db.Get(calcVoteResultKey(seq))
 +      if data == nil {
 +              return nil, protocol.ErrNotFoundVoteResult
 +      }
 +
 +      voteResult := new(state.VoteResult)
 +      if err := json.Unmarshal(data, voteResult); err != nil {
 +              return nil, errors.Wrap(err, "unmarshaling vote result")
 +      }
 +      return voteResult, nil
 +}
 +
  // NewStore creates and returns a new Store object.
  func NewStore(db dbm.DB) *Store {
-       bc := newBlockCache(func(hash *bc.Hash) (*types.Block, error) {
-               return GetBlock(db, hash)
-       })
+       fillBlockHeaderFn := func(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
+               return GetBlockHeader(db, hash, height)
+       }
 -
+       fillBlockTxsFn := func(hash *bc.Hash) ([]*types.Tx, error) {
+               return GetBlockTransactions(db, hash)
+       }
 -
 -      cache := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn)
++      bc := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn)
 +      vrc := newVoteResultCache(func(seq uint64) (*state.VoteResult, error) {
 +              return GetVoteResult(db, seq)
 +      })
        return &Store{
 -              db:    db,
 -              cache: cache,
 +              db:  db,
 +              bc:  bc,
 +              vrc: vrc,
        }
  }
  
@@@ -117,14 -120,45 +137,45 @@@ func (s *Store) GetUtxo(hash *bc.Hash) 
  }
  
  // BlockExist check if the block is stored in disk
- func (s *Store) BlockExist(hash *bc.Hash) bool {
-       block, err := s.bc.lookup(hash)
-       return err == nil && block != nil
+ func (s *Store) BlockExist(hash *bc.Hash, height uint64) bool {
 -      blockHeader, err := s.cache.lookupBlockHeader(hash, height)
++      blockHeader, err := s.bc.lookupBlockHeader(hash, height)
+       return err == nil && blockHeader != nil
  }
  
  // GetBlock return the block by given hash
- func (s *Store) GetBlock(hash *bc.Hash) (*types.Block, error) {
-       return s.bc.lookup(hash)
+ func (s *Store) GetBlock(hash *bc.Hash, height uint64) (*types.Block, error) {
+       blockHeader, err := s.GetBlockHeader(hash, height)
+       if err != nil {
+               return nil, err
+       }
+       txs, err := s.GetBlockTransactions(hash)
+       if err != nil {
+               return nil, err
+       }
+       return &types.Block{
+               BlockHeader:  *blockHeader,
+               Transactions: txs,
+       }, nil
+ }
+ // GetBlockHeader return the BlockHeader by given hash
+ func (s *Store) GetBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
 -      blockHeader, err := s.cache.lookupBlockHeader(hash, height)
++      blockHeader, err := s.bc.lookupBlockHeader(hash, height)
+       if err != nil {
+               return nil, err
+       }
+       return blockHeader, nil
+ }
+ // GetBlockTransactions return the Block transactions by given hash
+ func (s *Store) GetBlockTransactions(hash *bc.Hash) ([]*types.Tx, error) {
 -      txs, err := s.cache.lookupBlockTxs(hash)
++      txs, err := s.bc.lookupBlockTxs(hash)
+       if err != nil {
+               return nil, err
+       }
+       return txs, nil
  }
  
  // GetTransactionsUtxo will return all the utxo that related to the input txs