@cryptotaxi247 / kubo / commits / 474b74f70

dht/bootstrap: (optional) parallelism + error on peer

This also makes it an Error to find a peer.

Juan Batiz-Benet committed Dec 9, 2014 at 12:04 UTC 474b74f70b3fb583b2ccc2062a1acf3a86509cba
2 files changed +59 -6
routing/dht/dht.go
+41 -6
@@ -342,6 +342,7 @@ func (dht *IpfsDHT) PingRoutine(t time.Duration) {
342
343 // Bootstrap builds up list of peers by requesting random peer IDs
344 func (dht *IpfsDHT) Bootstrap(ctx context.Context, queries int) error {
345 + var merr u.MultiErr
346
347 randomID := func() peer.ID {
348 // 16 random bytes is not a valid peer id. it may be fine becuase
@@ -352,18 +353,52 @@ func (dht *IpfsDHT) Bootstrap(ctx context.Context, queries int) error {
353 }
354
355 // bootstrap sequentially, as results will compound
355 - for i := 0; i < queries; i++ {
356 - id := randomID()
357 - log.Debugf("Bootstrapping query (%d/%d) to random ID: %s", i, queries, id)
356 + runQuery := func(ctx context.Context, id peer.ID) {
357 p, err := dht.FindPeer(ctx, id)
358 if err == routing.ErrNotFound {
359 // this isn't an error. this is precisely what we expect.
360 } else if err != nil {
362 - log.Errorf("Bootstrap peer error: %s", err)
361 + merr = append(merr, err)
362 } else {
364 - // woah, we got a peer under a random id? it _cannot_ be valid.
365 - log.Errorf("dht seemingly found a peer at a random bootstrap id (%s)...", p)
363 + // woah, actually found a peer with that ID? this shouldn't happen normally
364 + // (as the ID we use is not a real ID). this is an odd error worth logging.
365 + err := fmt.Errorf("Bootstrap peer error: Actually FOUND peer. (%s, %s)", id, p)
366 + log.Errorf("%s", err)
367 + merr = append(merr, err)
368 }
369 }
370 +
371 + sequential := true
372 + if sequential {
373 + // these should be parallel normally. but can make them sequential for debugging.
374 + // note that the core/bootstrap context deadline should be extended too for that.
375 + for i := 0; i < queries; i++ {
376 + id := randomID()
377 + log.Debugf("Bootstrapping query (%d/%d) to random ID: %s", i+1, queries, id)
378 + runQuery(ctx, id)
379 + }
380 +
381 + } else {
382 + // note on parallelism here: the context is passed in to the queries, so they
383 + // **should** exit when it exceeds, making this function exit on ctx cancel.
384 + // normally, we should be selecting on ctx.Done() here too, but this gets
385 + // complicated to do with WaitGroup, and doesnt wait for the children to exit.
386 + var wg sync.WaitGroup
387 + for i := 0; i < queries; i++ {
388 + wg.Add(1)
389 + go func() {
390 + defer wg.Done()
391 +
392 + id := randomID()
393 + log.Debugf("Bootstrapping query (%d/%d) to random ID: %s", i+1, queries, id)
394 + runQuery(ctx, id)
395 + }()
396 + }
397 + wg.Wait()
398 + }
399 +
400 + if len(merr) > 0 {
401 + return merr
402 + }
403 return nil
404 }
util/util.go
+18
@@ -126,3 +126,21 @@ func GetenvBool(name string) bool {
126 v := strings.ToLower(os.Getenv(name))
127 return v == "true" || v == "t" || v == "1"
128 }
129 +
130 +// multiErr is a util to return multiple errors
131 +type MultiErr []error
132 +
133 +func (m MultiErr) Error() string {
134 + if len(m) == 0 {
135 + return "no errors"
136 + }
137 +
138 + s := "Multiple errors: "
139 + for i, e := range m {
140 + if i != 0 {
141 + s += ", "
142 + }
143 + s += e.Error()
144 + }
145 + return s
146 +}