make the lotus node use the new native badger blockstore.
This commit is contained in:
parent
ce27b13076
commit
d2e2322fd2
@ -77,12 +77,12 @@ func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ChainBlockstore(lc fx.Lifecycle, mctx helpers.MetricsCtx, r repo.LockedRepo) (dtypes.ChainBlockstore, error) {
|
func ChainBlockstore(lc fx.Lifecycle, mctx helpers.MetricsCtx, r repo.LockedRepo) (dtypes.ChainBlockstore, error) {
|
||||||
blocks, err := r.Datastore("/chain")
|
bs, err := r.Blockstore(repo.BlockstoreChain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bs := blockstore.NewBlockstore(blocks)
|
// TODO potentially replace this cached blockstore by a CBOR cache.
|
||||||
cbs, err := blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, blockstore.DefaultCacheOpts())
|
cbs, err := blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, blockstore.DefaultCacheOpts())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
fslock "github.com/ipfs/go-fs-lock"
|
fslock "github.com/ipfs/go-fs-lock"
|
||||||
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/multiformats/go-base32"
|
"github.com/multiformats/go-base32"
|
||||||
@ -22,6 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||||
|
badgerbs "github.com/filecoin-project/lotus/lib/blockstore/badger"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/node/config"
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
@ -284,6 +286,52 @@ func (fsr *fsLockedRepo) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fsr *fsLockedRepo) Blockstore(domain BlockstoreDomain) (blockstore.Blockstore, error) {
|
||||||
|
if domain != BlockstoreChain {
|
||||||
|
return nil, ErrInvalidBlockstoreDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
path := fsr.join(filepath.Join(fsDatastore, "chain"))
|
||||||
|
opts := badgerbs.DefaultOptions(path)
|
||||||
|
|
||||||
|
// Due to legacy usage of blockstore.Blockstore, over a datastore, all
|
||||||
|
// blocks are prefixed with this namespace. In the future, this can go away,
|
||||||
|
// in order to shorten keys, but it'll require a migration.
|
||||||
|
opts.Prefix = "/blocks/"
|
||||||
|
|
||||||
|
// Blockstore values are immutable; therefore we do not expect any
|
||||||
|
// conflicts to emerge.
|
||||||
|
opts.DetectConflicts = false
|
||||||
|
|
||||||
|
// This is to optimize the database on close so it can be opened
|
||||||
|
// read-only and efficiently queried. We don't do that and hanging on
|
||||||
|
// stop isn't nice.
|
||||||
|
opts.CompactL0OnClose = false
|
||||||
|
|
||||||
|
// The alternative is "crash on start and tell the user to fix it". This
|
||||||
|
// will truncate corrupt and unsynced data, which we don't guarantee to
|
||||||
|
// persist anyways.
|
||||||
|
opts.Truncate = true
|
||||||
|
|
||||||
|
// We mmap the index into memory, and access values from disk.
|
||||||
|
// Ideally the table loading mode would be settable by LSM level.
|
||||||
|
opts.ValueLogLoadingMode = badgerbs.FileIO
|
||||||
|
opts.TableLoadingMode = badgerbs.MemoryMap
|
||||||
|
|
||||||
|
// Embed only values < 128 bytes in the LSM; larger values in value logs.
|
||||||
|
opts.ValueThreshold = 128
|
||||||
|
|
||||||
|
// Reduce this from 64MiB to 16MiB. That means badger will hold on to
|
||||||
|
// 20MiB by default instead of 80MiB. This does not appear to have a
|
||||||
|
// significant performance hit.
|
||||||
|
opts.MaxTableSize = 16 << 20
|
||||||
|
|
||||||
|
// NOTE: The chain blockstore doesn't require any GC (blocks are never
|
||||||
|
// deleted). This will change if we move to a tiered blockstore.
|
||||||
|
|
||||||
|
return badgerbs.Open(opts)
|
||||||
|
}
|
||||||
|
|
||||||
// join joins path elements with fsr.path
|
// join joins path elements with fsr.path
|
||||||
func (fsr *fsLockedRepo) join(paths ...string) string {
|
func (fsr *fsLockedRepo) join(paths ...string) string {
|
||||||
return filepath.Join(append([]string{fsr.path}, paths...)...)
|
return filepath.Join(append([]string{fsr.path}, paths...)...)
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
type dsCtor func(path string, readonly bool) (datastore.Batching, error)
|
type dsCtor func(path string, readonly bool) (datastore.Batching, error)
|
||||||
|
|
||||||
var fsDatastores = map[string]dsCtor{
|
var fsDatastores = map[string]dsCtor{
|
||||||
"chain": chainBadgerDs,
|
|
||||||
"metadata": levelDs,
|
"metadata": levelDs,
|
||||||
|
|
||||||
// Those need to be fast for large writes... but also need a really good GC :c
|
// Those need to be fast for large writes... but also need a really good GC :c
|
||||||
@ -26,17 +25,6 @@ var fsDatastores = map[string]dsCtor{
|
|||||||
"client": badgerDs, // client specific
|
"client": badgerDs, // client specific
|
||||||
}
|
}
|
||||||
|
|
||||||
func chainBadgerDs(path string, readonly bool) (datastore.Batching, error) {
|
|
||||||
opts := badger.DefaultOptions
|
|
||||||
opts.GcInterval = 0 // disable GC for chain datastore
|
|
||||||
opts.ReadOnly = readonly
|
|
||||||
|
|
||||||
opts.Options = dgbadger.DefaultOptions("").WithTruncate(true).
|
|
||||||
WithValueThreshold(1 << 10)
|
|
||||||
|
|
||||||
return badger.NewDatastore(path, &opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func badgerDs(path string, readonly bool) (datastore.Batching, error) {
|
func badgerDs(path string, readonly bool) (datastore.Batching, error) {
|
||||||
opts := badger.DefaultOptions
|
opts := badger.DefaultOptions
|
||||||
opts.ReadOnly = readonly
|
opts.ReadOnly = readonly
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||||
@ -12,11 +13,26 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BlockstoreDomain represents the domain of a blockstore.
|
||||||
|
type BlockstoreDomain string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BlockstoreChain represents the blockstore domain for chain data.
|
||||||
|
// Right now, this includes chain objects (tipsets, blocks, messages), as
|
||||||
|
// well as state. In the future, they may get segretated into different
|
||||||
|
// domains.
|
||||||
|
BlockstoreChain = BlockstoreDomain("chain")
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoAPIEndpoint = errors.New("API not running (no endpoint)")
|
ErrNoAPIEndpoint = errors.New("API not running (no endpoint)")
|
||||||
ErrNoAPIToken = errors.New("API token not set")
|
ErrNoAPIToken = errors.New("API token not set")
|
||||||
ErrRepoAlreadyLocked = errors.New("repo is already locked (lotus daemon already running)")
|
ErrRepoAlreadyLocked = errors.New("repo is already locked (lotus daemon already running)")
|
||||||
ErrClosedRepo = errors.New("repo is no longer open")
|
ErrClosedRepo = errors.New("repo is no longer open")
|
||||||
|
|
||||||
|
// ErrInvalidBlockstoreDomain is returned by LockedRepo#Blockstore() when
|
||||||
|
// an unrecognized domain is requested.
|
||||||
|
ErrInvalidBlockstoreDomain = errors.New("invalid blockstore domain")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Repo interface {
|
type Repo interface {
|
||||||
@ -37,6 +53,9 @@ type LockedRepo interface {
|
|||||||
// Returns datastore defined in this repo.
|
// Returns datastore defined in this repo.
|
||||||
Datastore(namespace string) (datastore.Batching, error)
|
Datastore(namespace string) (datastore.Batching, error)
|
||||||
|
|
||||||
|
// Blockstore returns an IPLD blockstore for the requested domain.
|
||||||
|
Blockstore(domain BlockstoreDomain) (blockstore.Blockstore, error)
|
||||||
|
|
||||||
// Returns config in this repo
|
// Returns config in this repo
|
||||||
Config() (interface{}, error)
|
Config() (interface{}, error)
|
||||||
SetConfig(func(interface{})) error
|
SetConfig(func(interface{})) error
|
||||||
|
@ -11,13 +11,14 @@ import (
|
|||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
"github.com/ipfs/go-datastore/namespace"
|
"github.com/ipfs/go-datastore/namespace"
|
||||||
dssync "github.com/ipfs/go-datastore/sync"
|
dssync "github.com/ipfs/go-datastore/sync"
|
||||||
|
"github.com/ipfs/go-ipfs-blockstore"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||||
|
lblockstore "github.com/filecoin-project/lotus/lib/blockstore"
|
||||||
"github.com/filecoin-project/lotus/node/config"
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ type MemRepo struct {
|
|||||||
|
|
||||||
datastore datastore.Datastore
|
datastore datastore.Datastore
|
||||||
keystore map[string]types.KeyInfo
|
keystore map[string]types.KeyInfo
|
||||||
|
blockstore blockstore.Blockstore
|
||||||
|
|
||||||
// given a repo type, produce the default config
|
// given a repo type, produce the default config
|
||||||
configF func(t RepoType) interface{}
|
configF func(t RepoType) interface{}
|
||||||
@ -159,7 +161,7 @@ func NewMemory(opts *MemRepoOptions) *MemRepo {
|
|||||||
|
|
||||||
return &MemRepo{
|
return &MemRepo{
|
||||||
repoLock: make(chan struct{}, 1),
|
repoLock: make(chan struct{}, 1),
|
||||||
|
blockstore: lblockstore.NewTemporarySync(),
|
||||||
datastore: opts.Ds,
|
datastore: opts.Ds,
|
||||||
configF: opts.ConfigF,
|
configF: opts.ConfigF,
|
||||||
keystore: opts.KeyStore,
|
keystore: opts.KeyStore,
|
||||||
@ -243,6 +245,13 @@ 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) Blockstore(domain BlockstoreDomain) (blockstore.Blockstore, error) {
|
||||||
|
if domain != BlockstoreChain {
|
||||||
|
return nil, ErrInvalidBlockstoreDomain
|
||||||
|
}
|
||||||
|
return lmem.mem.blockstore, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (lmem *lockedMemRepo) ListDatastores(ns string) ([]int64, error) {
|
func (lmem *lockedMemRepo) ListDatastores(ns string) ([]int64, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user