keep genesis-linked state hot

This commit is contained in:
vyzo 2021-03-19 12:17:32 +02:00
parent e9f531b4aa
commit 7cf75e667d
2 changed files with 67 additions and 2 deletions

View File

@ -101,6 +101,7 @@ type Config struct {
// ChainAccessor allows the Splitstore to access the chain. It will most likely
// be a ChainStore at runtime.
type ChainAccessor interface {
GetGenesis() (*types.BlockHeader, error)
GetTipsetByHeight(context.Context, abi.ChainEpoch, *types.TipSet, bool) (*types.TipSet, error)
GetHeaviestTipSet() *types.TipSet
SubscribeHeadChanges(change func(revert []*types.TipSet, apply []*types.TipSet) error)
@ -127,6 +128,8 @@ type SplitStore struct {
cold bstore.Blockstore
tracker TrackingStore
genesis, genesisStateRoot cid.Cid
env MarkSetEnv
markSetSize int64
@ -326,6 +329,60 @@ func (s *SplitStore) Start(chain ChainAccessor) error {
s.chain = chain
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
// if none, then use current epoch because it's a fresh start
bs, err := s.ds.Get(baseEpochKey)

View File

@ -149,8 +149,8 @@ func testSplitStore(t *testing.T, cfg *Config) {
t.Errorf("expected %d cold blocks, but got %d", 7, coldCnt)
}
if hotCnt != 4 {
t.Errorf("expected %d hot blocks, but got %d", 4, hotCnt)
if hotCnt != 5 {
t.Errorf("expected %d hot blocks, but got %d", 5, hotCnt)
}
// Make sure we can revert without panicking.
@ -165,6 +165,7 @@ type mockChain struct {
t testing.TB
sync.Mutex
genesis *types.BlockHeader
tipsets []*types.TipSet
listener func(revert []*types.TipSet, apply []*types.TipSet) error
}
@ -172,6 +173,9 @@ type mockChain struct {
func (c *mockChain) push(ts *types.TipSet) {
c.Lock()
c.tipsets = append(c.tipsets, ts)
if c.genesis == nil {
c.genesis = ts.Blocks()[0]
}
c.Unlock()
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) {
c.Lock()
defer c.Unlock()