)
const (
- maxCachedBlocks = 30
maxCachedBlockHeaders = 1000
maxCachedBlockTransactons = 1000
)
-type fillBlockFn func(hash *bc.Hash, height uint64) (*types.Block, error)
type fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
type fillBlockTransactionsFn func(hash *bc.Hash) ([]*types.Tx, error)
-func newBlockCache(fillBlock fillBlockFn, fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn) blockCache {
+func newBlockCache(fillBlockHeader fillBlockHeaderFn, fillBlockTxs fillBlockTransactionsFn) blockCache {
return blockCache{
- lru: lru.New(maxCachedBlocks),
- lruBlockHeaders: lru.New(maxCachedBlockHeaders),
- lruTxs: lru.New(maxCachedBlockTransactons),
- fillFn: fillBlock,
+ lruBlockHeaders: lru.New(maxCachedBlockHeaders),
+ lruTxs: lru.New(maxCachedBlockTransactons),
+
fillBlockHeaderFn: fillBlockHeader,
fillBlockTransactionFn: fillBlockTxs,
}
}
type blockCache struct {
- mu sync.Mutex
- muHeaders sync.Mutex
- muTxs sync.Mutex
- lru *lru.Cache
- lruBlockHeaders *lru.Cache
- lruTxs *lru.Cache
- fillFn func(hash *bc.Hash, height uint64) (*types.Block, error)
- fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
- fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error)
- single singleflight.Group
- singleBlockHeader singleflight.Group
- singleBlockTxs singleflight.Group
-}
+ muHeaders sync.Mutex
+ muTxs sync.Mutex
-func (c *blockCache) lookup(hash *bc.Hash, height uint64) (*types.Block, error) {
- if b, ok := c.get(hash); ok {
- return b, nil
- }
+ lruBlockHeaders *lru.Cache
+ lruTxs *lru.Cache
- block, err := c.single.Do(hash.String(), func() (interface{}, error) {
- b, err := c.fillFn(hash, height)
- if err != nil {
- return nil, err
- }
-
- if b == nil {
- return nil, fmt.Errorf("There are no block with given hash %s", hash.String())
- }
+ fillBlockHeaderFn func(hash *bc.Hash, height uint64) (*types.BlockHeader, error)
+ fillBlockTransactionFn func(hash *bc.Hash) ([]*types.Tx, error)
- c.add(b)
- return b, nil
- })
- if err != nil {
- return nil, err
- }
- return block.(*types.Block), nil
+ singleBlockHeader singleflight.Group
+ singleBlockTxs singleflight.Group
}
func (c *blockCache) lookupBlockHeader(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
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 {
- return nil, ok
- }
- return block.(*types.Block), ok
-}
-
func (c *blockCache) getBlockHeader(hash *bc.Hash) (*types.BlockHeader, bool) {
c.muHeaders.Lock()
blockHeader, ok := c.lruBlockHeaders.Get(*hash)
return txs.([]*types.Tx), ok
}
-func (c *blockCache) add(block *types.Block) {
- c.mu.Lock()
- c.lru.Add(block.Hash(), block)
- c.mu.Unlock()
-}
-
func (c *blockCache) addHeader(blockHeader *types.BlockHeader) {
c.muHeaders.Lock()
c.lruBlockHeaders.Add(blockHeader.Hash(), blockHeader)
}
}
blocks := make(map[bc.Hash]*types.Block)
- for i := 0; i < maxCachedBlocks+10; i++ {
+ for i := 0; i < maxCachedBlockHeaders+10; i++ {
block := newBlock(uint64(i))
blocks[block.Hash()] = block
}
- cache := newBlockCache(func(hash *bc.Hash, height uint64) (*types.Block, error) {
- return blocks[*hash], nil
- })
+ fillBlockHeaderFn := func(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
+ return &blocks[*hash].BlockHeader, nil
+ }
+
+ fillBlockTxsFn := func(hash *bc.Hash) ([]*types.Tx, error) {
+ return blocks[*hash].Transactions, nil
+ }
+
+ cache := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn)
- for i := 0; i < maxCachedBlocks+10; i++ {
+ for i := 0; i < maxCachedBlockHeaders+10; i++ {
block := newBlock(uint64(i))
hash := block.Hash()
- cache.lookup(&hash, block.Height)
+ cache.lookupBlockHeader(&hash, block.Height)
}
for i := 0; i < 10; i++ {
block := newBlock(uint64(i))
hash := block.Hash()
- if b, _ := cache.get(&hash); b != nil {
+ if b, _ := cache.getBlockHeader(&hash); b != nil {
t.Fatalf("find old block")
}
}
- for i := 10; i < maxCachedBlocks+10; i++ {
+ for i := 10; i < maxCachedBlockHeaders+10; i++ {
block := newBlock(uint64(i))
hash := block.Hash()
- if b, _ := cache.get(&hash); b == nil {
+ if b, _ := cache.getBlockHeader(&hash); b == nil {
t.Fatalf("can't find new block")
}
}
return append(voteResultPrefix, buf[:]...)
}
-// GetBlock return the block by given hash and height
-func GetBlock(db dbm.DB, hash *bc.Hash, height uint64) (*types.Block, error) {
- block := &types.Block{}
- binaryBlockHeader := db.Get(calcBlockHeaderKey(height, hash))
- if binaryBlockHeader == nil {
- return nil, nil
- }
-
- binaryBlockTxs := db.Get(calcBlockTransactionsKey(hash))
- if binaryBlockTxs == nil {
- return nil, errors.New("The transactions in the block is empty")
- }
-
- if err := block.UnmarshalText(binaryBlockHeader); err != nil {
- return nil, err
- }
-
- if err := block.UnmarshalText(binaryBlockTxs); err != nil {
- return nil, err
- }
-
- return block, 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{}
// NewStore creates and returns a new Store object.
func NewStore(db dbm.DB) *Store {
- fillBlockFn := func(hash *bc.Hash, height uint64) (*types.Block, error) {
- return GetBlock(db, hash, height)
- }
-
fillBlockHeaderFn := func(hash *bc.Hash, height uint64) (*types.BlockHeader, error) {
return GetBlockHeader(db, hash, height)
}
return GetBlockTransactions(db, hash)
}
- cache := newBlockCache(fillBlockFn, fillBlockHeaderFn, fillBlockTxsFn)
+ cache := newBlockCache(fillBlockHeaderFn, fillBlockTxsFn)
return &Store{
db: db,
cache: cache,
if err != nil {
return nil, err
}
+
txs, err := s.GetBlockTransactions(hash)
if err != nil {
return nil, err