splitstore constructor

This commit is contained in:
vyzo 2020-12-01 17:17:34 +02:00
parent e87ce6cb60
commit e07c6c71c0
2 changed files with 81 additions and 6 deletions

View File

@ -1,11 +1,16 @@
package splitstore package splitstore
import ( import (
"fmt"
"os"
"github.com/bmatsuo/lmdb-go/lmdb" "github.com/bmatsuo/lmdb-go/lmdb"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
) )
var LiveSetMapSize int64 = 1 << 34 // 16G; TODO this may be a little too big, we should figure out how to gradually grow the map.
type LiveSet interface { type LiveSet interface {
Mark(cid.Cid) error Mark(cid.Cid) error
Has(cid.Cid) (bool, error) Has(cid.Cid) (bool, error)
@ -19,6 +24,39 @@ type liveSet struct {
var markBytes = []byte{} var markBytes = []byte{}
func NewLiveSetEnv(path string) (*lmdb.Env, error) {
env, err := lmdb.NewEnv()
if err != nil {
return nil, fmt.Errorf("failed to initialize LDMB env: %w", err)
}
if err = env.SetMapSize(LiveSetMapSize); err != nil {
return nil, fmt.Errorf("failed to set LMDB map size: %w", err)
}
if err = env.SetMaxDBs(2); err != nil {
return nil, fmt.Errorf("failed to set LMDB max dbs: %w", err)
}
if err = env.SetMaxReaders(1); err != nil {
return nil, fmt.Errorf("failed to set LMDB max readers: %w", err)
}
if st, err := os.Stat(path); os.IsNotExist(err) {
if err := os.MkdirAll(path, 0777); err != nil {
return nil, fmt.Errorf("failed to create LMDB data directory at %s: %w", path, err)
}
} else if err != nil {
return nil, fmt.Errorf("failed to stat LMDB data dir: %w", err)
} else if !st.IsDir() {
return nil, fmt.Errorf("LMDB path is not a directory %s", path)
}
err = env.Open(path, lmdb.NoSync|lmdb.WriteMap|lmdb.MapAsync|lmdb.NoReadahead, 0777)
if err != nil {
env.Close() //nolint:errcheck
return nil, fmt.Errorf("error opening LMDB database: %w", err)
}
return env, nil
}
func NewLiveSet(env *lmdb.Env, name string) (LiveSet, error) { func NewLiveSet(env *lmdb.Env, name string) (LiveSet, error) {
var db lmdb.DBI var db lmdb.DBI
err := env.Update(func(txn *lmdb.Txn) (err error) { err := env.Update(func(txn *lmdb.Txn) (err error) {

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"errors" "errors"
"path/filepath"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -15,6 +16,7 @@ import (
dstore "github.com/ipfs/go-datastore" dstore "github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/go-bs-lmdb"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
@ -36,12 +38,10 @@ type SplitStore struct {
mx sync.Mutex mx sync.Mutex
curTs *types.TipSet curTs *types.TipSet
cs *store.ChainStore cs *store.ChainStore
ds dstore.Datastore ds dstore.Datastore
hot bstore.Blockstore
hot bstore.Blockstore cold bstore.Blockstore
cold bstore.Blockstore
snoop TrackingStore snoop TrackingStore
env *lmdb.Env env *lmdb.Env
@ -49,6 +49,43 @@ type SplitStore struct {
var _ bstore.Blockstore = (*SplitStore)(nil) var _ bstore.Blockstore = (*SplitStore)(nil)
// NewSplitStore creates a new SplitStore instance, given a path for the hotstore dbs and a cold
// blockstore. The SplitStore must be attached to the ChainStore with Start in order to trigger
// compaction.
func NewSplitStore(path string, ds dstore.Datastore, cold bstore.Blockstore) (*SplitStore, error) {
// the hot store
hot, err := lmdbbs.Open(filepath.Join(path, "hot.db"))
if err != nil {
return nil, err
}
// the tracking store
snoop, err := NewTrackingStore(filepath.Join(path, "snoop.db"))
if err != nil {
hot.Close() //nolint:errcheck
return nil, err
}
// the liveset env
env, err := NewLiveSetEnv(filepath.Join(path, "sweep.db"))
if err != nil {
hot.Close() //nolint:errcheck
snoop.Close() //nolint:errcheck
return nil, err
}
// and now we can make a SplitStore
ss := &SplitStore{
ds: ds,
hot: hot,
cold: cold,
snoop: snoop,
env: env,
}
return ss, nil
}
// Blockstore interface // Blockstore interface
func (s *SplitStore) DeleteBlock(cid cid.Cid) error { func (s *SplitStore) DeleteBlock(cid cid.Cid) error {
// afaict we don't seem to be using this method, so it's not implemented // afaict we don't seem to be using this method, so it's not implemented