mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
peer: rename noncemap to noncecache
It's a cache, but it is implemented with a map.
This commit is contained in:
parent
70dd37e644
commit
b9225dcb66
@ -12,27 +12,27 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// lruNonceMap provides a concurrency safe map that is limited to a maximum
|
||||
// lruNonceCache provides a concurrency safe cache that is limited to a maximum
|
||||
// number of items with eviction for the oldest entry when the limit is
|
||||
// exceeded.
|
||||
type lruNonceMap struct {
|
||||
mtx sync.Mutex
|
||||
nonceMap map[uint64]*list.Element // nearly O(1) lookups
|
||||
nonceList *list.List // O(1) insert, update, delete
|
||||
limit uint
|
||||
type lruNonceCache struct {
|
||||
mtx sync.Mutex
|
||||
nonceCache map[uint64]*list.Element // nearly O(1) lookups
|
||||
nonceList *list.List // O(1) insert, update, delete
|
||||
limit uint
|
||||
}
|
||||
|
||||
// String returns the map as a human-readable string.
|
||||
// String returns the cache as a human-readable string.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *lruNonceMap) String() string {
|
||||
func (m *lruNonceCache) String() string {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
lastEntryNum := len(m.nonceMap) - 1
|
||||
lastEntryNum := len(m.nonceCache) - 1
|
||||
curEntry := 0
|
||||
buf := bytes.NewBufferString("[")
|
||||
for nonce := range m.nonceMap {
|
||||
for nonce := range m.nonceCache {
|
||||
buf.WriteString(fmt.Sprintf("%d", nonce))
|
||||
if curEntry < lastEntryNum {
|
||||
buf.WriteString(", ")
|
||||
@ -44,27 +44,27 @@ func (m *lruNonceMap) String() string {
|
||||
return fmt.Sprintf("<%d>%s", m.limit, buf.String())
|
||||
}
|
||||
|
||||
// Exists returns whether or not the passed nonce is in the map.
|
||||
// Exists returns whether or not the passed nonce is in the cache.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *lruNonceMap) Exists(nonce uint64) bool {
|
||||
func (m *lruNonceCache) Exists(nonce uint64) bool {
|
||||
m.mtx.Lock()
|
||||
_, exists := m.nonceMap[nonce]
|
||||
_, exists := m.nonceCache[nonce]
|
||||
m.mtx.Unlock()
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
// Add adds the passed nonce to the map and handles eviction of the oldest item
|
||||
// Add adds the passed nonce to the cache and handles eviction of the oldest item
|
||||
// if adding the new item would exceed the max limit. Adding an existing item
|
||||
// makes it the most recently used item.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *lruNonceMap) Add(nonce uint64) {
|
||||
func (m *lruNonceCache) Add(nonce uint64) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
// When the limit is zero, nothing can be added to the map, so just
|
||||
// When the limit is zero, nothing can be added to the cache, so just
|
||||
// return.
|
||||
if m.limit == 0 {
|
||||
return
|
||||
@ -72,55 +72,55 @@ func (m *lruNonceMap) Add(nonce uint64) {
|
||||
|
||||
// When the entry already exists move it to the front of the list
|
||||
// thereby marking it most recently used.
|
||||
if node, exists := m.nonceMap[nonce]; exists {
|
||||
if node, exists := m.nonceCache[nonce]; exists {
|
||||
m.nonceList.MoveToFront(node)
|
||||
return
|
||||
}
|
||||
|
||||
// Evict the least recently used entry (back of the list) if the the new
|
||||
// entry would exceed the size limit for the map. Also reuse the list
|
||||
// entry would exceed the size limit for the cache. Also reuse the list
|
||||
// node so a new one doesn't have to be allocated.
|
||||
if uint(len(m.nonceMap))+1 > m.limit {
|
||||
if uint(len(m.nonceCache))+1 > m.limit {
|
||||
node := m.nonceList.Back()
|
||||
lru := node.Value.(uint64)
|
||||
|
||||
// Evict least recently used item.
|
||||
delete(m.nonceMap, lru)
|
||||
delete(m.nonceCache, lru)
|
||||
|
||||
// Reuse the list node of the item that was just evicted for the
|
||||
// new item.
|
||||
node.Value = nonce
|
||||
m.nonceList.MoveToFront(node)
|
||||
m.nonceMap[nonce] = node
|
||||
m.nonceCache[nonce] = node
|
||||
return
|
||||
}
|
||||
|
||||
// The limit hasn't been reached yet, so just add the new item.
|
||||
node := m.nonceList.PushFront(nonce)
|
||||
m.nonceMap[nonce] = node
|
||||
m.nonceCache[nonce] = node
|
||||
}
|
||||
|
||||
// Delete deletes the passed nonce from the map (if it exists).
|
||||
// Delete deletes the passed nonce from the cache (if it exists).
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *lruNonceMap) Delete(nonce uint64) {
|
||||
func (m *lruNonceCache) Delete(nonce uint64) {
|
||||
m.mtx.Lock()
|
||||
if node, exists := m.nonceMap[nonce]; exists {
|
||||
if node, exists := m.nonceCache[nonce]; exists {
|
||||
m.nonceList.Remove(node)
|
||||
delete(m.nonceMap, nonce)
|
||||
delete(m.nonceCache, nonce)
|
||||
}
|
||||
m.mtx.Unlock()
|
||||
}
|
||||
|
||||
// newLruNonceMap returns a new nonce map that is limited to the number of
|
||||
// newLruNonceCache returns a new nonce cache that is limited to the number of
|
||||
// entries specified by limit. When the number of entries exceeds the limit,
|
||||
// the oldest (least recently used) entry will be removed to make room for the
|
||||
// new entry.
|
||||
func newLruNonceMap(limit uint) *lruNonceMap {
|
||||
m := lruNonceMap{
|
||||
nonceMap: make(map[uint64]*list.Element),
|
||||
nonceList: list.New(),
|
||||
limit: limit,
|
||||
func newLruNonceCache(limit uint) *lruNonceCache {
|
||||
m := lruNonceCache{
|
||||
nonceCache: make(map[uint64]*list.Element),
|
||||
nonceList: list.New(),
|
||||
limit: limit,
|
||||
}
|
||||
return &m
|
||||
}
|
||||
@ -10,10 +10,10 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestLruNonceMap ensures the lruNonceMap behaves as expected including
|
||||
// TestLruNonceCache ensures the lruNonceCache behaves as expected including
|
||||
// limiting, eviction of least-recently used entries, specific entry removal,
|
||||
// and existence tests.
|
||||
func TestLruNonceMap(t *testing.T) {
|
||||
func TestLruNonceCache(t *testing.T) {
|
||||
// Create a bunch of fake nonces to use in testing the lru nonce code.
|
||||
numNonces := 10
|
||||
nonces := make([]uint64, 0, numNonces)
|
||||
@ -35,18 +35,18 @@ func TestLruNonceMap(t *testing.T) {
|
||||
|
||||
testLoop:
|
||||
for i, test := range tests {
|
||||
// Create a new lru nonce map limited by the specified test
|
||||
// Create a new lru nonce cache limited by the specified test
|
||||
// limit and add all of the test nonces. This will cause
|
||||
// evicition since there are more test nonces than the limits.
|
||||
lruNonceMap := newLruNonceMap(uint(test.limit))
|
||||
lruNonceCache := newLruNonceCache(uint(test.limit))
|
||||
for j := 0; j < numNonces; j++ {
|
||||
lruNonceMap.Add(nonces[j])
|
||||
lruNonceCache.Add(nonces[j])
|
||||
}
|
||||
|
||||
// Ensure the limited number of most recent entries in the list
|
||||
// exist.
|
||||
for j := numNonces - test.limit; j < numNonces; j++ {
|
||||
if !lruNonceMap.Exists(nonces[j]) {
|
||||
if !lruNonceCache.Exists(nonces[j]) {
|
||||
t.Errorf("Exists #%d (%s) entry %d does not "+
|
||||
"exist", i, test.name, nonces[j])
|
||||
continue testLoop
|
||||
@ -56,7 +56,7 @@ testLoop:
|
||||
// Ensure the entries before the limited number of most recent
|
||||
// entries in the list do not exist.
|
||||
for j := 0; j < numNonces-test.limit; j++ {
|
||||
if lruNonceMap.Exists(nonces[j]) {
|
||||
if lruNonceCache.Exists(nonces[j]) {
|
||||
t.Errorf("Exists #%d (%s) entry %d exists", i,
|
||||
test.name, nonces[j])
|
||||
continue testLoop
|
||||
@ -72,13 +72,13 @@ testLoop:
|
||||
// This check needs at least 2 entries.
|
||||
if test.limit > 1 {
|
||||
origLruIndex := numNonces - test.limit
|
||||
lruNonceMap.Add(nonces[origLruIndex])
|
||||
lruNonceCache.Add(nonces[origLruIndex])
|
||||
|
||||
lruNonceMap.Add(uint64(numNonces) + 1)
|
||||
lruNonceCache.Add(uint64(numNonces) + 1)
|
||||
|
||||
// Ensure the original lru entry still exists since it
|
||||
// was updated and should've have become the lru entry.
|
||||
if !lruNonceMap.Exists(nonces[origLruIndex]) {
|
||||
if !lruNonceCache.Exists(nonces[origLruIndex]) {
|
||||
t.Errorf("LRU #%d (%s) entry %d does not exist",
|
||||
i, test.name, nonces[origLruIndex])
|
||||
continue testLoop
|
||||
@ -87,7 +87,7 @@ testLoop:
|
||||
// Ensure the entry that should've become the new lru
|
||||
// entry was evicted.
|
||||
newLruIndex := origLruIndex + 1
|
||||
if lruNonceMap.Exists(nonces[newLruIndex]) {
|
||||
if lruNonceCache.Exists(nonces[newLruIndex]) {
|
||||
t.Errorf("LRU #%d (%s) entry %d exists", i,
|
||||
test.name, nonces[newLruIndex])
|
||||
continue testLoop
|
||||
@ -95,10 +95,10 @@ testLoop:
|
||||
}
|
||||
|
||||
// Delete all of the entries in the list, including those that
|
||||
// don't exist in the map, and ensure they no longer exist.
|
||||
// don't exist in the cache, and ensure they no longer exist.
|
||||
for j := 0; j < numNonces; j++ {
|
||||
lruNonceMap.Delete(nonces[j])
|
||||
if lruNonceMap.Exists(nonces[j]) {
|
||||
lruNonceCache.Delete(nonces[j])
|
||||
if lruNonceCache.Exists(nonces[j]) {
|
||||
t.Errorf("Delete #%d (%s) entry %d exists", i,
|
||||
test.name, nonces[j])
|
||||
continue testLoop
|
||||
@ -107,24 +107,24 @@ testLoop:
|
||||
}
|
||||
}
|
||||
|
||||
// TestLruNonceMapStringer tests the stringized output for the lruNonceMap type.
|
||||
func TestLruNonceMapStringer(t *testing.T) {
|
||||
// TestLruNonceCacheStringer tests the stringized output for the lruNonceCache type.
|
||||
func TestLruNonceCacheStringer(t *testing.T) {
|
||||
// Create a couple of fake nonces to use in testing the lru nonce
|
||||
// stringer code.
|
||||
nonce1 := uint64(10)
|
||||
nonce2 := uint64(20)
|
||||
|
||||
// Create new lru nonce map and add the nonces.
|
||||
lruNonceMap := newLruNonceMap(uint(2))
|
||||
lruNonceMap.Add(nonce1)
|
||||
lruNonceMap.Add(nonce2)
|
||||
// Create new lru nonce cache and add the nonces.
|
||||
lruNonceCache := newLruNonceCache(uint(2))
|
||||
lruNonceCache.Add(nonce1)
|
||||
lruNonceCache.Add(nonce2)
|
||||
|
||||
// Ensure the stringer gives the expected result. Since map iteration
|
||||
// Ensure the stringer gives the expected result. Since cache iteration
|
||||
// is not ordered, either entry could be first, so account for both
|
||||
// cases.
|
||||
wantStr1 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce1, nonce2)
|
||||
wantStr2 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce2, nonce1)
|
||||
gotStr := lruNonceMap.String()
|
||||
gotStr := lruNonceCache.String()
|
||||
if gotStr != wantStr1 && gotStr != wantStr2 {
|
||||
t.Fatalf("unexpected string representation - got %q, want %q "+
|
||||
"or %q", gotStr, wantStr1, wantStr2)
|
||||
@ -146,8 +146,8 @@ func BenchmarkLruNonceList(b *testing.B) {
|
||||
|
||||
// Benchmark the add plus evicition code.
|
||||
limit := 20000
|
||||
lruNonceMap := newLruNonceMap(uint(limit))
|
||||
lruNonceCache := newLruNonceCache(uint(limit))
|
||||
for i := 0; i < b.N; i++ {
|
||||
lruNonceMap.Add(nonces[i%numNonces])
|
||||
lruNonceCache.Add(nonces[i%numNonces])
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,7 @@ var (
|
||||
|
||||
// sentNonces houses the unique nonces that are generated when pushing
|
||||
// version messages that are used to detect self connections.
|
||||
sentNonces = newLruNonceMap(50)
|
||||
sentNonces = newLruNonceCache(50)
|
||||
|
||||
// allowSelfConns is only used to allow the tests to bypass the self
|
||||
// connection detecting and disconnect logic since they intentionally
|
||||
|
||||
Loading…
Reference in New Issue
Block a user