@cryptotaxi247 / kubo / commits / 07aa00dfa

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 }