From cd3d6dfad54afe2565c45893ada4eb69428f599d Mon Sep 17 00:00:00 2001 From: Jeromy Date: Thu, 13 Aug 2015 11:44:10 -0700 Subject: [PATCH] replace nodebuilder with a nicer interface License: MIT Signed-off-by: Jeromy --- cmd/ipfs/daemon.go | 13 ++-- core/builder.go | 150 +++++++++++++++++++++++++++---------------- core/commands/add.go | 4 +- 3 files changed, 107 insertions(+), 60 deletions(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 0b23d079db7a..1b59dc4e5e43 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -192,9 +192,11 @@ func daemonFunc(req cmds.Request, res cmds.Response) { return } - // Start assembling corebuilder - nb := core.NewNodeBuilder().Online() - nb.SetRepo(repo) + // Start assembling node config + ncfg := &core.BuildCfg{ + Online: true, + Repo: repo, + } routingOption, _, err := req.Option(routingOptionKwd).String() if err != nil { @@ -215,10 +217,11 @@ func daemonFunc(req cmds.Request, res cmds.Response) { Addrs: []ma.Multiaddr{addr.Transport()}, }) } - nb.SetRouting(corerouting.SupernodeClient(infos...)) + + ncfg.Routing = corerouting.SupernodeClient(infos...) } - node, err := nb.Build(req.Context()) + node, err := core.NewNode(req.Context(), ncfg) if err != nil { log.Error("error from node construction: ", err) res.SetError(err, cmds.ErrNormal) diff --git a/core/builder.go b/core/builder.go index 2eb168a21351..24be960db701 100644 --- a/core/builder.go +++ b/core/builder.go @@ -3,35 +3,59 @@ package core import ( "crypto/rand" "encoding/base64" - "errors" ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" dsync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" + goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context" context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + bstore "github.com/ipfs/go-ipfs/blocks/blockstore" key "github.com/ipfs/go-ipfs/blocks/key" + bserv "github.com/ipfs/go-ipfs/blockservice" + offline "github.com/ipfs/go-ipfs/exchange/offline" + dag "github.com/ipfs/go-ipfs/merkledag" ci "github.com/ipfs/go-ipfs/p2p/crypto" + peer "github.com/ipfs/go-ipfs/p2p/peer" + path "github.com/ipfs/go-ipfs/path" + pin "github.com/ipfs/go-ipfs/pin" repo "github.com/ipfs/go-ipfs/repo" cfg "github.com/ipfs/go-ipfs/repo/config" ) -var ErrAlreadyBuilt = errors.New("this builder has already been used") +type BuildCfg struct { + // If online is set, the node will have networking enabled + Online bool -// NodeBuilder is an object used to generate an IpfsNode -type NodeBuilder struct { - online bool - routing RoutingOption - peerhost HostOption - repo repo.Repo - built bool - nilrepo bool + // If NilRepo is set, a repo backed by a nil datastore will be constructed + NilRepo bool + + Routing RoutingOption + Host HostOption + Repo repo.Repo } -func NewNodeBuilder() *NodeBuilder { - return &NodeBuilder{ - online: false, - routing: DHTOption, - peerhost: DefaultHostOption, +func (cfg *BuildCfg) fillDefaults() error { + if cfg.Repo == nil { + var d ds.Datastore + d = ds.NewMapDatastore() + if cfg.NilRepo { + d = ds.NewNullDatastore() + } + r, err := defaultRepo(dsync.MutexWrap(d)) + if err != nil { + return err + } + cfg.Repo = r + } + + if cfg.Routing == nil { + cfg.Routing = DHTOption + } + + if cfg.Host == nil { + cfg.Host = DefaultHostOption } + + return nil } func defaultRepo(dstore ds.ThreadSafeDatastore) (repo.Repo, error) { @@ -62,53 +86,71 @@ func defaultRepo(dstore ds.ThreadSafeDatastore) (repo.Repo, error) { }, nil } -func (nb *NodeBuilder) Online() *NodeBuilder { - nb.online = true - return nb -} +func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) { + if cfg == nil { + cfg = new(BuildCfg) + } -func (nb *NodeBuilder) Offline() *NodeBuilder { - nb.online = false - return nb -} + err := cfg.fillDefaults() + if err != nil { + return nil, err + } -func (nb *NodeBuilder) SetRouting(ro RoutingOption) *NodeBuilder { - nb.routing = ro - return nb -} + n := &IpfsNode{ + mode: offlineMode, + Repo: cfg.Repo, + ctx: ctx, + Peerstore: peer.NewPeerstore(), + } + if cfg.Online { + n.mode = onlineMode + } -func (nb *NodeBuilder) SetHost(ho HostOption) *NodeBuilder { - nb.peerhost = ho - return nb -} + // TODO: this is a weird circular-ish dependency, rework it + n.proc = goprocessctx.WithContextAndTeardown(ctx, n.teardown) -func (nb *NodeBuilder) SetRepo(r repo.Repo) *NodeBuilder { - nb.repo = r - return nb -} + success := false + defer func() { + if !success { + n.teardown() + } + }() -func (nb *NodeBuilder) NilRepo() *NodeBuilder { - nb.nilrepo = true - return nb -} + // setup local peer ID (private key is loaded in online setup) + if err := n.loadID(); err != nil { + return nil, err + } -func (nb *NodeBuilder) Build(ctx context.Context) (*IpfsNode, error) { - if nb.built { - return nil, ErrAlreadyBuilt + n.Blockstore, err = bstore.WriteCached(bstore.NewBlockstore(n.Repo.Datastore()), kSizeBlockstoreWriteCache) + if err != nil { + return nil, err } - nb.built = true - if nb.repo == nil { - var d ds.Datastore - d = ds.NewMapDatastore() - if nb.nilrepo { - d = ds.NewNullDatastore() - } - r, err := defaultRepo(dsync.MutexWrap(d)) - if err != nil { + + if cfg.Online { + do := setupDiscoveryOption(n.Repo.Config().Discovery) + if err := n.startOnlineServices(ctx, cfg.Routing, cfg.Host, do); err != nil { return nil, err } - nb.repo = r + } else { + n.Exchange = offline.Exchange(n.Blockstore) } - conf := standardWithRouting(nb.repo, nb.online, nb.routing, nb.peerhost) - return NewIPFSNode(ctx, conf) + + n.Blocks, err = bserv.New(n.Blockstore, n.Exchange) + if err != nil { + return nil, err + } + + n.DAG = dag.NewDAGService(n.Blocks) + n.Pinning, err = pin.LoadPinner(n.Repo.Datastore(), n.DAG) + if err != nil { + // TODO: we should move towards only running 'NewPinner' explicity on + // node init instead of implicitly here as a result of the pinner keys + // not being found in the datastore. + // this is kinda sketchy and could cause data loss + n.Pinning = pin.NewPinner(n.Repo.Datastore(), n.DAG) + } + n.Resolver = &path.Resolver{DAG: n.DAG} + + success = true + return n, nil } diff --git a/core/commands/add.go b/core/commands/add.go index 4f87054b6a06..23c7e7f26978 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -104,7 +104,9 @@ remains to be implemented. chunker, _, _ := req.Option(chunkerOptionName).String() if hash { - nilnode, err := core.NewNodeBuilder().Build(n.Context()) + nilnode, err := core.NewNode(n.Context(), &core.BuildCfg{ + NilRepo: true, + }) if err != nil { res.SetError(err, cmds.ErrNormal) return