implement bolt backed tracking store

This commit is contained in:
vyzo 2021-02-27 13:35:57 +02:00
parent b83994797a
commit f1c61c4753
3 changed files with 104 additions and 3 deletions

View File

@ -1,7 +1,6 @@
package splitstore package splitstore
import ( import (
"fmt"
"path/filepath" "path/filepath"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
@ -22,5 +21,5 @@ func NewTrackingStore(path string, useLMDB bool) (TrackingStore, error) {
return NewLMDBTrackingStore(filepath.Join(path, "snoop.lmdb")) return NewLMDBTrackingStore(filepath.Join(path, "snoop.lmdb"))
} }
return nil, fmt.Errorf("TODO: non-lmdb livesets") return NewBoltTrackingStore(filepath.Join(path, "snoop.bolt"))
} }

View File

@ -0,0 +1,102 @@
package splitstore
import (
"time"
"golang.org/x/xerrors"
cid "github.com/ipfs/go-cid"
bolt "go.etcd.io/bbolt"
"github.com/filecoin-project/go-state-types/abi"
)
type BoltTrackingStore struct {
db *bolt.DB
bucketId []byte
}
var _ TrackingStore = (*BoltTrackingStore)(nil)
func NewBoltTrackingStore(path string) (*BoltTrackingStore, error) {
db, err := bolt.Open(path, 0644,
&bolt.Options{
Timeout: 1 * time.Second,
})
if err != nil {
return nil, err
}
bucketId := []byte("snoop")
err = db.Update(func(tx *bolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(bucketId)
if err != nil {
return xerrors.Errorf("error creating bolt db bucket %s: %w", string(bucketId), err)
}
return nil
})
if err != nil {
db.Close() //nolint:errcheck
return nil, err
}
return &BoltTrackingStore{db: db, bucketId: bucketId}, nil
}
func (s *BoltTrackingStore) Put(cid cid.Cid, epoch abi.ChainEpoch) error {
val := epochToBytes(epoch)
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.Put(cid.Hash(), val)
})
}
func (s *BoltTrackingStore) PutBatch(cids []cid.Cid, epoch abi.ChainEpoch) error {
val := epochToBytes(epoch)
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
for _, cid := range cids {
err := b.Put(cid.Hash(), val)
if err != nil {
return err
}
}
return nil
})
}
func (s *BoltTrackingStore) Get(cid cid.Cid) (epoch abi.ChainEpoch, err error) {
err = s.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
val := b.Get(cid.Hash())
if val == nil {
return xerrors.Errorf("missing tracking epoch for %s", cid)
}
epoch = bytesToEpoch(val)
return nil
})
return epoch, err
}
func (s *BoltTrackingStore) Delete(cid cid.Cid) error {
return s.db.Batch(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.Delete(cid.Hash())
})
}
func (s *BoltTrackingStore) ForEach(f func(cid.Cid, abi.ChainEpoch) error) error {
return s.db.View(func(tx *bolt.Tx) error {
b := tx.Bucket(s.bucketId)
return b.ForEach(func(k, v []byte) error {
cid := cid.NewCidV1(cid.Raw, k)
epoch := bytesToEpoch(v)
return f(cid, epoch)
})
})
}
func (s *BoltTrackingStore) Close() error {
return s.db.Close()
}

View File

@ -20,7 +20,7 @@ type LMDBTrackingStore struct {
var _ TrackingStore = (*LMDBTrackingStore)(nil) var _ TrackingStore = (*LMDBTrackingStore)(nil)
func NewLMDBTrackingStore(path string) (TrackingStore, error) { func NewLMDBTrackingStore(path string) (*LMDBTrackingStore, error) {
env, err := lmdb.NewEnv() env, err := lmdb.NewEnv()
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to initialize LMDB env: %w", err) return nil, xerrors.Errorf("failed to initialize LMDB env: %w", err)