Skip to content

Commit 7d693dc

Browse files
authored
Merge pull request ipfs/go-bitswap#116 from ipfs/bugs/queue-memory-leak
fix(decision): cleanup request queues This commit was moved from ipfs/go-bitswap@61f1223
2 parents 52ee7ff + c501d01 commit 7d693dc

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

bitswap/decision/peer_request_queue.go

+18-4
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func (tl *prq) Push(to peer.ID, entries ...wantlist.Entry) {
5151
defer tl.lock.Unlock()
5252
partner, ok := tl.partners[to]
5353
if !ok {
54-
partner = newActivePartner()
54+
partner = newActivePartner(to)
5555
tl.pQueue.Push(partner)
5656
tl.partners[to] = partner
5757
}
@@ -136,7 +136,13 @@ func (tl *prq) Pop() *peerRequestTask {
136136
break // and return |out|
137137
}
138138

139-
tl.pQueue.Push(partner)
139+
if partner.IsIdle() {
140+
target := partner.target
141+
delete(tl.partners, target)
142+
delete(tl.frozen, target)
143+
} else {
144+
tl.pQueue.Push(partner)
145+
}
140146
return out
141147
}
142148

@@ -252,7 +258,7 @@ func wrapCmp(f func(a, b *peerRequestTask) bool) func(a, b pq.Elem) bool {
252258
}
253259

254260
type activePartner struct {
255-
261+
target peer.ID
256262
// Active is the number of blocks this peer is currently being sent
257263
// active must be locked around as it will be updated externally
258264
activelk sync.Mutex
@@ -274,8 +280,9 @@ type activePartner struct {
274280
taskQueue pq.PQ
275281
}
276282

277-
func newActivePartner() *activePartner {
283+
func newActivePartner(target peer.ID) *activePartner {
278284
return &activePartner{
285+
target: target,
279286
taskQueue: pq.New(wrapCmp(V1)),
280287
activeBlocks: cid.NewSet(),
281288
}
@@ -323,6 +330,7 @@ func (p *activePartner) StartTask(k cid.Cid) {
323330
// TaskDone signals that a task was completed for this partner.
324331
func (p *activePartner) TaskDone(k cid.Cid) {
325332
p.activelk.Lock()
333+
326334
p.activeBlocks.Remove(k)
327335
p.active--
328336
if p.active < 0 {
@@ -331,6 +339,12 @@ func (p *activePartner) TaskDone(k cid.Cid) {
331339
p.activelk.Unlock()
332340
}
333341

342+
func (p *activePartner) IsIdle() bool {
343+
p.activelk.Lock()
344+
defer p.activelk.Unlock()
345+
return p.requests == 0 && p.active == 0
346+
}
347+
334348
// Index implements pq.Elem.
335349
func (p *activePartner) Index() int {
336350
return p.index

bitswap/decision/peer_request_queue_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,35 @@ func TestPeerRepeats(t *testing.T) {
128128
}
129129
}
130130
}
131+
132+
func TestCleaningUpQueues(t *testing.T) {
133+
partner := testutil.RandPeerIDFatal(t)
134+
var entries []wantlist.Entry
135+
for i := 0; i < 5; i++ {
136+
entries = append(entries, wantlist.Entry{Cid: cid.NewCidV0(u.Hash([]byte(fmt.Sprint(i))))})
137+
}
138+
139+
prq := newPRQ()
140+
141+
// push a block, pop a block, complete everything, should be removed
142+
prq.Push(partner, entries...)
143+
task := prq.Pop()
144+
task.Done(task.Entries)
145+
task = prq.Pop()
146+
147+
if task != nil || len(prq.partners) > 0 || prq.pQueue.Len() > 0 {
148+
t.Fatal("Partner should have been removed because it's idle")
149+
}
150+
151+
// push a block, remove each of its entries, should be removed
152+
prq.Push(partner, entries...)
153+
for _, entry := range entries {
154+
prq.Remove(entry.Cid, partner)
155+
}
156+
task = prq.Pop()
157+
158+
if task != nil || len(prq.partners) > 0 || prq.pQueue.Len() > 0 {
159+
t.Fatal("Partner should have been removed because it's idle")
160+
}
161+
162+
}

0 commit comments

Comments
 (0)