lotus/node/repo/retrievalstoremgr/retrievalstoremgr.go
Raúl Kripalani 3795cc2bd2 segregate chain and state blockstores.
This paves the way for better object lifetime management.

Concretely, it makes it possible to:
- have different stores backing chain and state data.
- having the same datastore library, but using different parameters.
- attach different caching layers/policies to each class of data, e.g.
  sizing caches differently.
- specifying different retention policies for chain and state data.

This separation is important because:
- access patterns/frequency of chain and state data are different.
- state is derivable from chain, so one could never expunge the chain
  store, and only retain state objects reachable from the last finality
  in the state store.
2021-02-28 22:49:44 +00:00

111 lines
3.2 KiB
Go

package retrievalstoremgr
import (
"errors"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/node/repo/importmgr"
"github.com/ipfs/go-blockservice"
offline "github.com/ipfs/go-ipfs-exchange-offline"
ipldformat "github.com/ipfs/go-ipld-format"
"github.com/ipfs/go-merkledag"
)
// RetrievalStore references a store for a retrieval deal
// which may or may not have a multistore ID associated with it
type RetrievalStore interface {
StoreID() *multistore.StoreID
DAGService() ipldformat.DAGService
}
// RetrievalStoreManager manages stores for retrieval deals, abstracting
// the underlying storage mechanism
type RetrievalStoreManager interface {
NewStore() (RetrievalStore, error)
ReleaseStore(RetrievalStore) error
}
// MultiStoreRetrievalStoreManager manages stores on top of the import manager
type MultiStoreRetrievalStoreManager struct {
imgr *importmgr.Mgr
}
var _ RetrievalStoreManager = &MultiStoreRetrievalStoreManager{}
// NewMultiStoreRetrievalStoreManager returns a new multstore based RetrievalStoreManager
func NewMultiStoreRetrievalStoreManager(imgr *importmgr.Mgr) RetrievalStoreManager {
return &MultiStoreRetrievalStoreManager{
imgr: imgr,
}
}
// NewStore creates a new store (uses multistore)
func (mrsm *MultiStoreRetrievalStoreManager) NewStore() (RetrievalStore, error) {
storeID, store, err := mrsm.imgr.NewStore()
if err != nil {
return nil, err
}
return &multiStoreRetrievalStore{storeID, store}, nil
}
// ReleaseStore releases a store (uses multistore remove)
func (mrsm *MultiStoreRetrievalStoreManager) ReleaseStore(retrievalStore RetrievalStore) error {
mrs, ok := retrievalStore.(*multiStoreRetrievalStore)
if !ok {
return errors.New("Cannot release this store type")
}
return mrsm.imgr.Remove(mrs.storeID)
}
type multiStoreRetrievalStore struct {
storeID multistore.StoreID
store *multistore.Store
}
func (mrs *multiStoreRetrievalStore) StoreID() *multistore.StoreID {
return &mrs.storeID
}
func (mrs *multiStoreRetrievalStore) DAGService() ipldformat.DAGService {
return mrs.store.DAG
}
// BlockstoreRetrievalStoreManager manages a single blockstore as if it were multiple stores
type BlockstoreRetrievalStoreManager struct {
bs blockstore.BasicBlockstore
}
var _ RetrievalStoreManager = &BlockstoreRetrievalStoreManager{}
// NewBlockstoreRetrievalStoreManager returns a new blockstore based RetrievalStoreManager
func NewBlockstoreRetrievalStoreManager(bs blockstore.BasicBlockstore) RetrievalStoreManager {
return &BlockstoreRetrievalStoreManager{
bs: bs,
}
}
// NewStore creates a new store (just uses underlying blockstore)
func (brsm *BlockstoreRetrievalStoreManager) NewStore() (RetrievalStore, error) {
return &blockstoreRetrievalStore{
dagService: merkledag.NewDAGService(blockservice.New(brsm.bs, offline.Exchange(brsm.bs))),
}, nil
}
// ReleaseStore for this implementation does nothing
func (brsm *BlockstoreRetrievalStoreManager) ReleaseStore(RetrievalStore) error {
return nil
}
type blockstoreRetrievalStore struct {
dagService ipldformat.DAGService
}
func (brs *blockstoreRetrievalStore) StoreID() *multistore.StoreID {
return nil
}
func (brs *blockstoreRetrievalStore) DAGService() ipldformat.DAGService {
return brs.dagService
}