make the lotus node use the new native badger blockstore.

This commit is contained in:
Raúl Kripalani 2020-11-01 13:01:26 +00:00
parent ce27b13076
commit d2e2322fd2
5 changed files with 87 additions and 23 deletions

View File

@ -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) {
blocks, err := r.Datastore("/chain")
bs, err := r.Blockstore(repo.BlockstoreChain)
if err != nil {
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())
if err != nil {
return nil, err

View File

@ -14,6 +14,7 @@ import (
"github.com/BurntSushi/toml"
"github.com/ipfs/go-datastore"
fslock "github.com/ipfs/go-fs-lock"
blockstore "github.com/ipfs/go-ipfs-blockstore"
logging "github.com/ipfs/go-log/v2"
"github.com/mitchellh/go-homedir"
"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/stores"
badgerbs "github.com/filecoin-project/lotus/lib/blockstore/badger"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/config"
@ -284,6 +286,52 @@ func (fsr *fsLockedRepo) Close() error {
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
func (fsr *fsLockedRepo) join(paths ...string) string {
return filepath.Join(append([]string{fsr.path}, paths...)...)

View File

@ -17,7 +17,6 @@ import (
type dsCtor func(path string, readonly bool) (datastore.Batching, error)
var fsDatastores = map[string]dsCtor{
"chain": chainBadgerDs,
"metadata": levelDs,
// 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
}
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) {
opts := badger.DefaultOptions
opts.ReadOnly = readonly

View File

@ -4,6 +4,7 @@ import (
"errors"
"github.com/ipfs/go-datastore"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
@ -12,11 +13,26 @@ import (
"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 (
ErrNoAPIEndpoint = errors.New("API not running (no endpoint)")
ErrNoAPIToken = errors.New("API token not set")
ErrRepoAlreadyLocked = errors.New("repo is already locked (lotus daemon already running)")
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 {
@ -37,6 +53,9 @@ type LockedRepo interface {
// Returns datastore defined in this repo.
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
Config() (interface{}, error)
SetConfig(func(interface{})) error

View File

@ -11,13 +11,14 @@ import (
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace"
dssync "github.com/ipfs/go-datastore/sync"
"github.com/ipfs/go-ipfs-blockstore"
"github.com/multiformats/go-multiaddr"
"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/extern/sector-storage/fsutil"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
lblockstore "github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/node/config"
)
@ -31,8 +32,9 @@ type MemRepo struct {
repoLock chan struct{}
token *byte
datastore datastore.Datastore
keystore map[string]types.KeyInfo
datastore datastore.Datastore
keystore map[string]types.KeyInfo
blockstore blockstore.Blockstore
// given a repo type, produce the default config
configF func(t RepoType) interface{}
@ -158,11 +160,11 @@ func NewMemory(opts *MemRepoOptions) *MemRepo {
}
return &MemRepo{
repoLock: make(chan struct{}, 1),
datastore: opts.Ds,
configF: opts.ConfigF,
keystore: opts.KeyStore,
repoLock: make(chan struct{}, 1),
blockstore: lblockstore.NewTemporarySync(),
datastore: opts.Ds,
configF: opts.ConfigF,
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
}
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) {
return nil, nil
}