Add support for different configs

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
Jakub Sztandera 2019-10-30 17:38:39 +01:00
parent 413314b44b
commit 3ea0997c93
No known key found for this signature in database
GPG Key ID: 9A9AF56F8B3879BA
13 changed files with 207 additions and 81 deletions

View File

@ -75,7 +75,7 @@ func (m mybs) Get(c cid.Cid) (block.Block, error) {
func NewGenerator() (*ChainGen, error) { func NewGenerator() (*ChainGen, error) {
mr := repo.NewMemory(nil) mr := repo.NewMemory(nil)
lr, err := mr.Lock() lr, err := mr.Lock(repo.RepoStorageMiner)
if err != nil { if err != nil {
return nil, xerrors.Errorf("taking mem-repo lock failed: %w", err) return nil, xerrors.Errorf("taking mem-repo lock failed: %w", err)
} }

View File

@ -101,7 +101,7 @@ var initCmd = &cli.Command{
log.Info("Initializing repo") log.Info("Initializing repo")
if err := r.Init(); err != nil { if err := r.Init(repo.RepoStorageMiner); err != nil {
return err return err
} }
@ -122,7 +122,7 @@ var initCmd = &cli.Command{
} }
func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, r repo.Repo) error { func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, r repo.Repo) error {
lr, err := r.Lock() lr, err := r.Lock(repo.RepoStorageMiner)
if err != nil { if err != nil {
return err return err
} }

View File

@ -4,9 +4,10 @@ package main
import ( import (
"context" "context"
"github.com/filecoin-project/lotus/peermgr"
"io/ioutil" "io/ioutil"
"github.com/filecoin-project/lotus/peermgr"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@ -53,7 +54,7 @@ var DaemonCmd = &cli.Command{
return err return err
} }
if err := r.Init(); err != nil && err != repo.ErrRepoExists { if err := r.Init(repo.RepoFullNode); err != nil && err != repo.ErrRepoExists {
return err return err
} }

View File

@ -15,6 +15,7 @@ import (
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
record "github.com/libp2p/go-libp2p-record" record "github.com/libp2p/go-libp2p-record"
"go.uber.org/fx" "go.uber.org/fx"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
@ -100,11 +101,6 @@ const (
_nInvokes // keep this last _nInvokes // keep this last
) )
const (
nodeFull = iota
nodeStorageMiner
)
type Settings struct { type Settings struct {
// modules is a map of constructors for DI // modules is a map of constructors for DI
// //
@ -117,14 +113,12 @@ type Settings struct {
// type, and must be applied in correct order // type, and must be applied in correct order
invokes []fx.Option invokes []fx.Option
nodeType int nodeType repo.RepoType
Online bool // Online option applied Online bool // Online option applied
Config bool // Config option applied Config bool // Config option applied
} }
var defConf = config.Default()
func defaults() []Option { func defaults() []Option {
return []Option{ return []Option{
Override(new(helpers.MetricsCtx), context.Background), Override(new(helpers.MetricsCtx), context.Background),
@ -161,10 +155,14 @@ func libp2p() Option {
Override(new(*pubsub.PubSub), lp2p.GossipSub()), Override(new(*pubsub.PubSub), lp2p.GossipSub()),
Override(PstoreAddSelfKeysKey, lp2p.PstoreAddSelfKeys), Override(PstoreAddSelfKeysKey, lp2p.PstoreAddSelfKeys),
Override(StartListeningKey, lp2p.StartListening(defConf.Libp2p.ListenAddresses)), Override(StartListeningKey, lp2p.StartListening(config.DefaultFullNode().Libp2p.ListenAddresses)),
) )
} }
func isType(t repo.RepoType) func(s *Settings) bool {
return func(s *Settings) bool { return s.nodeType == t }
}
// Online sets up basic libp2p node // Online sets up basic libp2p node
func Online() Option { func Online() Option {
return Options( return Options(
@ -181,7 +179,7 @@ func Online() Option {
// Full node // Full node
ApplyIf(func(s *Settings) bool { return s.nodeType == nodeFull }, ApplyIf(isType(repo.RepoFullNode),
// TODO: Fix offline mode // TODO: Fix offline mode
Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap), Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap),
@ -230,7 +228,7 @@ func Online() Option {
), ),
// Storage miner // Storage miner
ApplyIf(func(s *Settings) bool { return s.nodeType == nodeStorageMiner }, ApplyIf(func(s *Settings) bool { return s.nodeType == repo.RepoStorageMiner },
Override(new(*sectorbuilder.SectorBuilder), sectorbuilder.New), Override(new(*sectorbuilder.SectorBuilder), sectorbuilder.New),
Override(new(*sector.Store), sector.NewStore), Override(new(*sector.Store), sector.NewStore),
Override(new(*sectorblocks.SectorBlocks), sectorblocks.NewSectorBlocks), Override(new(*sectorblocks.SectorBlocks), sectorblocks.NewSectorBlocks),
@ -260,7 +258,7 @@ func StorageMiner(out *api.StorageMiner) Option {
), ),
func(s *Settings) error { func(s *Settings) error {
s.nodeType = nodeStorageMiner s.nodeType = repo.RepoStorageMiner
return nil return nil
}, },
@ -274,7 +272,7 @@ func StorageMiner(out *api.StorageMiner) Option {
} }
// Config sets up constructors based on the provided Config // Config sets up constructors based on the provided Config
func Config(cfg *config.Root) Option { func ConfigCommon(cfg *config.Common) Option {
return Options( return Options(
func(s *Settings) error { s.Config = true; return nil }, func(s *Settings) error { s.Config = true; return nil },
@ -284,27 +282,64 @@ func Config(cfg *config.Root) Option {
ApplyIf(func(s *Settings) bool { return len(cfg.Libp2p.BootstrapPeers) > 0 }, ApplyIf(func(s *Settings) bool { return len(cfg.Libp2p.BootstrapPeers) > 0 },
Override(new(dtypes.BootstrapPeers), modules.ConfigBootstrap(cfg.Libp2p.BootstrapPeers)), Override(new(dtypes.BootstrapPeers), modules.ConfigBootstrap(cfg.Libp2p.BootstrapPeers)),
), ),
ApplyIf(func(s *Settings) bool { return s.nodeType == nodeFull },
Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)),
),
), ),
) )
} }
func Repo(r repo.Repo) Option { func ConfigFullNode(cfg *config.FullNode) Option {
lr, err := r.Lock() //ApplyIf(func(s *Settings) bool { return s.nodeType == repo.RepoFullNode }),
return Options(
ConfigCommon(&cfg.Common),
Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)),
)
}
func repoFull(r repo.Repo) Option {
lr, err := r.Lock(repo.RepoFullNode)
if err != nil { if err != nil {
return Error(err) return Error(err)
} }
cfg, err := lr.Config() c, err := lr.Config()
if err != nil {
return Error(err)
}
cfg, ok := c.(*config.FullNode)
if !ok {
return Error(xerrors.Errorf("invalid config from repo, got: %T", c))
}
return Options(
ConfigFullNode(cfg),
Override(new(repo.LockedRepo), modules.LockedRepo(lr)), // module handles closing
)
}
func repoMiner(r repo.Repo) Option {
lr, err := r.Lock(repo.RepoStorageMiner)
if err != nil {
return Error(err)
}
c, err := lr.Config()
if err != nil { if err != nil {
return Error(err) return Error(err)
} }
cfg, ok := c.(*config.StorageMiner)
if !ok {
return Error(xerrors.Errorf("invalid config from repo, got: %T", c))
}
return Options( return Options(
Config(cfg), ConfigCommon(&cfg.Common),
Override(new(repo.LockedRepo), modules.LockedRepo(lr)), // module handles closing Override(new(repo.LockedRepo), modules.LockedRepo(lr)), // module handles closing
)
}
func Repo(r repo.Repo) Option {
return Options(
ApplyIf(isType(repo.RepoFullNode), repoFull(r)),
ApplyIf(isType(repo.RepoStorageMiner), repoMiner(r)),
Override(new(dtypes.MetadataDS), modules.Datastore), Override(new(dtypes.MetadataDS), modules.Datastore),
Override(new(dtypes.ChainBlockstore), modules.ChainBlockstore), Override(new(dtypes.ChainBlockstore), modules.ChainBlockstore),
@ -337,8 +372,9 @@ type StopFunc func(context.Context) error
// New builds and starts new Filecoin node // New builds and starts new Filecoin node
func New(ctx context.Context, opts ...Option) (StopFunc, error) { func New(ctx context.Context, opts ...Option) (StopFunc, error) {
settings := Settings{ settings := Settings{
modules: map[interface{}]fx.Option{}, modules: map[interface{}]fx.Option{},
invokes: make([]fx.Option, _nInvokes), invokes: make([]fx.Option, _nInvokes),
nodeType: repo.RepoFullNode,
} }
// apply module options in the right order // apply module options in the right order

View File

@ -1,15 +1,27 @@
package config package config
import "time" import (
"encoding"
"time"
)
// Root is starting point of the config // Common is common config between full node and miner
type Root struct { type Common struct {
API API API API
Libp2p Libp2p Libp2p Libp2p
}
// FullNode is a full node config
type FullNode struct {
Common
Metrics Metrics Metrics Metrics
} }
// StorageMiner is a storage miner config
type StorageMiner struct {
Common
}
// API contains configs for API endpoint // API contains configs for API endpoint
type API struct { type API struct {
ListenAddress string ListenAddress string
@ -26,9 +38,8 @@ type Metrics struct {
Nickname string Nickname string
} }
// Default returns the default config func defCommon() Common {
func Default() *Root { return Common{
def := Root{
API: API{ API: API{
ListenAddress: "/ip6/::1/tcp/1234/http", ListenAddress: "/ip6/::1/tcp/1234/http",
Timeout: Duration(30 * time.Second), Timeout: Duration(30 * time.Second),
@ -40,10 +51,27 @@ func Default() *Root {
}, },
}, },
} }
return &def
} }
// Duration is a wrapper type for time.Duration for decoding it from TOML // Default returns the default config
func DefaultFullNode() *FullNode {
return &FullNode{
Common: defCommon(),
}
}
func DefaultStorageMiner() *StorageMiner {
return &StorageMiner{
Common: defCommon(),
}
}
var _ encoding.TextMarshaler = (*Duration)(nil)
var _ encoding.TextUnmarshaler = (*Duration)(nil)
// Duration is a wrapper type for time.Duration
// for decoding and encoding from/to TOML
type Duration time.Duration type Duration time.Duration
// UnmarshalText implements interface for TOML decoding // UnmarshalText implements interface for TOML decoding
@ -55,3 +83,8 @@ func (dur *Duration) UnmarshalText(text []byte) error {
*dur = Duration(d) *dur = Duration(d)
return err return err
} }
func (dur Duration) MarshalText() ([]byte, error) {
d := time.Duration(dur)
return []byte(d.String()), nil
}

View File

@ -1,30 +1,32 @@
package config package config
import ( import (
"bytes"
"io" "io"
"os" "os"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"golang.org/x/xerrors"
) )
// FromFile loads config from a specified file overriding defaults specified in // FromFile loads config from a specified file overriding defaults specified in
// the source code. If file does not exist or is empty defaults are asummed. // the def parameter. If file does not exist or is empty defaults are asummed.
func FromFile(path string) (*Root, error) { func FromFile(path string, def interface{}) (interface{}, error) {
file, err := os.Open(path) file, err := os.Open(path)
switch { switch {
case os.IsNotExist(err): case os.IsNotExist(err):
return Default(), nil return def, nil
case err != nil: case err != nil:
return nil, err return nil, err
} }
defer file.Close() //nolint:errcheck // The file is RO defer file.Close() //nolint:errcheck // The file is RO
return FromReader(file) return FromReader(file, def)
} }
// FromReader loads config from a reader instance. // FromReader loads config from a reader instance.
func FromReader(reader io.Reader) (*Root, error) { func FromReader(reader io.Reader, def interface{}) (interface{}, error) {
cfg := Default() cfg := def
_, err := toml.DecodeReader(reader, cfg) _, err := toml.DecodeReader(reader, cfg)
if err != nil { if err != nil {
return nil, err return nil, err
@ -32,3 +34,16 @@ func FromReader(reader io.Reader) (*Root, error) {
return cfg, nil return cfg, nil
} }
func ConfigComment(t interface{}) ([]byte, error) {
buf := new(bytes.Buffer)
_, _ = buf.WriteString("# Default config:\n")
e := toml.NewEncoder(buf)
if err := e.Encode(t); err != nil {
return nil, xerrors.Errorf("encoding config: %w", err)
}
b := buf.Bytes()
b = bytes.ReplaceAll(b, []byte("\n"), []byte("\n#"))
return b, nil
}

View File

@ -14,16 +14,16 @@ func TestDecodeNothing(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
{ {
cfg, err := FromFile(os.DevNull) cfg, err := FromFile(os.DevNull, DefaultFullNode())
assert.Nil(err, "error should be nil") assert.Nil(err, "error should be nil")
assert.Equal(Default(), cfg, assert.Equal(DefaultFullNode(), cfg,
"config from empty file should be the same as default") "config from empty file should be the same as default")
} }
{ {
cfg, err := FromFile("./does-not-exist.toml") cfg, err := FromFile("./does-not-exist.toml", DefaultFullNode())
assert.Nil(err, "error should be nil") assert.Nil(err, "error should be nil")
assert.Equal(Default(), cfg, assert.Equal(DefaultFullNode(), cfg,
"config from not exisiting file should be the same as default") "config from not exisiting file should be the same as default")
} }
} }
@ -34,11 +34,11 @@ func TestParitalConfig(t *testing.T) {
[API] [API]
Timeout = "10s" Timeout = "10s"
` `
expected := Default() expected := DefaultFullNode()
expected.API.Timeout = Duration(10 * time.Second) expected.API.Timeout = Duration(10 * time.Second)
{ {
cfg, err := FromReader(bytes.NewReader([]byte(cfgString))) cfg, err := FromReader(bytes.NewReader([]byte(cfgString)), DefaultFullNode())
assert.NoError(err, "error should be nil") assert.NoError(err, "error should be nil")
assert.Equal(expected, cfg, assert.Equal(expected, cfg,
"config from reader should contain changes") "config from reader should contain changes")
@ -55,7 +55,7 @@ func TestParitalConfig(t *testing.T) {
assert.NoError(err, "closing tmp file should not error") assert.NoError(err, "closing tmp file should not error")
defer os.Remove(fname) //nolint:errcheck defer os.Remove(fname) //nolint:errcheck
cfg, err := FromFile(fname) cfg, err := FromFile(fname, DefaultFullNode())
assert.Nil(err, "error should be nil") assert.Nil(err, "error should be nil")
assert.Equal(expected, cfg, assert.Equal(expected, cfg,
"config from reader should contain changes") "config from reader should contain changes")

View File

@ -34,7 +34,7 @@ import (
func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, act address.Address, tnd test.TestNode) test.TestStorageNode { func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, act address.Address, tnd test.TestNode) test.TestStorageNode {
r := repo.NewMemory(nil) r := repo.NewMemory(nil)
lr, err := r.Lock() lr, err := r.Lock(repo.RepoStorageMiner)
require.NoError(t, err) require.NoError(t, err)
pk, _, err := crypto.GenerateEd25519Key(rand.Reader) pk, _, err := crypto.GenerateEd25519Key(rand.Reader)

View File

@ -2,6 +2,7 @@ package repo
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
@ -33,13 +34,33 @@ const (
fsKeystore = "keystore" fsKeystore = "keystore"
) )
type RepoType int
const (
_ = iota // Default is invalid
RepoFullNode RepoType = iota
RepoStorageMiner
)
func defConfForType(t RepoType) interface{} {
switch t {
case RepoFullNode:
return config.DefaultFullNode()
case RepoStorageMiner:
return config.DefaultStorageMiner()
default:
panic(fmt.Sprintf("unknown RepoType(%d)", int(t)))
}
}
var log = logging.Logger("repo") var log = logging.Logger("repo")
var ErrRepoExists = xerrors.New("repo exists") var ErrRepoExists = xerrors.New("repo exists")
// FsRepo is struct for repo, use NewFS to create // FsRepo is struct for repo, use NewFS to create
type FsRepo struct { type FsRepo struct {
path string path string
repoType RepoType
} }
var _ Repo = &FsRepo{} var _ Repo = &FsRepo{}
@ -65,7 +86,7 @@ func (fsr *FsRepo) Exists() (bool, error) {
return !notexist, err return !notexist, err
} }
func (fsr *FsRepo) Init() error { func (fsr *FsRepo) Init(t RepoType) error {
exist, err := fsr.Exists() exist, err := fsr.Exists()
if err != nil { if err != nil {
return err return err
@ -79,18 +100,36 @@ func (fsr *FsRepo) Init() error {
if err != nil && !os.IsExist(err) { if err != nil && !os.IsExist(err) {
return err return err
} }
c, err := os.Create(filepath.Join(fsr.path, fsConfig))
if err != nil { if err := fsr.initConfig(t); err != nil {
return err return xerrors.Errorf("init config: %w", err)
}
if err := c.Close(); err != nil {
return err
} }
return fsr.initKeystore() return fsr.initKeystore()
} }
func (fsr *FsRepo) initConfig(t RepoType) error {
c, err := os.Create(filepath.Join(fsr.path, fsConfig))
if err != nil {
return err
}
comm, err := config.ConfigComment(defConfForType(t))
if err != nil {
return xerrors.Errorf("comment: %w", err)
}
_, err = c.Write(comm)
if err != nil {
return xerrors.Errorf("write config: %w", err)
}
if err := c.Close(); err != nil {
return xerrors.Errorf("close config: %w", err)
}
return nil
}
func (fsr *FsRepo) initKeystore() error { func (fsr *FsRepo) initKeystore() error {
kstorePath := filepath.Join(fsr.path, fsKeystore) kstorePath := filepath.Join(fsr.path, fsKeystore)
if _, err := os.Stat(kstorePath); err == nil { if _, err := os.Stat(kstorePath); err == nil {
@ -142,7 +181,7 @@ func (fsr *FsRepo) APIToken() ([]byte, error) {
} }
// Lock acquires exclusive lock on this repo // Lock acquires exclusive lock on this repo
func (fsr *FsRepo) Lock() (LockedRepo, error) { func (fsr *FsRepo) Lock(repoType RepoType) (LockedRepo, error) {
locked, err := fslock.Locked(fsr.path, fsLock) locked, err := fslock.Locked(fsr.path, fsLock)
if err != nil { if err != nil {
return nil, xerrors.Errorf("could not check lock status: %w", err) return nil, xerrors.Errorf("could not check lock status: %w", err)
@ -156,14 +195,16 @@ func (fsr *FsRepo) Lock() (LockedRepo, error) {
return nil, xerrors.Errorf("could not lock the repo: %w", err) return nil, xerrors.Errorf("could not lock the repo: %w", err)
} }
return &fsLockedRepo{ return &fsLockedRepo{
path: fsr.path, path: fsr.path,
closer: closer, repoType: repoType,
closer: closer,
}, nil }, nil
} }
type fsLockedRepo struct { type fsLockedRepo struct {
path string path string
closer io.Closer repoType RepoType
closer io.Closer
ds datastore.Batching ds datastore.Batching
dsErr error dsErr error
@ -219,11 +260,11 @@ func (fsr *fsLockedRepo) Datastore(ns string) (datastore.Batching, error) {
return namespace.Wrap(fsr.ds, datastore.NewKey(ns)), nil return namespace.Wrap(fsr.ds, datastore.NewKey(ns)), nil
} }
func (fsr *fsLockedRepo) Config() (*config.Root, error) { func (fsr *fsLockedRepo) Config() (interface{}, error) {
if err := fsr.stillValid(); err != nil { if err := fsr.stillValid(); err != nil {
return nil, err return nil, err
} }
return config.FromFile(fsr.join(fsConfig)) return config.FromFile(fsr.join(fsConfig), defConfForType(fsr.repoType))
} }
func (fsr *fsLockedRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error { func (fsr *fsLockedRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {

View File

@ -17,7 +17,7 @@ func genFsRepo(t *testing.T) (*FsRepo, func()) {
t.Fatal(err) t.Fatal(err)
} }
err = repo.Init() err = repo.Init(RepoFullNode)
if err != ErrRepoExists && err != nil { if err != ErrRepoExists && err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -7,7 +7,6 @@ import (
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/config"
) )
var ( var (
@ -25,7 +24,7 @@ type Repo interface {
APIToken() ([]byte, error) APIToken() ([]byte, error)
// Lock locks the repo for exclusive use. // Lock locks the repo for exclusive use.
Lock() (LockedRepo, error) Lock(RepoType) (LockedRepo, error)
} }
type LockedRepo interface { type LockedRepo interface {
@ -36,7 +35,7 @@ type LockedRepo interface {
Datastore(namespace string) (datastore.Batching, error) Datastore(namespace string) (datastore.Batching, error)
// Returns config in this repo // Returns config in this repo
Config() (*config.Root, error) Config() (interface{}, error)
// SetAPIEndpoint sets the endpoint of the current API // SetAPIEndpoint sets the endpoint of the current API
// so it can be read by API clients // so it can be read by API clients

View File

@ -10,7 +10,6 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/config"
) )
type MemRepo struct { type MemRepo struct {
@ -24,12 +23,13 @@ type MemRepo struct {
token *byte token *byte
datastore datastore.Datastore datastore datastore.Datastore
configF func() *config.Root configF func(t RepoType) interface{}
keystore map[string]types.KeyInfo keystore map[string]types.KeyInfo
} }
type lockedMemRepo struct { type lockedMemRepo struct {
mem *MemRepo mem *MemRepo
t RepoType
sync.RWMutex sync.RWMutex
token *byte token *byte
@ -44,7 +44,7 @@ var _ Repo = &MemRepo{}
// MemRepoOptions contains options for memory repo // MemRepoOptions contains options for memory repo
type MemRepoOptions struct { type MemRepoOptions struct {
Ds datastore.Datastore Ds datastore.Datastore
ConfigF func() *config.Root ConfigF func(RepoType) interface{}
KeyStore map[string]types.KeyInfo KeyStore map[string]types.KeyInfo
} }
@ -56,7 +56,7 @@ func NewMemory(opts *MemRepoOptions) *MemRepo {
opts = &MemRepoOptions{} opts = &MemRepoOptions{}
} }
if opts.ConfigF == nil { if opts.ConfigF == nil {
opts.ConfigF = config.Default opts.ConfigF = defConfForType
} }
if opts.Ds == nil { if opts.Ds == nil {
opts.Ds = dssync.MutexWrap(datastore.NewMapDatastore()) opts.Ds = dssync.MutexWrap(datastore.NewMapDatastore())
@ -92,7 +92,7 @@ func (mem *MemRepo) APIToken() ([]byte, error) {
return mem.api.token, nil return mem.api.token, nil
} }
func (mem *MemRepo) Lock() (LockedRepo, error) { func (mem *MemRepo) Lock(t RepoType) (LockedRepo, error) {
select { select {
case mem.repoLock <- struct{}{}: case mem.repoLock <- struct{}{}:
default: default:
@ -102,6 +102,7 @@ func (mem *MemRepo) Lock() (LockedRepo, error) {
return &lockedMemRepo{ return &lockedMemRepo{
mem: mem, mem: mem,
t: t,
token: mem.token, token: mem.token,
}, nil }, nil
} }
@ -143,11 +144,11 @@ func (lmem *lockedMemRepo) Datastore(ns string) (datastore.Batching, error) {
return namespace.Wrap(lmem.mem.datastore, datastore.NewKey(ns)), nil return namespace.Wrap(lmem.mem.datastore, datastore.NewKey(ns)), nil
} }
func (lmem *lockedMemRepo) Config() (*config.Root, error) { func (lmem *lockedMemRepo) Config() (interface{}, error) {
if err := lmem.checkToken(); err != nil { if err := lmem.checkToken(); err != nil {
return nil, err return nil, err
} }
return lmem.mem.configF(), nil return lmem.mem.configF(lmem.t), nil
} }
func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error { func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {

View File

@ -18,12 +18,12 @@ func basicTest(t *testing.T, repo Repo) {
} }
assert.Nil(t, apima, "with no api endpoint, return should be nil") assert.Nil(t, apima, "with no api endpoint, return should be nil")
lrepo, err := repo.Lock() lrepo, err := repo.Lock(RepoFullNode)
assert.NoError(t, err, "should be able to lock once") assert.NoError(t, err, "should be able to lock once")
assert.NotNil(t, lrepo, "locked repo shouldn't be nil") assert.NotNil(t, lrepo, "locked repo shouldn't be nil")
{ {
lrepo2, err := repo.Lock() lrepo2, err := repo.Lock(RepoFullNode)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Equal(t, ErrRepoAlreadyLocked, err) assert.Equal(t, ErrRepoAlreadyLocked, err)
} }
@ -33,7 +33,7 @@ func basicTest(t *testing.T, repo Repo) {
err = lrepo.Close() err = lrepo.Close()
assert.NoError(t, err, "should be able to unlock") assert.NoError(t, err, "should be able to unlock")
lrepo, err = repo.Lock() lrepo, err = repo.Lock(RepoFullNode)
assert.NoError(t, err, "should be able to relock") assert.NoError(t, err, "should be able to relock")
assert.NotNil(t, lrepo, "locked repo shouldn't be nil") assert.NotNil(t, lrepo, "locked repo shouldn't be nil")
@ -48,7 +48,7 @@ func basicTest(t *testing.T, repo Repo) {
assert.Equal(t, ma, apima, "returned API multiaddr should be the same") assert.Equal(t, ma, apima, "returned API multiaddr should be the same")
cfg, err := lrepo.Config() cfg, err := lrepo.Config()
assert.Equal(t, config.Default(), cfg, "there should be a default config") assert.Equal(t, config.DefaultFullNode(), cfg, "there should be a default config")
assert.NoError(t, err, "config should not error") assert.NoError(t, err, "config should not error")
err = lrepo.Close() err = lrepo.Close()
@ -64,7 +64,7 @@ func basicTest(t *testing.T, repo Repo) {
k1 := types.KeyInfo{Type: "foo"} k1 := types.KeyInfo{Type: "foo"}
k2 := types.KeyInfo{Type: "bar"} k2 := types.KeyInfo{Type: "bar"}
lrepo, err = repo.Lock() lrepo, err = repo.Lock(RepoFullNode)
assert.NoError(t, err, "should be able to relock") assert.NoError(t, err, "should be able to relock")
assert.NotNil(t, lrepo, "locked repo shouldn't be nil") assert.NotNil(t, lrepo, "locked repo shouldn't be nil")