From e0dfb8fb229fc3d01a353f16c6cb9cfaab03b106 Mon Sep 17 00:00:00 2001 From: Alex Sharov <AskAlexSharov@gmail.com> Date: Thu, 24 Mar 2022 14:19:14 +0700 Subject: [PATCH] Snapshots: handle well gaps in idx files (#3762) * handle well gaps in idx files * handle well gaps in idx files --- eth/stagedsync/stage_senders.go | 1 - turbo/snapshotsync/block_snapshots.go | 125 +++++++++++++------------- 2 files changed, 61 insertions(+), 65 deletions(-) diff --git a/eth/stagedsync/stage_senders.go b/eth/stagedsync/stage_senders.go index b952f8580e..905349e2f8 100644 --- a/eth/stagedsync/stage_senders.go +++ b/eth/stagedsync/stage_senders.go @@ -413,7 +413,6 @@ func retireBlocks(s *PruneState, tx kv.RwTx, cfg SendersCfg, ctx context.Context } blockFrom, blockTo, ok := cfg.blockRetire.CanRetire(s.ForwardProgress) - fmt.Printf("alex: %d,%d\n", blockFrom, blockTo) if !ok { return nil } diff --git a/turbo/snapshotsync/block_snapshots.go b/turbo/snapshotsync/block_snapshots.go index adc95d7e01..b5adba076e 100644 --- a/turbo/snapshotsync/block_snapshots.go +++ b/turbo/snapshotsync/block_snapshots.go @@ -230,8 +230,11 @@ func (s *headerSegments) closeLocked() { } } func (s *headerSegments) reopen(dir string) error { - for i := range s.segments { - if err := s.segments[i].reopen(dir); err != nil { + for _, seg := range s.segments { + if err := seg.reopen(dir); err != nil { + if errors.Is(err, os.ErrNotExist) { + continue + } return err } } @@ -265,8 +268,11 @@ func (s *bodySegments) closeLocked() { } } func (s *bodySegments) reopen(dir string) error { - for i := range s.segments { - if err := s.segments[i].reopen(dir); err != nil { + for _, seg := range s.segments { + if err := seg.reopen(dir); err != nil { + if errors.Is(err, os.ErrNotExist) { + continue + } return err } } @@ -300,8 +306,11 @@ func (s *txnSegments) closeLocked() { } } func (s *txnSegments) reopen(dir string) error { - for i := range s.segments { - if err := s.segments[i].reopen(dir); err != nil { + for _, seg := range s.segments { + if err := seg.reopen(dir); err != nil { + if errors.Is(err, os.ErrNotExist) { + continue + } return err } } @@ -364,18 +373,6 @@ func (s *RoSnapshots) EnsureExpectedBlocksAreAvailable(cfg *snapshothashes.Confi return nil } -func (s *RoSnapshots) SegmentsAvailability() (headers, bodies, txs uint64, err error) { - if headers, err = latestSegment(s.dir, Headers); err != nil { - return - } - if bodies, err = latestSegment(s.dir, Bodies); err != nil { - return - } - if txs, err = latestSegment(s.dir, Transactions); err != nil { - return - } - return -} func (s *RoSnapshots) idxAvailability() uint64 { var headers, bodies, txs uint64 for i := len(s.Headers.segments) - 1; i >= 0; i-- { @@ -417,28 +414,19 @@ func (s *RoSnapshots) ReopenSomeIndices(types ...Type) (err error) { defer s.Bodies.lock.Unlock() s.Txs.lock.Lock() defer s.Txs.lock.Unlock() -Loop: + for _, t := range types { switch t { case Headers: if err := s.Headers.reopen(s.dir); err != nil { - if errors.Is(err, os.ErrNotExist) { - break Loop - } return err } case Bodies: if err := s.Bodies.reopen(s.dir); err != nil { - if errors.Is(err, os.ErrNotExist) { - break Loop - } return err } case Transactions: if err := s.Txs.reopen(s.dir); err != nil { - if errors.Is(err, os.ErrNotExist) { - break Loop - } return err } default: @@ -478,7 +466,7 @@ func (s *RoSnapshots) ReopenSegments() error { s.Txs.lock.Lock() defer s.Txs.lock.Unlock() s.closeSegmentsLocked() - files, err := segmentsOfType(s.dir, Headers) + files, err := segments2(s.dir) if err != nil { return err } @@ -553,6 +541,27 @@ func (s *RoSnapshots) closeSegmentsLocked() { s.Txs.segments = nil } } +func (s *RoSnapshots) PrintDebug() { + s.Headers.lock.Lock() + defer s.Headers.lock.Unlock() + s.Bodies.lock.Lock() + defer s.Bodies.lock.Unlock() + s.Txs.lock.Lock() + defer s.Txs.lock.Unlock() + fmt.Printf("sn: %d, %d\n", s.segmentsAvailable.Load(), s.idxAvailable.Load()) + fmt.Println(" == Snapshots, Header") + for _, sn := range s.Headers.segments { + fmt.Printf("%d, %t\n", sn.From, sn.idxHeaderHash == nil) + } + fmt.Println(" == Snapshots, Body") + for _, sn := range s.Bodies.segments { + fmt.Printf("%d, %t\n", sn.From, sn.idxBodyNumber == nil) + } + fmt.Println(" == Snapshots, Txs") + for _, sn := range s.Txs.segments { + fmt.Printf("%d, %t, %t, %t\n", sn.From, sn.IdxTxnId == nil, sn.IdxTxnHash == nil, sn.IdxTxnHash2BlockNum == nil) + } +} func (s *RoSnapshots) ViewHeaders(blockNum uint64, f func(sn *HeaderSegment) error) (found bool, err error) { if !s.indicesReady.Load() || blockNum > s.BlocksAvailable() { return false, nil @@ -635,23 +644,6 @@ func BuildIndices(ctx context.Context, s *RoSnapshots, snapshotDir *dir.Rw, chai return nil } -func latestSegment(dir string, ofType Type) (uint64, error) { - files, err := segmentsOfType(dir, ofType) - if err != nil { - return 0, err - } - var maxBlock uint64 - for _, f := range files { - if maxBlock < f.To { - maxBlock = f.To - } - } - if maxBlock == 0 { - return 0, nil - } - return maxBlock - 1, nil -} - // FileInfo - parsed file metadata type FileInfo struct { _ fs.FileInfo @@ -734,6 +726,26 @@ func parseDir(dir string) (res []FileInfo, err error) { return res, nil } +func allTypeOfSegmentsMustExist(dir string, in []FileInfo) (res []FileInfo) { +MainLoop: + for _, f := range in { + if f.From == f.To { + continue + } + for _, t := range AllSnapshotTypes { + p := filepath.Join(dir, SegmentFileName(f.From, f.To, t)) + if _, err := os.Stat(p); err != nil { + if errors.Is(err, os.ErrNotExist) { + continue MainLoop + } + continue MainLoop + } + } + res = append(res, f) + } + return res +} + // noOverlaps - keep largest ranges and avoid overlap func noOverlaps(in []FileInfo) (res []FileInfo) { for i := range in { @@ -759,33 +771,18 @@ func noOverlaps(in []FileInfo) (res []FileInfo) { return res } -func segmentsOfType(dir string, ofType Type) (res []FileInfo, err error) { +func segments2(dir string) (res []FileInfo, err error) { list, err := Segments(dir) if err != nil { return nil, err } for _, f := range list { - if f.T != ofType { - continue - } - res = append(res, f) - } - return noGaps(noOverlaps(res)) -} - -// nolint -func idxFilesOfType(dir string, ofType Type) (res []FileInfo, err error) { - files, err := IdxFiles(dir) - if err != nil { - return nil, err - } - for _, f := range files { - if f.T != ofType { + if f.T != Headers { continue } res = append(res, f) } - return noGaps(noOverlaps(res)) + return noGaps(noOverlaps(allTypeOfSegmentsMustExist(dir, res))) } func filterExt(in []FileInfo, expectExt string) (out []FileInfo) { -- GitLab