@@ -413,20 +413,18 @@ unsafe extern "C" fn kv_io_read(
413413 let end_chunk = ( offset + requested_length - 1 ) / kv:: CHUNK_SIZE ;
414414
415415 let mut chunk_keys_to_fetch = Vec :: new( ) ;
416- let mut buffered_chunks: HashMap <usize , Vec <u8 >> = HashMap :: new( ) ;
416+ let mut buffered_chunks = HashMap :: new( ) ;
417+ // Skip fetching chunks already present in the dirty buffer (batch mode) or read cache.
417418 for chunk_idx in start_chunk..=end_chunk {
418- // Check dirty buffer first (batch mode writes).
419419 if state. batch_mode {
420- if let Some ( buffered) = state. dirty_buffer. get( & ( chunk_idx as u32 ) ) {
421- buffered_chunks. insert( chunk_idx, buffered. clone( ) ) ;
420+ if state. dirty_buffer. contains_key( & ( chunk_idx as u32 ) ) {
422421 continue ;
423422 }
424423 }
425- // Check read cache.
426424 let key = kv:: get_chunk_key( file. file_tag, chunk_idx as u32 ) ;
427425 if let Some ( read_cache) = state. read_cache. as_ref( ) {
428426 if let Some ( cached) = read_cache. get( key. as_slice( ) ) {
429- buffered_chunks. insert( chunk_idx, cached. clone ( ) ) ;
427+ buffered_chunks. insert( chunk_idx, cached. as_slice ( ) ) ;
430428 continue ;
431429 }
432430 }
@@ -440,29 +438,24 @@ unsafe extern "C" fn kv_io_read(
440438 }
441439 } else {
442440 match ctx. kv_get( chunk_keys_to_fetch) {
443- Ok ( resp) => {
444- if let Some ( read_cache) = state. read_cache. as_mut( ) {
445- for ( key, value) in resp. keys. iter( ) . zip( resp. values. iter( ) ) {
446- if !value. is_empty( ) {
447- read_cache. insert( key. clone( ) , value. clone( ) ) ;
448- }
449- }
450- }
451- resp
452- }
441+ Ok ( resp) => resp,
453442 Err ( _) => return SQLITE_IOERR_READ ,
454443 }
455444 } ;
456445 let value_map = build_value_map( & resp) ;
457446
458447 for chunk_idx in start_chunk..=end_chunk {
459- let chunk_data: Option <& [ u8 ] > = buffered_chunks
460- . get( & chunk_idx)
461- . map( |v| v. as_slice( ) )
462- . or_else( || {
463- let key = kv:: get_chunk_key( file. file_tag, chunk_idx as u32 ) ;
464- value_map. get( key. as_slice( ) ) . copied( )
465- } ) ;
448+ let chunk_key = kv:: get_chunk_key( file. file_tag, chunk_idx as u32 ) ;
449+ let chunk_data = if state. batch_mode {
450+ state
451+ . dirty_buffer
452+ . get( & ( chunk_idx as u32 ) )
453+ . map( |buffered| buffered. as_slice( ) )
454+ } else {
455+ None
456+ }
457+ . or_else( || buffered_chunks. get( & chunk_idx) . copied( ) )
458+ . or_else( || value_map. get( chunk_key. as_slice( ) ) . copied( ) ) ;
466459 let chunk_offset = chunk_idx * kv:: CHUNK_SIZE ;
467460 let read_start = offset. saturating_sub( chunk_offset) ;
468461 let read_end = std:: cmp:: min( kv:: CHUNK_SIZE , offset + requested_length - chunk_offset) ;
@@ -485,6 +478,14 @@ unsafe extern "C" fn kv_io_read(
485478 }
486479 }
487480
481+ if let Some ( read_cache) = state. read_cache. as_mut( ) {
482+ for ( key, value) in resp. keys. iter( ) . zip( resp. values. iter( ) ) {
483+ if !value. is_empty( ) {
484+ read_cache. insert( key. clone( ) , value. clone( ) ) ;
485+ }
486+ }
487+ }
488+
488489 let actual_bytes = std:: cmp:: min( requested_length, file_size - offset) ;
489490 if actual_bytes < requested_length {
490491 buf[ actual_bytes..] . fill( 0 ) ;
0 commit comments