@@ -543,6 +543,40 @@ pub struct CacheBuffer {
543543 handle : Option < CachePinnedHandle > ,
544544}
545545
546+ const STORAGE_BATCH_LINEAR_SCAN_MAX_KEYS : usize = 64 ;
547+
548+ fn coalesce_storage_batch_keys ( keys : & [ String ] ) -> ( Vec < String > , Vec < usize > ) {
549+ if keys. len ( ) <= STORAGE_BATCH_LINEAR_SCAN_MAX_KEYS {
550+ let mut unique_keys = Vec :: < String > :: with_capacity ( keys. len ( ) ) ;
551+ let mut output_positions = Vec :: with_capacity ( keys. len ( ) ) ;
552+ for key in keys {
553+ if let Some ( position) = unique_keys. iter ( ) . position ( |existing| existing == key) {
554+ output_positions. push ( position) ;
555+ } else {
556+ output_positions. push ( unique_keys. len ( ) ) ;
557+ unique_keys. push ( key. clone ( ) ) ;
558+ }
559+ }
560+ return ( unique_keys, output_positions) ;
561+ }
562+
563+ let mut unique_keys = Vec :: < String > :: with_capacity ( keys. len ( ) ) ;
564+ let mut unique_positions = HashMap :: < String , usize > :: with_capacity ( keys. len ( ) ) ;
565+ let mut output_positions = Vec :: with_capacity ( keys. len ( ) ) ;
566+ for key in keys {
567+ let position = if let Some ( position) = unique_positions. get ( key) . copied ( ) {
568+ position
569+ } else {
570+ let position = unique_keys. len ( ) ;
571+ unique_positions. insert ( key. clone ( ) , position) ;
572+ unique_keys. push ( key. clone ( ) ) ;
573+ position
574+ } ;
575+ output_positions. push ( position) ;
576+ }
577+ ( unique_keys, output_positions)
578+ }
579+
546580impl CacheBuffer {
547581 pub fn new ( value : impl Into < Vec < u8 > > ) -> Self {
548582 Self {
@@ -2352,20 +2386,7 @@ impl StorageEngineRocksDb {
23522386 if keys. is_empty ( ) {
23532387 return Ok ( Vec :: new ( ) ) ;
23542388 }
2355- let mut unique_keys = Vec :: < String > :: new ( ) ;
2356- let mut unique_positions = HashMap :: < String , usize > :: new ( ) ;
2357- let mut output_positions = Vec :: with_capacity ( keys. len ( ) ) ;
2358- for key in keys {
2359- let position = if let Some ( position) = unique_positions. get ( key) . copied ( ) {
2360- position
2361- } else {
2362- let position = unique_keys. len ( ) ;
2363- unique_positions. insert ( key. clone ( ) , position) ;
2364- unique_keys. push ( key. clone ( ) ) ;
2365- position
2366- } ;
2367- output_positions. push ( position) ;
2368- }
2389+ let ( unique_keys, output_positions) = coalesce_storage_batch_keys ( keys) ;
23692390 #[ cfg( feature = "rocksdb-ssd" ) ]
23702391 let unique_values = {
23712392 self . rocksdb ( ) ?
@@ -2997,6 +3018,96 @@ impl StorageEngineMultiSsd {
29973018 self . ssdcache_type
29983019 }
29993020
3021+ pub fn get_batch ( & self , keys : & [ String ] ) -> Result < Vec < Option < Vec < u8 > > > , CacheError > {
3022+ if !self . initialized || self . storages . is_empty ( ) {
3023+ return Err ( CacheError :: Stopped ) ;
3024+ }
3025+ if keys. is_empty ( ) {
3026+ return Ok ( Vec :: new ( ) ) ;
3027+ }
3028+
3029+ let ( unique_keys, output_positions) = coalesce_storage_batch_keys ( keys) ;
3030+
3031+ let mut routed = vec ! [ Vec :: <( usize , String ) >:: new( ) ; self . storages. len( ) ] ;
3032+ for ( unique_index, key) in unique_keys. iter ( ) . enumerate ( ) {
3033+ let storage_index = Self :: hash ( key) as usize % self . storages . len ( ) ;
3034+ routed[ storage_index] . push ( ( unique_index, key. clone ( ) ) ) ;
3035+ }
3036+
3037+ let mut unique_values = vec ! [ None ; unique_keys. len( ) ] ;
3038+ for ( storage_index, entries) in routed. into_iter ( ) . enumerate ( ) {
3039+ if entries. is_empty ( ) {
3040+ continue ;
3041+ }
3042+ let storage_keys = entries
3043+ . iter ( )
3044+ . map ( |( _, key) | key. clone ( ) )
3045+ . collect :: < Vec < _ > > ( ) ;
3046+ let storage_values = self . storages [ storage_index] . get_batch ( & storage_keys) ?;
3047+ for ( ( unique_index, _) , value) in entries. into_iter ( ) . zip ( storage_values) {
3048+ unique_values[ unique_index] = value;
3049+ }
3050+ }
3051+
3052+ Ok ( output_positions
3053+ . into_iter ( )
3054+ . map ( |position| unique_values[ position] . clone ( ) )
3055+ . collect ( ) )
3056+ }
3057+
3058+ pub fn put_batch ( & mut self , entries : Vec < ( String , Vec < u8 > ) > ) -> Result < usize , CacheError > {
3059+ if !self . initialized || self . storages . is_empty ( ) {
3060+ return Err ( CacheError :: Stopped ) ;
3061+ }
3062+ if entries. is_empty ( ) {
3063+ return Ok ( 0 ) ;
3064+ }
3065+
3066+ let count = entries. len ( ) ;
3067+ let mut routed = vec ! [ Vec :: <( String , Vec <u8 >) >:: new( ) ; self . storages. len( ) ] ;
3068+ for ( key, value) in entries {
3069+ let storage_index = Self :: hash ( & key) as usize % self . storages . len ( ) ;
3070+ routed[ storage_index] . push ( ( key, value) ) ;
3071+ }
3072+
3073+ for ( storage_index, entries) in routed. into_iter ( ) . enumerate ( ) {
3074+ if entries. is_empty ( ) {
3075+ continue ;
3076+ }
3077+ self . storages [ storage_index] . put_batch ( entries) ?;
3078+ }
3079+
3080+ Ok ( count)
3081+ }
3082+
3083+ pub fn delete_batch ( & mut self , keys : & [ String ] ) -> Result < usize , CacheError > {
3084+ if !self . initialized || self . storages . is_empty ( ) {
3085+ return Err ( CacheError :: Stopped ) ;
3086+ }
3087+ if keys. is_empty ( ) {
3088+ return Ok ( 0 ) ;
3089+ }
3090+
3091+ let mut routed = vec ! [ Vec :: <String >:: new( ) ; self . storages. len( ) ] ;
3092+ let mut seen = HashSet :: < String > :: new ( ) ;
3093+ for key in keys {
3094+ if !seen. insert ( key. clone ( ) ) {
3095+ continue ;
3096+ }
3097+ let storage_index = Self :: hash ( key) as usize % self . storages . len ( ) ;
3098+ routed[ storage_index] . push ( key. clone ( ) ) ;
3099+ }
3100+
3101+ let mut deleted = 0usize ;
3102+ for ( storage_index, keys) in routed. into_iter ( ) . enumerate ( ) {
3103+ if keys. is_empty ( ) {
3104+ continue ;
3105+ }
3106+ deleted = deleted. saturating_add ( self . storages [ storage_index] . delete_batch ( & keys) ?) ;
3107+ }
3108+ Ok ( deleted)
3109+ }
3110+
30003111 #[ cfg( feature = "rocksdb-ssd" ) ]
30013112 pub fn recover_view_data < C > ( & mut self , callback : & mut C ) -> Result < ( ) , CacheError >
30023113 where
@@ -3701,4 +3812,3 @@ impl StringViewBuffer {
37013812 self . size ( )
37023813 }
37033814}
3704-
0 commit comments