@@ -5,9 +5,10 @@ use log::{debug, info, trace, warn};
55
66use crate :: {
77 commit:: StoredCommit ,
8- error,
8+ error:: { self , source_chain} ,
9+ index:: IndexError ,
910 payload:: Decoder ,
10- repo:: { self , Repo } ,
11+ repo:: { self , Repo , TxOffsetIndex } ,
1112 segment:: { self , FileLike , Transaction , Writer } ,
1213 Commit , Encode , Options , DEFAULT_LOG_FORMAT_VERSION ,
1314} ;
@@ -476,25 +477,8 @@ fn reset_to_internal(repo: &impl Repo, segments: &[u64], offset: u64) -> io::Res
476477 // Read commit-wise until we find the byte offset.
477478 let mut reader = repo:: open_segment_reader ( repo, DEFAULT_LOG_FORMAT_VERSION , segment) ?;
478479
479- let ( index_file, mut byte_offset) = repo
480- . get_offset_index ( segment)
481- . and_then ( |index_file| {
482- let ( key, byte_offset) = index_file. key_lookup ( offset) . map_err ( |e| {
483- io:: Error :: new ( io:: ErrorKind :: NotFound , format ! ( "Offset index cannot be used: {e:?}" ) )
484- } ) ?;
485-
486- reader. seek_to_offset ( & index_file, key) . map_err ( |e| {
487- io:: Error :: new (
488- io:: ErrorKind :: InvalidData ,
489- format ! ( "Offset index is not used at offset {key}: {e}" ) ,
490- )
491- } ) ?;
492-
493- Ok ( ( Some ( index_file) , byte_offset) )
494- } )
495- . inspect_err ( |e| {
496- warn ! ( "commitlog offset index is not used: {e:?}" ) ;
497- } )
480+ let ( index_file, mut byte_offset) = try_seek_using_offset_index ( repo, & mut reader, offset)
481+ . map ( |( index_file, byte_offset) | ( Some ( index_file) , byte_offset) )
498482 . unwrap_or ( ( None , segment:: Header :: LEN as u64 ) ) ;
499483
500484 let commits = reader. commits ( ) ;
@@ -732,18 +716,7 @@ impl<R: Repo> Commits<R> {
732716 /// index to advance the segment reader.
733717 fn try_seek_to_initial_offset ( & self , segment : & mut segment:: Reader < R :: SegmentReader > ) {
734718 if let CommitInfo :: Initial { next_offset } = & self . last_commit {
735- let _ = self
736- . segments
737- . repo
738- . get_offset_index ( segment. min_tx_offset )
739- . map_err ( Into :: into)
740- . and_then ( |index_file| segment. seek_to_offset ( & index_file, * next_offset) )
741- . inspect_err ( |e| {
742- warn ! (
743- "commitlog offset index is not used at segment {}: {}" ,
744- segment. min_tx_offset, e
745- ) ;
746- } ) ;
719+ try_seek_using_offset_index ( & self . segments . repo , segment, * next_offset) ;
747720 }
748721 }
749722}
@@ -794,6 +767,48 @@ impl<R: Repo> Iterator for CommitsWithVersion<R> {
794767 }
795768}
796769
770+ /// Try to advance `reader` to `offset` using the offset index.
771+ ///
772+ /// If successful, returns the offset index and the byte position of `reader`.
773+ /// `None` if the position of `reader` is unchanged.
774+ fn try_seek_using_offset_index < R : Repo > (
775+ repo : & R ,
776+ reader : & mut segment:: Reader < R :: SegmentReader > ,
777+ offset : u64 ,
778+ ) -> Option < ( TxOffsetIndex , u64 ) > {
779+ let segment_offset = reader. min_tx_offset ;
780+ let index = repo
781+ . get_offset_index ( segment_offset)
782+ . inspect_err ( |e| {
783+ if e. kind ( ) == io:: ErrorKind :: NotFound {
784+ debug ! ( "offset index does not exist segment={segment_offset}" ) ;
785+ } else {
786+ warn ! (
787+ "error opening offset index segment={segment_offset}: {e} {}" ,
788+ source_chain( & e)
789+ ) ;
790+ }
791+ } )
792+ . ok ( ) ?;
793+
794+ reader
795+ . seek_to_offset ( & index, offset)
796+ . inspect_err ( |e| match e {
797+ // Can happen if the segment is empty or small, so don't spam the logs.
798+ IndexError :: KeyNotFound => {
799+ debug ! ( "offset not found segment={segment_offset} offset={offset}" ) ;
800+ }
801+ e => {
802+ warn ! (
803+ "error reading index segment={segment_offset} offset={offset}: {e} {}" ,
804+ source_chain( & e)
805+ ) ;
806+ }
807+ } )
808+ . ok ( )
809+ . map ( |pos| ( index, pos) )
810+ }
811+
797812#[ cfg( test) ]
798813mod tests {
799814 use std:: { cell:: Cell , iter:: repeat} ;
0 commit comments