OSDN Git Service

fix: waive charging storage gas for cross-chain (#162)
[bytom/vapor.git] / database / cache.go
1 package database
2
3 import (
4         "fmt"
5         "sync"
6
7         "github.com/golang/groupcache/lru"
8         "github.com/golang/groupcache/singleflight"
9
10         "github.com/vapor/protocol/bc"
11         "github.com/vapor/protocol/bc/types"
12 )
13
14 const maxCachedBlocks = 30
15
16 func newBlockCache(fillFn func(hash *bc.Hash) (*types.Block, error)) blockCache {
17         return blockCache{
18                 lru:    lru.New(maxCachedBlocks),
19                 fillFn: fillFn,
20         }
21 }
22
23 type blockCache struct {
24         mu     sync.Mutex
25         lru    *lru.Cache
26         fillFn func(hash *bc.Hash) (*types.Block, error)
27         single singleflight.Group
28 }
29
30 func (c *blockCache) lookup(hash *bc.Hash) (*types.Block, error) {
31         if b, ok := c.get(hash); ok {
32                 return b, nil
33         }
34
35         block, err := c.single.Do(hash.String(), func() (interface{}, error) {
36                 b, err := c.fillFn(hash)
37                 if err != nil {
38                         return nil, err
39                 }
40
41                 if b == nil {
42                         return nil, fmt.Errorf("There are no block with given hash %s", hash.String())
43                 }
44
45                 c.add(b)
46                 return b, nil
47         })
48         if err != nil {
49                 return nil, err
50         }
51         return block.(*types.Block), nil
52 }
53
54 func (c *blockCache) get(hash *bc.Hash) (*types.Block, bool) {
55         c.mu.Lock()
56         block, ok := c.lru.Get(*hash)
57         c.mu.Unlock()
58         if block == nil {
59                 return nil, ok
60         }
61         return block.(*types.Block), ok
62 }
63
64 func (c *blockCache) add(block *types.Block) {
65         c.mu.Lock()
66         c.lru.Add(block.Hash(), block)
67         c.mu.Unlock()
68 }