Advance the current-segment iterator to yield the next commit. Checks that the offset sequence is contiguous, and may skip commits until the requested offset. Returns `None` if the segment iterator is exhausted or returns an error.
(&mut self)
| 864 | /// |
| 865 | /// Returns `None` if the segment iterator is exhausted or returns an error. |
| 866 | fn next_commit(&mut self) -> Option<Result<StoredCommit, error::Traversal>> { |
| 867 | loop { |
| 868 | match self.inner.as_mut()?.next()? { |
| 869 | Ok(commit) => { |
| 870 | // Pop the last error. Either we'll return it below, or it's no longer |
| 871 | // interesting. |
| 872 | let prev_error = self.last_error.take(); |
| 873 | |
| 874 | // Skip entries before the initial commit. |
| 875 | if self.last_commit.adjust_initial_offset(&commit) { |
| 876 | trace!("adjust initial offset"); |
| 877 | continue; |
| 878 | // Same offset: ignore if duplicate (same crc), else report a "fork". |
| 879 | } else if self.last_commit.same_offset_as(&commit) { |
| 880 | if !self.last_commit.same_checksum_as(&commit) { |
| 881 | warn!( |
| 882 | "forked: commit={:?} last-error={:?} last-crc={:?}", |
| 883 | commit, |
| 884 | prev_error, |
| 885 | self.last_commit.checksum() |
| 886 | ); |
| 887 | return Some(Err(error::Traversal::Forked { |
| 888 | offset: commit.min_tx_offset, |
| 889 | })); |
| 890 | } else { |
| 891 | trace!("ignore duplicate"); |
| 892 | continue; |
| 893 | } |
| 894 | // Not the expected offset: report out-of-order. |
| 895 | } else if self.last_commit.expected_offset() != &commit.min_tx_offset { |
| 896 | warn!("out-of-order: commit={commit:?} last-error={prev_error:?}"); |
| 897 | return Some(Err(error::Traversal::OutOfOrder { |
| 898 | expected_offset: *self.last_commit.expected_offset(), |
| 899 | actual_offset: commit.min_tx_offset, |
| 900 | prev_error: prev_error.map(Box::new), |
| 901 | })); |
| 902 | // Seems legit, record info. |
| 903 | } else { |
| 904 | self.last_commit = CommitInfo::LastSeen { |
| 905 | tx_range: commit.tx_range(), |
| 906 | checksum: commit.checksum, |
| 907 | }; |
| 908 | |
| 909 | return Some(Ok(commit)); |
| 910 | } |
| 911 | } |
| 912 | |
| 913 | Err(e) => { |
| 914 | warn!("error reading next commit: {e}"); |
| 915 | // Stop traversing this segment here. |
| 916 | // |
| 917 | // If this is just a partial write at the end of the segment, |
| 918 | // we may be able to obtain a commit with right offset from |
| 919 | // the next segment. |
| 920 | // |
| 921 | // If we don't, the error here is likely more helpful, but |
| 922 | // would be clobbered by `OutOfOrder`. Therefore we store it |
| 923 | // here. |
no test coverage detected