2020-11-26 14:53:16 +00:00
|
|
|
package splitstore
|
|
|
|
|
|
|
|
import (
|
2021-02-27 10:01:55 +00:00
|
|
|
"path/filepath"
|
2021-03-05 17:55:32 +00:00
|
|
|
"sync"
|
2021-02-27 10:01:55 +00:00
|
|
|
|
2021-02-28 07:59:11 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2020-11-26 14:53:16 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
2021-02-26 18:54:47 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
2020-11-26 14:53:16 +00:00
|
|
|
)
|
|
|
|
|
2021-03-02 00:47:21 +00:00
|
|
|
// TrackingStore is a persistent store that tracks blocks that are added
|
2021-03-02 08:04:02 +00:00
|
|
|
// to the hotstore, tracking the epoch at which they are written.
|
2020-11-26 14:53:16 +00:00
|
|
|
type TrackingStore interface {
|
|
|
|
Put(cid.Cid, abi.ChainEpoch) error
|
|
|
|
PutBatch([]cid.Cid, abi.ChainEpoch) error
|
|
|
|
Get(cid.Cid) (abi.ChainEpoch, error)
|
|
|
|
Delete(cid.Cid) error
|
2021-03-02 16:59:00 +00:00
|
|
|
DeleteBatch([]cid.Cid) error
|
2021-02-26 13:59:36 +00:00
|
|
|
ForEach(func(cid.Cid, abi.ChainEpoch) error) error
|
2021-02-27 16:16:09 +00:00
|
|
|
Sync() error
|
2020-11-26 18:37:02 +00:00
|
|
|
Close() error
|
|
|
|
}
|
2021-02-27 10:01:55 +00:00
|
|
|
|
2021-03-02 00:47:21 +00:00
|
|
|
// OpenTrackingStore opens a tracking store of the specified type in the
|
|
|
|
// specified path.
|
|
|
|
func OpenTrackingStore(path string, ttype string) (TrackingStore, error) {
|
|
|
|
switch ttype {
|
2021-02-28 07:59:11 +00:00
|
|
|
case "", "bolt":
|
2021-03-02 00:47:21 +00:00
|
|
|
return OpenBoltTrackingStore(filepath.Join(path, "tracker.bolt"))
|
2021-03-05 17:55:32 +00:00
|
|
|
case "mem":
|
|
|
|
return NewMemTrackingStore(), nil
|
2021-02-28 07:59:11 +00:00
|
|
|
default:
|
2021-03-02 00:47:21 +00:00
|
|
|
return nil, xerrors.Errorf("unknown tracking store type %s", ttype)
|
2021-02-27 10:01:55 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-05 17:55:32 +00:00
|
|
|
|
|
|
|
// NewMemTrackingStore creates an in-memory tracking store.
|
|
|
|
// This is only useful for test or situations where you don't want to open the
|
|
|
|
// real tracking store (eg concurrent read only access on a node's datastore)
|
|
|
|
func NewMemTrackingStore() *MemTrackingStore {
|
|
|
|
return &MemTrackingStore{tab: make(map[cid.Cid]abi.ChainEpoch)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MemTrackingStore is a simple in-memory tracking store
|
|
|
|
type MemTrackingStore struct {
|
|
|
|
sync.Mutex
|
|
|
|
tab map[cid.Cid]abi.ChainEpoch
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ TrackingStore = (*MemTrackingStore)(nil)
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) Put(cid cid.Cid, epoch abi.ChainEpoch) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
s.tab[cid] = epoch
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) PutBatch(cids []cid.Cid, epoch abi.ChainEpoch) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
for _, cid := range cids {
|
|
|
|
s.tab[cid] = epoch
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) Get(cid cid.Cid) (abi.ChainEpoch, error) {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
epoch, ok := s.tab[cid]
|
|
|
|
if ok {
|
|
|
|
return epoch, nil
|
|
|
|
}
|
|
|
|
return 0, xerrors.Errorf("missing tracking epoch for %s", cid)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) Delete(cid cid.Cid) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
delete(s.tab, cid)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) DeleteBatch(cids []cid.Cid) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
for _, cid := range cids {
|
|
|
|
delete(s.tab, cid)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) ForEach(f func(cid.Cid, abi.ChainEpoch) error) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
for cid, epoch := range s.tab {
|
|
|
|
err := f(cid, epoch)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MemTrackingStore) Sync() error { return nil }
|
|
|
|
func (s *MemTrackingStore) Close() error { return nil }
|