@@ -12,7 +12,8 @@ import (
12
12
pset "github.com/jbenet/go-ipfs/util/peerset"
13
13
todoctr "github.com/jbenet/go-ipfs/util/todocounter"
14
14
15
- ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
15
+ process "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
16
+ ctxproc "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
16
17
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
17
18
)
18
19
@@ -61,8 +62,8 @@ func (q *dhtQuery) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, e
61
62
ctx , cancel := context .WithCancel (ctx )
62
63
defer cancel ()
63
64
64
- runner := newQueryRunner (ctx , q )
65
- return runner .Run (peers )
65
+ runner := newQueryRunner (q )
66
+ return runner .Run (ctx , peers )
66
67
}
67
68
68
69
type dhtQueryRunner struct {
@@ -77,22 +78,24 @@ type dhtQueryRunner struct {
77
78
rateLimit chan struct {} // processing semaphore
78
79
log eventlog.EventLogger
79
80
80
- cg ctxgroup. ContextGroup
81
+ proc process. Process
81
82
sync.RWMutex
82
83
}
83
84
84
- func newQueryRunner (ctx context.Context , q * dhtQuery ) * dhtQueryRunner {
85
+ func newQueryRunner (q * dhtQuery ) * dhtQueryRunner {
86
+ proc := process .WithParent (process .Background ())
87
+ ctx := ctxproc .WithProcessClosing (context .Background (), proc )
85
88
return & dhtQueryRunner {
86
89
query : q ,
87
90
peersToQuery : queue .NewChanQueue (ctx , queue .NewXORDistancePQ (q .key )),
88
91
peersRemaining : todoctr .NewSyncCounter (),
89
92
peersSeen : pset .New (),
90
93
rateLimit : make (chan struct {}, q .concurrency ),
91
- cg : ctxgroup . WithContext ( ctx ) ,
94
+ proc : proc ,
92
95
}
93
96
}
94
97
95
- func (r * dhtQueryRunner ) Run (peers []peer.ID ) (* dhtQueryResult , error ) {
98
+ func (r * dhtQueryRunner ) Run (ctx context. Context , peers []peer.ID ) (* dhtQueryResult , error ) {
96
99
r .log = log
97
100
98
101
if len (peers ) == 0 {
@@ -107,31 +110,30 @@ func (r *dhtQueryRunner) Run(peers []peer.ID) (*dhtQueryResult, error) {
107
110
108
111
// add all the peers we got first.
109
112
for _ , p := range peers {
110
- r .addPeerToQuery (r .cg .Context (), p )
111
- }
112
-
113
- // may be closed already. this caused an odd race (where we attempt to
114
- // add a child to an already closed ctxgroup). this is a temp workaround
115
- // as we'll switch to using a proc here soon.
116
- select {
117
- case <- r .cg .Closed ():
118
- return nil , r .cg .Context ().Err ()
119
- default :
113
+ r .addPeerToQuery (p )
120
114
}
121
115
122
116
// go do this thing.
123
- // do it as a child func to make sure Run exits
117
+ // do it as a child proc to make sure Run exits
124
118
// ONLY AFTER spawn workers has exited.
125
- r .cg . AddChildFunc (r .spawnWorkers )
119
+ r .proc . Go (r .spawnWorkers )
126
120
127
121
// so workers are working.
128
122
129
123
// wait until they're done.
130
124
err := routing .ErrNotFound
131
125
126
+ // now, if the context finishes, close the proc.
127
+ // we have to do it here because the logic before is setup, which
128
+ // should run without closing the proc.
129
+ go func () {
130
+ <- ctx .Done ()
131
+ r .proc .Close ()
132
+ }()
133
+
132
134
select {
133
135
case <- r .peersRemaining .Done ():
134
- r .cg .Close ()
136
+ r .proc .Close ()
135
137
r .RLock ()
136
138
defer r .RUnlock ()
137
139
@@ -143,12 +145,10 @@ func (r *dhtQueryRunner) Run(peers []peer.ID) (*dhtQueryResult, error) {
143
145
err = r .errs [0 ]
144
146
}
145
147
146
- case <- r .cg .Closed ():
147
- log .Debug ("r.cg.Closed()" )
148
-
148
+ case <- r .proc .Closed ():
149
149
r .RLock ()
150
150
defer r .RUnlock ()
151
- err = r . cg . Context (). Err () // collect the error.
151
+ err = context . DeadlineExceeded
152
152
}
153
153
154
154
if r .result != nil && r .result .success {
@@ -158,7 +158,7 @@ func (r *dhtQueryRunner) Run(peers []peer.ID) (*dhtQueryResult, error) {
158
158
return nil , err
159
159
}
160
160
161
- func (r * dhtQueryRunner ) addPeerToQuery (ctx context. Context , next peer.ID ) {
161
+ func (r * dhtQueryRunner ) addPeerToQuery (next peer.ID ) {
162
162
// if new peer is ourselves...
163
163
if next == r .query .dht .self {
164
164
r .log .Debug ("addPeerToQuery skip self" )
@@ -172,18 +172,18 @@ func (r *dhtQueryRunner) addPeerToQuery(ctx context.Context, next peer.ID) {
172
172
r .peersRemaining .Increment (1 )
173
173
select {
174
174
case r .peersToQuery .EnqChan <- next :
175
- case <- ctx . Done ():
175
+ case <- r . proc . Closing ():
176
176
}
177
177
}
178
178
179
- func (r * dhtQueryRunner ) spawnWorkers (parent ctxgroup. ContextGroup ) {
179
+ func (r * dhtQueryRunner ) spawnWorkers (proc process. Process ) {
180
180
for {
181
181
182
182
select {
183
183
case <- r .peersRemaining .Done ():
184
184
return
185
185
186
- case <- r .cg .Closing ():
186
+ case <- r .proc .Closing ():
187
187
return
188
188
189
189
case p , more := <- r .peersToQuery .DeqChan :
@@ -193,24 +193,27 @@ func (r *dhtQueryRunner) spawnWorkers(parent ctxgroup.ContextGroup) {
193
193
194
194
// do it as a child func to make sure Run exits
195
195
// ONLY AFTER spawn workers has exited.
196
- parent . AddChildFunc (func (cg ctxgroup. ContextGroup ) {
197
- r .queryPeer (cg , p )
196
+ proc . Go (func (proc process. Process ) {
197
+ r .queryPeer (proc , p )
198
198
})
199
199
}
200
200
}
201
201
}
202
202
203
- func (r * dhtQueryRunner ) queryPeer (cg ctxgroup. ContextGroup , p peer.ID ) {
203
+ func (r * dhtQueryRunner ) queryPeer (proc process. Process , p peer.ID ) {
204
204
// make sure we rate limit concurrency.
205
205
select {
206
206
case <- r .rateLimit :
207
- case <- cg .Closing ():
207
+ case <- proc .Closing ():
208
208
r .peersRemaining .Decrement (1 )
209
209
return
210
210
}
211
211
212
212
// ok let's do this!
213
213
214
+ // create a context from our proc.
215
+ ctx := ctxproc .WithProcessClosing (context .Background (), proc )
216
+
214
217
// make sure we do this when we exit
215
218
defer func () {
216
219
// signal we're done proccessing peer p
@@ -227,10 +230,11 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
227
230
r .rateLimit <- struct {}{}
228
231
229
232
pi := peer.PeerInfo {ID : p }
230
- if err := r .query .dht .host .Connect (cg .Context (), pi ); err != nil {
233
+
234
+ if err := r .query .dht .host .Connect (ctx , pi ); err != nil {
231
235
log .Debugf ("Error connecting: %s" , err )
232
236
233
- notif .PublishQueryEvent (cg . Context () , & notif.QueryEvent {
237
+ notif .PublishQueryEvent (ctx , & notif.QueryEvent {
234
238
Type : notif .QueryError ,
235
239
Extra : err .Error (),
236
240
})
@@ -246,7 +250,7 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
246
250
}
247
251
248
252
// finally, run the query against this peer
249
- res , err := r .query .qfunc (cg . Context () , p )
253
+ res , err := r .query .qfunc (ctx , p )
250
254
251
255
if err != nil {
252
256
log .Debugf ("ERROR worker for: %v %v" , p , err )
@@ -259,7 +263,7 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
259
263
r .Lock ()
260
264
r .result = res
261
265
r .Unlock ()
262
- go r .cg .Close () // signal to everyone that we're done.
266
+ go r .proc .Close () // signal to everyone that we're done.
263
267
// must be async, as we're one of the children, and Close blocks.
264
268
265
269
} else if len (res .closerPeers ) > 0 {
@@ -272,7 +276,7 @@ func (r *dhtQueryRunner) queryPeer(cg ctxgroup.ContextGroup, p peer.ID) {
272
276
273
277
// add their addresses to the dialer's peerstore
274
278
r .query .dht .peerstore .AddAddrs (next .ID , next .Addrs , peer .TempAddrTTL )
275
- r .addPeerToQuery (cg . Context (), next .ID )
279
+ r .addPeerToQuery (next .ID )
276
280
log .Debugf ("PEERS CLOSER -- worker for: %v added %v (%v)" , p , next .ID , next .Addrs )
277
281
}
278
282
} else {
0 commit comments