Implement memrepo
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
b843dcb590
commit
195cf4f84d
2
go.mod
2
go.mod
@ -23,6 +23,7 @@ require (
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.0
|
||||
github.com/libp2p/go-libp2p-connmgr v0.1.0
|
||||
github.com/libp2p/go-libp2p-core v0.0.6
|
||||
github.com/libp2p/go-libp2p-crypto v0.1.0
|
||||
github.com/libp2p/go-libp2p-discovery v0.1.0
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.1.1
|
||||
github.com/libp2p/go-libp2p-mplex v0.2.1
|
||||
@ -50,6 +51,7 @@ require (
|
||||
go.uber.org/dig v1.7.0 // indirect
|
||||
go.uber.org/fx v1.9.0
|
||||
go.uber.org/goleak v0.10.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522
|
||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
||||
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect
|
||||
)
|
||||
|
43
node/repo/interface.go
Normal file
43
node/repo/interface.go
Normal file
@ -0,0 +1,43 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/node/config"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoAPIEndpoint = xerrors.New("no API Endpoint set")
|
||||
ErrRepoAlreadyLocked = xerrors.New("repo is already locked")
|
||||
ErrClosedRepo = xerrors.New("repo is no longer open")
|
||||
)
|
||||
|
||||
type Repo interface {
|
||||
// APIEndpoint returns multiaddress for communication with Lotus API
|
||||
APIEndpoint() (multiaddr.Multiaddr, error)
|
||||
|
||||
// Lock locks the repo for exclusive use.
|
||||
Lock() (LockedRepo, error)
|
||||
}
|
||||
|
||||
type LockedRepo interface {
|
||||
// Close closes repo and removes lock.
|
||||
Close() error
|
||||
|
||||
// Returns datastore defined in this repo.
|
||||
Datastore() (datastore.Datastore, error)
|
||||
|
||||
// Returns config in this repo
|
||||
Config() (*config.Root, error)
|
||||
|
||||
// Libp2pIdentity returns private key for libp2p indentity
|
||||
Libp2pIdentity() (crypto.PrivKey, error)
|
||||
|
||||
SetAPIEndpoint(multiaddr.Multiaddr) error
|
||||
|
||||
// Wallet returns store of private keys for Filecoin transactions
|
||||
Wallet() (interface{}, error)
|
||||
}
|
160
node/repo/memrepo.go
Normal file
160
node/repo/memrepo.go
Normal file
@ -0,0 +1,160 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/node/config"
|
||||
"github.com/ipfs/go-datastore"
|
||||
dssync "github.com/ipfs/go-datastore/sync"
|
||||
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
type MemRepo struct {
|
||||
api struct {
|
||||
sync.Mutex
|
||||
ma multiaddr.Multiaddr
|
||||
}
|
||||
|
||||
repoLock chan struct{}
|
||||
token *byte
|
||||
|
||||
datastore datastore.Datastore
|
||||
configF func() *config.Root
|
||||
libp2pKey crypto.PrivKey
|
||||
wallet interface{}
|
||||
}
|
||||
|
||||
type lockedMemRepo struct {
|
||||
mem *MemRepo
|
||||
sync.RWMutex
|
||||
|
||||
token *byte
|
||||
}
|
||||
|
||||
var _ Repo = &MemRepo{}
|
||||
|
||||
type MemRepoOptions struct {
|
||||
ds datastore.Datastore
|
||||
configF func() *config.Root
|
||||
libp2pKey crypto.PrivKey
|
||||
wallet interface{}
|
||||
}
|
||||
|
||||
func NewMemory(opts *MemRepoOptions) *MemRepo {
|
||||
if opts == nil {
|
||||
opts = &MemRepoOptions{}
|
||||
}
|
||||
if opts.configF == nil {
|
||||
opts.configF = config.Default
|
||||
}
|
||||
if opts.ds == nil {
|
||||
opts.ds = dssync.MutexWrap(datastore.NewMapDatastore())
|
||||
}
|
||||
if opts.libp2pKey == nil {
|
||||
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
opts.libp2pKey = pk
|
||||
}
|
||||
|
||||
return &MemRepo{
|
||||
repoLock: make(chan struct{}, 1),
|
||||
|
||||
datastore: opts.ds,
|
||||
configF: opts.configF,
|
||||
libp2pKey: opts.libp2pKey,
|
||||
wallet: opts.wallet,
|
||||
}
|
||||
}
|
||||
|
||||
func (mem *MemRepo) APIEndpoint() (multiaddr.Multiaddr, error) {
|
||||
mem.api.Lock()
|
||||
defer mem.api.Unlock()
|
||||
if mem.api.ma == nil {
|
||||
return nil, ErrNoAPIEndpoint
|
||||
}
|
||||
return mem.api.ma, nil
|
||||
}
|
||||
|
||||
func (mem *MemRepo) Lock() (LockedRepo, error) {
|
||||
select {
|
||||
case mem.repoLock <- struct{}{}:
|
||||
default:
|
||||
return nil, ErrRepoAlreadyLocked
|
||||
}
|
||||
mem.token = new(byte)
|
||||
|
||||
return &lockedMemRepo{
|
||||
mem: mem,
|
||||
token: mem.token,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) checkToken() error {
|
||||
lmem.RLock()
|
||||
defer lmem.RUnlock()
|
||||
if lmem.mem.token != lmem.token {
|
||||
return ErrClosedRepo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) Close() error {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return err
|
||||
}
|
||||
lmem.Lock()
|
||||
defer lmem.Unlock()
|
||||
|
||||
if lmem.mem.token != lmem.token {
|
||||
return ErrClosedRepo
|
||||
}
|
||||
|
||||
lmem.mem.token = nil
|
||||
lmem.mem.api.Lock()
|
||||
lmem.mem.api.ma = nil
|
||||
lmem.mem.api.Unlock()
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) Datastore() (datastore.Datastore, error) {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lmem.mem.datastore, nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) Config() (*config.Root, error) {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lmem.mem.configF(), nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) Libp2pIdentity() (crypto.PrivKey, error) {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lmem.mem.libp2pKey, nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) SetAPIEndpoint(ma multiaddr.Multiaddr) error {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return err
|
||||
}
|
||||
lmem.mem.api.Lock()
|
||||
lmem.mem.api.ma = ma
|
||||
lmem.mem.api.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lmem *lockedMemRepo) Wallet() (interface{}, error) {
|
||||
if err := lmem.checkToken(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lmem.mem.wallet, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user