keep genesis-linked state hot
This commit is contained in:
parent
e9f531b4aa
commit
7cf75e667d
@ -101,6 +101,7 @@ type Config struct {
|
|||||||
// ChainAccessor allows the Splitstore to access the chain. It will most likely
|
// ChainAccessor allows the Splitstore to access the chain. It will most likely
|
||||||
// be a ChainStore at runtime.
|
// be a ChainStore at runtime.
|
||||||
type ChainAccessor interface {
|
type ChainAccessor interface {
|
||||||
|
GetGenesis() (*types.BlockHeader, error)
|
||||||
GetTipsetByHeight(context.Context, abi.ChainEpoch, *types.TipSet, bool) (*types.TipSet, error)
|
GetTipsetByHeight(context.Context, abi.ChainEpoch, *types.TipSet, bool) (*types.TipSet, error)
|
||||||
GetHeaviestTipSet() *types.TipSet
|
GetHeaviestTipSet() *types.TipSet
|
||||||
SubscribeHeadChanges(change func(revert []*types.TipSet, apply []*types.TipSet) error)
|
SubscribeHeadChanges(change func(revert []*types.TipSet, apply []*types.TipSet) error)
|
||||||
@ -127,6 +128,8 @@ type SplitStore struct {
|
|||||||
cold bstore.Blockstore
|
cold bstore.Blockstore
|
||||||
tracker TrackingStore
|
tracker TrackingStore
|
||||||
|
|
||||||
|
genesis, genesisStateRoot cid.Cid
|
||||||
|
|
||||||
env MarkSetEnv
|
env MarkSetEnv
|
||||||
|
|
||||||
markSetSize int64
|
markSetSize int64
|
||||||
@ -326,6 +329,60 @@ func (s *SplitStore) Start(chain ChainAccessor) error {
|
|||||||
s.chain = chain
|
s.chain = chain
|
||||||
s.curTs = chain.GetHeaviestTipSet()
|
s.curTs = chain.GetHeaviestTipSet()
|
||||||
|
|
||||||
|
// make sure the genesis and its state root are hot
|
||||||
|
gb, err := chain.GetGenesis()
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error getting genesis: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.genesis = gb.Cid()
|
||||||
|
s.genesisStateRoot = gb.ParentStateRoot
|
||||||
|
|
||||||
|
has, err := s.hot.Has(s.genesis)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error checking hotstore for genesis: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
blk, err := gb.ToStorageBlock()
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error converting genesis block to storage block: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.hot.Put(blk)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error putting genesis block to hotstore: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.walkLinks(s.genesisStateRoot, cid.NewSet(), func(c cid.Cid) error {
|
||||||
|
has, err = s.hot.Has(c)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error checking hotstore for genesis state root: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
blk, err := s.cold.Get(c)
|
||||||
|
if err != nil {
|
||||||
|
if err == bstore.ErrNotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return xerrors.Errorf("error retrieving genesis state linked object from coldstore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.hot.Put(blk)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error putting genesis state linked object to hotstore: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error walking genesis state root links: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// load base epoch from metadata ds
|
// load base epoch from metadata ds
|
||||||
// if none, then use current epoch because it's a fresh start
|
// if none, then use current epoch because it's a fresh start
|
||||||
bs, err := s.ds.Get(baseEpochKey)
|
bs, err := s.ds.Get(baseEpochKey)
|
||||||
|
@ -149,8 +149,8 @@ func testSplitStore(t *testing.T, cfg *Config) {
|
|||||||
t.Errorf("expected %d cold blocks, but got %d", 7, coldCnt)
|
t.Errorf("expected %d cold blocks, but got %d", 7, coldCnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hotCnt != 4 {
|
if hotCnt != 5 {
|
||||||
t.Errorf("expected %d hot blocks, but got %d", 4, hotCnt)
|
t.Errorf("expected %d hot blocks, but got %d", 5, hotCnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can revert without panicking.
|
// Make sure we can revert without panicking.
|
||||||
@ -165,6 +165,7 @@ type mockChain struct {
|
|||||||
t testing.TB
|
t testing.TB
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
genesis *types.BlockHeader
|
||||||
tipsets []*types.TipSet
|
tipsets []*types.TipSet
|
||||||
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
listener func(revert []*types.TipSet, apply []*types.TipSet) error
|
||||||
}
|
}
|
||||||
@ -172,6 +173,9 @@ type mockChain struct {
|
|||||||
func (c *mockChain) push(ts *types.TipSet) {
|
func (c *mockChain) push(ts *types.TipSet) {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
c.tipsets = append(c.tipsets, ts)
|
c.tipsets = append(c.tipsets, ts)
|
||||||
|
if c.genesis == nil {
|
||||||
|
c.genesis = ts.Blocks()[0]
|
||||||
|
}
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
|
|
||||||
if c.listener != nil {
|
if c.listener != nil {
|
||||||
@ -201,6 +205,10 @@ func (c *mockChain) revert(count int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *mockChain) GetGenesis() (*types.BlockHeader, error) {
|
||||||
|
return c.genesis, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *mockChain) GetTipsetByHeight(_ context.Context, epoch abi.ChainEpoch, _ *types.TipSet, _ bool) (*types.TipSet, error) {
|
func (c *mockChain) GetTipsetByHeight(_ context.Context, epoch abi.ChainEpoch, _ *types.TipSet, _ bool) (*types.TipSet, error) {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
Loading…
Reference in New Issue
Block a user