bootstrap: update bootstrapping process.
Note: the dht-specific part of the bootstrap function was only there to make sure to call `dht.Update(ctx, npeer)`. This already happens on all new connections made by the network, as the dht is signed up for notifications.
Juan Batiz-Benet committed
Feb 5, 2015 at 07:53 UTC
cc8ed14e7a3b012ef7e08682529240953662a0e9
2 files changed
+40
-40
core/bootstrap.go
+15
-34
@@ -4,7 +4,6 @@ import (
4
"errors"
5
"fmt"
6
"io"
7
- "io/ioutil"
7
"math/rand"
8
"sync"
9
"time"
@@ -13,7 +12,6 @@ import (
12
inet "github.com/jbenet/go-ipfs/p2p/net"
13
peer "github.com/jbenet/go-ipfs/p2p/peer"
14
config "github.com/jbenet/go-ipfs/repo/config"
16
- dht "github.com/jbenet/go-ipfs/routing/dht"
15
math2 "github.com/jbenet/go-ipfs/thirdparty/math2"
16
lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"
17
@@ -76,15 +74,6 @@ func BootstrapConfigWithPeers(pis []peer.PeerInfo) BootstrapConfig {
74
// bootstrapping (i.e. routing).
75
func Bootstrap(n *IpfsNode, cfg BootstrapConfig) (io.Closer, error) {
76
79
- // TODO what bootstrapping should happen if there is no DHT? i.e. we could
80
- // continue connecting to our bootstrap peers, but for what purpose? for now
81
- // simply exit without connecting to any of them. When we introduce another
82
- // routing system that uses bootstrap peers we can change this.
83
- thedht, ok := n.Routing.(*dht.IpfsDHT)
84
- if !ok {
85
- return ioutil.NopCloser(nil), nil
86
- }
87
-
77
// make a signal to wait for one bootstrap round to complete.
78
doneWithRound := make(chan struct{})
79
@@ -93,7 +82,7 @@ func Bootstrap(n *IpfsNode, cfg BootstrapConfig) (io.Closer, error) {
82
ctx := procctx.WithProcessClosing(context.Background(), worker)
83
defer log.EventBegin(ctx, "periodicBootstrap", n.Identity).Done()
84
96
- if err := bootstrapRound(ctx, n.PeerHost, thedht, n.Peerstore, cfg); err != nil {
85
+ if err := bootstrapRound(ctx, n.PeerHost, cfg); err != nil {
86
log.Event(ctx, "bootstrapError", n.Identity, lgbl.Error(err))
87
log.Debugf("%s bootstrap error: %s", n.Identity, err)
88
}
@@ -105,25 +94,21 @@ func Bootstrap(n *IpfsNode, cfg BootstrapConfig) (io.Closer, error) {
94
proc := periodicproc.Tick(cfg.Period, periodic)
95
proc.Go(periodic) // run one right now.
96
108
- // kick off dht bootstrapping.
109
- dbproc, err := thedht.BootstrapWithConfig(dht.DefaultBootstrapConfig)
110
- if err != nil {
111
- proc.Close()
112
- return nil, err
97
+ // kick off Routing.Bootstrap
98
+ if n.Routing != nil {
99
+ ctx := procctx.WithProcessClosing(context.Background(), proc)
100
+ if err := n.Routing.Bootstrap(ctx); err != nil {
101
+ proc.Close()
102
+ return nil, err
103
+ }
104
}
105
115
- // add dht bootstrap proc as a child, so it is closed automatically when we are.
116
- proc.AddChild(dbproc)
106
doneWithRound <- struct{}{}
107
close(doneWithRound) // it no longer blocks periodic
108
return proc, nil
109
}
110
122
-func bootstrapRound(ctx context.Context,
123
- host host.Host,
124
- route *dht.IpfsDHT,
125
- peerstore peer.Peerstore,
126
- cfg BootstrapConfig) error {
111
+func bootstrapRound(ctx context.Context, host host.Host, cfg BootstrapConfig) error {
112
113
ctx, _ = context.WithTimeout(ctx, cfg.ConnectionTimeout)
114
id := host.ID()
@@ -161,16 +146,13 @@ func bootstrapRound(ctx context.Context,
146
147
defer log.EventBegin(ctx, "bootstrapStart", id).Done()
148
log.Debugf("%s bootstrapping to %d nodes: %s", id, numToDial, randSubset)
164
- if err := bootstrapConnect(ctx, peerstore, route, randSubset); err != nil {
149
+ if err := bootstrapConnect(ctx, host, randSubset); err != nil {
150
return err
151
}
152
return nil
153
}
154
170
-func bootstrapConnect(ctx context.Context,
171
- ps peer.Peerstore,
172
- route *dht.IpfsDHT,
173
- peers []peer.PeerInfo) error {
155
+func bootstrapConnect(ctx context.Context, ph host.Host, peers []peer.PeerInfo) error {
156
if len(peers) < 1 {
157
return ErrNotEnoughBootstrapPeers
158
}
@@ -187,12 +169,11 @@ func bootstrapConnect(ctx context.Context,
169
wg.Add(1)
170
go func(p peer.PeerInfo) {
171
defer wg.Done()
190
- defer log.EventBegin(ctx, "bootstrapDial", route.LocalPeer(), p.ID).Done()
191
- log.Debugf("%s bootstrapping to %s", route.LocalPeer(), p.ID)
172
+ defer log.EventBegin(ctx, "bootstrapDial", ph.ID(), p.ID).Done()
173
+ log.Debugf("%s bootstrapping to %s", ph.ID(), p.ID)
174
193
- ps.AddAddrs(p.ID, p.Addrs, peer.PermanentAddrTTL)
194
- err := route.Connect(ctx, p.ID)
195
- if err != nil {
175
+ ph.Peerstore().AddAddrs(p.ID, p.Addrs, peer.PermanentAddrTTL)
176
+ if err := ph.Connect(ctx, p); err != nil {
177
log.Event(ctx, "bootstrapDialFailed", p.ID)
178
log.Debugf("failed to bootstrap with %v: %s", p.ID, err)
179
errs <- err
routing/dht/dht_bootstrap.go
+25
-6
@@ -4,7 +4,6 @@ package dht
4
5
import (
6
"crypto/rand"
7
- "errors"
7
"fmt"
8
"sync"
9
"time"
@@ -45,17 +44,37 @@ var DefaultBootstrapConfig = BootstrapConfig{
44
Timeout: time.Duration(20 * time.Second),
45
}
46
48
-func (dht *IpfsDHT) Bootstrap(context.Context) error {
49
- // Bootstrap satisfies the routing interface
50
- return errors.New("TODO: perform DHT bootstrap")
47
+// Bootstrap ensures the dht routing table remains healthy as peers come and go.
48
+// it builds up a list of peers by requesting random peer IDs. The Bootstrap
49
+// process will run a number of queries each time, and run every time signal fires.
50
+// These parameters are configurable.
51
+//
52
+// As opposed to BootstrapWithConfig, Bootstrap satisfies the routing interface
53
+func (dht *IpfsDHT) Bootstrap(ctx context.Context) error {
54
+ proc, err := dht.BootstrapWithConfig(DefaultBootstrapConfig)
55
+ if err != nil {
56
+ return err
57
+ }
58
+
59
+ // wait till ctx or dht.Context exits.
60
+ // we have to do it this way to satisfy the Routing interface (contexts)
61
+ go func() {
62
+ defer proc.Close()
63
+ select {
64
+ case <-ctx.Done():
65
+ case <-dht.Context().Done():
66
+ }
67
+ }()
68
+
69
+ return nil
70
}
71
53
-// Bootstrap ensures the dht routing table remains healthy as peers come and go.
72
+// BootstrapWithConfig ensures the dht routing table remains healthy as peers come and go.
73
// it builds up a list of peers by requesting random peer IDs. The Bootstrap
74
// process will run a number of queries each time, and run every time signal fires.
75
// These parameters are configurable.
76
//
58
-// Bootstrap returns a process, so the user can stop it.
77
+// BootstrapWithConfig returns a process, so the user can stop it.
78
func (dht *IpfsDHT) BootstrapWithConfig(config BootstrapConfig) (goprocess.Process, error) {
79
sig := time.Tick(config.Period)
80
return dht.BootstrapOnSignal(config, sig)