11// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
22
33use std:: any:: Any ;
4+ use std:: collections:: HashMap ;
45use std:: ops:: Range ;
56use std:: sync:: Arc ;
67use std:: time:: Duration ;
78
89use async_trait:: async_trait;
910use futures:: stream:: BoxStream ;
11+ use futures:: StreamExt ;
1012use tonic:: transport:: Channel ;
1113
1214use super :: RawRpcRequest ;
@@ -190,23 +192,44 @@ impl KvRequest for kvrpcpb::RawBatchPutRequest {
190192}
191193
192194impl Shardable for kvrpcpb:: RawBatchPutRequest {
193- type Shard = Vec < kvrpcpb:: KvPair > ;
195+ type Shard = Vec < ( kvrpcpb:: KvPair , u64 ) > ;
194196
195197 fn shards (
196198 & self ,
197199 pd_client : & Arc < impl PdClient > ,
198200 ) -> BoxStream < ' static , Result < ( Self :: Shard , RegionStore ) > > {
201+ // Maintain a map of the pair and its associated ttl
202+ let kvs = self . pairs . clone ( ) ;
203+ let kv_pair = kvs. into_iter ( ) . map ( Into :: < KvPair > :: into) ;
204+ let kv_ttl = kv_pair. zip ( self . ttls . clone ( ) ) . collect :: < HashMap < _ , _ > > ( ) ;
199205 let mut pairs = self . pairs . clone ( ) ;
200206 pairs. sort_by ( |a, b| a. key . cmp ( & b. key ) ) ;
201207 store_stream_for_keys (
202208 pairs. into_iter ( ) . map ( Into :: < KvPair > :: into) ,
203209 pd_client. clone ( ) ,
204210 )
211+ . map ( move |r| {
212+ let s = r. map ( |( kv, store) | {
213+ let kv_ttls = kv
214+ . into_iter ( )
215+ . map ( |k : KvPair | {
216+ let kv: kvrpcpb:: KvPair = k. clone ( ) . into ( ) ;
217+ let ttl = * kv_ttl. get ( & k) . unwrap ( ) ;
218+ ( kv, ttl)
219+ } )
220+ . collect :: < Vec < _ > > ( ) ;
221+ ( kv_ttls, store)
222+ } ) ;
223+ s
224+ } )
225+ . boxed ( )
205226 }
206227
207228 fn apply_shard ( & mut self , shard : Self :: Shard , store : & RegionStore ) -> Result < ( ) > {
229+ let ( pairs, ttls) = shard. into_iter ( ) . unzip ( ) ;
208230 self . set_leader ( & store. region_with_leader ) ?;
209- self . pairs = shard;
231+ self . pairs = pairs;
232+ self . ttls = ttls;
210233 Ok ( ( ) )
211234 }
212235}
@@ -531,21 +554,34 @@ impl_raw_rpc_request!(RawDeleteRangeRequest);
531554impl_raw_rpc_request ! ( RawCasRequest ) ;
532555
533556impl HasLocks for kvrpcpb:: RawGetResponse { }
557+
534558impl HasLocks for kvrpcpb:: RawBatchGetResponse { }
559+
535560impl HasLocks for kvrpcpb:: RawGetKeyTtlResponse { }
561+
536562impl HasLocks for kvrpcpb:: RawPutResponse { }
563+
537564impl HasLocks for kvrpcpb:: RawBatchPutResponse { }
565+
538566impl HasLocks for kvrpcpb:: RawDeleteResponse { }
567+
539568impl HasLocks for kvrpcpb:: RawBatchDeleteResponse { }
569+
540570impl HasLocks for kvrpcpb:: RawScanResponse { }
571+
541572impl HasLocks for kvrpcpb:: RawBatchScanResponse { }
573+
542574impl HasLocks for kvrpcpb:: RawDeleteRangeResponse { }
575+
543576impl HasLocks for kvrpcpb:: RawCasResponse { }
577+
544578impl HasLocks for kvrpcpb:: RawCoprocessorResponse { }
545579
546580#[ cfg( test) ]
547581mod test {
548582 use std:: any:: Any ;
583+ use std:: ops:: Deref ;
584+ use std:: sync:: Mutex ;
549585
550586 use super :: * ;
551587 use crate :: backoff:: DEFAULT_REGION_BACKOFF ;
@@ -555,7 +591,7 @@ mod test {
555591 use crate :: proto:: kvrpcpb;
556592 use crate :: request:: Keyspace ;
557593 use crate :: request:: Plan ;
558- use crate :: Key ;
594+
559595
560596 #[ rstest:: rstest]
561597 #[ case( Keyspace :: Disable ) ]
@@ -600,4 +636,62 @@ mod test {
600636 assert_eq ! ( scan. len( ) , 49 ) ;
601637 // FIXME test the keys returned.
602638 }
639+
640+ #[ tokio:: test]
641+ async fn test_raw_batch_put ( ) -> Result < ( ) > {
642+ let region1_kvs = vec ! [ KvPair ( vec![ 9 ] . into( ) , vec![ 12 ] . into( ) ) ] ;
643+ let region1_ttls = vec ! [ 0 ] ;
644+ let region2_kvs = vec ! [
645+ KvPair ( vec![ 11 ] . into( ) , vec![ 12 ] . into( ) ) ,
646+ KvPair (
647+ "FFF" . to_string( ) . as_bytes( ) . to_vec( ) . into( ) ,
648+ vec![ 12 ] . into( ) ,
649+ ) ,
650+ ] ;
651+ let region2_ttls = vec ! [ 0 , 1 ] ;
652+
653+ let expected_map = HashMap :: from ( [
654+ ( region1_kvs. clone ( ) , region1_ttls. clone ( ) ) ,
655+ ( region2_kvs. clone ( ) , region2_ttls. clone ( ) ) ,
656+ ] ) ;
657+
658+ let pairs: Vec < kvrpcpb:: KvPair > = [ region1_kvs, region2_kvs]
659+ . concat ( )
660+ . into_iter ( )
661+ . map ( |kv| kv. into ( ) )
662+ . collect ( ) ;
663+ let ttls = [ region1_ttls, region2_ttls] . concat ( ) ;
664+ let cf = ColumnFamily :: Default ;
665+
666+ let actual_map: Arc < Mutex < HashMap < Vec < KvPair > , Vec < u64 > > > > =
667+ Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ;
668+ let fut_actual_map = actual_map. clone ( ) ;
669+ let client = Arc :: new ( MockPdClient :: new ( MockKvClient :: with_dispatch_hook (
670+ move |req : & dyn Any | {
671+ let req: & kvrpcpb:: RawBatchPutRequest = req. downcast_ref ( ) . unwrap ( ) ;
672+ let kv_pair = req
673+ . pairs
674+ . clone ( )
675+ . into_iter ( )
676+ . map ( |p| p. into ( ) )
677+ . collect :: < Vec < KvPair > > ( ) ;
678+ let ttls = req. ttls . clone ( ) ;
679+ fut_actual_map. lock ( ) . unwrap ( ) . insert ( kv_pair, ttls) ;
680+ let resp = kvrpcpb:: RawBatchPutResponse :: default ( ) ;
681+ Ok ( Box :: new ( resp) as Box < dyn Any > )
682+ } ,
683+ ) ) ) ;
684+
685+ let batch_put_request =
686+ new_raw_batch_put_request ( pairs. clone ( ) , ttls. clone ( ) , Some ( cf) , false ) ;
687+ let keyspace = Keyspace :: Enable { keyspace_id : 0 } ;
688+ let plan = crate :: request:: PlanBuilder :: new ( client, keyspace, batch_put_request)
689+ . resolve_lock ( OPTIMISTIC_BACKOFF , keyspace)
690+ . retry_multi_region ( DEFAULT_REGION_BACKOFF )
691+ . plan ( ) ;
692+ let _ = plan. execute ( ) . await ;
693+ assert_eq ! ( actual_map. lock( ) . unwrap( ) . len( ) , 2 ) ;
694+ assert_eq ! ( actual_map. lock( ) . unwrap( ) . deref( ) . clone( ) , expected_map) ;
695+ Ok ( ( ) )
696+ }
603697}
0 commit comments