add (salted) bloom filter liveset
This commit is contained in:
parent
aba6530411
commit
97abbe1eca
@ -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"))
|
||||
}
|
||||
|
65
chain/store/splitstore/liveset_bloom.go
Normal file
65
chain/store/splitstore/liveset_bloom.go
Normal file
@ -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
|
||||
}
|
@ -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"))
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user