96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
|
package channeldb
|
||
|
|
||
|
// rejectFlags is a compact representation of various metadata stored by the
|
||
|
// reject cache about a particular channel.
|
||
|
type rejectFlags uint8
|
||
|
|
||
|
const (
|
||
|
// rejectFlagExists is a flag indicating whether the channel exists,
|
||
|
// i.e. the channel is open and has a recent channel update. If this
|
||
|
// flag is not set, the channel is either a zombie or unknown.
|
||
|
rejectFlagExists rejectFlags = 1 << iota
|
||
|
|
||
|
// rejectFlagZombie is a flag indicating whether the channel is a
|
||
|
// zombie, i.e. the channel is open but has no recent channel updates.
|
||
|
rejectFlagZombie
|
||
|
)
|
||
|
|
||
|
// packRejectFlags computes the rejectFlags corresponding to the passed boolean
|
||
|
// values indicating whether the edge exists or is a zombie.
|
||
|
func packRejectFlags(exists, isZombie bool) rejectFlags {
|
||
|
var flags rejectFlags
|
||
|
if exists {
|
||
|
flags |= rejectFlagExists
|
||
|
}
|
||
|
if isZombie {
|
||
|
flags |= rejectFlagZombie
|
||
|
}
|
||
|
|
||
|
return flags
|
||
|
}
|
||
|
|
||
|
// unpack returns the booleans packed into the rejectFlags. The first indicates
|
||
|
// if the edge exists in our graph, the second indicates if the edge is a
|
||
|
// zombie.
|
||
|
func (f rejectFlags) unpack() (bool, bool) {
|
||
|
return f&rejectFlagExists == rejectFlagExists,
|
||
|
f&rejectFlagZombie == rejectFlagZombie
|
||
|
}
|
||
|
|
||
|
// rejectCacheEntry caches frequently accessed information about a channel,
|
||
|
// including the timestamps of its latest edge policies and whether or not the
|
||
|
// channel exists in the graph.
|
||
|
type rejectCacheEntry struct {
|
||
|
upd1Time int64
|
||
|
upd2Time int64
|
||
|
flags rejectFlags
|
||
|
}
|
||
|
|
||
|
// rejectCache is an in-memory cache used to improve the performance of
|
||
|
// HasChannelEdge. It caches information about the whether or channel exists, as
|
||
|
// well as the most recent timestamps for each policy (if they exists).
|
||
|
type rejectCache struct {
|
||
|
n int
|
||
|
edges map[uint64]rejectCacheEntry
|
||
|
}
|
||
|
|
||
|
// newRejectCache creates a new rejectCache with maximum capacity of n entries.
|
||
|
func newRejectCache(n int) *rejectCache {
|
||
|
return &rejectCache{
|
||
|
n: n,
|
||
|
edges: make(map[uint64]rejectCacheEntry, n),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// get returns the entry from the cache for chanid, if it exists.
|
||
|
func (c *rejectCache) get(chanid uint64) (rejectCacheEntry, bool) {
|
||
|
entry, ok := c.edges[chanid]
|
||
|
return entry, ok
|
||
|
}
|
||
|
|
||
|
// insert adds the entry to the reject cache. If an entry for chanid already
|
||
|
// exists, it will be replaced with the new entry. If the entry doesn't exists,
|
||
|
// it will be inserted to the cache, performing a random eviction if the cache
|
||
|
// is at capacity.
|
||
|
func (c *rejectCache) insert(chanid uint64, entry rejectCacheEntry) {
|
||
|
// If entry exists, replace it.
|
||
|
if _, ok := c.edges[chanid]; ok {
|
||
|
c.edges[chanid] = entry
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Otherwise, evict an entry at random and insert.
|
||
|
if len(c.edges) == c.n {
|
||
|
for id := range c.edges {
|
||
|
delete(c.edges, id)
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
c.edges[chanid] = entry
|
||
|
}
|
||
|
|
||
|
// remove deletes an entry for chanid from the cache, if it exists.
|
||
|
func (c *rejectCache) remove(chanid uint64) {
|
||
|
delete(c.edges, chanid)
|
||
|
}
|