/
nodedb_cache.go
149 lines (134 loc) · 3.89 KB
/
nodedb_cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package iavl
import (
"container/list"
"sync"
"github.com/FiboChain/fbc/libs/iavl/config"
"github.com/tendermint/go-amino"
)
type NodeCache struct {
nodeCache map[string]*list.Element // Node cache.
nodeCacheSize int // Node cache size limit in elements.
nodeCacheQueue *syncList // LRU queue of cache elements. Used for deletion.
nodeCacheMutex sync.RWMutex // Mutex for node cache.
}
func newNodeCache(dbName string, cacheSize int) *NodeCache {
if dbName == "evm" {
return &NodeCache{
nodeCache: makeNodeCacheMap(cacheSize, IavlCacheInitRatio),
nodeCacheSize: cacheSize,
nodeCacheQueue: newSyncList(),
}
} else {
return &NodeCache{
nodeCache: make(map[string]*list.Element),
nodeCacheSize: cacheSize,
nodeCacheQueue: newSyncList(),
}
}
}
func makeNodeCacheMap(cacheSize int, initRatio float64) map[string]*list.Element {
if initRatio <= 0 {
return make(map[string]*list.Element)
}
if initRatio >= 1 {
return make(map[string]*list.Element, cacheSize)
}
cacheSize = int(float64(cacheSize) * initRatio)
return make(map[string]*list.Element, cacheSize)
}
// ===================================================
// ======= map[string]*list.Element implementation
// ===================================================
func (ndb *NodeCache) uncache(hash []byte) {
ndb.nodeCacheMutex.Lock()
if elem, ok := ndb.nodeCache[string(hash)]; ok {
ndb.nodeCacheQueue.Remove(elem)
delete(ndb.nodeCache, string(hash))
}
ndb.nodeCacheMutex.Unlock()
}
// Add a node to the cache and pop the least recently used node if we've
// reached the cache size limit.
func (ndb *NodeCache) cache(node *Node) {
ndb.nodeCacheMutex.Lock()
if ele, ok := ndb.nodeCache[string(node.hash)]; ok {
ndb.nodeCacheQueue.MoveToBack(ele)
} else {
elem := ndb.nodeCacheQueue.PushBack(node)
ndb.nodeCache[string(node.hash)] = elem
for ndb.nodeCacheQueue.Len() > config.DynamicConfig.GetIavlCacheSize() {
oldest := ndb.nodeCacheQueue.Front()
hash := ndb.nodeCacheQueue.Remove(oldest).(*Node).hash
delete(ndb.nodeCache, amino.BytesToStr(hash))
}
}
ndb.nodeCacheMutex.Unlock()
}
func (ndb *NodeCache) cacheWithKey(key string, node *Node) {
ndb.nodeCacheMutex.Lock()
elem := ndb.nodeCacheQueue.PushBack(node)
ndb.nodeCache[key] = elem
for ndb.nodeCacheQueue.Len() > config.DynamicConfig.GetIavlCacheSize() {
oldest := ndb.nodeCacheQueue.Front()
hash := ndb.nodeCacheQueue.Remove(oldest).(*Node).hash
delete(ndb.nodeCache, amino.BytesToStr(hash))
}
ndb.nodeCacheMutex.Unlock()
}
func (ndb *NodeCache) get(hash []byte, promoteRecentNode bool) (n *Node) {
// Check the cache.
ndb.nodeCacheMutex.RLock()
elem, ok := ndb.nodeCache[string(hash)]
if ok {
if promoteRecentNode {
// Already exists. Move to back of nodeCacheQueue.
ndb.nodeCacheQueue.MoveToBack(elem)
}
n = elem.Value.(*Node)
}
ndb.nodeCacheMutex.RUnlock()
return
}
func (ndb *NodeCache) nodeCacheLen() int {
return len(ndb.nodeCache)
}
// =========================================================
// ======= github.com/hashicorp/golang-lru implementation
// =========================================================
//func (ndb *nodeDB) cacheNode(node *Node) {
// ndb.lruNodeCache.Add(string(node.hash), node)
//}
//
//func (ndb *nodeDB) cacheNodeByCheck(node *Node) {
// if ndb.lruNodeCache.Contains(string(node.hash)) {
// return
// }
// ndb.cacheNode(node)
//}
//
//
//func (ndb *nodeDB) getNodeFromCache(hash []byte, promoteRecentNode bool) (n *Node) {
//
// var ok bool
// var res interface{}
// if promoteRecentNode {
// res, ok = ndb.lruNodeCache.Get(string(hash))
// } else {
// res, ok = ndb.lruNodeCache.Peek(string(hash))
// }
//
// if ok {
// n = res.(*Node)
// }
// return
//}
//
//
//func (ndb *nodeDB) uncacheNode(hash []byte) {
// ndb.lruNodeCache.Remove(string(hash))
//}
//
//
//func (ndb *nodeDB) nodeCacheLen() int {
// return ndb.lruNodeCache.Len()
//}