83 lines
2.2 KiB
Go
83 lines
2.2 KiB
Go
|
// Copyright (c) 2013 Conformal Systems LLC.
|
||
|
// Use of this source code is governed by an ISC
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"github.com/conformal/btcwire"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// MruInventoryMap provides a map that is limited to a maximum number of items
|
||
|
// with eviction for the oldest entry when the limit is exceeded.
|
||
|
type MruInventoryMap struct {
|
||
|
invMap map[btcwire.InvVect]int64 // Use int64 for time for less mem.
|
||
|
limit uint
|
||
|
}
|
||
|
|
||
|
// String returns the map as a human-readable string.
|
||
|
func (m MruInventoryMap) String() string {
|
||
|
return fmt.Sprintf("<%d>%v", m.limit, m.invMap)
|
||
|
}
|
||
|
|
||
|
// Exists returns whether or not the passed inventory item is in the map.
|
||
|
func (m *MruInventoryMap) Exists(iv *btcwire.InvVect) bool {
|
||
|
if _, exists := m.invMap[*iv]; exists {
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// Add adds the passed inventory to the map and handles eviction of the oldest
|
||
|
// item if adding the new item would exceed the max limit.
|
||
|
func (m *MruInventoryMap) Add(iv *btcwire.InvVect) {
|
||
|
// When the limit is zero, nothing can be added to the map, so just
|
||
|
// return
|
||
|
if m.limit == 0 {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// When the entry already exists update its last seen time.
|
||
|
if m.Exists(iv) {
|
||
|
m.invMap[*iv] = time.Now().Unix()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Evict the oldest entry if the the new entry would exceed the size
|
||
|
// limit for the map.
|
||
|
if uint(len(m.invMap))+1 > m.limit {
|
||
|
var oldestEntry btcwire.InvVect
|
||
|
var oldestTime int64
|
||
|
for iv, lastUpdated := range m.invMap {
|
||
|
if oldestTime == 0 || lastUpdated < oldestTime {
|
||
|
oldestEntry = iv
|
||
|
oldestTime = lastUpdated
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m.Delete(&oldestEntry)
|
||
|
}
|
||
|
|
||
|
m.invMap[*iv] = time.Now().Unix()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Delete deletes the passed inventory item from the map (if it exists).
|
||
|
func (m *MruInventoryMap) Delete(iv *btcwire.InvVect) {
|
||
|
delete(m.invMap, *iv)
|
||
|
}
|
||
|
|
||
|
// NewMruInventoryMap returns a new inventory map 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 NewMruInventoryMap(limit uint) *MruInventoryMap {
|
||
|
m := MruInventoryMap{
|
||
|
invMap: make(map[btcwire.InvVect]int64),
|
||
|
limit: limit,
|
||
|
}
|
||
|
return &m
|
||
|
}
|