Skip to content

Commit 477e735

Browse files
authored
Merge pull request ipfs/go-bitswap#74 from ipfs/feat/differentiate_wantList
More specific wantlists This commit was moved from ipfs/go-bitswap@ab7ddf0
2 parents 386036d + 81c5613 commit 477e735

11 files changed

+186
-167
lines changed

bitswap/bitswap.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ func New(parent context.Context, network bsnet.BitSwapNetwork,
9797
return nil
9898
})
9999

100-
peerQueueFactory := func(p peer.ID) bspm.PeerQueue {
101-
return bsmq.New(p, network)
100+
peerQueueFactory := func(ctx context.Context, p peer.ID) bspm.PeerQueue {
101+
return bsmq.New(ctx, p, network)
102102
}
103103

104104
wm := bswm.New(ctx)

bitswap/decision/peer_request_queue.go

+13-8
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (tl *prq) Push(to peer.ID, entries ...*wantlist.Entry) {
6060
defer partner.activelk.Unlock()
6161

6262
var priority int
63-
newEntries := make([]*wantlist.Entry, 0, len(entries))
63+
newEntries := make([]*peerRequestTaskEntry, 0, len(entries))
6464
for _, entry := range entries {
6565
if partner.activeBlocks.Has(entry.Cid) {
6666
continue
@@ -75,7 +75,7 @@ func (tl *prq) Push(to peer.ID, entries ...*wantlist.Entry) {
7575
if entry.Priority > priority {
7676
priority = entry.Priority
7777
}
78-
newEntries = append(newEntries, entry)
78+
newEntries = append(newEntries, &peerRequestTaskEntry{entry, false})
7979
}
8080

8181
if len(newEntries) == 0 {
@@ -86,7 +86,7 @@ func (tl *prq) Push(to peer.ID, entries ...*wantlist.Entry) {
8686
Entries: newEntries,
8787
Target: to,
8888
created: time.Now(),
89-
Done: func(e []*wantlist.Entry) {
89+
Done: func(e []*peerRequestTaskEntry) {
9090
tl.lock.Lock()
9191
for _, entry := range e {
9292
partner.TaskDone(entry.Cid)
@@ -117,10 +117,10 @@ func (tl *prq) Pop() *peerRequestTask {
117117
for partner.taskQueue.Len() > 0 && partner.freezeVal == 0 {
118118
out = partner.taskQueue.Pop().(*peerRequestTask)
119119

120-
newEntries := make([]*wantlist.Entry, 0, len(out.Entries))
120+
newEntries := make([]*peerRequestTaskEntry, 0, len(out.Entries))
121121
for _, entry := range out.Entries {
122122
delete(tl.taskMap, taskEntryKey{out.Target, entry.Cid})
123-
if entry.Trash {
123+
if entry.trash {
124124
continue
125125
}
126126
partner.requests--
@@ -150,7 +150,7 @@ func (tl *prq) Remove(k cid.Cid, p peer.ID) {
150150
// remove the task "lazily"
151151
// simply mark it as trash, so it'll be dropped when popped off the
152152
// queue.
153-
entry.Trash = true
153+
entry.trash = true
154154
break
155155
}
156156
}
@@ -197,13 +197,18 @@ func (tl *prq) thawRound() {
197197
}
198198
}
199199

200+
type peerRequestTaskEntry struct {
201+
*wantlist.Entry
202+
// trash in a book-keeping field
203+
trash bool
204+
}
200205
type peerRequestTask struct {
201-
Entries []*wantlist.Entry
206+
Entries []*peerRequestTaskEntry
202207
Priority int
203208
Target peer.ID
204209

205210
// A callback to signal that this task has been completed
206-
Done func([]*wantlist.Entry)
211+
Done func([]*peerRequestTaskEntry)
207212

208213
// created marks the time that the task was added to the queue
209214
created time.Time

bitswap/messagequeue/messagequeue.go

+99-82
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package messagequeue
22

33
import (
44
"context"
5-
"sync"
65
"time"
76

87
bsmsg "github.com/ipfs/go-bitswap/message"
@@ -23,86 +22,99 @@ type MessageNetwork interface {
2322
NewMessageSender(context.Context, peer.ID) (bsnet.MessageSender, error)
2423
}
2524

25+
type request interface {
26+
handle(mq *MessageQueue)
27+
}
28+
2629
// MessageQueue implements queue of want messages to send to peers.
2730
type MessageQueue struct {
28-
p peer.ID
29-
30-
outlk sync.Mutex
31-
out bsmsg.BitSwapMessage
31+
ctx context.Context
32+
p peer.ID
3233
network MessageNetwork
33-
wl *wantlist.ThreadSafe
3434

35-
sender bsnet.MessageSender
35+
newRequests chan request
36+
outgoingMessages chan bsmsg.BitSwapMessage
37+
done chan struct{}
38+
39+
// do not touch out of run loop
40+
wl *wantlist.SessionTrackedWantlist
41+
nextMessage bsmsg.BitSwapMessage
42+
sender bsnet.MessageSender
43+
}
44+
45+
type messageRequest struct {
46+
entries []*bsmsg.Entry
47+
ses uint64
48+
}
3649

37-
work chan struct{}
38-
done chan struct{}
50+
type wantlistRequest struct {
51+
wl *wantlist.SessionTrackedWantlist
3952
}
4053

4154
// New creats a new MessageQueue.
42-
func New(p peer.ID, network MessageNetwork) *MessageQueue {
55+
func New(ctx context.Context, p peer.ID, network MessageNetwork) *MessageQueue {
4356
return &MessageQueue{
44-
done: make(chan struct{}),
45-
work: make(chan struct{}, 1),
46-
wl: wantlist.NewThreadSafe(),
47-
network: network,
48-
p: p,
57+
ctx: ctx,
58+
wl: wantlist.NewSessionTrackedWantlist(),
59+
network: network,
60+
p: p,
61+
newRequests: make(chan request, 16),
62+
outgoingMessages: make(chan bsmsg.BitSwapMessage),
63+
done: make(chan struct{}),
4964
}
5065
}
5166

5267
// AddMessage adds new entries to an outgoing message for a given session.
5368
func (mq *MessageQueue) AddMessage(entries []*bsmsg.Entry, ses uint64) {
54-
if !mq.addEntries(entries, ses) {
55-
return
56-
}
5769
select {
58-
case mq.work <- struct{}{}:
59-
default:
70+
case mq.newRequests <- &messageRequest{entries, ses}:
71+
case <-mq.ctx.Done():
6072
}
6173
}
6274

6375
// AddWantlist adds a complete session tracked want list to a message queue
64-
func (mq *MessageQueue) AddWantlist(initialEntries []*wantlist.Entry) {
65-
if len(initialEntries) > 0 {
66-
if mq.out == nil {
67-
mq.out = bsmsg.New(false)
68-
}
76+
func (mq *MessageQueue) AddWantlist(initialWants *wantlist.SessionTrackedWantlist) {
77+
wl := wantlist.NewSessionTrackedWantlist()
78+
initialWants.CopyWants(wl)
6979

70-
for _, e := range initialEntries {
71-
for k := range e.SesTrk {
72-
mq.wl.AddEntry(e, k)
73-
}
74-
mq.out.AddEntry(e.Cid, e.Priority)
75-
}
76-
77-
select {
78-
case mq.work <- struct{}{}:
79-
default:
80-
}
80+
select {
81+
case mq.newRequests <- &wantlistRequest{wl}:
82+
case <-mq.ctx.Done():
8183
}
8284
}
8385

8486
// Startup starts the processing of messages, and creates an initial message
8587
// based on the given initial wantlist.
86-
func (mq *MessageQueue) Startup(ctx context.Context) {
87-
go mq.runQueue(ctx)
88+
func (mq *MessageQueue) Startup() {
89+
go mq.runQueue()
90+
go mq.sendMessages()
8891
}
8992

9093
// Shutdown stops the processing of messages for a message queue.
9194
func (mq *MessageQueue) Shutdown() {
9295
close(mq.done)
9396
}
9497

95-
func (mq *MessageQueue) runQueue(ctx context.Context) {
98+
func (mq *MessageQueue) runQueue() {
99+
outgoingMessages := func() chan bsmsg.BitSwapMessage {
100+
if mq.nextMessage == nil {
101+
return nil
102+
}
103+
return mq.outgoingMessages
104+
}
105+
96106
for {
97107
select {
98-
case <-mq.work: // there is work to be done
99-
mq.doWork(ctx)
108+
case newRequest := <-mq.newRequests:
109+
newRequest.handle(mq)
110+
case outgoingMessages() <- mq.nextMessage:
111+
mq.nextMessage = nil
100112
case <-mq.done:
101113
if mq.sender != nil {
102114
mq.sender.Close()
103115
}
104116
return
105-
case <-ctx.Done():
117+
case <-mq.ctx.Done():
106118
if mq.sender != nil {
107119
mq.sender.Reset()
108120
}
@@ -111,72 +123,86 @@ func (mq *MessageQueue) runQueue(ctx context.Context) {
111123
}
112124
}
113125

114-
func (mq *MessageQueue) addEntries(entries []*bsmsg.Entry, ses uint64) bool {
115-
var work bool
116-
mq.outlk.Lock()
117-
defer mq.outlk.Unlock()
118-
// if we have no message held allocate a new one
119-
if mq.out == nil {
120-
mq.out = bsmsg.New(false)
126+
func (mr *messageRequest) handle(mq *MessageQueue) {
127+
mq.addEntries(mr.entries, mr.ses)
128+
}
129+
130+
func (wr *wantlistRequest) handle(mq *MessageQueue) {
131+
initialWants := wr.wl
132+
initialWants.CopyWants(mq.wl)
133+
if initialWants.Len() > 0 {
134+
if mq.nextMessage == nil {
135+
mq.nextMessage = bsmsg.New(false)
136+
}
137+
for _, e := range initialWants.Entries() {
138+
mq.nextMessage.AddEntry(e.Cid, e.Priority)
139+
}
121140
}
141+
}
122142

123-
// TODO: add a msg.Combine(...) method
124-
// otherwise, combine the one we are holding with the
125-
// one passed in
143+
func (mq *MessageQueue) addEntries(entries []*bsmsg.Entry, ses uint64) {
126144
for _, e := range entries {
127145
if e.Cancel {
128146
if mq.wl.Remove(e.Cid, ses) {
129-
work = true
130-
mq.out.Cancel(e.Cid)
147+
if mq.nextMessage == nil {
148+
mq.nextMessage = bsmsg.New(false)
149+
}
150+
mq.nextMessage.Cancel(e.Cid)
131151
}
132152
} else {
133153
if mq.wl.Add(e.Cid, e.Priority, ses) {
134-
work = true
135-
mq.out.AddEntry(e.Cid, e.Priority)
154+
if mq.nextMessage == nil {
155+
mq.nextMessage = bsmsg.New(false)
156+
}
157+
mq.nextMessage.AddEntry(e.Cid, e.Priority)
136158
}
137159
}
138160
}
139-
140-
return work
141161
}
142162

143-
func (mq *MessageQueue) doWork(ctx context.Context) {
144-
145-
wlm := mq.extractOutgoingMessage()
146-
if wlm == nil || wlm.Empty() {
147-
return
163+
func (mq *MessageQueue) sendMessages() {
164+
for {
165+
select {
166+
case nextMessage := <-mq.outgoingMessages:
167+
mq.sendMessage(nextMessage)
168+
case <-mq.done:
169+
return
170+
case <-mq.ctx.Done():
171+
return
172+
}
148173
}
174+
}
175+
176+
func (mq *MessageQueue) sendMessage(message bsmsg.BitSwapMessage) {
149177

150-
// NB: only open a stream if we actually have data to send
151-
err := mq.initializeSender(ctx)
178+
err := mq.initializeSender()
152179
if err != nil {
153180
log.Infof("cant open message sender to peer %s: %s", mq.p, err)
154181
// TODO: cant connect, what now?
155182
return
156183
}
157184

158-
// send wantlist updates
159185
for i := 0; i < maxRetries; i++ { // try to send this message until we fail.
160-
if mq.attemptSendAndRecovery(ctx, wlm) {
186+
if mq.attemptSendAndRecovery(message) {
161187
return
162188
}
163189
}
164190
}
165191

166-
func (mq *MessageQueue) initializeSender(ctx context.Context) error {
192+
func (mq *MessageQueue) initializeSender() error {
167193
if mq.sender != nil {
168194
return nil
169195
}
170-
nsender, err := openSender(ctx, mq.network, mq.p)
196+
nsender, err := openSender(mq.ctx, mq.network, mq.p)
171197
if err != nil {
172198
return err
173199
}
174200
mq.sender = nsender
175201
return nil
176202
}
177203

178-
func (mq *MessageQueue) attemptSendAndRecovery(ctx context.Context, wlm bsmsg.BitSwapMessage) bool {
179-
err := mq.sender.SendMsg(ctx, wlm)
204+
func (mq *MessageQueue) attemptSendAndRecovery(message bsmsg.BitSwapMessage) bool {
205+
err := mq.sender.SendMsg(mq.ctx, message)
180206
if err == nil {
181207
return true
182208
}
@@ -188,14 +214,14 @@ func (mq *MessageQueue) attemptSendAndRecovery(ctx context.Context, wlm bsmsg.Bi
188214
select {
189215
case <-mq.done:
190216
return true
191-
case <-ctx.Done():
217+
case <-mq.ctx.Done():
192218
return true
193219
case <-time.After(time.Millisecond * 100):
194220
// wait 100ms in case disconnect notifications are still propogating
195221
log.Warning("SendMsg errored but neither 'done' nor context.Done() were set")
196222
}
197223

198-
err = mq.initializeSender(ctx)
224+
err = mq.initializeSender()
199225
if err != nil {
200226
log.Infof("couldnt open sender again after SendMsg(%s) failed: %s", mq.p, err)
201227
// TODO(why): what do we do now?
@@ -215,15 +241,6 @@ func (mq *MessageQueue) attemptSendAndRecovery(ctx context.Context, wlm bsmsg.Bi
215241
return false
216242
}
217243

218-
func (mq *MessageQueue) extractOutgoingMessage() bsmsg.BitSwapMessage {
219-
// grab outgoing message
220-
mq.outlk.Lock()
221-
wlm := mq.out
222-
mq.out = nil
223-
mq.outlk.Unlock()
224-
return wlm
225-
}
226-
227244
func openSender(ctx context.Context, network MessageNetwork, p peer.ID) (bsnet.MessageSender, error) {
228245
// allow ten minutes for connections this includes looking them up in the
229246
// dht dialing them, and handshaking

0 commit comments

Comments
 (0)