提交 ae1f7688 作者: Juan Batiz-Benet 提交者: Brian Tiger Chow

separate to ensure sync safety

上级 9e2c3fb8
...@@ -10,61 +10,69 @@ import ( ...@@ -10,61 +10,69 @@ import (
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
) )
// peerDistance tracks a peer and its distance to something else. // peerMetric tracks a peer and its distance to something else.
type peerDistance struct { type peerMetric struct {
// the peer // the peer
peer *peer.Peer peer *peer.Peer
// big.Int for XOR metric // big.Int for XOR metric
distance *big.Int metric *big.Int
} }
// distancePQ implements heap.Interface and PeerQueue // peerMetricHeap implements a heap of peerDistances
type distancePQ struct { type peerMetricHeap []*peerMetric
// from is the Key this PQ measures against
from ks.Key
// peers is a heap of peerDistance items
peers []*peerDistance
sync.RWMutex
}
func (pq *distancePQ) Len() int { func (ph peerMetricHeap) Len() int {
return len(pq.peers) return len(ph)
} }
func (pq *distancePQ) Less(i, j int) bool { func (ph peerMetricHeap) Less(i, j int) bool {
return -1 == pq.peers[i].distance.Cmp(pq.peers[j].distance) return -1 == ph[i].metric.Cmp(ph[j].metric)
} }
func (pq *distancePQ) Swap(i, j int) { func (ph peerMetricHeap) Swap(i, j int) {
p := pq.peers ph[i], ph[j] = ph[j], ph[i]
p[i], p[j] = p[j], p[i]
} }
func (pq *distancePQ) Push(x interface{}) { func (ph *peerMetricHeap) Push(x interface{}) {
item := x.(*peerDistance) item := x.(*peerMetric)
pq.peers = append(pq.peers, item) *ph = append(*ph, item)
} }
func (pq *distancePQ) Pop() interface{} { func (ph *peerMetricHeap) Pop() interface{} {
old := pq.peers old := *ph
n := len(old) n := len(old)
item := old[n-1] item := old[n-1]
pq.peers = old[0 : n-1] *ph = old[0 : n-1]
return item return item
} }
// distancePQ implements heap.Interface and PeerQueue
type distancePQ struct {
// from is the Key this PQ measures against
from ks.Key
// heap is a heap of peerDistance items
heap peerMetricHeap
sync.RWMutex
}
func (pq *distancePQ) Len() int {
pq.Lock()
defer pq.Unlock()
return len(pq.heap)
}
func (pq *distancePQ) Enqueue(p *peer.Peer) { func (pq *distancePQ) Enqueue(p *peer.Peer) {
pq.Lock() pq.Lock()
defer pq.Unlock() defer pq.Unlock()
distance := ks.XORKeySpace.Key(p.ID).Distance(pq.from) distance := ks.XORKeySpace.Key(p.ID).Distance(pq.from)
heap.Push(pq, &peerDistance{ heap.Push(&pq.heap, &peerMetric{
peer: p, peer: p,
distance: distance, metric: distance,
}) })
} }
...@@ -72,13 +80,13 @@ func (pq *distancePQ) Dequeue() *peer.Peer { ...@@ -72,13 +80,13 @@ func (pq *distancePQ) Dequeue() *peer.Peer {
pq.Lock() pq.Lock()
defer pq.Unlock() defer pq.Unlock()
if len(pq.peers) < 1 { if len(pq.heap) < 1 {
panic("called Dequeue on an empty PeerQueue") panic("called Dequeue on an empty PeerQueue")
// will panic internally anyway, but we can help debug here // will panic internally anyway, but we can help debug here
} }
o := heap.Pop(pq) o := heap.Pop(&pq.heap)
p := o.(*peerDistance) p := o.(*peerMetric)
return p.peer return p.peer
} }
...@@ -87,7 +95,7 @@ func (pq *distancePQ) Dequeue() *peer.Peer { ...@@ -87,7 +95,7 @@ func (pq *distancePQ) Dequeue() *peer.Peer {
// XOR as a metric of distance). // XOR as a metric of distance).
func NewXORDistancePQ(fromKey u.Key) PeerQueue { func NewXORDistancePQ(fromKey u.Key) PeerQueue {
return &distancePQ{ return &distancePQ{
from: ks.XORKeySpace.Key([]byte(fromKey)), from: ks.XORKeySpace.Key([]byte(fromKey)),
peers: []*peerDistance{}, heap: peerMetricHeap{},
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论