|
@ -7,6 +7,7 @@ import ( |
|
|
// IPeerSet has a (immutable) subset of the methods of PeerSet.
|
|
|
// IPeerSet has a (immutable) subset of the methods of PeerSet.
|
|
|
type IPeerSet interface { |
|
|
type IPeerSet interface { |
|
|
Has(key ID) bool |
|
|
Has(key ID) bool |
|
|
|
|
|
HasIP(ip string) bool |
|
|
Get(key ID) Peer |
|
|
Get(key ID) Peer |
|
|
List() []Peer |
|
|
List() []Peer |
|
|
Size() int |
|
|
Size() int |
|
@ -17,9 +18,10 @@ type IPeerSet interface { |
|
|
// PeerSet is a special structure for keeping a table of peers.
|
|
|
// PeerSet is a special structure for keeping a table of peers.
|
|
|
// Iteration over the peers is super fast and thread-safe.
|
|
|
// Iteration over the peers is super fast and thread-safe.
|
|
|
type PeerSet struct { |
|
|
type PeerSet struct { |
|
|
mtx sync.Mutex |
|
|
|
|
|
lookup map[ID]*peerSetItem |
|
|
|
|
|
list []Peer |
|
|
|
|
|
|
|
|
mtx sync.Mutex |
|
|
|
|
|
lookup map[ID]*peerSetItem |
|
|
|
|
|
lookupIP map[string]struct{} |
|
|
|
|
|
list []Peer |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
type peerSetItem struct { |
|
|
type peerSetItem struct { |
|
@ -30,8 +32,9 @@ type peerSetItem struct { |
|
|
// NewPeerSet creates a new peerSet with a list of initial capacity of 256 items.
|
|
|
// NewPeerSet creates a new peerSet with a list of initial capacity of 256 items.
|
|
|
func NewPeerSet() *PeerSet { |
|
|
func NewPeerSet() *PeerSet { |
|
|
return &PeerSet{ |
|
|
return &PeerSet{ |
|
|
lookup: make(map[ID]*peerSetItem), |
|
|
|
|
|
list: make([]Peer, 0, 256), |
|
|
|
|
|
|
|
|
lookup: make(map[ID]*peerSetItem), |
|
|
|
|
|
lookupIP: make(map[string]struct{}), |
|
|
|
|
|
list: make([]Peer, 0, 256), |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -41,7 +44,10 @@ func (ps *PeerSet) Add(peer Peer) error { |
|
|
ps.mtx.Lock() |
|
|
ps.mtx.Lock() |
|
|
defer ps.mtx.Unlock() |
|
|
defer ps.mtx.Unlock() |
|
|
if ps.lookup[peer.ID()] != nil { |
|
|
if ps.lookup[peer.ID()] != nil { |
|
|
return ErrSwitchDuplicatePeer |
|
|
|
|
|
|
|
|
return ErrSwitchDuplicatePeerID{peer.ID()} |
|
|
|
|
|
} |
|
|
|
|
|
if _, ok := ps.lookupIP[peer.RemoteIP()]; ok { |
|
|
|
|
|
return ErrSwitchDuplicatePeerIP{peer.RemoteIP()} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
index := len(ps.list) |
|
|
index := len(ps.list) |
|
@ -49,6 +55,7 @@ func (ps *PeerSet) Add(peer Peer) error { |
|
|
// iterating over the ps.list slice.
|
|
|
// iterating over the ps.list slice.
|
|
|
ps.list = append(ps.list, peer) |
|
|
ps.list = append(ps.list, peer) |
|
|
ps.lookup[peer.ID()] = &peerSetItem{peer, index} |
|
|
ps.lookup[peer.ID()] = &peerSetItem{peer, index} |
|
|
|
|
|
ps.lookupIP[peer.RemoteIP()] = struct{}{} |
|
|
return nil |
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -61,6 +68,15 @@ func (ps *PeerSet) Has(peerKey ID) bool { |
|
|
return ok |
|
|
return ok |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// HasIP returns true iff the PeerSet contains
|
|
|
|
|
|
// the peer referred to by this IP address.
|
|
|
|
|
|
func (ps *PeerSet) HasIP(peerIP string) bool { |
|
|
|
|
|
ps.mtx.Lock() |
|
|
|
|
|
_, ok := ps.lookupIP[peerIP] |
|
|
|
|
|
ps.mtx.Unlock() |
|
|
|
|
|
return ok |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Get looks up a peer by the provided peerKey.
|
|
|
// Get looks up a peer by the provided peerKey.
|
|
|
func (ps *PeerSet) Get(peerKey ID) Peer { |
|
|
func (ps *PeerSet) Get(peerKey ID) Peer { |
|
|
ps.mtx.Lock() |
|
|
ps.mtx.Lock() |
|
@ -76,6 +92,7 @@ func (ps *PeerSet) Get(peerKey ID) Peer { |
|
|
func (ps *PeerSet) Remove(peer Peer) { |
|
|
func (ps *PeerSet) Remove(peer Peer) { |
|
|
ps.mtx.Lock() |
|
|
ps.mtx.Lock() |
|
|
defer ps.mtx.Unlock() |
|
|
defer ps.mtx.Unlock() |
|
|
|
|
|
delete(ps.lookupIP[peer.RemoteIP()]) |
|
|
item := ps.lookup[peer.ID()] |
|
|
item := ps.lookup[peer.ID()] |
|
|
if item == nil { |
|
|
if item == nil { |
|
|
return |
|
|
return |
|
|