From 2c7a89a1dbcc2c20fd15bfc861daa0a2fb0c4c2b Mon Sep 17 00:00:00 2001 From: vyzo Date: Sun, 4 Jul 2021 13:15:45 +0300 Subject: [PATCH] short-circuit rescanning on block headers --- blockstore/splitstore/splitstore.go | 37 ++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/blockstore/splitstore/splitstore.go b/blockstore/splitstore/splitstore.go index c05bd8039..914e2973f 100644 --- a/blockstore/splitstore/splitstore.go +++ b/blockstore/splitstore/splitstore.go @@ -918,7 +918,28 @@ func (s *SplitStore) doCompact(curTs *types.TipSet) error { return errStopWalk } - return markSet.Mark(c) + // mark it + err = markSet.Mark(c) + if err != nil { + return err + } + + // we also short-circuit in case of a block header, as it may cause us to walk the + // entire chain because of a network request (and fail if we were synced form a snapshot + // because of missing messages or receipts!) + // this is necessary because we don't have interface options to signal network request + // initiated API calls; when we have that, we can stop tracking those references and + // we can remove this check. + isBlock, err := s.isBlockHeader(c) + if err != nil { + return xerrors.Errorf("error checking object type for %s: %W", c, err) + } + + if isBlock { + return errStopWalk + } + + return nil }) if err != nil { @@ -1091,6 +1112,20 @@ func (s *SplitStore) walkChain(ts *types.TipSet, boundary abi.ChainEpoch, inclMs return nil } +func (s *SplitStore) isBlockHeader(c cid.Cid) (isBlock bool, err error) { + if c.Prefix().Codec != cid.DagCBOR { + return false, nil + } + + err = s.view(c, func(data []byte) error { + var hdr types.BlockHeader + isBlock = hdr.UnmarshalCBOR(bytes.NewBuffer(data)) == nil + return nil + }) + + return isBlock, err +} + func (s *SplitStore) walkObject(c cid.Cid, walked *cid.Set, f func(cid.Cid) error) error { if !walked.Visit(c) { return nil