Do not fetch recursive pins from pinner unnecessarily
When fetching all pins, the recursive pins are fetched from the pinner two times. The second fetch is unnecessary and copies all recursive pins into a slice again. Additionally, the output channel is now buffered. This allows the goroutine to exit in the case the pinner returns an error and there is no reader for the output channel. This might be possible if a canceled context causes the caller to abandon waiting to read the output of Ls().
gammazero committed
Jan 27, 2021 at 10:17 UTC
07aa00dfa69e81a7dd5623d82ed130a46dd9c188
1 file changed
+13
-16
core/coreapi/pin.go
+13
-16
@@ -220,7 +220,7 @@ func (p *pinInfo) Err() error {
220
221
// pinLsAll is an internal function for returning a list of pins
222
func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreiface.Pin {
223
- out := make(chan coreiface.Pin)
223
+ out := make(chan coreiface.Pin, 1)
224
225
keys := cid.NewSet()
226
@@ -249,37 +249,34 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac
249
go func() {
250
defer close(out)
251
252
+ var dkeys, rkeys []cid.Cid
253
+ var err error
254
if typeStr == "recursive" || typeStr == "all" {
253
- rkeys, err := api.pinning.RecursiveKeys(ctx)
255
+ rkeys, err = api.pinning.RecursiveKeys(ctx)
256
if err != nil {
257
out <- &pinInfo{err: err}
258
return
259
}
258
- if err := AddToResultKeys(rkeys, "recursive"); err != nil {
260
+ if err = AddToResultKeys(rkeys, "recursive"); err != nil {
261
out <- &pinInfo{err: err}
262
return
263
}
264
}
265
if typeStr == "direct" || typeStr == "all" {
264
- dkeys, err := api.pinning.DirectKeys(ctx)
266
+ dkeys, err = api.pinning.DirectKeys(ctx)
267
if err != nil {
268
out <- &pinInfo{err: err}
269
return
270
}
269
- if err := AddToResultKeys(dkeys, "direct"); err != nil {
271
+ if err = AddToResultKeys(dkeys, "direct"); err != nil {
272
out <- &pinInfo{err: err}
273
return
274
}
275
}
276
if typeStr == "all" {
277
set := cid.NewSet()
276
- rkeys, err := api.pinning.RecursiveKeys(ctx)
277
- if err != nil {
278
- out <- &pinInfo{err: err}
279
- return
280
- }
278
for _, k := range rkeys {
282
- err := merkledag.Walk(
279
+ err = merkledag.Walk(
280
ctx, merkledag.GetLinksWithDAG(api.dag), k,
281
set.Visit,
282
merkledag.SkipRoot(), merkledag.Concurrent(),
@@ -289,7 +286,7 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac
286
return
287
}
288
}
292
- if err := AddToResultKeys(set.Keys(), "indirect"); err != nil {
289
+ if err = AddToResultKeys(set.Keys(), "indirect"); err != nil {
290
out <- &pinInfo{err: err}
291
return
292
}
@@ -298,14 +295,14 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac
295
// We need to first visit the direct pins that have priority
296
// without emitting them
297
301
- dkeys, err := api.pinning.DirectKeys(ctx)
298
+ dkeys, err = api.pinning.DirectKeys(ctx)
299
if err != nil {
300
out <- &pinInfo{err: err}
301
return
302
}
303
VisitKeys(dkeys)
304
308
- rkeys, err := api.pinning.RecursiveKeys(ctx)
305
+ rkeys, err = api.pinning.RecursiveKeys(ctx)
306
if err != nil {
307
out <- &pinInfo{err: err}
308
return
@@ -314,7 +311,7 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac
311
312
set := cid.NewSet()
313
for _, k := range rkeys {
317
- err := merkledag.Walk(
314
+ err = merkledag.Walk(
315
ctx, merkledag.GetLinksWithDAG(api.dag), k,
316
set.Visit,
317
merkledag.SkipRoot(), merkledag.Concurrent(),
@@ -324,7 +321,7 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac
321
return
322
}
323
}
327
- if err := AddToResultKeys(set.Keys(), "indirect"); err != nil {
324
+ if err = AddToResultKeys(set.Keys(), "indirect"); err != nil {
325
out <- &pinInfo{err: err}
326
return
327
}