diff --git a/chain/store/splitstore/liveset.go b/chain/store/splitstore/liveset.go index 1636c6efa..6b64a3a56 100644 --- a/chain/store/splitstore/liveset.go +++ b/chain/store/splitstore/liveset.go @@ -3,6 +3,8 @@ package splitstore import ( "path/filepath" + "golang.org/x/xerrors" + cid "github.com/ipfs/go-cid" ) @@ -19,10 +21,15 @@ type LiveSetEnv interface { Close() error } -func NewLiveSetEnv(path string, useLMDB bool) (LiveSetEnv, error) { - if useLMDB { +func NewLiveSetEnv(path string, liveSetType string) (LiveSetEnv, error) { + switch liveSetType { + case "", "bloom": + return NewBloomLiveSetEnv() + case "bolt": + return NewBoltLiveSetEnv(filepath.Join(path, "sweep.bolt")) + case "lmdb": return NewLMDBLiveSetEnv(filepath.Join(path, "sweep.lmdb")) + default: + return nil, xerrors.Errorf("unknown live set type %s", liveSetType) } - - return NewBoltLiveSetEnv(filepath.Join(path, "sweep.bolt")) } diff --git a/chain/store/splitstore/liveset_bloom.go b/chain/store/splitstore/liveset_bloom.go new file mode 100644 index 000000000..d553671a9 --- /dev/null +++ b/chain/store/splitstore/liveset_bloom.go @@ -0,0 +1,65 @@ +package splitstore + +import ( + "math/rand" + + "golang.org/x/xerrors" + + bbloom "github.com/ipfs/bbloom" + cid "github.com/ipfs/go-cid" +) + +type BloomLiveSetEnv struct{} + +var _ LiveSetEnv = (*BloomLiveSetEnv)(nil) + +type BloomLiveSet struct { + salt []byte + bf *bbloom.Bloom +} + +var _ LiveSet = (*BloomLiveSet)(nil) + +func NewBloomLiveSetEnv() (*BloomLiveSetEnv, error) { + return &BloomLiveSetEnv{}, nil +} + +func (e *BloomLiveSetEnv) NewLiveSet(name string) (LiveSet, error) { + salt := make([]byte, 4) + _, err := rand.Read(salt) + if err != nil { + return nil, xerrors.Errorf("error reading salt: %w", err) + } + + bf, err := bbloom.New(float64(10_000_000), float64(0.01)) + if err != nil { + return nil, xerrors.Errorf("error creating bloom filter: %w", err) + } + + return &BloomLiveSet{salt: salt, bf: bf}, nil +} + +func (e *BloomLiveSetEnv) Close() error { + return nil +} + +func (s *BloomLiveSet) saltedKey(cid cid.Cid) []byte { + hash := cid.Hash() + key := make([]byte, len(s.salt)+len(hash)) + n := copy(key, s.salt) + copy(key[n:], hash) + return key +} + +func (s *BloomLiveSet) Mark(cid cid.Cid) error { + s.bf.Add(s.saltedKey(cid)) + return nil +} + +func (s *BloomLiveSet) Has(cid cid.Cid) (bool, error) { + return s.bf.Has(s.saltedKey(cid)), nil +} + +func (s *BloomLiveSet) Close() error { + return nil +} diff --git a/chain/store/splitstore/snoop.go b/chain/store/splitstore/snoop.go index 02c270fc7..eeff09e0e 100644 --- a/chain/store/splitstore/snoop.go +++ b/chain/store/splitstore/snoop.go @@ -3,6 +3,8 @@ package splitstore import ( "path/filepath" + "golang.org/x/xerrors" + "github.com/filecoin-project/go-state-types/abi" cid "github.com/ipfs/go-cid" ) @@ -18,10 +20,13 @@ type TrackingStore interface { Close() error } -func NewTrackingStore(path string, useLMDB bool) (TrackingStore, error) { - if useLMDB { +func NewTrackingStore(path string, trackingStoreType string) (TrackingStore, error) { + switch trackingStoreType { + case "", "bolt": + return NewBoltTrackingStore(filepath.Join(path, "snoop.bolt")) + case "lmdb": return NewLMDBTrackingStore(filepath.Join(path, "snoop.lmdb")) + default: + return nil, xerrors.Errorf("unknown tracking store type %s", trackingStoreType) } - - return NewBoltTrackingStore(filepath.Join(path, "snoop.bolt")) } diff --git a/chain/store/splitstore/splitstore.go b/chain/store/splitstore/splitstore.go index edfe09ff9..45ec50d33 100644 --- a/chain/store/splitstore/splitstore.go +++ b/chain/store/splitstore/splitstore.go @@ -39,8 +39,10 @@ func init() { } type Config struct { - // use LMDB for tracking store and liveset instead of BoltDB - UseLMDB bool + // TrackingStore type; bolt (default) or lmdb + TrackingStoreType string + // LiveSet type; bloom (default), bolt, or lmdb + LiveSetType string // perform full reachability analysis (expensive) for compaction // You should enable this option if you plan to use the splitstore without a backing coldstore EnableFullCompaction bool @@ -83,13 +85,13 @@ var _ bstore.Blockstore = (*SplitStore)(nil) // compaction. func NewSplitStore(path string, ds dstore.Datastore, cold, hot bstore.Blockstore, cfg *Config) (*SplitStore, error) { // the tracking store - snoop, err := NewTrackingStore(path, cfg.UseLMDB) + snoop, err := NewTrackingStore(path, cfg.TrackingStoreType) if err != nil { return nil, err } // the liveset env - env, err := NewLiveSetEnv(path, cfg.UseLMDB) + env, err := NewLiveSetEnv(path, cfg.LiveSetType) if err != nil { snoop.Close() //nolint:errcheck return nil, err diff --git a/node/builder.go b/node/builder.go index 2efa52c52..c92ab1248 100644 --- a/node/builder.go +++ b/node/builder.go @@ -611,10 +611,10 @@ func Repo(r repo.Repo) Option { Override(new(dtypes.UniversalBlockstore), modules.UniversalBlockstore), If(cfg.EnableSplitstore, - If(cfg.Splitstore.UseLMDBHotstore, - Override(new(dtypes.HotBlockstore), modules.LMDBHotBlockstore)), - If(!cfg.Splitstore.UseLMDBHotstore, + If(cfg.Splitstore.GetHotStoreType() == "badger", Override(new(dtypes.HotBlockstore), modules.BadgerHotBlockstore)), + If(cfg.Splitstore.GetHotStoreType() == "lmdb", + Override(new(dtypes.HotBlockstore), modules.LMDBHotBlockstore)), Override(new(dtypes.SplitBlockstore), modules.SplitBlockstore(cfg)), Override(new(dtypes.ChainBlockstore), modules.ChainSplitBlockstore), Override(new(dtypes.StateBlockstore), modules.StateSplitBlockstore), diff --git a/node/config/def.go b/node/config/def.go index fcbdefda5..f66ac2ba0 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -126,13 +126,22 @@ type Blockstore struct { } type Splitstore struct { - UseLMDBHotstore bool - UseLMDBTracking bool + HotStoreType string + TrackingStoreType string + LiveSetType string EnableFullCompaction bool EnableGC bool // EXPERIMENTAL Archival bool } +func (s *Splitstore) GetHotStoreType() string { + // default is badger + if s.HotStoreType == "" { + return "badger" + } + return s.HotStoreType +} + // // Full Node type Metrics struct { diff --git a/node/modules/blockstore.go b/node/modules/blockstore.go index fdb6d1417..ae4f7a188 100644 --- a/node/modules/blockstore.go +++ b/node/modules/blockstore.go @@ -105,7 +105,8 @@ func SplitBlockstore(cfg *config.Blockstore) func(lc fx.Lifecycle, r repo.Locked ss, err := splitstore.NewSplitStore(path, ds, cold, hot, &splitstore.Config{ - UseLMDB: cfg.Splitstore.UseLMDBTracking, + TrackingStoreType: cfg.Splitstore.TrackingStoreType, + LiveSetType: cfg.Splitstore.LiveSetType, EnableFullCompaction: cfg.Splitstore.EnableFullCompaction, EnableGC: cfg.Splitstore.EnableGC, Archival: cfg.Splitstore.Archival,