From 4b5ff960c93ae478cbf174cea175fdd5924d76ac Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 15 Jan 2015 11:28:14 -0800 Subject: [PATCH] feat(core): use repo.Repo in core constructor --- cmd/ipfs/init.go | 12 ++++++---- cmd/ipfs/main.go | 14 +++++++----- core/core.go | 45 ++++++++++++++++---------------------- core/core_test.go | 14 ++++++++++-- core/mock.go | 12 +++++----- repo/repo.go | 4 ++++ test/epictest/core.go | 15 ++++++++----- util/testutil/datastore.go | 11 ++++++++++ 8 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 util/testutil/datastore.go diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index 1791b28cf..7afa23e70 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -106,7 +106,7 @@ func doInit(repoRoot string, force bool, nBitsForKeypair int) (interface{}, erro if err := repo.ConfigureEventLogger(conf.Logs); err != nil { return nil, err } - err = addTheWelcomeFile(conf) + err = addTheWelcomeFile(repoRoot) if err != nil { return nil, err } @@ -116,15 +116,19 @@ func doInit(repoRoot string, force bool, nBitsForKeypair int) (interface{}, erro // addTheWelcomeFile adds a file containing the welcome message to the newly // minted node. On success, it calls onSuccess -func addTheWelcomeFile(conf *config.Config) error { +func addTheWelcomeFile(repoRoot string) error { // TODO extract this file creation operation into a function ctx, cancel := context.WithCancel(context.Background()) - nd, err := core.NewIPFSNode(ctx, core.Offline(conf)) + defer cancel() + r := fsrepo.At(repoRoot) + if err := r.Open(); err != nil { // NB: repo is owned by the node + return err + } + nd, err := core.NewIPFSNode(ctx, core.Offline(r)) if err != nil { return err } defer nd.Close() - defer cancel() // Set up default file reader := bytes.NewBufferString(welcomeMsg) diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index f2cdf9e00..6b722c7ef 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -181,15 +181,19 @@ func (i *cmdInvocation) constructNodeFunc(ctx context.Context) func() (*core.Ipf return nil, errors.New("constructing node without a request context") } - cfg, err := cmdctx.GetConfig() - if err != nil { - return nil, fmt.Errorf("constructing node without a config: %s", err) + r := fsrepo.At(i.req.Context().ConfigRoot) + if err := r.Open(); err != nil { + return nil, err } // ok everything is good. set it on the invocation (for ownership) // and return it. - i.node, err = core.NewIPFSNode(ctx, core.Standard(cfg, cmdctx.Online)) - return i.node, err + n, err := core.NewIPFSNode(ctx, core.Standard(r, cmdctx.Online)) + if err != nil { + return nil, err + } + i.node = n + return i.node, nil } } diff --git a/core/core.go b/core/core.go index f643890d4..28c53b5c6 100644 --- a/core/core.go +++ b/core/core.go @@ -29,11 +29,11 @@ import ( peer "github.com/jbenet/go-ipfs/p2p/peer" path "github.com/jbenet/go-ipfs/path" pin "github.com/jbenet/go-ipfs/pin" + repo "github.com/jbenet/go-ipfs/repo" config "github.com/jbenet/go-ipfs/repo/config" routing "github.com/jbenet/go-ipfs/routing" dht "github.com/jbenet/go-ipfs/routing/dht" util "github.com/jbenet/go-ipfs/util" - ds2 "github.com/jbenet/go-ipfs/util/datastore2" debugerror "github.com/jbenet/go-ipfs/util/debugerror" eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog" lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables" @@ -59,9 +59,7 @@ type IpfsNode struct { // Self Identity peer.ID // the local node's identity - // TODO abstract as repo.Repo - Config *config.Config // the node's configuration - Datastore ds2.ThreadSafeDatastoreCloser // the local datastore + Repo repo.Repo // Local node Pinning pin.Pinner // the pinning manager @@ -120,24 +118,24 @@ func NewIPFSNode(ctx context.Context, option ConfigOption) (*IpfsNode, error) { node.Peerstore = peer.NewPeerstore() } node.DAG = merkledag.NewDAGService(node.Blocks) - node.Pinning, err = pin.LoadPinner(node.Datastore, node.DAG) + node.Pinning, err = pin.LoadPinner(node.Repo.Datastore(), node.DAG) if err != nil { - node.Pinning = pin.NewPinner(node.Datastore, node.DAG) + node.Pinning = pin.NewPinner(node.Repo.Datastore(), node.DAG) } node.Resolver = &path.Resolver{DAG: node.DAG} return node, nil } -func Offline(cfg *config.Config) ConfigOption { - return Standard(cfg, false) +func Offline(r repo.Repo) ConfigOption { + return Standard(r, false) } -func Online(cfg *config.Config) ConfigOption { - return Standard(cfg, true) +func Online(r repo.Repo) ConfigOption { + return Standard(r, true) } // DEPRECATED: use Online, Offline functions -func Standard(cfg *config.Config, online bool) ConfigOption { +func Standard(r repo.Repo, online bool) ConfigOption { return func(ctx context.Context) (n *IpfsNode, err error) { success := false // flip to true after all sub-system inits succeed @@ -147,8 +145,8 @@ func Standard(cfg *config.Config, online bool) ConfigOption { } }() - if cfg == nil { - return nil, debugerror.Errorf("configuration required") + if r == nil { + return nil, debugerror.Errorf("repo required") } n = &IpfsNode{ mode: func() mode { @@ -157,7 +155,7 @@ func Standard(cfg *config.Config, online bool) ConfigOption { } return offlineMode }(), - Config: cfg, + Repo: r, } n.ContextGroup = ctxgroup.WithContextAndTeardown(ctx, n.teardown) @@ -166,17 +164,12 @@ func Standard(cfg *config.Config, online bool) ConfigOption { // setup Peerstore n.Peerstore = peer.NewPeerstore() - // setup datastore. - if n.Datastore, err = makeDatastore(cfg.Datastore); err != nil { - return nil, debugerror.Wrap(err) - } - // setup local peer ID (private key is loaded in online setup) if err := n.loadID(); err != nil { return nil, err } - n.Blockstore, err = bstore.WriteCached(bstore.NewBlockstore(n.Datastore), kSizeBlockstoreWriteCache) + n.Blockstore, err = bstore.WriteCached(bstore.NewBlockstore(n.Repo.Datastore()), kSizeBlockstoreWriteCache) if err != nil { return nil, debugerror.Wrap(err) } @@ -207,7 +200,7 @@ func (n *IpfsNode) StartOnlineServices() error { return err } - peerhost, err := constructPeerHost(ctx, n.ContextGroup, n.Config, n.Identity, n.Peerstore) + peerhost, err := constructPeerHost(ctx, n.ContextGroup, n.Repo.Config(), n.Identity, n.Peerstore) if err != nil { return debugerror.Wrap(err) } @@ -217,7 +210,7 @@ func (n *IpfsNode) StartOnlineServices() error { n.Diagnostics = diag.NewDiagnostics(n.Identity, n.PeerHost) // setup routing service - dhtRouting, err := constructDHTRouting(ctx, n.ContextGroup, n.PeerHost, n.Datastore) + dhtRouting, err := constructDHTRouting(ctx, n.ContextGroup, n.PeerHost, n.Repo.Datastore()) if err != nil { return debugerror.Wrap(err) } @@ -240,7 +233,7 @@ func (n *IpfsNode) StartOnlineServices() error { // manage the wiring. In that scenario, this dangling function is a bit // awkward. var bootstrapPeers []peer.PeerInfo - for _, bootstrap := range n.Config.Bootstrap { + for _, bootstrap := range n.Repo.Config().Bootstrap { p, err := toPeer(bootstrap) if err != nil { log.Event(ctx, "bootstrapError", n.Identity, lgbl.Error(err)) @@ -258,7 +251,7 @@ func (n *IpfsNode) StartOnlineServices() error { } func (n *IpfsNode) teardown() error { - if err := n.Datastore.Close(); err != nil { + if err := n.Repo.Close(); err != nil { return err } return nil @@ -293,7 +286,7 @@ func (n *IpfsNode) loadID() error { return debugerror.New("identity already loaded") } - cid := n.Config.Identity.PeerID + cid := n.Repo.Config().Identity.PeerID if cid == "" { return debugerror.New("Identity was not set in config (was ipfs init run?)") } @@ -314,7 +307,7 @@ func (n *IpfsNode) loadPrivateKey() error { return debugerror.New("private key already loaded") } - sk, err := loadPrivateKey(&n.Config.Identity, n.Identity) + sk, err := loadPrivateKey(&n.Repo.Config().Identity, n.Identity) if err != nil { return err } diff --git a/core/core_test.go b/core/core_test.go index 5931cffd0..293bac0f6 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -4,7 +4,9 @@ import ( "testing" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" + "github.com/jbenet/go-ipfs/repo" config "github.com/jbenet/go-ipfs/repo/config" + "github.com/jbenet/go-ipfs/util/testutil" ) func TestInitialization(t *testing.T) { @@ -42,14 +44,22 @@ func TestInitialization(t *testing.T) { } for i, c := range good { - n, err := NewIPFSNode(ctx, Standard(c, false)) + r := &repo.Mock{ + C: *c, + D: testutil.ThreadSafeCloserMapDatastore(), + } + n, err := NewIPFSNode(ctx, Standard(r, false)) if n == nil || err != nil { t.Error("Should have constructed.", i, err) } } for i, c := range bad { - n, err := NewIPFSNode(ctx, Standard(c, false)) + r := &repo.Mock{ + C: *c, + D: testutil.ThreadSafeCloserMapDatastore(), + } + n, err := NewIPFSNode(ctx, Standard(r, false)) if n != nil || err == nil { t.Error("Should have failed to construct.", i) } diff --git a/core/mock.go b/core/mock.go index e4c15540b..040aab03e 100644 --- a/core/mock.go +++ b/core/mock.go @@ -2,8 +2,7 @@ package core import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" - - ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" syncds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" "github.com/jbenet/go-ipfs/blocks/blockstore" blockservice "github.com/jbenet/go-ipfs/blockservice" @@ -13,6 +12,7 @@ import ( mocknet "github.com/jbenet/go-ipfs/p2p/net/mock" peer "github.com/jbenet/go-ipfs/p2p/peer" path "github.com/jbenet/go-ipfs/path" + "github.com/jbenet/go-ipfs/repo" mockrouting "github.com/jbenet/go-ipfs/routing/mock" ds2 "github.com/jbenet/go-ipfs/util/datastore2" testutil "github.com/jbenet/go-ipfs/util/testutil" @@ -46,14 +46,16 @@ func NewMockNode() (*IpfsNode, error) { } // Temp Datastore - dstore := ds.NewMapDatastore() - nd.Datastore = ds2.CloserWrap(syncds.MutexWrap(dstore)) + nd.Repo = &repo.Mock{ + // TODO C: conf, + D: ds2.CloserWrap(syncds.MutexWrap(datastore.NewMapDatastore())), + } // Routing nd.Routing = mockrouting.NewServer().Client(ident) // Bitswap - bstore := blockstore.NewBlockstore(nd.Datastore) + bstore := blockstore.NewBlockstore(nd.Repo.Datastore()) bserv, err := blockservice.New(bstore, offline.Exchange(bstore)) if err != nil { return nil, err diff --git a/repo/repo.go b/repo/repo.go index 616c1ebc9..ee6899779 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -1,6 +1,8 @@ package repo import ( + "io" + datastore "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" config "github.com/jbenet/go-ipfs/repo/config" util "github.com/jbenet/go-ipfs/util" @@ -14,6 +16,8 @@ type Repo interface { GetConfigKey(key string) (interface{}, error) Datastore() datastore.ThreadSafeDatastore + + io.Closer } // IsInitialized returns true if the path is home to an initialized IPFS diff --git a/test/epictest/core.go b/test/epictest/core.go index 2208a8f60..23a4a6ffc 100644 --- a/test/epictest/core.go +++ b/test/epictest/core.go @@ -2,19 +2,19 @@ package epictest import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" - datastore "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" - sync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" - + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" + syncds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" blockstore "github.com/jbenet/go-ipfs/blocks/blockstore" core "github.com/jbenet/go-ipfs/core" bitswap "github.com/jbenet/go-ipfs/exchange/bitswap" bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network" host "github.com/jbenet/go-ipfs/p2p/host" peer "github.com/jbenet/go-ipfs/p2p/peer" + "github.com/jbenet/go-ipfs/repo" dht "github.com/jbenet/go-ipfs/routing/dht" delay "github.com/jbenet/go-ipfs/thirdparty/delay" eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog" - "github.com/jbenet/go-ipfs/util/datastore2" + ds2 "github.com/jbenet/go-ipfs/util/datastore2" testutil "github.com/jbenet/go-ipfs/util/testutil" ) @@ -25,7 +25,10 @@ func MocknetTestRepo(p peer.ID, h host.Host, conf testutil.LatencyConfig) core.C const kWriteCacheElems = 100 const alwaysSendToPeer = true dsDelay := delay.Fixed(conf.BlockstoreLatency) - ds := datastore2.CloserWrap(sync.MutexWrap(datastore2.WithDelay(datastore.NewMapDatastore(), dsDelay))) + r := &repo.Mock{ + D: ds2.CloserWrap(syncds.MutexWrap(ds2.WithDelay(datastore.NewMapDatastore(), dsDelay))), + } + ds := r.Datastore() log.Debugf("MocknetTestRepo: %s %s %s", p, h.ID(), h) dhtt := dht.NewDHT(ctx, h, ds) @@ -39,7 +42,7 @@ func MocknetTestRepo(p peer.ID, h host.Host, conf testutil.LatencyConfig) core.C Peerstore: h.Peerstore(), Blockstore: bstore, Exchange: exch, - Datastore: ds, + Repo: r, PeerHost: h, Routing: dhtt, Identity: p, diff --git a/util/testutil/datastore.go b/util/testutil/datastore.go new file mode 100644 index 000000000..d635df428 --- /dev/null +++ b/util/testutil/datastore.go @@ -0,0 +1,11 @@ +package testutil + +import ( + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" + syncds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" + ds2 "github.com/jbenet/go-ipfs/util/datastore2" +) + +func ThreadSafeCloserMapDatastore() ds2.ThreadSafeDatastoreCloser { + return ds2.CloserWrap(syncds.MutexWrap(datastore.NewMapDatastore())) +}