Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
G
go-ipfs
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
jihao
go-ipfs
Commits
c2bbca05
提交
c2bbca05
authored
3月 07, 2015
作者:
Juan Batiz-Benet
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
query: fix race condition: redux
this time just move to goprocess
上级
7a03d677
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
42 行增加
和
38 行删除
+42
-38
ext_test.go
routing/dht/ext_test.go
+1
-1
query.go
routing/dht/query.go
+41
-37
没有找到文件。
routing/dht/ext_test.go
浏览文件 @
c2bbca05
...
...
@@ -52,7 +52,7 @@ func TestGetFailures(t *testing.T) {
err
=
merr
[
0
]
}
if
err
!=
context
.
DeadlineExceeded
{
if
err
!=
context
.
DeadlineExceeded
&&
err
!=
context
.
Canceled
{
t
.
Fatal
(
"Got different error than we expected"
,
err
)
}
}
else
{
...
...
routing/dht/query.go
浏览文件 @
c2bbca05
...
...
@@ -12,7 +12,8 @@ import (
pset
"github.com/jbenet/go-ipfs/util/peerset"
todoctr
"github.com/jbenet/go-ipfs/util/todocounter"
ctxgroup
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
process
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
ctxproc
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
context
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
)
...
...
@@ -61,8 +62,8 @@ func (q *dhtQuery) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, e
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
defer
cancel
()
runner
:=
newQueryRunner
(
ctx
,
q
)
return
runner
.
Run
(
peers
)
runner
:=
newQueryRunner
(
q
)
return
runner
.
Run
(
ctx
,
peers
)
}
type
dhtQueryRunner
struct
{
...
...
@@ -77,22 +78,24 @@ type dhtQueryRunner struct {
rateLimit
chan
struct
{}
// processing semaphore
log
eventlog
.
EventLogger
cg
ctxgroup
.
ContextGroup
proc
process
.
Process
sync
.
RWMutex
}
func
newQueryRunner
(
ctx
context
.
Context
,
q
*
dhtQuery
)
*
dhtQueryRunner
{
func
newQueryRunner
(
q
*
dhtQuery
)
*
dhtQueryRunner
{
proc
:=
process
.
WithParent
(
process
.
Background
())
ctx
:=
ctxproc
.
WithProcessClosing
(
context
.
Background
(),
proc
)
return
&
dhtQueryRunner
{
query
:
q
,
peersToQuery
:
queue
.
NewChanQueue
(
ctx
,
queue
.
NewXORDistancePQ
(
q
.
key
)),
peersRemaining
:
todoctr
.
NewSyncCounter
(),
peersSeen
:
pset
.
New
(),
rateLimit
:
make
(
chan
struct
{},
q
.
concurrency
),
cg
:
ctxgroup
.
WithContext
(
ctx
)
,
proc
:
proc
,
}
}
func
(
r
*
dhtQueryRunner
)
Run
(
peers
[]
peer
.
ID
)
(
*
dhtQueryResult
,
error
)
{
func
(
r
*
dhtQueryRunner
)
Run
(
ctx
context
.
Context
,
peers
[]
peer
.
ID
)
(
*
dhtQueryResult
,
error
)
{
r
.
log
=
log
if
len
(
peers
)
==
0
{
...
...
@@ -107,31 +110,30 @@ func (r *dhtQueryRunner) Run(peers []peer.ID) (*dhtQueryResult, error) {
// add all the peers we got first.
for
_
,
p
:=
range
peers
{
r
.
addPeerToQuery
(
r
.
cg
.
Context
(),
p
)
}
// may be closed already. this caused an odd race (where we attempt to
// add a child to an already closed ctxgroup). this is a temp workaround
// as we'll switch to using a proc here soon.
select
{
case
<-
r
.
cg
.
Closed
()
:
return
nil
,
r
.
cg
.
Context
()
.
Err
()
default
:
r
.
addPeerToQuery
(
p
)
}
// go do this thing.
// do it as a child
fun
c to make sure Run exits
// do it as a child
pro
c to make sure Run exits
// ONLY AFTER spawn workers has exited.
r
.
cg
.
AddChildFunc
(
r
.
spawnWorkers
)
r
.
proc
.
Go
(
r
.
spawnWorkers
)
// so workers are working.
// wait until they're done.
err
:=
routing
.
ErrNotFound
// now, if the context finishes, close the proc.
// we have to do it here because the logic before is setup, which
// should run without closing the proc.
go
func
()
{
<-
ctx
.
Done
()
r
.
proc
.
Close
()
}()
select
{
case
<-
r
.
peersRemaining
.
Done
()
:
r
.
cg
.
Close
()
r
.
proc
.
Close
()
r
.
RLock
()
defer
r
.
RUnlock
()
...
...
@@ -143,12 +145,10 @@ func (r *dhtQueryRunner) Run(peers []peer.ID) (*dhtQueryResult, error) {
err
=
r
.
errs
[
0
]
}
case
<-
r
.
cg
.
Closed
()
:
log
.
Debug
(
"r.cg.Closed()"
)
case
<-
r
.
proc
.
Closed
()
:
r
.
RLock
()
defer
r
.
RUnlock
()
err
=
r
.
cg
.
Context
()
.
Err
()
// collect the error.
err
=
context
.
DeadlineExceeded
}
if
r
.
result
!=
nil
&&
r
.
result
.
success
{
...
...
@@ -158,7 +158,7 @@ func (r *dhtQueryRunner) Run(peers []peer.ID) (*dhtQueryResult, error) {
return
nil
,
err
}
func
(
r
*
dhtQueryRunner
)
addPeerToQuery
(
ctx
context
.
Context
,
next
peer
.
ID
)
{
func
(
r
*
dhtQueryRunner
)
addPeerToQuery
(
next
peer
.
ID
)
{
// if new peer is ourselves...
if
next
==
r
.
query
.
dht
.
self
{
r
.
log
.
Debug
(
"addPeerToQuery skip self"
)
...
...
@@ -172,18 +172,18 @@ func (r *dhtQueryRunner) addPeerToQuery(ctx context.Context, next peer.ID) {
r
.
peersRemaining
.
Increment
(
1
)
select
{
case
r
.
peersToQuery
.
EnqChan
<-
next
:
case
<-
ctx
.
Done
()
:
case
<-
r
.
proc
.
Closing
()
:
}
}
func
(
r
*
dhtQueryRunner
)
spawnWorkers
(
p
arent
ctxgroup
.
ContextGroup
)
{
func
(
r
*
dhtQueryRunner
)
spawnWorkers
(
p
roc
process
.
Process
)
{
for
{
select
{
case
<-
r
.
peersRemaining
.
Done
()
:
return
case
<-
r
.
cg
.
Closing
()
:
case
<-
r
.
proc
.
Closing
()
:
return
case
p
,
more
:=
<-
r
.
peersToQuery
.
DeqChan
:
...
...
@@ -193,24 +193,27 @@ func (r *dhtQueryRunner) spawnWorkers(parent ctxgroup.ContextGroup) {
// do it as a child func to make sure Run exits
// ONLY AFTER spawn workers has exited.
p
arent
.
AddChildFunc
(
func
(
cg
ctxgroup
.
ContextGroup
)
{
r
.
queryPeer
(
cg
,
p
)
p
roc
.
Go
(
func
(
proc
process
.
Process
)
{
r
.
queryPeer
(
proc
,
p
)
})
}
}
}
func
(
r
*
dhtQueryRunner
)
queryPeer
(
cg
ctxgroup
.
ContextGroup
,
p
peer
.
ID
)
{
func
(
r
*
dhtQueryRunner
)
queryPeer
(
proc
process
.
Process
,
p
peer
.
ID
)
{
// make sure we rate limit concurrency.
select
{
case
<-
r
.
rateLimit
:
case
<-
cg
.
Closing
()
:
case
<-
proc
.
Closing
()
:
r
.
peersRemaining
.
Decrement
(
1
)
return
}
// ok let's do this!
// create a context from our proc.
ctx
:=
ctxproc
.
WithProcessClosing
(
context
.
Background
(),
proc
)
// make sure we do this when we exit
defer
func
()
{
// signal we're done proccessing peer p
...
...
@@ -227,10 +230,11 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
r
.
rateLimit
<-
struct
{}{}
pi
:=
peer
.
PeerInfo
{
ID
:
p
}
if
err
:=
r
.
query
.
dht
.
host
.
Connect
(
cg
.
Context
(),
pi
);
err
!=
nil
{
if
err
:=
r
.
query
.
dht
.
host
.
Connect
(
ctx
,
pi
);
err
!=
nil
{
log
.
Debugf
(
"Error connecting: %s"
,
err
)
notif
.
PublishQueryEvent
(
c
g
.
Context
()
,
&
notif
.
QueryEvent
{
notif
.
PublishQueryEvent
(
c
tx
,
&
notif
.
QueryEvent
{
Type
:
notif
.
QueryError
,
Extra
:
err
.
Error
(),
})
...
...
@@ -246,7 +250,7 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
}
// finally, run the query against this peer
res
,
err
:=
r
.
query
.
qfunc
(
c
g
.
Context
()
,
p
)
res
,
err
:=
r
.
query
.
qfunc
(
c
tx
,
p
)
if
err
!=
nil
{
log
.
Debugf
(
"ERROR worker for: %v %v"
,
p
,
err
)
...
...
@@ -259,7 +263,7 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
r
.
Lock
()
r
.
result
=
res
r
.
Unlock
()
go
r
.
cg
.
Close
()
// signal to everyone that we're done.
go
r
.
proc
.
Close
()
// signal to everyone that we're done.
// must be async, as we're one of the children, and Close blocks.
}
else
if
len
(
res
.
closerPeers
)
>
0
{
...
...
@@ -272,7 +276,7 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
// add their addresses to the dialer's peerstore
r
.
query
.
dht
.
peerstore
.
AddAddrs
(
next
.
ID
,
next
.
Addrs
,
peer
.
TempAddrTTL
)
r
.
addPeerToQuery
(
cg
.
Context
(),
next
.
ID
)
r
.
addPeerToQuery
(
next
.
ID
)
log
.
Debugf
(
"PEERS CLOSER -- worker for: %v added %v (%v)"
,
p
,
next
.
ID
,
next
.
Addrs
)
}
}
else
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论