Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-bitswap
Commits
6370a0b9
Commit
6370a0b9
authored
Nov 21, 2016
by
Jeromy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cleanup bitswap and handle message send failure slightly better
License: MIT Signed-off-by:
Jeromy
<
why@ipfs.io
>
parent
0f7b0a06
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
88 additions
and
49 deletions
+88
-49
bitswap.go
bitswap.go
+18
-18
wantmanager.go
wantmanager.go
+64
-31
workers.go
workers.go
+6
-0
No files found.
bitswap.go
View file @
6370a0b9
...
@@ -82,7 +82,6 @@ func New(parent context.Context, p peer.ID, network bsnet.BitSwapNetwork,
...
@@ -82,7 +82,6 @@ func New(parent context.Context, p peer.ID, network bsnet.BitSwapNetwork,
})
})
bs
:=
&
Bitswap
{
bs
:=
&
Bitswap
{
self
:
p
,
blockstore
:
bstore
,
blockstore
:
bstore
,
notifications
:
notif
,
notifications
:
notif
,
engine
:
decision
.
NewEngine
(
ctx
,
bstore
),
// TODO close the engine with Close() method
engine
:
decision
.
NewEngine
(
ctx
,
bstore
),
// TODO close the engine with Close() method
...
@@ -112,34 +111,36 @@ func New(parent context.Context, p peer.ID, network bsnet.BitSwapNetwork,
...
@@ -112,34 +111,36 @@ func New(parent context.Context, p peer.ID, network bsnet.BitSwapNetwork,
// Bitswap instances implement the bitswap protocol.
// Bitswap instances implement the bitswap protocol.
type
Bitswap
struct
{
type
Bitswap
struct
{
// the peermanager manages sending messages to peers in a way that
// wont block bitswap operation
wm
*
WantManager
// the
ID of the peer to act on behalf of
// the
engine is the bit of logic that decides who to send which blocks to
self
peer
.
ID
engine
*
decision
.
Engine
// network delivers messages on behalf of the session
// network delivers messages on behalf of the session
network
bsnet
.
BitSwapNetwork
network
bsnet
.
BitSwapNetwork
// the peermanager manages sending messages to peers in a way that
// wont block bitswap operation
wm
*
WantManager
// blockstore is the local database
// blockstore is the local database
// NB: ensure threadsafety
// NB: ensure threadsafety
blockstore
blockstore
.
Blockstore
blockstore
blockstore
.
Blockstore
// notifications engine for receiving new blocks and routing them to the
// appropriate user requests
notifications
notifications
.
PubSub
notifications
notifications
.
PubSub
// send keys to a worker to find and connect to providers for them
//
findKeys
send
s
keys to a worker to find and connect to providers for them
findKeys
chan
*
blockRequest
findKeys
chan
*
blockRequest
// newBlocks is a channel for newly added blocks to be provided to the
engine
*
decision
.
Engine
// network. blocks pushed down this channel get buffered and fed to the
// provideKeys channel later on to avoid too much network activity
process
process
.
Process
newBlocks
chan
*
cid
.
Cid
newBlocks
chan
*
cid
.
Cid
// provideKeys directly feeds provide workers
provideKeys
chan
*
cid
.
Cid
provideKeys
chan
*
cid
.
Cid
process
process
.
Process
// Counters for various statistics
counterLk
sync
.
Mutex
counterLk
sync
.
Mutex
blocksRecvd
int
blocksRecvd
int
dupBlocksRecvd
int
dupBlocksRecvd
int
...
@@ -167,13 +168,12 @@ func (bs *Bitswap) GetBlock(parent context.Context, k *cid.Cid) (blocks.Block, e
...
@@ -167,13 +168,12 @@ func (bs *Bitswap) GetBlock(parent context.Context, k *cid.Cid) (blocks.Block, e
// enforce. May this comment keep you safe.
// enforce. May this comment keep you safe.
ctx
,
cancelFunc
:=
context
.
WithCancel
(
parent
)
ctx
,
cancelFunc
:=
context
.
WithCancel
(
parent
)
// TODO: this request ID should come in from a higher layer so we can track
// across multiple 'GetBlock' invocations
ctx
=
logging
.
ContextWithLoggable
(
ctx
,
loggables
.
Uuid
(
"GetBlockRequest"
))
ctx
=
logging
.
ContextWithLoggable
(
ctx
,
loggables
.
Uuid
(
"GetBlockRequest"
))
log
.
Event
(
ctx
,
"Bitswap.GetBlockRequest.Start"
,
k
)
log
.
Event
(
ctx
,
"Bitswap.GetBlockRequest.Start"
,
k
)
defer
log
.
Event
(
ctx
,
"Bitswap.GetBlockRequest.End"
,
k
)
defer
log
.
Event
(
ctx
,
"Bitswap.GetBlockRequest.End"
,
k
)
defer
cancelFunc
()
defer
func
()
{
cancelFunc
()
}()
promise
,
err
:=
bs
.
GetBlocks
(
ctx
,
[]
*
cid
.
Cid
{
k
})
promise
,
err
:=
bs
.
GetBlocks
(
ctx
,
[]
*
cid
.
Cid
{
k
})
if
err
!=
nil
{
if
err
!=
nil
{
...
...
wantmanager.go
View file @
6370a0b9
...
@@ -175,28 +175,13 @@ func (mq *msgQueue) runQueue(ctx context.Context) {
...
@@ -175,28 +175,13 @@ func (mq *msgQueue) runQueue(ctx context.Context) {
}
}
func
(
mq
*
msgQueue
)
doWork
(
ctx
context
.
Context
)
{
func
(
mq
*
msgQueue
)
doWork
(
ctx
context
.
Context
)
{
// allow ten minutes for connections
// this includes looking them up in the dht
// dialing them, and handshaking
if
mq
.
sender
==
nil
{
if
mq
.
sender
==
nil
{
conctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
*
10
)
err
:=
mq
.
openSender
(
ctx
)
defer
cancel
()
err
:=
mq
.
network
.
ConnectTo
(
conctx
,
mq
.
p
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Infof
(
"cant
connect
to peer %s: %s"
,
mq
.
p
,
err
)
log
.
Infof
(
"cant
open message sender
to peer %s: %s"
,
mq
.
p
,
err
)
// TODO: cant connect, what now?
// TODO: cant connect, what now?
return
return
}
}
nsender
,
err
:=
mq
.
network
.
NewMessageSender
(
ctx
,
mq
.
p
)
if
err
!=
nil
{
log
.
Infof
(
"cant open new stream to peer %s: %s"
,
mq
.
p
,
err
)
// TODO: cant open stream, what now?
return
}
mq
.
sender
=
nsender
}
}
// grab outgoing message
// grab outgoing message
...
@@ -210,14 +195,64 @@ func (mq *msgQueue) doWork(ctx context.Context) {
...
@@ -210,14 +195,64 @@ func (mq *msgQueue) doWork(ctx context.Context) {
mq
.
outlk
.
Unlock
()
mq
.
outlk
.
Unlock
()
// send wantlist updates
// send wantlist updates
err
:=
mq
.
sender
.
SendMsg
(
wlm
)
for
{
// try to send this message until we fail.
if
err
!=
nil
{
err
:=
mq
.
sender
.
SendMsg
(
wlm
)
if
err
==
nil
{
return
}
log
.
Infof
(
"bitswap send error: %s"
,
err
)
log
.
Infof
(
"bitswap send error: %s"
,
err
)
mq
.
sender
.
Close
()
mq
.
sender
.
Close
()
mq
.
sender
=
nil
mq
.
sender
=
nil
// TODO: what do we do if this fails?
return
select
{
case
<-
mq
.
done
:
return
case
<-
ctx
.
Done
()
:
return
case
<-
time
.
After
(
time
.
Millisecond
*
100
)
:
// wait 100ms in case disconnect notifications are still propogating
log
.
Warning
(
"SendMsg errored but neither 'done' nor context.Done() were set"
)
}
err
=
mq
.
openSender
(
ctx
)
if
err
!=
nil
{
log
.
Error
(
"couldnt open sender again after SendMsg(%s) failed: %s"
,
mq
.
p
,
err
)
// TODO(why): what do we do now?
// I think the *right* answer is to probably put the message we're
// trying to send back, and then return to waiting for new work or
// a disconnect.
return
}
// TODO: Is this the same instance for the remote peer?
// If its not, we should resend our entire wantlist to them
/*
if mq.sender.InstanceID() != mq.lastSeenInstanceID {
wlm = mq.getFullWantlistMessage()
}
*/
}
}
func
(
mq
*
msgQueue
)
openSender
(
ctx
context
.
Context
)
error
{
// allow ten minutes for connections this includes looking them up in the
// dht dialing them, and handshaking
conctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
*
10
)
defer
cancel
()
err
:=
mq
.
network
.
ConnectTo
(
conctx
,
mq
.
p
)
if
err
!=
nil
{
return
err
}
nsender
,
err
:=
mq
.
network
.
NewMessageSender
(
ctx
,
mq
.
p
)
if
err
!=
nil
{
return
err
}
}
mq
.
sender
=
nsender
return
nil
}
}
func
(
pm
*
WantManager
)
Connected
(
p
peer
.
ID
)
{
func
(
pm
*
WantManager
)
Connected
(
p
peer
.
ID
)
{
...
@@ -292,14 +327,13 @@ func (pm *WantManager) Run() {
...
@@ -292,14 +327,13 @@ func (pm *WantManager) Run() {
}
}
func
(
wm
*
WantManager
)
newMsgQueue
(
p
peer
.
ID
)
*
msgQueue
{
func
(
wm
*
WantManager
)
newMsgQueue
(
p
peer
.
ID
)
*
msgQueue
{
mq
:=
new
(
msgQueue
)
return
&
msgQueue
{
mq
.
done
=
make
(
chan
struct
{})
done
:
make
(
chan
struct
{}),
mq
.
work
=
make
(
chan
struct
{},
1
)
work
:
make
(
chan
struct
{},
1
),
mq
.
network
=
wm
.
network
network
:
wm
.
network
,
mq
.
p
=
p
p
:
p
,
mq
.
refcnt
=
1
refcnt
:
1
,
}
return
mq
}
}
func
(
mq
*
msgQueue
)
addMessage
(
entries
[]
*
bsmsg
.
Entry
)
{
func
(
mq
*
msgQueue
)
addMessage
(
entries
[]
*
bsmsg
.
Entry
)
{
...
@@ -312,8 +346,7 @@ func (mq *msgQueue) addMessage(entries []*bsmsg.Entry) {
...
@@ -312,8 +346,7 @@ func (mq *msgQueue) addMessage(entries []*bsmsg.Entry) {
}
}
}()
}()
// if we have no message held, or the one we are given is full
// if we have no message held allocate a new one
// overwrite the one we are holding
if
mq
.
out
==
nil
{
if
mq
.
out
==
nil
{
mq
.
out
=
bsmsg
.
New
(
false
)
mq
.
out
=
bsmsg
.
New
(
false
)
}
}
...
...
workers.go
View file @
6370a0b9
...
@@ -197,6 +197,12 @@ func (bs *Bitswap) providerQueryManager(ctx context.Context) {
...
@@ -197,6 +197,12 @@ func (bs *Bitswap) providerQueryManager(ctx context.Context) {
for
{
for
{
select
{
select
{
case
e
:=
<-
bs
.
findKeys
:
case
e
:=
<-
bs
.
findKeys
:
select
{
// make sure its not already cancelled
case
<-
e
.
Ctx
.
Done
()
:
continue
default
:
}
activeLk
.
Lock
()
activeLk
.
Lock
()
if
kset
.
Has
(
e
.
Cid
)
{
if
kset
.
Has
(
e
.
Cid
)
{
activeLk
.
Unlock
()
activeLk
.
Unlock
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment