From 1f314ee77657131e509554ee7b127e7a94851050 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 21 Jun 2022 20:48:39 +0800 Subject: [PATCH 01/43] fix type checking for new interface Signed-off-by: iosmanthus --- src/lib.rs | 2 + src/pd/client.rs | 96 +++++++----- src/raw/client.rs | 34 +++-- src/raw/lowering.rs | 61 ++++---- src/raw/requests.rs | 154 ++++++++++++++++---- src/request/mod.rs | 40 +++-- src/request/plan.rs | 71 +++++---- src/request/plan_builder.rs | 69 +++++---- src/request/request_codec.rs | 22 +++ src/request/shard.rs | 2 +- src/transaction/client.rs | 44 +++--- src/transaction/lock.rs | 13 +- src/transaction/lowering.rs | 53 +++---- src/transaction/requests.rs | 259 +++++++++++++++++++++++++-------- src/transaction/snapshot.rs | 7 +- src/transaction/transaction.rs | 107 +++++++------- 16 files changed, 687 insertions(+), 347 deletions(-) create mode 100644 src/request/request_codec.rs diff --git a/src/lib.rs b/src/lib.rs index e94785b0..7e90b420 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,8 @@ //! # })} //! ``` +#![feature(specialization)] +#![feature(explicit_generic_args_with_impl_trait)] #[macro_use] pub mod request; #[macro_use] diff --git a/src/pd/client.rs b/src/pd/client.rs index 8bccbe32..8a886247 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -1,23 +1,28 @@ // Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. -use crate::{ - compat::stream_fn, - kv::codec, - pd::{retry::RetryClientTrait, RetryClient}, - region::{RegionId, RegionVerId, RegionWithLeader}, - region_cache::RegionCache, - store::RegionStore, - BoundRange, Config, Key, Result, SecurityManager, Timestamp, -}; +use std::{collections::HashMap, sync::Arc, thread}; +use std::marker::PhantomData; + use async_trait::async_trait; use futures::{prelude::*, stream::BoxStream}; use grpcio::{EnvBuilder, Environment}; use slog::Logger; -use std::{collections::HashMap, sync::Arc, thread}; +use tokio::sync::RwLock; + use tikv_client_pd::Cluster; use tikv_client_proto::{kvrpcpb, metapb}; use tikv_client_store::{KvClient, KvConnect, TikvConnect}; -use tokio::sync::RwLock; + +use crate::{ + BoundRange, + compat::stream_fn, + Config, + Key, + kv::codec, + pd::{retry::RetryClientTrait, RetryClient}, + region::{RegionId, RegionVerId, RegionWithLeader}, region_cache::RegionCache, Result, SecurityManager, store::RegionStore, Timestamp, +}; +use crate::request::request_codec::RequestCodec; const CQ_COUNT: usize = 1; const CLIENT_PREFIX: &str = "tikv-client"; @@ -42,6 +47,7 @@ const CLIENT_PREFIX: &str = "tikv-client"; #[async_trait] pub trait PdClient: Send + Sync + 'static { type KvClient: KvClient + Send + Sync + 'static; + type RequestCodec: RequestCodec; /// In transactional API, `region` is decoded (keys in raw format). async fn map_region_to_store(self: Arc, region: RegionWithLeader) -> Result; @@ -69,11 +75,11 @@ pub trait PdClient: Send + Sync + 'static { fn group_keys_by_region( self: Arc, - keys: impl Iterator + Send + Sync + 'static, + keys: impl Iterator + Send + Sync + 'static, ) -> BoxStream<'static, Result<(RegionId, Vec)>> - where - K: AsRef + Into + Send + Sync + 'static, - K2: Send + Sync + 'static, + where + K: AsRef + Into + Send + Sync + 'static, + K2: Send + Sync + 'static, { let keys = keys.peekable(); stream_fn(keys, move |mut keys| { @@ -95,7 +101,7 @@ pub trait PdClient: Send + Sync + 'static { } } }) - .boxed() + .boxed() } /// Returns a Stream which iterates over the contexts for each region covered by range. @@ -126,7 +132,7 @@ pub trait PdClient: Send + Sync + 'static { Ok(Some((Some(region_end), store))) } }) - .boxed() + .boxed() } /// Returns a Stream which iterates over the contexts for ranges in the same region. @@ -190,7 +196,7 @@ pub trait PdClient: Send + Sync + 'static { } } }) - .boxed() + .boxed() } fn decode_region(mut region: RegionWithLeader, enable_codec: bool) -> Result { @@ -204,22 +210,27 @@ pub trait PdClient: Send + Sync + 'static { async fn update_leader(&self, ver_id: RegionVerId, leader: metapb::Peer) -> Result<()>; async fn invalidate_region_cache(&self, ver_id: RegionVerId); + + fn get_request_codec(&self) -> Self::RequestCodec; } /// This client converts requests for the logical TiKV cluster into requests /// for a single TiKV store using PD and internal logic. -pub struct PdRpcClient { +pub struct PdRpcClient { pd: Arc>, kv_connect: KvC, kv_client_cache: Arc>>, enable_codec: bool, region_cache: RegionCache>, logger: Logger, + // TODO: change to a real codec. + _phantom: PhantomData, } #[async_trait] -impl PdClient for PdRpcClient { +impl PdClient for PdRpcClient { type KvClient = KvC::KvClient; + type RequestCodec = C; async fn map_region_to_store(self: Arc, region: RegionWithLeader) -> Result { let store_id = region.get_store_id()?; @@ -260,15 +271,19 @@ impl PdClient for PdRpcClient { async fn invalidate_region_cache(&self, ver_id: RegionVerId) { self.region_cache.invalidate_region_cache(ver_id).await } + + fn get_request_codec(&self) -> Self::RequestCodec { + todo!() + } } -impl PdRpcClient { +impl PdRpcClient { pub async fn connect( pd_endpoints: &[String], config: Config, enable_codec: bool, logger: Logger, - ) -> Result { + ) -> Result> { PdRpcClient::new( config.clone(), |env, security_mgr| TikvConnect::new(env, security_mgr, config.timeout), @@ -278,7 +293,7 @@ impl PdRpcClient { enable_codec, logger, ) - .await + .await } } @@ -291,18 +306,18 @@ fn thread_name(prefix: &str) -> String { .unwrap_or_else(|| prefix.to_owned()) } -impl PdRpcClient { +impl PdRpcClient { pub async fn new( config: Config, kv_connect: MakeKvC, pd: MakePd, enable_codec: bool, logger: Logger, - ) -> Result> - where - PdFut: Future>>, - MakeKvC: FnOnce(Arc, Arc) -> KvC, - MakePd: FnOnce(Arc, Arc) -> PdFut, + ) -> Result> + where + PdFut: Future>>, + MakeKvC: FnOnce(Arc, Arc) -> KvC, + MakePd: FnOnce(Arc, Arc) -> PdFut, { let env = Arc::new( EnvBuilder::new() @@ -312,7 +327,7 @@ impl PdRpcClient { ); let security_mgr = Arc::new( if let (Some(ca_path), Some(cert_path), Some(key_path)) = - (&config.ca_path, &config.cert_path, &config.key_path) + (&config.ca_path, &config.cert_path, &config.key_path) { SecurityManager::load(ca_path, cert_path, key_path)? } else { @@ -329,6 +344,8 @@ impl PdRpcClient { enable_codec, region_cache: RegionCache::new(pd), logger, + // TODO + _phantom: PhantomData, }) } @@ -352,10 +369,11 @@ impl PdRpcClient { #[cfg(test)] pub mod test { - use super::*; + use futures::{executor, executor::block_on}; + use crate::mock::*; - use futures::{executor, executor::block_on}; + use super::*; #[tokio::test] async fn test_kv_client_caching() { @@ -396,7 +414,7 @@ pub mod test { vec![1].into(), vec![2].into(), vec![3].into(), - vec![5, 2].into() + vec![5, 2].into(), ] ); assert_eq!( @@ -458,12 +476,12 @@ pub mod test { vec![ kvrpcpb::KeyRange { start_key: k1.clone(), - end_key: k2.clone() + end_key: k2.clone(), }, kvrpcpb::KeyRange { start_key: k1, - end_key: k_split.clone() - } + end_key: k_split.clone(), + }, ] ); assert_eq!(ranges2.0, 2); @@ -471,7 +489,7 @@ pub mod test { ranges2.1, vec![kvrpcpb::KeyRange { start_key: k_split.clone(), - end_key: k3 + end_key: k3, }] ); assert_eq!(ranges3.0, 1); @@ -479,7 +497,7 @@ pub mod test { ranges3.1, vec![kvrpcpb::KeyRange { start_key: k2, - end_key: k_split.clone() + end_key: k_split.clone(), }] ); assert_eq!(ranges4.0, 2); @@ -487,7 +505,7 @@ pub mod test { ranges4.1, vec![kvrpcpb::KeyRange { start_key: k_split, - end_key: k4 + end_key: k4, }] ); assert!(stream.next().is_none()); diff --git a/src/raw/client.rs b/src/raw/client.rs index 3252e408..430386d3 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -2,6 +2,7 @@ use core::ops::Range; use std::{str::FromStr, sync::Arc, u32}; +use std::marker::PhantomData; use slog::{Drain, Logger}; use tikv_client_common::Error; @@ -15,6 +16,7 @@ use crate::{ request::{Collect, CollectSingle, Plan}, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; +use crate::request::request_codec::RequestCodec; const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; @@ -26,15 +28,16 @@ const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; /// The returned results of raw request methods are [`Future`](std::future::Future)s that must be /// awaited to execute. #[derive(Clone)] -pub struct Client { +pub struct Client> { rpc: Arc, cf: Option, /// Whether to use the [`atomic mode`](Client::with_atomic_for_cas). atomic: bool, logger: Logger, + _phantom: std::marker::PhantomData, } -impl Client { +impl Client> { /// Create a raw [`Client`] and connect to the TiKV cluster. /// /// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for @@ -103,6 +106,7 @@ impl Client { cf: None, atomic: false, logger, + _phantom: PhantomData }) } @@ -137,6 +141,7 @@ impl Client { cf: Some(cf), atomic: self.atomic, logger: self.logger.clone(), + _phantom: PhantomData } } @@ -154,11 +159,12 @@ impl Client { cf: self.cf.clone(), atomic: true, logger: self.logger.clone(), + _phantom: PhantomData } } } -impl Client { +impl Client { /// Create a new 'get' request. /// /// Once resolved this request will result in the fetching of the value associated with the @@ -179,7 +185,7 @@ impl Client { /// ``` pub async fn get(&self, key: impl Into) -> Result> { debug!(self.logger, "invoking raw get request"); - let request = new_raw_get_request(key.into(), self.cf.clone()); + let request = new_raw_get_request::(key.into(), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(CollectSingle) @@ -211,7 +217,7 @@ impl Client { keys: impl IntoIterator>, ) -> Result> { debug!(self.logger, "invoking raw batch_get request"); - let request = new_raw_batch_get_request(keys.into_iter().map(Into::into), self.cf.clone()); + let request = new_raw_batch_get_request::(keys.into_iter().map(Into::into), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(Collect) @@ -239,7 +245,7 @@ impl Client { /// ``` pub async fn put(&self, key: impl Into, value: impl Into) -> Result<()> { debug!(self.logger, "invoking raw put request"); - let request = new_raw_put_request(key.into(), value.into(), self.cf.clone(), self.atomic); + let request = new_raw_put_request::(key.into(), value.into(), self.cf.clone(), self.atomic); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(CollectSingle) @@ -271,7 +277,7 @@ impl Client { pairs: impl IntoIterator>, ) -> Result<()> { debug!(self.logger, "invoking raw batch_put request"); - let request = new_raw_batch_put_request( + let request = new_raw_batch_put_request::( pairs.into_iter().map(Into::into), self.cf.clone(), self.atomic, @@ -303,7 +309,7 @@ impl Client { /// ``` pub async fn delete(&self, key: impl Into) -> Result<()> { debug!(self.logger, "invoking raw delete request"); - let request = new_raw_delete_request(key.into(), self.cf.clone(), self.atomic); + let request = new_raw_delete_request::(key.into(), self.cf.clone(), self.atomic); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(CollectSingle) @@ -334,7 +340,7 @@ impl Client { debug!(self.logger, "invoking raw batch_delete request"); self.assert_non_atomic()?; let request = - new_raw_batch_delete_request(keys.into_iter().map(Into::into), self.cf.clone()); + new_raw_batch_delete_request::(keys.into_iter().map(Into::into), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .extract_error() @@ -369,7 +375,7 @@ impl Client { ) -> Result<()> { debug!(self.logger, "invoking raw delete_range request"); self.assert_non_atomic()?; - let request = new_raw_delete_range_request(range.into(), self.cf.clone()); + let request = new_raw_delete_range_request::(range.into(), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .extract_error() @@ -520,7 +526,7 @@ impl Client { ) -> Result<(Option, bool)> { debug!(self.logger, "invoking raw compare_and_swap request"); self.assert_atomic()?; - let req = new_cas_request( + let req = new_cas_request::( key.into(), new_value.into(), previous_value.into(), @@ -543,7 +549,7 @@ impl Client { ) -> Result, Vec>)>> { let copr_version_req = copr_version_req.into(); semver::VersionReq::from_str(&copr_version_req)?; - let req = new_raw_coprocessor_request( + let req = new_raw_coprocessor_request::( copr_name.into(), copr_version_req, ranges.into_iter().map(Into::into), @@ -570,7 +576,7 @@ impl Client { }); } - let request = new_raw_scan_request(range.into(), limit, key_only, self.cf.clone()); + let request = new_raw_scan_request::(range.into(), limit, key_only, self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(Collect) @@ -595,7 +601,7 @@ impl Client { }); } - let request = new_raw_batch_scan_request( + let request = new_raw_batch_scan_request::( ranges.into_iter().map(Into::into), each_limit, key_only, diff --git a/src/raw/lowering.rs b/src/raw/lowering.rs index 32327a80..d9ae6de4 100644 --- a/src/raw/lowering.rs +++ b/src/raw/lowering.rs @@ -5,70 +5,73 @@ //! generated protobuf code, then calls the low-level ctor functions in the requests module. use std::{iter::Iterator, ops::Range, sync::Arc}; +use std::marker::PhantomData; use tikv_client_proto::{kvrpcpb, metapb}; -use crate::{raw::requests, BoundRange, ColumnFamily, Key, KvPair, Value}; +use crate::{BoundRange, ColumnFamily, Key, KvPair, raw::requests, Value}; +use crate::request::KvRequest; +use crate::request::request_codec::RequestCodec; -pub fn new_raw_get_request(key: Key, cf: Option) -> kvrpcpb::RawGetRequest { - requests::new_raw_get_request(key.into(), cf) +pub fn new_raw_get_request(key: Key, cf: Option) -> kvrpcpb::RawGetRequest { + requests::new_raw_get_request::(key.into(), cf) } -pub fn new_raw_batch_get_request( - keys: impl Iterator, +pub fn new_raw_batch_get_request( + keys: impl Iterator, cf: Option, ) -> kvrpcpb::RawBatchGetRequest { - requests::new_raw_batch_get_request(keys.map(Into::into).collect(), cf) + requests::new_raw_batch_get_request::(keys.map(Into::into).collect(), cf) } -pub fn new_raw_put_request( +pub fn new_raw_put_request( key: Key, value: Value, cf: Option, atomic: bool, ) -> kvrpcpb::RawPutRequest { - requests::new_raw_put_request(key.into(), value, cf, atomic) + requests::new_raw_put_request::(key.into(), value, cf, atomic) } -pub fn new_raw_batch_put_request( - pairs: impl Iterator, +pub fn new_raw_batch_put_request( + pairs: impl Iterator, cf: Option, atomic: bool, ) -> kvrpcpb::RawBatchPutRequest { - requests::new_raw_batch_put_request(pairs.map(Into::into).collect(), cf, atomic) + requests::new_raw_batch_put_request::(pairs.map(Into::into).collect(), cf, atomic) } -pub fn new_raw_delete_request( +pub fn new_raw_delete_request( key: Key, cf: Option, atomic: bool, ) -> kvrpcpb::RawDeleteRequest { - requests::new_raw_delete_request(key.into(), cf, atomic) + requests::new_raw_delete_request::(key.into(), cf, atomic) } -pub fn new_raw_batch_delete_request( - keys: impl Iterator, +pub fn new_raw_batch_delete_request( + keys: impl Iterator, cf: Option, ) -> kvrpcpb::RawBatchDeleteRequest { - requests::new_raw_batch_delete_request(keys.map(Into::into).collect(), cf) + requests::new_raw_batch_delete_request::(keys.map(Into::into).collect(), cf) } -pub fn new_raw_delete_range_request( +pub fn new_raw_delete_range_request( range: BoundRange, cf: Option, ) -> kvrpcpb::RawDeleteRangeRequest { let (start_key, end_key) = range.into_keys(); - requests::new_raw_delete_range_request(start_key.into(), end_key.unwrap_or_default().into(), cf) + requests::new_raw_delete_range_request::(start_key.into(), end_key.unwrap_or_default().into(), cf) } -pub fn new_raw_scan_request( +pub fn new_raw_scan_request( range: BoundRange, limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawScanRequest { +) -> kvrpcpb::RawScanRequest { let (start_key, end_key) = range.into_keys(); - requests::new_raw_scan_request( + requests::new_raw_scan_request::( start_key.into(), end_key.unwrap_or_default().into(), limit, @@ -77,31 +80,31 @@ pub fn new_raw_scan_request( ) } -pub fn new_raw_batch_scan_request( - ranges: impl Iterator, +pub fn new_raw_batch_scan_request( + ranges: impl Iterator, each_limit: u32, key_only: bool, cf: Option, ) -> kvrpcpb::RawBatchScanRequest { - requests::new_raw_batch_scan_request(ranges.map(Into::into).collect(), each_limit, key_only, cf) + requests::new_raw_batch_scan_request::(ranges.map(Into::into).collect(), each_limit, key_only, cf) } -pub fn new_cas_request( +pub fn new_cas_request( key: Key, value: Value, previous_value: Option, cf: Option, ) -> kvrpcpb::RawCasRequest { - requests::new_cas_request(key.into(), value, previous_value, cf) + requests::new_cas_request::(key.into(), value, previous_value, cf) } -pub fn new_raw_coprocessor_request( +pub fn new_raw_coprocessor_request( copr_name: String, copr_version_req: String, - ranges: impl Iterator, + ranges: impl Iterator, request_builder: impl Fn(metapb::Region, Vec>) -> Vec + Send + Sync + 'static, ) -> requests::RawCoprocessorRequest { - requests::new_raw_coprocessor_request( + requests::new_raw_coprocessor_request::( copr_name, copr_version_req, ranges.map(Into::into).collect(), diff --git a/src/raw/requests.rs b/src/raw/requests.rs index bd678aaf..5b0fa52e 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -1,6 +1,7 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use std::{any::Any, ops::Range, sync::Arc}; +use std::borrow::Cow; use async_trait::async_trait; use futures::stream::BoxStream; @@ -21,8 +22,9 @@ use crate::{ util::iter::FlatMapOkIterExt, ColumnFamily, Key, KvPair, Result, Value, }; +use crate::request::request_codec::{RawApiV1, RequestCodec}; -pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::RawGetRequest { +pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::RawGetRequest where kvrpcpb::RawGetRequest: KvRequest { let mut req = kvrpcpb::RawGetRequest::default(); req.set_key(key); req.maybe_set_cf(cf); @@ -30,8 +32,16 @@ pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::R req } -impl KvRequest for kvrpcpb::RawGetRequest { +impl KvRequest for kvrpcpb::RawGetRequest { type Response = kvrpcpb::RawGetResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_key!(kvrpcpb::RawGetRequest); @@ -56,10 +66,10 @@ impl Process for DefaultProcessor { } } -pub fn new_raw_batch_get_request( +pub fn new_raw_batch_get_request( keys: Vec>, cf: Option, -) -> kvrpcpb::RawBatchGetRequest { +) -> kvrpcpb::RawBatchGetRequest where kvrpcpb::RawBatchGetRequest: KvRequest{ let mut req = kvrpcpb::RawBatchGetRequest::default(); req.set_keys(keys); req.maybe_set_cf(cf); @@ -67,8 +77,16 @@ pub fn new_raw_batch_get_request( req } -impl KvRequest for kvrpcpb::RawBatchGetRequest { +impl KvRequest for kvrpcpb::RawBatchGetRequest { type Response = kvrpcpb::RawBatchGetResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::RawBatchGetRequest); @@ -84,12 +102,12 @@ impl Merge for Collect { } } -pub fn new_raw_put_request( +pub fn new_raw_put_request( key: Vec, value: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawPutRequest { +) -> kvrpcpb::RawPutRequest where kvrpcpb::RawPutRequest: KvRequest { let mut req = kvrpcpb::RawPutRequest::default(); req.set_key(key); req.set_value(value); @@ -99,8 +117,16 @@ pub fn new_raw_put_request( req } -impl KvRequest for kvrpcpb::RawPutRequest { +impl KvRequest for kvrpcpb::RawPutRequest { type Response = kvrpcpb::RawPutResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_key!(kvrpcpb::RawPutRequest); @@ -111,11 +137,11 @@ impl SingleKey for kvrpcpb::RawPutRequest { } } -pub fn new_raw_batch_put_request( +pub fn new_raw_batch_put_request( pairs: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawBatchPutRequest { +) -> kvrpcpb::RawBatchPutRequest where kvrpcpb::RawBatchPutRequest: KvRequest { let mut req = kvrpcpb::RawBatchPutRequest::default(); req.set_pairs(pairs); req.maybe_set_cf(cf); @@ -124,8 +150,16 @@ pub fn new_raw_batch_put_request( req } -impl KvRequest for kvrpcpb::RawBatchPutRequest { +impl KvRequest for kvrpcpb::RawBatchPutRequest { type Response = kvrpcpb::RawBatchPutResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::RawBatchPutRequest { @@ -150,11 +184,11 @@ impl Shardable for kvrpcpb::RawBatchPutRequest { } } -pub fn new_raw_delete_request( +pub fn new_raw_delete_request( key: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawDeleteRequest { +) -> kvrpcpb::RawDeleteRequest where kvrpcpb::RawDeleteRequest: KvRequest { let mut req = kvrpcpb::RawDeleteRequest::default(); req.set_key(key); req.maybe_set_cf(cf); @@ -163,8 +197,16 @@ pub fn new_raw_delete_request( req } -impl KvRequest for kvrpcpb::RawDeleteRequest { +impl KvRequest for kvrpcpb::RawDeleteRequest { type Response = kvrpcpb::RawDeleteResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_key!(kvrpcpb::RawDeleteRequest); @@ -175,10 +217,10 @@ impl SingleKey for kvrpcpb::RawDeleteRequest { } } -pub fn new_raw_batch_delete_request( +pub fn new_raw_batch_delete_request( keys: Vec>, cf: Option, -) -> kvrpcpb::RawBatchDeleteRequest { +) -> kvrpcpb::RawBatchDeleteRequest where kvrpcpb::RawBatchDeleteRequest: KvRequest { let mut req = kvrpcpb::RawBatchDeleteRequest::default(); req.set_keys(keys); req.maybe_set_cf(cf); @@ -186,17 +228,25 @@ pub fn new_raw_batch_delete_request( req } -impl KvRequest for kvrpcpb::RawBatchDeleteRequest { +impl KvRequest for kvrpcpb::RawBatchDeleteRequest { type Response = kvrpcpb::RawBatchDeleteResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::RawBatchDeleteRequest); -pub fn new_raw_delete_range_request( +pub fn new_raw_delete_range_request( start_key: Vec, end_key: Vec, cf: Option, -) -> kvrpcpb::RawDeleteRangeRequest { +) -> kvrpcpb::RawDeleteRangeRequest where kvrpcpb::RawDeleteRangeRequest: KvRequest { let mut req = kvrpcpb::RawDeleteRangeRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -205,19 +255,27 @@ pub fn new_raw_delete_range_request( req } -impl KvRequest for kvrpcpb::RawDeleteRangeRequest { +impl KvRequest for kvrpcpb::RawDeleteRangeRequest { type Response = kvrpcpb::RawDeleteRangeResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_range!(kvrpcpb::RawDeleteRangeRequest); -pub fn new_raw_scan_request( +pub fn new_raw_scan_request( start_key: Vec, end_key: Vec, limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawScanRequest { +) -> kvrpcpb::RawScanRequest where kvrpcpb::RawScanRequest: KvRequest { let mut req = kvrpcpb::RawScanRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -228,8 +286,16 @@ pub fn new_raw_scan_request( req } -impl KvRequest for kvrpcpb::RawScanRequest { +impl KvRequest for kvrpcpb::RawScanRequest { type Response = kvrpcpb::RawScanResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_range!(kvrpcpb::RawScanRequest); @@ -245,12 +311,12 @@ impl Merge for Collect { } } -pub fn new_raw_batch_scan_request( +pub fn new_raw_batch_scan_request( ranges: Vec, each_limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawBatchScanRequest { +) -> kvrpcpb::RawBatchScanRequest where kvrpcpb::RawBatchScanRequest: KvRequest { let mut req = kvrpcpb::RawBatchScanRequest::default(); req.set_ranges(ranges); req.set_each_limit(each_limit); @@ -260,8 +326,16 @@ pub fn new_raw_batch_scan_request( req } -impl KvRequest for kvrpcpb::RawBatchScanRequest { +impl KvRequest for kvrpcpb::RawBatchScanRequest { type Response = kvrpcpb::RawBatchScanResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::RawBatchScanRequest { @@ -292,12 +366,12 @@ impl Merge for Collect { } } -pub fn new_cas_request( +pub fn new_cas_request( key: Vec, value: Vec, previous_value: Option>, cf: Option, -) -> kvrpcpb::RawCasRequest { +) -> kvrpcpb::RawCasRequest where kvrpcpb::RawCasRequest: KvRequest { let mut req = kvrpcpb::RawCasRequest::default(); req.set_key(key); req.set_value(value); @@ -309,8 +383,16 @@ pub fn new_cas_request( req } -impl KvRequest for kvrpcpb::RawCasRequest { +impl KvRequest for kvrpcpb::RawCasRequest { type Response = kvrpcpb::RawCasResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_key!(kvrpcpb::RawCasRequest); @@ -337,12 +419,12 @@ impl Process for DefaultProcessor { type RawCoprocessorRequestDataBuilder = Arc) -> Vec + Send + Sync>; -pub fn new_raw_coprocessor_request( +pub fn new_raw_coprocessor_request( copr_name: String, copr_version_req: String, ranges: Vec, data_builder: RawCoprocessorRequestDataBuilder, -) -> RawCoprocessorRequest { +) -> RawCoprocessorRequest where RawCoprocessorRequest: KvRequest { let mut inner = kvrpcpb::RawCoprocessorRequest::default(); inner.set_copr_name(copr_name); inner.set_copr_version_req(copr_version_req); @@ -378,8 +460,16 @@ impl Request for RawCoprocessorRequest { } } -impl KvRequest for RawCoprocessorRequest { +impl KvRequest for RawCoprocessorRequest { type Response = kvrpcpb::RawCoprocessorResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for RawCoprocessorRequest { diff --git a/src/request/mod.rs b/src/request/mod.rs index 959ff5e7..f18f9eb2 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -1,12 +1,17 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. +use std::borrow::Cow; + +use async_trait::async_trait; +use derive_new::new; + +use tikv_client_store::{HasKeyErrors, HasRegionError, Request}; + use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF, PESSIMISTIC_BACKOFF}, transaction::HasLocks, }; -use async_trait::async_trait; -use derive_new::new; -use tikv_client_store::{HasKeyErrors, Request}; +use crate::pd::PdClient; pub use self::{ plan::{ @@ -22,12 +27,15 @@ pub mod plan; mod plan_builder; #[macro_use] mod shard; +pub mod request_codec; /// Abstracts any request sent to a TiKV server. #[async_trait] -pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { +pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { /// The expected response to the request. - type Response: HasKeyErrors + HasLocks + Clone + Send + 'static; + type Response: HasKeyErrors + HasLocks + HasRegionError + Clone + Send + 'static; + fn encode_request(&self, _codec: &C) -> Cow; + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> crate::Result; } #[derive(Clone, Debug, new, Eq, PartialEq)] @@ -63,22 +71,26 @@ impl RetryOptions { #[cfg(test)] mod test { - use super::*; - use crate::{ - mock::{MockKvClient, MockPdClient}, - store::store_stream_for_keys, - transaction::lowering::new_commit_request, - Error, Key, Result, - }; - use grpcio::CallOption; use std::{ any::Any, iter, - sync::{atomic::AtomicUsize, Arc}, + sync::{Arc, atomic::AtomicUsize}, }; + + use grpcio::CallOption; + use tikv_client_proto::{kvrpcpb, pdpb::Timestamp, tikvpb::TikvClient}; use tikv_client_store::HasRegionError; + use crate::{ + Error, + Key, + mock::{MockKvClient, MockPdClient}, + Result, store::store_stream_for_keys, transaction::lowering::new_commit_request, + }; + + use super::*; + #[tokio::test] async fn test_region_retry() { #[derive(Clone)] diff --git a/src/request/plan.rs b/src/request/plan.rs index ce785262..e0941702 100644 --- a/src/request/plan.rs +++ b/src/request/plan.rs @@ -5,20 +5,22 @@ use std::{marker::PhantomData, sync::Arc}; use async_recursion::async_recursion; use async_trait::async_trait; use futures::{future::try_join_all, prelude::*}; +use tokio::sync::Semaphore; + use tikv_client_proto::{errorpb, errorpb::EpochNotMatch, kvrpcpb}; use tikv_client_store::{HasKeyErrors, HasRegionError, HasRegionErrors, KvClient}; -use tokio::sync::Semaphore; use crate::{ backoff::Backoff, + Error, pd::PdClient, request::{KvRequest, Shardable}, + Result, stats::tikv_stats, store::RegionStore, - transaction::{resolve_locks, HasLocks}, - util::iter::FlatMapOkIterExt, - Error, Result, + transaction::{HasLocks, resolve_locks}, util::iter::FlatMapOkIterExt, }; +use crate::request::request_codec::RequestCodec; /// A plan for how to execute a request. A user builds up a plan with various /// options, then exectutes it. @@ -33,27 +35,39 @@ pub trait Plan: Sized + Clone + Sync + Send + 'static { /// The simplest plan which just dispatches a request to a specific kv server. #[derive(Clone)] -pub struct Dispatch { +pub struct Dispatch> { pub request: Req, pub kv_client: Option>, + codec: C, +} + +impl> Dispatch { + pub fn new(request: Req, kv_client: Option>, codec: C) -> Self { + Self { + request, + kv_client, + codec, + } + } } #[async_trait] -impl Plan for Dispatch { +impl> Plan for Dispatch { type Result = Req::Response; async fn execute(&self) -> Result { + let req = self.request.encode_request(&self.codec); let stats = tikv_stats(self.request.label()); let result = self .kv_client .as_ref() .expect("Unreachable: kv_client has not been initialised in Dispatch") - .dispatch(&self.request) + .dispatch(req.as_ref()) .await; let result = stats.done(result); - result.map(|r| { - *r.downcast() - .expect("Downcast failed: request and response type mismatch") + result.and_then(|r| { + req.decode_response(&self.codec, *r.downcast() + .expect("Downcast failed: request and response type mismatch")) }) } } @@ -72,8 +86,8 @@ pub struct RetryableMultiRegion { } impl RetryableMultiRegion -where - P::Result: HasKeyErrors + HasRegionError, + where + P::Result: HasKeyErrors + HasRegionError, { // A plan may involve multiple shards #[async_recursion] @@ -153,7 +167,7 @@ where permits, preserve_region_results, ) - .await + .await } None => Err(Error::RegionError(e)), } @@ -205,7 +219,7 @@ where region_store, e.take_epoch_not_match(), ) - .await + .await } else if e.has_stale_command() || e.has_region_not_found() { pd_client.invalidate_region_cache(ver_id).await; Ok(false) @@ -277,8 +291,8 @@ impl Clone for RetryableMultiRegion { #[async_trait] impl Plan for RetryableMultiRegion -where - P::Result: HasKeyErrors + HasRegionError, + where + P::Result: HasKeyErrors + HasRegionError, { type Result = Vec>; @@ -294,7 +308,7 @@ where concurrency_permits.clone(), self.preserve_region_results, ) - .await + .await } } @@ -313,8 +327,8 @@ pub struct MergeResponse> { } #[async_trait] -impl>>, M: Merge> Plan - for MergeResponse +impl>>, M: Merge> Plan +for MergeResponse { type Result = M::Out; @@ -408,8 +422,8 @@ impl Clone for ResolveLock { #[async_trait] impl Plan for ResolveLock -where - P::Result: HasLocks, + where + P::Result: HasLocks, { type Result = P::Result; @@ -464,8 +478,8 @@ impl Clone for ExtractError

{ #[async_trait] impl Plan for ExtractError

-where - P::Result: HasKeyErrors + HasRegionErrors, + where + P::Result: HasKeyErrors + HasRegionErrors, { type Result = P::Result; @@ -504,8 +518,8 @@ impl Clone for PreserveShard

{ #[async_trait] impl

Plan for PreserveShard

-where - P: Plan + Shardable, + where + P: Plan + Shardable, { type Result = ResponseWithShard; @@ -544,11 +558,14 @@ impl HasRegionError for ResponseWithShard { @@ -25,19 +29,24 @@ pub struct PlanBuilder { /// Used to ensure that a plan has a designated target or targets, a target is /// a particular TiKV server. pub trait PlanBuilderPhase {} + pub struct NoTarget; + impl PlanBuilderPhase for NoTarget {} + pub struct Targetted; + impl PlanBuilderPhase for Targetted {} -impl PlanBuilder, NoTarget> { +impl PlanBuilder, NoTarget> where + C: RequestCodec, + Req: KvRequest, + PdC: PdClient { pub fn new(pd_client: Arc, request: Req) -> Self { + let codec = pd_client.get_request_codec().clone(); PlanBuilder { pd_client, - plan: Dispatch { - request, - kv_client: None, - }, + plan: Dispatch::new(request, None, codec), phantom: PhantomData, } } @@ -54,8 +63,8 @@ impl PlanBuilder { impl PlanBuilder { /// If there is a lock error, then resolve the lock and retry the request. pub fn resolve_lock(self, backoff: Backoff) -> PlanBuilder, Ph> - where - P::Result: HasLocks, + where + P::Result: HasLocks, { PlanBuilder { pd_client: self.pd_client.clone(), @@ -71,9 +80,9 @@ impl PlanBuilder { /// Merge the results of a request. Usually used where a request is sent to multiple regions /// to combine the responses from each region. pub fn merge>(self, merge: M) -> PlanBuilder, Ph> - where - In: Clone + Send + Sync + 'static, - P: Plan>>, + where + In: Clone + Send + Sync + 'static, + P: Plan>>, { PlanBuilder { pd_client: self.pd_client.clone(), @@ -90,9 +99,9 @@ impl PlanBuilder { /// to a single region because post-porcessing can be incorporated in the merge step for /// multi-region requests). pub fn post_process_default(self) -> PlanBuilder, Ph> - where - P: Plan, - DefaultProcessor: Process, + where + P: Plan, + DefaultProcessor: Process, { PlanBuilder { pd_client: self.pd_client.clone(), @@ -106,8 +115,8 @@ impl PlanBuilder { } impl PlanBuilder -where - P::Result: HasKeyErrors + HasRegionError, + where + P::Result: HasKeyErrors + HasRegionError, { /// Split the request into shards sending a request to the region of each shard. pub fn retry_multi_region( @@ -144,11 +153,11 @@ where } } -impl PlanBuilder, NoTarget> { +impl + SingleKey> PlanBuilder, NoTarget> { /// Target the request at a single region. *Note*: single region plan will /// cannot automatically retry on region errors. It's only used for requests /// that target at a specific region but not keys (e.g. ResolveLockRequest). - pub async fn single_region(self) -> Result, Targetted>> { + pub async fn single_region(self) -> Result, Targetted>> { let key = self.plan.request.key(); // TODO: retry when region error occurred let store = self.pd_client.clone().store_for_key(key.into()).await?; @@ -156,19 +165,19 @@ impl PlanBuilder, NoTa } } -impl PlanBuilder, NoTarget> { +impl> PlanBuilder, NoTarget> { /// Target the request at a single region; caller supplies the store to target. pub async fn single_region_with_store( self, store: RegionStore, - ) -> Result, Targetted>> { + ) -> Result, Targetted>> { set_single_region_store(self.plan, store, self.pd_client) } } impl PlanBuilder -where - P::Result: HasKeyErrors, + where + P::Result: HasKeyErrors, { pub fn preserve_shard(self) -> PlanBuilder, NoTarget> { PlanBuilder { @@ -183,8 +192,8 @@ where } impl PlanBuilder -where - P::Result: HasKeyErrors + HasRegionErrors, + where + P::Result: HasKeyErrors + HasRegionErrors, { pub fn extract_error(self) -> PlanBuilder, Targetted> { PlanBuilder { @@ -195,11 +204,11 @@ where } } -fn set_single_region_store( - mut plan: Dispatch, +fn set_single_region_store>( + mut plan: Dispatch, store: RegionStore, pd_client: Arc, -) -> Result, Targetted>> { +) -> Result, Targetted>> { plan.request .set_context(store.region_with_leader.context()?); plan.kv_client = Some(store.client); diff --git a/src/request/request_codec.rs b/src/request/request_codec.rs new file mode 100644 index 00000000..a90922fa --- /dev/null +++ b/src/request/request_codec.rs @@ -0,0 +1,22 @@ +use tikv_client_proto::metapb::Region; + +use crate::Result; + +pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { + fn encode_key(&self, key: Vec) -> Vec { key } + fn decode_key(&self, key: Vec) -> Result> { Ok(key) } + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { (start, end) } + fn encode_pd_query(&self, key: Vec) -> Vec { key } + fn decode_region(&self, region: Region) -> Result { Ok(region) } +} + +#[derive(Clone)] +pub struct RawApiV1; + +impl RequestCodec for RawApiV1 {} + + +#[derive(Clone)] +pub struct TxnApiV1; + +impl RequestCodec for TxnApiV1 {} \ No newline at end of file diff --git a/src/request/shard.rs b/src/request/shard.rs index cdf3f198..bbe48de2 100644 --- a/src/request/shard.rs +++ b/src/request/shard.rs @@ -38,7 +38,7 @@ pub trait Shardable { fn apply_shard(&mut self, shard: Self::Shard, store: &RegionStore) -> Result<()>; } -impl Shardable for Dispatch { +impl + Shardable> Shardable for Dispatch { type Shard = Req::Shard; fn shards( diff --git a/src/transaction/client.rs b/src/transaction/client.rs index fee8e251..a65fd2a0 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -1,18 +1,24 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use super::{requests::new_scan_lock_request, resolve_locks}; +use std::{mem, sync::Arc}; +use std::marker::PhantomData; + +use slog::{Drain, Logger}; + +use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; + use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, pd::{PdClient, PdRpcClient}, request::Plan, + Result, timestamp::TimestampExt, transaction::{Snapshot, Transaction, TransactionOptions}, - Result, }; -use slog::{Drain, Logger}; -use std::{mem, sync::Arc}; -use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; +use crate::request::request_codec::RequestCodec; + +use super::{requests::new_scan_lock_request, resolve_locks}; // FIXME: cargo-culted value const SCAN_LOCK_BATCH_SIZE: u32 = 1024; @@ -33,12 +39,16 @@ const SCAN_LOCK_BATCH_SIZE: u32 = 1024; /// /// The returned results of transactional requests are [`Future`](std::future::Future)s that must be /// awaited to execute. -pub struct Client { - pd: Arc, +pub struct Client { + pd: Arc>, logger: Logger, + _phantom: PhantomData, } -impl Client { +impl Client + where + C: RequestCodec, +{ /// Create a transactional [`Client`] and connect to the TiKV cluster. /// /// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for @@ -59,7 +69,7 @@ impl Client { pub async fn new>( pd_endpoints: Vec, logger: Option, - ) -> Result { + ) -> Result> { // debug!(self.logger, "creating transactional client"); Self::new_with_config(pd_endpoints, Config::default(), logger).await } @@ -90,7 +100,7 @@ impl Client { pd_endpoints: Vec, config: Config, optional_logger: Option, - ) -> Result { + ) -> Result> { let logger = optional_logger.unwrap_or_else(|| { let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); Logger::root( @@ -104,7 +114,7 @@ impl Client { debug!(logger, "creating new transactional client"); let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); let pd = Arc::new(PdRpcClient::connect(&pd_endpoints, config, true, logger.clone()).await?); - Ok(Client { pd, logger }) + Ok(Client { pd, logger, _phantom: PhantomData }) } /// Creates a new optimistic [`Transaction`]. @@ -129,7 +139,7 @@ impl Client { /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_optimistic(&self) -> Result { + pub async fn begin_optimistic(&self) -> Result>> { debug!(self.logger, "creating new optimistic transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, TransactionOptions::new_optimistic())) @@ -154,7 +164,7 @@ impl Client { /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_pessimistic(&self) -> Result { + pub async fn begin_pessimistic(&self) -> Result>> { debug!(self.logger, "creating new pessimistic transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, TransactionOptions::new_pessimistic())) @@ -179,14 +189,14 @@ impl Client { /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_with_options(&self, options: TransactionOptions) -> Result { + pub async fn begin_with_options(&self, options: TransactionOptions) -> Result>> { debug!(self.logger, "creating new customized transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, options)) } /// Create a new [`Snapshot`](Snapshot) at the given [`Timestamp`](Timestamp). - pub fn snapshot(&self, timestamp: Timestamp, options: TransactionOptions) -> Snapshot { + pub fn snapshot(&self, timestamp: Timestamp, options: TransactionOptions) -> Snapshot> { debug!(self.logger, "creating new snapshot"); let logger = self.logger.new(o!("child" => 1)); Snapshot::new(self.new_transaction(timestamp, options.read_only()), logger) @@ -230,7 +240,7 @@ impl Client { let mut locks: Vec = vec![]; let mut start_key = vec![]; loop { - let req = new_scan_lock_request( + let req = new_scan_lock_request::( mem::take(&mut start_key), safepoint.version(), SCAN_LOCK_BATCH_SIZE, @@ -267,7 +277,7 @@ impl Client { Ok(res) } - fn new_transaction(&self, timestamp: Timestamp, options: TransactionOptions) -> Transaction { + fn new_transaction(&self, timestamp: Timestamp, options: TransactionOptions) -> Transaction> { let logger = self.logger.new(o!("child" => 1)); Transaction::new(timestamp, self.pd.clone(), options, logger) } diff --git a/src/transaction/lock.rs b/src/transaction/lock.rs index 871effc6..01a07db9 100644 --- a/src/transaction/lock.rs +++ b/src/transaction/lock.rs @@ -15,6 +15,7 @@ use std::{ sync::Arc, }; use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; +use crate::request::request_codec::RequestCodec; const RESOLVE_LOCK_RETRY_LIMIT: usize = 10; @@ -25,9 +26,9 @@ const RESOLVE_LOCK_RETRY_LIMIT: usize = 10; /// the key. We first use `CleanupRequest` to let the status of the primary lock converge and get /// its status (committed or rolled back). Then, we use the status of its primary lock to determine /// the status of the other keys in the same transaction. -pub async fn resolve_locks( +pub async fn resolve_locks( locks: Vec, - pd_client: Arc, + pd_client: Arc, ) -> Result { debug!("resolving locks"); let ts = pd_client.clone().get_timestamp().await?; @@ -61,7 +62,7 @@ pub async fn resolve_locks( let commit_version = match commit_versions.get(&lock.lock_version) { Some(&commit_version) => commit_version, None => { - let request = requests::new_cleanup_request(lock.primary_lock, lock.lock_version); + let request = requests::new_cleanup_request::(lock.primary_lock, lock.lock_version); let plan = crate::request::PlanBuilder::new(pd_client.clone(), request) .resolve_lock(OPTIMISTIC_BACKOFF) .retry_multi_region(DEFAULT_REGION_BACKOFF) @@ -89,11 +90,11 @@ pub async fn resolve_locks( Ok(!has_live_locks) } -async fn resolve_lock_with_retry( +async fn resolve_lock_with_retry( #[allow(clippy::ptr_arg)] key: &Vec, start_version: u64, commit_version: u64, - pd_client: Arc, + pd_client: Arc, ) -> Result { debug!("resolving locks with retry"); // FIXME: Add backoff @@ -102,7 +103,7 @@ async fn resolve_lock_with_retry( debug!("resolving locks: attempt {}", (i + 1)); let store = pd_client.clone().store_for_key(key.into()).await?; let ver_id = store.region_with_leader.ver_id(); - let request = requests::new_resolve_lock_request(start_version, commit_version); + let request = requests::new_resolve_lock_request::(start_version, commit_version); // The only place where single-region is used let plan = crate::request::PlanBuilder::new(pd_client.clone(), request) .single_region_with_store(store) diff --git a/src/transaction/lowering.rs b/src/transaction/lowering.rs index 413c6bf8..4477de46 100644 --- a/src/transaction/lowering.rs +++ b/src/transaction/lowering.rs @@ -6,26 +6,27 @@ use crate::{timestamp::TimestampExt, transaction::requests, BoundRange, Key}; use std::iter::Iterator; use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; +use crate::request::request_codec::RequestCodec; -pub fn new_get_request(key: Key, timestamp: Timestamp) -> kvrpcpb::GetRequest { - requests::new_get_request(key.into(), timestamp.version()) +pub fn new_get_request(key: Key, timestamp: Timestamp) -> kvrpcpb::GetRequest { + requests::new_get_request::(key.into(), timestamp.version()) } -pub fn new_batch_get_request( +pub fn new_batch_get_request( keys: impl Iterator, timestamp: Timestamp, ) -> kvrpcpb::BatchGetRequest { - requests::new_batch_get_request(keys.map(Into::into).collect(), timestamp.version()) + requests::new_batch_get_request::(keys.map(Into::into).collect(), timestamp.version()) } -pub fn new_scan_request( +pub fn new_scan_request( range: BoundRange, timestamp: Timestamp, limit: u32, key_only: bool, ) -> kvrpcpb::ScanRequest { let (start_key, end_key) = range.into_keys(); - requests::new_scan_request( + requests::new_scan_request::( start_key.into(), end_key.unwrap_or_default().into(), timestamp.version(), @@ -34,24 +35,24 @@ pub fn new_scan_request( ) } -pub fn new_resolve_lock_request( +pub fn new_resolve_lock_request( start_version: Timestamp, commit_version: Timestamp, ) -> kvrpcpb::ResolveLockRequest { - requests::new_resolve_lock_request(start_version.version(), commit_version.version()) + requests::new_resolve_lock_request::(start_version.version(), commit_version.version()) } -pub fn new_cleanup_request(key: Key, start_version: Timestamp) -> kvrpcpb::CleanupRequest { - requests::new_cleanup_request(key.into(), start_version.version()) +pub fn new_cleanup_request(key: Key, start_version: Timestamp) -> kvrpcpb::CleanupRequest { + requests::new_cleanup_request::(key.into(), start_version.version()) } -pub fn new_prewrite_request( +pub fn new_prewrite_request( mutations: Vec, primary_lock: Key, start_version: Timestamp, lock_ttl: u64, ) -> kvrpcpb::PrewriteRequest { - requests::new_prewrite_request( + requests::new_prewrite_request::( mutations, primary_lock.into(), start_version.version(), @@ -59,14 +60,14 @@ pub fn new_prewrite_request( ) } -pub fn new_pessimistic_prewrite_request( +pub fn new_pessimistic_prewrite_request( mutations: Vec, primary_lock: Key, start_version: Timestamp, lock_ttl: u64, for_update_ts: Timestamp, ) -> kvrpcpb::PrewriteRequest { - requests::new_pessimistic_prewrite_request( + requests::new_pessimistic_prewrite_request::( mutations, primary_lock.into(), start_version.version(), @@ -75,31 +76,31 @@ pub fn new_pessimistic_prewrite_request( ) } -pub fn new_commit_request( +pub fn new_commit_request( keys: impl Iterator, start_version: Timestamp, commit_version: Timestamp, ) -> kvrpcpb::CommitRequest { - requests::new_commit_request( + requests::new_commit_request::( keys.map(Into::into).collect(), start_version.version(), commit_version.version(), ) } -pub fn new_batch_rollback_request( +pub fn new_batch_rollback_request( keys: impl Iterator, start_version: Timestamp, ) -> kvrpcpb::BatchRollbackRequest { - requests::new_batch_rollback_request(keys.map(Into::into).collect(), start_version.version()) + requests::new_batch_rollback_request::(keys.map(Into::into).collect(), start_version.version()) } -pub fn new_pessimistic_rollback_request( +pub fn new_pessimistic_rollback_request( keys: impl Iterator, start_version: Timestamp, for_update_ts: Timestamp, ) -> kvrpcpb::PessimisticRollbackRequest { - requests::new_pessimistic_rollback_request( + requests::new_pessimistic_rollback_request::( keys.map(Into::into).collect(), start_version.version(), for_update_ts.version(), @@ -132,7 +133,7 @@ impl PessimisticLock for (Key, kvrpcpb::Assertion) { } } -pub fn new_pessimistic_lock_request( +pub fn new_pessimistic_lock_request( locks: impl Iterator, primary_lock: Key, start_version: Timestamp, @@ -140,7 +141,7 @@ pub fn new_pessimistic_lock_request( for_update_ts: Timestamp, need_value: bool, ) -> kvrpcpb::PessimisticLockRequest { - requests::new_pessimistic_lock_request( + requests::new_pessimistic_lock_request::( locks .map(|pl| { let mut mutation = kvrpcpb::Mutation::default(); @@ -158,18 +159,18 @@ pub fn new_pessimistic_lock_request( ) } -pub fn new_scan_lock_request( +pub fn new_scan_lock_request( start_key: Key, safepoint: Timestamp, limit: u32, ) -> kvrpcpb::ScanLockRequest { - requests::new_scan_lock_request(start_key.into(), safepoint.version(), limit) + requests::new_scan_lock_request::(start_key.into(), safepoint.version(), limit) } -pub fn new_heart_beat_request( +pub fn new_heart_beat_request( start_ts: Timestamp, primary_lock: Key, ttl: u64, ) -> kvrpcpb::TxnHeartBeatRequest { - requests::new_heart_beat_request(start_ts.version(), primary_lock.into(), ttl) + requests::new_heart_beat_request::(start_ts.version(), primary_lock.into(), ttl) } diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index e1d05df3..3cd5440c 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -1,26 +1,31 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. +use std::{collections::HashMap, iter, sync::Arc}; +use std::borrow::Cow; + +use either::Either; +use futures::stream::BoxStream; + +use tikv_client_common::Error::PessimisticLockError; +use tikv_client_proto::{ + kvrpcpb::{self, TxnHeartBeatResponse}, + pdpb::Timestamp, +}; +use tikv_client_store::HasRegionErrors; use crate::{ collect_first, + Key, + KvPair, pd::PdClient, request::{ Collect, CollectSingle, CollectWithShard, DefaultProcessor, KvRequest, Merge, Process, ResponseWithShard, Shardable, SingleKey, }, - store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, - timestamp::TimestampExt, - transaction::HasLocks, - util::iter::FlatMapOkIterExt, - Key, KvPair, Result, Value, -}; -use either::Either; -use futures::stream::BoxStream; -use std::{collections::HashMap, iter, sync::Arc}; -use tikv_client_common::Error::PessimisticLockError; -use tikv_client_proto::{ - kvrpcpb::{self, TxnHeartBeatResponse}, - pdpb::Timestamp, + Result, + store::{RegionStore, store_stream_for_keys, store_stream_for_range_by_start_key}, + timestamp::TimestampExt, transaction::HasLocks, util::iter::FlatMapOkIterExt, Value, }; +use crate::request::request_codec::{RequestCodec, TxnApiV1}; // implement HasLocks for a response type that has a `pairs` field, // where locks can be extracted from both the `pairs` and `error` fields @@ -63,15 +68,25 @@ macro_rules! error_locks { }; } -pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest { +pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest + where kvrpcpb::GetRequest: KvRequest +{ let mut req = kvrpcpb::GetRequest::default(); req.set_key(key); req.set_version(timestamp); req } -impl KvRequest for kvrpcpb::GetRequest { +impl KvRequest for kvrpcpb::GetRequest { type Response = kvrpcpb::GetResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_key!(kvrpcpb::GetRequest); @@ -95,15 +110,25 @@ impl Process for DefaultProcessor { } } -pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::BatchGetRequest { +pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::BatchGetRequest + where kvrpcpb::BatchGetRequest: KvRequest +{ let mut req = kvrpcpb::BatchGetRequest::default(); req.set_keys(keys); req.set_version(timestamp); req } -impl KvRequest for kvrpcpb::BatchGetRequest { +impl KvRequest for kvrpcpb::BatchGetRequest { type Response = kvrpcpb::BatchGetResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::BatchGetRequest); @@ -119,13 +144,15 @@ impl Merge for Collect { } } -pub fn new_scan_request( +pub fn new_scan_request( start_key: Vec, end_key: Vec, timestamp: u64, limit: u32, key_only: bool, -) -> kvrpcpb::ScanRequest { +) -> kvrpcpb::ScanRequest + where kvrpcpb::ScanRequest: KvRequest +{ let mut req = kvrpcpb::ScanRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -135,8 +162,16 @@ pub fn new_scan_request( req } -impl KvRequest for kvrpcpb::ScanRequest { +impl KvRequest for kvrpcpb::ScanRequest { type Response = kvrpcpb::ScanResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_range!(kvrpcpb::ScanRequest); @@ -152,10 +187,12 @@ impl Merge for Collect { } } -pub fn new_resolve_lock_request( +pub fn new_resolve_lock_request( start_version: u64, commit_version: u64, -) -> kvrpcpb::ResolveLockRequest { +) -> kvrpcpb::ResolveLockRequest where + kvrpcpb::ResolveLockRequest: KvRequest, +{ let mut req = kvrpcpb::ResolveLockRequest::default(); req.set_start_version(start_version); req.set_commit_version(commit_version); @@ -167,11 +204,33 @@ pub fn new_resolve_lock_request( // region without keys. So it's not Shardable. And we don't automatically retry // on its region errors (in the Plan level). The region error must be manually // handled (in the upper level). -impl KvRequest for kvrpcpb::ResolveLockRequest { +impl KvRequest for kvrpcpb::ResolveLockRequest { type Response = kvrpcpb::ResolveLockResponse; + + fn encode_request(&self, _codec: &TxnApiV1) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &TxnApiV1, _resp: Self::Response) -> Result { + todo!() + } +} + +impl KvRequest for kvrpcpb::ResolveLockRequest { + default type Response = kvrpcpb::ResolveLockResponse; + + default fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + default fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } -pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest { +pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest + where kvrpcpb::CleanupRequest: KvRequest +{ let mut req = kvrpcpb::CleanupRequest::default(); req.set_key(key); req.set_start_version(start_version); @@ -179,8 +238,16 @@ pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::Cleanup req } -impl KvRequest for kvrpcpb::CleanupRequest { +impl KvRequest for kvrpcpb::CleanupRequest { type Response = kvrpcpb::CleanupResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_key!(kvrpcpb::CleanupRequest); @@ -199,12 +266,12 @@ impl Process for DefaultProcessor { } } -pub fn new_prewrite_request( +pub fn new_prewrite_request( mutations: Vec, primary_lock: Vec, start_version: u64, lock_ttl: u64, -) -> kvrpcpb::PrewriteRequest { +) -> kvrpcpb::PrewriteRequest where kvrpcpb::PrewriteRequest: KvRequest { let mut req = kvrpcpb::PrewriteRequest::default(); req.set_mutations(mutations); req.set_primary_lock(primary_lock); @@ -216,13 +283,13 @@ pub fn new_prewrite_request( req } -pub fn new_pessimistic_prewrite_request( +pub fn new_pessimistic_prewrite_request( mutations: Vec, primary_lock: Vec, start_version: u64, lock_ttl: u64, for_update_ts: u64, -) -> kvrpcpb::PrewriteRequest { +) -> kvrpcpb::PrewriteRequest where kvrpcpb::PrewriteRequest: KvRequest { let len = mutations.len(); let mut req = new_prewrite_request(mutations, primary_lock, start_version, lock_ttl); req.set_for_update_ts(for_update_ts); @@ -230,8 +297,16 @@ pub fn new_pessimistic_prewrite_request( req } -impl KvRequest for kvrpcpb::PrewriteRequest { +impl KvRequest for kvrpcpb::PrewriteRequest { type Response = kvrpcpb::PrewriteResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::PrewriteRequest { @@ -264,29 +339,37 @@ impl Shardable for kvrpcpb::PrewriteRequest { } } -pub fn new_commit_request( +pub fn new_commit_request( keys: Vec>, start_version: u64, commit_version: u64, -) -> kvrpcpb::CommitRequest { - let mut req = kvrpcpb::CommitRequest::default(); - req.set_keys(keys); - req.set_start_version(start_version); - req.set_commit_version(commit_version); +) -> kvrpcpb::CommitRequest where kvrpcpb::CommitRequest: KvRequest { +let mut req = kvrpcpb::CommitRequest::default(); +req.set_keys(keys); +req.set_start_version(start_version); +req.set_commit_version(commit_version); - req +req } -impl KvRequest for kvrpcpb::CommitRequest { +impl KvRequest for kvrpcpb::CommitRequest { type Response = kvrpcpb::CommitResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::CommitRequest); -pub fn new_batch_rollback_request( +pub fn new_batch_rollback_request( keys: Vec>, start_version: u64, -) -> kvrpcpb::BatchRollbackRequest { +) -> kvrpcpb::BatchRollbackRequest where kvrpcpb::BatchRollbackRequest: KvRequest { let mut req = kvrpcpb::BatchRollbackRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -294,17 +377,25 @@ pub fn new_batch_rollback_request( req } -impl KvRequest for kvrpcpb::BatchRollbackRequest { +impl KvRequest for kvrpcpb::BatchRollbackRequest { type Response = kvrpcpb::BatchRollbackResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::BatchRollbackRequest); -pub fn new_pessimistic_rollback_request( +pub fn new_pessimistic_rollback_request( keys: Vec>, start_version: u64, for_update_ts: u64, -) -> kvrpcpb::PessimisticRollbackRequest { +) -> kvrpcpb::PessimisticRollbackRequest where kvrpcpb::PessimisticRollbackRequest: KvRequest { let mut req = kvrpcpb::PessimisticRollbackRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -313,20 +404,28 @@ pub fn new_pessimistic_rollback_request( req } -impl KvRequest for kvrpcpb::PessimisticRollbackRequest { +impl KvRequest for kvrpcpb::PessimisticRollbackRequest { type Response = kvrpcpb::PessimisticRollbackResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::PessimisticRollbackRequest); -pub fn new_pessimistic_lock_request( +pub fn new_pessimistic_lock_request( mutations: Vec, primary_lock: Vec, start_version: u64, lock_ttl: u64, for_update_ts: u64, need_value: bool, -) -> kvrpcpb::PessimisticLockRequest { +) -> kvrpcpb::PessimisticLockRequest where kvrpcpb::PessimisticLockRequest: KvRequest { let mut req = kvrpcpb::PessimisticLockRequest::default(); req.set_mutations(mutations); req.set_primary_lock(primary_lock); @@ -344,8 +443,16 @@ pub fn new_pessimistic_lock_request( req } -impl KvRequest for kvrpcpb::PessimisticLockRequest { +impl KvRequest for kvrpcpb::PessimisticLockRequest { type Response = kvrpcpb::PessimisticLockResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::PessimisticLockRequest { @@ -370,7 +477,7 @@ impl Shardable for kvrpcpb::PessimisticLockRequest { // PessimisticLockResponse returns values that preserves the order with keys in request, thus the // kvpair result should be produced by zipping the keys in request and the values in respponse. impl Merge>> - for CollectWithShard +for CollectWithShard { type Out = Vec; @@ -430,11 +537,11 @@ impl Merge( start_key: Vec, safepoint: u64, limit: u32, -) -> kvrpcpb::ScanLockRequest { +) -> kvrpcpb::ScanLockRequest where kvrpcpb::ScanLockRequest: KvRequest { let mut req = kvrpcpb::ScanLockRequest::default(); req.set_start_key(start_key); req.set_max_version(safepoint); @@ -442,8 +549,16 @@ pub fn new_scan_lock_request( req } -impl KvRequest for kvrpcpb::ScanLockRequest { +impl KvRequest for kvrpcpb::ScanLockRequest { type Response = kvrpcpb::ScanLockResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::ScanLockRequest { @@ -474,11 +589,11 @@ impl Merge for Collect { } } -pub fn new_heart_beat_request( +pub fn new_heart_beat_request( start_ts: u64, primary_lock: Vec, ttl: u64, -) -> kvrpcpb::TxnHeartBeatRequest { +) -> kvrpcpb::TxnHeartBeatRequest where kvrpcpb::TxnHeartBeatRequest: KvRequest { let mut req = kvrpcpb::TxnHeartBeatRequest::default(); req.set_start_version(start_ts); req.set_primary_lock(primary_lock); @@ -486,8 +601,16 @@ pub fn new_heart_beat_request( req } -impl KvRequest for kvrpcpb::TxnHeartBeatRequest { +impl KvRequest for kvrpcpb::TxnHeartBeatRequest { type Response = kvrpcpb::TxnHeartBeatResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::TxnHeartBeatRequest { @@ -524,8 +647,16 @@ impl Process for DefaultProcessor { } } -impl KvRequest for kvrpcpb::CheckTxnStatusRequest { +impl KvRequest for kvrpcpb::CheckTxnStatusRequest { type Response = kvrpcpb::CheckTxnStatusResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } impl Shardable for kvrpcpb::CheckTxnStatusRequest { @@ -593,8 +724,16 @@ impl From<(u64, u64, Option)> for TransactionStatusKind { } } -impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { +impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { type Response = kvrpcpb::CheckSecondaryLocksResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + todo!() + } + + fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + todo!() + } } shardable_keys!(kvrpcpb::CheckSecondaryLocksRequest); @@ -644,6 +783,7 @@ error_locks!(kvrpcpb::CheckTxnStatusResponse); error_locks!(kvrpcpb::CheckSecondaryLocksResponse); impl HasLocks for kvrpcpb::CleanupResponse {} + impl HasLocks for kvrpcpb::ScanLockResponse {} impl HasLocks for kvrpcpb::PessimisticRollbackResponse { @@ -675,12 +815,13 @@ impl HasLocks for kvrpcpb::PrewriteResponse { #[cfg(test)] mod tests { + use tikv_client_common::Error::{PessimisticLockError, ResolveLockError}; + use tikv_client_proto::kvrpcpb; + use crate::{ - request::{plan::Merge, CollectWithShard, ResponseWithShard}, KvPair, + request::{CollectWithShard, plan::Merge, ResponseWithShard}, }; - use tikv_client_common::Error::{PessimisticLockError, ResolveLockError}; - use tikv_client_proto::kvrpcpb; #[tokio::test] async fn test_merge_pessimistic_lock_response() { diff --git a/src/transaction/snapshot.rs b/src/transaction/snapshot.rs index d08ad6da..08ba2981 100644 --- a/src/transaction/snapshot.rs +++ b/src/transaction/snapshot.rs @@ -5,6 +5,7 @@ use derive_new::new; use futures::stream::BoxStream; use slog::Logger; use std::ops::RangeBounds; +use crate::pd::PdClient; /// A read-only transaction which reads at the given timestamp. /// @@ -14,12 +15,12 @@ use std::ops::RangeBounds; /// /// See the [Transaction](struct@crate::Transaction) docs for more information on the methods. #[derive(new)] -pub struct Snapshot { - transaction: Transaction, +pub struct Snapshot { + transaction: Transaction, logger: Logger, } -impl Snapshot { +impl Snapshot { /// Get the value associated with the given key. pub async fn get(&mut self, key: impl Into) -> Result> { debug!(self.logger, "invoking get request on snapshot"); diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index f067f668..b3e4a9f0 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -1,23 +1,27 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use crate::{ - backoff::{Backoff, DEFAULT_REGION_BACKOFF}, - pd::{PdClient, PdRpcClient}, - request::{ - Collect, CollectError, CollectSingle, CollectWithShard, Plan, PlanBuilder, RetryOptions, - }, - timestamp::TimestampExt, - transaction::{buffer::Buffer, lowering::*}, - BoundRange, Error, Key, KvPair, Result, Value, -}; +use std::{iter, ops::RangeBounds, sync::Arc, time::Instant}; + use derive_new::new; use fail::fail_point; use futures::{prelude::*, stream::BoxStream}; use slog::Logger; -use std::{iter, ops::RangeBounds, sync::Arc, time::Instant}; -use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; use tokio::{sync::RwLock, time::Duration}; +use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; + +use crate::{ + backoff::{Backoff, DEFAULT_REGION_BACKOFF}, + BoundRange, + Error, + Key, + KvPair, + pd::{PdClient, PdRpcClient}, request::{ + Collect, CollectError, CollectSingle, CollectWithShard, Plan, PlanBuilder, RetryOptions, + }, Result, timestamp::TimestampExt, transaction::{buffer::Buffer, lowering::*}, Value, +}; +use crate::request::KvRequest; + /// An undo-able set of actions on the dataset. /// /// Create a transaction using a [`TransactionClient`](crate::TransactionClient), then run actions @@ -58,7 +62,7 @@ use tokio::{sync::RwLock, time::Duration}; /// txn.commit().await.unwrap(); /// # }); /// ``` -pub struct Transaction { +pub struct Transaction { status: Arc>, timestamp: Timestamp, buffer: Buffer, @@ -121,7 +125,7 @@ impl Transaction { self.buffer .get_or_else(key, |key| async move { - let request = new_get_request(key, timestamp); + let request = new_get_request::(key, timestamp); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(DEFAULT_REGION_BACKOFF) @@ -242,8 +246,8 @@ impl Transaction { /// ``` pub async fn batch_get( &mut self, - keys: impl IntoIterator>, - ) -> Result> { + keys: impl IntoIterator>, + ) -> Result> { debug!(self.logger, "invoking transactional batch_get request"); self.check_allow_operation().await?; let timestamp = self.timestamp.clone(); @@ -252,7 +256,7 @@ impl Transaction { self.buffer .batch_get_or_else(keys.into_iter().map(|k| k.into()), move |keys| async move { - let request = new_batch_get_request(keys, timestamp); + let request = new_batch_get_request::(keys, timestamp); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(retry_options.region_backoff) @@ -294,7 +298,7 @@ impl Transaction { /// ``` pub async fn batch_get_for_update( &mut self, - keys: impl IntoIterator>, + keys: impl IntoIterator>, ) -> Result> { debug!( self.logger, @@ -342,7 +346,7 @@ impl Transaction { &mut self, range: impl Into, limit: u32, - ) -> Result> { + ) -> Result> { debug!(self.logger, "invoking transactional scan request"); self.scan_inner(range, limit, false).await } @@ -378,7 +382,7 @@ impl Transaction { &mut self, range: impl Into, limit: u32, - ) -> Result> { + ) -> Result> { debug!(self.logger, "invoking transactional scan_keys request"); Ok(self .scan_inner(range, limit, true) @@ -453,7 +457,7 @@ impl Transaction { iter::once((key.clone(), kvrpcpb::Assertion::NotExist)), false, ) - .await?; + .await?; } self.buffer.insert(key, value.into()); Ok(()) @@ -513,7 +517,7 @@ impl Transaction { /// ``` pub async fn lock_keys( &mut self, - keys: impl IntoIterator>, + keys: impl IntoIterator>, ) -> Result<()> { debug!(self.logger, "invoking transactional lock_keys request"); self.check_allow_operation().await?; @@ -578,8 +582,8 @@ impl Transaction { self.start_instant, self.logger.new(o!("child" => 1)), ) - .commit() - .await; + .commit() + .await; if res.is_ok() { let mut status = self.status.write().await; @@ -635,8 +639,8 @@ impl Transaction { self.start_instant, self.logger.new(o!("child" => 1)), ) - .rollback() - .await; + .rollback() + .await; if res.is_ok() { let mut status = self.status.write().await; @@ -661,7 +665,7 @@ impl Transaction { Some(k) => k, None => return Err(Error::NoPrimaryKey), }; - let request = new_heart_beat_request( + let request = new_heart_beat_request::( self.timestamp.clone(), primary_key, self.start_instant.elapsed().as_millis() as u64 + MAX_TTL, @@ -680,7 +684,7 @@ impl Transaction { range: impl Into, limit: u32, key_only: bool, - ) -> Result> { + ) -> Result> { self.check_allow_operation().await?; let timestamp = self.timestamp.clone(); let rpc = self.rpc.clone(); @@ -692,7 +696,7 @@ impl Transaction { limit, !key_only, move |new_range, new_limit| async move { - let request = new_scan_request(new_range, timestamp, new_limit, key_only); + let request = new_scan_request::(new_range, timestamp, new_limit, key_only); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(retry_options.region_backoff) @@ -717,7 +721,7 @@ impl Transaction { /// Only valid for pessimistic transactions, panics if called on an optimistic transaction. async fn pessimistic_lock( &mut self, - keys: impl IntoIterator, + keys: impl IntoIterator, need_value: bool, ) -> Result> { debug!(self.logger, "acquiring pessimistic lock"); @@ -740,7 +744,7 @@ impl Transaction { .unwrap_or_else(|| first_key.clone()); let for_update_ts = self.rpc.clone().get_timestamp().await?; self.options.push_for_update_ts(for_update_ts.clone()); - let request = new_pessimistic_lock_request( + let request = new_pessimistic_lock_request::( keys.clone().into_iter(), primary_lock, self.timestamp.clone(), @@ -786,7 +790,7 @@ impl Transaction { /// Rollback pessimistic lock async fn pessimistic_lock_rollback( &mut self, - keys: impl Iterator, + keys: impl Iterator, start_version: Timestamp, for_update_ts: Timestamp, ) -> Result<()> { @@ -797,7 +801,7 @@ impl Transaction { return Ok(()); } - let req = new_pessimistic_rollback_request( + let req = new_pessimistic_rollback_request::( keys.clone().into_iter(), start_version, for_update_ts, @@ -867,7 +871,7 @@ impl Transaction { break; } } - let request = new_heart_beat_request( + let request = new_heart_beat_request::( start_ts.clone(), primary_key.clone(), start_instant.elapsed().as_millis() as u64 + MAX_TTL, @@ -1099,7 +1103,7 @@ impl HeartbeatOption { /// The committer implements `prewrite`, `commit` and `rollback` functions. #[allow(clippy::too_many_arguments)] #[derive(new)] -struct Committer { +struct Committer { primary_key: Option, mutations: Vec, start_version: Timestamp, @@ -1154,13 +1158,13 @@ impl Committer { let elapsed = self.start_instant.elapsed().as_millis() as u64; let lock_ttl = self.calc_txn_lock_ttl(); let mut request = match &self.options.kind { - TransactionKind::Optimistic => new_prewrite_request( + TransactionKind::Optimistic => new_prewrite_request::( self.mutations.clone(), primary_lock, self.start_version.clone(), lock_ttl + elapsed, ), - TransactionKind::Pessimistic(for_update_ts) => new_pessimistic_prewrite_request( + TransactionKind::Pessimistic(for_update_ts) => new_pessimistic_prewrite_request::( self.mutations.clone(), primary_lock, self.start_version.clone(), @@ -1214,7 +1218,7 @@ impl Committer { debug!(self.logger, "committing primary"); let primary_key = self.primary_key.clone().into_iter(); let commit_version = self.rpc.clone().get_timestamp().await?; - let req = new_commit_request( + let req = new_commit_request::( primary_key, self.start_version.clone(), commit_version.clone(), @@ -1246,7 +1250,7 @@ impl Committer { let req = if self.options.async_commit { let keys = mutations.map(|m| m.key.into()); - new_commit_request(keys, self.start_version, commit_version) + new_commit_request::(keys, self.start_version, commit_version) } else if primary_only { return Ok(()); } else { @@ -1254,7 +1258,7 @@ impl Committer { let keys = mutations .map(|m| m.key.into()) .filter(|key| &primary_key != key); - new_commit_request(keys, self.start_version, commit_version) + new_commit_request::(keys, self.start_version, commit_version) }; let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) @@ -1276,7 +1280,7 @@ impl Committer { .map(|mutation| mutation.key.into()); match self.options.kind { TransactionKind::Optimistic => { - let req = new_batch_rollback_request(keys, self.start_version); + let req = new_batch_rollback_request::(keys, self.start_version); let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) .retry_multi_region(self.options.retry_options.region_backoff) @@ -1285,7 +1289,7 @@ impl Committer { plan.execute().await?; } TransactionKind::Pessimistic(for_update_ts) => { - let req = new_pessimistic_rollback_request(keys, self.start_version, for_update_ts); + let req = new_pessimistic_rollback_request::(keys, self.start_version, for_update_ts); let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) .retry_multi_region(self.options.retry_options.region_backoff) @@ -1328,24 +1332,27 @@ enum TransactionStatus { #[cfg(test)] mod tests { - use crate::{ - mock::{MockKvClient, MockPdClient}, - transaction::HeartbeatOption, - Transaction, TransactionOptions, - }; - use fail::FailScenario; - use slog::{Drain, Logger}; use std::{ any::Any, io, sync::{ - atomic::{AtomicUsize, Ordering}, Arc, + atomic::{AtomicUsize, Ordering}, }, time::Duration, }; + + use fail::FailScenario; + use slog::{Drain, Logger}; + use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; + use crate::{ + mock::{MockKvClient, MockPdClient}, + Transaction, + transaction::HeartbeatOption, TransactionOptions, + }; + #[tokio::test] async fn test_optimistic_heartbeat() -> Result<(), io::Error> { let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); From aa6e4b5eb516316e64f8ef8d7da76a2e845fe1a2 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 21 Jun 2022 20:55:31 +0800 Subject: [PATCH 02/43] cargo fmt Signed-off-by: iosmanthus --- src/pd/client.rs | 39 ++++++------- src/raw/client.rs | 20 +++---- src/raw/lowering.rs | 61 +++++++++++-------- src/raw/requests.rs | 103 ++++++++++++++++++++++----------- src/request/mod.rs | 10 ++-- src/request/plan.rs | 46 ++++++++------- src/request/plan_builder.rs | 46 ++++++++------- src/request/request_codec.rs | 23 +++++--- src/transaction/client.rs | 35 +++++++---- src/transaction/lock.rs | 13 +++-- src/transaction/lowering.rs | 34 ++++++----- src/transaction/requests.rs | 94 ++++++++++++++++++++---------- src/transaction/snapshot.rs | 3 +- src/transaction/transaction.rs | 76 +++++++++++++----------- 14 files changed, 364 insertions(+), 239 deletions(-) diff --git a/src/pd/client.rs b/src/pd/client.rs index 8a886247..814493bb 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -1,7 +1,6 @@ // Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. -use std::{collections::HashMap, sync::Arc, thread}; -use std::marker::PhantomData; +use std::{collections::HashMap, marker::PhantomData, sync::Arc, thread}; use async_trait::async_trait; use futures::{prelude::*, stream::BoxStream}; @@ -14,15 +13,15 @@ use tikv_client_proto::{kvrpcpb, metapb}; use tikv_client_store::{KvClient, KvConnect, TikvConnect}; use crate::{ - BoundRange, compat::stream_fn, - Config, - Key, kv::codec, pd::{retry::RetryClientTrait, RetryClient}, - region::{RegionId, RegionVerId, RegionWithLeader}, region_cache::RegionCache, Result, SecurityManager, store::RegionStore, Timestamp, + region::{RegionId, RegionVerId, RegionWithLeader}, + region_cache::RegionCache, + request::request_codec::RequestCodec, + store::RegionStore, + BoundRange, Config, Key, Result, SecurityManager, Timestamp, }; -use crate::request::request_codec::RequestCodec; const CQ_COUNT: usize = 1; const CLIENT_PREFIX: &str = "tikv-client"; @@ -75,11 +74,11 @@ pub trait PdClient: Send + Sync + 'static { fn group_keys_by_region( self: Arc, - keys: impl Iterator + Send + Sync + 'static, + keys: impl Iterator + Send + Sync + 'static, ) -> BoxStream<'static, Result<(RegionId, Vec)>> - where - K: AsRef + Into + Send + Sync + 'static, - K2: Send + Sync + 'static, + where + K: AsRef + Into + Send + Sync + 'static, + K2: Send + Sync + 'static, { let keys = keys.peekable(); stream_fn(keys, move |mut keys| { @@ -101,7 +100,7 @@ pub trait PdClient: Send + Sync + 'static { } } }) - .boxed() + .boxed() } /// Returns a Stream which iterates over the contexts for each region covered by range. @@ -132,7 +131,7 @@ pub trait PdClient: Send + Sync + 'static { Ok(Some((Some(region_end), store))) } }) - .boxed() + .boxed() } /// Returns a Stream which iterates over the contexts for ranges in the same region. @@ -196,7 +195,7 @@ pub trait PdClient: Send + Sync + 'static { } } }) - .boxed() + .boxed() } fn decode_region(mut region: RegionWithLeader, enable_codec: bool) -> Result { @@ -293,7 +292,7 @@ impl PdRpcClient { enable_codec, logger, ) - .await + .await } } @@ -314,10 +313,10 @@ impl PdRpcClient { enable_codec: bool, logger: Logger, ) -> Result> - where - PdFut: Future>>, - MakeKvC: FnOnce(Arc, Arc) -> KvC, - MakePd: FnOnce(Arc, Arc) -> PdFut, + where + PdFut: Future>>, + MakeKvC: FnOnce(Arc, Arc) -> KvC, + MakePd: FnOnce(Arc, Arc) -> PdFut, { let env = Arc::new( EnvBuilder::new() @@ -327,7 +326,7 @@ impl PdRpcClient { ); let security_mgr = Arc::new( if let (Some(ca_path), Some(cert_path), Some(key_path)) = - (&config.ca_path, &config.cert_path, &config.key_path) + (&config.ca_path, &config.cert_path, &config.key_path) { SecurityManager::load(ca_path, cert_path, key_path)? } else { diff --git a/src/raw/client.rs b/src/raw/client.rs index 430386d3..942272e5 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -1,8 +1,7 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use core::ops::Range; -use std::{str::FromStr, sync::Arc, u32}; -use std::marker::PhantomData; +use std::{marker::PhantomData, str::FromStr, sync::Arc, u32}; use slog::{Drain, Logger}; use tikv_client_common::Error; @@ -13,10 +12,9 @@ use crate::{ config::Config, pd::{PdClient, PdRpcClient}, raw::lowering::*, - request::{Collect, CollectSingle, Plan}, + request::{request_codec::RequestCodec, Collect, CollectSingle, Plan}, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; -use crate::request::request_codec::RequestCodec; const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; @@ -106,7 +104,7 @@ impl Client> { cf: None, atomic: false, logger, - _phantom: PhantomData + _phantom: PhantomData, }) } @@ -141,7 +139,7 @@ impl Client> { cf: Some(cf), atomic: self.atomic, logger: self.logger.clone(), - _phantom: PhantomData + _phantom: PhantomData, } } @@ -159,12 +157,12 @@ impl Client> { cf: self.cf.clone(), atomic: true, logger: self.logger.clone(), - _phantom: PhantomData + _phantom: PhantomData, } } } -impl Client { +impl Client { /// Create a new 'get' request. /// /// Once resolved this request will result in the fetching of the value associated with the @@ -217,7 +215,8 @@ impl Client { keys: impl IntoIterator>, ) -> Result> { debug!(self.logger, "invoking raw batch_get request"); - let request = new_raw_batch_get_request::(keys.into_iter().map(Into::into), self.cf.clone()); + let request = + new_raw_batch_get_request::(keys.into_iter().map(Into::into), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(Collect) @@ -245,7 +244,8 @@ impl Client { /// ``` pub async fn put(&self, key: impl Into, value: impl Into) -> Result<()> { debug!(self.logger, "invoking raw put request"); - let request = new_raw_put_request::(key.into(), value.into(), self.cf.clone(), self.atomic); + let request = + new_raw_put_request::(key.into(), value.into(), self.cf.clone(), self.atomic); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(DEFAULT_REGION_BACKOFF) .merge(CollectSingle) diff --git a/src/raw/lowering.rs b/src/raw/lowering.rs index d9ae6de4..8f60daab 100644 --- a/src/raw/lowering.rs +++ b/src/raw/lowering.rs @@ -4,27 +4,31 @@ //! types (i.e., the types from the client crate) and converts these to the types used in the //! generated protobuf code, then calls the low-level ctor functions in the requests module. -use std::{iter::Iterator, ops::Range, sync::Arc}; -use std::marker::PhantomData; +use std::{iter::Iterator, marker::PhantomData, ops::Range, sync::Arc}; use tikv_client_proto::{kvrpcpb, metapb}; -use crate::{BoundRange, ColumnFamily, Key, KvPair, raw::requests, Value}; -use crate::request::KvRequest; -use crate::request::request_codec::RequestCodec; +use crate::{ + raw::requests, + request::{request_codec::RequestCodec, KvRequest}, + BoundRange, ColumnFamily, Key, KvPair, Value, +}; -pub fn new_raw_get_request(key: Key, cf: Option) -> kvrpcpb::RawGetRequest { +pub fn new_raw_get_request( + key: Key, + cf: Option, +) -> kvrpcpb::RawGetRequest { requests::new_raw_get_request::(key.into(), cf) } -pub fn new_raw_batch_get_request( - keys: impl Iterator, +pub fn new_raw_batch_get_request( + keys: impl Iterator, cf: Option, ) -> kvrpcpb::RawBatchGetRequest { requests::new_raw_batch_get_request::(keys.map(Into::into).collect(), cf) } -pub fn new_raw_put_request( +pub fn new_raw_put_request( key: Key, value: Value, cf: Option, @@ -33,15 +37,15 @@ pub fn new_raw_put_request( requests::new_raw_put_request::(key.into(), value, cf, atomic) } -pub fn new_raw_batch_put_request( - pairs: impl Iterator, +pub fn new_raw_batch_put_request( + pairs: impl Iterator, cf: Option, atomic: bool, ) -> kvrpcpb::RawBatchPutRequest { requests::new_raw_batch_put_request::(pairs.map(Into::into).collect(), cf, atomic) } -pub fn new_raw_delete_request( +pub fn new_raw_delete_request( key: Key, cf: Option, atomic: bool, @@ -49,27 +53,31 @@ pub fn new_raw_delete_request( requests::new_raw_delete_request::(key.into(), cf, atomic) } -pub fn new_raw_batch_delete_request( - keys: impl Iterator, +pub fn new_raw_batch_delete_request( + keys: impl Iterator, cf: Option, ) -> kvrpcpb::RawBatchDeleteRequest { requests::new_raw_batch_delete_request::(keys.map(Into::into).collect(), cf) } -pub fn new_raw_delete_range_request( +pub fn new_raw_delete_range_request( range: BoundRange, cf: Option, ) -> kvrpcpb::RawDeleteRangeRequest { let (start_key, end_key) = range.into_keys(); - requests::new_raw_delete_range_request::(start_key.into(), end_key.unwrap_or_default().into(), cf) + requests::new_raw_delete_range_request::( + start_key.into(), + end_key.unwrap_or_default().into(), + cf, + ) } -pub fn new_raw_scan_request( +pub fn new_raw_scan_request( range: BoundRange, limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawScanRequest { +) -> kvrpcpb::RawScanRequest { let (start_key, end_key) = range.into_keys(); requests::new_raw_scan_request::( start_key.into(), @@ -80,16 +88,21 @@ pub fn new_raw_scan_request( ) } -pub fn new_raw_batch_scan_request( - ranges: impl Iterator, +pub fn new_raw_batch_scan_request( + ranges: impl Iterator, each_limit: u32, key_only: bool, cf: Option, ) -> kvrpcpb::RawBatchScanRequest { - requests::new_raw_batch_scan_request::(ranges.map(Into::into).collect(), each_limit, key_only, cf) + requests::new_raw_batch_scan_request::( + ranges.map(Into::into).collect(), + each_limit, + key_only, + cf, + ) } -pub fn new_cas_request( +pub fn new_cas_request( key: Key, value: Value, previous_value: Option, @@ -98,10 +111,10 @@ pub fn new_cas_request( requests::new_cas_request::(key.into(), value, previous_value, cf) } -pub fn new_raw_coprocessor_request( +pub fn new_raw_coprocessor_request( copr_name: String, copr_version_req: String, - ranges: impl Iterator, + ranges: impl Iterator, request_builder: impl Fn(metapb::Region, Vec>) -> Vec + Send + Sync + 'static, ) -> requests::RawCoprocessorRequest { requests::new_raw_coprocessor_request::( diff --git a/src/raw/requests.rs b/src/raw/requests.rs index 5b0fa52e..c3c10fee 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -1,7 +1,6 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::{any::Any, ops::Range, sync::Arc}; -use std::borrow::Cow; +use std::{any::Any, borrow::Cow, ops::Range, sync::Arc}; use async_trait::async_trait; use futures::stream::BoxStream; @@ -14,17 +13,23 @@ use crate::{ collect_first, pd::PdClient, request::{ - plan::ResponseWithShard, Collect, CollectSingle, DefaultProcessor, KvRequest, Merge, - Process, Shardable, SingleKey, + plan::ResponseWithShard, + request_codec::{RawApiV1, RequestCodec}, + Collect, CollectSingle, DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, transaction::HasLocks, util::iter::FlatMapOkIterExt, ColumnFamily, Key, KvPair, Result, Value, }; -use crate::request::request_codec::{RawApiV1, RequestCodec}; -pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::RawGetRequest where kvrpcpb::RawGetRequest: KvRequest { +pub fn new_raw_get_request( + key: Vec, + cf: Option, +) -> kvrpcpb::RawGetRequest +where + kvrpcpb::RawGetRequest: KvRequest, +{ let mut req = kvrpcpb::RawGetRequest::default(); req.set_key(key); req.maybe_set_cf(cf); @@ -32,7 +37,7 @@ pub fn new_raw_get_request(key: Vec, cf: Option KvRequest for kvrpcpb::RawGetRequest { +impl KvRequest for kvrpcpb::RawGetRequest { type Response = kvrpcpb::RawGetResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -69,7 +74,10 @@ impl Process for DefaultProcessor { pub fn new_raw_batch_get_request( keys: Vec>, cf: Option, -) -> kvrpcpb::RawBatchGetRequest where kvrpcpb::RawBatchGetRequest: KvRequest{ +) -> kvrpcpb::RawBatchGetRequest +where + kvrpcpb::RawBatchGetRequest: KvRequest, +{ let mut req = kvrpcpb::RawBatchGetRequest::default(); req.set_keys(keys); req.maybe_set_cf(cf); @@ -77,7 +85,7 @@ pub fn new_raw_batch_get_request( req } -impl KvRequest for kvrpcpb::RawBatchGetRequest { +impl KvRequest for kvrpcpb::RawBatchGetRequest { type Response = kvrpcpb::RawBatchGetResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -102,12 +110,15 @@ impl Merge for Collect { } } -pub fn new_raw_put_request( +pub fn new_raw_put_request( key: Vec, value: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawPutRequest where kvrpcpb::RawPutRequest: KvRequest { +) -> kvrpcpb::RawPutRequest +where + kvrpcpb::RawPutRequest: KvRequest, +{ let mut req = kvrpcpb::RawPutRequest::default(); req.set_key(key); req.set_value(value); @@ -117,7 +128,7 @@ pub fn new_raw_put_request( req } -impl KvRequest for kvrpcpb::RawPutRequest { +impl KvRequest for kvrpcpb::RawPutRequest { type Response = kvrpcpb::RawPutResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -141,7 +152,10 @@ pub fn new_raw_batch_put_request( pairs: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawBatchPutRequest where kvrpcpb::RawBatchPutRequest: KvRequest { +) -> kvrpcpb::RawBatchPutRequest +where + kvrpcpb::RawBatchPutRequest: KvRequest, +{ let mut req = kvrpcpb::RawBatchPutRequest::default(); req.set_pairs(pairs); req.maybe_set_cf(cf); @@ -150,7 +164,7 @@ pub fn new_raw_batch_put_request( req } -impl KvRequest for kvrpcpb::RawBatchPutRequest { +impl KvRequest for kvrpcpb::RawBatchPutRequest { type Response = kvrpcpb::RawBatchPutResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -188,7 +202,10 @@ pub fn new_raw_delete_request( key: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawDeleteRequest where kvrpcpb::RawDeleteRequest: KvRequest { +) -> kvrpcpb::RawDeleteRequest +where + kvrpcpb::RawDeleteRequest: KvRequest, +{ let mut req = kvrpcpb::RawDeleteRequest::default(); req.set_key(key); req.maybe_set_cf(cf); @@ -197,7 +214,7 @@ pub fn new_raw_delete_request( req } -impl KvRequest for kvrpcpb::RawDeleteRequest { +impl KvRequest for kvrpcpb::RawDeleteRequest { type Response = kvrpcpb::RawDeleteResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -217,10 +234,13 @@ impl SingleKey for kvrpcpb::RawDeleteRequest { } } -pub fn new_raw_batch_delete_request( +pub fn new_raw_batch_delete_request( keys: Vec>, cf: Option, -) -> kvrpcpb::RawBatchDeleteRequest where kvrpcpb::RawBatchDeleteRequest: KvRequest { +) -> kvrpcpb::RawBatchDeleteRequest +where + kvrpcpb::RawBatchDeleteRequest: KvRequest, +{ let mut req = kvrpcpb::RawBatchDeleteRequest::default(); req.set_keys(keys); req.maybe_set_cf(cf); @@ -228,7 +248,7 @@ pub fn new_raw_batch_delete_request( req } -impl KvRequest for kvrpcpb::RawBatchDeleteRequest { +impl KvRequest for kvrpcpb::RawBatchDeleteRequest { type Response = kvrpcpb::RawBatchDeleteResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -242,11 +262,14 @@ impl KvRequest for kvrpcpb::RawBatchDeleteRequest { shardable_keys!(kvrpcpb::RawBatchDeleteRequest); -pub fn new_raw_delete_range_request( +pub fn new_raw_delete_range_request( start_key: Vec, end_key: Vec, cf: Option, -) -> kvrpcpb::RawDeleteRangeRequest where kvrpcpb::RawDeleteRangeRequest: KvRequest { +) -> kvrpcpb::RawDeleteRangeRequest +where + kvrpcpb::RawDeleteRangeRequest: KvRequest, +{ let mut req = kvrpcpb::RawDeleteRangeRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -255,7 +278,7 @@ pub fn new_raw_delete_range_request( req } -impl KvRequest for kvrpcpb::RawDeleteRangeRequest { +impl KvRequest for kvrpcpb::RawDeleteRangeRequest { type Response = kvrpcpb::RawDeleteRangeResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -269,13 +292,16 @@ impl KvRequest for kvrpcpb::RawDeleteRangeRequest { shardable_range!(kvrpcpb::RawDeleteRangeRequest); -pub fn new_raw_scan_request( +pub fn new_raw_scan_request( start_key: Vec, end_key: Vec, limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawScanRequest where kvrpcpb::RawScanRequest: KvRequest { +) -> kvrpcpb::RawScanRequest +where + kvrpcpb::RawScanRequest: KvRequest, +{ let mut req = kvrpcpb::RawScanRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -286,7 +312,7 @@ pub fn new_raw_scan_request( req } -impl KvRequest for kvrpcpb::RawScanRequest { +impl KvRequest for kvrpcpb::RawScanRequest { type Response = kvrpcpb::RawScanResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -311,12 +337,15 @@ impl Merge for Collect { } } -pub fn new_raw_batch_scan_request( +pub fn new_raw_batch_scan_request( ranges: Vec, each_limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawBatchScanRequest where kvrpcpb::RawBatchScanRequest: KvRequest { +) -> kvrpcpb::RawBatchScanRequest +where + kvrpcpb::RawBatchScanRequest: KvRequest, +{ let mut req = kvrpcpb::RawBatchScanRequest::default(); req.set_ranges(ranges); req.set_each_limit(each_limit); @@ -326,7 +355,7 @@ pub fn new_raw_batch_scan_request( req } -impl KvRequest for kvrpcpb::RawBatchScanRequest { +impl KvRequest for kvrpcpb::RawBatchScanRequest { type Response = kvrpcpb::RawBatchScanResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -366,12 +395,15 @@ impl Merge for Collect { } } -pub fn new_cas_request( +pub fn new_cas_request( key: Vec, value: Vec, previous_value: Option>, cf: Option, -) -> kvrpcpb::RawCasRequest where kvrpcpb::RawCasRequest: KvRequest { +) -> kvrpcpb::RawCasRequest +where + kvrpcpb::RawCasRequest: KvRequest, +{ let mut req = kvrpcpb::RawCasRequest::default(); req.set_key(key); req.set_value(value); @@ -383,7 +415,7 @@ pub fn new_cas_request( req } -impl KvRequest for kvrpcpb::RawCasRequest { +impl KvRequest for kvrpcpb::RawCasRequest { type Response = kvrpcpb::RawCasResponse; fn encode_request(&self, _codec: &C) -> Cow { @@ -419,12 +451,15 @@ impl Process for DefaultProcessor { type RawCoprocessorRequestDataBuilder = Arc) -> Vec + Send + Sync>; -pub fn new_raw_coprocessor_request( +pub fn new_raw_coprocessor_request( copr_name: String, copr_version_req: String, ranges: Vec, data_builder: RawCoprocessorRequestDataBuilder, -) -> RawCoprocessorRequest where RawCoprocessorRequest: KvRequest { +) -> RawCoprocessorRequest +where + RawCoprocessorRequest: KvRequest, +{ let mut inner = kvrpcpb::RawCoprocessorRequest::default(); inner.set_copr_name(copr_name); inner.set_copr_version_req(copr_version_req); @@ -460,7 +495,7 @@ impl Request for RawCoprocessorRequest { } } -impl KvRequest for RawCoprocessorRequest { +impl KvRequest for RawCoprocessorRequest { type Response = kvrpcpb::RawCoprocessorResponse; fn encode_request(&self, _codec: &C) -> Cow { diff --git a/src/request/mod.rs b/src/request/mod.rs index f18f9eb2..461ff6c7 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -9,9 +9,9 @@ use tikv_client_store::{HasKeyErrors, HasRegionError, Request}; use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF, PESSIMISTIC_BACKOFF}, + pd::PdClient, transaction::HasLocks, }; -use crate::pd::PdClient; pub use self::{ plan::{ @@ -74,7 +74,7 @@ mod test { use std::{ any::Any, iter, - sync::{Arc, atomic::AtomicUsize}, + sync::{atomic::AtomicUsize, Arc}, }; use grpcio::CallOption; @@ -83,10 +83,10 @@ mod test { use tikv_client_store::HasRegionError; use crate::{ - Error, - Key, mock::{MockKvClient, MockPdClient}, - Result, store::store_stream_for_keys, transaction::lowering::new_commit_request, + store::store_stream_for_keys, + transaction::lowering::new_commit_request, + Error, Key, Result, }; use super::*; diff --git a/src/request/plan.rs b/src/request/plan.rs index e0941702..4de3338e 100644 --- a/src/request/plan.rs +++ b/src/request/plan.rs @@ -12,15 +12,14 @@ use tikv_client_store::{HasKeyErrors, HasRegionError, HasRegionErrors, KvClient} use crate::{ backoff::Backoff, - Error, pd::PdClient, - request::{KvRequest, Shardable}, - Result, + request::{request_codec::RequestCodec, KvRequest, Shardable}, stats::tikv_stats, store::RegionStore, - transaction::{HasLocks, resolve_locks}, util::iter::FlatMapOkIterExt, + transaction::{resolve_locks, HasLocks}, + util::iter::FlatMapOkIterExt, + Error, Result, }; -use crate::request::request_codec::RequestCodec; /// A plan for how to execute a request. A user builds up a plan with various /// options, then exectutes it. @@ -66,8 +65,11 @@ impl> Plan for Dispatch { .await; let result = stats.done(result); result.and_then(|r| { - req.decode_response(&self.codec, *r.downcast() - .expect("Downcast failed: request and response type mismatch")) + req.decode_response( + &self.codec, + *r.downcast() + .expect("Downcast failed: request and response type mismatch"), + ) }) } } @@ -86,8 +88,8 @@ pub struct RetryableMultiRegion { } impl RetryableMultiRegion - where - P::Result: HasKeyErrors + HasRegionError, +where + P::Result: HasKeyErrors + HasRegionError, { // A plan may involve multiple shards #[async_recursion] @@ -167,7 +169,7 @@ impl RetryableMultiRegion permits, preserve_region_results, ) - .await + .await } None => Err(Error::RegionError(e)), } @@ -219,7 +221,7 @@ impl RetryableMultiRegion region_store, e.take_epoch_not_match(), ) - .await + .await } else if e.has_stale_command() || e.has_region_not_found() { pd_client.invalidate_region_cache(ver_id).await; Ok(false) @@ -291,8 +293,8 @@ impl Clone for RetryableMultiRegion { #[async_trait] impl Plan for RetryableMultiRegion - where - P::Result: HasKeyErrors + HasRegionError, +where + P::Result: HasKeyErrors + HasRegionError, { type Result = Vec>; @@ -308,7 +310,7 @@ impl Plan for RetryableMultiRegion concurrency_permits.clone(), self.preserve_region_results, ) - .await + .await } } @@ -327,8 +329,8 @@ pub struct MergeResponse> { } #[async_trait] -impl>>, M: Merge> Plan -for MergeResponse +impl>>, M: Merge> Plan + for MergeResponse { type Result = M::Out; @@ -422,8 +424,8 @@ impl Clone for ResolveLock { #[async_trait] impl Plan for ResolveLock - where - P::Result: HasLocks, +where + P::Result: HasLocks, { type Result = P::Result; @@ -478,8 +480,8 @@ impl Clone for ExtractError

{ #[async_trait] impl Plan for ExtractError

- where - P::Result: HasKeyErrors + HasRegionErrors, +where + P::Result: HasKeyErrors + HasRegionErrors, { type Result = P::Result; @@ -518,8 +520,8 @@ impl Clone for PreserveShard

{ #[async_trait] impl

Plan for PreserveShard

- where - P: Plan + Shardable, +where + P: Plan + Shardable, { type Result = ResponseWithShard; diff --git a/src/request/plan_builder.rs b/src/request/plan_builder.rs index 70e53e82..c354ed57 100644 --- a/src/request/plan_builder.rs +++ b/src/request/plan_builder.rs @@ -8,14 +8,14 @@ use crate::{ backoff::Backoff, pd::PdClient, request::{ - DefaultProcessor, Dispatch, ExtractError, KvRequest, Merge, MergeResponse, Plan, Process, - ProcessResponse, ResolveLock, RetryableMultiRegion, Shardable, + request_codec::RequestCodec, DefaultProcessor, Dispatch, ExtractError, KvRequest, Merge, + MergeResponse, Plan, Process, ProcessResponse, ResolveLock, RetryableMultiRegion, + Shardable, }, - Result, store::RegionStore, transaction::HasLocks, + Result, }; -use crate::request::request_codec::RequestCodec; use super::plan::PreserveShard; @@ -38,10 +38,12 @@ pub struct Targetted; impl PlanBuilderPhase for Targetted {} -impl PlanBuilder, NoTarget> where +impl PlanBuilder, NoTarget> +where C: RequestCodec, Req: KvRequest, - PdC: PdClient { + PdC: PdClient, +{ pub fn new(pd_client: Arc, request: Req) -> Self { let codec = pd_client.get_request_codec().clone(); PlanBuilder { @@ -63,8 +65,8 @@ impl PlanBuilder { impl PlanBuilder { /// If there is a lock error, then resolve the lock and retry the request. pub fn resolve_lock(self, backoff: Backoff) -> PlanBuilder, Ph> - where - P::Result: HasLocks, + where + P::Result: HasLocks, { PlanBuilder { pd_client: self.pd_client.clone(), @@ -80,9 +82,9 @@ impl PlanBuilder { /// Merge the results of a request. Usually used where a request is sent to multiple regions /// to combine the responses from each region. pub fn merge>(self, merge: M) -> PlanBuilder, Ph> - where - In: Clone + Send + Sync + 'static, - P: Plan>>, + where + In: Clone + Send + Sync + 'static, + P: Plan>>, { PlanBuilder { pd_client: self.pd_client.clone(), @@ -99,9 +101,9 @@ impl PlanBuilder { /// to a single region because post-porcessing can be incorporated in the merge step for /// multi-region requests). pub fn post_process_default(self) -> PlanBuilder, Ph> - where - P: Plan, - DefaultProcessor: Process, + where + P: Plan, + DefaultProcessor: Process, { PlanBuilder { pd_client: self.pd_client.clone(), @@ -115,8 +117,8 @@ impl PlanBuilder { } impl PlanBuilder - where - P::Result: HasKeyErrors + HasRegionError, +where + P::Result: HasKeyErrors + HasRegionError, { /// Split the request into shards sending a request to the region of each shard. pub fn retry_multi_region( @@ -153,7 +155,9 @@ impl PlanBuilder } } -impl + SingleKey> PlanBuilder, NoTarget> { +impl + SingleKey> + PlanBuilder, NoTarget> +{ /// Target the request at a single region. *Note*: single region plan will /// cannot automatically retry on region errors. It's only used for requests /// that target at a specific region but not keys (e.g. ResolveLockRequest). @@ -176,8 +180,8 @@ impl> PlanBuilder PlanBuilder - where - P::Result: HasKeyErrors, +where + P::Result: HasKeyErrors, { pub fn preserve_shard(self) -> PlanBuilder, NoTarget> { PlanBuilder { @@ -192,8 +196,8 @@ impl PlanBuilder } impl PlanBuilder - where - P::Result: HasKeyErrors + HasRegionErrors, +where + P::Result: HasKeyErrors + HasRegionErrors, { pub fn extract_error(self) -> PlanBuilder, Targetted> { PlanBuilder { diff --git a/src/request/request_codec.rs b/src/request/request_codec.rs index a90922fa..463b3406 100644 --- a/src/request/request_codec.rs +++ b/src/request/request_codec.rs @@ -3,11 +3,21 @@ use tikv_client_proto::metapb::Region; use crate::Result; pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { - fn encode_key(&self, key: Vec) -> Vec { key } - fn decode_key(&self, key: Vec) -> Result> { Ok(key) } - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { (start, end) } - fn encode_pd_query(&self, key: Vec) -> Vec { key } - fn decode_region(&self, region: Region) -> Result { Ok(region) } + fn encode_key(&self, key: Vec) -> Vec { + key + } + fn decode_key(&self, key: Vec) -> Result> { + Ok(key) + } + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + (start, end) + } + fn encode_pd_query(&self, key: Vec) -> Vec { + key + } + fn decode_region(&self, region: Region) -> Result { + Ok(region) + } } #[derive(Clone)] @@ -15,8 +25,7 @@ pub struct RawApiV1; impl RequestCodec for RawApiV1 {} - #[derive(Clone)] pub struct TxnApiV1; -impl RequestCodec for TxnApiV1 {} \ No newline at end of file +impl RequestCodec for TxnApiV1 {} diff --git a/src/transaction/client.rs b/src/transaction/client.rs index a65fd2a0..c8464c11 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -1,7 +1,6 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::{mem, sync::Arc}; -use std::marker::PhantomData; +use std::{marker::PhantomData, mem, sync::Arc}; use slog::{Drain, Logger}; @@ -11,12 +10,11 @@ use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, pd::{PdClient, PdRpcClient}, - request::Plan, - Result, + request::{request_codec::RequestCodec, Plan}, timestamp::TimestampExt, transaction::{Snapshot, Transaction, TransactionOptions}, + Result, }; -use crate::request::request_codec::RequestCodec; use super::{requests::new_scan_lock_request, resolve_locks}; @@ -46,8 +44,8 @@ pub struct Client { } impl Client - where - C: RequestCodec, +where + C: RequestCodec, { /// Create a transactional [`Client`] and connect to the TiKV cluster. /// @@ -114,7 +112,11 @@ impl Client debug!(logger, "creating new transactional client"); let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); let pd = Arc::new(PdRpcClient::connect(&pd_endpoints, config, true, logger.clone()).await?); - Ok(Client { pd, logger, _phantom: PhantomData }) + Ok(Client { + pd, + logger, + _phantom: PhantomData, + }) } /// Creates a new optimistic [`Transaction`]. @@ -189,14 +191,21 @@ impl Client /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_with_options(&self, options: TransactionOptions) -> Result>> { + pub async fn begin_with_options( + &self, + options: TransactionOptions, + ) -> Result>> { debug!(self.logger, "creating new customized transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, options)) } /// Create a new [`Snapshot`](Snapshot) at the given [`Timestamp`](Timestamp). - pub fn snapshot(&self, timestamp: Timestamp, options: TransactionOptions) -> Snapshot> { + pub fn snapshot( + &self, + timestamp: Timestamp, + options: TransactionOptions, + ) -> Snapshot> { debug!(self.logger, "creating new snapshot"); let logger = self.logger.new(o!("child" => 1)); Snapshot::new(self.new_transaction(timestamp, options.read_only()), logger) @@ -277,7 +286,11 @@ impl Client Ok(res) } - fn new_transaction(&self, timestamp: Timestamp, options: TransactionOptions) -> Transaction> { + fn new_transaction( + &self, + timestamp: Timestamp, + options: TransactionOptions, + ) -> Transaction> { let logger = self.logger.new(o!("child" => 1)); Transaction::new(timestamp, self.pd.clone(), options, logger) } diff --git a/src/transaction/lock.rs b/src/transaction/lock.rs index 01a07db9..bbd9667a 100644 --- a/src/transaction/lock.rs +++ b/src/transaction/lock.rs @@ -4,7 +4,7 @@ use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, pd::PdClient, region::RegionVerId, - request::{CollectSingle, Plan}, + request::{request_codec::RequestCodec, CollectSingle, Plan}, timestamp::TimestampExt, transaction::requests, Error, Result, @@ -15,7 +15,6 @@ use std::{ sync::Arc, }; use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; -use crate::request::request_codec::RequestCodec; const RESOLVE_LOCK_RETRY_LIMIT: usize = 10; @@ -62,7 +61,10 @@ pub async fn resolve_locks( let commit_version = match commit_versions.get(&lock.lock_version) { Some(&commit_version) => commit_version, None => { - let request = requests::new_cleanup_request::(lock.primary_lock, lock.lock_version); + let request = requests::new_cleanup_request::( + lock.primary_lock, + lock.lock_version, + ); let plan = crate::request::PlanBuilder::new(pd_client.clone(), request) .resolve_lock(OPTIMISTIC_BACKOFF) .retry_multi_region(DEFAULT_REGION_BACKOFF) @@ -90,7 +92,7 @@ pub async fn resolve_locks( Ok(!has_live_locks) } -async fn resolve_lock_with_retry( +async fn resolve_lock_with_retry( #[allow(clippy::ptr_arg)] key: &Vec, start_version: u64, commit_version: u64, @@ -103,7 +105,8 @@ async fn resolve_lock_with_retry( debug!("resolving locks: attempt {}", (i + 1)); let store = pd_client.clone().store_for_key(key.into()).await?; let ver_id = store.region_with_leader.ver_id(); - let request = requests::new_resolve_lock_request::(start_version, commit_version); + let request = + requests::new_resolve_lock_request::(start_version, commit_version); // The only place where single-region is used let plan = crate::request::PlanBuilder::new(pd_client.clone(), request) .single_region_with_store(store) diff --git a/src/transaction/lowering.rs b/src/transaction/lowering.rs index 4477de46..509e1d3d 100644 --- a/src/transaction/lowering.rs +++ b/src/transaction/lowering.rs @@ -1,25 +1,25 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. +use crate::request::request_codec::RequestCodec; /// This module provides constructor functions for requests which take arguments as high-level /// types (i.e., the types from the client crate) and converts these to the types used in the /// generated protobuf code, then calls the low-level ctor functions in the requests module. use crate::{timestamp::TimestampExt, transaction::requests, BoundRange, Key}; use std::iter::Iterator; use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; -use crate::request::request_codec::RequestCodec; pub fn new_get_request(key: Key, timestamp: Timestamp) -> kvrpcpb::GetRequest { requests::new_get_request::(key.into(), timestamp.version()) } -pub fn new_batch_get_request( +pub fn new_batch_get_request( keys: impl Iterator, timestamp: Timestamp, ) -> kvrpcpb::BatchGetRequest { requests::new_batch_get_request::(keys.map(Into::into).collect(), timestamp.version()) } -pub fn new_scan_request( +pub fn new_scan_request( range: BoundRange, timestamp: Timestamp, limit: u32, @@ -35,18 +35,21 @@ pub fn new_scan_request( ) } -pub fn new_resolve_lock_request( +pub fn new_resolve_lock_request( start_version: Timestamp, commit_version: Timestamp, ) -> kvrpcpb::ResolveLockRequest { requests::new_resolve_lock_request::(start_version.version(), commit_version.version()) } -pub fn new_cleanup_request(key: Key, start_version: Timestamp) -> kvrpcpb::CleanupRequest { +pub fn new_cleanup_request( + key: Key, + start_version: Timestamp, +) -> kvrpcpb::CleanupRequest { requests::new_cleanup_request::(key.into(), start_version.version()) } -pub fn new_prewrite_request( +pub fn new_prewrite_request( mutations: Vec, primary_lock: Key, start_version: Timestamp, @@ -60,7 +63,7 @@ pub fn new_prewrite_request( ) } -pub fn new_pessimistic_prewrite_request( +pub fn new_pessimistic_prewrite_request( mutations: Vec, primary_lock: Key, start_version: Timestamp, @@ -76,7 +79,7 @@ pub fn new_pessimistic_prewrite_request( ) } -pub fn new_commit_request( +pub fn new_commit_request( keys: impl Iterator, start_version: Timestamp, commit_version: Timestamp, @@ -88,14 +91,17 @@ pub fn new_commit_request( ) } -pub fn new_batch_rollback_request( +pub fn new_batch_rollback_request( keys: impl Iterator, start_version: Timestamp, ) -> kvrpcpb::BatchRollbackRequest { - requests::new_batch_rollback_request::(keys.map(Into::into).collect(), start_version.version()) + requests::new_batch_rollback_request::( + keys.map(Into::into).collect(), + start_version.version(), + ) } -pub fn new_pessimistic_rollback_request( +pub fn new_pessimistic_rollback_request( keys: impl Iterator, start_version: Timestamp, for_update_ts: Timestamp, @@ -133,7 +139,7 @@ impl PessimisticLock for (Key, kvrpcpb::Assertion) { } } -pub fn new_pessimistic_lock_request( +pub fn new_pessimistic_lock_request( locks: impl Iterator, primary_lock: Key, start_version: Timestamp, @@ -159,7 +165,7 @@ pub fn new_pessimistic_lock_request( ) } -pub fn new_scan_lock_request( +pub fn new_scan_lock_request( start_key: Key, safepoint: Timestamp, limit: u32, @@ -167,7 +173,7 @@ pub fn new_scan_lock_request( requests::new_scan_lock_request::(start_key.into(), safepoint.version(), limit) } -pub fn new_heart_beat_request( +pub fn new_heart_beat_request( start_ts: Timestamp, primary_lock: Key, ttl: u64, diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 3cd5440c..619267a2 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -1,6 +1,5 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. -use std::{collections::HashMap, iter, sync::Arc}; -use std::borrow::Cow; +use std::{borrow::Cow, collections::HashMap, iter, sync::Arc}; use either::Either; use futures::stream::BoxStream; @@ -14,18 +13,18 @@ use tikv_client_store::HasRegionErrors; use crate::{ collect_first, - Key, - KvPair, pd::PdClient, request::{ + request_codec::{RequestCodec, TxnApiV1}, Collect, CollectSingle, CollectWithShard, DefaultProcessor, KvRequest, Merge, Process, ResponseWithShard, Shardable, SingleKey, }, - Result, - store::{RegionStore, store_stream_for_keys, store_stream_for_range_by_start_key}, - timestamp::TimestampExt, transaction::HasLocks, util::iter::FlatMapOkIterExt, Value, + store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, + timestamp::TimestampExt, + transaction::HasLocks, + util::iter::FlatMapOkIterExt, + Key, KvPair, Result, Value, }; -use crate::request::request_codec::{RequestCodec, TxnApiV1}; // implement HasLocks for a response type that has a `pairs` field, // where locks can be extracted from both the `pairs` and `error` fields @@ -69,7 +68,8 @@ macro_rules! error_locks { } pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest - where kvrpcpb::GetRequest: KvRequest +where + kvrpcpb::GetRequest: KvRequest, { let mut req = kvrpcpb::GetRequest::default(); req.set_key(key); @@ -110,8 +110,12 @@ impl Process for DefaultProcessor { } } -pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::BatchGetRequest - where kvrpcpb::BatchGetRequest: KvRequest +pub fn new_batch_get_request( + keys: Vec>, + timestamp: u64, +) -> kvrpcpb::BatchGetRequest +where + kvrpcpb::BatchGetRequest: KvRequest, { let mut req = kvrpcpb::BatchGetRequest::default(); req.set_keys(keys); @@ -151,7 +155,8 @@ pub fn new_scan_request( limit: u32, key_only: bool, ) -> kvrpcpb::ScanRequest - where kvrpcpb::ScanRequest: KvRequest +where + kvrpcpb::ScanRequest: KvRequest, { let mut req = kvrpcpb::ScanRequest::default(); req.set_start_key(start_key); @@ -190,7 +195,8 @@ impl Merge for Collect { pub fn new_resolve_lock_request( start_version: u64, commit_version: u64, -) -> kvrpcpb::ResolveLockRequest where +) -> kvrpcpb::ResolveLockRequest +where kvrpcpb::ResolveLockRequest: KvRequest, { let mut req = kvrpcpb::ResolveLockRequest::default(); @@ -228,8 +234,12 @@ impl KvRequest for kvrpcpb::ResolveLockRequest { } } -pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest - where kvrpcpb::CleanupRequest: KvRequest +pub fn new_cleanup_request( + key: Vec, + start_version: u64, +) -> kvrpcpb::CleanupRequest +where + kvrpcpb::CleanupRequest: KvRequest, { let mut req = kvrpcpb::CleanupRequest::default(); req.set_key(key); @@ -271,7 +281,10 @@ pub fn new_prewrite_request( primary_lock: Vec, start_version: u64, lock_ttl: u64, -) -> kvrpcpb::PrewriteRequest where kvrpcpb::PrewriteRequest: KvRequest { +) -> kvrpcpb::PrewriteRequest +where + kvrpcpb::PrewriteRequest: KvRequest, +{ let mut req = kvrpcpb::PrewriteRequest::default(); req.set_mutations(mutations); req.set_primary_lock(primary_lock); @@ -289,7 +302,10 @@ pub fn new_pessimistic_prewrite_request( start_version: u64, lock_ttl: u64, for_update_ts: u64, -) -> kvrpcpb::PrewriteRequest where kvrpcpb::PrewriteRequest: KvRequest { +) -> kvrpcpb::PrewriteRequest +where + kvrpcpb::PrewriteRequest: KvRequest, +{ let len = mutations.len(); let mut req = new_prewrite_request(mutations, primary_lock, start_version, lock_ttl); req.set_for_update_ts(for_update_ts); @@ -343,13 +359,16 @@ pub fn new_commit_request( keys: Vec>, start_version: u64, commit_version: u64, -) -> kvrpcpb::CommitRequest where kvrpcpb::CommitRequest: KvRequest { -let mut req = kvrpcpb::CommitRequest::default(); -req.set_keys(keys); -req.set_start_version(start_version); -req.set_commit_version(commit_version); +) -> kvrpcpb::CommitRequest +where + kvrpcpb::CommitRequest: KvRequest, +{ + let mut req = kvrpcpb::CommitRequest::default(); + req.set_keys(keys); + req.set_start_version(start_version); + req.set_commit_version(commit_version); -req + req } impl KvRequest for kvrpcpb::CommitRequest { @@ -369,7 +388,10 @@ shardable_keys!(kvrpcpb::CommitRequest); pub fn new_batch_rollback_request( keys: Vec>, start_version: u64, -) -> kvrpcpb::BatchRollbackRequest where kvrpcpb::BatchRollbackRequest: KvRequest { +) -> kvrpcpb::BatchRollbackRequest +where + kvrpcpb::BatchRollbackRequest: KvRequest, +{ let mut req = kvrpcpb::BatchRollbackRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -395,7 +417,10 @@ pub fn new_pessimistic_rollback_request( keys: Vec>, start_version: u64, for_update_ts: u64, -) -> kvrpcpb::PessimisticRollbackRequest where kvrpcpb::PessimisticRollbackRequest: KvRequest { +) -> kvrpcpb::PessimisticRollbackRequest +where + kvrpcpb::PessimisticRollbackRequest: KvRequest, +{ let mut req = kvrpcpb::PessimisticRollbackRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -425,7 +450,10 @@ pub fn new_pessimistic_lock_request( lock_ttl: u64, for_update_ts: u64, need_value: bool, -) -> kvrpcpb::PessimisticLockRequest where kvrpcpb::PessimisticLockRequest: KvRequest { +) -> kvrpcpb::PessimisticLockRequest +where + kvrpcpb::PessimisticLockRequest: KvRequest, +{ let mut req = kvrpcpb::PessimisticLockRequest::default(); req.set_mutations(mutations); req.set_primary_lock(primary_lock); @@ -477,7 +505,7 @@ impl Shardable for kvrpcpb::PessimisticLockRequest { // PessimisticLockResponse returns values that preserves the order with keys in request, thus the // kvpair result should be produced by zipping the keys in request and the values in respponse. impl Merge>> -for CollectWithShard + for CollectWithShard { type Out = Vec; @@ -541,7 +569,10 @@ pub fn new_scan_lock_request( start_key: Vec, safepoint: u64, limit: u32, -) -> kvrpcpb::ScanLockRequest where kvrpcpb::ScanLockRequest: KvRequest { +) -> kvrpcpb::ScanLockRequest +where + kvrpcpb::ScanLockRequest: KvRequest, +{ let mut req = kvrpcpb::ScanLockRequest::default(); req.set_start_key(start_key); req.set_max_version(safepoint); @@ -593,7 +624,10 @@ pub fn new_heart_beat_request( start_ts: u64, primary_lock: Vec, ttl: u64, -) -> kvrpcpb::TxnHeartBeatRequest where kvrpcpb::TxnHeartBeatRequest: KvRequest { +) -> kvrpcpb::TxnHeartBeatRequest +where + kvrpcpb::TxnHeartBeatRequest: KvRequest, +{ let mut req = kvrpcpb::TxnHeartBeatRequest::default(); req.set_start_version(start_ts); req.set_primary_lock(primary_lock); @@ -819,8 +853,8 @@ mod tests { use tikv_client_proto::kvrpcpb; use crate::{ + request::{plan::Merge, CollectWithShard, ResponseWithShard}, KvPair, - request::{CollectWithShard, plan::Merge, ResponseWithShard}, }; #[tokio::test] diff --git a/src/transaction/snapshot.rs b/src/transaction/snapshot.rs index 08ba2981..a93ab0ba 100644 --- a/src/transaction/snapshot.rs +++ b/src/transaction/snapshot.rs @@ -1,11 +1,10 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use crate::{BoundRange, Key, KvPair, Result, Transaction, Value}; +use crate::{pd::PdClient, BoundRange, Key, KvPair, Result, Transaction, Value}; use derive_new::new; use futures::stream::BoxStream; use slog::Logger; use std::ops::RangeBounds; -use crate::pd::PdClient; /// A read-only transaction which reads at the given timestamp. /// diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index b3e4a9f0..20c090db 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -12,15 +12,15 @@ use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF}, - BoundRange, - Error, - Key, - KvPair, - pd::{PdClient, PdRpcClient}, request::{ - Collect, CollectError, CollectSingle, CollectWithShard, Plan, PlanBuilder, RetryOptions, - }, Result, timestamp::TimestampExt, transaction::{buffer::Buffer, lowering::*}, Value, + pd::{PdClient, PdRpcClient}, + request::{ + Collect, CollectError, CollectSingle, CollectWithShard, KvRequest, Plan, PlanBuilder, + RetryOptions, + }, + timestamp::TimestampExt, + transaction::{buffer::Buffer, lowering::*}, + BoundRange, Error, Key, KvPair, Result, Value, }; -use crate::request::KvRequest; /// An undo-able set of actions on the dataset. /// @@ -246,8 +246,8 @@ impl Transaction { /// ``` pub async fn batch_get( &mut self, - keys: impl IntoIterator>, - ) -> Result> { + keys: impl IntoIterator>, + ) -> Result> { debug!(self.logger, "invoking transactional batch_get request"); self.check_allow_operation().await?; let timestamp = self.timestamp.clone(); @@ -298,7 +298,7 @@ impl Transaction { /// ``` pub async fn batch_get_for_update( &mut self, - keys: impl IntoIterator>, + keys: impl IntoIterator>, ) -> Result> { debug!( self.logger, @@ -346,7 +346,7 @@ impl Transaction { &mut self, range: impl Into, limit: u32, - ) -> Result> { + ) -> Result> { debug!(self.logger, "invoking transactional scan request"); self.scan_inner(range, limit, false).await } @@ -382,7 +382,7 @@ impl Transaction { &mut self, range: impl Into, limit: u32, - ) -> Result> { + ) -> Result> { debug!(self.logger, "invoking transactional scan_keys request"); Ok(self .scan_inner(range, limit, true) @@ -457,7 +457,7 @@ impl Transaction { iter::once((key.clone(), kvrpcpb::Assertion::NotExist)), false, ) - .await?; + .await?; } self.buffer.insert(key, value.into()); Ok(()) @@ -517,7 +517,7 @@ impl Transaction { /// ``` pub async fn lock_keys( &mut self, - keys: impl IntoIterator>, + keys: impl IntoIterator>, ) -> Result<()> { debug!(self.logger, "invoking transactional lock_keys request"); self.check_allow_operation().await?; @@ -582,8 +582,8 @@ impl Transaction { self.start_instant, self.logger.new(o!("child" => 1)), ) - .commit() - .await; + .commit() + .await; if res.is_ok() { let mut status = self.status.write().await; @@ -639,8 +639,8 @@ impl Transaction { self.start_instant, self.logger.new(o!("child" => 1)), ) - .rollback() - .await; + .rollback() + .await; if res.is_ok() { let mut status = self.status.write().await; @@ -684,7 +684,7 @@ impl Transaction { range: impl Into, limit: u32, key_only: bool, - ) -> Result> { + ) -> Result> { self.check_allow_operation().await?; let timestamp = self.timestamp.clone(); let rpc = self.rpc.clone(); @@ -696,7 +696,9 @@ impl Transaction { limit, !key_only, move |new_range, new_limit| async move { - let request = new_scan_request::(new_range, timestamp, new_limit, key_only); + let request = new_scan_request::( + new_range, timestamp, new_limit, key_only, + ); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(retry_options.region_backoff) @@ -721,7 +723,7 @@ impl Transaction { /// Only valid for pessimistic transactions, panics if called on an optimistic transaction. async fn pessimistic_lock( &mut self, - keys: impl IntoIterator, + keys: impl IntoIterator, need_value: bool, ) -> Result> { debug!(self.logger, "acquiring pessimistic lock"); @@ -790,7 +792,7 @@ impl Transaction { /// Rollback pessimistic lock async fn pessimistic_lock_rollback( &mut self, - keys: impl Iterator, + keys: impl Iterator, start_version: Timestamp, for_update_ts: Timestamp, ) -> Result<()> { @@ -1164,13 +1166,15 @@ impl Committer { self.start_version.clone(), lock_ttl + elapsed, ), - TransactionKind::Pessimistic(for_update_ts) => new_pessimistic_prewrite_request::( - self.mutations.clone(), - primary_lock, - self.start_version.clone(), - lock_ttl + elapsed, - for_update_ts.clone(), - ), + TransactionKind::Pessimistic(for_update_ts) => { + new_pessimistic_prewrite_request::( + self.mutations.clone(), + primary_lock, + self.start_version.clone(), + lock_ttl + elapsed, + for_update_ts.clone(), + ) + } }; request.use_async_commit = self.options.async_commit; @@ -1289,7 +1293,11 @@ impl Committer { plan.execute().await?; } TransactionKind::Pessimistic(for_update_ts) => { - let req = new_pessimistic_rollback_request::(keys, self.start_version, for_update_ts); + let req = new_pessimistic_rollback_request::( + keys, + self.start_version, + for_update_ts, + ); let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) .retry_multi_region(self.options.retry_options.region_backoff) @@ -1336,8 +1344,8 @@ mod tests { any::Any, io, sync::{ - Arc, atomic::{AtomicUsize, Ordering}, + Arc, }, time::Duration, }; @@ -1349,8 +1357,8 @@ mod tests { use crate::{ mock::{MockKvClient, MockPdClient}, - Transaction, - transaction::HeartbeatOption, TransactionOptions, + transaction::HeartbeatOption, + Transaction, TransactionOptions, }; #[tokio::test] From 222908e2b908c1e52aa560911c22cc8b915fae33 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Wed, 22 Jun 2022 11:44:33 +0800 Subject: [PATCH 03/43] git fire: changing sig for PdRpcClient Signed-off-by: iosmanthus --- src/pd/client.rs | 14 +++++-------- src/raw/client.rs | 42 ++++++++++++++++++++++----------------- src/transaction/client.rs | 14 +++++++------ 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/pd/client.rs b/src/pd/client.rs index 814493bb..26dab20c 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -219,11 +219,9 @@ pub struct PdRpcClient>, kv_connect: KvC, kv_client_cache: Arc>>, - enable_codec: bool, region_cache: RegionCache>, logger: Logger, - // TODO: change to a real codec. - _phantom: PhantomData, + codec: C, } #[async_trait] @@ -280,7 +278,7 @@ impl PdRpcClient { pub async fn connect( pd_endpoints: &[String], config: Config, - enable_codec: bool, + codec: C, logger: Logger, ) -> Result> { PdRpcClient::new( @@ -289,7 +287,7 @@ impl PdRpcClient { |env, security_mgr| { RetryClient::connect(env, pd_endpoints, security_mgr, config.timeout) }, - enable_codec, + codec, logger, ) .await @@ -310,7 +308,7 @@ impl PdRpcClient { config: Config, kv_connect: MakeKvC, pd: MakePd, - enable_codec: bool, + codec: C, logger: Logger, ) -> Result> where @@ -340,11 +338,9 @@ impl PdRpcClient { pd: pd.clone(), kv_client_cache, kv_connect: kv_connect(env, security_mgr), - enable_codec, region_cache: RegionCache::new(pd), logger, - // TODO - _phantom: PhantomData, + codec }) } diff --git a/src/raw/client.rs b/src/raw/client.rs index 942272e5..3a3ed978 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -4,16 +4,17 @@ use core::ops::Range; use std::{marker::PhantomData, str::FromStr, sync::Arc, u32}; use slog::{Drain, Logger}; + use tikv_client_common::Error; use tikv_client_proto::metapb; use crate::{ + Backoff, backoff::DEFAULT_REGION_BACKOFF, + BoundRange, + ColumnFamily, config::Config, - pd::{PdClient, PdRpcClient}, - raw::lowering::*, - request::{request_codec::RequestCodec, Collect, CollectSingle, Plan}, - Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, + Key, KvPair, pd::{PdClient, PdRpcClient}, raw::lowering::*, request::{Collect, CollectSingle, Plan, request_codec::RequestCodec}, Result, Value, }; const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; @@ -53,9 +54,10 @@ impl Client> { /// ``` pub async fn new>( pd_endpoints: Vec, + codec: C, logger: Option, ) -> Result { - Self::new_with_config(pd_endpoints, Config::default(), logger).await + Self::new_with_config(pd_endpoints, Config::default(), codec, logger).await } /// Create a raw [`Client`] with a custom configuration, and connect to the TiKV cluster. @@ -83,6 +85,7 @@ impl Client> { pub async fn new_with_config>( pd_endpoints: Vec, config: Config, + codec: C, optional_logger: Option, ) -> Result { let logger = optional_logger.unwrap_or_else(|| { @@ -98,7 +101,7 @@ impl Client> { debug!(logger, "creating new raw client"); let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); let rpc = - Arc::new(PdRpcClient::connect(&pd_endpoints, config, false, logger.clone()).await?); + Arc::new(PdRpcClient::connect(&pd_endpoints, config, codec, logger.clone()).await?); Ok(Client { rpc, cf: None, @@ -212,7 +215,7 @@ impl Client { /// ``` pub async fn batch_get( &self, - keys: impl IntoIterator>, + keys: impl IntoIterator>, ) -> Result> { debug!(self.logger, "invoking raw batch_get request"); let request = @@ -274,7 +277,7 @@ impl Client { /// ``` pub async fn batch_put( &self, - pairs: impl IntoIterator>, + pairs: impl IntoIterator>, ) -> Result<()> { debug!(self.logger, "invoking raw batch_put request"); let request = new_raw_batch_put_request::( @@ -336,7 +339,7 @@ impl Client { /// let result: () = req.await.unwrap(); /// # }); /// ``` - pub async fn batch_delete(&self, keys: impl IntoIterator>) -> Result<()> { + pub async fn batch_delete(&self, keys: impl IntoIterator>) -> Result<()> { debug!(self.logger, "invoking raw batch_delete request"); self.assert_non_atomic()?; let request = @@ -462,7 +465,7 @@ impl Client { /// ``` pub async fn batch_scan( &self, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, each_limit: u32, ) -> Result> { debug!(self.logger, "invoking raw batch_scan request"); @@ -494,7 +497,7 @@ impl Client { /// ``` pub async fn batch_scan_keys( &self, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, each_limit: u32, ) -> Result> { debug!(self.logger, "invoking raw batch_scan_keys request"); @@ -544,7 +547,7 @@ impl Client { &self, copr_name: impl Into, copr_version_req: impl Into, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, request_builder: impl Fn(metapb::Region, Vec>) -> Vec + Send + Sync + 'static, ) -> Result, Vec>)>> { let copr_version_req = copr_version_req.into(); @@ -590,7 +593,7 @@ impl Client { async fn batch_scan_inner( &self, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, each_limit: u32, key_only: bool, ) -> Result> { @@ -625,13 +628,16 @@ impl Client { #[cfg(test)] mod tests { - use super::*; + use std::{any::Any, sync::Arc}; + + use tikv_client_proto::kvrpcpb; + use crate::{ mock::{MockKvClient, MockPdClient}, Result, }; - use std::{any::Any, sync::Arc}; - use tikv_client_proto::kvrpcpb; + + use super::*; #[tokio::test] async fn test_raw_coprocessor() -> Result<()> { @@ -687,13 +693,13 @@ mod tests { "2:[Key(0A)..Key(0F), Key(14)..Key(FAFA)]".to_string(), vec![ Key::from(vec![10])..Key::from(vec![15]), - Key::from(vec![20])..Key::from(vec![250, 250]) + Key::from(vec![20])..Key::from(vec![250, 250]), ] ), ( "3:[Key(FAFA)..Key()]".to_string(), vec![Key::from(vec![250, 250])..Key::from(vec![])] - ) + ), ] ); Ok(()) diff --git a/src/transaction/client.rs b/src/transaction/client.rs index c8464c11..aa56b47d 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -10,10 +10,10 @@ use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, pd::{PdClient, PdRpcClient}, - request::{request_codec::RequestCodec, Plan}, + request::{Plan, request_codec::RequestCodec}, + Result, timestamp::TimestampExt, transaction::{Snapshot, Transaction, TransactionOptions}, - Result, }; use super::{requests::new_scan_lock_request, resolve_locks}; @@ -44,8 +44,8 @@ pub struct Client { } impl Client -where - C: RequestCodec, + where + C: RequestCodec, { /// Create a transactional [`Client`] and connect to the TiKV cluster. /// @@ -66,10 +66,11 @@ where /// ``` pub async fn new>( pd_endpoints: Vec, + codec: C, logger: Option, ) -> Result> { // debug!(self.logger, "creating transactional client"); - Self::new_with_config(pd_endpoints, Config::default(), logger).await + Self::new_with_config(pd_endpoints, Config::default(), codec, logger).await } /// Create a transactional [`Client`] with a custom configuration, and connect to the TiKV cluster. @@ -97,6 +98,7 @@ where pub async fn new_with_config>( pd_endpoints: Vec, config: Config, + codec: C, optional_logger: Option, ) -> Result> { let logger = optional_logger.unwrap_or_else(|| { @@ -111,7 +113,7 @@ where }); debug!(logger, "creating new transactional client"); let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); - let pd = Arc::new(PdRpcClient::connect(&pd_endpoints, config, true, logger.clone()).await?); + let pd = Arc::new(PdRpcClient::connect(&pd_endpoints, config, codec, logger.clone()).await?); Ok(Client { pd, logger, From 605aed899d3572f9dc8c075ed6e953a1831c1fc5 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 23 Jun 2022 02:25:06 +0800 Subject: [PATCH 04/43] fix TxnApiV1 test Signed-off-by: iosmanthus --- examples/transaction.rs | 20 ++++--- src/lib.rs | 2 +- src/pd/client.rs | 32 ++-------- src/raw/client.rs | 22 +++---- src/raw/lowering.rs | 7 +-- src/raw/requests.rs | 5 +- src/region_cache.rs | 64 +++++++++++++------- src/request/mod.rs | 1 - src/request/plan_builder.rs | 2 +- src/request/request_codec.rs | 43 +++++++++++-- src/transaction/client.rs | 11 ++-- src/transaction/lock.rs | 9 ++- src/transaction/requests.rs | 106 +++++++++++++++++++-------------- src/transaction/transaction.rs | 5 +- 14 files changed, 190 insertions(+), 139 deletions(-) diff --git a/examples/transaction.rs b/examples/transaction.rs index 5d58a59b..acd6b836 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -3,9 +3,15 @@ mod common; use crate::common::parse_args; -use tikv_client::{BoundRange, Config, Key, KvPair, TransactionClient as Client, Value}; +use tikv_client::{ + request::request_codec::{RequestCodec, TxnApiV1}, + BoundRange, Config, Key, KvPair, TransactionClient as Client, Value, +}; -async fn puts(client: &Client, pairs: impl IntoIterator>) { +async fn puts( + client: &Client, + pairs: impl IntoIterator>, +) { let mut txn = client .begin_optimistic() .await @@ -17,7 +23,7 @@ async fn puts(client: &Client, pairs: impl IntoIterator txn.commit().await.expect("Could not commit transaction"); } -async fn get(client: &Client, key: Key) -> Option { +async fn get(client: &Client, key: Key) -> Option { let mut txn = client .begin_optimistic() .await @@ -29,7 +35,7 @@ async fn get(client: &Client, key: Key) -> Option { res } -async fn key_exists(client: &Client, key: Key) -> bool { +async fn key_exists(client: &Client, key: Key) -> bool { let mut txn = client .begin_optimistic() .await @@ -44,7 +50,7 @@ async fn key_exists(client: &Client, key: Key) -> bool { res } -async fn scan(client: &Client, range: impl Into, limit: u32) { +async fn scan(client: &Client, range: impl Into, limit: u32) { let mut txn = client .begin_optimistic() .await @@ -56,7 +62,7 @@ async fn scan(client: &Client, range: impl Into, limit: u32) { txn.commit().await.expect("Could not commit transaction"); } -async fn dels(client: &Client, keys: impl IntoIterator) { +async fn dels(client: &Client, keys: impl IntoIterator) { let mut txn = client .begin_optimistic() .await @@ -81,7 +87,7 @@ async fn main() { Config::default() }; - let txn = Client::new_with_config(args.pd, config, None) + let txn = Client::new_with_config(args.pd, config, TxnApiV1, None) .await .expect("Could not connect to tikv"); diff --git a/src/lib.rs b/src/lib.rs index 7e90b420..1261f44c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ //! # })} //! ``` -#![feature(specialization)] +#![feature(min_specialization)] #![feature(explicit_generic_args_with_impl_trait)] #[macro_use] pub mod request; diff --git a/src/pd/client.rs b/src/pd/client.rs index 26dab20c..b136910f 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -1,6 +1,6 @@ // Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. -use std::{collections::HashMap, marker::PhantomData, sync::Arc, thread}; +use std::{collections::HashMap, sync::Arc, thread}; use async_trait::async_trait; use futures::{prelude::*, stream::BoxStream}; @@ -14,7 +14,6 @@ use tikv_client_store::{KvClient, KvConnect, TikvConnect}; use crate::{ compat::stream_fn, - kv::codec, pd::{retry::RetryClientTrait, RetryClient}, region::{RegionId, RegionVerId, RegionWithLeader}, region_cache::RegionCache, @@ -198,14 +197,6 @@ pub trait PdClient: Send + Sync + 'static { .boxed() } - fn decode_region(mut region: RegionWithLeader, enable_codec: bool) -> Result { - if enable_codec { - codec::decode_bytes_in_place(region.region.mut_start_key(), false)?; - codec::decode_bytes_in_place(region.region.mut_end_key(), false)?; - } - Ok(region) - } - async fn update_leader(&self, ver_id: RegionVerId, leader: metapb::Peer) -> Result<()>; async fn invalidate_region_cache(&self, ver_id: RegionVerId); @@ -219,9 +210,8 @@ pub struct PdRpcClient>, kv_connect: KvC, kv_client_cache: Arc>>, - region_cache: RegionCache>, + region_cache: RegionCache>, logger: Logger, - codec: C, } #[async_trait] @@ -237,20 +227,11 @@ impl PdClient for PdRpc } async fn region_for_key(&self, key: &Key) -> Result { - let enable_codec = self.enable_codec; - let key = if enable_codec { - key.to_encoded() - } else { - key.clone() - }; - - let region = self.region_cache.get_region_by_key(&key).await?; - Self::decode_region(region, enable_codec) + self.region_cache.get_region_by_key(&key).await } async fn region_for_id(&self, id: RegionId) -> Result { - let region = self.region_cache.get_region_by_id(id).await?; - Self::decode_region(region, self.enable_codec) + self.region_cache.get_region_by_id(id).await } async fn get_timestamp(self: Arc) -> Result { @@ -270,7 +251,7 @@ impl PdClient for PdRpc } fn get_request_codec(&self) -> Self::RequestCodec { - todo!() + self.region_cache.get_request_codec() } } @@ -338,9 +319,8 @@ impl PdRpcClient { pd: pd.clone(), kv_client_cache, kv_connect: kv_connect(env, security_mgr), - region_cache: RegionCache::new(pd), + region_cache: RegionCache::new(codec, pd), logger, - codec }) } diff --git a/src/raw/client.rs b/src/raw/client.rs index 3a3ed978..03e854c1 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -9,12 +9,12 @@ use tikv_client_common::Error; use tikv_client_proto::metapb; use crate::{ - Backoff, backoff::DEFAULT_REGION_BACKOFF, - BoundRange, - ColumnFamily, config::Config, - Key, KvPair, pd::{PdClient, PdRpcClient}, raw::lowering::*, request::{Collect, CollectSingle, Plan, request_codec::RequestCodec}, Result, Value, + pd::{PdClient, PdRpcClient}, + raw::lowering::*, + request::{request_codec::RequestCodec, Collect, CollectSingle, Plan}, + Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; @@ -215,7 +215,7 @@ impl Client { /// ``` pub async fn batch_get( &self, - keys: impl IntoIterator>, + keys: impl IntoIterator>, ) -> Result> { debug!(self.logger, "invoking raw batch_get request"); let request = @@ -277,7 +277,7 @@ impl Client { /// ``` pub async fn batch_put( &self, - pairs: impl IntoIterator>, + pairs: impl IntoIterator>, ) -> Result<()> { debug!(self.logger, "invoking raw batch_put request"); let request = new_raw_batch_put_request::( @@ -339,7 +339,7 @@ impl Client { /// let result: () = req.await.unwrap(); /// # }); /// ``` - pub async fn batch_delete(&self, keys: impl IntoIterator>) -> Result<()> { + pub async fn batch_delete(&self, keys: impl IntoIterator>) -> Result<()> { debug!(self.logger, "invoking raw batch_delete request"); self.assert_non_atomic()?; let request = @@ -465,7 +465,7 @@ impl Client { /// ``` pub async fn batch_scan( &self, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, each_limit: u32, ) -> Result> { debug!(self.logger, "invoking raw batch_scan request"); @@ -497,7 +497,7 @@ impl Client { /// ``` pub async fn batch_scan_keys( &self, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, each_limit: u32, ) -> Result> { debug!(self.logger, "invoking raw batch_scan_keys request"); @@ -547,7 +547,7 @@ impl Client { &self, copr_name: impl Into, copr_version_req: impl Into, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, request_builder: impl Fn(metapb::Region, Vec>) -> Vec + Send + Sync + 'static, ) -> Result, Vec>)>> { let copr_version_req = copr_version_req.into(); @@ -593,7 +593,7 @@ impl Client { async fn batch_scan_inner( &self, - ranges: impl IntoIterator>, + ranges: impl IntoIterator>, each_limit: u32, key_only: bool, ) -> Result> { diff --git a/src/raw/lowering.rs b/src/raw/lowering.rs index 8f60daab..abef6709 100644 --- a/src/raw/lowering.rs +++ b/src/raw/lowering.rs @@ -4,14 +4,13 @@ //! types (i.e., the types from the client crate) and converts these to the types used in the //! generated protobuf code, then calls the low-level ctor functions in the requests module. -use std::{iter::Iterator, marker::PhantomData, ops::Range, sync::Arc}; +use std::{iter::Iterator, ops::Range, sync::Arc}; use tikv_client_proto::{kvrpcpb, metapb}; use crate::{ - raw::requests, - request::{request_codec::RequestCodec, KvRequest}, - BoundRange, ColumnFamily, Key, KvPair, Value, + raw::requests, request::request_codec::RequestCodec, BoundRange, ColumnFamily, Key, KvPair, + Value, }; pub fn new_raw_get_request( diff --git a/src/raw/requests.rs b/src/raw/requests.rs index c3c10fee..d786e3b5 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -13,9 +13,8 @@ use crate::{ collect_first, pd::PdClient, request::{ - plan::ResponseWithShard, - request_codec::{RawApiV1, RequestCodec}, - Collect, CollectSingle, DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, + plan::ResponseWithShard, request_codec::RequestCodec, Collect, CollectSingle, + DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, transaction::HasLocks, diff --git a/src/region_cache.rs b/src/region_cache.rs index bef93a5d..62963465 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -1,18 +1,22 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. -use crate::{ - pd::{RetryClient, RetryClientTrait}, - region::{RegionId, RegionVerId, RegionWithLeader, StoreId}, - Key, Result, -}; use std::{ collections::{BTreeMap, HashMap, HashSet}, sync::Arc, }; + +use tokio::sync::{Notify, RwLock}; + use tikv_client_common::Error; use tikv_client_pd::Cluster; use tikv_client_proto::metapb::{self, Store}; -use tokio::sync::{Notify, RwLock}; + +use crate::{ + pd::{RetryClient, RetryClientTrait}, + region::{RegionId, RegionVerId, RegionWithLeader, StoreId}, + request::request_codec::RequestCodec, + Key, Result, +}; const MAX_RETRY_WAITING_CONCURRENT_REQUEST: usize = 4; @@ -44,23 +48,25 @@ impl RegionCacheMap { } } -pub struct RegionCache> { +pub struct RegionCache> { region_cache: RwLock, store_cache: RwLock>, inner_client: Arc, + codec: C, } -impl RegionCache { - pub fn new(inner_client: Arc) -> RegionCache { +impl RegionCache { + pub fn new(codec: C, inner_client: Arc) -> Self { RegionCache { region_cache: RwLock::new(RegionCacheMap::new()), store_cache: RwLock::new(HashMap::new()), inner_client, + codec, } } } -impl RegionCache { +impl RegionCache { // Retrieve cache entry by key. If there's no entry, query PD and update cache. pub async fn get_region_by_key(&self, key: &Key) -> Result { let region_cache_guard = self.region_cache.read().await; @@ -126,9 +132,14 @@ impl RegionCache { /// Force read through (query from PD) and update cache pub async fn read_through_region_by_key(&self, key: Key) -> Result { - let region = self.inner_client.clone().get_region(key.into()).await?; - self.add_region(region.clone()).await; - Ok(region) + let mut r = self + .inner_client + .clone() + .get_region(self.codec.encode_pd_query(key).into()) + .await?; + r.region = self.codec.decode_region(r.region)?; + self.add_region(r.clone()).await; + Ok(r) } /// Force read through (query from PD) and update cache @@ -140,7 +151,8 @@ impl RegionCache { region_cache_guard.on_my_way_id.insert(id, notify.clone()); } - let region = self.inner_client.clone().get_region_by_id(id).await?; + let mut region = self.inner_client.clone().get_region_by_id(id).await?; + region.region = self.codec.decode_region(region.region)?; self.add_region(region.clone()).await; // notify others @@ -226,17 +238,14 @@ impl RegionCache { cache.key_to_ver_id.remove(&start_key); } } + + pub fn get_request_codec(&self) -> C { + self.codec.clone() + } } #[cfg(test)] mod test { - use super::RegionCache; - use crate::{ - pd::RetryClientTrait, - region::{RegionId, RegionWithLeader}, - Key, Result, - }; - use async_trait::async_trait; use std::{ collections::{BTreeMap, HashMap, HashSet}, sync::{ @@ -244,9 +253,20 @@ mod test { Arc, }, }; + + use async_trait::async_trait; + use tokio::sync::Mutex; + use tikv_client_common::Error; use tikv_client_proto::metapb; - use tokio::sync::Mutex; + + use crate::{ + pd::RetryClientTrait, + region::{RegionId, RegionWithLeader}, + Key, Result, + }; + + use super::RegionCache; #[derive(Default)] struct MockRetryClient { diff --git a/src/request/mod.rs b/src/request/mod.rs index 461ff6c7..990a3b71 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -9,7 +9,6 @@ use tikv_client_store::{HasKeyErrors, HasRegionError, Request}; use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF, PESSIMISTIC_BACKOFF}, - pd::PdClient, transaction::HasLocks, }; diff --git a/src/request/plan_builder.rs b/src/request/plan_builder.rs index c354ed57..72aa8d4e 100644 --- a/src/request/plan_builder.rs +++ b/src/request/plan_builder.rs @@ -45,7 +45,7 @@ where PdC: PdClient, { pub fn new(pd_client: Arc, request: Req) -> Self { - let codec = pd_client.get_request_codec().clone(); + let codec = pd_client.get_request_codec(); PlanBuilder { pd_client, plan: Dispatch::new(request, None, codec), diff --git a/src/request/request_codec.rs b/src/request/request_codec.rs index 463b3406..64ed4479 100644 --- a/src/request/request_codec.rs +++ b/src/request/request_codec.rs @@ -1,23 +1,44 @@ use tikv_client_proto::metapb::Region; -use crate::Result; +use crate::{kv::codec::decode_bytes_in_place, Key, Result}; + +#[macro_export] +macro_rules! plain_request { + ($req: ident, $codec: ident) => { + if $codec.is_plain() { + return ::std::borrow::Cow::Borrowed($req); + } + }; +} + +#[macro_export] +macro_rules! plain_response { + ($resp: ident, $codec: ident) => { + if $codec.is_plain() { + return Ok($resp); + } + }; +} pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { - fn encode_key(&self, key: Vec) -> Vec { + fn encode_key(&self, key: Key) -> Key { key } - fn decode_key(&self, key: Vec) -> Result> { + fn decode_key(&self, key: Key) -> Result { Ok(key) } - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + fn encode_range(&self, start: Key, end: Key) -> (Key, Key) { (start, end) } - fn encode_pd_query(&self, key: Vec) -> Vec { + fn encode_pd_query(&self, key: Key) -> Key { key } fn decode_region(&self, region: Region) -> Result { Ok(region) } + fn is_plain(&self) -> bool { + true + } } #[derive(Clone)] @@ -28,4 +49,14 @@ impl RequestCodec for RawApiV1 {} #[derive(Clone)] pub struct TxnApiV1; -impl RequestCodec for TxnApiV1 {} +impl RequestCodec for TxnApiV1 { + fn encode_pd_query(&self, key: Key) -> Key { + key.to_encoded() + } + + fn decode_region(&self, mut region: Region) -> Result { + decode_bytes_in_place(region.mut_start_key(), false)?; + decode_bytes_in_place(region.mut_end_key(), false)?; + Ok(region) + } +} diff --git a/src/transaction/client.rs b/src/transaction/client.rs index aa56b47d..0a96ad1b 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -10,10 +10,10 @@ use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, pd::{PdClient, PdRpcClient}, - request::{Plan, request_codec::RequestCodec}, - Result, + request::{request_codec::RequestCodec, Plan}, timestamp::TimestampExt, transaction::{Snapshot, Transaction, TransactionOptions}, + Result, }; use super::{requests::new_scan_lock_request, resolve_locks}; @@ -44,8 +44,8 @@ pub struct Client { } impl Client - where - C: RequestCodec, +where + C: RequestCodec, { /// Create a transactional [`Client`] and connect to the TiKV cluster. /// @@ -113,7 +113,8 @@ impl Client }); debug!(logger, "creating new transactional client"); let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); - let pd = Arc::new(PdRpcClient::connect(&pd_endpoints, config, codec, logger.clone()).await?); + let pd = + Arc::new(PdRpcClient::connect(&pd_endpoints, config, codec, logger.clone()).await?); Ok(Client { pd, logger, diff --git a/src/transaction/lock.rs b/src/transaction/lock.rs index bbd9667a..06dc0ee4 100644 --- a/src/transaction/lock.rs +++ b/src/transaction/lock.rs @@ -4,7 +4,7 @@ use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, pd::PdClient, region::RegionVerId, - request::{request_codec::RequestCodec, CollectSingle, Plan}, + request::{CollectSingle, Plan}, timestamp::TimestampExt, transaction::requests, Error, Result, @@ -144,11 +144,14 @@ pub trait HasLocks { #[cfg(test)] mod tests { - use super::*; - use crate::mock::{MockKvClient, MockPdClient}; use std::any::Any; + use tikv_client_proto::errorpb; + use crate::mock::{MockKvClient, MockPdClient}; + + use super::*; + #[tokio::test] async fn test_resolve_lock_with_retry() { // Test resolve lock within retry limit diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 619267a2..65dc8aa2 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -9,15 +9,14 @@ use tikv_client_proto::{ kvrpcpb::{self, TxnHeartBeatResponse}, pdpb::Timestamp, }; -use tikv_client_store::HasRegionErrors; use crate::{ collect_first, pd::PdClient, + plain_request, plain_response, request::{ - request_codec::{RequestCodec, TxnApiV1}, - Collect, CollectSingle, CollectWithShard, DefaultProcessor, KvRequest, Merge, Process, - ResponseWithShard, Shardable, SingleKey, + request_codec::RequestCodec, Collect, CollectSingle, CollectWithShard, DefaultProcessor, + KvRequest, Merge, Process, ResponseWithShard, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, timestamp::TimestampExt, @@ -80,11 +79,13 @@ where impl KvRequest for kvrpcpb::GetRequest { type Response = kvrpcpb::GetResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -126,11 +127,13 @@ where impl KvRequest for kvrpcpb::BatchGetRequest { type Response = kvrpcpb::BatchGetResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -170,11 +173,13 @@ where impl KvRequest for kvrpcpb::ScanRequest { type Response = kvrpcpb::ScanResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -210,26 +215,16 @@ where // region without keys. So it's not Shardable. And we don't automatically retry // on its region errors (in the Plan level). The region error must be manually // handled (in the upper level). -impl KvRequest for kvrpcpb::ResolveLockRequest { - type Response = kvrpcpb::ResolveLockResponse; - - fn encode_request(&self, _codec: &TxnApiV1) -> Cow { - todo!() - } - - fn decode_response(&self, _codec: &TxnApiV1, _resp: Self::Response) -> Result { - todo!() - } -} - impl KvRequest for kvrpcpb::ResolveLockRequest { - default type Response = kvrpcpb::ResolveLockResponse; + type Response = kvrpcpb::ResolveLockResponse; - default fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - default fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -251,11 +246,13 @@ where impl KvRequest for kvrpcpb::CleanupRequest { type Response = kvrpcpb::CleanupResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -316,11 +313,13 @@ where impl KvRequest for kvrpcpb::PrewriteRequest { type Response = kvrpcpb::PrewriteResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -374,11 +373,13 @@ where impl KvRequest for kvrpcpb::CommitRequest { type Response = kvrpcpb::CommitResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -402,11 +403,13 @@ where impl KvRequest for kvrpcpb::BatchRollbackRequest { type Response = kvrpcpb::BatchRollbackResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -432,11 +435,13 @@ where impl KvRequest for kvrpcpb::PessimisticRollbackRequest { type Response = kvrpcpb::PessimisticRollbackResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -474,11 +479,13 @@ where impl KvRequest for kvrpcpb::PessimisticLockRequest { type Response = kvrpcpb::PessimisticLockResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -583,11 +590,13 @@ where impl KvRequest for kvrpcpb::ScanLockRequest { type Response = kvrpcpb::ScanLockResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -637,12 +646,13 @@ where impl KvRequest for kvrpcpb::TxnHeartBeatRequest { type Response = kvrpcpb::TxnHeartBeatResponse; - - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -684,11 +694,13 @@ impl Process for DefaultProcessor { impl KvRequest for kvrpcpb::CheckTxnStatusRequest { type Response = kvrpcpb::CheckTxnStatusResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -761,11 +773,13 @@ impl From<(u64, u64, Option)> for TransactionStatusKind { impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { type Response = kvrpcpb::CheckSecondaryLocksResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 20c090db..1080bcb4 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -12,10 +12,9 @@ use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF}, - pd::{PdClient, PdRpcClient}, + pd::PdClient, request::{ - Collect, CollectError, CollectSingle, CollectWithShard, KvRequest, Plan, PlanBuilder, - RetryOptions, + Collect, CollectError, CollectSingle, CollectWithShard, Plan, PlanBuilder, RetryOptions, }, timestamp::TimestampExt, transaction::{buffer::Buffer, lowering::*}, From 9164cf00960e7467a1586e620b60122b635c1da5 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 23 Jun 2022 17:12:30 +0800 Subject: [PATCH 05/43] fix all tests for API v1 Signed-off-by: iosmanthus --- examples/pessimistic.rs | 7 +++-- examples/raw.rs | 7 +++-- examples/transaction.rs | 15 ++++------ src/lib.rs | 10 ++++--- src/mock.rs | 10 +++++-- src/raw/client.rs | 53 +++++++++++++++++++++++----------- src/raw/requests.rs | 8 ----- src/region_cache.rs | 13 +++++---- src/request/mod.rs | 28 +++++++++++++++--- src/request/request_codec.rs | 7 +++++ src/transaction/client.rs | 21 +++++++++----- src/transaction/transaction.rs | 42 ++++++++++++++++++--------- tests/mock_tikv_tests.rs | 4 +-- 13 files changed, 148 insertions(+), 77 deletions(-) diff --git a/examples/pessimistic.rs b/examples/pessimistic.rs index bfdb9e27..360e4746 100644 --- a/examples/pessimistic.rs +++ b/examples/pessimistic.rs @@ -3,7 +3,10 @@ mod common; use crate::common::parse_args; -use tikv_client::{Config, Key, TransactionClient as Client, TransactionOptions, Value}; +use tikv_client::{ + request::request_codec::TxnApiV1, Config, Key, TransactionClient as Client, TransactionOptions, + Value, +}; #[tokio::main] async fn main() { @@ -20,7 +23,7 @@ async fn main() { }; // init - let client = Client::new_with_config(args.pd, config, None) + let client = Client::new_with_config(args.pd, config, TxnApiV1, None) .await .expect("Could not connect to tikv"); diff --git a/examples/raw.rs b/examples/raw.rs index aefd7313..cc3ea3b1 100644 --- a/examples/raw.rs +++ b/examples/raw.rs @@ -5,7 +5,10 @@ mod common; use crate::common::parse_args; -use tikv_client::{Config, IntoOwnedRange, Key, KvPair, RawClient as Client, Result, Value}; +use tikv_client::{ + request::request_codec::RawApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, + Result, Value, +}; const KEY: &str = "TiKV"; const VALUE: &str = "Rust"; @@ -26,7 +29,7 @@ async fn main() -> Result<()> { // When we first create a client we receive a `Connect` structure which must be resolved before // the client is actually connected and usable. - let client = Client::new_with_config(args.pd, config, None).await?; + let client = Client::new_with_config(args.pd, config, RawApiV1, None).await?; // Requests are created from the connected client. These calls return structures which // implement `Future`. This means the `Future` must be resolved before the action ever takes diff --git a/examples/transaction.rs b/examples/transaction.rs index acd6b836..ae8cef18 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -4,14 +4,11 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::request_codec::{RequestCodec, TxnApiV1}, + request::request_codec::{TxnApiV1, TxnCodec}, BoundRange, Config, Key, KvPair, TransactionClient as Client, Value, }; -async fn puts( - client: &Client, - pairs: impl IntoIterator>, -) { +async fn puts(client: &Client, pairs: impl IntoIterator>) { let mut txn = client .begin_optimistic() .await @@ -23,7 +20,7 @@ async fn puts( txn.commit().await.expect("Could not commit transaction"); } -async fn get(client: &Client, key: Key) -> Option { +async fn get(client: &Client, key: Key) -> Option { let mut txn = client .begin_optimistic() .await @@ -35,7 +32,7 @@ async fn get(client: &Client, key: Key) -> Option { res } -async fn key_exists(client: &Client, key: Key) -> bool { +async fn key_exists(client: &Client, key: Key) -> bool { let mut txn = client .begin_optimistic() .await @@ -50,7 +47,7 @@ async fn key_exists(client: &Client, key: Key) -> bool { res } -async fn scan(client: &Client, range: impl Into, limit: u32) { +async fn scan(client: &Client, range: impl Into, limit: u32) { let mut txn = client .begin_optimistic() .await @@ -62,7 +59,7 @@ async fn scan(client: &Client, range: impl Into, txn.commit().await.expect("Could not commit transaction"); } -async fn dels(client: &Client, keys: impl IntoIterator) { +async fn dels(client: &Client, keys: impl IntoIterator) { let mut txn = client .begin_optimistic() .await diff --git a/src/lib.rs b/src/lib.rs index 1261f44c..6e8734ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,8 +66,9 @@ //! # use tikv_client::{RawClient, Result}; //! # use futures::prelude::*; //! # fn main() -> Result<()> { -//! # futures::executor::block_on(async { -//! let client = RawClient::new(vec!["127.0.0.1:2379"], None).await?; +//! # use tikv_client::request::request_codec::RawApiV1; +//! futures::executor::block_on(async { +//! let client = RawClient::new(vec!["127.0.0.1:2379"], RawApiV1, None).await?; //! client.put("key".to_owned(), "value".to_owned()).await?; //! let value = client.get("key".to_owned()).await?; //! # Ok(()) @@ -80,8 +81,9 @@ //! # use tikv_client::{TransactionClient, Result}; //! # use futures::prelude::*; //! # fn main() -> Result<()> { -//! # futures::executor::block_on(async { -//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], None).await?; +//! # use tikv_client::request::request_codec::TxnApiV1; +//! futures::executor::block_on(async { +//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], TxnApiV1, None).await?; //! let mut txn = txn_client.begin_optimistic().await?; //! txn.put("key".to_owned(), "value".to_owned()).await?; //! let value = txn.get("key".to_owned()).await?; diff --git a/src/mock.rs b/src/mock.rs index 02a0bef9..b05d9da4 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -8,6 +8,7 @@ use crate::{ pd::{PdClient, PdRpcClient, RetryClient}, region::{RegionId, RegionWithLeader}, + request::request_codec::RawApiV1, store::RegionStore, Config, Error, Key, Result, Timestamp, }; @@ -20,7 +21,7 @@ use tikv_client_store::{KvClient, KvConnect, Request}; /// Create a `PdRpcClient` with it's internals replaced with mocks so that the /// client can be tested without doing any RPC calls. -pub async fn pd_rpc_client() -> PdRpcClient { +pub async fn pd_rpc_client() -> PdRpcClient { let config = Config::default(); let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); let logger = Logger::root( @@ -41,7 +42,7 @@ pub async fn pd_rpc_client() -> PdRpcClient { MockCluster, )) }, - false, + RawApiV1, logger, ) .await @@ -153,6 +154,7 @@ impl MockPdClient { #[async_trait] impl PdClient for MockPdClient { type KvClient = MockKvClient; + type RequestCodec = RawApiV1; async fn map_region_to_store(self: Arc, region: RegionWithLeader) -> Result { Ok(RegionStore::new(region, Arc::new(self.client.clone()))) @@ -197,4 +199,8 @@ impl PdClient for MockPdClient { } async fn invalidate_region_cache(&self, _ver_id: crate::region::RegionVerId) {} + + fn get_request_codec(&self) -> Self::RequestCodec { + RawApiV1 + } } diff --git a/src/raw/client.rs b/src/raw/client.rs index 03e854c1..cf90b620 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -13,7 +13,7 @@ use crate::{ config::Config, pd::{PdClient, PdRpcClient}, raw::lowering::*, - request::{request_codec::RequestCodec, Collect, CollectSingle, Plan}, + request::{request_codec::RawCodec, Collect, CollectSingle, Plan}, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; @@ -33,10 +33,10 @@ pub struct Client> { /// Whether to use the [`atomic mode`](Client::with_atomic_for_cas). atomic: bool, logger: Logger, - _phantom: std::marker::PhantomData, + _phantom: PhantomData, } -impl Client> { +impl Client> { /// Create a raw [`Client`] and connect to the TiKV cluster. /// /// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for @@ -48,8 +48,11 @@ impl Client> { /// ```rust,no_run /// # use tikv_client::RawClient; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None) + /// .await + /// .unwrap(); /// # }); /// ``` pub async fn new>( @@ -72,10 +75,12 @@ impl Client> { /// # use tikv_client::{Config, RawClient}; /// # use futures::prelude::*; /// # use std::time::Duration; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { /// let client = RawClient::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), + /// RawApiV1, /// None, /// ) /// .await @@ -126,8 +131,9 @@ impl Client> { /// # use tikv_client::{Config, RawClient, ColumnFamily}; /// # use futures::prelude::*; /// # use std::convert::TryInto; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], None) + /// let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None) /// .await /// .unwrap() /// .with_cf(ColumnFamily::Write); @@ -165,7 +171,7 @@ impl Client> { } } -impl Client { +impl Client { /// Create a new 'get' request. /// /// Once resolved this request will result in the fetching of the value associated with the @@ -177,8 +183,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Value, Config, RawClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.get(key); /// let result: Option = req.await.unwrap(); @@ -206,8 +213,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{KvPair, Config, RawClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_get(keys); /// let result: Vec = req.await.unwrap(); @@ -237,8 +245,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, RawClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let val = "TiKV".to_owned(); /// let req = client.put(key, val); @@ -266,8 +275,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Result, KvPair, Key, Value, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let kvpair1 = ("PD".to_owned(), "Go".to_owned()); /// let kvpair2 = ("TiKV".to_owned(), "Rust".to_owned()); /// let iterable = vec![kvpair1, kvpair2]; @@ -303,8 +313,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.delete(key); /// let result: () = req.await.unwrap(); @@ -332,8 +343,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Config, RawClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_delete(keys); /// let result: () = req.await.unwrap(); @@ -360,8 +372,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.delete_range(inclusive_range.into_owned()); /// let result: () = req.await.unwrap(); @@ -399,8 +412,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{KvPair, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -423,8 +437,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan_keys(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -454,8 +469,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; @@ -486,8 +502,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::RawApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; @@ -634,6 +651,7 @@ mod tests { use crate::{ mock::{MockKvClient, MockPdClient}, + request::request_codec::RawApiV1, Result, }; @@ -669,6 +687,7 @@ mod tests { cf: Some(ColumnFamily::Default), atomic: false, logger, + _phantom: PhantomData::, }; let resps = client .coprocessor( diff --git a/src/raw/requests.rs b/src/raw/requests.rs index d786e3b5..fa8b80cd 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -496,14 +496,6 @@ impl Request for RawCoprocessorRequest { impl KvRequest for RawCoprocessorRequest { type Response = kvrpcpb::RawCoprocessorResponse; - - fn encode_request(&self, _codec: &C) -> Cow { - todo!() - } - - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { - todo!() - } } impl Shardable for RawCoprocessorRequest { diff --git a/src/region_cache.rs b/src/region_cache.rs index 62963465..c2b8eea7 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -263,6 +263,7 @@ mod test { use crate::{ pd::RetryClientTrait, region::{RegionId, RegionWithLeader}, + request::request_codec::{RawApiV1, RequestCodec}, Key, Result, }; @@ -329,7 +330,7 @@ mod test { #[tokio::test] async fn cache_is_used() -> Result<()> { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(retry_client.clone()); + let cache = RegionCache::new(RawApiV1, retry_client.clone()); retry_client.regions.lock().await.insert( 1, RegionWithLeader { @@ -399,7 +400,7 @@ mod test { #[tokio::test] async fn test_add_disjoint_regions() { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(retry_client.clone()); + let cache = RegionCache::new(RawApiV1, retry_client.clone()); let region1 = region(1, vec![], vec![10]); let region2 = region(2, vec![10], vec![20]); let region3 = region(3, vec![30], vec![]); @@ -418,7 +419,7 @@ mod test { #[tokio::test] async fn test_add_intersecting_regions() { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(retry_client.clone()); + let cache = RegionCache::new(RawApiV1, retry_client.clone()); cache.add_region(region(1, vec![], vec![10])).await; cache.add_region(region(2, vec![10], vec![20])).await; @@ -456,7 +457,7 @@ mod test { #[tokio::test] async fn test_get_region_by_key() -> Result<()> { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(retry_client.clone()); + let cache = RegionCache::new(RawApiV1, retry_client.clone()); let region1 = region(1, vec![], vec![10]); let region2 = region(2, vec![10], vec![20]); @@ -486,8 +487,8 @@ mod test { } // a helper function to assert the cache is in expected state - async fn assert( - cache: &RegionCache, + async fn assert( + cache: &RegionCache, expected_cache: &BTreeMap, ) { let guard = cache.region_cache.read().await; diff --git a/src/request/mod.rs b/src/request/mod.rs index 990a3b71..a254f9cc 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -33,8 +33,12 @@ pub mod request_codec; pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { /// The expected response to the request. type Response: HasKeyErrors + HasLocks + HasRegionError + Clone + Send + 'static; - fn encode_request(&self, _codec: &C) -> Cow; - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> crate::Result; + fn encode_request(&self, _codec: &C) -> Cow { + Cow::Borrowed(self) + } + fn decode_response(&self, _codec: &C, resp: Self::Response) -> crate::Result { + Ok(resp) + } } #[derive(Clone, Debug, new, Eq, PartialEq)] @@ -83,6 +87,10 @@ mod test { use crate::{ mock::{MockKvClient, MockPdClient}, + request::{ + request_codec::{RequestCodec, TxnApiV1}, + KvRequest, + }, store::store_stream_for_keys, transaction::lowering::new_commit_request, Error, Key, Result, @@ -134,8 +142,16 @@ mod test { } #[async_trait] - impl KvRequest for MockKvRequest { + impl KvRequest for MockKvRequest { type Response = MockRpcResponse; + + fn encode_request(&self, _codec: &C) -> Cow { + Cow::Borrowed(self) + } + + fn decode_response(&self, _codec: &C, resp: Self::Response) -> Result { + Ok(resp) + } } impl Shardable for MockKvRequest { @@ -200,7 +216,11 @@ mod test { ))); let key: Key = "key".to_owned().into(); - let req = new_commit_request(iter::once(key), Timestamp::default(), Timestamp::default()); + let req = new_commit_request::( + iter::once(key), + Timestamp::default(), + Timestamp::default(), + ); // does not extract error let plan = crate::request::PlanBuilder::new(pd_client.clone(), req.clone()) diff --git a/src/request/request_codec.rs b/src/request/request_codec.rs index 64ed4479..892c820d 100644 --- a/src/request/request_codec.rs +++ b/src/request/request_codec.rs @@ -57,6 +57,13 @@ impl RequestCodec for TxnApiV1 { fn decode_region(&self, mut region: Region) -> Result { decode_bytes_in_place(region.mut_start_key(), false)?; decode_bytes_in_place(region.mut_end_key(), false)?; + Ok(region) } } + +pub trait RawCodec: RequestCodec {} +pub trait TxnCodec: RequestCodec {} + +impl RawCodec for RawApiV1 {} +impl TxnCodec for TxnApiV1 {} diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 0a96ad1b..28bc45b9 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -10,7 +10,7 @@ use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, pd::{PdClient, PdRpcClient}, - request::{request_codec::RequestCodec, Plan}, + request::{request_codec::TxnCodec, Plan}, timestamp::TimestampExt, transaction::{Snapshot, Transaction, TransactionOptions}, Result, @@ -45,7 +45,7 @@ pub struct Client { impl Client where - C: RequestCodec, + C: TxnCodec, { /// Create a transactional [`Client`] and connect to the TiKV cluster. /// @@ -58,8 +58,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await /// .unwrap(); /// # }); @@ -85,10 +86,12 @@ where /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::time::Duration; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), + /// TxnApiV1, /// None, /// ) /// .await @@ -135,8 +138,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await /// .unwrap(); /// let mut transaction = client.begin_optimistic().await.unwrap(); @@ -160,8 +164,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await /// .unwrap(); /// let mut transaction = client.begin_pessimistic().await.unwrap(); @@ -182,8 +187,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient, TransactionOptions}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await /// .unwrap(); /// let mut transaction = client @@ -221,8 +227,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await /// .unwrap(); /// let timestamp = client.current_timestamp().await.unwrap(); diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 1080bcb4..a03ef0ad 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -51,8 +51,9 @@ use crate::{ /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; +/// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { -/// let client = TransactionClient::new(vec!["192.168.0.100"], None) +/// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await /// .unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -107,8 +108,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Option = txn.get(key).await.unwrap(); @@ -168,8 +170,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Value = txn.get_for_update(key).await.unwrap().unwrap(); @@ -202,8 +205,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let exists = txn.key_exists("k1".to_owned()).await.unwrap(); /// txn.commit().await.unwrap(); @@ -229,8 +233,9 @@ impl Transaction { /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let result: HashMap = txn @@ -282,8 +287,9 @@ impl Transaction { /// # use tikv_client::{Key, Value, Config, TransactionClient, KvPair}; /// # use futures::prelude::*; /// # use std::collections::HashMap; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let keys = vec!["foo".to_owned(), "bar".to_owned()]; /// let result: Vec = txn @@ -327,8 +333,9 @@ impl Transaction { /// # use tikv_client::{Key, KvPair, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -363,8 +370,9 @@ impl Transaction { /// # use tikv_client::{Key, KvPair, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -404,8 +412,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -435,8 +444,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -471,8 +481,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// txn.delete(key); @@ -506,8 +517,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// txn.lock_keys(vec!["TiKV".to_owned(), "Rust".to_owned()]); /// // ... Do some actions. @@ -542,8 +554,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, Timestamp, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// let result: Timestamp = txn.commit().await.unwrap().unwrap(); @@ -600,8 +613,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, Timestamp, TransactionClient}; /// # use futures::prelude::*; + /// use tikv_client::request::request_codec::TxnApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// txn.rollback().await.unwrap(); diff --git a/tests/mock_tikv_tests.rs b/tests/mock_tikv_tests.rs index f047feb0..5d8963f5 100644 --- a/tests/mock_tikv_tests.rs +++ b/tests/mock_tikv_tests.rs @@ -4,7 +4,7 @@ mod test { use log::debug; use mock_tikv::{start_mock_pd_server, start_mock_tikv_server, MOCK_PD_PORT}; use simple_logger::SimpleLogger; - use tikv_client::{KvPair, RawClient}; + use tikv_client::{request::request_codec::RawApiV1, KvPair, RawClient}; #[tokio::test] #[ignore] @@ -15,7 +15,7 @@ mod test { let mut tikv_server = start_mock_tikv_server(); let _pd_server = start_mock_pd_server(); - let client = RawClient::new(vec![format!("localhost:{}", MOCK_PD_PORT)], None) + let client = RawClient::new(vec![format!("localhost:{}", MOCK_PD_PORT)], RawApiV1, None) .await .unwrap(); From 7668c370bd898591286e4957fbf4a3d8ce7b9b64 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 23 Jun 2022 17:48:26 +0800 Subject: [PATCH 06/43] fix integration tests for API v1 Signed-off-by: iosmanthus --- src/lib.rs | 2 ++ src/raw/requests.rs | 61 +++++++++++++++++++++++++------------- tests/common/mod.rs | 12 ++++++-- tests/failpoint_tests.rs | 7 +++-- tests/integration_tests.rs | 61 ++++++++++++++++++++++---------------- 5 files changed, 93 insertions(+), 50 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6e8734ed..3005daaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,6 +128,8 @@ pub use crate::backoff::Backoff; #[doc(inline)] pub use crate::kv::{BoundRange, IntoOwnedRange, Key, KvPair, Value}; #[doc(inline)] +pub use crate::pd::PdClient; +#[doc(inline)] pub use crate::raw::{lowering as raw_lowering, Client as RawClient, ColumnFamily}; #[doc(inline)] pub use crate::request::RetryOptions; diff --git a/src/raw/requests.rs b/src/raw/requests.rs index fa8b80cd..b3329d76 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -12,6 +12,7 @@ use super::RawRpcRequest; use crate::{ collect_first, pd::PdClient, + plain_request, plain_response, request::{ plan::ResponseWithShard, request_codec::RequestCodec, Collect, CollectSingle, DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, @@ -39,11 +40,13 @@ where impl KvRequest for kvrpcpb::RawGetRequest { type Response = kvrpcpb::RawGetResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -87,11 +90,13 @@ where impl KvRequest for kvrpcpb::RawBatchGetRequest { type Response = kvrpcpb::RawBatchGetResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -130,11 +135,13 @@ where impl KvRequest for kvrpcpb::RawPutRequest { type Response = kvrpcpb::RawPutResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -166,11 +173,13 @@ where impl KvRequest for kvrpcpb::RawBatchPutRequest { type Response = kvrpcpb::RawBatchPutResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -216,11 +225,13 @@ where impl KvRequest for kvrpcpb::RawDeleteRequest { type Response = kvrpcpb::RawDeleteResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -250,11 +261,13 @@ where impl KvRequest for kvrpcpb::RawBatchDeleteRequest { type Response = kvrpcpb::RawBatchDeleteResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -280,11 +293,13 @@ where impl KvRequest for kvrpcpb::RawDeleteRangeRequest { type Response = kvrpcpb::RawDeleteRangeResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -314,11 +329,13 @@ where impl KvRequest for kvrpcpb::RawScanRequest { type Response = kvrpcpb::RawScanResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -357,11 +374,13 @@ where impl KvRequest for kvrpcpb::RawBatchScanRequest { type Response = kvrpcpb::RawBatchScanResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } @@ -417,11 +436,13 @@ where impl KvRequest for kvrpcpb::RawCasRequest { type Response = kvrpcpb::RawCasResponse; - fn encode_request(&self, _codec: &C) -> Cow { + fn encode_request(&self, codec: &C) -> Cow { + plain_request!(self, codec); todo!() } - fn decode_response(&self, _codec: &C, _resp: Self::Response) -> Result { + fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { + plain_response!(resp, codec); todo!() } } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index d666be77..d6594761 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -3,7 +3,10 @@ mod ctl; use futures_timer::Delay; use log::{info, warn}; use std::{env, time::Duration}; -use tikv_client::{ColumnFamily, Key, RawClient, Result, TransactionClient}; +use tikv_client::{ + request::request_codec::{RawApiV1, TxnApiV1}, + ColumnFamily, Key, RawClient, Result, TransactionClient, +}; const ENV_PD_ADDRS: &str = "PD_ADDRS"; const ENV_ENABLE_MULIT_REGION: &str = "MULTI_REGION"; @@ -19,7 +22,10 @@ pub async fn clear_tikv() { // DEFAULT_REGION_BACKOFF is not long enough for CI environment. So set a longer backoff. let backoff = tikv_client::Backoff::no_jitter_backoff(100, 10000, 10); for cf in cfs { - let raw_client = RawClient::new(pd_addrs(), None).await.unwrap().with_cf(cf); + let raw_client = RawClient::new(pd_addrs(), RawApiV1, None) + .await + .unwrap() + .with_cf(cf); raw_client .delete_range_opt(vec![].., backoff.clone()) .await @@ -60,7 +66,7 @@ async fn ensure_region_split( // 1. write plenty transactional keys // 2. wait until regions split - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut txn = client.begin_optimistic().await?; for key in keys.into_iter() { txn.put(key.into(), vec![0, 0, 0, 0]).await?; diff --git a/tests/failpoint_tests.rs b/tests/failpoint_tests.rs index 80519c27..cc926d17 100644 --- a/tests/failpoint_tests.rs +++ b/tests/failpoint_tests.rs @@ -5,7 +5,10 @@ use common::{init, pd_addrs}; use fail::FailScenario; use serial_test::serial; use std::time::Duration; -use tikv_client::{transaction::HeartbeatOption, Result, TransactionClient, TransactionOptions}; +use tikv_client::{ + request::request_codec::TxnApiV1, transaction::HeartbeatOption, Result, TransactionClient, + TransactionOptions, +}; #[tokio::test] #[serial] @@ -16,7 +19,7 @@ async fn txn_optimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut heartbeat_txn = client .begin_with_options( diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index c5866d83..99ba86b4 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -22,8 +22,10 @@ use std::{ iter, }; use tikv_client::{ - transaction::HeartbeatOption, Error, Key, KvPair, RawClient, Result, Transaction, - TransactionClient, TransactionOptions, Value, + request::request_codec::{RawApiV1, RawCodec, TxnApiV1}, + transaction::HeartbeatOption, + Error, Key, KvPair, PdClient, RawClient, Result, Transaction, TransactionClient, + TransactionOptions, Value, }; // Parameters used in test @@ -34,7 +36,7 @@ const NUM_TRNASFER: u32 = 100; #[serial] async fn txn_get_timestamp() -> Result<()> { const COUNT: usize = 1 << 8; // use a small number to make test fast - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut versions = future::join_all((0..COUNT).map(|_| client.current_timestamp())) .await @@ -55,7 +57,7 @@ async fn txn_get_timestamp() -> Result<()> { async fn txn_crud() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut txn = client.begin_optimistic().await?; // Get non-existent keys @@ -139,7 +141,7 @@ async fn txn_crud() -> Result<()> { async fn txn_insert_duplicate_keys() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; // Initialize TiKV store with {foo => bar} let mut txn = client.begin_optimistic().await?; txn.put("foo".to_owned(), "bar".to_owned()).await?; @@ -163,7 +165,7 @@ async fn txn_insert_duplicate_keys() -> Result<()> { async fn txn_pessimistic() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut txn = client.begin_pessimistic().await?; txn.put("foo".to_owned(), "foo".to_owned()).await.unwrap(); @@ -180,7 +182,7 @@ async fn txn_pessimistic() -> Result<()> { #[serial] async fn raw_bank_transfer() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), None).await?; + let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; let mut rng = thread_rng(); let people = gen_u32_keys(NUM_PEOPLE, &mut rng); @@ -232,7 +234,7 @@ async fn txn_read() -> Result<()> { let value = "large_value".repeat(10); init().await?; - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -324,7 +326,7 @@ async fn txn_read() -> Result<()> { #[serial] async fn txn_bank_transfer() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut rng = thread_rng(); let options = TransactionOptions::new_optimistic() .use_async_commit() @@ -377,7 +379,7 @@ async fn txn_bank_transfer() -> Result<()> { #[serial] async fn raw_req() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), None).await?; + let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; // empty; get non-existent key let res = client.get("k1".to_owned()).await; @@ -507,7 +509,7 @@ async fn raw_req() -> Result<()> { #[serial] async fn txn_update_safepoint() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let res = client.gc(client.current_timestamp().await?).await?; assert!(res); Ok(()) @@ -522,7 +524,7 @@ async fn raw_write_million() -> Result<()> { let interval = 2u32.pow(32 - NUM_BITS_TXN - NUM_BITS_KEY_PER_TXN); init().await?; - let client = RawClient::new(pd_addrs(), None).await?; + let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -568,7 +570,8 @@ async fn raw_write_million() -> Result<()> { #[serial] async fn txn_pessimistic_rollback() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config(pd_addrs(), Default::default(), None).await?; + let client = + TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; let mut preload_txn = client.begin_optimistic().await?; let key1 = vec![1]; let key2 = vec![2]; @@ -600,9 +603,13 @@ async fn txn_pessimistic_rollback() -> Result<()> { #[serial] async fn txn_pessimistic_delete() -> Result<()> { init().await?; - let client = - TransactionClient::new_with_config(vec!["127.0.0.1:2379"], Default::default(), None) - .await?; + let client = TransactionClient::new_with_config( + vec!["127.0.0.1:2379"], + Default::default(), + TxnApiV1, + None, + ) + .await?; // The transaction will lock the keys and must release the locks on commit, // even when values are not written to the DB. @@ -644,7 +651,8 @@ async fn txn_pessimistic_delete() -> Result<()> { #[serial] async fn txn_lock_keys() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config(pd_addrs(), Default::default(), None).await?; + let client = + TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; let k1 = b"key1".to_vec(); let k2 = b"key2".to_vec(); @@ -678,7 +686,8 @@ async fn txn_lock_keys() -> Result<()> { #[serial] async fn txn_lock_keys_error_handle() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config(pd_addrs(), Default::default(), None).await?; + let client = + TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; // Keys in `k` should locate in different regions. See `init()` for boundary of regions. let k: Vec = vec![ @@ -715,7 +724,8 @@ async fn txn_lock_keys_error_handle() -> Result<()> { #[serial] async fn txn_get_for_update() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config(pd_addrs(), Default::default(), None).await?; + let client = + TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; let key1 = "key".to_owned(); let key2 = "another key".to_owned(); let value1 = b"some value".to_owned(); @@ -762,7 +772,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), None).await?; + let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; let mut heartbeat_txn = client .begin_with_options(TransactionOptions::new_pessimistic()) @@ -802,7 +812,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { #[serial] async fn raw_cas() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), None) + let client = RawClient::new(pd_addrs(), RawApiV1, None) .await? .with_atomic_for_cas(); let key = "key".to_owned(); @@ -847,7 +857,7 @@ async fn raw_cas() -> Result<()> { client.batch_delete(vec![key.clone()]).await.err().unwrap(), Error::UnsupportedMode )); - let client = RawClient::new(pd_addrs(), None).await?; + let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; assert!(matches!( client .compare_and_swap(key.clone(), None, vec![]) @@ -864,7 +874,8 @@ async fn raw_cas() -> Result<()> { #[serial] async fn txn_scan() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config(pd_addrs(), Default::default(), None).await?; + let client = + TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; let k1 = b"a".to_vec(); let v = b"b".to_vec(); @@ -884,7 +895,7 @@ async fn txn_scan() -> Result<()> { } // helper function -async fn get_u32(client: &RawClient, key: Vec) -> Result { +async fn get_u32(client: &RawClient, key: Vec) -> Result { let x = client.get(key).await?.unwrap(); let boxed_slice = x.into_boxed_slice(); let array: Box<[u8; 4]> = boxed_slice @@ -894,7 +905,7 @@ async fn get_u32(client: &RawClient, key: Vec) -> Result { } // helper function -async fn get_txn_u32(txn: &mut Transaction, key: Vec) -> Result { +async fn get_txn_u32(txn: &mut Transaction, key: Vec) -> Result { let x = txn.get(key).await?.unwrap(); let boxed_slice = x.into_boxed_slice(); let array: Box<[u8; 4]> = boxed_slice From dd1c7b9bf7294897e4bef0469656c9887412afb9 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 23 Jun 2022 17:49:56 +0800 Subject: [PATCH 07/43] remove specification feature Signed-off-by: iosmanthus --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3005daaa..efad038a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,6 @@ //! # })} //! ``` -#![feature(min_specialization)] #![feature(explicit_generic_args_with_impl_trait)] #[macro_use] pub mod request; From 3a0df009f71541ddee23edfe2cde247da5ef68da Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 24 Jun 2022 15:54:21 +0800 Subject: [PATCH 08/43] reduce type annotation Signed-off-by: iosmanthus --- src/pd/client.rs | 2 +- src/raw/client.rs | 30 +++++------ src/raw/lowering.rs | 61 +++++++++-------------- src/raw/requests.rs | 78 ++++++++--------------------- src/request/mod.rs | 11 +--- src/transaction/client.rs | 6 +-- src/transaction/lock.rs | 8 +-- src/transaction/lowering.rs | 59 ++++++++++------------ src/transaction/requests.rs | 91 +++++++++------------------------- src/transaction/transaction.rs | 48 ++++++++---------- 10 files changed, 137 insertions(+), 257 deletions(-) diff --git a/src/pd/client.rs b/src/pd/client.rs index 49679bc8..157b7d4f 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -225,7 +225,7 @@ impl PdClient for PdRpc } async fn region_for_key(&self, key: &Key) -> Result { - self.region_cache.get_region_by_key(&key).await + self.region_cache.get_region_by_key(key).await } async fn region_for_id(&self, id: RegionId) -> Result { diff --git a/src/raw/client.rs b/src/raw/client.rs index 287f1ae1..e18d70fb 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -185,7 +185,11 @@ impl Client { } } -impl Client { +impl Client +where + C: RawCodec, + PdC: PdClient, +{ /// Create a new 'get' request. /// /// Once resolved this request will result in the fetching of the value associated with the @@ -212,7 +216,7 @@ impl Client { /// Same as [`get`](Client::get) but with custom [`backoff`](crate::Backoff) strategy. pub async fn get_opt(&self, key: impl Into, backoff: Backoff) -> Result> { debug!(self.logger, "invoking raw get request"); - let request = new_raw_get_request::(key.into(), self.cf.clone()); + let request = new_raw_get_request(key.into(), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .merge(CollectSingle) @@ -254,8 +258,7 @@ impl Client { backoff: Backoff, ) -> Result> { debug!(self.logger, "invoking raw batch_get request"); - let request = - new_raw_batch_get_request::(keys.into_iter().map(Into::into), self.cf.clone()); + let request = new_raw_batch_get_request(keys.into_iter().map(Into::into), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .merge(Collect) @@ -294,8 +297,7 @@ impl Client { backoff: Backoff, ) -> Result<()> { debug!(self.logger, "invoking raw put request"); - let request = - new_raw_put_request::(key.into(), value.into(), self.cf.clone(), self.atomic); + let request = new_raw_put_request(key.into(), value.into(), self.cf.clone(), self.atomic); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .merge(CollectSingle) @@ -337,7 +339,7 @@ impl Client { backoff: Backoff, ) -> Result<()> { debug!(self.logger, "invoking raw batch_put request"); - let request = new_raw_batch_put_request::( + let request = new_raw_batch_put_request( pairs.into_iter().map(Into::into), self.cf.clone(), self.atomic, @@ -375,7 +377,7 @@ impl Client { /// Same as [`delete`](Client::delete) but with custom [`backoff`](crate::Backoff) strategy. pub async fn delete_opt(&self, key: impl Into, backoff: Backoff) -> Result<()> { debug!(self.logger, "invoking raw delete request"); - let request = new_raw_delete_request::(key.into(), self.cf.clone(), self.atomic); + let request = new_raw_delete_request(key.into(), self.cf.clone(), self.atomic); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .merge(CollectSingle) @@ -416,7 +418,7 @@ impl Client { debug!(self.logger, "invoking raw batch_delete request"); self.assert_non_atomic()?; let request = - new_raw_batch_delete_request::(keys.into_iter().map(Into::into), self.cf.clone()); + new_raw_batch_delete_request(keys.into_iter().map(Into::into), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .extract_error() @@ -453,7 +455,7 @@ impl Client { ) -> Result<()> { debug!(self.logger, "invoking raw delete_range request"); self.assert_non_atomic()?; - let request = new_raw_delete_range_request::(range.into(), self.cf.clone()); + let request = new_raw_delete_range_request(range.into(), self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .extract_error() @@ -664,7 +666,7 @@ impl Client { ) -> Result<(Option, bool)> { debug!(self.logger, "invoking raw compare_and_swap request"); self.assert_atomic()?; - let req = new_cas_request::( + let req = new_cas_request( key.into(), new_value.into(), previous_value.into(), @@ -706,7 +708,7 @@ impl Client { ) -> Result, Vec>)>> { let copr_version_req = copr_version_req.into(); semver::VersionReq::from_str(&copr_version_req)?; - let req = new_raw_coprocessor_request::( + let req = new_raw_coprocessor_request( copr_name.into(), copr_version_req, ranges.into_iter().map(Into::into), @@ -734,7 +736,7 @@ impl Client { }); } - let request = new_raw_scan_request::(range.into(), limit, key_only, self.cf.clone()); + let request = new_raw_scan_request(range.into(), limit, key_only, self.cf.clone()); let plan = crate::request::PlanBuilder::new(self.rpc.clone(), request) .retry_multi_region(backoff) .merge(Collect) @@ -760,7 +762,7 @@ impl Client { }); } - let request = new_raw_batch_scan_request::( + let request = new_raw_batch_scan_request( ranges.into_iter().map(Into::into), each_limit, key_only, diff --git a/src/raw/lowering.rs b/src/raw/lowering.rs index abef6709..32327a80 100644 --- a/src/raw/lowering.rs +++ b/src/raw/lowering.rs @@ -8,77 +8,67 @@ use std::{iter::Iterator, ops::Range, sync::Arc}; use tikv_client_proto::{kvrpcpb, metapb}; -use crate::{ - raw::requests, request::request_codec::RequestCodec, BoundRange, ColumnFamily, Key, KvPair, - Value, -}; +use crate::{raw::requests, BoundRange, ColumnFamily, Key, KvPair, Value}; -pub fn new_raw_get_request( - key: Key, - cf: Option, -) -> kvrpcpb::RawGetRequest { - requests::new_raw_get_request::(key.into(), cf) +pub fn new_raw_get_request(key: Key, cf: Option) -> kvrpcpb::RawGetRequest { + requests::new_raw_get_request(key.into(), cf) } -pub fn new_raw_batch_get_request( +pub fn new_raw_batch_get_request( keys: impl Iterator, cf: Option, ) -> kvrpcpb::RawBatchGetRequest { - requests::new_raw_batch_get_request::(keys.map(Into::into).collect(), cf) + requests::new_raw_batch_get_request(keys.map(Into::into).collect(), cf) } -pub fn new_raw_put_request( +pub fn new_raw_put_request( key: Key, value: Value, cf: Option, atomic: bool, ) -> kvrpcpb::RawPutRequest { - requests::new_raw_put_request::(key.into(), value, cf, atomic) + requests::new_raw_put_request(key.into(), value, cf, atomic) } -pub fn new_raw_batch_put_request( +pub fn new_raw_batch_put_request( pairs: impl Iterator, cf: Option, atomic: bool, ) -> kvrpcpb::RawBatchPutRequest { - requests::new_raw_batch_put_request::(pairs.map(Into::into).collect(), cf, atomic) + requests::new_raw_batch_put_request(pairs.map(Into::into).collect(), cf, atomic) } -pub fn new_raw_delete_request( +pub fn new_raw_delete_request( key: Key, cf: Option, atomic: bool, ) -> kvrpcpb::RawDeleteRequest { - requests::new_raw_delete_request::(key.into(), cf, atomic) + requests::new_raw_delete_request(key.into(), cf, atomic) } -pub fn new_raw_batch_delete_request( +pub fn new_raw_batch_delete_request( keys: impl Iterator, cf: Option, ) -> kvrpcpb::RawBatchDeleteRequest { - requests::new_raw_batch_delete_request::(keys.map(Into::into).collect(), cf) + requests::new_raw_batch_delete_request(keys.map(Into::into).collect(), cf) } -pub fn new_raw_delete_range_request( +pub fn new_raw_delete_range_request( range: BoundRange, cf: Option, ) -> kvrpcpb::RawDeleteRangeRequest { let (start_key, end_key) = range.into_keys(); - requests::new_raw_delete_range_request::( - start_key.into(), - end_key.unwrap_or_default().into(), - cf, - ) + requests::new_raw_delete_range_request(start_key.into(), end_key.unwrap_or_default().into(), cf) } -pub fn new_raw_scan_request( +pub fn new_raw_scan_request( range: BoundRange, limit: u32, key_only: bool, cf: Option, ) -> kvrpcpb::RawScanRequest { let (start_key, end_key) = range.into_keys(); - requests::new_raw_scan_request::( + requests::new_raw_scan_request( start_key.into(), end_key.unwrap_or_default().into(), limit, @@ -87,36 +77,31 @@ pub fn new_raw_scan_request( ) } -pub fn new_raw_batch_scan_request( +pub fn new_raw_batch_scan_request( ranges: impl Iterator, each_limit: u32, key_only: bool, cf: Option, ) -> kvrpcpb::RawBatchScanRequest { - requests::new_raw_batch_scan_request::( - ranges.map(Into::into).collect(), - each_limit, - key_only, - cf, - ) + requests::new_raw_batch_scan_request(ranges.map(Into::into).collect(), each_limit, key_only, cf) } -pub fn new_cas_request( +pub fn new_cas_request( key: Key, value: Value, previous_value: Option, cf: Option, ) -> kvrpcpb::RawCasRequest { - requests::new_cas_request::(key.into(), value, previous_value, cf) + requests::new_cas_request(key.into(), value, previous_value, cf) } -pub fn new_raw_coprocessor_request( +pub fn new_raw_coprocessor_request( copr_name: String, copr_version_req: String, ranges: impl Iterator, request_builder: impl Fn(metapb::Region, Vec>) -> Vec + Send + Sync + 'static, ) -> requests::RawCoprocessorRequest { - requests::new_raw_coprocessor_request::( + requests::new_raw_coprocessor_request( copr_name, copr_version_req, ranges.map(Into::into).collect(), diff --git a/src/raw/requests.rs b/src/raw/requests.rs index b3329d76..a3d8de3d 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -23,13 +23,7 @@ use crate::{ ColumnFamily, Key, KvPair, Result, Value, }; -pub fn new_raw_get_request( - key: Vec, - cf: Option, -) -> kvrpcpb::RawGetRequest -where - kvrpcpb::RawGetRequest: KvRequest, -{ +pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::RawGetRequest { let mut req = kvrpcpb::RawGetRequest::default(); req.set_key(key); req.maybe_set_cf(cf); @@ -73,13 +67,10 @@ impl Process for DefaultProcessor { } } -pub fn new_raw_batch_get_request( +pub fn new_raw_batch_get_request( keys: Vec>, cf: Option, -) -> kvrpcpb::RawBatchGetRequest -where - kvrpcpb::RawBatchGetRequest: KvRequest, -{ +) -> kvrpcpb::RawBatchGetRequest { let mut req = kvrpcpb::RawBatchGetRequest::default(); req.set_keys(keys); req.maybe_set_cf(cf); @@ -114,15 +105,12 @@ impl Merge for Collect { } } -pub fn new_raw_put_request( +pub fn new_raw_put_request( key: Vec, value: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawPutRequest -where - kvrpcpb::RawPutRequest: KvRequest, -{ +) -> kvrpcpb::RawPutRequest { let mut req = kvrpcpb::RawPutRequest::default(); req.set_key(key); req.set_value(value); @@ -154,14 +142,11 @@ impl SingleKey for kvrpcpb::RawPutRequest { } } -pub fn new_raw_batch_put_request( +pub fn new_raw_batch_put_request( pairs: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawBatchPutRequest -where - kvrpcpb::RawBatchPutRequest: KvRequest, -{ +) -> kvrpcpb::RawBatchPutRequest { let mut req = kvrpcpb::RawBatchPutRequest::default(); req.set_pairs(pairs); req.maybe_set_cf(cf); @@ -206,14 +191,11 @@ impl Shardable for kvrpcpb::RawBatchPutRequest { } } -pub fn new_raw_delete_request( +pub fn new_raw_delete_request( key: Vec, cf: Option, atomic: bool, -) -> kvrpcpb::RawDeleteRequest -where - kvrpcpb::RawDeleteRequest: KvRequest, -{ +) -> kvrpcpb::RawDeleteRequest { let mut req = kvrpcpb::RawDeleteRequest::default(); req.set_key(key); req.maybe_set_cf(cf); @@ -244,13 +226,10 @@ impl SingleKey for kvrpcpb::RawDeleteRequest { } } -pub fn new_raw_batch_delete_request( +pub fn new_raw_batch_delete_request( keys: Vec>, cf: Option, -) -> kvrpcpb::RawBatchDeleteRequest -where - kvrpcpb::RawBatchDeleteRequest: KvRequest, -{ +) -> kvrpcpb::RawBatchDeleteRequest { let mut req = kvrpcpb::RawBatchDeleteRequest::default(); req.set_keys(keys); req.maybe_set_cf(cf); @@ -274,14 +253,11 @@ impl KvRequest for kvrpcpb::RawBatchDeleteRequest { shardable_keys!(kvrpcpb::RawBatchDeleteRequest); -pub fn new_raw_delete_range_request( +pub fn new_raw_delete_range_request( start_key: Vec, end_key: Vec, cf: Option, -) -> kvrpcpb::RawDeleteRangeRequest -where - kvrpcpb::RawDeleteRangeRequest: KvRequest, -{ +) -> kvrpcpb::RawDeleteRangeRequest { let mut req = kvrpcpb::RawDeleteRangeRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -306,16 +282,13 @@ impl KvRequest for kvrpcpb::RawDeleteRangeRequest { shardable_range!(kvrpcpb::RawDeleteRangeRequest); -pub fn new_raw_scan_request( +pub fn new_raw_scan_request( start_key: Vec, end_key: Vec, limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawScanRequest -where - kvrpcpb::RawScanRequest: KvRequest, -{ +) -> kvrpcpb::RawScanRequest { let mut req = kvrpcpb::RawScanRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -353,15 +326,12 @@ impl Merge for Collect { } } -pub fn new_raw_batch_scan_request( +pub fn new_raw_batch_scan_request( ranges: Vec, each_limit: u32, key_only: bool, cf: Option, -) -> kvrpcpb::RawBatchScanRequest -where - kvrpcpb::RawBatchScanRequest: KvRequest, -{ +) -> kvrpcpb::RawBatchScanRequest { let mut req = kvrpcpb::RawBatchScanRequest::default(); req.set_ranges(ranges); req.set_each_limit(each_limit); @@ -413,15 +383,12 @@ impl Merge for Collect { } } -pub fn new_cas_request( +pub fn new_cas_request( key: Vec, value: Vec, previous_value: Option>, cf: Option, -) -> kvrpcpb::RawCasRequest -where - kvrpcpb::RawCasRequest: KvRequest, -{ +) -> kvrpcpb::RawCasRequest { let mut req = kvrpcpb::RawCasRequest::default(); req.set_key(key); req.set_value(value); @@ -471,15 +438,12 @@ impl Process for DefaultProcessor { type RawCoprocessorRequestDataBuilder = Arc) -> Vec + Send + Sync>; -pub fn new_raw_coprocessor_request( +pub fn new_raw_coprocessor_request( copr_name: String, copr_version_req: String, ranges: Vec, data_builder: RawCoprocessorRequestDataBuilder, -) -> RawCoprocessorRequest -where - RawCoprocessorRequest: KvRequest, -{ +) -> RawCoprocessorRequest { let mut inner = kvrpcpb::RawCoprocessorRequest::default(); inner.set_copr_name(copr_name); inner.set_copr_version_req(copr_version_req); diff --git a/src/request/mod.rs b/src/request/mod.rs index a254f9cc..ff02e269 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -87,10 +87,7 @@ mod test { use crate::{ mock::{MockKvClient, MockPdClient}, - request::{ - request_codec::{RequestCodec, TxnApiV1}, - KvRequest, - }, + request::{request_codec::RequestCodec, KvRequest}, store::store_stream_for_keys, transaction::lowering::new_commit_request, Error, Key, Result, @@ -216,11 +213,7 @@ mod test { ))); let key: Key = "key".to_owned().into(); - let req = new_commit_request::( - iter::once(key), - Timestamp::default(), - Timestamp::default(), - ); + let req = new_commit_request(iter::once(key), Timestamp::default(), Timestamp::default()); // does not extract error let plan = crate::request::PlanBuilder::new(pd_client.clone(), req.clone()) diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 50e509ed..e94dc923 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -45,10 +45,10 @@ pub struct Client { impl Clone for Client { fn clone(&self) -> Self { - Self { + Self { pd: self.pd.clone(), logger: self.logger.clone(), - _phantom: PhantomData, + _phantom: PhantomData, } } } @@ -269,7 +269,7 @@ where let mut locks: Vec = vec![]; let mut start_key = vec![]; loop { - let req = new_scan_lock_request::( + let req = new_scan_lock_request( mem::take(&mut start_key), safepoint.version(), SCAN_LOCK_BATCH_SIZE, diff --git a/src/transaction/lock.rs b/src/transaction/lock.rs index 06dc0ee4..f568ff35 100644 --- a/src/transaction/lock.rs +++ b/src/transaction/lock.rs @@ -61,10 +61,7 @@ pub async fn resolve_locks( let commit_version = match commit_versions.get(&lock.lock_version) { Some(&commit_version) => commit_version, None => { - let request = requests::new_cleanup_request::( - lock.primary_lock, - lock.lock_version, - ); + let request = requests::new_cleanup_request(lock.primary_lock, lock.lock_version); let plan = crate::request::PlanBuilder::new(pd_client.clone(), request) .resolve_lock(OPTIMISTIC_BACKOFF) .retry_multi_region(DEFAULT_REGION_BACKOFF) @@ -105,8 +102,7 @@ async fn resolve_lock_with_retry( debug!("resolving locks: attempt {}", (i + 1)); let store = pd_client.clone().store_for_key(key.into()).await?; let ver_id = store.region_with_leader.ver_id(); - let request = - requests::new_resolve_lock_request::(start_version, commit_version); + let request = requests::new_resolve_lock_request(start_version, commit_version); // The only place where single-region is used let plan = crate::request::PlanBuilder::new(pd_client.clone(), request) .single_region_with_store(store) diff --git a/src/transaction/lowering.rs b/src/transaction/lowering.rs index 509e1d3d..413c6bf8 100644 --- a/src/transaction/lowering.rs +++ b/src/transaction/lowering.rs @@ -1,6 +1,5 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. -use crate::request::request_codec::RequestCodec; /// This module provides constructor functions for requests which take arguments as high-level /// types (i.e., the types from the client crate) and converts these to the types used in the /// generated protobuf code, then calls the low-level ctor functions in the requests module. @@ -8,25 +7,25 @@ use crate::{timestamp::TimestampExt, transaction::requests, BoundRange, Key}; use std::iter::Iterator; use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; -pub fn new_get_request(key: Key, timestamp: Timestamp) -> kvrpcpb::GetRequest { - requests::new_get_request::(key.into(), timestamp.version()) +pub fn new_get_request(key: Key, timestamp: Timestamp) -> kvrpcpb::GetRequest { + requests::new_get_request(key.into(), timestamp.version()) } -pub fn new_batch_get_request( +pub fn new_batch_get_request( keys: impl Iterator, timestamp: Timestamp, ) -> kvrpcpb::BatchGetRequest { - requests::new_batch_get_request::(keys.map(Into::into).collect(), timestamp.version()) + requests::new_batch_get_request(keys.map(Into::into).collect(), timestamp.version()) } -pub fn new_scan_request( +pub fn new_scan_request( range: BoundRange, timestamp: Timestamp, limit: u32, key_only: bool, ) -> kvrpcpb::ScanRequest { let (start_key, end_key) = range.into_keys(); - requests::new_scan_request::( + requests::new_scan_request( start_key.into(), end_key.unwrap_or_default().into(), timestamp.version(), @@ -35,27 +34,24 @@ pub fn new_scan_request( ) } -pub fn new_resolve_lock_request( +pub fn new_resolve_lock_request( start_version: Timestamp, commit_version: Timestamp, ) -> kvrpcpb::ResolveLockRequest { - requests::new_resolve_lock_request::(start_version.version(), commit_version.version()) + requests::new_resolve_lock_request(start_version.version(), commit_version.version()) } -pub fn new_cleanup_request( - key: Key, - start_version: Timestamp, -) -> kvrpcpb::CleanupRequest { - requests::new_cleanup_request::(key.into(), start_version.version()) +pub fn new_cleanup_request(key: Key, start_version: Timestamp) -> kvrpcpb::CleanupRequest { + requests::new_cleanup_request(key.into(), start_version.version()) } -pub fn new_prewrite_request( +pub fn new_prewrite_request( mutations: Vec, primary_lock: Key, start_version: Timestamp, lock_ttl: u64, ) -> kvrpcpb::PrewriteRequest { - requests::new_prewrite_request::( + requests::new_prewrite_request( mutations, primary_lock.into(), start_version.version(), @@ -63,14 +59,14 @@ pub fn new_prewrite_request( ) } -pub fn new_pessimistic_prewrite_request( +pub fn new_pessimistic_prewrite_request( mutations: Vec, primary_lock: Key, start_version: Timestamp, lock_ttl: u64, for_update_ts: Timestamp, ) -> kvrpcpb::PrewriteRequest { - requests::new_pessimistic_prewrite_request::( + requests::new_pessimistic_prewrite_request( mutations, primary_lock.into(), start_version.version(), @@ -79,34 +75,31 @@ pub fn new_pessimistic_prewrite_request( ) } -pub fn new_commit_request( +pub fn new_commit_request( keys: impl Iterator, start_version: Timestamp, commit_version: Timestamp, ) -> kvrpcpb::CommitRequest { - requests::new_commit_request::( + requests::new_commit_request( keys.map(Into::into).collect(), start_version.version(), commit_version.version(), ) } -pub fn new_batch_rollback_request( +pub fn new_batch_rollback_request( keys: impl Iterator, start_version: Timestamp, ) -> kvrpcpb::BatchRollbackRequest { - requests::new_batch_rollback_request::( - keys.map(Into::into).collect(), - start_version.version(), - ) + requests::new_batch_rollback_request(keys.map(Into::into).collect(), start_version.version()) } -pub fn new_pessimistic_rollback_request( +pub fn new_pessimistic_rollback_request( keys: impl Iterator, start_version: Timestamp, for_update_ts: Timestamp, ) -> kvrpcpb::PessimisticRollbackRequest { - requests::new_pessimistic_rollback_request::( + requests::new_pessimistic_rollback_request( keys.map(Into::into).collect(), start_version.version(), for_update_ts.version(), @@ -139,7 +132,7 @@ impl PessimisticLock for (Key, kvrpcpb::Assertion) { } } -pub fn new_pessimistic_lock_request( +pub fn new_pessimistic_lock_request( locks: impl Iterator, primary_lock: Key, start_version: Timestamp, @@ -147,7 +140,7 @@ pub fn new_pessimistic_lock_request( for_update_ts: Timestamp, need_value: bool, ) -> kvrpcpb::PessimisticLockRequest { - requests::new_pessimistic_lock_request::( + requests::new_pessimistic_lock_request( locks .map(|pl| { let mut mutation = kvrpcpb::Mutation::default(); @@ -165,18 +158,18 @@ pub fn new_pessimistic_lock_request( ) } -pub fn new_scan_lock_request( +pub fn new_scan_lock_request( start_key: Key, safepoint: Timestamp, limit: u32, ) -> kvrpcpb::ScanLockRequest { - requests::new_scan_lock_request::(start_key.into(), safepoint.version(), limit) + requests::new_scan_lock_request(start_key.into(), safepoint.version(), limit) } -pub fn new_heart_beat_request( +pub fn new_heart_beat_request( start_ts: Timestamp, primary_lock: Key, ttl: u64, ) -> kvrpcpb::TxnHeartBeatRequest { - requests::new_heart_beat_request::(start_ts.version(), primary_lock.into(), ttl) + requests::new_heart_beat_request(start_ts.version(), primary_lock.into(), ttl) } diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 65dc8aa2..15c457d0 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -66,10 +66,7 @@ macro_rules! error_locks { }; } -pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest -where - kvrpcpb::GetRequest: KvRequest, -{ +pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest { let mut req = kvrpcpb::GetRequest::default(); req.set_key(key); req.set_version(timestamp); @@ -111,13 +108,7 @@ impl Process for DefaultProcessor { } } -pub fn new_batch_get_request( - keys: Vec>, - timestamp: u64, -) -> kvrpcpb::BatchGetRequest -where - kvrpcpb::BatchGetRequest: KvRequest, -{ +pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::BatchGetRequest { let mut req = kvrpcpb::BatchGetRequest::default(); req.set_keys(keys); req.set_version(timestamp); @@ -151,16 +142,13 @@ impl Merge for Collect { } } -pub fn new_scan_request( +pub fn new_scan_request( start_key: Vec, end_key: Vec, timestamp: u64, limit: u32, key_only: bool, -) -> kvrpcpb::ScanRequest -where - kvrpcpb::ScanRequest: KvRequest, -{ +) -> kvrpcpb::ScanRequest { let mut req = kvrpcpb::ScanRequest::default(); req.set_start_key(start_key); req.set_end_key(end_key); @@ -197,13 +185,10 @@ impl Merge for Collect { } } -pub fn new_resolve_lock_request( +pub fn new_resolve_lock_request( start_version: u64, commit_version: u64, -) -> kvrpcpb::ResolveLockRequest -where - kvrpcpb::ResolveLockRequest: KvRequest, -{ +) -> kvrpcpb::ResolveLockRequest { let mut req = kvrpcpb::ResolveLockRequest::default(); req.set_start_version(start_version); req.set_commit_version(commit_version); @@ -229,13 +214,7 @@ impl KvRequest for kvrpcpb::ResolveLockRequest { } } -pub fn new_cleanup_request( - key: Vec, - start_version: u64, -) -> kvrpcpb::CleanupRequest -where - kvrpcpb::CleanupRequest: KvRequest, -{ +pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest { let mut req = kvrpcpb::CleanupRequest::default(); req.set_key(key); req.set_start_version(start_version); @@ -273,15 +252,12 @@ impl Process for DefaultProcessor { } } -pub fn new_prewrite_request( +pub fn new_prewrite_request( mutations: Vec, primary_lock: Vec, start_version: u64, lock_ttl: u64, -) -> kvrpcpb::PrewriteRequest -where - kvrpcpb::PrewriteRequest: KvRequest, -{ +) -> kvrpcpb::PrewriteRequest { let mut req = kvrpcpb::PrewriteRequest::default(); req.set_mutations(mutations); req.set_primary_lock(primary_lock); @@ -293,16 +269,13 @@ where req } -pub fn new_pessimistic_prewrite_request( +pub fn new_pessimistic_prewrite_request( mutations: Vec, primary_lock: Vec, start_version: u64, lock_ttl: u64, for_update_ts: u64, -) -> kvrpcpb::PrewriteRequest -where - kvrpcpb::PrewriteRequest: KvRequest, -{ +) -> kvrpcpb::PrewriteRequest { let len = mutations.len(); let mut req = new_prewrite_request(mutations, primary_lock, start_version, lock_ttl); req.set_for_update_ts(for_update_ts); @@ -354,14 +327,11 @@ impl Shardable for kvrpcpb::PrewriteRequest { } } -pub fn new_commit_request( +pub fn new_commit_request( keys: Vec>, start_version: u64, commit_version: u64, -) -> kvrpcpb::CommitRequest -where - kvrpcpb::CommitRequest: KvRequest, -{ +) -> kvrpcpb::CommitRequest { let mut req = kvrpcpb::CommitRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -386,13 +356,10 @@ impl KvRequest for kvrpcpb::CommitRequest { shardable_keys!(kvrpcpb::CommitRequest); -pub fn new_batch_rollback_request( +pub fn new_batch_rollback_request( keys: Vec>, start_version: u64, -) -> kvrpcpb::BatchRollbackRequest -where - kvrpcpb::BatchRollbackRequest: KvRequest, -{ +) -> kvrpcpb::BatchRollbackRequest { let mut req = kvrpcpb::BatchRollbackRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -416,14 +383,11 @@ impl KvRequest for kvrpcpb::BatchRollbackRequest { shardable_keys!(kvrpcpb::BatchRollbackRequest); -pub fn new_pessimistic_rollback_request( +pub fn new_pessimistic_rollback_request( keys: Vec>, start_version: u64, for_update_ts: u64, -) -> kvrpcpb::PessimisticRollbackRequest -where - kvrpcpb::PessimisticRollbackRequest: KvRequest, -{ +) -> kvrpcpb::PessimisticRollbackRequest { let mut req = kvrpcpb::PessimisticRollbackRequest::default(); req.set_keys(keys); req.set_start_version(start_version); @@ -448,17 +412,14 @@ impl KvRequest for kvrpcpb::PessimisticRollbackRequest { shardable_keys!(kvrpcpb::PessimisticRollbackRequest); -pub fn new_pessimistic_lock_request( +pub fn new_pessimistic_lock_request( mutations: Vec, primary_lock: Vec, start_version: u64, lock_ttl: u64, for_update_ts: u64, need_value: bool, -) -> kvrpcpb::PessimisticLockRequest -where - kvrpcpb::PessimisticLockRequest: KvRequest, -{ +) -> kvrpcpb::PessimisticLockRequest { let mut req = kvrpcpb::PessimisticLockRequest::default(); req.set_mutations(mutations); req.set_primary_lock(primary_lock); @@ -572,14 +533,11 @@ impl Merge( +pub fn new_scan_lock_request( start_key: Vec, safepoint: u64, limit: u32, -) -> kvrpcpb::ScanLockRequest -where - kvrpcpb::ScanLockRequest: KvRequest, -{ +) -> kvrpcpb::ScanLockRequest { let mut req = kvrpcpb::ScanLockRequest::default(); req.set_start_key(start_key); req.set_max_version(safepoint); @@ -629,14 +587,11 @@ impl Merge for Collect { } } -pub fn new_heart_beat_request( +pub fn new_heart_beat_request( start_ts: u64, primary_lock: Vec, ttl: u64, -) -> kvrpcpb::TxnHeartBeatRequest -where - kvrpcpb::TxnHeartBeatRequest: KvRequest, -{ +) -> kvrpcpb::TxnHeartBeatRequest { let mut req = kvrpcpb::TxnHeartBeatRequest::default(); req.set_start_version(start_ts); req.set_primary_lock(primary_lock); diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 5e90d471..5f852ffe 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -126,7 +126,7 @@ impl Transaction { self.buffer .get_or_else(key, |key| async move { - let request = new_get_request::(key, timestamp); + let request = new_get_request(key, timestamp); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(DEFAULT_REGION_BACKOFF) @@ -260,7 +260,7 @@ impl Transaction { self.buffer .batch_get_or_else(keys.into_iter().map(|k| k.into()), move |keys| async move { - let request = new_batch_get_request::(keys, timestamp); + let request = new_batch_get_request(keys, timestamp); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(retry_options.region_backoff) @@ -678,7 +678,7 @@ impl Transaction { Some(k) => k, None => return Err(Error::NoPrimaryKey), }; - let request = new_heart_beat_request::( + let request = new_heart_beat_request( self.timestamp.clone(), primary_key, self.start_instant.elapsed().as_millis() as u64 + MAX_TTL, @@ -709,9 +709,7 @@ impl Transaction { limit, !key_only, move |new_range, new_limit| async move { - let request = new_scan_request::( - new_range, timestamp, new_limit, key_only, - ); + let request = new_scan_request(new_range, timestamp, new_limit, key_only); let plan = PlanBuilder::new(rpc, request) .resolve_lock(retry_options.lock_backoff) .retry_multi_region(retry_options.region_backoff) @@ -759,7 +757,7 @@ impl Transaction { .unwrap_or_else(|| first_key.clone()); let for_update_ts = self.rpc.clone().get_timestamp().await?; self.options.push_for_update_ts(for_update_ts.clone()); - let request = new_pessimistic_lock_request::( + let request = new_pessimistic_lock_request( keys.clone().into_iter(), primary_lock, self.timestamp.clone(), @@ -816,7 +814,7 @@ impl Transaction { return Ok(()); } - let req = new_pessimistic_rollback_request::( + let req = new_pessimistic_rollback_request( keys.clone().into_iter(), start_version, for_update_ts, @@ -886,7 +884,7 @@ impl Transaction { break; } } - let request = new_heart_beat_request::( + let request = new_heart_beat_request( start_ts.clone(), primary_key.clone(), start_instant.elapsed().as_millis() as u64 + MAX_TTL, @@ -1173,21 +1171,19 @@ impl Committer { let elapsed = self.start_instant.elapsed().as_millis() as u64; let lock_ttl = self.calc_txn_lock_ttl(); let mut request = match &self.options.kind { - TransactionKind::Optimistic => new_prewrite_request::( + TransactionKind::Optimistic => new_prewrite_request( self.mutations.clone(), primary_lock, self.start_version.clone(), lock_ttl + elapsed, ), - TransactionKind::Pessimistic(for_update_ts) => { - new_pessimistic_prewrite_request::( - self.mutations.clone(), - primary_lock, - self.start_version.clone(), - lock_ttl + elapsed, - for_update_ts.clone(), - ) - } + TransactionKind::Pessimistic(for_update_ts) => new_pessimistic_prewrite_request( + self.mutations.clone(), + primary_lock, + self.start_version.clone(), + lock_ttl + elapsed, + for_update_ts.clone(), + ), }; request.use_async_commit = self.options.async_commit; @@ -1235,7 +1231,7 @@ impl Committer { debug!(self.logger, "committing primary"); let primary_key = self.primary_key.clone().into_iter(); let commit_version = self.rpc.clone().get_timestamp().await?; - let req = new_commit_request::( + let req = new_commit_request( primary_key, self.start_version.clone(), commit_version.clone(), @@ -1267,7 +1263,7 @@ impl Committer { let req = if self.options.async_commit { let keys = mutations.map(|m| m.key.into()); - new_commit_request::(keys, self.start_version, commit_version) + new_commit_request(keys, self.start_version, commit_version) } else if primary_only { return Ok(()); } else { @@ -1275,7 +1271,7 @@ impl Committer { let keys = mutations .map(|m| m.key.into()) .filter(|key| &primary_key != key); - new_commit_request::(keys, self.start_version, commit_version) + new_commit_request(keys, self.start_version, commit_version) }; let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) @@ -1297,7 +1293,7 @@ impl Committer { .map(|mutation| mutation.key.into()); match self.options.kind { TransactionKind::Optimistic => { - let req = new_batch_rollback_request::(keys, self.start_version); + let req = new_batch_rollback_request(keys, self.start_version); let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) .retry_multi_region(self.options.retry_options.region_backoff) @@ -1306,11 +1302,7 @@ impl Committer { plan.execute().await?; } TransactionKind::Pessimistic(for_update_ts) => { - let req = new_pessimistic_rollback_request::( - keys, - self.start_version, - for_update_ts, - ); + let req = new_pessimistic_rollback_request(keys, self.start_version, for_update_ts); let plan = PlanBuilder::new(self.rpc, req) .resolve_lock(self.options.retry_options.lock_backoff) .retry_multi_region(self.options.retry_options.region_backoff) From 7c3de1af9eeca2904c9bc8fd532c67508465c9b3 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 24 Jun 2022 15:59:31 +0800 Subject: [PATCH 09/43] recover impl Trait for resolve_locks* Signed-off-by: iosmanthus --- src/lib.rs | 1 - src/transaction/lock.rs | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index efad038a..56f132a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,6 @@ //! # })} //! ``` -#![feature(explicit_generic_args_with_impl_trait)] #[macro_use] pub mod request; #[macro_use] diff --git a/src/transaction/lock.rs b/src/transaction/lock.rs index f568ff35..e70836d6 100644 --- a/src/transaction/lock.rs +++ b/src/transaction/lock.rs @@ -25,9 +25,9 @@ const RESOLVE_LOCK_RETRY_LIMIT: usize = 10; /// the key. We first use `CleanupRequest` to let the status of the primary lock converge and get /// its status (committed or rolled back). Then, we use the status of its primary lock to determine /// the status of the other keys in the same transaction. -pub async fn resolve_locks( +pub async fn resolve_locks( locks: Vec, - pd_client: Arc, + pd_client: Arc, ) -> Result { debug!("resolving locks"); let ts = pd_client.clone().get_timestamp().await?; @@ -89,11 +89,11 @@ pub async fn resolve_locks( Ok(!has_live_locks) } -async fn resolve_lock_with_retry( +async fn resolve_lock_with_retry( #[allow(clippy::ptr_arg)] key: &Vec, start_version: u64, commit_version: u64, - pd_client: Arc, + pd_client: Arc, ) -> Result { debug!("resolving locks with retry"); // FIXME: Add backoff From 02377b764b75aac611ab1c9a151ff3302871d657 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 28 Jun 2022 20:48:51 +0800 Subject: [PATCH 10/43] git fire!: wip api v2 Signed-off-by: iosmanthus --- src/kv/key.rs | 15 +++++ src/raw/client.rs | 13 ++++- src/request/request_codec.rs | 99 +++++++++++++++++++++++++++++--- tikv-client-common/src/errors.rs | 6 ++ 4 files changed, 124 insertions(+), 9 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 3d879c73..2ba556e1 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -8,6 +8,7 @@ use proptest::{arbitrary::any_with, collection::size_range}; #[cfg(test)] use proptest_derive::Arbitrary; use std::{fmt, ops::Bound, u8}; +use std::ops::{Deref, DerefMut}; use tikv_client_proto::kvrpcpb; const _PROPTEST_KEY_MAX: usize = 1024 * 2; // 2 KB @@ -179,3 +180,17 @@ impl fmt::Debug for Key { write!(f, "Key({})", HexRepr(&self.0)) } } + +impl Deref for Key { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Key { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} \ No newline at end of file diff --git a/src/raw/client.rs b/src/raw/client.rs index e18d70fb..7ef1923b 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -19,6 +19,7 @@ use crate::{ }, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; +use crate::request::request_codec::RawApiV1; const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; @@ -50,6 +51,16 @@ impl Clone for Client { } } +impl Client { + pub async fn new>( + pd_endpoints: Vec, + logger: Option, + ) -> Result { + Self::new_with_config(pd_endpoints, Config::default(), RawApiV1, logger).await + } +} + + impl Client { /// Create a raw [`Client`] and connect to the TiKV cluster. /// @@ -69,7 +80,7 @@ impl Client { /// .unwrap(); /// # }); /// ``` - pub async fn new>( + pub async fn new_with_codec>( pd_endpoints: Vec, codec: C, logger: Option, diff --git a/src/request/request_codec.rs b/src/request/request_codec.rs index 892c820d..773d5402 100644 --- a/src/request/request_codec.rs +++ b/src/request/request_codec.rs @@ -1,6 +1,15 @@ +use tikv_client_common::Error; use tikv_client_proto::metapb::Region; +use tikv_client_store::Request; -use crate::{kv::codec::decode_bytes_in_place, Key, Result}; +use crate::{Key, kv::codec::decode_bytes_in_place, Result}; + +const KEYSPACE_PREFIX_LEN: usize = 4; +const RAW_MODE_PREFIX: u8 = b'r'; +const TXN_MODE_PREFIX: u8 = b'x'; +const RAW_MODE_MAX_KEY: Prefix = [RAW_MODE_PREFIX + 1, 0, 0, 0]; +const TXN_MODE_MAX_KEY: Prefix = [TXN_MODE_PREFIX + 1, 0, 0, 0]; +const MAX_KEYSPACE_ID: KeySpaceId = [0xff, 0xff, 0xff]; #[macro_export] macro_rules! plain_request { @@ -41,14 +50,90 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { } } -#[derive(Clone)] -pub struct RawApiV1; +#[derive(Copy, Clone)] +enum KeyMode { + Raw, + Txn, +} -impl RequestCodec for RawApiV1 {} +impl From for u8 { + fn from(mode: KeyMode) -> u8 { + match mode { + KeyMode::Raw => b'r', + KeyMode::Txn => b'x', + } + } +} + +type Prefix = [u8; KEYSPACE_PREFIX_LEN]; + +type KeySpaceId = [u8; 3]; + +#[derive(Copy, Clone)] +struct KeySpaceCodec { + mode: KeyMode, + id: KeySpaceId, +} + +impl From for Prefix { + fn from(codec: KeySpaceCodec) -> Self { + [codec.mode.into(), codec.id[0], codec.id[1], codec.id[2]] + } +} + +impl RequestCodec for KeySpaceCodec { + fn encode_key(&self, mut key: Key) -> Key { + let this = self.clone(); + let mut encoded = Vec::with_capacity(key.len() + KEYSPACE_PREFIX_LEN); + let prefix: Prefix = this.into(); + encoded.extend_from_slice(&prefix); + encoded.append(&mut key); + encoded.into() + } + + fn decode_key(&self, mut key: Key) -> Result { + let prefix: Prefix = self.clone().into(); + + if !key.starts_with(&prefix) { + return Err(Error::CorruptedKeyspace { + expected: prefix.to_vec(), + actual: key[..KEYSPACE_PREFIX_LEN].to_vec(), + key: key.into(), + }); + } + + Ok(key.split_off(KEYSPACE_PREFIX_LEN).into()) + } + + fn encode_range(&self, start: Key, end: Key) -> (Key, Key) { + (self.encode_key(start), self.encode_key(end)) + } + + fn encode_pd_query(&self, key: Key) -> Key { + todo!() + } + + fn decode_region(&self, region: Region) -> Result { + todo!() + } + + fn is_plain(&self) -> bool { + todo!() + } +} #[derive(Clone)] pub struct TxnApiV1; +#[derive(Clone)] +pub struct RawApiV1; + +pub trait RawCodec: RequestCodec {} + +pub trait TxnCodec: RequestCodec {} + +impl RequestCodec for RawApiV1 {} + impl RequestCodec for TxnApiV1 { fn encode_pd_query(&self, key: Key) -> Key { key.to_encoded() @@ -62,8 +147,6 @@ impl RequestCodec for TxnApiV1 { } } -pub trait RawCodec: RequestCodec {} -pub trait TxnCodec: RequestCodec {} - impl RawCodec for RawApiV1 {} -impl TxnCodec for TxnApiV1 {} + +impl TxnCodec for TxnApiV1 {} \ No newline at end of file diff --git a/tikv-client-common/src/errors.rs b/tikv-client-common/src/errors.rs index db309107..89c3a844 100644 --- a/tikv-client-common/src/errors.rs +++ b/tikv-client-common/src/errors.rs @@ -93,6 +93,12 @@ pub enum Error { inner: Box, success_keys: Vec>, }, + #[error("Corrupted keyspace: expected: {:?}, actual: {:?}, key: {:?}" , expected, actual, key)] + CorruptedKeyspace { + expected: Vec, + actual: Vec, + key: Vec + }, } impl From for Error { From 59002d1078a48bfb3619c0aa835ca6d06e43f7ac Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 1 Jul 2022 15:24:25 +0800 Subject: [PATCH 11/43] impl KeyspaceCodec, along with RawKeyspaceCodec and TxnKeyspaceCodec Signed-off-by: iosmanthus --- src/raw/client.rs | 13 +--- src/request/request_codec.rs | 121 +++++++++++++++++++++++++++-------- 2 files changed, 96 insertions(+), 38 deletions(-) diff --git a/src/raw/client.rs b/src/raw/client.rs index 7ef1923b..e18d70fb 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -19,7 +19,6 @@ use crate::{ }, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; -use crate::request::request_codec::RawApiV1; const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; @@ -51,16 +50,6 @@ impl Clone for Client { } } -impl Client { - pub async fn new>( - pd_endpoints: Vec, - logger: Option, - ) -> Result { - Self::new_with_config(pd_endpoints, Config::default(), RawApiV1, logger).await - } -} - - impl Client { /// Create a raw [`Client`] and connect to the TiKV cluster. /// @@ -80,7 +69,7 @@ impl Client { /// .unwrap(); /// # }); /// ``` - pub async fn new_with_codec>( + pub async fn new>( pd_endpoints: Vec, codec: C, logger: Option, diff --git a/src/request/request_codec.rs b/src/request/request_codec.rs index 773d5402..a8d7c97b 100644 --- a/src/request/request_codec.rs +++ b/src/request/request_codec.rs @@ -1,15 +1,18 @@ use tikv_client_common::Error; use tikv_client_proto::metapb::Region; -use tikv_client_store::Request; -use crate::{Key, kv::codec::decode_bytes_in_place, Result}; +use crate::{kv::codec::decode_bytes_in_place, Key, Result}; -const KEYSPACE_PREFIX_LEN: usize = 4; const RAW_MODE_PREFIX: u8 = b'r'; const TXN_MODE_PREFIX: u8 = b'x'; + +const KEYSPACE_PREFIX_LEN: usize = 4; + +const RAW_MODE_MIN_KEY: Prefix = [RAW_MODE_PREFIX, 0, 0, 0]; const RAW_MODE_MAX_KEY: Prefix = [RAW_MODE_PREFIX + 1, 0, 0, 0]; + +const TXN_MODE_MIN_KEY: Prefix = [TXN_MODE_PREFIX, 0, 0, 0]; const TXN_MODE_MAX_KEY: Prefix = [TXN_MODE_PREFIX + 1, 0, 0, 0]; -const MAX_KEYSPACE_ID: KeySpaceId = [0xff, 0xff, 0xff]; #[macro_export] macro_rules! plain_request { @@ -50,6 +53,34 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { } } +#[derive(Clone)] +pub struct TxnApiV1; + +#[derive(Clone)] +pub struct RawApiV1; + +pub trait RawCodec: RequestCodec {} + +pub trait TxnCodec: RequestCodec {} + +impl RequestCodec for RawApiV1 {} + +impl RequestCodec for TxnApiV1 { + fn encode_pd_query(&self, key: Key) -> Key { + key.to_encoded() + } + + fn decode_region(&self, mut region: Region) -> Result { + decode_bytes_in_place(region.mut_start_key(), false)?; + decode_bytes_in_place(region.mut_end_key(), false)?; + Ok(region) + } +} + +impl RawCodec for RawApiV1 {} + +impl TxnCodec for TxnApiV1 {} + #[derive(Copy, Clone)] enum KeyMode { Raw, @@ -65,6 +96,22 @@ impl From for u8 { } } +impl KeyMode { + fn min_key(self) -> Key { + match self { + KeyMode::Raw => Key::from(RAW_MODE_MIN_KEY.to_vec()), + KeyMode::Txn => Key::from(TXN_MODE_MIN_KEY.to_vec()), + } + } + + fn max_key(self) -> Key { + match self { + KeyMode::Raw => Key::from(RAW_MODE_MAX_KEY.to_vec()), + KeyMode::Txn => Key::from(TXN_MODE_MAX_KEY.to_vec()), + } + } +} + type Prefix = [u8; KEYSPACE_PREFIX_LEN]; type KeySpaceId = [u8; 3]; @@ -110,43 +157,65 @@ impl RequestCodec for KeySpaceCodec { } fn encode_pd_query(&self, key: Key) -> Key { - todo!() + self.encode_key(key).to_encoded() } - fn decode_region(&self, region: Region) -> Result { - todo!() + fn decode_region(&self, mut region: Region) -> Result { + decode_bytes_in_place(region.mut_start_key(), false)?; + decode_bytes_in_place(region.mut_end_key(), false)?; + + if region.get_start_key() < self.mode.min_key().as_slice() { + *region.mut_start_key() = vec![]; + } else { + *region.mut_start_key() = self + .decode_key(region.get_start_key().to_vec().into())? + .into(); + } + + if region.get_end_key() > self.mode.max_key().as_slice() { + *region.mut_end_key() = vec![]; + } else { + *region.mut_end_key() = self + .decode_key(region.get_end_key().to_vec().into())? + .into(); + } + + Ok(region) } fn is_plain(&self) -> bool { - todo!() + false } } #[derive(Clone)] -pub struct TxnApiV1; - -#[derive(Clone)] -pub struct RawApiV1; +pub struct RawKeyspaceCodec(KeySpaceCodec); -pub trait RawCodec: RequestCodec {} +impl RawKeyspaceCodec { + pub fn new(id: KeySpaceId) -> Self { + RawKeyspaceCodec(KeySpaceCodec { + mode: KeyMode::Raw, + id, + }) + } +} -pub trait TxnCodec: RequestCodec {} +impl RequestCodec for RawKeyspaceCodec {} -impl RequestCodec for RawApiV1 {} +impl RawCodec for RawKeyspaceCodec {} -impl RequestCodec for TxnApiV1 { - fn encode_pd_query(&self, key: Key) -> Key { - key.to_encoded() - } - - fn decode_region(&self, mut region: Region) -> Result { - decode_bytes_in_place(region.mut_start_key(), false)?; - decode_bytes_in_place(region.mut_end_key(), false)?; +#[derive(Clone)] +pub struct TxnKeyspaceCodec(KeySpaceCodec); - Ok(region) +impl TxnKeyspaceCodec { + pub fn new(id: KeySpaceId) -> Self { + TxnKeyspaceCodec(KeySpaceCodec { + mode: KeyMode::Txn, + id, + }) } } -impl RawCodec for RawApiV1 {} +impl RequestCodec for TxnKeyspaceCodec {} -impl TxnCodec for TxnApiV1 {} \ No newline at end of file +impl TxnCodec for TxnKeyspaceCodec {} From a4407945130bcbb0037346833f216b1553b9ca15 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 1 Jul 2022 15:29:48 +0800 Subject: [PATCH 12/43] fix fmt check Signed-off-by: iosmanthus --- src/kv/key.rs | 9 ++++++--- tikv-client-common/src/errors.rs | 9 +++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 2ba556e1..b83e0fd2 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -7,8 +7,11 @@ use crate::kv::codec::{self, BytesEncoder}; use proptest::{arbitrary::any_with, collection::size_range}; #[cfg(test)] use proptest_derive::Arbitrary; -use std::{fmt, ops::Bound, u8}; -use std::ops::{Deref, DerefMut}; +use std::{ + fmt, + ops::{Bound, Deref, DerefMut}, + u8, +}; use tikv_client_proto::kvrpcpb; const _PROPTEST_KEY_MAX: usize = 1024 * 2; // 2 KB @@ -193,4 +196,4 @@ impl DerefMut for Key { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } -} \ No newline at end of file +} diff --git a/tikv-client-common/src/errors.rs b/tikv-client-common/src/errors.rs index 89c3a844..019d213d 100644 --- a/tikv-client-common/src/errors.rs +++ b/tikv-client-common/src/errors.rs @@ -93,11 +93,16 @@ pub enum Error { inner: Box, success_keys: Vec>, }, - #[error("Corrupted keyspace: expected: {:?}, actual: {:?}, key: {:?}" , expected, actual, key)] + #[error( + "Corrupted keyspace: expected: {:?}, actual: {:?}, key: {:?}", + expected, + actual, + key + )] CorruptedKeyspace { expected: Vec, actual: Vec, - key: Vec + key: Vec, }, } From 0a72d3108a204f6b17c4bbb8b4a17f7d42fc88f6 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 1 Jul 2022 15:37:11 +0800 Subject: [PATCH 13/43] rename request_codec.rs to codec.rs Signed-off-by: iosmanthus --- examples/pessimistic.rs | 2 +- examples/raw.rs | 2 +- examples/transaction.rs | 2 +- src/mock.rs | 2 +- src/pd/client.rs | 2 +- src/raw/client.rs | 4 ++-- src/raw/requests.rs | 2 +- src/region_cache.rs | 4 ++-- src/request/{request_codec.rs => codec.rs} | 0 src/request/mod.rs | 4 ++-- src/request/plan.rs | 2 +- src/request/plan_builder.rs | 2 +- src/transaction/client.rs | 2 +- src/transaction/requests.rs | 2 +- tests/common/mod.rs | 2 +- tests/failpoint_tests.rs | 2 +- tests/integration_tests.rs | 2 +- tests/mock_tikv_tests.rs | 2 +- 18 files changed, 20 insertions(+), 20 deletions(-) rename src/request/{request_codec.rs => codec.rs} (100%) diff --git a/examples/pessimistic.rs b/examples/pessimistic.rs index 360e4746..861742b1 100644 --- a/examples/pessimistic.rs +++ b/examples/pessimistic.rs @@ -4,7 +4,7 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::request_codec::TxnApiV1, Config, Key, TransactionClient as Client, TransactionOptions, + request::codec::TxnApiV1, Config, Key, TransactionClient as Client, TransactionOptions, Value, }; diff --git a/examples/raw.rs b/examples/raw.rs index cc3ea3b1..dd0b6c7c 100644 --- a/examples/raw.rs +++ b/examples/raw.rs @@ -6,7 +6,7 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::request_codec::RawApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, + request::codec::RawApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, Result, Value, }; diff --git a/examples/transaction.rs b/examples/transaction.rs index ae8cef18..a960faaf 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -4,7 +4,7 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::request_codec::{TxnApiV1, TxnCodec}, + request::codec::{TxnApiV1, TxnCodec}, BoundRange, Config, Key, KvPair, TransactionClient as Client, Value, }; diff --git a/src/mock.rs b/src/mock.rs index b05d9da4..8cc9c963 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -8,7 +8,7 @@ use crate::{ pd::{PdClient, PdRpcClient, RetryClient}, region::{RegionId, RegionWithLeader}, - request::request_codec::RawApiV1, + request::codec::RawApiV1, store::RegionStore, Config, Error, Key, Result, Timestamp, }; diff --git a/src/pd/client.rs b/src/pd/client.rs index 157b7d4f..021f20f4 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -17,7 +17,7 @@ use crate::{ pd::{retry::RetryClientTrait, RetryClient}, region::{RegionId, RegionVerId, RegionWithLeader}, region_cache::RegionCache, - request::request_codec::RequestCodec, + request::codec::RequestCodec, store::RegionStore, BoundRange, Config, Key, Result, SecurityManager, Timestamp, }; diff --git a/src/raw/client.rs b/src/raw/client.rs index e18d70fb..be7aae0d 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -14,7 +14,7 @@ use crate::{ pd::{PdClient, PdRpcClient}, raw::lowering::*, request::{ - request_codec::{RawCodec, RequestCodec}, + codec::{RawCodec, RequestCodec}, Collect, CollectSingle, Plan, }, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, @@ -792,7 +792,7 @@ mod tests { use crate::{ mock::{MockKvClient, MockPdClient}, - request::request_codec::RawApiV1, + request::codec::RawApiV1, Result, }; diff --git a/src/raw/requests.rs b/src/raw/requests.rs index a3d8de3d..a58ce45e 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -14,7 +14,7 @@ use crate::{ pd::PdClient, plain_request, plain_response, request::{ - plan::ResponseWithShard, request_codec::RequestCodec, Collect, CollectSingle, + plan::ResponseWithShard, codec::RequestCodec, Collect, CollectSingle, DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, diff --git a/src/region_cache.rs b/src/region_cache.rs index e8beb199..9e57f1cb 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -14,7 +14,7 @@ use tikv_client_proto::metapb::{self, Store}; use crate::{ pd::{RetryClient, RetryClientTrait}, region::{RegionId, RegionVerId, RegionWithLeader, StoreId}, - request::request_codec::RequestCodec, + request::codec::RequestCodec, Key, Result, }; @@ -263,7 +263,7 @@ mod test { use crate::{ pd::RetryClientTrait, region::{RegionId, RegionWithLeader}, - request::request_codec::{RawApiV1, RequestCodec}, + request::codec::{RawApiV1, RequestCodec}, Key, Result, }; diff --git a/src/request/request_codec.rs b/src/request/codec.rs similarity index 100% rename from src/request/request_codec.rs rename to src/request/codec.rs diff --git a/src/request/mod.rs b/src/request/mod.rs index ff02e269..6325b935 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -26,7 +26,7 @@ pub mod plan; mod plan_builder; #[macro_use] mod shard; -pub mod request_codec; +pub mod codec; /// Abstracts any request sent to a TiKV server. #[async_trait] @@ -87,7 +87,7 @@ mod test { use crate::{ mock::{MockKvClient, MockPdClient}, - request::{request_codec::RequestCodec, KvRequest}, + request::{codec::RequestCodec, KvRequest}, store::store_stream_for_keys, transaction::lowering::new_commit_request, Error, Key, Result, diff --git a/src/request/plan.rs b/src/request/plan.rs index 4de3338e..14bad044 100644 --- a/src/request/plan.rs +++ b/src/request/plan.rs @@ -13,7 +13,7 @@ use tikv_client_store::{HasKeyErrors, HasRegionError, HasRegionErrors, KvClient} use crate::{ backoff::Backoff, pd::PdClient, - request::{request_codec::RequestCodec, KvRequest, Shardable}, + request::{codec::RequestCodec, KvRequest, Shardable}, stats::tikv_stats, store::RegionStore, transaction::{resolve_locks, HasLocks}, diff --git a/src/request/plan_builder.rs b/src/request/plan_builder.rs index 72aa8d4e..cae0ba6c 100644 --- a/src/request/plan_builder.rs +++ b/src/request/plan_builder.rs @@ -8,7 +8,7 @@ use crate::{ backoff::Backoff, pd::PdClient, request::{ - request_codec::RequestCodec, DefaultProcessor, Dispatch, ExtractError, KvRequest, Merge, + codec::RequestCodec, DefaultProcessor, Dispatch, ExtractError, KvRequest, Merge, MergeResponse, Plan, Process, ProcessResponse, ResolveLock, RetryableMultiRegion, Shardable, }, diff --git a/src/transaction/client.rs b/src/transaction/client.rs index e94dc923..de8ef4e9 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -10,7 +10,7 @@ use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, pd::{PdClient, PdRpcClient}, - request::{request_codec::TxnCodec, Plan}, + request::{codec::TxnCodec, Plan}, timestamp::TimestampExt, transaction::{Snapshot, Transaction, TransactionOptions}, Result, diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 15c457d0..3509d620 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -15,7 +15,7 @@ use crate::{ pd::PdClient, plain_request, plain_response, request::{ - request_codec::RequestCodec, Collect, CollectSingle, CollectWithShard, DefaultProcessor, + codec::RequestCodec, Collect, CollectSingle, CollectWithShard, DefaultProcessor, KvRequest, Merge, Process, ResponseWithShard, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index d6594761..1310d4ee 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -4,7 +4,7 @@ use futures_timer::Delay; use log::{info, warn}; use std::{env, time::Duration}; use tikv_client::{ - request::request_codec::{RawApiV1, TxnApiV1}, + request::codec::{RawApiV1, TxnApiV1}, ColumnFamily, Key, RawClient, Result, TransactionClient, }; diff --git a/tests/failpoint_tests.rs b/tests/failpoint_tests.rs index cc926d17..bcb2161f 100644 --- a/tests/failpoint_tests.rs +++ b/tests/failpoint_tests.rs @@ -6,7 +6,7 @@ use fail::FailScenario; use serial_test::serial; use std::time::Duration; use tikv_client::{ - request::request_codec::TxnApiV1, transaction::HeartbeatOption, Result, TransactionClient, + request::codec::TxnApiV1, transaction::HeartbeatOption, Result, TransactionClient, TransactionOptions, }; diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 99ba86b4..d1aab796 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -22,7 +22,7 @@ use std::{ iter, }; use tikv_client::{ - request::request_codec::{RawApiV1, RawCodec, TxnApiV1}, + request::codec::{RawApiV1, RawCodec, TxnApiV1}, transaction::HeartbeatOption, Error, Key, KvPair, PdClient, RawClient, Result, Transaction, TransactionClient, TransactionOptions, Value, diff --git a/tests/mock_tikv_tests.rs b/tests/mock_tikv_tests.rs index 5d8963f5..5e0a76c1 100644 --- a/tests/mock_tikv_tests.rs +++ b/tests/mock_tikv_tests.rs @@ -4,7 +4,7 @@ mod test { use log::debug; use mock_tikv::{start_mock_pd_server, start_mock_tikv_server, MOCK_PD_PORT}; use simple_logger::SimpleLogger; - use tikv_client::{request::request_codec::RawApiV1, KvPair, RawClient}; + use tikv_client::{request::codec::RawApiV1, KvPair, RawClient}; #[tokio::test] #[ignore] From 19c312379de967c84ca7655642851c3a51f10b4a Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 1 Jul 2022 20:16:31 +0800 Subject: [PATCH 14/43] git fire!: wip impl RequestCodec for requests Signed-off-by: iosmanthus --- src/raw/requests.rs | 51 ++++++-------------------------------------- src/request/codec.rs | 18 ---------------- src/request/mod.rs | 30 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 63 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index a58ce45e..86dc54dd 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -12,10 +12,9 @@ use super::RawRpcRequest; use crate::{ collect_first, pd::PdClient, - plain_request, plain_response, request::{ - plan::ResponseWithShard, codec::RequestCodec, Collect, CollectSingle, - DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, + codec::RequestCodec, plan::ResponseWithShard, Collect, CollectSingle, DefaultProcessor, + KvRequest, Merge, Process, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, transaction::HasLocks, @@ -31,20 +30,7 @@ pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::R req } -impl KvRequest for kvrpcpb::RawGetRequest { - type Response = kvrpcpb::RawGetResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +kv_request_with_key!(kvrpcpb::RawGetRequest, kvrpcpb::RawGetResponse); shardable_key!(kvrpcpb::RawGetRequest); collect_first!(kvrpcpb::RawGetResponse); @@ -78,20 +64,7 @@ pub fn new_raw_batch_get_request( req } -impl KvRequest for kvrpcpb::RawBatchGetRequest { - type Response = kvrpcpb::RawBatchGetResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +kv_request_with_key!(kvrpcpb::RawBatchGetRequest, kvrpcpb::RawBatchGetResponse); shardable_keys!(kvrpcpb::RawBatchGetRequest); impl Merge for Collect { @@ -120,22 +93,10 @@ pub fn new_raw_put_request( req } -impl KvRequest for kvrpcpb::RawPutRequest { - type Response = kvrpcpb::RawPutResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +kv_request_with_key!(kvrpcpb::RawPutRequest, kvrpcpb::RawPutResponse); shardable_key!(kvrpcpb::RawPutRequest); collect_first!(kvrpcpb::RawPutResponse); + impl SingleKey for kvrpcpb::RawPutRequest { fn key(&self) -> &Vec { &self.key diff --git a/src/request/codec.rs b/src/request/codec.rs index a8d7c97b..1a03a57a 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -14,24 +14,6 @@ const RAW_MODE_MAX_KEY: Prefix = [RAW_MODE_PREFIX + 1, 0, 0, 0]; const TXN_MODE_MIN_KEY: Prefix = [TXN_MODE_PREFIX, 0, 0, 0]; const TXN_MODE_MAX_KEY: Prefix = [TXN_MODE_PREFIX + 1, 0, 0, 0]; -#[macro_export] -macro_rules! plain_request { - ($req: ident, $codec: ident) => { - if $codec.is_plain() { - return ::std::borrow::Cow::Borrowed($req); - } - }; -} - -#[macro_export] -macro_rules! plain_response { - ($resp: ident, $codec: ident) => { - if $codec.is_plain() { - return Ok($resp); - } - }; -} - pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { fn encode_key(&self, key: Key) -> Key { key diff --git a/src/request/mod.rs b/src/request/mod.rs index 6325b935..496f2541 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -41,6 +41,36 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { } } +#[macro_export] +macro_rules! kv_request_with_key { + ($req: ty, $resp: ty) => { + impl KvRequest for $req + where + C: RequestCodec, + { + type Response = $resp; + + fn encode_request(&self, codec: &C) -> Cow { + if codec.is_plain() { + return Cow::Borrowed(self); + } + unimplemented!() + } + + fn decode_response( + &self, + codec: &C, + resp: Self::Response, + ) -> crate::Result { + if codec.is_plain() { + return Ok(resp); + } + unimplemented!() + } + } + }; +} + #[derive(Clone, Debug, new, Eq, PartialEq)] pub struct RetryOptions { /// How to retry when there is a region error and we need to resolve regions with PD. From 624c68ef320c987671e84edb98b66953bfe5afb0 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Mon, 4 Jul 2022 20:13:12 +0800 Subject: [PATCH 15/43] impl KvRequest for raw requests Signed-off-by: iosmanthus --- Cargo.toml | 1 + src/raw/requests.rs | 156 +++++++++++++-------------- src/region_cache.rs | 2 +- src/request/codec.rs | 106 ++++++++++++++----- src/request/mod.rs | 81 +++++++++++++- src/transaction/requests.rs | 203 +++--------------------------------- 6 files changed, 245 insertions(+), 304 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 77f97216..fad2ae0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ slog-term = { version = "2.4" } thiserror = "1" tokio = { version = "1", features = [ "sync", "rt-multi-thread", "macros" ] } async-recursion = "0.3" +paste = "1.0" tikv-client-common = { version = "0.1.0", path = "tikv-client-common" } tikv-client-pd = { version = "0.1.0", path = "tikv-client-pd" } diff --git a/src/raw/requests.rs b/src/raw/requests.rs index 86dc54dd..e80c6bac 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -5,23 +5,25 @@ use std::{any::Any, borrow::Cow, ops::Range, sync::Arc}; use async_trait::async_trait; use futures::stream::BoxStream; use grpcio::CallOption; + use tikv_client_proto::{kvrpcpb, metapb, tikvpb::TikvClient}; use tikv_client_store::Request; -use super::RawRpcRequest; use crate::{ collect_first, + ColumnFamily, + Key, + KvPair, pd::PdClient, request::{ - codec::RequestCodec, plan::ResponseWithShard, Collect, CollectSingle, DefaultProcessor, - KvRequest, Merge, Process, Shardable, SingleKey, + codec::RequestCodec, Collect, CollectSingle, DefaultProcessor, KvRequest, + Merge, plan::ResponseWithShard, Process, Shardable, SingleKey, }, - store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, - transaction::HasLocks, - util::iter::FlatMapOkIterExt, - ColumnFamily, Key, KvPair, Result, Value, + Result, store::{RegionStore, store_stream_for_keys, store_stream_for_ranges}, transaction::HasLocks, util::iter::FlatMapOkIterExt, Value, }; +use super::RawRpcRequest; + pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::RawGetRequest { let mut req = kvrpcpb::RawGetRequest::default(); req.set_key(key); @@ -30,7 +32,7 @@ pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::R req } -kv_request_with_key!(kvrpcpb::RawGetRequest, kvrpcpb::RawGetResponse); +impl_kv_request_for_single_key_op!(kvrpcpb::RawGetRequest, kvrpcpb::RawGetResponse); shardable_key!(kvrpcpb::RawGetRequest); collect_first!(kvrpcpb::RawGetResponse); @@ -64,7 +66,8 @@ pub fn new_raw_batch_get_request( req } -kv_request_with_key!(kvrpcpb::RawBatchGetRequest, kvrpcpb::RawBatchGetResponse); +impl_kv_request_for_batch_get!(kvrpcpb::RawBatchGetRequest, kvrpcpb::RawBatchGetResponse); + shardable_keys!(kvrpcpb::RawBatchGetRequest); impl Merge for Collect { @@ -93,7 +96,7 @@ pub fn new_raw_put_request( req } -kv_request_with_key!(kvrpcpb::RawPutRequest, kvrpcpb::RawPutResponse); +impl_kv_request_for_single_key_op!(kvrpcpb::RawPutRequest, kvrpcpb::RawPutResponse); shardable_key!(kvrpcpb::RawPutRequest); collect_first!(kvrpcpb::RawPutResponse); @@ -120,13 +123,15 @@ impl KvRequest for kvrpcpb::RawBatchPutRequest { type Response = kvrpcpb::RawBatchPutResponse; fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } + if codec.is_plain() { + return Cow::Borrowed(self); + } + + let mut req = self.clone(); + + *req.mut_pairs() = codec.encode_pairs(req.take_pairs()); - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() + Cow::Owned(req) } } @@ -165,20 +170,7 @@ pub fn new_raw_delete_request( req } -impl KvRequest for kvrpcpb::RawDeleteRequest { - type Response = kvrpcpb::RawDeleteResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::RawDeleteRequest, kvrpcpb::RawDeleteResponse); shardable_key!(kvrpcpb::RawDeleteRequest); collect_first!(kvrpcpb::RawDeleteResponse); impl SingleKey for kvrpcpb::RawDeleteRequest { @@ -202,13 +194,15 @@ impl KvRequest for kvrpcpb::RawBatchDeleteRequest { type Response = kvrpcpb::RawBatchDeleteResponse; fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } + if codec.is_plain() { + return Cow::Borrowed(self); + } + + let mut req = self.clone(); - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() + *req.mut_keys() = codec.encode_keys(req.take_keys()); + + Cow::Owned(req) } } @@ -231,13 +225,17 @@ impl KvRequest for kvrpcpb::RawDeleteRangeRequest { type Response = kvrpcpb::RawDeleteRangeResponse; fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } + if codec.is_plain() { + return Cow::Borrowed(self); + } + + let mut req = self.clone(); - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() + let (start, end) = (req.take_start_key(), req.take_end_key()); + *req.mut_start_key() = codec.encode_key(start); + *req.mut_end_key() = codec.encode_key(end); + + Cow::Owned(req) } } @@ -260,20 +258,7 @@ pub fn new_raw_scan_request( req } -impl KvRequest for kvrpcpb::RawScanRequest { - type Response = kvrpcpb::RawScanResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_scan_op!(kvrpcpb::RawScanRequest, kvrpcpb::RawScanResponse, kvs); shardable_range!(kvrpcpb::RawScanRequest); impl Merge for Collect { @@ -306,13 +291,15 @@ impl KvRequest for kvrpcpb::RawBatchScanRequest { type Response = kvrpcpb::RawBatchScanResponse; fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } + if codec.is_plain() { + return Cow::Borrowed(self); + } - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() + let mut req = self.clone(); + + *req.mut_ranges() = codec.encode_ranges(req.take_ranges()); + + Cow::Owned(req) } } @@ -361,20 +348,7 @@ pub fn new_cas_request( req } -impl KvRequest for kvrpcpb::RawCasRequest { - type Response = kvrpcpb::RawCasResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::RawCasRequest, kvrpcpb::RawCasResponse); shardable_key!(kvrpcpb::RawCasRequest); collect_first!(kvrpcpb::RawCasResponse); impl SingleKey for kvrpcpb::RawCasRequest { @@ -397,7 +371,7 @@ impl Process for DefaultProcessor { } type RawCoprocessorRequestDataBuilder = - Arc) -> Vec + Send + Sync>; +Arc) -> Vec + Send + Sync>; pub fn new_raw_coprocessor_request( copr_name: String, @@ -467,8 +441,8 @@ impl Shardable for RawCoprocessorRequest { #[allow(clippy::type_complexity)] impl - Process>>>> - for DefaultProcessor +Process>>>> +for DefaultProcessor { type Out = Vec<(Vec, Vec>)>; @@ -517,29 +491,43 @@ impl_raw_rpc_request!(RawDeleteRangeRequest); impl_raw_rpc_request!(RawCasRequest); impl HasLocks for kvrpcpb::RawGetResponse {} + impl HasLocks for kvrpcpb::RawBatchGetResponse {} + impl HasLocks for kvrpcpb::RawPutResponse {} + impl HasLocks for kvrpcpb::RawBatchPutResponse {} + impl HasLocks for kvrpcpb::RawDeleteResponse {} + impl HasLocks for kvrpcpb::RawBatchDeleteResponse {} + impl HasLocks for kvrpcpb::RawScanResponse {} + impl HasLocks for kvrpcpb::RawBatchScanResponse {} + impl HasLocks for kvrpcpb::RawDeleteRangeResponse {} + impl HasLocks for kvrpcpb::RawCasResponse {} + impl HasLocks for kvrpcpb::RawCoprocessorResponse {} #[cfg(test)] mod test { - use super::*; + use std::any::Any; + + use futures::executor; + + use tikv_client_proto::kvrpcpb; + use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, + Key, mock::{MockKvClient, MockPdClient}, request::Plan, - Key, }; - use futures::executor; - use std::any::Any; - use tikv_client_proto::kvrpcpb; + + use super::*; #[test] #[ignore] diff --git a/src/region_cache.rs b/src/region_cache.rs index 9e57f1cb..1610720f 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -135,7 +135,7 @@ impl RegionCache { let mut r = self .inner_client .clone() - .get_region(self.codec.encode_pd_query(key).into()) + .get_region(self.codec.encode_pd_query(key.into())) .await?; r.region = self.codec.decode_region(r.region)?; self.add_region(r.clone()).await; diff --git a/src/request/codec.rs b/src/request/codec.rs index 1a03a57a..51e25c66 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,7 +1,8 @@ use tikv_client_common::Error; +use tikv_client_proto::kvrpcpb; use tikv_client_proto::metapb::Region; -use crate::{kv::codec::decode_bytes_in_place, Key, Result}; +use crate::{Key, kv::codec::decode_bytes_in_place, Result}; const RAW_MODE_PREFIX: u8 = b'r'; const TXN_MODE_PREFIX: u8 = b'x'; @@ -14,22 +15,41 @@ const RAW_MODE_MAX_KEY: Prefix = [RAW_MODE_PREFIX + 1, 0, 0, 0]; const TXN_MODE_MIN_KEY: Prefix = [TXN_MODE_PREFIX, 0, 0, 0]; const TXN_MODE_MAX_KEY: Prefix = [TXN_MODE_PREFIX + 1, 0, 0, 0]; +const MAX_KEYSPACE_ID: KeySpaceId = [0xff, 0xff, 0xff]; + pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { - fn encode_key(&self, key: Key) -> Key { + fn encode_key(&self, key: Vec) -> Vec { key } - fn decode_key(&self, key: Key) -> Result { + + fn encode_keys(&self, keys: Vec>) -> Vec> { + keys + } + + fn encode_pairs(&self, pairs: Vec) -> Vec { pairs } + + fn decode_key(&self, key: Vec) -> Result> { Ok(key) } - fn encode_range(&self, start: Key, end: Key) -> (Key, Key) { + + fn decode_pairs(&self, pairs: Vec) -> Result> { + Ok(pairs) + } + + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { (start, end) } - fn encode_pd_query(&self, key: Key) -> Key { + + fn encode_ranges(&self, ranges: Vec) -> Vec { ranges } + + fn encode_pd_query(&self, key: Vec) -> Vec { key } + fn decode_region(&self, region: Region) -> Result { Ok(region) } + fn is_plain(&self) -> bool { true } @@ -48,8 +68,8 @@ pub trait TxnCodec: RequestCodec {} impl RequestCodec for RawApiV1 {} impl RequestCodec for TxnApiV1 { - fn encode_pd_query(&self, key: Key) -> Key { - key.to_encoded() + fn encode_pd_query(&self, key: Vec) -> Vec { + Key::from(key).to_encoded().into() } fn decode_region(&self, mut region: Region) -> Result { @@ -79,17 +99,17 @@ impl From for u8 { } impl KeyMode { - fn min_key(self) -> Key { + fn min_key(self) -> Vec { match self { - KeyMode::Raw => Key::from(RAW_MODE_MIN_KEY.to_vec()), - KeyMode::Txn => Key::from(TXN_MODE_MIN_KEY.to_vec()), + KeyMode::Raw => RAW_MODE_MIN_KEY.to_vec(), + KeyMode::Txn => TXN_MODE_MIN_KEY.to_vec(), } } - fn max_key(self) -> Key { + fn max_key(self) -> Vec { match self { - KeyMode::Raw => Key::from(RAW_MODE_MAX_KEY.to_vec()), - KeyMode::Txn => Key::from(TXN_MODE_MAX_KEY.to_vec()), + KeyMode::Raw => RAW_MODE_MAX_KEY.to_vec(), + KeyMode::Txn => TXN_MODE_MAX_KEY.to_vec(), } } } @@ -111,55 +131,89 @@ impl From for Prefix { } impl RequestCodec for KeySpaceCodec { - fn encode_key(&self, mut key: Key) -> Key { + fn encode_key(&self, mut key: Vec) -> Vec { let this = self.clone(); let mut encoded = Vec::with_capacity(key.len() + KEYSPACE_PREFIX_LEN); let prefix: Prefix = this.into(); encoded.extend_from_slice(&prefix); encoded.append(&mut key); - encoded.into() + encoded + } + + fn encode_keys(&self, mut keys: Vec>) -> Vec> { + keys.into_iter().map(|key| self.encode_key(key)).collect() } - fn decode_key(&self, mut key: Key) -> Result { + fn encode_pairs(&self, mut pairs: Vec) -> Vec { + for pair in pairs.iter_mut() { + *pair.mut_key() = self.encode_key(pair.take_key()); + } + + pairs + } + + fn decode_key(&self, mut key: Vec) -> Result> { let prefix: Prefix = self.clone().into(); if !key.starts_with(&prefix) { return Err(Error::CorruptedKeyspace { expected: prefix.to_vec(), actual: key[..KEYSPACE_PREFIX_LEN].to_vec(), - key: key.into(), + key, }); } - Ok(key.split_off(KEYSPACE_PREFIX_LEN).into()) + Ok(key.split_off(KEYSPACE_PREFIX_LEN)) + } + + fn decode_pairs(&self, mut pairs: Vec) -> Result> { + for pair in pairs.iter_mut() { + *pair.mut_key() = self.decode_key(pair.take_key())?; + } + + Ok(pairs) } - fn encode_range(&self, start: Key, end: Key) -> (Key, Key) { - (self.encode_key(start), self.encode_key(end)) + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + if self.id == MAX_KEYSPACE_ID { + (self.encode_key(start), self.mode.max_key()) + } else { + (self.encode_key(start), self.encode_key(end)) + } + } + + fn encode_ranges(&self, mut ranges: Vec) -> Vec { + for range in ranges.iter_mut() { + let (start, end) = self.encode_range(range.take_start_key(), range.take_end_key()); + *range.mut_start_key() = start; + *range.mut_end_key() = end; + } + + ranges } - fn encode_pd_query(&self, key: Key) -> Key { - self.encode_key(key).to_encoded() + fn encode_pd_query(&self, key: Vec) -> Vec { + Key::from(self.encode_key(key)).to_encoded().into() } fn decode_region(&self, mut region: Region) -> Result { decode_bytes_in_place(region.mut_start_key(), false)?; decode_bytes_in_place(region.mut_end_key(), false)?; + // Map the region's start key to the keyspace's start key. if region.get_start_key() < self.mode.min_key().as_slice() { *region.mut_start_key() = vec![]; } else { *region.mut_start_key() = self - .decode_key(region.get_start_key().to_vec().into())? - .into(); + .decode_key(region.get_start_key().to_vec())?; } + // Map the region's end key to the keyspace's end key. if region.get_end_key() > self.mode.max_key().as_slice() { *region.mut_end_key() = vec![]; } else { *region.mut_end_key() = self - .decode_key(region.get_end_key().to_vec().into())? - .into(); + .decode_key(region.get_end_key().to_vec())?; } Ok(region) diff --git a/src/request/mod.rs b/src/request/mod.rs index 496f2541..dd3be3bf 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -11,6 +11,7 @@ use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF, PESSIMISTIC_BACKOFF}, transaction::HasLocks, }; +use crate::request::codec::RequestCodec; pub use self::{ plan::{ @@ -42,7 +43,7 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { } #[macro_export] -macro_rules! kv_request_with_key { +macro_rules! impl_kv_request_for_single_key_op { ($req: ty, $resp: ty) => { impl KvRequest for $req where @@ -54,18 +55,90 @@ macro_rules! kv_request_with_key { if codec.is_plain() { return Cow::Borrowed(self); } - unimplemented!() + let mut req = self.clone(); + *req.mut_key() = codec.encode_key(req.take_key()); + + Cow::Owned(req) + } + } + }; +} + +#[macro_export] +macro_rules! impl_kv_request_for_batch_get { + ($req: ty, $resp: ty) => { + impl KvRequest for $req + where + C: RequestCodec, + { + type Response = $resp; + + fn encode_request(&self, codec: &C) -> Cow { + if codec.is_plain() { + return Cow::Borrowed(self); + } + + let mut req = self.clone(); + *req.mut_keys() = codec.encode_keys(req.take_keys()); + + Cow::Owned(req) } fn decode_response( &self, codec: &C, - resp: Self::Response, + mut resp: Self::Response, ) -> crate::Result { if codec.is_plain() { return Ok(resp); } - unimplemented!() + + *resp.mut_pairs() = codec.decode_pairs(resp.take_pairs())?; + + Ok(resp) + } + } + }; +} + +#[macro_export] +macro_rules! impl_kv_request_for_scan_op { + ($req: ty, $resp: ty, $pairs: ident) => { + impl KvRequest for $req + where + C: RequestCodec, + { + type Response = $resp; + + fn encode_request(&self, codec: &C) -> Cow { + if codec.is_plain() { + return Cow::Borrowed(self); + } + let mut req = self.clone(); + let (start, end) = + codec.encode_range(req.take_start_key().into(), req.take_end_key().into()); + + *req.mut_start_key() = start.into(); + *req.mut_end_key() = end.into(); + Cow::Owned(req) + } + + fn decode_response( + &self, + codec: &C, + mut resp: Self::Response, + ) -> crate::Result { + if codec.is_plain() { + return Ok(resp); + } + + paste::paste! { + let pairs = resp.[](); + + *resp.[]() = codec.encode_pairs(pairs); + + Ok(resp) + } } } }; diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 3509d620..48f41ee8 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -13,7 +13,6 @@ use tikv_client_proto::{ use crate::{ collect_first, pd::PdClient, - plain_request, plain_response, request::{ codec::RequestCodec, Collect, CollectSingle, CollectWithShard, DefaultProcessor, KvRequest, Merge, Process, ResponseWithShard, Shardable, SingleKey, @@ -73,20 +72,7 @@ pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest { req } -impl KvRequest for kvrpcpb::GetRequest { - type Response = kvrpcpb::GetResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::GetRequest, kvrpcpb::GetResponse); shardable_key!(kvrpcpb::GetRequest); collect_first!(kvrpcpb::GetResponse); impl SingleKey for kvrpcpb::GetRequest { @@ -115,20 +101,7 @@ pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::Bat req } -impl KvRequest for kvrpcpb::BatchGetRequest { - type Response = kvrpcpb::BatchGetResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_batch_get!(kvrpcpb::BatchGetRequest, kvrpcpb::BatchGetResponse); shardable_keys!(kvrpcpb::BatchGetRequest); impl Merge for Collect { @@ -158,20 +131,7 @@ pub fn new_scan_request( req } -impl KvRequest for kvrpcpb::ScanRequest { - type Response = kvrpcpb::ScanResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_scan_op!(kvrpcpb::ScanRequest, kvrpcpb::ScanResponse, pairs); shardable_range!(kvrpcpb::ScanRequest); impl Merge for Collect { @@ -200,19 +160,8 @@ pub fn new_resolve_lock_request( // region without keys. So it's not Shardable. And we don't automatically retry // on its region errors (in the Plan level). The region error must be manually // handled (in the upper level). -impl KvRequest for kvrpcpb::ResolveLockRequest { - type Response = kvrpcpb::ResolveLockResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} +impl_kv_request_for_single_key_op!(kvrpcpb::ResolveLockRequest, kvrpcpb::ResolveLockResponse); pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest { let mut req = kvrpcpb::CleanupRequest::default(); @@ -222,20 +171,7 @@ pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::Cleanup req } -impl KvRequest for kvrpcpb::CleanupRequest { - type Response = kvrpcpb::CleanupResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::CleanupRequest, kvrpcpb::CleanupResponse); shardable_key!(kvrpcpb::CleanupRequest); collect_first!(kvrpcpb::CleanupResponse); impl SingleKey for kvrpcpb::CleanupRequest { @@ -283,19 +219,7 @@ pub fn new_pessimistic_prewrite_request( req } -impl KvRequest for kvrpcpb::PrewriteRequest { - type Response = kvrpcpb::PrewriteResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} +impl_kv_request_for_single_key_op!(kvrpcpb::PrewriteRequest, kvrpcpb::PrewriteResponse); impl Shardable for kvrpcpb::PrewriteRequest { type Shard = Vec; @@ -340,20 +264,7 @@ pub fn new_commit_request( req } -impl KvRequest for kvrpcpb::CommitRequest { - type Response = kvrpcpb::CommitResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::CommitRequest, kvrpcpb::CommitResponse); shardable_keys!(kvrpcpb::CommitRequest); pub fn new_batch_rollback_request( @@ -367,20 +278,7 @@ pub fn new_batch_rollback_request( req } -impl KvRequest for kvrpcpb::BatchRollbackRequest { - type Response = kvrpcpb::BatchRollbackResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::BatchRollbackRequest, kvrpcpb::BatchRollbackResponse); shardable_keys!(kvrpcpb::BatchRollbackRequest); pub fn new_pessimistic_rollback_request( @@ -396,20 +294,7 @@ pub fn new_pessimistic_rollback_request( req } -impl KvRequest for kvrpcpb::PessimisticRollbackRequest { - type Response = kvrpcpb::PessimisticRollbackResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::PessimisticRollbackRequest, kvrpcpb::PessimisticRollbackResponse); shardable_keys!(kvrpcpb::PessimisticRollbackRequest); pub fn new_pessimistic_lock_request( @@ -437,19 +322,7 @@ pub fn new_pessimistic_lock_request( req } -impl KvRequest for kvrpcpb::PessimisticLockRequest { - type Response = kvrpcpb::PessimisticLockResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} +impl_kv_request_for_single_key_op!(kvrpcpb::PessimisticLockRequest, kvrpcpb::PessimisticLockResponse); impl Shardable for kvrpcpb::PessimisticLockRequest { type Shard = Vec; @@ -545,19 +418,7 @@ pub fn new_scan_lock_request( req } -impl KvRequest for kvrpcpb::ScanLockRequest { - type Response = kvrpcpb::ScanLockResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} +impl_kv_request_for_single_key_op!(kvrpcpb::ScanLockRequest, kvrpcpb::ScanLockResponse); impl Shardable for kvrpcpb::ScanLockRequest { type Shard = Vec; @@ -599,18 +460,7 @@ pub fn new_heart_beat_request( req } -impl KvRequest for kvrpcpb::TxnHeartBeatRequest { - type Response = kvrpcpb::TxnHeartBeatResponse; - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} +impl_kv_request_for_single_key_op!(kvrpcpb::TxnHeartBeatRequest, kvrpcpb::TxnHeartBeatResponse); impl Shardable for kvrpcpb::TxnHeartBeatRequest { type Shard = Vec>; @@ -646,19 +496,7 @@ impl Process for DefaultProcessor { } } -impl KvRequest for kvrpcpb::CheckTxnStatusRequest { - type Response = kvrpcpb::CheckTxnStatusResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} +impl_kv_request_for_single_key_op!(kvrpcpb::CheckTxnStatusRequest, kvrpcpb::CheckTxnStatusResponse); impl Shardable for kvrpcpb::CheckTxnStatusRequest { type Shard = Vec>; @@ -725,20 +563,7 @@ impl From<(u64, u64, Option)> for TransactionStatusKind { } } -impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { - type Response = kvrpcpb::CheckSecondaryLocksResponse; - - fn encode_request(&self, codec: &C) -> Cow { - plain_request!(self, codec); - todo!() - } - - fn decode_response(&self, codec: &C, resp: Self::Response) -> Result { - plain_response!(resp, codec); - todo!() - } -} - +impl_kv_request_for_single_key_op!(kvrpcpb::CheckSecondaryLocksRequest, kvrpcpb::CheckSecondaryLocksResponse); shardable_keys!(kvrpcpb::CheckSecondaryLocksRequest); impl Merge for Collect { From 71af50de2689c37ab03f1394098d4c6507c847dc Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 5 Jul 2022 14:13:57 +0800 Subject: [PATCH 16/43] cargo fmt Signed-off-by: iosmanthus --- examples/pessimistic.rs | 3 +-- examples/raw.rs | 4 ++-- src/raw/requests.rs | 20 ++++++++++---------- src/request/codec.rs | 19 ++++++++++--------- src/request/mod.rs | 2 +- src/transaction/requests.rs | 29 ++++++++++++++++++++++------- 6 files changed, 46 insertions(+), 31 deletions(-) diff --git a/examples/pessimistic.rs b/examples/pessimistic.rs index 861742b1..2822bc0f 100644 --- a/examples/pessimistic.rs +++ b/examples/pessimistic.rs @@ -4,8 +4,7 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::codec::TxnApiV1, Config, Key, TransactionClient as Client, TransactionOptions, - Value, + request::codec::TxnApiV1, Config, Key, TransactionClient as Client, TransactionOptions, Value, }; #[tokio::main] diff --git a/examples/raw.rs b/examples/raw.rs index dd0b6c7c..7194bdf8 100644 --- a/examples/raw.rs +++ b/examples/raw.rs @@ -6,8 +6,8 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::codec::RawApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, - Result, Value, + request::codec::RawApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, Result, + Value, }; const KEY: &str = "TiKV"; diff --git a/src/raw/requests.rs b/src/raw/requests.rs index e80c6bac..b7ba2f57 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -11,15 +11,15 @@ use tikv_client_store::Request; use crate::{ collect_first, - ColumnFamily, - Key, - KvPair, pd::PdClient, request::{ - codec::RequestCodec, Collect, CollectSingle, DefaultProcessor, KvRequest, - Merge, plan::ResponseWithShard, Process, Shardable, SingleKey, + codec::RequestCodec, plan::ResponseWithShard, Collect, CollectSingle, DefaultProcessor, + KvRequest, Merge, Process, Shardable, SingleKey, }, - Result, store::{RegionStore, store_stream_for_keys, store_stream_for_ranges}, transaction::HasLocks, util::iter::FlatMapOkIterExt, Value, + store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, + transaction::HasLocks, + util::iter::FlatMapOkIterExt, + ColumnFamily, Key, KvPair, Result, Value, }; use super::RawRpcRequest; @@ -371,7 +371,7 @@ impl Process for DefaultProcessor { } type RawCoprocessorRequestDataBuilder = -Arc) -> Vec + Send + Sync>; + Arc) -> Vec + Send + Sync>; pub fn new_raw_coprocessor_request( copr_name: String, @@ -441,8 +441,8 @@ impl Shardable for RawCoprocessorRequest { #[allow(clippy::type_complexity)] impl -Process>>>> -for DefaultProcessor + Process>>>> + for DefaultProcessor { type Out = Vec<(Vec, Vec>)>; @@ -522,9 +522,9 @@ mod test { use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, - Key, mock::{MockKvClient, MockPdClient}, request::Plan, + Key, }; use super::*; diff --git a/src/request/codec.rs b/src/request/codec.rs index 51e25c66..328e5d82 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,8 +1,7 @@ use tikv_client_common::Error; -use tikv_client_proto::kvrpcpb; -use tikv_client_proto::metapb::Region; +use tikv_client_proto::{kvrpcpb, metapb::Region}; -use crate::{Key, kv::codec::decode_bytes_in_place, Result}; +use crate::{kv::codec::decode_bytes_in_place, Key, Result}; const RAW_MODE_PREFIX: u8 = b'r'; const TXN_MODE_PREFIX: u8 = b'x'; @@ -26,7 +25,9 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { keys } - fn encode_pairs(&self, pairs: Vec) -> Vec { pairs } + fn encode_pairs(&self, pairs: Vec) -> Vec { + pairs + } fn decode_key(&self, key: Vec) -> Result> { Ok(key) @@ -40,7 +41,9 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { (start, end) } - fn encode_ranges(&self, ranges: Vec) -> Vec { ranges } + fn encode_ranges(&self, ranges: Vec) -> Vec { + ranges + } fn encode_pd_query(&self, key: Vec) -> Vec { key @@ -204,16 +207,14 @@ impl RequestCodec for KeySpaceCodec { if region.get_start_key() < self.mode.min_key().as_slice() { *region.mut_start_key() = vec![]; } else { - *region.mut_start_key() = self - .decode_key(region.get_start_key().to_vec())?; + *region.mut_start_key() = self.decode_key(region.get_start_key().to_vec())?; } // Map the region's end key to the keyspace's end key. if region.get_end_key() > self.mode.max_key().as_slice() { *region.mut_end_key() = vec![]; } else { - *region.mut_end_key() = self - .decode_key(region.get_end_key().to_vec())?; + *region.mut_end_key() = self.decode_key(region.get_end_key().to_vec())?; } Ok(region) diff --git a/src/request/mod.rs b/src/request/mod.rs index dd3be3bf..61086e35 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -11,7 +11,6 @@ use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF, PESSIMISTIC_BACKOFF}, transaction::HasLocks, }; -use crate::request::codec::RequestCodec; pub use self::{ plan::{ @@ -56,6 +55,7 @@ macro_rules! impl_kv_request_for_single_key_op { return Cow::Borrowed(self); } let mut req = self.clone(); + *req.mut_key() = codec.encode_key(req.take_key()); Cow::Owned(req) diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 48f41ee8..1705025c 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -14,8 +14,8 @@ use crate::{ collect_first, pd::PdClient, request::{ - codec::RequestCodec, Collect, CollectSingle, CollectWithShard, DefaultProcessor, - KvRequest, Merge, Process, ResponseWithShard, Shardable, SingleKey, + codec::RequestCodec, Collect, CollectSingle, CollectWithShard, DefaultProcessor, KvRequest, + Merge, Process, ResponseWithShard, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, timestamp::TimestampExt, @@ -278,7 +278,10 @@ pub fn new_batch_rollback_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::BatchRollbackRequest, kvrpcpb::BatchRollbackResponse); +impl_kv_request_for_single_key_op!( + kvrpcpb::BatchRollbackRequest, + kvrpcpb::BatchRollbackResponse +); shardable_keys!(kvrpcpb::BatchRollbackRequest); pub fn new_pessimistic_rollback_request( @@ -294,7 +297,10 @@ pub fn new_pessimistic_rollback_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::PessimisticRollbackRequest, kvrpcpb::PessimisticRollbackResponse); +impl_kv_request_for_single_key_op!( + kvrpcpb::PessimisticRollbackRequest, + kvrpcpb::PessimisticRollbackResponse +); shardable_keys!(kvrpcpb::PessimisticRollbackRequest); pub fn new_pessimistic_lock_request( @@ -322,7 +328,10 @@ pub fn new_pessimistic_lock_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::PessimisticLockRequest, kvrpcpb::PessimisticLockResponse); +impl_kv_request_for_single_key_op!( + kvrpcpb::PessimisticLockRequest, + kvrpcpb::PessimisticLockResponse +); impl Shardable for kvrpcpb::PessimisticLockRequest { type Shard = Vec; @@ -496,7 +505,10 @@ impl Process for DefaultProcessor { } } -impl_kv_request_for_single_key_op!(kvrpcpb::CheckTxnStatusRequest, kvrpcpb::CheckTxnStatusResponse); +impl_kv_request_for_single_key_op!( + kvrpcpb::CheckTxnStatusRequest, + kvrpcpb::CheckTxnStatusResponse +); impl Shardable for kvrpcpb::CheckTxnStatusRequest { type Shard = Vec>; @@ -563,7 +575,10 @@ impl From<(u64, u64, Option)> for TransactionStatusKind { } } -impl_kv_request_for_single_key_op!(kvrpcpb::CheckSecondaryLocksRequest, kvrpcpb::CheckSecondaryLocksResponse); +impl_kv_request_for_single_key_op!( + kvrpcpb::CheckSecondaryLocksRequest, + kvrpcpb::CheckSecondaryLocksResponse +); shardable_keys!(kvrpcpb::CheckSecondaryLocksRequest); impl Merge for Collect { From a5f326f5db2f4297914b064fbebfa847bb05c401 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 5 Jul 2022 20:31:20 +0800 Subject: [PATCH 17/43] impl KvRequest for txn requests Signed-off-by: iosmanthus --- src/raw/requests.rs | 51 ++------ src/request/codec.rs | 70 +++++----- src/request/mod.rs | 55 +++----- src/request/plan.rs | 24 +++- src/transaction/requests.rs | 255 ++++++++++++++++++++++++++++++++---- 5 files changed, 315 insertions(+), 140 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index b7ba2f57..a510ac3b 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -122,16 +122,10 @@ pub fn new_raw_batch_put_request( impl KvRequest for kvrpcpb::RawBatchPutRequest { type Response = kvrpcpb::RawBatchPutResponse; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - - let mut req = self.clone(); - - *req.mut_pairs() = codec.encode_pairs(req.take_pairs()); + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_pairs() = codec.encode_pairs(self.take_pairs()); - Cow::Owned(req) + self } } @@ -193,16 +187,10 @@ pub fn new_raw_batch_delete_request( impl KvRequest for kvrpcpb::RawBatchDeleteRequest { type Response = kvrpcpb::RawBatchDeleteResponse; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - - let mut req = self.clone(); - - *req.mut_keys() = codec.encode_keys(req.take_keys()); + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); - Cow::Owned(req) + self } } @@ -224,18 +212,13 @@ pub fn new_raw_delete_range_request( impl KvRequest for kvrpcpb::RawDeleteRangeRequest { type Response = kvrpcpb::RawDeleteRangeResponse; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - - let mut req = self.clone(); + fn encode_request(mut self, codec: &C) -> Self { + let (start, end) = (self.take_start_key(), self.take_end_key()); - let (start, end) = (req.take_start_key(), req.take_end_key()); - *req.mut_start_key() = codec.encode_key(start); - *req.mut_end_key() = codec.encode_key(end); + self.set_start_key(codec.encode_key(start)); + self.set_end_key(codec.encode_key(end)); - Cow::Owned(req) + self } } @@ -290,16 +273,10 @@ pub fn new_raw_batch_scan_request( impl KvRequest for kvrpcpb::RawBatchScanRequest { type Response = kvrpcpb::RawBatchScanResponse; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - - let mut req = self.clone(); - - *req.mut_ranges() = codec.encode_ranges(req.take_ranges()); + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_ranges() = codec.encode_ranges(self.take_ranges()); - Cow::Owned(req) + self } } diff --git a/src/request/codec.rs b/src/request/codec.rs index 328e5d82..0c0b4888 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -21,11 +21,26 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { key } + fn encode_mutations(&self, mutations: Vec) -> Vec { + mutations + .into_iter() + .map(|mut m| { + let key = m.take_key(); + m.set_key(self.encode_key(key)); + m + }) + .collect() + } + fn encode_keys(&self, keys: Vec>) -> Vec> { - keys + keys.into_iter().map(|key| self.encode_key(key)).collect() } - fn encode_pairs(&self, pairs: Vec) -> Vec { + fn encode_pairs(&self, mut pairs: Vec) -> Vec { + for pair in pairs.iter_mut() { + *pair.mut_key() = self.encode_key(pair.take_key()); + } + pairs } @@ -33,7 +48,18 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(key) } - fn decode_pairs(&self, pairs: Vec) -> Result> { + fn decode_keys(&self, keys: Vec>) -> Result>> { + Ok(keys + .into_iter() + .map(|key| self.decode_key(key)) + .collect::>>>()?) + } + + fn decode_pairs(&self, mut pairs: Vec) -> Result> { + for pair in pairs.iter_mut() { + *pair.mut_key() = self.decode_key(pair.take_key())?; + } + Ok(pairs) } @@ -41,7 +67,13 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { (start, end) } - fn encode_ranges(&self, ranges: Vec) -> Vec { + fn encode_ranges(&self, mut ranges: Vec) -> Vec { + for range in ranges.iter_mut() { + let (start, end) = self.encode_range(range.take_start_key(), range.take_end_key()); + *range.mut_start_key() = start; + *range.mut_end_key() = end; + } + ranges } @@ -143,18 +175,6 @@ impl RequestCodec for KeySpaceCodec { encoded } - fn encode_keys(&self, mut keys: Vec>) -> Vec> { - keys.into_iter().map(|key| self.encode_key(key)).collect() - } - - fn encode_pairs(&self, mut pairs: Vec) -> Vec { - for pair in pairs.iter_mut() { - *pair.mut_key() = self.encode_key(pair.take_key()); - } - - pairs - } - fn decode_key(&self, mut key: Vec) -> Result> { let prefix: Prefix = self.clone().into(); @@ -169,14 +189,6 @@ impl RequestCodec for KeySpaceCodec { Ok(key.split_off(KEYSPACE_PREFIX_LEN)) } - fn decode_pairs(&self, mut pairs: Vec) -> Result> { - for pair in pairs.iter_mut() { - *pair.mut_key() = self.decode_key(pair.take_key())?; - } - - Ok(pairs) - } - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { if self.id == MAX_KEYSPACE_ID { (self.encode_key(start), self.mode.max_key()) @@ -185,16 +197,6 @@ impl RequestCodec for KeySpaceCodec { } } - fn encode_ranges(&self, mut ranges: Vec) -> Vec { - for range in ranges.iter_mut() { - let (start, end) = self.encode_range(range.take_start_key(), range.take_end_key()); - *range.mut_start_key() = start; - *range.mut_end_key() = end; - } - - ranges - } - fn encode_pd_query(&self, key: Vec) -> Vec { Key::from(self.encode_key(key)).to_encoded().into() } diff --git a/src/request/mod.rs b/src/request/mod.rs index 61086e35..f9776005 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -33,9 +33,11 @@ pub mod codec; pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { /// The expected response to the request. type Response: HasKeyErrors + HasLocks + HasRegionError + Clone + Send + 'static; - fn encode_request(&self, _codec: &C) -> Cow { - Cow::Borrowed(self) + + fn encode_request(self, _codec: &C) -> Self { + self.clone() } + fn decode_response(&self, _codec: &C, resp: Self::Response) -> crate::Result { Ok(resp) } @@ -50,15 +52,10 @@ macro_rules! impl_kv_request_for_single_key_op { { type Response = $resp; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - let mut req = self.clone(); - - *req.mut_key() = codec.encode_key(req.take_key()); + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_key() = codec.encode_key(self.take_key()); - Cow::Owned(req) + self } } }; @@ -73,15 +70,10 @@ macro_rules! impl_kv_request_for_batch_get { { type Response = $resp; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - - let mut req = self.clone(); - *req.mut_keys() = codec.encode_keys(req.take_keys()); + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); - Cow::Owned(req) + self } fn decode_response( @@ -89,10 +81,6 @@ macro_rules! impl_kv_request_for_batch_get { codec: &C, mut resp: Self::Response, ) -> crate::Result { - if codec.is_plain() { - return Ok(resp); - } - *resp.mut_pairs() = codec.decode_pairs(resp.take_pairs())?; Ok(resp) @@ -110,17 +98,14 @@ macro_rules! impl_kv_request_for_scan_op { { type Response = $resp; - fn encode_request(&self, codec: &C) -> Cow { - if codec.is_plain() { - return Cow::Borrowed(self); - } - let mut req = self.clone(); + fn encode_request(mut self, codec: &C) -> Self { let (start, end) = - codec.encode_range(req.take_start_key().into(), req.take_end_key().into()); + codec.encode_range(self.take_start_key().into(), self.take_end_key().into()); + + self.set_start_key(start); + self.set_end_key(end); - *req.mut_start_key() = start.into(); - *req.mut_end_key() = end.into(); - Cow::Owned(req) + self } fn decode_response( @@ -128,10 +113,6 @@ macro_rules! impl_kv_request_for_scan_op { codec: &C, mut resp: Self::Response, ) -> crate::Result { - if codec.is_plain() { - return Ok(resp); - } - paste::paste! { let pairs = resp.[](); @@ -245,8 +226,8 @@ mod test { impl KvRequest for MockKvRequest { type Response = MockRpcResponse; - fn encode_request(&self, _codec: &C) -> Cow { - Cow::Borrowed(self) + fn encode_request(self, _codec: &C) -> Self { + self } fn decode_response(&self, _codec: &C, resp: Self::Response) -> Result { diff --git a/src/request/plan.rs b/src/request/plan.rs index 14bad044..e143deec 100644 --- a/src/request/plan.rs +++ b/src/request/plan.rs @@ -1,6 +1,6 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. -use std::{marker::PhantomData, sync::Arc}; +use std::{borrow::Cow, marker::PhantomData, sync::Arc}; use async_recursion::async_recursion; use async_trait::async_trait; @@ -55,7 +55,12 @@ impl> Plan for Dispatch { type Result = Req::Response; async fn execute(&self) -> Result { - let req = self.request.encode_request(&self.codec); + let req = if self.codec.is_plain() { + Cow::Borrowed(&self.request) + } else { + Cow::Owned(self.request.clone().encode_request(&self.codec)) + }; + let stats = tikv_stats(self.request.label()); let result = self .kv_client @@ -64,12 +69,17 @@ impl> Plan for Dispatch { .dispatch(req.as_ref()) .await; let result = stats.done(result); + result.and_then(|r| { - req.decode_response( - &self.codec, - *r.downcast() - .expect("Downcast failed: request and response type mismatch"), - ) + let resp = *r + .downcast() + .expect("Downcast failed: request and response type mismatch"); + + if self.codec.is_plain() { + Ok(resp) + } else { + req.decode_response(&self.codec, resp) + } }) } } diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 1705025c..5d40b1bf 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -9,6 +9,7 @@ use tikv_client_proto::{ kvrpcpb::{self, TxnHeartBeatResponse}, pdpb::Timestamp, }; +use tikv_client_store::Request; use crate::{ collect_first, @@ -20,6 +21,7 @@ use crate::{ store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, timestamp::TimestampExt, transaction::HasLocks, + transaction_lowering::PessimisticLock, util::iter::FlatMapOkIterExt, Key, KvPair, Result, Value, }; @@ -161,7 +163,21 @@ pub fn new_resolve_lock_request( // on its region errors (in the Plan level). The region error must be manually // handled (in the upper level). -impl_kv_request_for_single_key_op!(kvrpcpb::ResolveLockRequest, kvrpcpb::ResolveLockResponse); +impl KvRequest for kvrpcpb::ResolveLockRequest { + type Response = kvrpcpb::ResolveLockResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + + Ok(resp) + } +} pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest { let mut req = kvrpcpb::CleanupRequest::default(); @@ -219,7 +235,21 @@ pub fn new_pessimistic_prewrite_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::PrewriteRequest, kvrpcpb::PrewriteResponse); +impl KvRequest for kvrpcpb::PrewriteRequest { + type Response = kvrpcpb::PrewriteResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_mutations() = codec.encode_mutations(self.take_mutations()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_errors(codec, resp.mut_errors())?; + + Ok(resp) + } +} impl Shardable for kvrpcpb::PrewriteRequest { type Shard = Vec; @@ -264,7 +294,21 @@ pub fn new_commit_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::CommitRequest, kvrpcpb::CommitResponse); +impl KvRequest for kvrpcpb::CommitRequest { + type Response = kvrpcpb::CommitResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + + Ok(resp) + } +} shardable_keys!(kvrpcpb::CommitRequest); pub fn new_batch_rollback_request( @@ -278,10 +322,22 @@ pub fn new_batch_rollback_request( req } -impl_kv_request_for_single_key_op!( - kvrpcpb::BatchRollbackRequest, - kvrpcpb::BatchRollbackResponse -); +impl KvRequest for kvrpcpb::BatchRollbackRequest { + type Response = kvrpcpb::BatchRollbackResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + + Ok(resp) + } +} + shardable_keys!(kvrpcpb::BatchRollbackRequest); pub fn new_pessimistic_rollback_request( @@ -297,10 +353,22 @@ pub fn new_pessimistic_rollback_request( req } -impl_kv_request_for_single_key_op!( - kvrpcpb::PessimisticRollbackRequest, - kvrpcpb::PessimisticRollbackResponse -); +impl KvRequest for kvrpcpb::PessimisticRollbackRequest { + type Response = kvrpcpb::PessimisticRollbackResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_errors(codec, resp.mut_errors())?; + + Ok(resp) + } +} + shardable_keys!(kvrpcpb::PessimisticRollbackRequest); pub fn new_pessimistic_lock_request( @@ -328,10 +396,22 @@ pub fn new_pessimistic_lock_request( req } -impl_kv_request_for_single_key_op!( - kvrpcpb::PessimisticLockRequest, - kvrpcpb::PessimisticLockResponse -); +impl KvRequest for kvrpcpb::PessimisticLockRequest { + type Response = kvrpcpb::PessimisticLockResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_mutations() = codec.encode_mutations(self.take_mutations()); + *self.mut_primary_lock() = codec.encode_key(self.take_primary_lock()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_errors(codec, resp.mut_errors())?; + + Ok(resp) + } +} impl Shardable for kvrpcpb::PessimisticLockRequest { type Shard = Vec; @@ -427,7 +507,23 @@ pub fn new_scan_lock_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::ScanLockRequest, kvrpcpb::ScanLockResponse); +impl KvRequest for kvrpcpb::ScanLockRequest { + type Response = kvrpcpb::ScanLockResponse; + + fn encode_request(mut self, codec: &C) -> Self { + let (start, end) = codec.encode_range(self.take_start_key(), self.take_end_key()); + self.set_start_key(start); + self.set_end_key(end); + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + decode_lock_infos(codec, resp.mut_locks())?; + + Ok(resp) + } +} impl Shardable for kvrpcpb::ScanLockRequest { type Shard = Vec; @@ -469,7 +565,20 @@ pub fn new_heart_beat_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::TxnHeartBeatRequest, kvrpcpb::TxnHeartBeatResponse); +impl KvRequest for kvrpcpb::TxnHeartBeatRequest { + type Response = kvrpcpb::TxnHeartBeatResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_primary_lock() = codec.encode_key(self.take_primary_lock()); + + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + Ok(resp) + } +} impl Shardable for kvrpcpb::TxnHeartBeatRequest { type Shard = Vec>; @@ -505,10 +614,20 @@ impl Process for DefaultProcessor { } } -impl_kv_request_for_single_key_op!( - kvrpcpb::CheckTxnStatusRequest, - kvrpcpb::CheckTxnStatusResponse -); +impl KvRequest for kvrpcpb::CheckTxnStatusRequest { + type Response = kvrpcpb::CheckTxnStatusResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_primary_key() = codec.encode_key(self.take_primary_key()); + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + decode_lock_info(codec, resp.mut_lock_info())?; + Ok(resp) + } +} impl Shardable for kvrpcpb::CheckTxnStatusRequest { type Shard = Vec>; @@ -575,10 +694,21 @@ impl From<(u64, u64, Option)> for TransactionStatusKind { } } -impl_kv_request_for_single_key_op!( - kvrpcpb::CheckSecondaryLocksRequest, - kvrpcpb::CheckSecondaryLocksResponse -); +impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { + type Response = kvrpcpb::CheckSecondaryLocksResponse; + + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_keys() = codec.encode_keys(self.take_keys()); + self + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + decode_key_error(codec, resp.mut_error())?; + decode_lock_infos(codec, resp.mut_locks())?; + Ok(resp) + } +} + shardable_keys!(kvrpcpb::CheckSecondaryLocksRequest); impl Merge for Collect { @@ -656,6 +786,81 @@ impl HasLocks for kvrpcpb::PrewriteResponse { } } +pub(crate) fn decode_lock_info( + codec: &C, + err: &mut kvrpcpb::LockInfo, +) -> Result<()> { + *err.mut_primary_lock() = codec.decode_key(err.take_primary_lock())?; + *err.mut_key() = codec.decode_key(err.take_key())?; + *err.mut_secondaries() = codec.decode_keys(err.take_secondaries())?; + + Ok(()) +} + +pub(crate) fn decode_lock_infos( + codec: &C, + errs: &mut [kvrpcpb::LockInfo], +) -> Result<()> { + for err in errs.iter_mut() { + decode_lock_info(codec, err)?; + } + + Ok(()) +} + +pub(crate) fn decode_key_errors( + codec: &C, + errs: &mut [kvrpcpb::KeyError], +) -> Result<()> { + for err in errs.iter_mut() { + decode_key_error(codec, err)?; + } + + Ok(()) +} + +pub(crate) fn decode_key_error( + codec: &C, + err: &mut kvrpcpb::KeyError, +) -> Result<()> { + if err.has_locked() { + let locked = err.mut_locked(); + decode_lock_info(codec, locked)?; + } + + if err.has_conflict() { + let conflict = err.mut_conflict(); + *conflict.mut_key() = codec.decode_key(conflict.take_key())?; + *conflict.mut_primary() = codec.decode_key(conflict.take_primary())?; + } + + if err.has_already_exist() { + let already_exist = err.mut_already_exist(); + *already_exist.mut_key() = codec.decode_key(already_exist.take_key())?; + } + + // We do not decode key in `Deadlock` since there is no use for the key right now in client side. + // All we need is the key hash to detect deadlock. + // TODO: while we check the keys against the deadlock key hash, we need to encode the key. + + if err.has_commit_ts_expired() { + let commit_ts_expired = err.mut_commit_ts_expired(); + *commit_ts_expired.mut_key() = codec.decode_key(commit_ts_expired.take_key())?; + } + + if err.has_txn_not_found() { + let txn_not_found = err.mut_txn_not_found(); + *txn_not_found.mut_primary_key() = codec.decode_key(txn_not_found.take_primary_key())?; + } + + if err.has_assertion_failed() { + let assertion_failed = err.mut_assertion_failed(); + *assertion_failed.mut_key() = codec.decode_key(assertion_failed.take_key())?; + } + + Ok(()) +} + #[cfg(test)] mod tests { use tikv_client_common::Error::{PessimisticLockError, ResolveLockError}; From 5efbc12b6ad77e6be7a0b31e36d925eee55da82e Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 5 Jul 2022 20:38:17 +0800 Subject: [PATCH 18/43] make check Signed-off-by: iosmanthus --- src/raw/requests.rs | 2 +- src/request/codec.rs | 10 ++++------ src/request/mod.rs | 8 +++----- src/transaction/requests.rs | 4 +--- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index a510ac3b..e7250ea8 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -1,6 +1,6 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::{any::Any, borrow::Cow, ops::Range, sync::Arc}; +use std::{any::Any, ops::Range, sync::Arc}; use async_trait::async_trait; use futures::stream::BoxStream; diff --git a/src/request/codec.rs b/src/request/codec.rs index 0c0b4888..ee6a0d6e 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -49,10 +49,9 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { } fn decode_keys(&self, keys: Vec>) -> Result>> { - Ok(keys - .into_iter() + keys.into_iter() .map(|key| self.decode_key(key)) - .collect::>>>()?) + .collect::>>>() } fn decode_pairs(&self, mut pairs: Vec) -> Result> { @@ -167,16 +166,15 @@ impl From for Prefix { impl RequestCodec for KeySpaceCodec { fn encode_key(&self, mut key: Vec) -> Vec { - let this = self.clone(); let mut encoded = Vec::with_capacity(key.len() + KEYSPACE_PREFIX_LEN); - let prefix: Prefix = this.into(); + let prefix: Prefix = (*self).into(); encoded.extend_from_slice(&prefix); encoded.append(&mut key); encoded } fn decode_key(&self, mut key: Vec) -> Result> { - let prefix: Prefix = self.clone().into(); + let prefix: Prefix = (*self).into(); if !key.starts_with(&prefix) { return Err(Error::CorruptedKeyspace { diff --git a/src/request/mod.rs b/src/request/mod.rs index f9776005..7fe3d83f 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -1,7 +1,5 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::borrow::Cow; - use async_trait::async_trait; use derive_new::new; @@ -35,7 +33,7 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { type Response: HasKeyErrors + HasLocks + HasRegionError + Clone + Send + 'static; fn encode_request(self, _codec: &C) -> Self { - self.clone() + self } fn decode_response(&self, _codec: &C, resp: Self::Response) -> crate::Result { @@ -80,7 +78,7 @@ macro_rules! impl_kv_request_for_batch_get { &self, codec: &C, mut resp: Self::Response, - ) -> crate::Result { + ) -> $crate::Result { *resp.mut_pairs() = codec.decode_pairs(resp.take_pairs())?; Ok(resp) @@ -112,7 +110,7 @@ macro_rules! impl_kv_request_for_scan_op { &self, codec: &C, mut resp: Self::Response, - ) -> crate::Result { + ) -> $crate::Result { paste::paste! { let pairs = resp.[](); diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 5d40b1bf..30cdddd3 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -1,5 +1,5 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. -use std::{borrow::Cow, collections::HashMap, iter, sync::Arc}; +use std::{collections::HashMap, iter, sync::Arc}; use either::Either; use futures::stream::BoxStream; @@ -9,7 +9,6 @@ use tikv_client_proto::{ kvrpcpb::{self, TxnHeartBeatResponse}, pdpb::Timestamp, }; -use tikv_client_store::Request; use crate::{ collect_first, @@ -21,7 +20,6 @@ use crate::{ store::{store_stream_for_keys, store_stream_for_range_by_start_key, RegionStore}, timestamp::TimestampExt, transaction::HasLocks, - transaction_lowering::PessimisticLock, util::iter::FlatMapOkIterExt, Key, KvPair, Result, Value, }; From b534cfd57a13725bcc0d98100f7df774e8c8d161 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 5 Jul 2022 20:56:08 +0800 Subject: [PATCH 19/43] impl Default for KeyspaceId Signed-off-by: iosmanthus --- src/request/codec.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/request/codec.rs b/src/request/codec.rs index ee6a0d6e..812c8cd6 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,3 +1,4 @@ +use std::ops::{Deref, DerefMut}; use tikv_client_common::Error; use tikv_client_proto::{kvrpcpb, metapb::Region}; @@ -14,7 +15,7 @@ const RAW_MODE_MAX_KEY: Prefix = [RAW_MODE_PREFIX + 1, 0, 0, 0]; const TXN_MODE_MIN_KEY: Prefix = [TXN_MODE_PREFIX, 0, 0, 0]; const TXN_MODE_MAX_KEY: Prefix = [TXN_MODE_PREFIX + 1, 0, 0, 0]; -const MAX_KEYSPACE_ID: KeySpaceId = [0xff, 0xff, 0xff]; +const MAX_KEYSPACE_ID: KeySpaceId = KeySpaceId([0xff, 0xff, 0xff]); pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { fn encode_key(&self, key: Vec) -> Vec { @@ -150,7 +151,22 @@ impl KeyMode { type Prefix = [u8; KEYSPACE_PREFIX_LEN]; -type KeySpaceId = [u8; 3]; +#[derive(Clone,Copy,Default,PartialEq)] +pub struct KeySpaceId([u8; 3]); + +impl Deref for KeySpaceId { + type Target = [u8; 3]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for KeySpaceId { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} #[derive(Copy, Clone)] struct KeySpaceCodec { From 434e10d94135ea95a8ae06c38315a67b5d388912 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Wed, 6 Jul 2022 12:34:52 +0800 Subject: [PATCH 20/43] cargo fmt Signed-off-by: iosmanthus --- src/request/codec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request/codec.rs b/src/request/codec.rs index 812c8cd6..4e8a182b 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -151,7 +151,7 @@ impl KeyMode { type Prefix = [u8; KEYSPACE_PREFIX_LEN]; -#[derive(Clone,Copy,Default,PartialEq)] +#[derive(Clone, Copy, Default, PartialEq)] pub struct KeySpaceId([u8; 3]); impl Deref for KeySpaceId { From 317116b0315a6b12dddfb80c517f46546672301b Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Wed, 6 Jul 2022 17:54:04 +0800 Subject: [PATCH 21/43] decode in place Signed-off-by: iosmanthus --- src/raw/requests.rs | 2 +- src/region_cache.rs | 4 +- src/request/codec.rs | 131 ++++++++++++++++++++++++++++++------ src/request/mod.rs | 35 +++++++++- src/transaction/requests.rs | 101 ++++----------------------- 5 files changed, 157 insertions(+), 116 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index e7250ea8..d6f1c907 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -96,7 +96,7 @@ pub fn new_raw_put_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::RawPutRequest, kvrpcpb::RawPutResponse); +impl_kv_request!(kvrpcpb::RawPutRequest, kvrpcpb::RawPutResponse; encode=key); shardable_key!(kvrpcpb::RawPutRequest); collect_first!(kvrpcpb::RawPutResponse); diff --git a/src/region_cache.rs b/src/region_cache.rs index 1610720f..88c3b11d 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -137,7 +137,7 @@ impl RegionCache { .clone() .get_region(self.codec.encode_pd_query(key.into())) .await?; - r.region = self.codec.decode_region(r.region)?; + self.codec.decode_region(&mut r.region)?; self.add_region(r.clone()).await; Ok(r) } @@ -152,7 +152,7 @@ impl RegionCache { } let mut region = self.inner_client.clone().get_region_by_id(id).await?; - region.region = self.codec.decode_region(region.region)?; + self.codec.decode_region(&mut region.region)?; self.add_region(region.clone()).await; // notify others diff --git a/src/request/codec.rs b/src/request/codec.rs index 4e8a182b..02753af0 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,6 +1,7 @@ +use core::intrinsics::copy; use std::ops::{Deref, DerefMut}; use tikv_client_common::Error; -use tikv_client_proto::{kvrpcpb, metapb::Region}; +use tikv_client_proto::{errorpb, kvrpcpb, metapb::Region}; use crate::{kv::codec::decode_bytes_in_place, Key, Result}; @@ -45,22 +46,85 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { pairs } - fn decode_key(&self, key: Vec) -> Result> { - Ok(key) + fn decode_key(&self, _key: &mut Vec) -> Result<()> { + Ok(()) } - fn decode_keys(&self, keys: Vec>) -> Result>> { - keys.into_iter() - .map(|key| self.decode_key(key)) - .collect::>>>() + fn decode_keys(&self, keys: &mut [Vec]) -> Result<()> { + for key in keys.iter_mut() { + self.decode_key(key)?; + } + + Ok(()) + } + + fn decode_key_error(&self, err: &mut kvrpcpb::KeyError) -> Result<()> { + if err.has_locked() { + let locked = err.mut_locked(); + self.decode_lock(locked)?; + } + + if err.has_conflict() { + let conflict = err.mut_conflict(); + self.decode_key(conflict.mut_key())?; + self.decode_key(conflict.mut_primary())?; + } + + if err.has_already_exist() { + let already_exist = err.mut_already_exist(); + self.decode_key(already_exist.mut_key())?; + } + + // We do not decode key in `Deadlock` since there is no use for the key right now in client side. + // All we need is the key hash to detect deadlock. + // TODO: while we check the keys against the deadlock key hash, we need to encode the key. + + if err.has_commit_ts_expired() { + let commit_ts_expired = err.mut_commit_ts_expired(); + self.decode_key(commit_ts_expired.mut_key())?; + } + + if err.has_txn_not_found() { + let txn_not_found = err.mut_txn_not_found(); + self.decode_key(txn_not_found.mut_primary_key())?; + } + + if err.has_assertion_failed() { + let assertion_failed = err.mut_assertion_failed(); + self.decode_key(assertion_failed.mut_key())?; + } + + Ok(()) + } + + fn decode_key_errors(&self, errors: &mut [kvrpcpb::KeyError]) -> Result<()> { + for err in errors.iter_mut() { + self.decode_key_error(err)?; + } + + Ok(()) + } + + fn decode_lock(&self, lock: &mut kvrpcpb::LockInfo) -> Result<()> { + self.decode_key(lock.mut_primary_lock())?; + self.decode_key(lock.mut_key())?; + self.decode_keys(lock.mut_secondaries()) + } + + fn decode_locks(&self, locks: &mut [kvrpcpb::LockInfo]) -> Result<()> { + for lock in locks.iter_mut() { + self.decode_lock(lock)?; + } + + Ok(()) } - fn decode_pairs(&self, mut pairs: Vec) -> Result> { + fn decode_pairs(&self, pairs: &mut [kvrpcpb::KvPair]) -> Result<()> { for pair in pairs.iter_mut() { - *pair.mut_key() = self.decode_key(pair.take_key())?; + self.decode_key(pair.mut_key())?; } - Ok(pairs) + Ok(()) } fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { @@ -81,8 +145,22 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { key } - fn decode_region(&self, region: Region) -> Result { - Ok(region) + fn decode_region(&self, _region: &mut Region) -> Result<()> { + Ok(()) + } + + fn decode_regions(&self, regions: &mut [Region]) -> Result<()> { + for region in regions.iter_mut() { + self.decode_region(region)?; + } + Ok(()) + } + + fn decode_region_error(&self, err: &mut errorpb::Error) -> Result<()> { + if err.has_epoch_not_match() { + self.decode_regions(err.mut_epoch_not_match().mut_current_regions())?; + } + Ok(()) } fn is_plain(&self) -> bool { @@ -107,10 +185,10 @@ impl RequestCodec for TxnApiV1 { Key::from(key).to_encoded().into() } - fn decode_region(&self, mut region: Region) -> Result { + fn decode_region(&self, region: &mut Region) -> Result<()> { decode_bytes_in_place(region.mut_start_key(), false)?; decode_bytes_in_place(region.mut_end_key(), false)?; - Ok(region) + Ok(()) } } @@ -151,7 +229,7 @@ impl KeyMode { type Prefix = [u8; KEYSPACE_PREFIX_LEN]; -#[derive(Clone, Copy, Default, PartialEq)] +#[derive(Clone, Copy, Default, PartialEq, Eq)] pub struct KeySpaceId([u8; 3]); impl Deref for KeySpaceId { @@ -189,18 +267,27 @@ impl RequestCodec for KeySpaceCodec { encoded } - fn decode_key(&self, mut key: Vec) -> Result> { + fn decode_key(&self, key: &mut Vec) -> Result<()> { let prefix: Prefix = (*self).into(); if !key.starts_with(&prefix) { return Err(Error::CorruptedKeyspace { expected: prefix.to_vec(), actual: key[..KEYSPACE_PREFIX_LEN].to_vec(), - key, + key: key.to_vec(), }); } - Ok(key.split_off(KEYSPACE_PREFIX_LEN)) + unsafe { + let trimmed_len = key.len() - KEYSPACE_PREFIX_LEN; + let ptr = key.as_mut_ptr(); + let trimmed = key[KEYSPACE_PREFIX_LEN..].as_mut_ptr(); + + copy(trimmed, ptr, trimmed_len); + + key.set_len(trimmed_len); + } + Ok(()) } fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { @@ -215,7 +302,7 @@ impl RequestCodec for KeySpaceCodec { Key::from(self.encode_key(key)).to_encoded().into() } - fn decode_region(&self, mut region: Region) -> Result { + fn decode_region(&self, region: &mut Region) -> Result<()> { decode_bytes_in_place(region.mut_start_key(), false)?; decode_bytes_in_place(region.mut_end_key(), false)?; @@ -223,17 +310,17 @@ impl RequestCodec for KeySpaceCodec { if region.get_start_key() < self.mode.min_key().as_slice() { *region.mut_start_key() = vec![]; } else { - *region.mut_start_key() = self.decode_key(region.get_start_key().to_vec())?; + self.decode_key(region.mut_start_key())?; } // Map the region's end key to the keyspace's end key. if region.get_end_key() > self.mode.max_key().as_slice() { *region.mut_end_key() = vec![]; } else { - *region.mut_end_key() = self.decode_key(region.get_end_key().to_vec())?; + self.decode_key(region.mut_end_key())?; } - Ok(region) + Ok(()) } fn is_plain(&self) -> bool { diff --git a/src/request/mod.rs b/src/request/mod.rs index 7fe3d83f..3a746785 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -41,6 +41,35 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { } } +#[macro_export] +macro_rules! impl_kv_request { + ($req:ty, $resp:ty; encode=$($i:ident),*) => { + impl KvRequest for $req + where C: RequestCodec + { + type Response = $resp; + + fn encode_request(mut self, codec: &C) -> Self { + $( + paste::paste! { + *self.[]() = codec.[](self.[]()); + } + + self + )* + } + + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + if resp.has_region_error() { + codec.decode_region_error(resp.mut_region_error())?; + } + + Ok(resp) + } + } + }; +} + #[macro_export] macro_rules! impl_kv_request_for_single_key_op { ($req: ty, $resp: ty) => { @@ -79,7 +108,7 @@ macro_rules! impl_kv_request_for_batch_get { codec: &C, mut resp: Self::Response, ) -> $crate::Result { - *resp.mut_pairs() = codec.decode_pairs(resp.take_pairs())?; + codec.decode_pairs(resp.mut_pairs())?; Ok(resp) } @@ -112,9 +141,9 @@ macro_rules! impl_kv_request_for_scan_op { mut resp: Self::Response, ) -> $crate::Result { paste::paste! { - let pairs = resp.[](); + let pairs = resp.[](); - *resp.[]() = codec.encode_pairs(pairs); + codec.decode_pairs(pairs)?; Ok(resp) } diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 30cdddd3..8d7e6729 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -171,7 +171,7 @@ impl KvRequest for kvrpcpb::ResolveLockRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; + codec.decode_key_error(resp.mut_error())?; Ok(resp) } @@ -243,7 +243,7 @@ impl KvRequest for kvrpcpb::PrewriteRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_errors(codec, resp.mut_errors())?; + codec.decode_key_errors(resp.mut_errors())?; Ok(resp) } @@ -302,7 +302,7 @@ impl KvRequest for kvrpcpb::CommitRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; + codec.decode_key_error(resp.mut_error())?; Ok(resp) } @@ -330,7 +330,7 @@ impl KvRequest for kvrpcpb::BatchRollbackRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; + codec.decode_key_error(resp.mut_error())?; Ok(resp) } @@ -361,7 +361,7 @@ impl KvRequest for kvrpcpb::PessimisticRollbackRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_errors(codec, resp.mut_errors())?; + codec.decode_key_errors(resp.mut_errors())?; Ok(resp) } @@ -405,7 +405,7 @@ impl KvRequest for kvrpcpb::PessimisticLockRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_errors(codec, resp.mut_errors())?; + codec.decode_key_errors(resp.mut_errors())?; Ok(resp) } @@ -516,8 +516,8 @@ impl KvRequest for kvrpcpb::ScanLockRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; - decode_lock_infos(codec, resp.mut_locks())?; + codec.decode_key_error(resp.mut_error())?; + codec.decode_locks(resp.mut_locks())?; Ok(resp) } @@ -573,7 +573,7 @@ impl KvRequest for kvrpcpb::TxnHeartBeatRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; + codec.decode_key_error(resp.mut_error())?; Ok(resp) } } @@ -621,8 +621,8 @@ impl KvRequest for kvrpcpb::CheckTxnStatusRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; - decode_lock_info(codec, resp.mut_lock_info())?; + codec.decode_key_error(resp.mut_error())?; + codec.decode_lock(resp.mut_lock_info())?; Ok(resp) } } @@ -701,8 +701,8 @@ impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - decode_key_error(codec, resp.mut_error())?; - decode_lock_infos(codec, resp.mut_locks())?; + codec.decode_key_error(resp.mut_error())?; + codec.decode_locks(resp.mut_locks())?; Ok(resp) } } @@ -784,81 +784,6 @@ impl HasLocks for kvrpcpb::PrewriteResponse { } } -pub(crate) fn decode_lock_info( - codec: &C, - err: &mut kvrpcpb::LockInfo, -) -> Result<()> { - *err.mut_primary_lock() = codec.decode_key(err.take_primary_lock())?; - *err.mut_key() = codec.decode_key(err.take_key())?; - *err.mut_secondaries() = codec.decode_keys(err.take_secondaries())?; - - Ok(()) -} - -pub(crate) fn decode_lock_infos( - codec: &C, - errs: &mut [kvrpcpb::LockInfo], -) -> Result<()> { - for err in errs.iter_mut() { - decode_lock_info(codec, err)?; - } - - Ok(()) -} - -pub(crate) fn decode_key_errors( - codec: &C, - errs: &mut [kvrpcpb::KeyError], -) -> Result<()> { - for err in errs.iter_mut() { - decode_key_error(codec, err)?; - } - - Ok(()) -} - -pub(crate) fn decode_key_error( - codec: &C, - err: &mut kvrpcpb::KeyError, -) -> Result<()> { - if err.has_locked() { - let locked = err.mut_locked(); - decode_lock_info(codec, locked)?; - } - - if err.has_conflict() { - let conflict = err.mut_conflict(); - *conflict.mut_key() = codec.decode_key(conflict.take_key())?; - *conflict.mut_primary() = codec.decode_key(conflict.take_primary())?; - } - - if err.has_already_exist() { - let already_exist = err.mut_already_exist(); - *already_exist.mut_key() = codec.decode_key(already_exist.take_key())?; - } - - // We do not decode key in `Deadlock` since there is no use for the key right now in client side. - // All we need is the key hash to detect deadlock. - // TODO: while we check the keys against the deadlock key hash, we need to encode the key. - - if err.has_commit_ts_expired() { - let commit_ts_expired = err.mut_commit_ts_expired(); - *commit_ts_expired.mut_key() = codec.decode_key(commit_ts_expired.take_key())?; - } - - if err.has_txn_not_found() { - let txn_not_found = err.mut_txn_not_found(); - *txn_not_found.mut_primary_key() = codec.decode_key(txn_not_found.take_primary_key())?; - } - - if err.has_assertion_failed() { - let assertion_failed = err.mut_assertion_failed(); - *assertion_failed.mut_key() = codec.decode_key(assertion_failed.take_key())?; - } - - Ok(()) -} - #[cfg(test)] mod tests { use tikv_client_common::Error::{PessimisticLockError, ResolveLockError}; From 5c5809a2fc149eb7b8a9febd7b9cd7507cd61c40 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Wed, 6 Jul 2022 21:56:14 +0800 Subject: [PATCH 22/43] introduce impl_kv_request to simplify code Signed-off-by: iosmanthus --- src/raw/requests.rs | 67 +++++++++++-------------------------- src/request/codec.rs | 10 ++++-- src/request/mod.rs | 55 +++++++++++++++++++++++++----- src/transaction/requests.rs | 65 +++++++++++++---------------------- 4 files changed, 97 insertions(+), 100 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index d6f1c907..1b0f9385 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -32,7 +32,7 @@ pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::R req } -impl_kv_request_for_single_key_op!(kvrpcpb::RawGetRequest, kvrpcpb::RawGetResponse); +impl_kv_request!(kvrpcpb::RawGetRequest, key; kvrpcpb::RawGetResponse;); shardable_key!(kvrpcpb::RawGetRequest); collect_first!(kvrpcpb::RawGetResponse); @@ -66,8 +66,7 @@ pub fn new_raw_batch_get_request( req } -impl_kv_request_for_batch_get!(kvrpcpb::RawBatchGetRequest, kvrpcpb::RawBatchGetResponse); - +impl_kv_request!(kvrpcpb::RawBatchGetRequest, keys; kvrpcpb::RawBatchGetResponse;); shardable_keys!(kvrpcpb::RawBatchGetRequest); impl Merge for Collect { @@ -96,7 +95,7 @@ pub fn new_raw_put_request( req } -impl_kv_request!(kvrpcpb::RawPutRequest, kvrpcpb::RawPutResponse; encode=key); +impl_kv_request!(kvrpcpb::RawPutRequest, key; kvrpcpb::RawPutResponse;); shardable_key!(kvrpcpb::RawPutRequest); collect_first!(kvrpcpb::RawPutResponse); @@ -119,15 +118,7 @@ pub fn new_raw_batch_put_request( req } -impl KvRequest for kvrpcpb::RawBatchPutRequest { - type Response = kvrpcpb::RawBatchPutResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_pairs() = codec.encode_pairs(self.take_pairs()); - - self - } -} +impl_kv_request!(kvrpcpb::RawBatchPutRequest, pairs; kvrpcpb::RawBatchPutResponse;); impl Shardable for kvrpcpb::RawBatchPutRequest { type Shard = Vec; @@ -164,7 +155,7 @@ pub fn new_raw_delete_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::RawDeleteRequest, kvrpcpb::RawDeleteResponse); +impl_kv_request!(kvrpcpb::RawDeleteRequest, key; kvrpcpb::RawDeleteResponse;); shardable_key!(kvrpcpb::RawDeleteRequest); collect_first!(kvrpcpb::RawDeleteResponse); impl SingleKey for kvrpcpb::RawDeleteRequest { @@ -184,16 +175,7 @@ pub fn new_raw_batch_delete_request( req } -impl KvRequest for kvrpcpb::RawBatchDeleteRequest { - type Response = kvrpcpb::RawBatchDeleteResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - - self - } -} - +impl_kv_request!(kvrpcpb::RawBatchDeleteRequest, keys; kvrpcpb::RawBatchDeleteResponse;); shardable_keys!(kvrpcpb::RawBatchDeleteRequest); pub fn new_raw_delete_range_request( @@ -209,18 +191,10 @@ pub fn new_raw_delete_range_request( req } -impl KvRequest for kvrpcpb::RawDeleteRangeRequest { - type Response = kvrpcpb::RawDeleteRangeResponse; - - fn encode_request(mut self, codec: &C) -> Self { - let (start, end) = (self.take_start_key(), self.take_end_key()); - - self.set_start_key(codec.encode_key(start)); - self.set_end_key(codec.encode_key(end)); - - self - } -} +impl_kv_request!( + kvrpcpb::RawDeleteRangeRequest; + kvrpcpb::RawDeleteRangeResponse; +); shardable_range!(kvrpcpb::RawDeleteRangeRequest); @@ -241,7 +215,7 @@ pub fn new_raw_scan_request( req } -impl_kv_request_for_scan_op!(kvrpcpb::RawScanRequest, kvrpcpb::RawScanResponse, kvs); +impl_kv_request!(kvrpcpb::RawScanRequest; kvrpcpb::RawScanResponse, kvs;); shardable_range!(kvrpcpb::RawScanRequest); impl Merge for Collect { @@ -270,15 +244,10 @@ pub fn new_raw_batch_scan_request( req } -impl KvRequest for kvrpcpb::RawBatchScanRequest { - type Response = kvrpcpb::RawBatchScanResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_ranges() = codec.encode_ranges(self.take_ranges()); - - self - } -} +impl_kv_request!( + kvrpcpb::RawBatchScanRequest, ranges; + kvrpcpb::RawBatchScanResponse, kvs; +); impl Shardable for kvrpcpb::RawBatchScanRequest { type Shard = Vec; @@ -325,7 +294,11 @@ pub fn new_cas_request( req } -impl_kv_request_for_single_key_op!(kvrpcpb::RawCasRequest, kvrpcpb::RawCasResponse); +impl_kv_request!( + kvrpcpb::RawCasRequest, key; + kvrpcpb::RawCasResponse; +); + shardable_key!(kvrpcpb::RawCasRequest); collect_first!(kvrpcpb::RawCasResponse); impl SingleKey for kvrpcpb::RawCasRequest { diff --git a/src/request/codec.rs b/src/request/codec.rs index 02753af0..95081a80 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -58,7 +58,7 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } - fn decode_key_error(&self, err: &mut kvrpcpb::KeyError) -> Result<()> { + fn decode_error(&self, err: &mut kvrpcpb::KeyError) -> Result<()> { if err.has_locked() { let locked = err.mut_locked(); self.decode_lock(locked)?; @@ -97,9 +97,9 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } - fn decode_key_errors(&self, errors: &mut [kvrpcpb::KeyError]) -> Result<()> { + fn decode_errors(&self, errors: &mut [kvrpcpb::KeyError]) -> Result<()> { for err in errors.iter_mut() { - self.decode_key_error(err)?; + self.decode_error(err)?; } Ok(()) @@ -127,6 +127,10 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } + fn decode_kvs(&self, kvs: &mut [kvrpcpb::KvPair]) -> Result<()> { + self.decode_pairs(kvs) + } + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { (start, end) } diff --git a/src/request/mod.rs b/src/request/mod.rs index 3a746785..8548dda6 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -41,9 +41,36 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { } } +macro_rules! impl_decode_response { + ($($o:ident)*; $($e:ident)*) => { + fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + $( + paste::paste! { + codec.[](resp.[]())?; + } + )* + + // decode errors + if resp.has_region_error() { + codec.decode_region_error(resp.mut_region_error())?; + } + + $( + paste::paste! { + if resp.[]() { + codec.[](resp.[]())?; + } + } + )* + + Ok(resp) + } + }; +} + #[macro_export] macro_rules! impl_kv_request { - ($req:ty, $resp:ty; encode=$($i:ident),*) => { + ($req:ty $(,$i:ident)+; $resp:ty $(,$o:ident)*; $($e:ident),*) => { impl KvRequest for $req where C: RequestCodec { @@ -54,18 +81,30 @@ macro_rules! impl_kv_request { paste::paste! { *self.[]() = codec.[](self.[]()); } - - self )* + + self } - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - if resp.has_region_error() { - codec.decode_region_error(resp.mut_region_error())?; - } + impl_decode_response!{$($o)*; $($e)*} + } + }; - Ok(resp) + ($req:ty; $resp:ty $(,$o:ident)*;$($e:ident)*) => { + impl KvRequest for $req + where C: RequestCodec + { + type Response = $resp; + + fn encode_request(mut self, codec: &C) -> Self { + let (start, end) = codec.encode_range(self.take_start_key(), self.take_end_key()); + *self.mut_start_key() = start; + *self.mut_end_key() = end; + + self } + + impl_decode_response!{$($o)*; $($e)*} } }; } diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 8d7e6729..afaecc79 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -72,7 +72,7 @@ pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest { req } -impl_kv_request_for_single_key_op!(kvrpcpb::GetRequest, kvrpcpb::GetResponse); +impl_kv_request!(kvrpcpb::GetRequest, key; kvrpcpb::GetResponse; error); shardable_key!(kvrpcpb::GetRequest); collect_first!(kvrpcpb::GetResponse); impl SingleKey for kvrpcpb::GetRequest { @@ -101,7 +101,11 @@ pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::Bat req } -impl_kv_request_for_batch_get!(kvrpcpb::BatchGetRequest, kvrpcpb::BatchGetResponse); +impl_kv_request!( + kvrpcpb::BatchGetRequest, keys; + kvrpcpb::BatchGetResponse, pairs; + error +); shardable_keys!(kvrpcpb::BatchGetRequest); impl Merge for Collect { @@ -131,7 +135,7 @@ pub fn new_scan_request( req } -impl_kv_request_for_scan_op!(kvrpcpb::ScanRequest, kvrpcpb::ScanResponse, pairs); +impl_kv_request!(kvrpcpb::ScanRequest; kvrpcpb::ScanResponse, pairs; error); shardable_range!(kvrpcpb::ScanRequest); impl Merge for Collect { @@ -161,21 +165,7 @@ pub fn new_resolve_lock_request( // on its region errors (in the Plan level). The region error must be manually // handled (in the upper level). -impl KvRequest for kvrpcpb::ResolveLockRequest { - type Response = kvrpcpb::ResolveLockResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; - - Ok(resp) - } -} +impl_kv_request!(kvrpcpb::ResolveLockRequest, keys; kvrpcpb::ResolveLockResponse; error); pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest { let mut req = kvrpcpb::CleanupRequest::default(); @@ -185,7 +175,12 @@ pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::Cleanup req } -impl_kv_request_for_single_key_op!(kvrpcpb::CleanupRequest, kvrpcpb::CleanupResponse); +impl_kv_request!( + kvrpcpb::CleanupRequest, key; + kvrpcpb::CleanupResponse; + error +); + shardable_key!(kvrpcpb::CleanupRequest); collect_first!(kvrpcpb::CleanupResponse); impl SingleKey for kvrpcpb::CleanupRequest { @@ -233,21 +228,7 @@ pub fn new_pessimistic_prewrite_request( req } -impl KvRequest for kvrpcpb::PrewriteRequest { - type Response = kvrpcpb::PrewriteResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_mutations() = codec.encode_mutations(self.take_mutations()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_errors(resp.mut_errors())?; - - Ok(resp) - } -} +impl_kv_request!(kvrpcpb::PrewriteRequest, mutations; kvrpcpb::PrewriteResponse; errors); impl Shardable for kvrpcpb::PrewriteRequest { type Shard = Vec; @@ -302,7 +283,7 @@ impl KvRequest for kvrpcpb::CommitRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; + codec.decode_error(resp.mut_error())?; Ok(resp) } @@ -330,7 +311,7 @@ impl KvRequest for kvrpcpb::BatchRollbackRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; + codec.decode_error(resp.mut_error())?; Ok(resp) } @@ -361,7 +342,7 @@ impl KvRequest for kvrpcpb::PessimisticRollbackRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_errors(resp.mut_errors())?; + codec.decode_errors(resp.mut_errors())?; Ok(resp) } @@ -405,7 +386,7 @@ impl KvRequest for kvrpcpb::PessimisticLockRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_errors(resp.mut_errors())?; + codec.decode_errors(resp.mut_errors())?; Ok(resp) } @@ -516,7 +497,7 @@ impl KvRequest for kvrpcpb::ScanLockRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; + codec.decode_error(resp.mut_error())?; codec.decode_locks(resp.mut_locks())?; Ok(resp) @@ -573,7 +554,7 @@ impl KvRequest for kvrpcpb::TxnHeartBeatRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; + codec.decode_error(resp.mut_error())?; Ok(resp) } } @@ -621,7 +602,7 @@ impl KvRequest for kvrpcpb::CheckTxnStatusRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; + codec.decode_error(resp.mut_error())?; codec.decode_lock(resp.mut_lock_info())?; Ok(resp) } @@ -701,7 +682,7 @@ impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { } fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_key_error(resp.mut_error())?; + codec.decode_error(resp.mut_error())?; codec.decode_locks(resp.mut_locks())?; Ok(resp) } From 701964d24eb3ff87f9780ea43326c12c0c67cc0d Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 7 Jul 2022 00:59:27 +0800 Subject: [PATCH 23/43] refactor impl_kv_request macro Signed-off-by: iosmanthus --- src/raw/requests.rs | 20 ++--- src/request/codec.rs | 14 ++- src/request/mod.rs | 33 ++++--- src/transaction/requests.rs | 168 +++++++++--------------------------- 4 files changed, 80 insertions(+), 155 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index 1b0f9385..515f0603 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -32,7 +32,7 @@ pub fn new_raw_get_request(key: Vec, cf: Option) -> kvrpcpb::R req } -impl_kv_request!(kvrpcpb::RawGetRequest, key; kvrpcpb::RawGetResponse;); +impl_kv_request!(kvrpcpb::RawGetRequest, key; kvrpcpb::RawGetResponse); shardable_key!(kvrpcpb::RawGetRequest); collect_first!(kvrpcpb::RawGetResponse); @@ -66,7 +66,7 @@ pub fn new_raw_batch_get_request( req } -impl_kv_request!(kvrpcpb::RawBatchGetRequest, keys; kvrpcpb::RawBatchGetResponse;); +impl_kv_request!(kvrpcpb::RawBatchGetRequest, keys; kvrpcpb::RawBatchGetResponse); shardable_keys!(kvrpcpb::RawBatchGetRequest); impl Merge for Collect { @@ -95,7 +95,7 @@ pub fn new_raw_put_request( req } -impl_kv_request!(kvrpcpb::RawPutRequest, key; kvrpcpb::RawPutResponse;); +impl_kv_request!(kvrpcpb::RawPutRequest, key; kvrpcpb::RawPutResponse); shardable_key!(kvrpcpb::RawPutRequest); collect_first!(kvrpcpb::RawPutResponse); @@ -118,7 +118,7 @@ pub fn new_raw_batch_put_request( req } -impl_kv_request!(kvrpcpb::RawBatchPutRequest, pairs; kvrpcpb::RawBatchPutResponse;); +impl_kv_request!(kvrpcpb::RawBatchPutRequest, pairs; kvrpcpb::RawBatchPutResponse); impl Shardable for kvrpcpb::RawBatchPutRequest { type Shard = Vec; @@ -155,7 +155,7 @@ pub fn new_raw_delete_request( req } -impl_kv_request!(kvrpcpb::RawDeleteRequest, key; kvrpcpb::RawDeleteResponse;); +impl_kv_request!(kvrpcpb::RawDeleteRequest, key; kvrpcpb::RawDeleteResponse); shardable_key!(kvrpcpb::RawDeleteRequest); collect_first!(kvrpcpb::RawDeleteResponse); impl SingleKey for kvrpcpb::RawDeleteRequest { @@ -175,7 +175,7 @@ pub fn new_raw_batch_delete_request( req } -impl_kv_request!(kvrpcpb::RawBatchDeleteRequest, keys; kvrpcpb::RawBatchDeleteResponse;); +impl_kv_request!(kvrpcpb::RawBatchDeleteRequest, keys; kvrpcpb::RawBatchDeleteResponse); shardable_keys!(kvrpcpb::RawBatchDeleteRequest); pub fn new_raw_delete_range_request( @@ -193,7 +193,7 @@ pub fn new_raw_delete_range_request( impl_kv_request!( kvrpcpb::RawDeleteRangeRequest; - kvrpcpb::RawDeleteRangeResponse; + kvrpcpb::RawDeleteRangeResponse ); shardable_range!(kvrpcpb::RawDeleteRangeRequest); @@ -215,7 +215,7 @@ pub fn new_raw_scan_request( req } -impl_kv_request!(kvrpcpb::RawScanRequest; kvrpcpb::RawScanResponse, kvs;); +impl_kv_request!(kvrpcpb::RawScanRequest; kvrpcpb::RawScanResponse, kvs); shardable_range!(kvrpcpb::RawScanRequest); impl Merge for Collect { @@ -246,7 +246,7 @@ pub fn new_raw_batch_scan_request( impl_kv_request!( kvrpcpb::RawBatchScanRequest, ranges; - kvrpcpb::RawBatchScanResponse, kvs; + kvrpcpb::RawBatchScanResponse, kvs ); impl Shardable for kvrpcpb::RawBatchScanRequest { @@ -296,7 +296,7 @@ pub fn new_cas_request( impl_kv_request!( kvrpcpb::RawCasRequest, key; - kvrpcpb::RawCasResponse; + kvrpcpb::RawCasResponse ); shardable_key!(kvrpcpb::RawCasRequest); diff --git a/src/request/codec.rs b/src/request/codec.rs index 95081a80..0051fd5e 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -23,6 +23,14 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { key } + fn encode_primary_lock(&self, lock: Vec) -> Vec { + self.encode_key(lock) + } + + fn encode_primary_key(&self, key: Vec) -> Vec { + self.encode_key(key) + } + fn encode_mutations(&self, mutations: Vec) -> Vec { mutations .into_iter() @@ -61,7 +69,7 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { fn decode_error(&self, err: &mut kvrpcpb::KeyError) -> Result<()> { if err.has_locked() { let locked = err.mut_locked(); - self.decode_lock(locked)?; + self.decode_lock_info(locked)?; } if err.has_conflict() { @@ -105,7 +113,7 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } - fn decode_lock(&self, lock: &mut kvrpcpb::LockInfo) -> Result<()> { + fn decode_lock_info(&self, lock: &mut kvrpcpb::LockInfo) -> Result<()> { self.decode_key(lock.mut_primary_lock())?; self.decode_key(lock.mut_key())?; self.decode_keys(lock.mut_secondaries()) @@ -113,7 +121,7 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { fn decode_locks(&self, locks: &mut [kvrpcpb::LockInfo]) -> Result<()> { for lock in locks.iter_mut() { - self.decode_lock(lock)?; + self.decode_lock_info(lock)?; } Ok(()) diff --git a/src/request/mod.rs b/src/request/mod.rs index 8548dda6..575f9810 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -41,24 +41,31 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { } } +pub trait IsDefault { + fn is_default(&self) -> bool; +} + +impl IsDefault for T { + fn is_default(&self) -> bool { + *self == T::default() + } +} + macro_rules! impl_decode_response { - ($($o:ident)*; $($e:ident)*) => { + ($($o:ident)*) => { fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - $( - paste::paste! { - codec.[](resp.[]())?; - } - )* - // decode errors if resp.has_region_error() { codec.decode_region_error(resp.mut_region_error())?; } + #[allow(unused_imports)] + use $crate::request::IsDefault; + $( paste::paste! { - if resp.[]() { - codec.[](resp.[]())?; + if !resp.[]().is_default() { + codec.[](resp.[]())?; } } )* @@ -70,7 +77,7 @@ macro_rules! impl_decode_response { #[macro_export] macro_rules! impl_kv_request { - ($req:ty $(,$i:ident)+; $resp:ty $(,$o:ident)*; $($e:ident),*) => { + ($req:ty $(,$i:ident)+; $resp:ty $(,$o:ident)*) => { impl KvRequest for $req where C: RequestCodec { @@ -86,11 +93,11 @@ macro_rules! impl_kv_request { self } - impl_decode_response!{$($o)*; $($e)*} + impl_decode_response!{$($o)*} } }; - ($req:ty; $resp:ty $(,$o:ident)*;$($e:ident)*) => { + ($req:ty; $resp:ty $(,$o:ident)*) => { impl KvRequest for $req where C: RequestCodec { @@ -104,7 +111,7 @@ macro_rules! impl_kv_request { self } - impl_decode_response!{$($o)*; $($e)*} + impl_decode_response!{$($o)*} } }; } diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index afaecc79..9511ae8e 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -72,7 +72,7 @@ pub fn new_get_request(key: Vec, timestamp: u64) -> kvrpcpb::GetRequest { req } -impl_kv_request!(kvrpcpb::GetRequest, key; kvrpcpb::GetResponse; error); +impl_kv_request!(kvrpcpb::GetRequest, key; kvrpcpb::GetResponse, error); shardable_key!(kvrpcpb::GetRequest); collect_first!(kvrpcpb::GetResponse); impl SingleKey for kvrpcpb::GetRequest { @@ -103,8 +103,7 @@ pub fn new_batch_get_request(keys: Vec>, timestamp: u64) -> kvrpcpb::Bat impl_kv_request!( kvrpcpb::BatchGetRequest, keys; - kvrpcpb::BatchGetResponse, pairs; - error + kvrpcpb::BatchGetResponse, pairs, error ); shardable_keys!(kvrpcpb::BatchGetRequest); @@ -135,7 +134,7 @@ pub fn new_scan_request( req } -impl_kv_request!(kvrpcpb::ScanRequest; kvrpcpb::ScanResponse, pairs; error); +impl_kv_request!(kvrpcpb::ScanRequest; kvrpcpb::ScanResponse, pairs, error); shardable_range!(kvrpcpb::ScanRequest); impl Merge for Collect { @@ -165,7 +164,7 @@ pub fn new_resolve_lock_request( // on its region errors (in the Plan level). The region error must be manually // handled (in the upper level). -impl_kv_request!(kvrpcpb::ResolveLockRequest, keys; kvrpcpb::ResolveLockResponse; error); +impl_kv_request!(kvrpcpb::ResolveLockRequest, keys; kvrpcpb::ResolveLockResponse, error); pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::CleanupRequest { let mut req = kvrpcpb::CleanupRequest::default(); @@ -177,8 +176,7 @@ pub fn new_cleanup_request(key: Vec, start_version: u64) -> kvrpcpb::Cleanup impl_kv_request!( kvrpcpb::CleanupRequest, key; - kvrpcpb::CleanupResponse; - error + kvrpcpb::CleanupResponse, error ); shardable_key!(kvrpcpb::CleanupRequest); @@ -228,7 +226,7 @@ pub fn new_pessimistic_prewrite_request( req } -impl_kv_request!(kvrpcpb::PrewriteRequest, mutations; kvrpcpb::PrewriteResponse; errors); +impl_kv_request!(kvrpcpb::PrewriteRequest, mutations; kvrpcpb::PrewriteResponse, errors); impl Shardable for kvrpcpb::PrewriteRequest { type Shard = Vec; @@ -273,21 +271,7 @@ pub fn new_commit_request( req } -impl KvRequest for kvrpcpb::CommitRequest { - type Response = kvrpcpb::CommitResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_error(resp.mut_error())?; - - Ok(resp) - } -} +impl_kv_request!(kvrpcpb::CommitRequest, keys; kvrpcpb::CommitResponse, error); shardable_keys!(kvrpcpb::CommitRequest); pub fn new_batch_rollback_request( @@ -301,22 +285,7 @@ pub fn new_batch_rollback_request( req } -impl KvRequest for kvrpcpb::BatchRollbackRequest { - type Response = kvrpcpb::BatchRollbackResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_error(resp.mut_error())?; - - Ok(resp) - } -} - +impl_kv_request!(kvrpcpb::BatchRollbackRequest, keys; kvrpcpb::BatchRollbackResponse, error); shardable_keys!(kvrpcpb::BatchRollbackRequest); pub fn new_pessimistic_rollback_request( @@ -332,21 +301,12 @@ pub fn new_pessimistic_rollback_request( req } -impl KvRequest for kvrpcpb::PessimisticRollbackRequest { - type Response = kvrpcpb::PessimisticRollbackResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_errors(resp.mut_errors())?; - - Ok(resp) - } -} +impl_kv_request!( + kvrpcpb::PessimisticRollbackRequest, + keys; + kvrpcpb::PessimisticRollbackResponse, + errors +); shardable_keys!(kvrpcpb::PessimisticRollbackRequest); @@ -375,22 +335,12 @@ pub fn new_pessimistic_lock_request( req } -impl KvRequest for kvrpcpb::PessimisticLockRequest { - type Response = kvrpcpb::PessimisticLockResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_mutations() = codec.encode_mutations(self.take_mutations()); - *self.mut_primary_lock() = codec.encode_key(self.take_primary_lock()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_errors(resp.mut_errors())?; - - Ok(resp) - } -} +impl_kv_request!( + kvrpcpb::PessimisticLockRequest, + mutations, primary_lock; + kvrpcpb::PessimisticLockResponse, + errors +); impl Shardable for kvrpcpb::PessimisticLockRequest { type Shard = Vec; @@ -486,23 +436,11 @@ pub fn new_scan_lock_request( req } -impl KvRequest for kvrpcpb::ScanLockRequest { - type Response = kvrpcpb::ScanLockResponse; - - fn encode_request(mut self, codec: &C) -> Self { - let (start, end) = codec.encode_range(self.take_start_key(), self.take_end_key()); - self.set_start_key(start); - self.set_end_key(end); - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_error(resp.mut_error())?; - codec.decode_locks(resp.mut_locks())?; - - Ok(resp) - } -} +impl_kv_request!( + kvrpcpb::ScanLockRequest; + kvrpcpb::ScanLockResponse, + error, locks +); impl Shardable for kvrpcpb::ScanLockRequest { type Shard = Vec; @@ -544,20 +482,12 @@ pub fn new_heart_beat_request( req } -impl KvRequest for kvrpcpb::TxnHeartBeatRequest { - type Response = kvrpcpb::TxnHeartBeatResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_primary_lock() = codec.encode_key(self.take_primary_lock()); - - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_error(resp.mut_error())?; - Ok(resp) - } -} +impl_kv_request!( + kvrpcpb::TxnHeartBeatRequest, + primary_lock; + kvrpcpb::TxnHeartBeatResponse, + error +); impl Shardable for kvrpcpb::TxnHeartBeatRequest { type Shard = Vec>; @@ -593,20 +523,10 @@ impl Process for DefaultProcessor { } } -impl KvRequest for kvrpcpb::CheckTxnStatusRequest { - type Response = kvrpcpb::CheckTxnStatusResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_primary_key() = codec.encode_key(self.take_primary_key()); - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_error(resp.mut_error())?; - codec.decode_lock(resp.mut_lock_info())?; - Ok(resp) - } -} +impl_kv_request!( + kvrpcpb::CheckTxnStatusRequest, primary_key; + kvrpcpb::CheckTxnStatusResponse, lock_info, error +); impl Shardable for kvrpcpb::CheckTxnStatusRequest { type Shard = Vec>; @@ -673,20 +593,10 @@ impl From<(u64, u64, Option)> for TransactionStatusKind { } } -impl KvRequest for kvrpcpb::CheckSecondaryLocksRequest { - type Response = kvrpcpb::CheckSecondaryLocksResponse; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - self - } - - fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { - codec.decode_error(resp.mut_error())?; - codec.decode_locks(resp.mut_locks())?; - Ok(resp) - } -} +impl_kv_request!( + kvrpcpb::CheckSecondaryLocksRequest, keys; + kvrpcpb::CheckSecondaryLocksResponse, locks, error +); shardable_keys!(kvrpcpb::CheckSecondaryLocksRequest); From db38d958503e4ca3863a36332df00eb75b8406d9 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 7 Jul 2022 01:06:42 +0800 Subject: [PATCH 24/43] fix tests Signed-off-by: iosmanthus --- src/lib.rs | 4 ++-- src/raw/client.rs | 28 ++++++++++++++-------------- src/transaction/client.rs | 12 ++++++------ src/transaction/transaction.rs | 28 ++++++++++++++-------------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 56f132a5..e0fb9b40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,7 +66,7 @@ //! # use tikv_client::{RawClient, Result}; //! # use futures::prelude::*; //! # fn main() -> Result<()> { -//! # use tikv_client::request::request_codec::RawApiV1; +//! # use tikv_client::request::codec::RawApiV1; //! futures::executor::block_on(async { //! let client = RawClient::new(vec!["127.0.0.1:2379"], RawApiV1, None).await?; //! client.put("key".to_owned(), "value".to_owned()).await?; @@ -81,7 +81,7 @@ //! # use tikv_client::{TransactionClient, Result}; //! # use futures::prelude::*; //! # fn main() -> Result<()> { -//! # use tikv_client::request::request_codec::TxnApiV1; +//! # use tikv_client::request::codec::TxnApiV1; //! futures::executor::block_on(async { //! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], TxnApiV1, None).await?; //! let mut txn = txn_client.begin_optimistic().await?; diff --git a/src/raw/client.rs b/src/raw/client.rs index be7aae0d..9fed7fc4 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -62,7 +62,7 @@ impl Client { /// ```rust,no_run /// # use tikv_client::RawClient; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None) /// .await @@ -89,7 +89,7 @@ impl Client { /// # use tikv_client::{Config, RawClient}; /// # use futures::prelude::*; /// # use std::time::Duration; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// let client = RawClient::new_with_config( /// vec!["192.168.0.100"], @@ -145,7 +145,7 @@ impl Client { /// # use tikv_client::{Config, RawClient, ColumnFamily}; /// # use futures::prelude::*; /// # use std::convert::TryInto; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None) /// .await @@ -201,7 +201,7 @@ where /// ```rust,no_run /// # use tikv_client::{Value, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); @@ -236,7 +236,7 @@ where /// ```rust,no_run /// # use tikv_client::{KvPair, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; @@ -276,7 +276,7 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); @@ -315,7 +315,7 @@ where /// ```rust,no_run /// # use tikv_client::{Result, KvPair, Key, Value, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let kvpair1 = ("PD".to_owned(), "Go".to_owned()); @@ -362,7 +362,7 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); @@ -397,7 +397,7 @@ where /// ```rust,no_run /// # use tikv_client::{Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; @@ -435,7 +435,7 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; @@ -476,7 +476,7 @@ where /// ```rust,no_run /// # use tikv_client::{KvPair, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; @@ -511,7 +511,7 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; @@ -554,7 +554,7 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; @@ -599,7 +599,7 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::RawApiV1; + /// use tikv_client::request::codec::RawApiV1; /// # futures::executor::block_on(async { /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; diff --git a/src/transaction/client.rs b/src/transaction/client.rs index de8ef4e9..b7f79cac 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -68,7 +68,7 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await @@ -96,7 +96,7 @@ where /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::time::Duration; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new_with_config( /// vec!["192.168.0.100"], @@ -148,7 +148,7 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await @@ -174,7 +174,7 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await @@ -197,7 +197,7 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient, TransactionOptions}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await @@ -237,7 +237,7 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 5f852ffe..9391b380 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -51,7 +51,7 @@ use crate::{ /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; -/// use tikv_client::request::request_codec::TxnApiV1; +/// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) /// .await @@ -108,7 +108,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -170,7 +170,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); @@ -205,7 +205,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); @@ -233,7 +233,7 @@ impl Transaction { /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -287,7 +287,7 @@ impl Transaction { /// # use tikv_client::{Key, Value, Config, TransactionClient, KvPair}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); @@ -333,7 +333,7 @@ impl Transaction { /// # use tikv_client::{Key, KvPair, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -370,7 +370,7 @@ impl Transaction { /// # use tikv_client::{Key, KvPair, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -412,7 +412,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -444,7 +444,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -481,7 +481,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -517,7 +517,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -554,7 +554,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, Timestamp, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -613,7 +613,7 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, Timestamp, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::request_codec::TxnApiV1; + /// use tikv_client::request::codec::TxnApiV1; /// # futures::executor::block_on(async { /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); From 3660ca1c79a3c7f3ff39f78ac30915010cc5c3be Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 7 Jul 2022 18:44:56 +0800 Subject: [PATCH 25/43] move default impl into RequestCodecExt Signed-off-by: iosmanthus --- src/request/codec.rs | 61 ++++++++++++++++++++++++-------------------- src/request/mod.rs | 9 ++++--- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/request/codec.rs b/src/request/codec.rs index 0051fd5e..2cbe0ede 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,5 +1,6 @@ use core::intrinsics::copy; use std::ops::{Deref, DerefMut}; + use tikv_client_common::Error; use tikv_client_proto::{errorpb, kvrpcpb, metapb::Region}; @@ -23,6 +24,28 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { key } + fn decode_key(&self, _key: &mut Vec) -> Result<()> { + Ok(()) + } + + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + (start, end) + } + + fn encode_pd_query(&self, key: Vec) -> Vec { + key + } + + fn decode_region(&self, _region: &mut Region) -> Result<()> { + Ok(()) + } + + fn is_plain(&self) -> bool { + true + } +} + +pub trait RequestCodecExt: RequestCodec { fn encode_primary_lock(&self, lock: Vec) -> Vec { self.encode_key(lock) } @@ -54,8 +77,14 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { pairs } - fn decode_key(&self, _key: &mut Vec) -> Result<()> { - Ok(()) + fn encode_ranges(&self, mut ranges: Vec) -> Vec { + for range in ranges.iter_mut() { + let (start, end) = self.encode_range(range.take_start_key(), range.take_end_key()); + *range.mut_start_key() = start; + *range.mut_end_key() = end; + } + + ranges } fn decode_keys(&self, keys: &mut [Vec]) -> Result<()> { @@ -139,28 +168,6 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { self.decode_pairs(kvs) } - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { - (start, end) - } - - fn encode_ranges(&self, mut ranges: Vec) -> Vec { - for range in ranges.iter_mut() { - let (start, end) = self.encode_range(range.take_start_key(), range.take_end_key()); - *range.mut_start_key() = start; - *range.mut_end_key() = end; - } - - ranges - } - - fn encode_pd_query(&self, key: Vec) -> Vec { - key - } - - fn decode_region(&self, _region: &mut Region) -> Result<()> { - Ok(()) - } - fn decode_regions(&self, regions: &mut [Region]) -> Result<()> { for region in regions.iter_mut() { self.decode_region(region)?; @@ -174,12 +181,10 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { } Ok(()) } - - fn is_plain(&self) -> bool { - true - } } +impl RequestCodecExt for T {} + #[derive(Clone)] pub struct TxnApiV1; diff --git a/src/request/mod.rs b/src/request/mod.rs index 575f9810..0a784d43 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -54,14 +54,14 @@ impl IsDefault for T { macro_rules! impl_decode_response { ($($o:ident)*) => { fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { + #[allow(unused_imports)] + use $crate::request::{IsDefault, codec::RequestCodecExt}; + // decode errors if resp.has_region_error() { codec.decode_region_error(resp.mut_region_error())?; } - #[allow(unused_imports)] - use $crate::request::IsDefault; - $( paste::paste! { if !resp.[]().is_default() { @@ -84,6 +84,9 @@ macro_rules! impl_kv_request { type Response = $resp; fn encode_request(mut self, codec: &C) -> Self { + #[allow(unused_imports)] + use $crate::request::codec::RequestCodecExt; + $( paste::paste! { *self.[]() = codec.[](self.[]()); From 7d68247b09312a1400db95740fa35d854e3fbcf5 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 8 Jul 2022 00:34:09 +0800 Subject: [PATCH 26/43] fix api version context Signed-off-by: iosmanthus --- src/raw/requests.rs | 6 ++- src/request/codec.rs | 63 ++++++++++++++++++++--- src/request/mod.rs | 86 ++------------------------------ src/request/plan.rs | 18 ++++--- tikv-client-store/src/request.rs | 5 ++ 5 files changed, 80 insertions(+), 98 deletions(-) diff --git a/src/raw/requests.rs b/src/raw/requests.rs index 515f0603..e2053f09 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -66,7 +66,7 @@ pub fn new_raw_batch_get_request( req } -impl_kv_request!(kvrpcpb::RawBatchGetRequest, keys; kvrpcpb::RawBatchGetResponse); +impl_kv_request!(kvrpcpb::RawBatchGetRequest, keys; kvrpcpb::RawBatchGetResponse, pairs); shardable_keys!(kvrpcpb::RawBatchGetRequest); impl Merge for Collect { @@ -362,6 +362,10 @@ impl Request for RawCoprocessorRequest { fn set_context(&mut self, context: kvrpcpb::Context) { self.inner.set_context(context); } + + fn mut_context(&mut self) -> &mut kvrpcpb::Context { + self.inner.mut_context() + } } impl KvRequest for RawCoprocessorRequest { diff --git a/src/request/codec.rs b/src/request/codec.rs index 2cbe0ede..0704ad34 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -40,8 +40,8 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } - fn is_plain(&self) -> bool { - true + fn version(&self) -> kvrpcpb::ApiVersion { + kvrpcpb::ApiVersion::V1 } } @@ -331,7 +331,8 @@ impl RequestCodec for KeySpaceCodec { } // Map the region's end key to the keyspace's end key. - if region.get_end_key() > self.mode.max_key().as_slice() { + if region.get_end_key().is_empty() || region.get_end_key() > self.mode.max_key().as_slice() + { *region.mut_end_key() = vec![]; } else { self.decode_key(region.mut_end_key())?; @@ -340,8 +341,8 @@ impl RequestCodec for KeySpaceCodec { Ok(()) } - fn is_plain(&self) -> bool { - false + fn version(&self) -> kvrpcpb::ApiVersion { + kvrpcpb::ApiVersion::V2 } } @@ -357,7 +358,31 @@ impl RawKeyspaceCodec { } } -impl RequestCodec for RawKeyspaceCodec {} +impl RequestCodec for RawKeyspaceCodec { + fn encode_key(&self, key: Vec) -> Vec { + self.0.encode_key(key) + } + + fn decode_key(&self, key: &mut Vec) -> Result<()> { + self.0.decode_key(key) + } + + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + self.0.encode_range(start, end) + } + + fn encode_pd_query(&self, key: Vec) -> Vec { + self.0.encode_pd_query(key) + } + + fn decode_region(&self, region: &mut Region) -> Result<()> { + self.0.decode_region(region) + } + + fn version(&self) -> kvrpcpb::ApiVersion { + self.0.version() + } +} impl RawCodec for RawKeyspaceCodec {} @@ -373,6 +398,30 @@ impl TxnKeyspaceCodec { } } -impl RequestCodec for TxnKeyspaceCodec {} +impl RequestCodec for TxnKeyspaceCodec { + fn encode_key(&self, key: Vec) -> Vec { + self.0.encode_key(key) + } + + fn decode_key(&self, key: &mut Vec) -> Result<()> { + self.0.decode_key(key) + } + + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + self.0.encode_range(start, end) + } + + fn encode_pd_query(&self, key: Vec) -> Vec { + self.0.encode_pd_query(key) + } + + fn decode_region(&self, region: &mut Region) -> Result<()> { + self.0.decode_region(region) + } + + fn version(&self) -> kvrpcpb::ApiVersion { + self.0.version() + } +} impl TxnCodec for TxnKeyspaceCodec {} diff --git a/src/request/mod.rs b/src/request/mod.rs index 0a784d43..6415aeee 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -119,88 +119,6 @@ macro_rules! impl_kv_request { }; } -#[macro_export] -macro_rules! impl_kv_request_for_single_key_op { - ($req: ty, $resp: ty) => { - impl KvRequest for $req - where - C: RequestCodec, - { - type Response = $resp; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_key() = codec.encode_key(self.take_key()); - - self - } - } - }; -} - -#[macro_export] -macro_rules! impl_kv_request_for_batch_get { - ($req: ty, $resp: ty) => { - impl KvRequest for $req - where - C: RequestCodec, - { - type Response = $resp; - - fn encode_request(mut self, codec: &C) -> Self { - *self.mut_keys() = codec.encode_keys(self.take_keys()); - - self - } - - fn decode_response( - &self, - codec: &C, - mut resp: Self::Response, - ) -> $crate::Result { - codec.decode_pairs(resp.mut_pairs())?; - - Ok(resp) - } - } - }; -} - -#[macro_export] -macro_rules! impl_kv_request_for_scan_op { - ($req: ty, $resp: ty, $pairs: ident) => { - impl KvRequest for $req - where - C: RequestCodec, - { - type Response = $resp; - - fn encode_request(mut self, codec: &C) -> Self { - let (start, end) = - codec.encode_range(self.take_start_key().into(), self.take_end_key().into()); - - self.set_start_key(start); - self.set_end_key(end); - - self - } - - fn decode_response( - &self, - codec: &C, - mut resp: Self::Response, - ) -> $crate::Result { - paste::paste! { - let pairs = resp.[](); - - codec.decode_pairs(pairs)?; - - Ok(resp) - } - } - } - }; -} - #[derive(Clone, Debug, new, Eq, PartialEq)] pub struct RetryOptions { /// How to retry when there is a region error and we need to resolve regions with PD. @@ -296,6 +214,10 @@ mod test { fn set_context(&mut self, _: kvrpcpb::Context) { unreachable!(); } + + fn mut_context(&mut self) -> &mut kvrpcpb::Context { + unreachable!() + } } #[async_trait] diff --git a/src/request/plan.rs b/src/request/plan.rs index e143deec..3cc0c104 100644 --- a/src/request/plan.rs +++ b/src/request/plan.rs @@ -55,10 +55,13 @@ impl> Plan for Dispatch { type Result = Req::Response; async fn execute(&self) -> Result { - let req = if self.codec.is_plain() { - Cow::Borrowed(&self.request) - } else { - Cow::Owned(self.request.clone().encode_request(&self.codec)) + let req = match self.codec.version() { + kvrpcpb::ApiVersion::V2 => { + let mut req = self.request.clone(); + req.mut_context().set_api_version(self.codec.version()); + Cow::Owned(req.encode_request(&self.codec)) + } + _ => Cow::Borrowed(&self.request), }; let stats = tikv_stats(self.request.label()); @@ -75,10 +78,9 @@ impl> Plan for Dispatch { .downcast() .expect("Downcast failed: request and response type mismatch"); - if self.codec.is_plain() { - Ok(resp) - } else { - req.decode_response(&self.codec, resp) + match self.codec.version() { + kvrpcpb::ApiVersion::V2 => req.decode_response(&self.codec, resp), + _ => Ok(resp), } }) } diff --git a/tikv-client-store/src/request.rs b/tikv-client-store/src/request.rs index 290f142a..7c14e2e9 100644 --- a/tikv-client-store/src/request.rs +++ b/tikv-client-store/src/request.rs @@ -12,6 +12,7 @@ pub trait Request: Any + Sync + Send + 'static { fn label(&self) -> &'static str; fn as_any(&self) -> &dyn Any; fn set_context(&mut self, context: kvrpcpb::Context); + fn mut_context(&mut self) -> &mut kvrpcpb::Context; } macro_rules! impl_request { @@ -41,6 +42,10 @@ macro_rules! impl_request { fn set_context(&mut self, context: kvrpcpb::Context) { kvrpcpb::$name::set_context(self, context) } + + fn mut_context(&mut self) -> &mut kvrpcpb::Context { + kvrpcpb::$name::mut_context(self) + } } }; } From 81cbddd70b2a3997fce5e397a7d8956079eabe75 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 8 Jul 2022 16:08:34 +0800 Subject: [PATCH 27/43] move request codec into raw/txn owned module Signed-off-by: iosmanthus --- examples/pessimistic.rs | 11 +-- examples/raw.rs | 5 +- examples/transaction.rs | 6 +- src/mock.rs | 10 +-- src/raw/client.rs | 4 +- src/raw/codec.rs | 27 +++++++ src/raw/mod.rs | 6 +- src/region_cache.rs | 11 +-- src/request/codec.rs | 139 +++++++++---------------------------- src/transaction/codec.rs | 38 ++++++++++ src/transaction/mod.rs | 2 + tests/common/mod.rs | 9 +-- tests/failpoint_tests.rs | 6 +- tests/integration_tests.rs | 78 ++++++++++++++------- tests/mock_tikv_tests.rs | 4 +- 15 files changed, 190 insertions(+), 166 deletions(-) create mode 100644 src/raw/codec.rs create mode 100644 src/transaction/codec.rs diff --git a/examples/pessimistic.rs b/examples/pessimistic.rs index 2822bc0f..fd91eb4c 100644 --- a/examples/pessimistic.rs +++ b/examples/pessimistic.rs @@ -1,12 +1,13 @@ // Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0. -mod common; - -use crate::common::parse_args; use tikv_client::{ - request::codec::TxnApiV1, Config, Key, TransactionClient as Client, TransactionOptions, Value, + transaction::ApiV1, Config, Key, TransactionClient as Client, TransactionOptions, Value, }; +use crate::common::parse_args; + +mod common; + #[tokio::main] async fn main() { // You can try running this example by passing your pd endpoints @@ -22,7 +23,7 @@ async fn main() { }; // init - let client = Client::new_with_config(args.pd, config, TxnApiV1, None) + let client = Client::new_with_config(args.pd, config, ApiV1, None) .await .expect("Could not connect to tikv"); diff --git a/examples/raw.rs b/examples/raw.rs index 7194bdf8..fb69a9d6 100644 --- a/examples/raw.rs +++ b/examples/raw.rs @@ -6,8 +6,7 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::codec::RawApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, Result, - Value, + raw::ApiV1, Config, IntoOwnedRange, Key, KvPair, RawClient as Client, Result, Value, }; const KEY: &str = "TiKV"; @@ -29,7 +28,7 @@ async fn main() -> Result<()> { // When we first create a client we receive a `Connect` structure which must be resolved before // the client is actually connected and usable. - let client = Client::new_with_config(args.pd, config, RawApiV1, None).await?; + let client = Client::new_with_config(args.pd, config, ApiV1, None).await?; // Requests are created from the connected client. These calls return structures which // implement `Future`. This means the `Future` must be resolved before the action ever takes diff --git a/examples/transaction.rs b/examples/transaction.rs index a960faaf..a364ce65 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -4,8 +4,8 @@ mod common; use crate::common::parse_args; use tikv_client::{ - request::codec::{TxnApiV1, TxnCodec}, - BoundRange, Config, Key, KvPair, TransactionClient as Client, Value, + request::codec::TxnCodec, transaction::ApiV1, BoundRange, Config, Key, KvPair, + TransactionClient as Client, Value, }; async fn puts(client: &Client, pairs: impl IntoIterator>) { @@ -84,7 +84,7 @@ async fn main() { Config::default() }; - let txn = Client::new_with_config(args.pd, config, TxnApiV1, None) + let txn = Client::new_with_config(args.pd, config, ApiV1, None) .await .expect("Could not connect to tikv"); diff --git a/src/mock.rs b/src/mock.rs index 8cc9c963..910afc43 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -7,8 +7,8 @@ use crate::{ pd::{PdClient, PdRpcClient, RetryClient}, + raw::ApiV1, region::{RegionId, RegionWithLeader}, - request::codec::RawApiV1, store::RegionStore, Config, Error, Key, Result, Timestamp, }; @@ -21,7 +21,7 @@ use tikv_client_store::{KvClient, KvConnect, Request}; /// Create a `PdRpcClient` with it's internals replaced with mocks so that the /// client can be tested without doing any RPC calls. -pub async fn pd_rpc_client() -> PdRpcClient { +pub async fn pd_rpc_client() -> PdRpcClient { let config = Config::default(); let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); let logger = Logger::root( @@ -42,7 +42,7 @@ pub async fn pd_rpc_client() -> PdRpcClient, region: RegionWithLeader) -> Result { Ok(RegionStore::new(region, Arc::new(self.client.clone()))) @@ -201,6 +201,6 @@ impl PdClient for MockPdClient { async fn invalidate_region_cache(&self, _ver_id: crate::region::RegionVerId) {} fn get_request_codec(&self) -> Self::RequestCodec { - RawApiV1 + ApiV1 } } diff --git a/src/raw/client.rs b/src/raw/client.rs index 9fed7fc4..9be4cc7f 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -792,7 +792,7 @@ mod tests { use crate::{ mock::{MockKvClient, MockPdClient}, - request::codec::RawApiV1, + raw::ApiV1, Result, }; @@ -828,7 +828,7 @@ mod tests { cf: Some(ColumnFamily::Default), atomic: false, logger, - _phantom: PhantomData::, + _phantom: PhantomData::, }; let resps = client .coprocessor( diff --git a/src/raw/codec.rs b/src/raw/codec.rs new file mode 100644 index 00000000..c3beb53c --- /dev/null +++ b/src/raw/codec.rs @@ -0,0 +1,27 @@ +use tikv_client_proto::{kvrpcpb, metapb::Region}; + +use crate::{ + impl_request_codec_for_new_type, + request::codec::{KeyMode, KeySpaceCodec, KeySpaceId, RawCodec, RequestCodec, TxnCodec}, + Result, +}; + +#[derive(Clone)] +pub struct ApiV1; + +impl RequestCodec for ApiV1 {} + +impl RawCodec for ApiV1 {} + +#[derive(Clone)] +pub struct Keyspace(KeySpaceCodec); + +impl Keyspace { + pub fn new(id: KeySpaceId) -> Self { + Keyspace(KeySpaceCodec::new(KeyMode::Raw, id)) + } +} + +impl_request_codec_for_new_type!(Keyspace); + +impl TxnCodec for Keyspace {} diff --git a/src/raw/mod.rs b/src/raw/mod.rs index 823e0e21..ccfd239a 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -9,11 +9,15 @@ //! //! **Warning:** It is not advisable to use both raw and transactional functionality in the same keyspace. -pub use self::client::Client; +pub use self::{ + client::Client, + codec::{ApiV1, Keyspace}, +}; use crate::Error; use std::{convert::TryFrom, fmt}; mod client; +mod codec; pub mod lowering; mod requests; diff --git a/src/region_cache.rs b/src/region_cache.rs index 88c3b11d..94cef04d 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -262,8 +262,9 @@ mod test { use crate::{ pd::RetryClientTrait, + raw::ApiV1, region::{RegionId, RegionWithLeader}, - request::codec::{RawApiV1, RequestCodec}, + request::codec::RequestCodec, Key, Result, }; @@ -330,7 +331,7 @@ mod test { #[tokio::test] async fn cache_is_used() -> Result<()> { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(RawApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1, retry_client.clone()); retry_client.regions.lock().await.insert( 1, RegionWithLeader { @@ -400,7 +401,7 @@ mod test { #[tokio::test] async fn test_add_disjoint_regions() { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(RawApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1, retry_client.clone()); let region1 = region(1, vec![], vec![10]); let region2 = region(2, vec![10], vec![20]); let region3 = region(3, vec![30], vec![]); @@ -419,7 +420,7 @@ mod test { #[tokio::test] async fn test_add_intersecting_regions() { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(RawApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1, retry_client.clone()); cache.add_region(region(1, vec![], vec![10])).await; cache.add_region(region(2, vec![10], vec![20])).await; @@ -457,7 +458,7 @@ mod test { #[tokio::test] async fn test_get_region_by_key() -> Result<()> { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(RawApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1, retry_client.clone()); let region1 = region(1, vec![], vec![10]); let region2 = region(2, vec![10], vec![20]); diff --git a/src/request/codec.rs b/src/request/codec.rs index 0704ad34..62e1ae98 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,6 +1,8 @@ use core::intrinsics::copy; use std::ops::{Deref, DerefMut}; +use derive_new::new; + use tikv_client_common::Error; use tikv_client_proto::{errorpb, kvrpcpb, metapb::Region}; @@ -185,36 +187,12 @@ pub trait RequestCodecExt: RequestCodec { impl RequestCodecExt for T {} -#[derive(Clone)] -pub struct TxnApiV1; - -#[derive(Clone)] -pub struct RawApiV1; - pub trait RawCodec: RequestCodec {} pub trait TxnCodec: RequestCodec {} -impl RequestCodec for RawApiV1 {} - -impl RequestCodec for TxnApiV1 { - fn encode_pd_query(&self, key: Vec) -> Vec { - Key::from(key).to_encoded().into() - } - - fn decode_region(&self, region: &mut Region) -> Result<()> { - decode_bytes_in_place(region.mut_start_key(), false)?; - decode_bytes_in_place(region.mut_end_key(), false)?; - Ok(()) - } -} - -impl RawCodec for RawApiV1 {} - -impl TxnCodec for TxnApiV1 {} - #[derive(Copy, Clone)] -enum KeyMode { +pub(crate) enum KeyMode { Raw, Txn, } @@ -263,8 +241,8 @@ impl DerefMut for KeySpaceId { } } -#[derive(Copy, Clone)] -struct KeySpaceCodec { +#[derive(new, Copy, Clone)] +pub(crate) struct KeySpaceCodec { mode: KeyMode, id: KeySpaceId, } @@ -346,82 +324,33 @@ impl RequestCodec for KeySpaceCodec { } } -#[derive(Clone)] -pub struct RawKeyspaceCodec(KeySpaceCodec); - -impl RawKeyspaceCodec { - pub fn new(id: KeySpaceId) -> Self { - RawKeyspaceCodec(KeySpaceCodec { - mode: KeyMode::Raw, - id, - }) - } -} - -impl RequestCodec for RawKeyspaceCodec { - fn encode_key(&self, key: Vec) -> Vec { - self.0.encode_key(key) - } - - fn decode_key(&self, key: &mut Vec) -> Result<()> { - self.0.decode_key(key) - } - - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { - self.0.encode_range(start, end) - } - - fn encode_pd_query(&self, key: Vec) -> Vec { - self.0.encode_pd_query(key) - } - - fn decode_region(&self, region: &mut Region) -> Result<()> { - self.0.decode_region(region) - } - - fn version(&self) -> kvrpcpb::ApiVersion { - self.0.version() - } -} - -impl RawCodec for RawKeyspaceCodec {} - -#[derive(Clone)] -pub struct TxnKeyspaceCodec(KeySpaceCodec); - -impl TxnKeyspaceCodec { - pub fn new(id: KeySpaceId) -> Self { - TxnKeyspaceCodec(KeySpaceCodec { - mode: KeyMode::Txn, - id, - }) - } -} - -impl RequestCodec for TxnKeyspaceCodec { - fn encode_key(&self, key: Vec) -> Vec { - self.0.encode_key(key) - } - - fn decode_key(&self, key: &mut Vec) -> Result<()> { - self.0.decode_key(key) - } - - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { - self.0.encode_range(start, end) - } - - fn encode_pd_query(&self, key: Vec) -> Vec { - self.0.encode_pd_query(key) - } - - fn decode_region(&self, region: &mut Region) -> Result<()> { - self.0.decode_region(region) - } - - fn version(&self) -> kvrpcpb::ApiVersion { - self.0.version() - } +#[macro_export] +macro_rules! impl_request_codec_for_new_type { + ($t:ty) => { + impl RequestCodec for $t { + fn encode_key(&self, key: Vec) -> Vec { + self.0.encode_key(key) + } + + fn decode_key(&self, key: &mut Vec) -> Result<()> { + self.0.decode_key(key) + } + + fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + self.0.encode_range(start, end) + } + + fn encode_pd_query(&self, key: Vec) -> Vec { + self.0.encode_pd_query(key) + } + + fn decode_region(&self, region: &mut Region) -> Result<()> { + self.0.decode_region(region) + } + + fn version(&self) -> kvrpcpb::ApiVersion { + self.0.version() + } + } + }; } - -impl TxnCodec for TxnKeyspaceCodec {} diff --git a/src/transaction/codec.rs b/src/transaction/codec.rs new file mode 100644 index 00000000..1c4a7f7a --- /dev/null +++ b/src/transaction/codec.rs @@ -0,0 +1,38 @@ +use tikv_client_proto::{kvrpcpb, metapb::Region}; + +use crate::{ + impl_request_codec_for_new_type, + kv::codec::decode_bytes_in_place, + request::codec::{KeyMode, KeySpaceCodec, KeySpaceId, RequestCodec, TxnCodec}, + Key, Result, +}; + +#[derive(Clone)] +pub struct ApiV1; + +impl RequestCodec for ApiV1 { + fn encode_pd_query(&self, key: Vec) -> Vec { + Key::from(key).to_encoded().into() + } + + fn decode_region(&self, region: &mut Region) -> Result<()> { + decode_bytes_in_place(region.mut_start_key(), false)?; + decode_bytes_in_place(region.mut_end_key(), false)?; + Ok(()) + } +} + +impl TxnCodec for ApiV1 {} + +#[derive(Clone)] +pub struct Keyspace(KeySpaceCodec); + +impl Keyspace { + pub fn new(id: KeySpaceId) -> Self { + Keyspace(KeySpaceCodec::new(KeyMode::Txn, id)) + } +} + +impl_request_codec_for_new_type!(Keyspace); + +impl TxnCodec for Keyspace {} diff --git a/src/transaction/mod.rs b/src/transaction/mod.rs index 2fee1aee..9a0c595d 100644 --- a/src/transaction/mod.rs +++ b/src/transaction/mod.rs @@ -9,6 +9,7 @@ //! **Warning:** It is not advisable to use both raw and transactional functionality in the same keyspace. pub use client::Client; +pub use codec::{ApiV1, Keyspace}; pub(crate) use lock::{resolve_locks, HasLocks}; pub use snapshot::Snapshot; #[doc(hidden)] @@ -20,6 +21,7 @@ mod client; pub mod lowering; #[macro_use] mod requests; +mod codec; mod lock; mod snapshot; #[allow(clippy::module_inception)] diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 1310d4ee..4fe7b29b 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -3,10 +3,7 @@ mod ctl; use futures_timer::Delay; use log::{info, warn}; use std::{env, time::Duration}; -use tikv_client::{ - request::codec::{RawApiV1, TxnApiV1}, - ColumnFamily, Key, RawClient, Result, TransactionClient, -}; +use tikv_client::{raw, transaction, ColumnFamily, Key, RawClient, Result, TransactionClient}; const ENV_PD_ADDRS: &str = "PD_ADDRS"; const ENV_ENABLE_MULIT_REGION: &str = "MULTI_REGION"; @@ -22,7 +19,7 @@ pub async fn clear_tikv() { // DEFAULT_REGION_BACKOFF is not long enough for CI environment. So set a longer backoff. let backoff = tikv_client::Backoff::no_jitter_backoff(100, 10000, 10); for cf in cfs { - let raw_client = RawClient::new(pd_addrs(), RawApiV1, None) + let raw_client = RawClient::new(pd_addrs(), raw::ApiV1, None) .await .unwrap() .with_cf(cf); @@ -66,7 +63,7 @@ async fn ensure_region_split( // 1. write plenty transactional keys // 2. wait until regions split - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let mut txn = client.begin_optimistic().await?; for key in keys.into_iter() { txn.put(key.into(), vec![0, 0, 0, 0]).await?; diff --git a/tests/failpoint_tests.rs b/tests/failpoint_tests.rs index bcb2161f..fcd9770f 100644 --- a/tests/failpoint_tests.rs +++ b/tests/failpoint_tests.rs @@ -6,8 +6,8 @@ use fail::FailScenario; use serial_test::serial; use std::time::Duration; use tikv_client::{ - request::codec::TxnApiV1, transaction::HeartbeatOption, Result, TransactionClient, - TransactionOptions, + transaction::{ApiV1, HeartbeatOption}, + Result, TransactionClient, TransactionOptions, }; #[tokio::test] @@ -19,7 +19,7 @@ async fn txn_optimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), ApiV1, None).await?; let mut heartbeat_txn = client .begin_with_options( diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index d1aab796..a8f69b12 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -22,8 +22,9 @@ use std::{ iter, }; use tikv_client::{ - request::codec::{RawApiV1, RawCodec, TxnApiV1}, - transaction::HeartbeatOption, + raw, + request::codec::RawCodec, + transaction::{self, HeartbeatOption}, Error, Key, KvPair, PdClient, RawClient, Result, Transaction, TransactionClient, TransactionOptions, Value, }; @@ -36,7 +37,7 @@ const NUM_TRNASFER: u32 = 100; #[serial] async fn txn_get_timestamp() -> Result<()> { const COUNT: usize = 1 << 8; // use a small number to make test fast - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let mut versions = future::join_all((0..COUNT).map(|_| client.current_timestamp())) .await @@ -57,7 +58,7 @@ async fn txn_get_timestamp() -> Result<()> { async fn txn_crud() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let mut txn = client.begin_optimistic().await?; // Get non-existent keys @@ -141,7 +142,7 @@ async fn txn_crud() -> Result<()> { async fn txn_insert_duplicate_keys() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; // Initialize TiKV store with {foo => bar} let mut txn = client.begin_optimistic().await?; txn.put("foo".to_owned(), "bar".to_owned()).await?; @@ -165,7 +166,7 @@ async fn txn_insert_duplicate_keys() -> Result<()> { async fn txn_pessimistic() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let mut txn = client.begin_pessimistic().await?; txn.put("foo".to_owned(), "foo".to_owned()).await.unwrap(); @@ -182,7 +183,7 @@ async fn txn_pessimistic() -> Result<()> { #[serial] async fn raw_bank_transfer() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; let mut rng = thread_rng(); let people = gen_u32_keys(NUM_PEOPLE, &mut rng); @@ -234,7 +235,7 @@ async fn txn_read() -> Result<()> { let value = "large_value".repeat(10); init().await?; - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -326,7 +327,7 @@ async fn txn_read() -> Result<()> { #[serial] async fn txn_bank_transfer() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let mut rng = thread_rng(); let options = TransactionOptions::new_optimistic() .use_async_commit() @@ -379,7 +380,7 @@ async fn txn_bank_transfer() -> Result<()> { #[serial] async fn raw_req() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; // empty; get non-existent key let res = client.get("k1".to_owned()).await; @@ -509,7 +510,7 @@ async fn raw_req() -> Result<()> { #[serial] async fn txn_update_safepoint() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let res = client.gc(client.current_timestamp().await?).await?; assert!(res); Ok(()) @@ -524,7 +525,7 @@ async fn raw_write_million() -> Result<()> { let interval = 2u32.pow(32 - NUM_BITS_TXN - NUM_BITS_KEY_PER_TXN); init().await?; - let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -570,8 +571,13 @@ async fn raw_write_million() -> Result<()> { #[serial] async fn txn_pessimistic_rollback() -> Result<()> { init().await?; - let client = - TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; + let client = TransactionClient::new_with_config( + pd_addrs(), + Default::default(), + transaction::ApiV1, + None, + ) + .await?; let mut preload_txn = client.begin_optimistic().await?; let key1 = vec![1]; let key2 = vec![2]; @@ -606,7 +612,7 @@ async fn txn_pessimistic_delete() -> Result<()> { let client = TransactionClient::new_with_config( vec!["127.0.0.1:2379"], Default::default(), - TxnApiV1, + transaction::ApiV1, None, ) .await?; @@ -651,8 +657,13 @@ async fn txn_pessimistic_delete() -> Result<()> { #[serial] async fn txn_lock_keys() -> Result<()> { init().await?; - let client = - TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; + let client = TransactionClient::new_with_config( + pd_addrs(), + Default::default(), + transaction::ApiV1, + None, + ) + .await?; let k1 = b"key1".to_vec(); let k2 = b"key2".to_vec(); @@ -686,8 +697,13 @@ async fn txn_lock_keys() -> Result<()> { #[serial] async fn txn_lock_keys_error_handle() -> Result<()> { init().await?; - let client = - TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; + let client = TransactionClient::new_with_config( + pd_addrs(), + Default::default(), + transaction::ApiV1, + None, + ) + .await?; // Keys in `k` should locate in different regions. See `init()` for boundary of regions. let k: Vec = vec![ @@ -724,8 +740,13 @@ async fn txn_lock_keys_error_handle() -> Result<()> { #[serial] async fn txn_get_for_update() -> Result<()> { init().await?; - let client = - TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; + let client = TransactionClient::new_with_config( + pd_addrs(), + Default::default(), + transaction::ApiV1, + None, + ) + .await?; let key1 = "key".to_owned(); let key2 = "another key".to_owned(); let value1 = b"some value".to_owned(); @@ -772,7 +793,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), TxnApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; let mut heartbeat_txn = client .begin_with_options(TransactionOptions::new_pessimistic()) @@ -812,7 +833,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { #[serial] async fn raw_cas() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), RawApiV1, None) + let client = RawClient::new(pd_addrs(), raw::ApiV1, None) .await? .with_atomic_for_cas(); let key = "key".to_owned(); @@ -857,7 +878,7 @@ async fn raw_cas() -> Result<()> { client.batch_delete(vec![key.clone()]).await.err().unwrap(), Error::UnsupportedMode )); - let client = RawClient::new(pd_addrs(), RawApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; assert!(matches!( client .compare_and_swap(key.clone(), None, vec![]) @@ -874,8 +895,13 @@ async fn raw_cas() -> Result<()> { #[serial] async fn txn_scan() -> Result<()> { init().await?; - let client = - TransactionClient::new_with_config(pd_addrs(), Default::default(), TxnApiV1, None).await?; + let client = TransactionClient::new_with_config( + pd_addrs(), + Default::default(), + transaction::ApiV1, + None, + ) + .await?; let k1 = b"a".to_vec(); let v = b"b".to_vec(); diff --git a/tests/mock_tikv_tests.rs b/tests/mock_tikv_tests.rs index 5e0a76c1..60164de0 100644 --- a/tests/mock_tikv_tests.rs +++ b/tests/mock_tikv_tests.rs @@ -4,7 +4,7 @@ mod test { use log::debug; use mock_tikv::{start_mock_pd_server, start_mock_tikv_server, MOCK_PD_PORT}; use simple_logger::SimpleLogger; - use tikv_client::{request::codec::RawApiV1, KvPair, RawClient}; + use tikv_client::{raw::ApiV1, KvPair, RawClient}; #[tokio::test] #[ignore] @@ -15,7 +15,7 @@ mod test { let mut tikv_server = start_mock_tikv_server(); let _pd_server = start_mock_pd_server(); - let client = RawClient::new(vec![format!("localhost:{}", MOCK_PD_PORT)], RawApiV1, None) + let client = RawClient::new(vec![format!("localhost:{}", MOCK_PD_PORT)], ApiV1, None) .await .unwrap(); From 5bd0f6e2e14c4048397f48adb93dff8f63e24d62 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 8 Jul 2022 16:42:32 +0800 Subject: [PATCH 28/43] fix doc test Signed-off-by: iosmanthus --- src/lib.rs | 8 ++--- src/raw/client.rs | 56 +++++++++++++++++----------------- src/transaction/client.rs | 24 +++++++-------- src/transaction/transaction.rs | 56 +++++++++++++++++----------------- 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e0fb9b40..d7886e73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,9 +66,9 @@ //! # use tikv_client::{RawClient, Result}; //! # use futures::prelude::*; //! # fn main() -> Result<()> { -//! # use tikv_client::request::codec::RawApiV1; +//! # use tikv_client::raw::ApiV1; //! futures::executor::block_on(async { -//! let client = RawClient::new(vec!["127.0.0.1:2379"], RawApiV1, None).await?; +//! let client = RawClient::new(vec!["127.0.0.1:2379"], ApiV1, None).await?; //! client.put("key".to_owned(), "value".to_owned()).await?; //! let value = client.get("key".to_owned()).await?; //! # Ok(()) @@ -81,9 +81,9 @@ //! # use tikv_client::{TransactionClient, Result}; //! # use futures::prelude::*; //! # fn main() -> Result<()> { -//! # use tikv_client::request::codec::TxnApiV1; +//! # use tikv_client::transaction::ApiV1; //! futures::executor::block_on(async { -//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], TxnApiV1, None).await?; +//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], ApiV1, None).await?; //! let mut txn = txn_client.begin_optimistic().await?; //! txn.put("key".to_owned(), "value".to_owned()).await?; //! let value = txn.get("key".to_owned()).await?; diff --git a/src/raw/client.rs b/src/raw/client.rs index 9be4cc7f..222806d1 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -62,9 +62,9 @@ impl Client { /// ```rust,no_run /// # use tikv_client::RawClient; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None) + /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// # }); @@ -89,12 +89,12 @@ impl Client { /// # use tikv_client::{Config, RawClient}; /// # use futures::prelude::*; /// # use std::time::Duration; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { /// let client = RawClient::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), - /// RawApiV1, + /// ApiV1, /// None, /// ) /// .await @@ -145,9 +145,9 @@ impl Client { /// # use tikv_client::{Config, RawClient, ColumnFamily}; /// # use futures::prelude::*; /// # use std::convert::TryInto; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None) + /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap() /// .with_cf(ColumnFamily::Write); @@ -201,9 +201,9 @@ where /// ```rust,no_run /// # use tikv_client::{Value, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.get(key); /// let result: Option = req.await.unwrap(); @@ -236,9 +236,9 @@ where /// ```rust,no_run /// # use tikv_client::{KvPair, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_get(keys); /// let result: Vec = req.await.unwrap(); @@ -276,9 +276,9 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let val = "TiKV".to_owned(); /// let req = client.put(key, val); @@ -315,9 +315,9 @@ where /// ```rust,no_run /// # use tikv_client::{Result, KvPair, Key, Value, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let kvpair1 = ("PD".to_owned(), "Go".to_owned()); /// let kvpair2 = ("TiKV".to_owned(), "Rust".to_owned()); /// let iterable = vec![kvpair1, kvpair2]; @@ -362,9 +362,9 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.delete(key); /// let result: () = req.await.unwrap(); @@ -397,9 +397,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, RawClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_delete(keys); /// let result: () = req.await.unwrap(); @@ -435,9 +435,9 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.delete_range(inclusive_range.into_owned()); /// let result: () = req.await.unwrap(); @@ -476,9 +476,9 @@ where /// ```rust,no_run /// # use tikv_client::{KvPair, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -511,9 +511,9 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan_keys(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -554,9 +554,9 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; @@ -599,9 +599,9 @@ where /// ```rust,no_run /// # use tikv_client::{Key, Config, RawClient, IntoOwnedRange}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::RawApiV1; + /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], RawApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; diff --git a/src/transaction/client.rs b/src/transaction/client.rs index b7f79cac..665f045c 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -68,9 +68,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// # }); @@ -96,12 +96,12 @@ where /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::time::Duration; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { /// let client = TransactionClient::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), - /// TxnApiV1, + /// ApiV1, /// None, /// ) /// .await @@ -148,9 +148,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// let mut transaction = client.begin_optimistic().await.unwrap(); @@ -174,9 +174,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// let mut transaction = client.begin_pessimistic().await.unwrap(); @@ -197,9 +197,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient, TransactionOptions}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// let mut transaction = client @@ -237,9 +237,9 @@ where /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// let timestamp = client.current_timestamp().await.unwrap(); diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 9391b380..2a557aed 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -51,9 +51,9 @@ use crate::{ /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; -/// use tikv_client::request::codec::TxnApiV1; +/// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { -/// let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None) +/// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) /// .await /// .unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -108,9 +108,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Option = txn.get(key).await.unwrap(); @@ -170,9 +170,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Value = txn.get_for_update(key).await.unwrap().unwrap(); @@ -205,9 +205,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let exists = txn.key_exists("k1".to_owned()).await.unwrap(); /// txn.commit().await.unwrap(); @@ -233,9 +233,9 @@ impl Transaction { /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let result: HashMap = txn @@ -287,9 +287,9 @@ impl Transaction { /// # use tikv_client::{Key, Value, Config, TransactionClient, KvPair}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let keys = vec!["foo".to_owned(), "bar".to_owned()]; /// let result: Vec = txn @@ -333,9 +333,9 @@ impl Transaction { /// # use tikv_client::{Key, KvPair, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -370,9 +370,9 @@ impl Transaction { /// # use tikv_client::{Key, KvPair, Value, Config, TransactionClient}; /// # use futures::prelude::*; /// # use std::collections::HashMap; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -412,9 +412,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -444,9 +444,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Value, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -481,9 +481,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Key, Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// txn.delete(key); @@ -517,9 +517,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// txn.lock_keys(vec!["TiKV".to_owned(), "Rust".to_owned()]); /// // ... Do some actions. @@ -554,9 +554,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, Timestamp, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// let result: Timestamp = txn.commit().await.unwrap().unwrap(); @@ -613,9 +613,9 @@ impl Transaction { /// ```rust,no_run /// # use tikv_client::{Config, Timestamp, TransactionClient}; /// # use futures::prelude::*; - /// use tikv_client::request::codec::TxnApiV1; + /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], TxnApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// txn.rollback().await.unwrap(); From 1c1ce179bf1ff65fab3d9def50c19c76f849be3a Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Sat, 9 Jul 2022 13:56:27 +0800 Subject: [PATCH 29/43] fix wrong TxnCodec mark trait for raw::Keyspace Signed-off-by: iosmanthus --- src/raw/codec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raw/codec.rs b/src/raw/codec.rs index c3beb53c..1130ac4d 100644 --- a/src/raw/codec.rs +++ b/src/raw/codec.rs @@ -24,4 +24,4 @@ impl Keyspace { impl_request_codec_for_new_type!(Keyspace); -impl TxnCodec for Keyspace {} +impl RawCodec for Keyspace {} From 051a15716ae47a3a4aa231c7f0d685562f559c98 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Mon, 11 Jul 2022 17:54:36 +0800 Subject: [PATCH 30/43] refactor ApiVx with Mode generic para Signed-off-by: iosmanthus --- examples/pessimistic.rs | 2 +- examples/raw.rs | 2 +- examples/transaction.rs | 2 +- src/lib.rs | 4 +- src/mock.rs | 4 +- src/raw/client.rs | 28 +++--- src/raw/codec.rs | 29 +----- src/raw/mod.rs | 2 +- src/region_cache.rs | 8 +- src/request/codec.rs | 169 +++++++++++++++------------------ src/transaction/client.rs | 12 +-- src/transaction/codec.rs | 40 +------- src/transaction/mod.rs | 2 +- src/transaction/transaction.rs | 28 +++--- tests/common/mod.rs | 4 +- tests/failpoint_tests.rs | 2 +- tests/integration_tests.rs | 38 ++++---- tests/mock_tikv_tests.rs | 10 +- 18 files changed, 160 insertions(+), 226 deletions(-) diff --git a/examples/pessimistic.rs b/examples/pessimistic.rs index fd91eb4c..15a69dea 100644 --- a/examples/pessimistic.rs +++ b/examples/pessimistic.rs @@ -23,7 +23,7 @@ async fn main() { }; // init - let client = Client::new_with_config(args.pd, config, ApiV1, None) + let client = Client::new_with_config(args.pd, config, ApiV1::default(), None) .await .expect("Could not connect to tikv"); diff --git a/examples/raw.rs b/examples/raw.rs index fb69a9d6..673aa45c 100644 --- a/examples/raw.rs +++ b/examples/raw.rs @@ -28,7 +28,7 @@ async fn main() -> Result<()> { // When we first create a client we receive a `Connect` structure which must be resolved before // the client is actually connected and usable. - let client = Client::new_with_config(args.pd, config, ApiV1, None).await?; + let client = Client::new_with_config(args.pd, config, ApiV1::default(), None).await?; // Requests are created from the connected client. These calls return structures which // implement `Future`. This means the `Future` must be resolved before the action ever takes diff --git a/examples/transaction.rs b/examples/transaction.rs index a364ce65..4b040ca0 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -84,7 +84,7 @@ async fn main() { Config::default() }; - let txn = Client::new_with_config(args.pd, config, ApiV1, None) + let txn = Client::new_with_config(args.pd, config, ApiV1::default(), None) .await .expect("Could not connect to tikv"); diff --git a/src/lib.rs b/src/lib.rs index d7886e73..7a1c5b9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,7 +68,7 @@ //! # fn main() -> Result<()> { //! # use tikv_client::raw::ApiV1; //! futures::executor::block_on(async { -//! let client = RawClient::new(vec!["127.0.0.1:2379"], ApiV1, None).await?; +//! let client = RawClient::new(vec!["127.0.0.1:2379"], ApiV1::default(), None).await?; //! client.put("key".to_owned(), "value".to_owned()).await?; //! let value = client.get("key".to_owned()).await?; //! # Ok(()) @@ -83,7 +83,7 @@ //! # fn main() -> Result<()> { //! # use tikv_client::transaction::ApiV1; //! futures::executor::block_on(async { -//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], ApiV1, None).await?; +//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], ApiV1::default(), None).await?; //! let mut txn = txn_client.begin_optimistic().await?; //! txn.put("key".to_owned(), "value".to_owned()).await?; //! let value = txn.get("key".to_owned()).await?; diff --git a/src/mock.rs b/src/mock.rs index 910afc43..d0c8e3cb 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -42,7 +42,7 @@ pub async fn pd_rpc_client() -> PdRpcClient { MockCluster, )) }, - ApiV1, + ApiV1::default(), logger, ) .await @@ -201,6 +201,6 @@ impl PdClient for MockPdClient { async fn invalidate_region_cache(&self, _ver_id: crate::region::RegionVerId) {} fn get_request_codec(&self) -> Self::RequestCodec { - ApiV1 + ApiV1::default() } } diff --git a/src/raw/client.rs b/src/raw/client.rs index 222806d1..a7c4a632 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -64,7 +64,7 @@ impl Client { /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// # }); @@ -94,7 +94,7 @@ impl Client { /// let client = RawClient::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), - /// ApiV1, + /// ApiV1::default(), /// None, /// ) /// .await @@ -147,7 +147,7 @@ impl Client { /// # use std::convert::TryInto; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap() /// .with_cf(ColumnFamily::Write); @@ -203,7 +203,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.get(key); /// let result: Option = req.await.unwrap(); @@ -238,7 +238,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_get(keys); /// let result: Vec = req.await.unwrap(); @@ -278,7 +278,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let val = "TiKV".to_owned(); /// let req = client.put(key, val); @@ -317,7 +317,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let kvpair1 = ("PD".to_owned(), "Go".to_owned()); /// let kvpair2 = ("TiKV".to_owned(), "Rust".to_owned()); /// let iterable = vec![kvpair1, kvpair2]; @@ -364,7 +364,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.delete(key); /// let result: () = req.await.unwrap(); @@ -399,7 +399,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_delete(keys); /// let result: () = req.await.unwrap(); @@ -437,7 +437,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.delete_range(inclusive_range.into_owned()); /// let result: () = req.await.unwrap(); @@ -478,7 +478,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -513,7 +513,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan_keys(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -556,7 +556,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; @@ -601,7 +601,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; diff --git a/src/raw/codec.rs b/src/raw/codec.rs index 1130ac4d..cc530ee2 100644 --- a/src/raw/codec.rs +++ b/src/raw/codec.rs @@ -1,27 +1,4 @@ -use tikv_client_proto::{kvrpcpb, metapb::Region}; +use crate::request::codec::{self, RawMode}; -use crate::{ - impl_request_codec_for_new_type, - request::codec::{KeyMode, KeySpaceCodec, KeySpaceId, RawCodec, RequestCodec, TxnCodec}, - Result, -}; - -#[derive(Clone)] -pub struct ApiV1; - -impl RequestCodec for ApiV1 {} - -impl RawCodec for ApiV1 {} - -#[derive(Clone)] -pub struct Keyspace(KeySpaceCodec); - -impl Keyspace { - pub fn new(id: KeySpaceId) -> Self { - Keyspace(KeySpaceCodec::new(KeyMode::Raw, id)) - } -} - -impl_request_codec_for_new_type!(Keyspace); - -impl RawCodec for Keyspace {} +pub type ApiV1 = codec::ApiV1; +pub type ApiV2 = codec::ApiV2; diff --git a/src/raw/mod.rs b/src/raw/mod.rs index ccfd239a..4166d5c9 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -11,7 +11,7 @@ pub use self::{ client::Client, - codec::{ApiV1, Keyspace}, + codec::{ApiV1, ApiV2}, }; use crate::Error; use std::{convert::TryFrom, fmt}; diff --git a/src/region_cache.rs b/src/region_cache.rs index 94cef04d..7028d5d2 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -331,7 +331,7 @@ mod test { #[tokio::test] async fn cache_is_used() -> Result<()> { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(ApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1::default(), retry_client.clone()); retry_client.regions.lock().await.insert( 1, RegionWithLeader { @@ -401,7 +401,7 @@ mod test { #[tokio::test] async fn test_add_disjoint_regions() { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(ApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1::default(), retry_client.clone()); let region1 = region(1, vec![], vec![10]); let region2 = region(2, vec![10], vec![20]); let region3 = region(3, vec![30], vec![]); @@ -420,7 +420,7 @@ mod test { #[tokio::test] async fn test_add_intersecting_regions() { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(ApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1::default(), retry_client.clone()); cache.add_region(region(1, vec![], vec![10])).await; cache.add_region(region(2, vec![10], vec![20])).await; @@ -458,7 +458,7 @@ mod test { #[tokio::test] async fn test_get_region_by_key() -> Result<()> { let retry_client = Arc::new(MockRetryClient::default()); - let cache = RegionCache::new(ApiV1, retry_client.clone()); + let cache = RegionCache::new(ApiV1::default(), retry_client.clone()); let region1 = region(1, vec![], vec![10]); let region2 = region(2, vec![10], vec![20]); diff --git a/src/request/codec.rs b/src/request/codec.rs index 62e1ae98..f3adcb1c 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,24 +1,18 @@ use core::intrinsics::copy; -use std::ops::{Deref, DerefMut}; - -use derive_new::new; +use std::{ + marker::PhantomData, + ops::{Deref, DerefMut}, +}; use tikv_client_common::Error; use tikv_client_proto::{errorpb, kvrpcpb, metapb::Region}; use crate::{kv::codec::decode_bytes_in_place, Key, Result}; -const RAW_MODE_PREFIX: u8 = b'r'; -const TXN_MODE_PREFIX: u8 = b'x'; +type Prefix = [u8; KEYSPACE_PREFIX_LEN]; const KEYSPACE_PREFIX_LEN: usize = 4; -const RAW_MODE_MIN_KEY: Prefix = [RAW_MODE_PREFIX, 0, 0, 0]; -const RAW_MODE_MAX_KEY: Prefix = [RAW_MODE_PREFIX + 1, 0, 0, 0]; - -const TXN_MODE_MIN_KEY: Prefix = [TXN_MODE_PREFIX, 0, 0, 0]; -const TXN_MODE_MAX_KEY: Prefix = [TXN_MODE_PREFIX + 1, 0, 0, 0]; - const MAX_KEYSPACE_ID: KeySpaceId = KeySpaceId([0xff, 0xff, 0xff]); pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { @@ -191,39 +185,6 @@ pub trait RawCodec: RequestCodec {} pub trait TxnCodec: RequestCodec {} -#[derive(Copy, Clone)] -pub(crate) enum KeyMode { - Raw, - Txn, -} - -impl From for u8 { - fn from(mode: KeyMode) -> u8 { - match mode { - KeyMode::Raw => b'r', - KeyMode::Txn => b'x', - } - } -} - -impl KeyMode { - fn min_key(self) -> Vec { - match self { - KeyMode::Raw => RAW_MODE_MIN_KEY.to_vec(), - KeyMode::Txn => TXN_MODE_MIN_KEY.to_vec(), - } - } - - fn max_key(self) -> Vec { - match self { - KeyMode::Raw => RAW_MODE_MAX_KEY.to_vec(), - KeyMode::Txn => TXN_MODE_MAX_KEY.to_vec(), - } - } -} - -type Prefix = [u8; KEYSPACE_PREFIX_LEN]; - #[derive(Clone, Copy, Default, PartialEq, Eq)] pub struct KeySpaceId([u8; 3]); @@ -241,29 +202,87 @@ impl DerefMut for KeySpaceId { } } -#[derive(new, Copy, Clone)] -pub(crate) struct KeySpaceCodec { - mode: KeyMode, +pub trait Mode: Clone + Copy + Sync + Send + 'static { + const PREFIX: u8; + const MIN_KEY: &'static [u8] = &[Self::PREFIX, 0, 0, 0]; + const MAX_KEY: &'static [u8] = &[Self::PREFIX + 1, 0, 0, 0]; +} + +#[derive(Clone, Copy)] +pub struct RawMode; + +#[derive(Clone, Copy)] +pub struct TxnMode; + +impl Mode for RawMode { + const PREFIX: u8 = b'r'; +} + +impl Mode for TxnMode { + const PREFIX: u8 = b't'; +} + +#[derive(Clone)] +pub struct ApiV1 { + _phantom: PhantomData, +} + +impl Default for ApiV1 { + fn default() -> Self { + ApiV1 { + _phantom: PhantomData, + } + } +} + +impl RequestCodec for ApiV1 {} + +impl RawCodec for ApiV1 {} + +impl RequestCodec for ApiV1 { + fn encode_pd_query(&self, key: Vec) -> Vec { + Key::from(key).to_encoded().into() + } + + fn decode_region(&self, region: &mut Region) -> Result<()> { + decode_bytes_in_place(region.mut_start_key(), false)?; + decode_bytes_in_place(region.mut_end_key(), false)?; + + Ok(()) + } +} + +impl TxnCodec for ApiV1 {} + +#[derive(Clone, Copy, Default)] +pub struct KeySpace { id: KeySpaceId, + _phantom: PhantomData, } -impl From for Prefix { - fn from(codec: KeySpaceCodec) -> Self { - [codec.mode.into(), codec.id[0], codec.id[1], codec.id[2]] +impl From> for Prefix { + fn from(s: KeySpace) -> Self { + [M::PREFIX, s.id[0], s.id[1], s.id[2]] } } -impl RequestCodec for KeySpaceCodec { +#[derive(Default, Clone)] +pub struct ApiV2 { + keyspace: KeySpace, +} + +impl RequestCodec for ApiV2 { fn encode_key(&self, mut key: Vec) -> Vec { let mut encoded = Vec::with_capacity(key.len() + KEYSPACE_PREFIX_LEN); - let prefix: Prefix = (*self).into(); + let prefix: Prefix = self.keyspace.into(); + encoded.extend_from_slice(&prefix); encoded.append(&mut key); encoded } fn decode_key(&self, key: &mut Vec) -> Result<()> { - let prefix: Prefix = (*self).into(); + let prefix: Prefix = self.keyspace.into(); if !key.starts_with(&prefix) { return Err(Error::CorruptedKeyspace { @@ -286,8 +305,8 @@ impl RequestCodec for KeySpaceCodec { } fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { - if self.id == MAX_KEYSPACE_ID { - (self.encode_key(start), self.mode.max_key()) + if self.keyspace.id == MAX_KEYSPACE_ID { + (self.encode_key(start), M::MAX_KEY.to_vec()) } else { (self.encode_key(start), self.encode_key(end)) } @@ -301,16 +320,15 @@ impl RequestCodec for KeySpaceCodec { decode_bytes_in_place(region.mut_start_key(), false)?; decode_bytes_in_place(region.mut_end_key(), false)?; - // Map the region's start key to the keyspace's start key. - if region.get_start_key() < self.mode.min_key().as_slice() { + // Map the region's start key to the keyspace start key. + if region.get_start_key() < M::MIN_KEY { *region.mut_start_key() = vec![]; } else { self.decode_key(region.mut_start_key())?; } - // Map the region's end key to the keyspace's end key. - if region.get_end_key().is_empty() || region.get_end_key() > self.mode.max_key().as_slice() - { + // Map the region's end key to the keyspace end key. + if region.get_end_key().is_empty() || region.get_end_key() > M::MAX_KEY { *region.mut_end_key() = vec![]; } else { self.decode_key(region.mut_end_key())?; @@ -323,34 +341,3 @@ impl RequestCodec for KeySpaceCodec { kvrpcpb::ApiVersion::V2 } } - -#[macro_export] -macro_rules! impl_request_codec_for_new_type { - ($t:ty) => { - impl RequestCodec for $t { - fn encode_key(&self, key: Vec) -> Vec { - self.0.encode_key(key) - } - - fn decode_key(&self, key: &mut Vec) -> Result<()> { - self.0.decode_key(key) - } - - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { - self.0.encode_range(start, end) - } - - fn encode_pd_query(&self, key: Vec) -> Vec { - self.0.encode_pd_query(key) - } - - fn decode_region(&self, region: &mut Region) -> Result<()> { - self.0.decode_region(region) - } - - fn version(&self) -> kvrpcpb::ApiVersion { - self.0.version() - } - } - }; -} diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 665f045c..55f1c3d5 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -70,7 +70,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// # }); @@ -101,7 +101,7 @@ where /// let client = TransactionClient::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), - /// ApiV1, + /// ApiV1::default(), /// None, /// ) /// .await @@ -150,7 +150,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// let mut transaction = client.begin_optimistic().await.unwrap(); @@ -176,7 +176,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// let mut transaction = client.begin_pessimistic().await.unwrap(); @@ -199,7 +199,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// let mut transaction = client @@ -239,7 +239,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) + /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// let timestamp = client.current_timestamp().await.unwrap(); diff --git a/src/transaction/codec.rs b/src/transaction/codec.rs index 1c4a7f7a..ad34acf1 100644 --- a/src/transaction/codec.rs +++ b/src/transaction/codec.rs @@ -1,38 +1,4 @@ -use tikv_client_proto::{kvrpcpb, metapb::Region}; +use crate::request::codec::{self, TxnMode}; -use crate::{ - impl_request_codec_for_new_type, - kv::codec::decode_bytes_in_place, - request::codec::{KeyMode, KeySpaceCodec, KeySpaceId, RequestCodec, TxnCodec}, - Key, Result, -}; - -#[derive(Clone)] -pub struct ApiV1; - -impl RequestCodec for ApiV1 { - fn encode_pd_query(&self, key: Vec) -> Vec { - Key::from(key).to_encoded().into() - } - - fn decode_region(&self, region: &mut Region) -> Result<()> { - decode_bytes_in_place(region.mut_start_key(), false)?; - decode_bytes_in_place(region.mut_end_key(), false)?; - Ok(()) - } -} - -impl TxnCodec for ApiV1 {} - -#[derive(Clone)] -pub struct Keyspace(KeySpaceCodec); - -impl Keyspace { - pub fn new(id: KeySpaceId) -> Self { - Keyspace(KeySpaceCodec::new(KeyMode::Txn, id)) - } -} - -impl_request_codec_for_new_type!(Keyspace); - -impl TxnCodec for Keyspace {} +pub type ApiV1 = codec::ApiV1; +pub type ApiV2 = codec::ApiV2; diff --git a/src/transaction/mod.rs b/src/transaction/mod.rs index 9a0c595d..b8e46c63 100644 --- a/src/transaction/mod.rs +++ b/src/transaction/mod.rs @@ -9,7 +9,7 @@ //! **Warning:** It is not advisable to use both raw and transactional functionality in the same keyspace. pub use client::Client; -pub use codec::{ApiV1, Keyspace}; +pub use codec::{ApiV1, ApiV2}; pub(crate) use lock::{resolve_locks, HasLocks}; pub use snapshot::Snapshot; #[doc(hidden)] diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 2a557aed..d973f14c 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -53,7 +53,7 @@ use crate::{ /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { -/// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None) +/// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) /// .await /// .unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -110,7 +110,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Option = txn.get(key).await.unwrap(); @@ -172,7 +172,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Value = txn.get_for_update(key).await.unwrap().unwrap(); @@ -207,7 +207,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let exists = txn.key_exists("k1".to_owned()).await.unwrap(); /// txn.commit().await.unwrap(); @@ -235,7 +235,7 @@ impl Transaction { /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let result: HashMap = txn @@ -289,7 +289,7 @@ impl Transaction { /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let keys = vec!["foo".to_owned(), "bar".to_owned()]; /// let result: Vec = txn @@ -335,7 +335,7 @@ impl Transaction { /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -372,7 +372,7 @@ impl Transaction { /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -414,7 +414,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -446,7 +446,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -483,7 +483,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// txn.delete(key); @@ -519,7 +519,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// txn.lock_keys(vec!["TiKV".to_owned(), "Rust".to_owned()]); /// // ... Do some actions. @@ -556,7 +556,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// let result: Timestamp = txn.commit().await.unwrap().unwrap(); @@ -615,7 +615,7 @@ impl Transaction { /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1, None).await.unwrap(); + /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// txn.rollback().await.unwrap(); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 4fe7b29b..497e22f3 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -19,7 +19,7 @@ pub async fn clear_tikv() { // DEFAULT_REGION_BACKOFF is not long enough for CI environment. So set a longer backoff. let backoff = tikv_client::Backoff::no_jitter_backoff(100, 10000, 10); for cf in cfs { - let raw_client = RawClient::new(pd_addrs(), raw::ApiV1, None) + let raw_client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None) .await .unwrap() .with_cf(cf); @@ -63,7 +63,7 @@ async fn ensure_region_split( // 1. write plenty transactional keys // 2. wait until regions split - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let mut txn = client.begin_optimistic().await?; for key in keys.into_iter() { txn.put(key.into(), vec![0, 0, 0, 0]).await?; diff --git a/tests/failpoint_tests.rs b/tests/failpoint_tests.rs index fcd9770f..67061175 100644 --- a/tests/failpoint_tests.rs +++ b/tests/failpoint_tests.rs @@ -19,7 +19,7 @@ async fn txn_optimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), ApiV1::default(), None).await?; let mut heartbeat_txn = client .begin_with_options( diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index a8f69b12..534b9722 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -37,7 +37,7 @@ const NUM_TRNASFER: u32 = 100; #[serial] async fn txn_get_timestamp() -> Result<()> { const COUNT: usize = 1 << 8; // use a small number to make test fast - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let mut versions = future::join_all((0..COUNT).map(|_| client.current_timestamp())) .await @@ -58,7 +58,7 @@ async fn txn_get_timestamp() -> Result<()> { async fn txn_crud() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let mut txn = client.begin_optimistic().await?; // Get non-existent keys @@ -142,7 +142,7 @@ async fn txn_crud() -> Result<()> { async fn txn_insert_duplicate_keys() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; // Initialize TiKV store with {foo => bar} let mut txn = client.begin_optimistic().await?; txn.put("foo".to_owned(), "bar".to_owned()).await?; @@ -166,7 +166,7 @@ async fn txn_insert_duplicate_keys() -> Result<()> { async fn txn_pessimistic() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let mut txn = client.begin_pessimistic().await?; txn.put("foo".to_owned(), "foo".to_owned()).await.unwrap(); @@ -183,7 +183,7 @@ async fn txn_pessimistic() -> Result<()> { #[serial] async fn raw_bank_transfer() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; let mut rng = thread_rng(); let people = gen_u32_keys(NUM_PEOPLE, &mut rng); @@ -235,7 +235,7 @@ async fn txn_read() -> Result<()> { let value = "large_value".repeat(10); init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -327,7 +327,7 @@ async fn txn_read() -> Result<()> { #[serial] async fn txn_bank_transfer() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let mut rng = thread_rng(); let options = TransactionOptions::new_optimistic() .use_async_commit() @@ -380,7 +380,7 @@ async fn txn_bank_transfer() -> Result<()> { #[serial] async fn raw_req() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; // empty; get non-existent key let res = client.get("k1".to_owned()).await; @@ -510,7 +510,7 @@ async fn raw_req() -> Result<()> { #[serial] async fn txn_update_safepoint() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let res = client.gc(client.current_timestamp().await?).await?; assert!(res); Ok(()) @@ -525,7 +525,7 @@ async fn raw_write_million() -> Result<()> { let interval = 2u32.pow(32 - NUM_BITS_TXN - NUM_BITS_KEY_PER_TXN); init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -574,7 +574,7 @@ async fn txn_pessimistic_rollback() -> Result<()> { let client = TransactionClient::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1, + transaction::ApiV1::default(), None, ) .await?; @@ -612,7 +612,7 @@ async fn txn_pessimistic_delete() -> Result<()> { let client = TransactionClient::new_with_config( vec!["127.0.0.1:2379"], Default::default(), - transaction::ApiV1, + transaction::ApiV1::default(), None, ) .await?; @@ -660,7 +660,7 @@ async fn txn_lock_keys() -> Result<()> { let client = TransactionClient::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1, + transaction::ApiV1::default(), None, ) .await?; @@ -700,7 +700,7 @@ async fn txn_lock_keys_error_handle() -> Result<()> { let client = TransactionClient::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1, + transaction::ApiV1::default(), None, ) .await?; @@ -743,7 +743,7 @@ async fn txn_get_for_update() -> Result<()> { let client = TransactionClient::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1, + transaction::ApiV1::default(), None, ) .await?; @@ -793,7 +793,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1, None).await?; + let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; let mut heartbeat_txn = client .begin_with_options(TransactionOptions::new_pessimistic()) @@ -833,7 +833,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { #[serial] async fn raw_cas() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1, None) + let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None) .await? .with_atomic_for_cas(); let key = "key".to_owned(); @@ -878,7 +878,7 @@ async fn raw_cas() -> Result<()> { client.batch_delete(vec![key.clone()]).await.err().unwrap(), Error::UnsupportedMode )); - let client = RawClient::new(pd_addrs(), raw::ApiV1, None).await?; + let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; assert!(matches!( client .compare_and_swap(key.clone(), None, vec![]) @@ -898,7 +898,7 @@ async fn txn_scan() -> Result<()> { let client = TransactionClient::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1, + transaction::ApiV1::default(), None, ) .await?; diff --git a/tests/mock_tikv_tests.rs b/tests/mock_tikv_tests.rs index 60164de0..411f28d7 100644 --- a/tests/mock_tikv_tests.rs +++ b/tests/mock_tikv_tests.rs @@ -15,9 +15,13 @@ mod test { let mut tikv_server = start_mock_tikv_server(); let _pd_server = start_mock_pd_server(); - let client = RawClient::new(vec![format!("localhost:{}", MOCK_PD_PORT)], ApiV1, None) - .await - .unwrap(); + let client = RawClient::new( + vec![format!("localhost:{}", MOCK_PD_PORT)], + ApiV1::default(), + None, + ) + .await + .unwrap(); // empty; get non-existent key let res = client.get("k1".to_owned()).await; From bfd1f28986eff32a01b4746d0fc4781e3ac4c6ac Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Mon, 11 Jul 2022 21:50:23 +0800 Subject: [PATCH 31/43] remove dynamic dispatch while encoding request in Dispatch Signed-off-by: iosmanthus --- src/request/codec.rs | 29 ++++++++++++++++++++++++----- src/request/plan.rs | 16 +++------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/request/codec.rs b/src/request/codec.rs index f3adcb1c..ee88d2f7 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -1,5 +1,6 @@ use core::intrinsics::copy; use std::{ + borrow::Cow, marker::PhantomData, ops::{Deref, DerefMut}, }; @@ -7,7 +8,7 @@ use std::{ use tikv_client_common::Error; use tikv_client_proto::{errorpb, kvrpcpb, metapb::Region}; -use crate::{kv::codec::decode_bytes_in_place, Key, Result}; +use crate::{kv::codec::decode_bytes_in_place, request::KvRequest, Key, Result}; type Prefix = [u8; KEYSPACE_PREFIX_LEN]; @@ -16,6 +17,10 @@ const KEYSPACE_PREFIX_LEN: usize = 4; const MAX_KEYSPACE_ID: KeySpaceId = KeySpaceId([0xff, 0xff, 0xff]); pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { + fn encode_request<'a, R: KvRequest>(&self, req: &'a R) -> Cow<'a, R> { + Cow::Borrowed(req) + } + fn encode_key(&self, key: Vec) -> Vec { key } @@ -36,8 +41,12 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } - fn version(&self) -> kvrpcpb::ApiVersion { - kvrpcpb::ApiVersion::V1 + fn decode_response>( + &self, + _req: &R, + resp: R::Response, + ) -> Result { + Ok(resp) } } @@ -272,6 +281,12 @@ pub struct ApiV2 { } impl RequestCodec for ApiV2 { + fn encode_request<'a, R: KvRequest>(&self, req: &'a R) -> Cow<'a, R> { + let mut req = req.clone(); + req.mut_context().set_api_version(kvrpcpb::ApiVersion::V2); + Cow::Owned(req.encode_request(self)) + } + fn encode_key(&self, mut key: Vec) -> Vec { let mut encoded = Vec::with_capacity(key.len() + KEYSPACE_PREFIX_LEN); let prefix: Prefix = self.keyspace.into(); @@ -337,7 +352,11 @@ impl RequestCodec for ApiV2 { Ok(()) } - fn version(&self) -> kvrpcpb::ApiVersion { - kvrpcpb::ApiVersion::V2 + fn decode_response>( + &self, + req: &R, + resp: R::Response, + ) -> Result { + req.decode_response(self, resp) } } diff --git a/src/request/plan.rs b/src/request/plan.rs index 3cc0c104..5b51fcae 100644 --- a/src/request/plan.rs +++ b/src/request/plan.rs @@ -1,6 +1,6 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. -use std::{borrow::Cow, marker::PhantomData, sync::Arc}; +use std::{marker::PhantomData, sync::Arc}; use async_recursion::async_recursion; use async_trait::async_trait; @@ -55,14 +55,7 @@ impl> Plan for Dispatch { type Result = Req::Response; async fn execute(&self) -> Result { - let req = match self.codec.version() { - kvrpcpb::ApiVersion::V2 => { - let mut req = self.request.clone(); - req.mut_context().set_api_version(self.codec.version()); - Cow::Owned(req.encode_request(&self.codec)) - } - _ => Cow::Borrowed(&self.request), - }; + let req = self.codec.encode_request(&self.request); let stats = tikv_stats(self.request.label()); let result = self @@ -78,10 +71,7 @@ impl> Plan for Dispatch { .downcast() .expect("Downcast failed: request and response type mismatch"); - match self.codec.version() { - kvrpcpb::ApiVersion::V2 => req.decode_response(&self.codec, resp), - _ => Ok(resp), - } + self.codec.decode_response(req.as_ref(), resp) }) } } From 7fc61eaca328c93fe3f29145d131aa9d4edacdd1 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Mon, 11 Jul 2022 21:54:26 +0800 Subject: [PATCH 32/43] make IsDefault private in crate Signed-off-by: iosmanthus --- src/request/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request/mod.rs b/src/request/mod.rs index 6415aeee..c8973039 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -41,7 +41,7 @@ pub trait KvRequest: Request + Sized + Clone + Sync + Send + 'static { } } -pub trait IsDefault { +pub(crate) trait IsDefault { fn is_default(&self) -> bool; } From 6baaa94964fdfb5b57971ec531d8381f644ebe0c Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Mon, 11 Jul 2022 22:47:35 +0800 Subject: [PATCH 33/43] remove impl Deref for Key Signed-off-by: iosmanthus --- src/kv/key.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index b83e0fd2..3d879c73 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -7,11 +7,7 @@ use crate::kv::codec::{self, BytesEncoder}; use proptest::{arbitrary::any_with, collection::size_range}; #[cfg(test)] use proptest_derive::Arbitrary; -use std::{ - fmt, - ops::{Bound, Deref, DerefMut}, - u8, -}; +use std::{fmt, ops::Bound, u8}; use tikv_client_proto::kvrpcpb; const _PROPTEST_KEY_MAX: usize = 1024 * 2; // 2 KB @@ -183,17 +179,3 @@ impl fmt::Debug for Key { write!(f, "Key({})", HexRepr(&self.0)) } } - -impl Deref for Key { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Key { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} From 07c7af7b96de10444b193aa7f658f9df56ae29a8 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 12 Jul 2022 13:49:36 +0800 Subject: [PATCH 34/43] fix potential index out of range while meets corrupted keyspace prefix Signed-off-by: iosmanthus --- src/request/codec.rs | 1 - tikv-client-common/src/errors.rs | 13 ++----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/request/codec.rs b/src/request/codec.rs index ee88d2f7..5fb62872 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -302,7 +302,6 @@ impl RequestCodec for ApiV2 { if !key.starts_with(&prefix) { return Err(Error::CorruptedKeyspace { expected: prefix.to_vec(), - actual: key[..KEYSPACE_PREFIX_LEN].to_vec(), key: key.to_vec(), }); } diff --git a/tikv-client-common/src/errors.rs b/tikv-client-common/src/errors.rs index 019d213d..57fff3ae 100644 --- a/tikv-client-common/src/errors.rs +++ b/tikv-client-common/src/errors.rs @@ -93,17 +93,8 @@ pub enum Error { inner: Box, success_keys: Vec>, }, - #[error( - "Corrupted keyspace: expected: {:?}, actual: {:?}, key: {:?}", - expected, - actual, - key - )] - CorruptedKeyspace { - expected: Vec, - actual: Vec, - key: Vec, - }, + #[error("Corrupted keyspace: expected: {:?}, key: {:?}", expected, key)] + CorruptedKeyspace { expected: Vec, key: Vec }, } impl From for Error { From 0ed902db77c5879b3f924ece8b0ca4c3ad02a605 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 12 Jul 2022 15:13:00 +0800 Subject: [PATCH 35/43] introduce codec type parameter for Snapshot and Transcation Signed-off-by: iosmanthus --- src/transaction/client.rs | 21 +++++---------------- src/transaction/snapshot.rs | 18 ++++++++++++++---- src/transaction/transaction.rs | 25 ++++++++++++++++++------- tests/integration_tests.rs | 6 +++--- 4 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 55f1c3d5..c9ee843c 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -158,7 +158,7 @@ where /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_optimistic(&self) -> Result>> { + pub async fn begin_optimistic(&self) -> Result> { debug!(self.logger, "creating new optimistic transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, TransactionOptions::new_optimistic())) @@ -184,7 +184,7 @@ where /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_pessimistic(&self) -> Result>> { + pub async fn begin_pessimistic(&self) -> Result> { debug!(self.logger, "creating new pessimistic transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, TransactionOptions::new_pessimistic())) @@ -210,21 +210,14 @@ where /// transaction.commit().await.unwrap(); /// # }); /// ``` - pub async fn begin_with_options( - &self, - options: TransactionOptions, - ) -> Result>> { + pub async fn begin_with_options(&self, options: TransactionOptions) -> Result> { debug!(self.logger, "creating new customized transaction"); let timestamp = self.current_timestamp().await?; Ok(self.new_transaction(timestamp, options)) } /// Create a new [`Snapshot`](Snapshot) at the given [`Timestamp`](Timestamp). - pub fn snapshot( - &self, - timestamp: Timestamp, - options: TransactionOptions, - ) -> Snapshot> { + pub fn snapshot(&self, timestamp: Timestamp, options: TransactionOptions) -> Snapshot { debug!(self.logger, "creating new snapshot"); let logger = self.logger.new(o!("child" => 1)); Snapshot::new(self.new_transaction(timestamp, options.read_only()), logger) @@ -306,11 +299,7 @@ where Ok(res) } - fn new_transaction( - &self, - timestamp: Timestamp, - options: TransactionOptions, - ) -> Transaction> { + fn new_transaction(&self, timestamp: Timestamp, options: TransactionOptions) -> Transaction { let logger = self.logger.new(o!("child" => 1)); Transaction::new(timestamp, self.pd.clone(), options, logger) } diff --git a/src/transaction/snapshot.rs b/src/transaction/snapshot.rs index 447dcdd9..286da338 100644 --- a/src/transaction/snapshot.rs +++ b/src/transaction/snapshot.rs @@ -1,8 +1,13 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use crate::{pd::PdClient, BoundRange, Key, KvPair, Result, Transaction, Value}; +use crate::{ + pd::{PdClient, PdRpcClient}, + request::codec::RequestCodec, + BoundRange, Key, KvPair, Result, Transaction, Value, +}; use derive_new::new; use slog::Logger; +use std::marker::PhantomData; /// A read-only transaction which reads at the given timestamp. /// @@ -12,12 +17,17 @@ use slog::Logger; /// /// See the [Transaction](struct@crate::Transaction) docs for more information on the methods. #[derive(new)] -pub struct Snapshot { - transaction: Transaction, +pub struct Snapshot = PdRpcClient> { + transaction: Transaction, logger: Logger, + _phantom: PhantomData, } -impl Snapshot { +impl Snapshot +where + C: RequestCodec, + PdC: PdClient, +{ /// Get the value associated with the given key. pub async fn get(&mut self, key: impl Into) -> Result> { debug!(self.logger, "invoking get request on snapshot"); diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 48519db0..988a1e8c 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -1,6 +1,6 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::{iter, sync::Arc, time::Instant}; +use std::{iter, marker::PhantomData, sync::Arc, time::Instant}; use derive_new::new; use fail::fail_point; @@ -12,9 +12,10 @@ use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; use crate::{ backoff::{Backoff, DEFAULT_REGION_BACKOFF}, - pd::PdClient, + pd::{PdClient, PdRpcClient}, request::{ - Collect, CollectError, CollectSingle, CollectWithShard, Plan, PlanBuilder, RetryOptions, + codec::RequestCodec, Collect, CollectError, CollectSingle, CollectWithShard, Plan, + PlanBuilder, RetryOptions, }, timestamp::TimestampExt, transaction::{buffer::Buffer, lowering::*}, @@ -62,7 +63,7 @@ use crate::{ /// txn.commit().await.unwrap(); /// # }); /// ``` -pub struct Transaction { +pub struct Transaction = PdRpcClient> { status: Arc>, timestamp: Timestamp, buffer: Buffer, @@ -71,15 +72,20 @@ pub struct Transaction { is_heartbeat_started: bool, start_instant: Instant, logger: Logger, + _phantom: PhantomData, } -impl Transaction { +impl Transaction +where + C: RequestCodec, + PdC: PdClient, +{ pub(crate) fn new( timestamp: Timestamp, rpc: Arc, options: TransactionOptions, logger: Logger, - ) -> Transaction { + ) -> Transaction { let status = if options.read_only { TransactionStatus::ReadOnly } else { @@ -94,6 +100,7 @@ impl Transaction { is_heartbeat_started: false, start_instant: std::time::Instant::now(), logger, + _phantom: PhantomData, } } @@ -931,7 +938,11 @@ impl Transaction { } } -impl Drop for Transaction { +impl Drop for Transaction +where + C: RequestCodec, + PdC: PdClient, +{ fn drop(&mut self) { debug!(self.logger, "dropping transaction"); if std::thread::panicking() { diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index bd71ad2a..33a3a6c7 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -23,9 +23,9 @@ use std::{ }; use tikv_client::{ raw, - request::codec::RawCodec, + request::codec::{RawCodec, RequestCodec}, transaction::{self, HeartbeatOption}, - BoundRange, Error, Key, KvPair, PdClient, RawClient, Result, Transaction, TransactionClient, + BoundRange, Error, Key, KvPair, RawClient, Result, Transaction, TransactionClient, TransactionOptions, Value, }; @@ -973,7 +973,7 @@ async fn get_u32(client: &RawClient, key: Vec) -> Result(txn: &mut Transaction, key: Vec) -> Result { +async fn get_txn_u32(txn: &mut Transaction, key: Vec) -> Result { let x = txn.get(key).await?.unwrap(); let boxed_slice = x.into_boxed_slice(); let array: Box<[u8; 4]> = boxed_slice From 182a4579d3fe3d59a2009919658eced7918341ef Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Tue, 12 Jul 2022 16:16:45 +0800 Subject: [PATCH 36/43] bound Client to right codec Signed-off-by: iosmanthus --- src/raw/client.rs | 9 +++------ src/request/codec.rs | 4 ++++ src/transaction/client.rs | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/raw/client.rs b/src/raw/client.rs index a7c4a632..37538dbf 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -13,10 +13,7 @@ use crate::{ config::Config, pd::{PdClient, PdRpcClient}, raw::lowering::*, - request::{ - codec::{RawCodec, RequestCodec}, - Collect, CollectSingle, Plan, - }, + request::{codec::RawCodec, Collect, CollectSingle, Plan}, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; @@ -29,7 +26,7 @@ const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; /// /// The returned results of raw request methods are [`Future`](std::future::Future)s that must be /// awaited to execute. -pub struct Client> { +pub struct Client> { rpc: Arc, cf: Option, /// Whether to use the [`atomic mode`](Client::with_atomic_for_cas). @@ -38,7 +35,7 @@ pub struct Client> { _phantom: PhantomData, } -impl Clone for Client { +impl Clone for Client { fn clone(&self) -> Self { Self { rpc: self.rpc.clone(), diff --git a/src/request/codec.rs b/src/request/codec.rs index 5fb62872..3cdf9595 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -359,3 +359,7 @@ impl RequestCodec for ApiV2 { req.decode_response(self, resp) } } + +impl RawCodec for ApiV2 {} + +impl TxnCodec for ApiV2 {} diff --git a/src/transaction/client.rs b/src/transaction/client.rs index c9ee843c..28d89c05 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -37,13 +37,13 @@ const SCAN_LOCK_BATCH_SIZE: u32 = 1024; /// /// The returned results of transactional requests are [`Future`](std::future::Future)s that must be /// awaited to execute. -pub struct Client { +pub struct Client { pd: Arc>, logger: Logger, _phantom: PhantomData, } -impl Clone for Client { +impl Clone for Client { fn clone(&self) -> Self { Self { pd: self.pd.clone(), From 0e76e1089a63d3a864b55fd945bc83c3a97a4139 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 14 Jul 2022 20:17:45 +0800 Subject: [PATCH 37/43] fix encode range issue with unbound end Signed-off-by: iosmanthus --- src/lib.rs | 1 + src/raw/requests.rs | 19 +++++++---- src/request/codec.rs | 68 ++++++++++++++++++++++++++++--------- src/request/mod.rs | 27 +++++++++++++-- src/transaction/requests.rs | 6 +++- 5 files changed, 95 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7a1c5b9f..815bf9ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,6 +92,7 @@ //! # })} //! ``` +#![feature(min_specialization)] #[macro_use] pub mod request; #[macro_use] diff --git a/src/raw/requests.rs b/src/raw/requests.rs index e2053f09..40676b2a 100644 --- a/src/raw/requests.rs +++ b/src/raw/requests.rs @@ -13,8 +13,9 @@ use crate::{ collect_first, pd::PdClient, request::{ - codec::RequestCodec, plan::ResponseWithShard, Collect, CollectSingle, DefaultProcessor, - KvRequest, Merge, Process, Shardable, SingleKey, + codec::{RequestCodec, RequestCodecExt}, + plan::ResponseWithShard, + Collect, CollectSingle, DefaultProcessor, KvRequest, Merge, Process, Shardable, SingleKey, }, store::{store_stream_for_keys, store_stream_for_ranges, RegionStore}, transaction::HasLocks, @@ -215,6 +216,7 @@ pub fn new_raw_scan_request( req } +has_reverse!(kvrpcpb::RawScanRequest); impl_kv_request!(kvrpcpb::RawScanRequest; kvrpcpb::RawScanResponse, kvs); shardable_range!(kvrpcpb::RawScanRequest); @@ -244,10 +246,15 @@ pub fn new_raw_batch_scan_request( req } -impl_kv_request!( - kvrpcpb::RawBatchScanRequest, ranges; - kvrpcpb::RawBatchScanResponse, kvs -); +impl KvRequest for kvrpcpb::RawBatchScanRequest { + type Response = kvrpcpb::RawBatchScanResponse; + fn encode_request(mut self, codec: &C) -> Self { + *self.mut_ranges() = codec.encode_ranges(self.take_ranges(), self.get_reverse()); + self + } + + impl_decode_response! {kvs} +} impl Shardable for kvrpcpb::RawBatchScanRequest { type Shard = Vec; diff --git a/src/request/codec.rs b/src/request/codec.rs index 3cdf9595..d90c3f22 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -14,8 +14,6 @@ type Prefix = [u8; KEYSPACE_PREFIX_LEN]; const KEYSPACE_PREFIX_LEN: usize = 4; -const MAX_KEYSPACE_ID: KeySpaceId = KeySpaceId([0xff, 0xff, 0xff]); - pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { fn encode_request<'a, R: KvRequest>(&self, req: &'a R) -> Cow<'a, R> { Cow::Borrowed(req) @@ -29,7 +27,7 @@ pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { Ok(()) } - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { + fn encode_range(&self, start: Vec, end: Vec, _reverse: bool) -> (Vec, Vec) { (start, end) } @@ -74,6 +72,10 @@ pub trait RequestCodecExt: RequestCodec { keys.into_iter().map(|key| self.encode_key(key)).collect() } + fn encode_secondaries(&self, secondaries: Vec>) -> Vec> { + self.encode_keys(secondaries) + } + fn encode_pairs(&self, mut pairs: Vec) -> Vec { for pair in pairs.iter_mut() { *pair.mut_key() = self.encode_key(pair.take_key()); @@ -82,9 +84,14 @@ pub trait RequestCodecExt: RequestCodec { pairs } - fn encode_ranges(&self, mut ranges: Vec) -> Vec { + fn encode_ranges( + &self, + mut ranges: Vec, + reverse: bool, + ) -> Vec { for range in ranges.iter_mut() { - let (start, end) = self.encode_range(range.take_start_key(), range.take_end_key()); + let (start, end) = + self.encode_range(range.take_start_key(), range.take_end_key(), reverse); *range.mut_start_key() = start; *range.mut_end_key() = end; } @@ -217,10 +224,10 @@ pub trait Mode: Clone + Copy + Sync + Send + 'static { const MAX_KEY: &'static [u8] = &[Self::PREFIX + 1, 0, 0, 0]; } -#[derive(Clone, Copy)] +#[derive(Default, Clone, Copy)] pub struct RawMode; -#[derive(Clone, Copy)] +#[derive(Default, Clone, Copy)] pub struct TxnMode; impl Mode for RawMode { @@ -228,7 +235,7 @@ impl Mode for RawMode { } impl Mode for TxnMode { - const PREFIX: u8 = b't'; + const PREFIX: u8 = b'x'; } #[derive(Clone)] @@ -263,18 +270,37 @@ impl RequestCodec for ApiV1 { impl TxnCodec for ApiV1 {} -#[derive(Clone, Copy, Default)] +#[derive(Clone, Copy)] pub struct KeySpace { id: KeySpaceId, _phantom: PhantomData, } +impl Default for KeySpace { + fn default() -> Self { + KeySpace { + id: KeySpaceId::default(), + _phantom: PhantomData, + } + } +} + impl From> for Prefix { fn from(s: KeySpace) -> Self { [M::PREFIX, s.id[0], s.id[1], s.id[2]] } } +impl KeySpace { + fn start(self) -> Prefix { + self.into() + } + + fn end(self) -> Prefix { + (u32::from_be_bytes(self.into()) + 1).to_be_bytes() + } +} + #[derive(Default, Clone)] pub struct ApiV2 { keyspace: KeySpace, @@ -318,12 +344,21 @@ impl RequestCodec for ApiV2 { Ok(()) } - fn encode_range(&self, start: Vec, end: Vec) -> (Vec, Vec) { - if self.keyspace.id == MAX_KEYSPACE_ID { - (self.encode_key(start), M::MAX_KEY.to_vec()) - } else { - (self.encode_key(start), self.encode_key(end)) + fn encode_range(&self, start: Vec, end: Vec, reverse: bool) -> (Vec, Vec) { + if reverse { + let (start, end) = self.encode_range(end, start, false); + return (end, start); } + + let start = self.encode_key(start); + + let end = if end.is_empty() { + self.keyspace.end().into() + } else { + self.encode_key(end) + }; + + (start, end) } fn encode_pd_query(&self, key: Vec) -> Vec { @@ -335,14 +370,15 @@ impl RequestCodec for ApiV2 { decode_bytes_in_place(region.mut_end_key(), false)?; // Map the region's start key to the keyspace start key. - if region.get_start_key() < M::MIN_KEY { + if region.get_start_key() <= self.keyspace.start().as_slice() { *region.mut_start_key() = vec![]; } else { self.decode_key(region.mut_start_key())?; } // Map the region's end key to the keyspace end key. - if region.get_end_key().is_empty() || region.get_end_key() > M::MAX_KEY { + if region.get_end_key().is_empty() || region.get_end_key() >= self.keyspace.end().as_slice() + { *region.mut_end_key() = vec![]; } else { self.decode_key(region.mut_end_key())?; diff --git a/src/request/mod.rs b/src/request/mod.rs index c8973039..96152f1a 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -51,6 +51,26 @@ impl IsDefault for T { } } +pub(crate) trait HasReverse { + fn has_reverse(&self) -> bool; +} + +impl HasReverse for T { + default fn has_reverse(&self) -> bool { + false + } +} + +macro_rules! has_reverse { + ($t:ty) => { + impl $crate::request::HasReverse for $t { + fn has_reverse(&self) -> bool { + self.get_reverse() + } + } + }; +} + macro_rules! impl_decode_response { ($($o:ident)*) => { fn decode_response(&self, codec: &C, mut resp: Self::Response) -> Result { @@ -75,7 +95,6 @@ macro_rules! impl_decode_response { }; } -#[macro_export] macro_rules! impl_kv_request { ($req:ty $(,$i:ident)+; $resp:ty $(,$o:ident)*) => { impl KvRequest for $req @@ -102,12 +121,14 @@ macro_rules! impl_kv_request { ($req:ty; $resp:ty $(,$o:ident)*) => { impl KvRequest for $req - where C: RequestCodec + where C: RequestCodec, + $req: $crate::request::HasReverse { type Response = $resp; fn encode_request(mut self, codec: &C) -> Self { - let (start, end) = codec.encode_range(self.take_start_key(), self.take_end_key()); + use $crate::request::HasReverse; + let (start, end) = codec.encode_range(self.take_start_key(), self.take_end_key(), self.has_reverse()); *self.mut_start_key() = start; *self.mut_end_key() = end; diff --git a/src/transaction/requests.rs b/src/transaction/requests.rs index 09573b38..673c7840 100644 --- a/src/transaction/requests.rs +++ b/src/transaction/requests.rs @@ -141,6 +141,7 @@ pub fn new_scan_request( req } +has_reverse!(kvrpcpb::ScanRequest); impl_kv_request!(kvrpcpb::ScanRequest; kvrpcpb::ScanResponse, pairs, error); shardable_range!(kvrpcpb::ScanRequest); @@ -233,7 +234,10 @@ pub fn new_pessimistic_prewrite_request( req } -impl_kv_request!(kvrpcpb::PrewriteRequest, mutations; kvrpcpb::PrewriteResponse, errors); +impl_kv_request!( + kvrpcpb::PrewriteRequest, mutations, primary_lock, secondaries; + kvrpcpb::PrewriteResponse, errors +); impl Shardable for kvrpcpb::PrewriteRequest { type Shard = Vec; From f46cea80cfcf7f1a95f7736374ea7d594d896cbf Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 21 Jul 2022 18:00:38 +0800 Subject: [PATCH 38/43] introduce newer version of proto Signed-off-by: iosmanthus --- Makefile | 3 + src/lib.rs | 2 + src/request/mod.rs | 1 + tikv-client-proto/proto/brpb.proto | 118 ++++++++++++++ tikv-client-proto/proto/cdcpb.proto | 14 ++ tikv-client-proto/proto/coprocessor.proto | 15 +- tikv-client-proto/proto/debugpb.proto | 11 ++ tikv-client-proto/proto/encryptionpb.proto | 1 + tikv-client-proto/proto/errorpb.proto | 7 + tikv-client-proto/proto/gcpb.proto | 117 ++++++++++++++ tikv-client-proto/proto/import_sstpb.proto | 94 +++++++++++- tikv-client-proto/proto/keyspacepb.proto | 80 ++++++++++ tikv-client-proto/proto/kvrpcpb.proto | 145 +++++++++++++++++- tikv-client-proto/proto/logbackuppb.proto | 43 ++++++ tikv-client-proto/proto/metapb.proto | 49 ++++++ tikv-client-proto/proto/mpp.proto | 3 + tikv-client-proto/proto/pdpb.proto | 123 ++++++++++++++- tikv-client-proto/proto/raft_serverpb.proto | 3 + .../proto/replication_modepb.proto | 15 +- .../proto/resource_usage_agent.proto | 57 +++---- tikv-client-proto/proto/tikvpb.proto | 6 + tikv-client-proto/proto/tracepb.proto | 60 ++++++++ tikv-client-proto/src/lib.rs | 4 +- tikv-client-store/src/errors.rs | 2 + 24 files changed, 918 insertions(+), 55 deletions(-) create mode 100644 tikv-client-proto/proto/gcpb.proto create mode 100644 tikv-client-proto/proto/keyspacepb.proto create mode 100644 tikv-client-proto/proto/logbackuppb.proto create mode 100644 tikv-client-proto/proto/tracepb.proto diff --git a/Makefile b/Makefile index 268dc574..c70ff9a8 100644 --- a/Makefile +++ b/Makefile @@ -34,3 +34,6 @@ tiup: tiup playground nightly --mode tikv-slim --kv 3 --without-monitor --kv.config $(shell pwd)/config/tikv.toml --pd.config $(shell pwd)/config/pd.toml & all: check doc test + +format: + cargo fmt --all \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 815bf9ed..4a579aac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,8 @@ //! ``` #![feature(min_specialization)] +#![feature(core_intrinsics)] + #[macro_use] pub mod request; #[macro_use] diff --git a/src/request/mod.rs b/src/request/mod.rs index 96152f1a..004e03cb 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -311,6 +311,7 @@ mod test { region_error: None, error: Some(kvrpcpb::KeyError::default()), commit_version: 0, + ..Default::default() }) as Box) }, ))); diff --git a/tikv-client-proto/proto/brpb.proto b/tikv-client-proto/proto/brpb.proto index c25da40a..66560fdb 100644 --- a/tikv-client-proto/proto/brpb.proto +++ b/tikv-client-proto/proto/brpb.proto @@ -54,6 +54,7 @@ message BackupMeta { // Note: `raw_ranges` is deprecated, as it bloats backupmeta. It is kept for // compatibility, so new BR can restore older backups. repeated RawRange raw_ranges = 9; + // An index to files contains RawRanges. MetaFile raw_range_index = 15; @@ -69,6 +70,12 @@ message BackupMeta { // API version implies the encode of the key and value. kvrpcpb.APIVersion api_version = 18; + + // the placement policy info in backup cluster. we assume the policy won't be too much for one cluster. + repeated PlacementPolicy policies = 19; + + // new_collations_enabled specifies the config `new_collations_enabled_on_first_bootstrap` in tidb. + string new_collations_enabled = 20; } message File { @@ -106,6 +113,10 @@ message MetaFile { repeated bytes ddls = 5; } +message PlacementPolicy { + bytes info = 1; +} + message Schema { bytes db = 1; bytes table = 2; @@ -182,6 +193,47 @@ message BackupRequest { int32 compression_level = 13; // The cipher_info is Used to encrypt sst CipherInfo cipher_info = 14; + + // dst_api_version indicates the key-value encoding version used by the + // generated SST file. Accepted values: + // 1. "v1": the generated SST files are encoded with api-v1, can be restored + // to TiKV clusters whose api version is set to v1. + // 2. "v2": the generated SST files are encoded with api-v2, can be restored + // to TiKV clusters whose api version is set to v2. + kvrpcpb.APIVersion dst_api_version = 15; +} + +message StreamBackupTaskInfo { + // The storage for backup, parsed by BR. + StorageBackend storage = 1; + // The time range for backing up. + uint64 start_ts = 2; + uint64 end_ts = 3; + + // Misc meta datas. + // The name of the task, also the ID of the task. + string name = 4; + // The table filter of the task. + // Only for displaying the task info. + repeated string table_filter = 5; + + // The last timestamp of the task has been updated. + // This is a simple solution for unfrequent config changing: + // When we watched a config change(via polling or etcd watching), + // We perform a incremental scan between [last_update_ts, now), + // for filling the diff data during conf changing. + // The current implementation scan [0, now) for every task ranges newly added, + // So this field is reserved for future usage. + reserved "last_update_ts"; + + // We use '/tidb/br-stream/ranges// -> ' + // for storing all the target ranges of the task, the "ranges" field will not be saved in the taskinfo. + reserved "ranges"; + + // The status field allow us mark the task as 'paused'. + // We use '/tidb/br-stream/pause/ -> ()' for pausing a task for now. + // If we need more complexed status transforming, maybe add the status field back would be fine. + reserved "status"; } message StorageBackend { @@ -287,6 +339,9 @@ message BackupResponse { bytes start_key = 2; bytes end_key = 3; repeated File files = 4; + + // API version implies the encode of the key and value. + kvrpcpb.APIVersion api_version = 5; } service Backup { @@ -321,3 +376,66 @@ message ExternalStorageSaveRequest { message ExternalStorageSaveResponse { } +message Metadata { + repeated DataFileInfo files = 1; + int64 store_id = 2; + uint64 resolved_ts = 3; + uint64 max_ts = 4; + uint64 min_ts = 5; +} + +enum FileType { + Delete = 0; + Put = 1; +} + +message DataFileInfo { + // SHA256 of the file. + bytes sha256 = 1; + // Path of the file. + string path = 2; + int64 number_of_entries = 3; + + /// Below are extra information of the file, for better filtering files. + // The min ts of the keys in the file. + uint64 min_ts = 4; + // The max ts of the keys in the file. + uint64 max_ts = 5; + // The resolved ts of the region when saving the file. + uint64 resolved_ts = 6; + // The region of the file. + int64 region_id = 7; + // The key range of the file. + // Encoded and starts with 'z'(internal key). + bytes start_key = 8; + bytes end_key = 9; + // The column family of the file. + string cf = 10; + // The operation type of the file. + FileType type = 11; + + // Whether the data file contains meta keys(m prefixed keys) only. + bool is_meta = 12; + // The table ID of the file contains, when `is_meta` is true, would be ignored. + int64 table_id = 13; + + // The file length. + uint64 length = 14; + + // The minimal begin ts in default cf if this file is write cf. + uint64 min_begin_ts_in_default_cf = 15; + + // It may support encrypting at future. + reserved "iv"; +} + +message StreamBackupError { + // the unix epoch time (in millisecs) of the time the error reported. + uint64 happen_at = 1; + // the unified error code of the error. + string error_code = 2; + // the user-friendly error message. + string error_message = 3; + // the store id of who issues the error. + uint64 store_id = 4; +} diff --git a/tikv-client-proto/proto/cdcpb.proto b/tikv-client-proto/proto/cdcpb.proto index 5682eafd..969beff8 100644 --- a/tikv-client-proto/proto/cdcpb.proto +++ b/tikv-client-proto/proto/cdcpb.proto @@ -83,6 +83,10 @@ message Event { bytes key = 5; bytes value = 6; bytes old_value = 7; + // expire_ts_unix_secs is used for RawKV (see `ChangeDataRequest.KvApi`), + // and represents the expiration time of this row. + // Absolute time, seconds since Unix epoch. + uint64 expire_ts_unix_secs = 8; } message Entries { @@ -150,6 +154,16 @@ message ChangeDataRequest { // min_commit_ts so that the resolved_ts can be advanced. NotifyTxnStatus notify_txn_status = 10; } + + // KvAPI specifies to capture data written by different KV API. + // See more details in https://github.com/tikv/rfcs/blob/master/text/0069-api-v2.md. + enum KvAPI { + TiDB = 0; + RawKV = 1; + TxnKV = 2; + } + + KvAPI kv_api = 11; } service ChangeData { diff --git a/tikv-client-proto/proto/coprocessor.proto b/tikv-client-proto/proto/coprocessor.proto index 4078f23e..45c724aa 100644 --- a/tikv-client-proto/proto/coprocessor.proto +++ b/tikv-client-proto/proto/coprocessor.proto @@ -6,7 +6,6 @@ import "kvrpcpb.proto"; import "gogoproto/gogo.proto"; import "rustproto.proto"; import "metapb.proto"; -import "span.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; @@ -57,7 +56,12 @@ message Response { bool is_cache_hit = 7; uint64 cache_last_version = 8; bool can_be_cached = 9; - repeated span.SpanSet spans = 10; + + reserved 10; + + // Contains the latest buckets version of the region. + // Clients should query PD to update buckets in cache if its is stale. + uint64 latest_buckets_version = 12; } message RegionInfo { @@ -66,6 +70,11 @@ message RegionInfo { repeated KeyRange ranges = 3; } +message TableRegions { + int64 physical_table_id = 1; + repeated RegionInfo regions = 2; +} + message BatchRequest { kvrpcpb.Context context = 1; int64 tp = 2; @@ -74,6 +83,8 @@ message BatchRequest { uint64 start_ts = 5; // Any schema-ful storage to validate schema correctness if necessary. int64 schema_ver = 6; + // Used for partition table scan + repeated TableRegions table_regions = 7; } message BatchResponse { diff --git a/tikv-client-proto/proto/debugpb.proto b/tikv-client-proto/proto/debugpb.proto index 400da51d..a5eab219 100644 --- a/tikv-client-proto/proto/debugpb.proto +++ b/tikv-client-proto/proto/debugpb.proto @@ -73,6 +73,10 @@ service Debug { // Get all region IDs in the store rpc GetAllRegionsInStore(GetAllRegionsInStoreRequest) returns (GetAllRegionsInStoreResponse) {} + + // Make this TiKV node return to the status on this node to certain ts. + rpc ResetToVersion(ResetToVersionRequest) returns (ResetToVersionResponse) {} + } enum DB { @@ -259,3 +263,10 @@ message GetAllRegionsInStoreRequest { message GetAllRegionsInStoreResponse { repeated uint64 regions = 1; } + +message ResetToVersionRequest { + uint64 ts = 1; +} + +message ResetToVersionResponse { +} diff --git a/tikv-client-proto/proto/encryptionpb.proto b/tikv-client-proto/proto/encryptionpb.proto index ddae704e..2328088c 100644 --- a/tikv-client-proto/proto/encryptionpb.proto +++ b/tikv-client-proto/proto/encryptionpb.proto @@ -44,6 +44,7 @@ enum EncryptionMethod { AES128_CTR = 2; AES192_CTR = 3; AES256_CTR = 4; + SM4_CTR = 5; } // The key used to encrypt the user data. diff --git a/tikv-client-proto/proto/errorpb.proto b/tikv-client-proto/proto/errorpb.proto index 8fd9c233..4a81c042 100644 --- a/tikv-client-proto/proto/errorpb.proto +++ b/tikv-client-proto/proto/errorpb.proto @@ -128,6 +128,11 @@ message DataIsNotReady { uint64 safe_ts = 3; } +message RecoveryInProgress { + // The requested region ID + uint64 region_id = 1; +} + // Error wraps all region errors, indicates an error encountered by a request. message Error { reserved "stale_epoch"; @@ -148,4 +153,6 @@ message Error { DataIsNotReady data_is_not_ready = 13; RegionNotInitialized region_not_initialized = 14; DiskFull disk_full = 15; + // Online recovery is still in performing, reject writes to avoid potential issues + RecoveryInProgress RecoveryInProgress = 16; } diff --git a/tikv-client-proto/proto/gcpb.proto b/tikv-client-proto/proto/gcpb.proto new file mode 100644 index 00000000..053872b8 --- /dev/null +++ b/tikv-client-proto/proto/gcpb.proto @@ -0,0 +1,117 @@ +syntax = "proto3"; +package gcpb; + +import "gogoproto/gogo.proto"; +import "rustproto.proto"; + +option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (rustproto.lite_runtime_all) = true; + +option java_package = "org.tikv.kvproto"; + +service GC { + rpc ListKeySpaces(ListKeySpacesRequest) returns (ListKeySpacesResponse) {} + + rpc GetMinServiceSafePoint(GetMinServiceSafePointRequest) returns (GetMinServiceSafePointResponse) {} + + rpc UpdateGCSafePoint(UpdateGCSafePointRequest) returns (UpdateGCSafePointResponse) {} + + rpc UpdateServiceSafePoint(UpdateServiceSafePointRequest) returns (UpdateServiceSafePointResponse) {} +} + +message RequestHeader { + // cluster_id is the ID of the cluster which be sent to. + uint64 cluster_id = 1; + // sender_id is the ID of the sender server, also member ID or etcd ID. + uint64 sender_id = 2; +} + +message ResponseHeader { + // cluster_id is the ID of the cluster which sent the response. + uint64 cluster_id = 1; + Error error = 2; +} + +enum ErrorType { + OK = 0; + UNKNOWN = 1; + NOT_BOOTSTRAPPED = 2; + // revision supplied does not match the current etcd revision + REVISION_MISMATCH = 3; + // if the proposed safe point is earlier than old safe point or gc safe point + SAFEPOINT_ROLLBACK = 4; +} + +message Error { + ErrorType type = 1; + string message = 2; +} + +message KeySpace { + bytes space_id = 1; + uint64 gc_safe_point = 2; +} + +message ListKeySpacesRequest { + RequestHeader header = 1; + // set with_gc_safe_point to true to also receive gc safe point for each key space + bool with_gc_safe_point = 2; +} + +message ListKeySpacesResponse { + ResponseHeader header = 1; + repeated KeySpace key_spaces = 2; +} + +message GetMinServiceSafePointRequest { + RequestHeader header = 1; + bytes space_id = 2; +} + +message GetMinServiceSafePointResponse { + ResponseHeader header = 1; + uint64 safe_point = 2; + // revision here is to safeguard the validity of the obtained min, + // preventing cases where new services register their safe points after min is obtained by gc worker + int64 revision = 3; +} + +message UpdateGCSafePointRequest { + RequestHeader header = 1; + bytes space_id = 2; + uint64 safe_point = 3; + // here client need to provide the revision obtained from GetMinServiceSafePoint, + // so server can check if it's still valid + int64 revision = 4; +} + +message UpdateGCSafePointResponse { + ResponseHeader header = 1; + // update will be successful if revision is valid and new safepoint > old safe point + // if failed, previously obtained min might be incorrect, should retry from GetMinServiceSafePoint + bool succeeded = 2; + uint64 new_safe_point = 3; +} + +message UpdateServiceSafePointRequest { + RequestHeader header = 1; + bytes space_id = 2; + bytes service_id = 3; + // safe point will be set to expire on (PD Server time + TTL) + // pass in a ttl < 0 to remove target safe point + // pass in MAX_INT64 to set a safe point that never expire + int64 TTL = 4; + uint64 safe_point = 5; +} + +message UpdateServiceSafePointResponse { + ResponseHeader header = 1; + // update will be successful if ttl < 0 (a removal request) + // or if new safe point >= old safe point and new safe point >= gc safe point + bool succeeded = 2; + uint64 gc_safe_point = 3; + uint64 old_safe_point = 4; + uint64 new_safe_point = 5; +} diff --git a/tikv-client-proto/proto/import_sstpb.proto b/tikv-client-proto/proto/import_sstpb.proto index ec1f0461..04834210 100644 --- a/tikv-client-proto/proto/import_sstpb.proto +++ b/tikv-client-proto/proto/import_sstpb.proto @@ -5,7 +5,6 @@ package import_sstpb; import "metapb.proto"; import "errorpb.proto"; import "kvrpcpb.proto"; -import "raft_serverpb.proto"; import "gogoproto/gogo.proto"; import "rustproto.proto"; import "brpb.proto"; @@ -56,6 +55,12 @@ service ImportSST { // Collect duplicate data from TiKV. rpc DuplicateDetect(DuplicateDetectRequest) returns (stream DuplicateDetectResponse) {} + + // Apply download & apply increment kv files to TiKV. + rpc Apply(ApplyRequest) returns (ApplyResponse) {} + + // ClearFiles clear applied file after restore succeed. + rpc ClearFiles(ClearRequest) returns (ClearResponse) {} } enum SwitchMode { @@ -176,6 +181,9 @@ message DownloadRequest { // of gRPC, add more concrete types if it is necessary later. message Error { string message = 1; + + // We meet some internal errors of the store. + errorpb.Error store_error = 2; } message DownloadResponse { @@ -235,6 +243,13 @@ message WriteResponse { message RawWriteBatch { uint64 ttl = 1; repeated Pair pairs = 2; + + // To be compatible with the key encoding of API V2. + // This field should be generated from the client instead of the server, + // since the message will be send to all the replicas of a region. + // Otherwise, the underlying data generated by the server would be inconsistent which is hard to scale + // for other features like MVCC over RawKV. + uint64 ts = 3; } message RawWriteRequest { @@ -280,3 +295,80 @@ message DuplicateDetectResponse { // ] repeated KvPair pairs = 3; } + +message KVMeta { + // The file name of the KV file. + string name = 1; + + // file length for check. + uint64 length = 2; + + // tell us which cf should apply. WRITE_CF or DEFAULT_CF e.g. + string cf = 3; + + // is_delete represents whether we should delete the kv in tikv. + // it may not be too much delete file. only rollBack operation will generate delete kv file. + bool is_delete = 4; + + // the key ts space being smaller than start_ts can be filter. + uint64 start_ts = 10; + + // the key ts space large than restore_ts can be filter. + uint64 restore_ts = 5; + + bytes start_key = 6; + + bytes end_key = 7; + + // used for checksum when download kv file. + bytes sha256 = 8; + + // the key ts space less than start_snapshot_ts can be filter. + // Deprecated: this field 'start_snapshot_ts' is replaced by the field 'start_ts'. + uint64 start_snapshot_ts = 9; +} + + +message ApplyRequest { + // The meta of the KV file. + KVMeta meta = 1; + + // Performs a key prefix rewrite after downloading the file. + // All keys in the files will be rewritten as: + // + // new_key = new_key_prefix + old_key[len(old_key_prefix)..] + // + // When used for TiDB, rewriting the prefix changes the table ID. Please + // note that key-rewrite is applied on the origin keys in encoded + // representation. + // + // You need to ensure that the keys before and after rewriting are in the + // same order, otherwise the RPC request will fail. + RewriteRule rewrite_rule = 2 [(gogoproto.nullable) = false]; + + backup.StorageBackend storage_backend = 3; + + // context represents region info and it used to build raft commands. + kvrpcpb.Context context = 4; + + // cipher_info is used to decrypt kv file when download file. + backup.CipherInfo cipher_info = 11; +} + +message ApplyResponse { + // The actual key range (after rewrite) of the downloaded file. The range is + // inclusive in both ends. + Range range = 1 [(gogoproto.nullable) = false]; + + Error error = 2; +} + +message ClearRequest { + // clear files in import directory with given prefix. + string prefix = 1; +} + +message ClearResponse { + Error error = 1; +} + diff --git a/tikv-client-proto/proto/keyspacepb.proto b/tikv-client-proto/proto/keyspacepb.proto new file mode 100644 index 00000000..70a58d10 --- /dev/null +++ b/tikv-client-proto/proto/keyspacepb.proto @@ -0,0 +1,80 @@ +syntax = "proto3"; +package keyspacepb; + +import "pdpb.proto"; + +import "gogoproto/gogo.proto"; +import "rustproto.proto"; + +option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (rustproto.lite_runtime_all) = true; + +option java_package = "org.tikv.kvproto"; + +// Keyspace provides services to manage keyspaces. +service Keyspace { + rpc UpdateKeyspaceConfig (UpdateKeyspaceConfigRequest) returns (UpdateKeyspaceConfigResponse) {} + + rpc LoadKeyspace (LoadKeyspaceRequest) returns (LoadKeyspaceResponse) {} + // WatchKeyspaces first return all current keyspaces' metadata as its first response. + // Then, it returns responses containing keyspaces that had their metadata changed. + rpc WatchKeyspaces (WatchKeyspacesRequest) returns (stream WatchKeyspacesResponse) {} +} + +message KeyspaceMeta { + uint32 id = 1; + string name = 2; + KeyspaceState state = 3; + int64 created_at = 4; + int64 state_changed_at = 5; + map config = 7; +} + +enum KeyspaceState { + ENABLED = 0; + DISABLED = 1; + ARCHIVED = 2; +} + +message UpdateKeyspaceConfigRequest { + pdpb.RequestHeader header = 1; + string name = 2; + repeated Mutation mutations = 3; +} + +message Mutation { + Op op = 1; + bytes key = 2; + bytes value = 3; +} + +enum Op { + PUT = 0; + DEL = 1; +} + +message UpdateKeyspaceConfigResponse { + pdpb.ResponseHeader header = 1; + KeyspaceMeta keyspace = 2; +} + +message LoadKeyspaceRequest { + pdpb.RequestHeader header = 1; + string name = 2; +} + +message LoadKeyspaceResponse { + pdpb.ResponseHeader header = 1; + KeyspaceMeta keyspace = 2; +} + +message WatchKeyspacesRequest { + pdpb.RequestHeader header = 1; +} + +message WatchKeyspacesResponse { + pdpb.ResponseHeader header = 1; + repeated KeyspaceMeta keyspaces = 2; +} diff --git a/tikv-client-proto/proto/kvrpcpb.proto b/tikv-client-proto/proto/kvrpcpb.proto index 34d08be4..e7e5a291 100644 --- a/tikv-client-proto/proto/kvrpcpb.proto +++ b/tikv-client-proto/proto/kvrpcpb.proto @@ -6,6 +6,7 @@ import "errorpb.proto"; import "gogoproto/gogo.proto"; import "rustproto.proto"; import "deadlock.proto"; +import "tracepb.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; @@ -121,6 +122,8 @@ message PrewriteResponse { // the commit ts of the transaction. Otherwise, if TiKV failed to commit it with 1PC or the // transaction is not 1PC, the value will be 0. uint64 one_pc_commit_ts = 4; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 5; } // Lock a set of keys to prepare to write to them. @@ -172,6 +175,8 @@ message PessimisticLockResponse { // In legacy TiKV, this field is not used even 'force' is false. In that case, an empty value indicates // two possible situations: (1) the key does not exist. (2) the key exists but the value is empty. repeated bool not_founds = 6; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 7; } // Unlock keys locked using `PessimisticLockRequest`. @@ -185,6 +190,8 @@ message PessimisticRollbackRequest { message PessimisticRollbackResponse { errorpb.Error region_error = 1; repeated KeyError errors = 2; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 3; } // Used to update the lock_ttl of a psessimistic and/or large transaction to prevent it from been killed. @@ -203,6 +210,8 @@ message TxnHeartBeatResponse { KeyError error = 2; // The TTL actually set on the requested lock. uint64 lock_ttl = 3; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 4; } // CheckTxnStatusRequest checks the status of a transaction. @@ -246,6 +255,8 @@ message CheckTxnStatusResponse { // The action performed by TiKV (and why if the action is to rollback). Action action = 5; LockInfo lock_info = 6; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 7; } // Part of the async commit protocol, checks for locks on all supplied keys. If a lock is missing, @@ -268,6 +279,8 @@ message CheckSecondaryLocksResponse { // If any of the locks have been committed, this is the commit ts used. If no // locks have been committed, it will be zero. uint64 commit_ts = 4; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 5; } // The second phase of writing to TiKV. If there are no errors or conflicts, then this request @@ -289,6 +302,8 @@ message CommitResponse { KeyError error = 2; // If the commit ts is derived from min_commit_ts, this field should be set. uint64 commit_version = 3; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 4; } // Not yet implemented. @@ -353,6 +368,8 @@ message BatchRollbackRequest { message BatchRollbackResponse { errorpb.Error region_error = 1; KeyError error = 2; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 3; } // Scan the database for locks. Used at the start of the GC process to find all @@ -374,6 +391,8 @@ message ScanLockResponse { KeyError error = 2; // Info on all locks found by the scan. repeated LockInfo locks = 3; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 4; } // For all keys locked by the transaction identified by `start_version`, either @@ -392,6 +411,8 @@ message ResolveLockRequest { message ResolveLockResponse { errorpb.Error region_error = 1; KeyError error = 2; + // Execution details about the request processing. + ExecDetailsV2 exec_details_v2 = 3; } // Request TiKV to garbage collect all non-current data older than `safe_point`. @@ -466,11 +487,13 @@ message RawBatchPutRequest { Context context = 1; repeated KvPair pairs = 2; string cf = 3; + uint64 ttl = 4 [deprecated=true]; + bool for_cas = 5; + // The time-to-live for each keys in seconds, and if the length of `ttls` // is exactly one, the ttl will be applied to all keys. Otherwise, the length // mismatch between `ttls` and `pairs` will return an error. - repeated uint64 ttls = 4; - bool for_cas = 5; + repeated uint64 ttls = 6; } message RawBatchPutResponse { @@ -710,6 +733,13 @@ message Context { // Read request should read through locks belonging to these transactions because these // transactions are committed and theirs commit_ts <= read request's start_ts. repeated uint64 committed_locks = 22; + + // The informantion to trace a request sent to TiKV. + tracepb.TraceContext trace_context = 23; + + // The source of the request, will be used as the tag of the metrics reporting. + // This field can be set for any requests that require to report metrics with any extra labels. + string request_source = 24; } // The API version the server and the client is using. @@ -841,6 +871,7 @@ enum CommandPri { enum IsolationLevel { SI = 0; // SI = snapshot isolation RC = 1; // RC = read committed + RCCheckTS = 2; // RC read and it's needed to check if there exists more recent versions. } // Operation allowed info during each TiKV storage threshold. @@ -852,16 +883,18 @@ enum DiskFullOpt { message TimeDetail { // Off-cpu wall time elapsed in TiKV side. Usually this includes queue waiting time and - // other kind of waitings in series. - int64 wait_wall_time_ms = 1; + // other kind of waitings in series. (Wait time in the raftstore is not included.) + uint64 wait_wall_time_ms = 1; // Off-cpu and on-cpu wall time elapsed to actually process the request payload. It does not // include `wait_wall_time`. // This field is very close to the CPU time in most cases. Some wait time spend in RocksDB // cannot be excluded for now, like Mutex wait time, which is included in this field, so that // this field is called wall time instead of CPU time. - int64 process_wall_time_ms = 2; + uint64 process_wall_time_ms = 2; // KV read wall Time means the time used in key/value scan and get. - int64 kv_read_wall_time_ms = 3; + uint64 kv_read_wall_time_ms = 3; + // Total wall clock time spent on this RPC in TiKV . + uint64 total_rpc_wall_time_ns = 4; } message ScanInfo { @@ -911,6 +944,12 @@ message ScanDetailV2 { // Total number of bytes from block reads. uint64 rocksdb_block_read_byte = 7; + + // Total time used for block reads. + uint64 rocksdb_block_read_nanos = 9; + + // Time used for getting a raftstore snapshot (including leader confirmation and getting the RocksDB snapshot). + uint64 get_snapshot_nanos = 10; } message ExecDetails { @@ -931,6 +970,50 @@ message ExecDetailsV2 { // Available when ctx.record_scan_stat = true or meet slow query. ScanDetailV2 scan_detail_v2 = 2; + + // Raftstore writing durations of the request. Only available for some write requests. + WriteDetail write_detail = 3; +} + +message WriteDetail { + // Wait duration in the store loop. + uint64 store_batch_wait_nanos = 1; + + // Wait duration before sending proposal to peers. + uint64 propose_send_wait_nanos = 2; + + // Total time spent on persisting the log. + uint64 persist_log_nanos = 3; + + // Wait time until the Raft log write leader begins to write. + uint64 raft_db_write_leader_wait_nanos = 4; + + // Time spent on synchronizing the Raft log to the disk. + uint64 raft_db_sync_log_nanos = 5; + + // Time spent on writing the Raft log to the Raft memtable. + uint64 raft_db_write_memtable_nanos = 6; + + // Time waiting for peers to confirm the proposal (counting from the instant when the leader sends the proposal message). + uint64 commit_log_nanos = 7; + + // Wait duration in the apply loop. + uint64 apply_batch_wait_nanos = 8; + + // Total time spend to applying the log. + uint64 apply_log_nanos = 9; + + // Wait time until the KV RocksDB lock is acquired. + uint64 apply_mutex_lock_nanos = 10; + + // Wait time until becoming the KV RocksDB write leader. + uint64 apply_write_leader_wait_nanos = 11; + + // Time spent on writing the KV DB WAL to the disk. + uint64 apply_write_wal_nanos = 12; + + // Time spent on writing to the memtable of the KV RocksDB. + uint64 apply_write_memtable_nanos = 13; } message KvPair { @@ -1144,3 +1227,53 @@ message RawChecksumResponse { uint64 total_kvs = 4; uint64 total_bytes = 5; } + +message CompactError { + oneof error { + CompactErrorInvalidStartKey err_invalid_start_key = 1; + CompactErrorPhysicalTableNotExist err_physical_table_not_exist = 2; + CompactErrorCompactInProgress err_compact_in_progress = 3; + CompactErrorTooManyPendingTasks err_too_many_pending_tasks = 4; + } +} + +message CompactErrorInvalidStartKey {} + +message CompactErrorPhysicalTableNotExist {} + +message CompactErrorCompactInProgress {} + +message CompactErrorTooManyPendingTasks {} + +message CompactRequest { + // If specified, the compaction will start from this start key. + // If unspecified, the compaction will start from beginning. + // NOTE 1: The start key should be never manually constructed. You should always use a key + // returned in CompactResponse. + // NOTE 2: the compaction range will be always restricted by physical_table_id. + bytes start_key = 1; + + // The physical table that will be compacted. + // + // TODO: this is information that TiKV doesn't need to know. + // See https://github.com/pingcap/kvproto/issues/912 + int64 physical_table_id = 2; + + // The logical table id of the compaction. When receiving parallel requests with the same + // logical table id, err_compact_in_progress will be returned. + // + // TODO: this is information that TiKV doesn't need to know. + // See https://github.com/pingcap/kvproto/issues/912 + int64 logical_table_id = 3; +} + +message CompactResponse { + CompactError error = 1; + + // The compaction is done incrementally. If there are more data to compact, this field + // will be set. The client can request to compact more data according to the `compacted_end_key`. + bool has_remaining = 2; + + bytes compacted_start_key = 3; + bytes compacted_end_key = 4; +} diff --git a/tikv-client-proto/proto/logbackuppb.proto b/tikv-client-proto/proto/logbackuppb.proto new file mode 100644 index 00000000..c377828a --- /dev/null +++ b/tikv-client-proto/proto/logbackuppb.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package logbackup; + +import "gogoproto/gogo.proto"; +import "rustproto.proto"; +import "errorpb.proto"; + +option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (rustproto.lite_runtime_all) = true; + +option java_package = "org.tikv.kvproto"; + +// The minimal information for identify a region. +message RegionIdentity { + uint64 id = 1; + uint64 epoch_version = 2; + // We omitted epoch_conf_version because config change won't make range change. +} + +// The last flush ts with region information. +message RegionCheckpoint { + errorpb.Error err = 1; + RegionIdentity region = 2; + uint64 checkpoint = 3; +} + +message GetLastFlushTSOfRegionRequest { + repeated RegionIdentity regions = 1; +} + +message GetLastFlushTSOfRegionResponse { + repeated RegionCheckpoint checkpoints = 1; +} + +// The log backup service. +// Generally, most essential interfaces of log backup (say, checkpoint management, task management) are +// provided by adding some key in the embed etcd of PD. +// This interface is mainly provided for the checkpoint advancer and debug usage. +service LogBackup { + rpc GetLastFlushTSOfRegion(GetLastFlushTSOfRegionRequest) returns (GetLastFlushTSOfRegionResponse) {} +} diff --git a/tikv-client-proto/proto/metapb.proto b/tikv-client-proto/proto/metapb.proto index f59de845..1f9aacb4 100644 --- a/tikv-client-proto/proto/metapb.proto +++ b/tikv-client-proto/proto/metapb.proto @@ -26,6 +26,17 @@ enum StoreState { Tombstone = 2; } +// NodeState is going to replace StoreState to make the state concept more clear. +// "Up" is devided into "Preparing" and "Serving" stages so that we can better describe the online process. +// "Removing" is just like previous `Offline` which is more accurate. +// "Removed" has the same meaning with `Tombstone`. +enum NodeState { + Preparing = 0; + Serving = 1; + Removing = 2; + Removed = 3; +} + // Case insensitive key/value for replica constraints. message StoreLabel { string key = 1; @@ -52,6 +63,8 @@ message Store { int64 last_heartbeat = 11; // If the store is physically destroyed, which means it can never up again. bool physically_destroyed = 12; + // NodeState is used to replace StoreState which will be deprecated in the future. + NodeState node_state = 13; } message RegionEpoch { @@ -61,6 +74,42 @@ message RegionEpoch { uint64 version = 2; } +message BucketStats { + // total read in bytes of each bucket + repeated uint64 read_bytes = 1; + + // total write in bytes of each bucket + repeated uint64 write_bytes = 2; + + // total read qps of each bucket + repeated uint64 read_qps = 3; + + // total write qps of each bucket + repeated uint64 write_qps = 4; + + // total read keys of each bucket + repeated uint64 read_keys = 5; + + // total write keys of each bucket + repeated uint64 write_keys = 6; +} + +message Buckets { + uint64 region_id = 1; + + // A hint indicate if keys have changed. + uint64 version = 2; + + // keys of buckets, include start/end key of region + repeated bytes keys = 3; + + // bucket stats + BucketStats stats = 4; + + // The period in milliseconds that stats are collected with in + uint64 period_in_ms = 5; +} + message Region { uint64 id = 1; // Region key range [start_key, end_key). diff --git a/tikv-client-proto/proto/mpp.proto b/tikv-client-proto/proto/mpp.proto index 4167b49c..13b73d92 100644 --- a/tikv-client-proto/proto/mpp.proto +++ b/tikv-client-proto/proto/mpp.proto @@ -34,6 +34,8 @@ message DispatchTaskRequest { repeated coprocessor.RegionInfo regions = 4; // If this task contains table scan, we still need their region info. int64 schema_ver = 5; + // Used for partition table scan + repeated coprocessor.TableRegions table_regions = 6; } // Get response of DispatchTaskRequest. @@ -64,6 +66,7 @@ message MPPDataPacket { bytes data = 1; Error error = 2; repeated bytes chunks = 3; + repeated uint64 stream_ids = 4; } message Error { diff --git a/tikv-client-proto/proto/pdpb.proto b/tikv-client-proto/proto/pdpb.proto index 4f3d08f5..0fb827f3 100644 --- a/tikv-client-proto/proto/pdpb.proto +++ b/tikv-client-proto/proto/pdpb.proto @@ -84,6 +84,46 @@ service PD { rpc SplitAndScatterRegions(SplitAndScatterRegionsRequest) returns (SplitAndScatterRegionsResponse) {} rpc GetDCLocationInfo(GetDCLocationInfoRequest) returns (GetDCLocationInfoResponse) {} + + rpc StoreGlobalConfig(StoreGlobalConfigRequest) returns (StoreGlobalConfigResponse) {} + + rpc LoadGlobalConfig(LoadGlobalConfigRequest) returns (LoadGlobalConfigResponse) {} + + rpc WatchGlobalConfig(WatchGlobalConfigRequest) returns (stream WatchGlobalConfigResponse) {} + + rpc ReportBuckets(stream ReportBucketsRequest) returns (ReportBucketsResponse) {} + + rpc ReportMinResolvedTS(ReportMinResolvedTsRequest) returns (ReportMinResolvedTsResponse) {} +} + +message WatchGlobalConfigRequest { + +} + +message WatchGlobalConfigResponse { + repeated GlobalConfigItem changes = 1; +} + +message StoreGlobalConfigRequest { + repeated GlobalConfigItem changes = 1; +} + +message StoreGlobalConfigResponse { + Error error = 1; +} + +message LoadGlobalConfigRequest { + repeated string names = 1; +} + +message LoadGlobalConfigResponse { + repeated GlobalConfigItem items = 1; +} + +message GlobalConfigItem { + string name = 1; + string value = 2; + Error error = 3; } message RequestHeader { @@ -107,6 +147,9 @@ enum ErrorType { ALREADY_BOOTSTRAPPED = 4; INCOMPATIBLE_VERSION = 5; REGION_NOT_FOUND = 6; + GLOBAL_CONFIG_NOT_FOUND = 7; + DUPLICATED_ENTRY = 8; + ENTRY_NOT_FOUND = 9; } message Error { @@ -207,6 +250,7 @@ message GetRegionRequest { RequestHeader header = 1; bytes region_key = 2; + bool need_buckets = 3; } message GetRegionResponse { @@ -221,12 +265,15 @@ message GetRegionResponse { // Pending peers are the peers that the leader can't consider as // working followers. repeated metapb.Peer pending_peers = 6; + // buckets isn't nil if GetRegion.* requests set need_buckets. + metapb.Buckets buckets = 7; } message GetRegionByIDRequest { RequestHeader header = 1; uint64 region_id = 2; + bool need_buckets = 3; } // Use GetRegionResponse as the response of GetRegionByIDRequest. @@ -407,7 +454,9 @@ message RegionHeartbeatResponse { // Multiple change peer operations atomically. // Note: PD can use both ChangePeer and ChangePeerV2 at the same time // (not in the same RegionHeartbeatResponse). - // Now, PD use ChangePeerV2 only for replacing peers. + // Now, PD use ChangePeerV2 in following scenarios: + // 1. replacing peers + // 2. demoting voter directly ChangePeerV2 change_peer_v2 = 9; } @@ -484,6 +533,8 @@ message PeerStat { uint64 read_keys = 2; uint64 read_bytes = 3; QueryStats query_stats = 4; + uint64 written_keys = 5; + uint64 written_bytes = 6; } message StoreStats { @@ -532,37 +583,72 @@ message StoreStats { uint64 slow_score = 22; // Damaged regions on the store that need to be removed by PD. repeated uint64 damaged_regions_id = 23; + // If the apply worker is busy, namely high apply wait duration + bool is_apply_busy = 24; } message PeerReport { raft_serverpb.RaftLocalState raft_state = 1; raft_serverpb.RegionLocalState region_state = 2; + bool is_force_leader = 3; + // The peer has proposed but uncommitted commit merge. + bool has_commit_merge = 4; } message StoreReport { repeated PeerReport peer_reports = 1; + uint64 step = 2; } message StoreHeartbeatRequest { RequestHeader header = 1; StoreStats stats = 2; - // Detailed store report that is only filled up on PD's demand for online unsafe recover. + // Detailed store report that is only filled up on PD's demand for online unsafe recovery. StoreReport store_report = 3; + replication_modepb.StoreDRAutoSyncStatus dr_autosync_status = 4; +} + +message DemoteFailedVoters { + uint64 region_id = 1; + repeated metapb.Peer failed_voters = 2; +} + +message ForceLeader { + // The store ids of the failed stores, TiKV uses it to decide if a peer is alive. + repeated uint64 failed_stores = 1; + // The region ids of the peer which is to be force leader. + repeated uint64 enter_force_leaders = 2; } message RecoveryPlan { + // Create empty regions to fill the key range hole. repeated metapb.Region creates = 1; - repeated metapb.Region updates = 2; - repeated uint64 deletes = 3; + // Update the meta of the regions, including peer lists, epoch and key range. + repeated metapb.Region updates = 2 [deprecated=true]; + // Tombstone the peers on the store locally. + repeated uint64 tombstones = 3; + // Issue conf change that demote voters on failed stores to learners on the regions. + repeated DemoteFailedVoters demotes = 4; + // Make the peers to be force leaders. + ForceLeader force_leader = 5; + // Step is an increasing number to note the round of recovery, + // It should be filled in the corresponding store report. + uint64 step = 6; } message StoreHeartbeatResponse { ResponseHeader header = 1; replication_modepb.ReplicationStatus replication_status = 2; string cluster_version = 3; - bool require_detailed_report = 4; - RecoveryPlan plan = 5; + + // Used by online unsafe recovery to request store report. + // Now it's substituted by reusing recovery_plan field. PD will send a empty + // recovery plan instead to request store report. + bool require_detailed_report = 4 [deprecated=true]; + // Operations of recovery. After the plan is executed, TiKV should attach the + // store report in store heartbeat. + RecoveryPlan recovery_plan = 5; } message ScatterRegionRequest { @@ -652,6 +738,8 @@ message SyncRegionResponse{ uint64 start_index = 3; repeated RegionStat region_stats = 4; repeated metapb.Peer region_leaders = 5; + // the buckets informations without stats. + repeated metapb.Buckets buckets =6; } message GetOperatorRequest { @@ -756,3 +844,26 @@ enum QueryKind { Commit = 10; Rollback = 11; } + +message ReportBucketsRequest { + RequestHeader header = 1; + + metapb.RegionEpoch region_epoch = 2; + metapb.Buckets buckets = 3; +} + +message ReportBucketsResponse { + ResponseHeader header = 1; +} + +message ReportMinResolvedTsRequest { + RequestHeader header = 1; + + uint64 store_id = 2; + + uint64 min_resolved_ts = 3; +} + +message ReportMinResolvedTsResponse { + ResponseHeader header = 1; +} diff --git a/tikv-client-proto/proto/raft_serverpb.proto b/tikv-client-proto/proto/raft_serverpb.proto index 8b071331..6c078b14 100644 --- a/tikv-client-proto/proto/raft_serverpb.proto +++ b/tikv-client-proto/proto/raft_serverpb.proto @@ -103,6 +103,8 @@ message RegionLocalState { PeerState state = 1; metapb.Region region = 2; MergeState merge_state = 3; + // The apply index corresponding to the storage when it's initialized. + uint64 tablet_index = 4; } enum ExtraMessageType { @@ -114,6 +116,7 @@ enum ExtraMessageType { // to make sure they all agree to sleep. MsgHibernateRequest = 4; MsgHibernateResponse = 5; + MsgRejectRaftLogCausedByMemoryUsage = 6; } message ExtraMessage { diff --git a/tikv-client-proto/proto/replication_modepb.proto b/tikv-client-proto/proto/replication_modepb.proto index 9bfb8814..c60005b6 100644 --- a/tikv-client-proto/proto/replication_modepb.proto +++ b/tikv-client-proto/proto/replication_modepb.proto @@ -17,10 +17,12 @@ message ReplicationStatus { enum DRAutoSyncState { // Raft logs need to sync between different DCs SYNC = 0; + // Wait for switching to ASYNC. Stop sync raft logs between DCs. + ASYNC_WAIT = 1; // Raft logs need to sync to majority peers - ASYNC = 1; + ASYNC = 2; // Switching from ASYNC to SYNC mode - SYNC_RECOVER = 2; + SYNC_RECOVER = 3; } // The status of dr-autosync mode. @@ -32,6 +34,10 @@ message DRAutoSync { uint64 state_id = 3; // Duration to wait before switching to SYNC by force (in seconds) int32 wait_sync_timeout_hint = 4; + // Stores should only sync messages with available stores when state is ASYNC or ASYNC_WAIT. + repeated uint64 available_stores = 5; + // Stores should forbid region split. + bool pause_region_split = 6; } enum RegionReplicationState { @@ -49,3 +55,8 @@ message RegionReplicationStatus { // Unique ID of the state, it increases after each state transfer. uint64 state_id = 2; } + +message StoreDRAutoSyncStatus { + DRAutoSyncState state = 1; + uint64 state_id = 2; +} diff --git a/tikv-client-proto/proto/resource_usage_agent.proto b/tikv-client-proto/proto/resource_usage_agent.proto index e1a30932..4250ec25 100644 --- a/tikv-client-proto/proto/resource_usage_agent.proto +++ b/tikv-client-proto/proto/resource_usage_agent.proto @@ -14,54 +14,37 @@ option java_package = "org.tikv.kvproto"; // ResourceUsageAgent is the service for storing resource usage records. service ResourceUsageAgent { - // DEPRECATED: We now use `Report` to report not only CPU time. - // - // Report the CPU time records. By default, the records with the same - // resource group tag will be batched by minute. - rpc ReportCPUTime(stream CPUTimeRecord) returns (EmptyResponse) {} - // Report the resource usage records. By default, the records with the same // resource group tag will be batched by minute. rpc Report(stream ResourceUsageRecord) returns (EmptyResponse) {} } -message CPUTimeRecord { - bytes resource_group_tag = 1; +// TiKV implements ResourceMeteringPubSub service for clients to subscribe to resource metering records. +service ResourceMeteringPubSub { + // Clients subscribe to resource metering records through this RPC, and TiKV periodically (e.g. per minute) + // publishes resource metering records to clients via gRPC stream. + rpc Subscribe(ResourceMeteringRequest) returns (stream ResourceUsageRecord) {} +} - // The following 2 repeated zipped together represents a List<(UnixTimestamp, CPUTime)> +message ResourceMeteringRequest {} - // UNIX timestamp in second. - repeated uint64 record_list_timestamp_sec = 2; - // The value can be greater than 1000ms if the requests are running parallelly. - repeated uint32 record_list_cpu_time_ms = 3; +message EmptyResponse {} +message ResourceUsageRecord { + oneof record_oneof { + GroupTagRecord record = 1; + } } -message ResourceUsageRecord { +// GroupTagRecord is a set of resource usage data grouped by resource_group_tag. +message GroupTagRecord { bytes resource_group_tag = 1; - - // The following repeated zipped together represents a List<(UnixTimestamp, Record)> - - // UNIX timestamp in second. - repeated uint64 record_list_timestamp_sec = 2; - - // The value can be greater than 1000ms if the requests are running parallelly. - repeated uint32 record_list_cpu_time_ms = 3; - - // The number of reads of keys associated with resource_group_tag. - repeated uint32 record_list_read_keys = 4; - - // The number of writes of keys associated with resource_group_tag. - repeated uint32 record_list_write_keys = 5; + repeated GroupTagRecordItem items = 2; } -message EmptyResponse {} - -// TiKV implements ResourceMeteringPubSub service for clients to subscribe to resource metering records. -service ResourceMeteringPubSub { - // Clients subscribe to resource metering records through this RPC, and TiKV periodically (e.g. per minute) - // publishes resource metering records to clients via gRPC stream. - rpc Subscribe(ResourceMeteringRequest) returns (stream ResourceUsageRecord) {} +message GroupTagRecordItem { + uint64 timestamp_sec = 1; + uint32 cpu_time_ms = 2; + uint32 read_keys = 3; + uint32 write_keys = 4; } - -message ResourceMeteringRequest {} diff --git a/tikv-client-proto/proto/tikvpb.proto b/tikv-client-proto/proto/tikvpb.proto index c3fd6ad3..dd37fcfa 100644 --- a/tikv-client-proto/proto/tikvpb.proto +++ b/tikv-client-proto/proto/tikvpb.proto @@ -104,6 +104,12 @@ service Tikv { /// Get the information about lock waiting from TiKV. rpc GetLockWaitInfo(kvrpcpb.GetLockWaitInfoRequest) returns (kvrpcpb.GetLockWaitInfoResponse); + + /// Compact a specified key range. This request is not restricted to raft leaders and will not be replicated. + /// It only compacts data on this node. + /// TODO: Currently this RPC is designed to be only compatible with TiFlash. + /// Shall be move out in https://github.com/pingcap/kvproto/issues/912 + rpc Compact(kvrpcpb.CompactRequest) returns (kvrpcpb.CompactResponse); } message BatchCommandsRequest { diff --git a/tikv-client-proto/proto/tracepb.proto b/tikv-client-proto/proto/tracepb.proto new file mode 100644 index 00000000..c229454c --- /dev/null +++ b/tikv-client-proto/proto/tracepb.proto @@ -0,0 +1,60 @@ +syntax = "proto3"; +package tracepb; + +option java_package = "org.tikv.kvproto"; + +service TraceRecordPubSub { + // Subscribe the Trace records generated on this service. The service will periodically (e.g. per minute) + // publishes Trace records to clients via gRPC stream. + rpc Subscribe(TraceRecordRequest) returns (stream TraceRecord) {} +} + +message TraceRecordRequest {} + +message TraceRecord { + oneof record_oneof { + Report report = 1; + NotifyCollect notify_collect = 2; + } +} + +message RemoteParentSpan { + // A unique id to identify the request. It's usually a UUID. + uint64 trace_id = 1; + // The span of remote caller that is awaiting the request. + uint64 span_id = 2; +} + +// The context of the request to be traced. +message TraceContext { + repeated RemoteParentSpan remote_parent_spans = 1; + // Report the trace records only if the duration of handling the request exceeds the threshold. + uint32 duration_threshold_ms = 2; +} + +// Report the spans collected when handling a request on a service. +message Report { + repeated RemoteParentSpan remote_parent_spans = 1; + repeated Span spans = 2; +} + +// Notify the subscriber to persis the spans of the trace. +message NotifyCollect { + uint64 trace_id = 1; +} + +message Span { + // The unique span id within the spans with the same `trace_id`. + // The most significant 32 bits should be random number generated by each service instance. + uint64 span_id = 1; + uint64 parent_id = 2; + uint64 begin_unix_ns = 3; + uint64 duration_ns = 4; + string event = 5; + repeated Property properties = 6; +} + +message Property { + string key = 1; + string value = 2; +} diff --git a/tikv-client-proto/src/lib.rs b/tikv-client-proto/src/lib.rs index 0a9a84af..a3bcc3c1 100644 --- a/tikv-client-proto/src/lib.rs +++ b/tikv-client-proto/src/lib.rs @@ -1,7 +1,9 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. use protos::*; -pub use protos::{coprocessor, errorpb, kvrpcpb, metapb, mpp, pdpb, raft_serverpb, tikvpb}; +pub use protos::{ + coprocessor, errorpb, keyspacepb, kvrpcpb, metapb, mpp, pdpb, raft_serverpb, tikvpb, +}; #[allow(dead_code)] #[allow(clippy::all)] diff --git a/tikv-client-store/src/errors.rs b/tikv-client-store/src/errors.rs index c1e915ac..7c57ed7a 100644 --- a/tikv-client-store/src/errors.rs +++ b/tikv-client-store/src/errors.rs @@ -227,6 +227,7 @@ mod test { region_error: None, error: None, commit_version: 0, + ..Default::default() }); assert!(resp.key_errors().is_none()); @@ -234,6 +235,7 @@ mod test { region_error: None, error: Some(kvrpcpb::KeyError::default()), commit_version: 0, + ..Default::default() }); assert!(resp.key_errors().is_some()); From 130e1b06362c0af435ef40657a65a78b96a3f17a Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Thu, 21 Jul 2022 20:45:48 +0800 Subject: [PATCH 39/43] git fire: impl load keyspace Signed-off-by: iosmanthus --- src/pd/retry.rs | 11 +++++++++++ tikv-client-pd/src/cluster.rs | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/pd/retry.rs b/src/pd/retry.rs index f6524cad..cbe5fecb 100644 --- a/src/pd/retry.rs +++ b/src/pd/retry.rs @@ -19,6 +19,7 @@ use tikv_client_pd::{Cluster, Connection}; use tikv_client_proto::{ metapb, pdpb::{self, Timestamp}, + keyspacepb }; use tokio::sync::RwLock; @@ -43,6 +44,8 @@ pub trait RetryClientTrait { async fn get_timestamp(self: Arc) -> Result; async fn update_safepoint(self: Arc, safepoint: u64) -> Result; + + async fn load_keyspace + Send>(self: Arc, name: T) -> Result; } /// Client for communication with a PD cluster. Has the facility to reconnect to the cluster. pub struct RetryClient { @@ -182,6 +185,14 @@ impl RetryClientTrait for RetryClient { .map(|resp| resp.get_new_safe_point() == safepoint) }) } + + async fn load_keyspace + Send>(self: Arc, name: T) -> Result { + retry!(self, "load_keyspace", |cluster| async { + cluster + .load_keyspace(name, self.timeout) + .await + }) + } } impl fmt::Debug for RetryClient { diff --git a/tikv-client-pd/src/cluster.rs b/tikv-client-pd/src/cluster.rs index 063532e9..38b3872f 100644 --- a/tikv-client-pd/src/cluster.rs +++ b/tikv-client-pd/src/cluster.rs @@ -10,6 +10,7 @@ use std::{ }; use tikv_client_common::internal_err; use tikv_client_proto::pdpb::{self, Timestamp}; +use tikv_client_proto::keyspacepb; /// A PD cluster. pub struct Cluster { @@ -75,6 +76,12 @@ impl Cluster { req.set_safe_point(safepoint); req.send(&self.client, timeout).await } + + pub async fn load_keyspace>(&self, name: T, timeout: Duration) -> Result { + let mut req = pd_request!(self.id, keyspacepb::LoadKeyspaceRequest); + req.set_name(name.as_ref().to_owned()); + req.send(&self.client, timeout).await + } } /// An object for connecting and reconnecting to a PD cluster. @@ -270,10 +277,11 @@ type GrpcResult = std::result::Result; #[async_trait] trait PdMessage { type Response: PdResponse; + type Client: Send + Sync; - async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult; + async fn rpc(&self, client: &Self::Client, opt: CallOption) -> GrpcResult; - async fn send(&self, client: &pdpb::PdClient, timeout: Duration) -> Result { + async fn send(&self, client: &Self::Client, timeout: Duration) -> Result { let option = CallOption::default().timeout(timeout); let response = self.rpc(client, option).await?; @@ -288,6 +296,7 @@ trait PdMessage { #[async_trait] impl PdMessage for pdpb::GetRegionRequest { type Response = pdpb::GetRegionResponse; + type Client = pdpb::PdClient; async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { client.get_region_async_opt(self, opt)?.await @@ -297,6 +306,7 @@ impl PdMessage for pdpb::GetRegionRequest { #[async_trait] impl PdMessage for pdpb::GetRegionByIdRequest { type Response = pdpb::GetRegionResponse; + type Client = pdpb::PdClient; async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { client.get_region_by_id_async_opt(self, opt)?.await @@ -306,6 +316,7 @@ impl PdMessage for pdpb::GetRegionByIdRequest { #[async_trait] impl PdMessage for pdpb::GetStoreRequest { type Response = pdpb::GetStoreResponse; + type Client = pdpb::PdClient; async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { client.get_store_async_opt(self, opt)?.await @@ -315,6 +326,7 @@ impl PdMessage for pdpb::GetStoreRequest { #[async_trait] impl PdMessage for pdpb::GetAllStoresRequest { type Response = pdpb::GetAllStoresResponse; + type Client = pdpb::PdClient; async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { client.get_all_stores_async_opt(self, opt)?.await @@ -324,12 +336,24 @@ impl PdMessage for pdpb::GetAllStoresRequest { #[async_trait] impl PdMessage for pdpb::UpdateGcSafePointRequest { type Response = pdpb::UpdateGcSafePointResponse; + type Client = pdpb::PdClient; async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { client.update_gc_safe_point_async_opt(self, opt)?.await } } +#[async_trait] +impl PdMessage for keyspacepb::LoadKeyspaceRequest { + type Response = keyspacepb::LoadKeyspaceResponse; + type Client = pdpb::PdClient; + + async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { + unimplemented!() + // client.load_keyspace_async_opt(self, opt)?.await + } +} + trait PdResponse { fn header(&self) -> &pdpb::ResponseHeader; } @@ -357,3 +381,9 @@ impl PdResponse for pdpb::UpdateGcSafePointResponse { self.get_header() } } + +impl PdResponse for keyspacepb::LoadKeyspaceResponse { + fn header(&self) -> &pdpb::ResponseHeader { + self.get_header() + } +} From 3819c8a58bc85a151c4e65242305fa04cc6d9274 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 22 Jul 2022 03:03:33 +0800 Subject: [PATCH 40/43] introduce keyspace mgr from keyspace service Signed-off-by: iosmanthus --- examples/pessimistic.rs | 2 +- examples/raw.rs | 2 +- examples/transaction.rs | 2 +- src/lib.rs | 6 +- src/mock.rs | 2 +- src/pd/client.rs | 21 +++-- src/pd/retry.rs | 15 ++-- src/raw/client.rs | 143 +++++++++++++++++++++---------- src/region_cache.rs | 9 +- src/request/codec.rs | 59 ++++++++++++- src/transaction/client.rs | 112 ++++++++++++++++++------ src/transaction/transaction.rs | 28 +++--- src/util/client.rs | 45 ++++++++++ src/util/mod.rs | 1 + tests/common/mod.rs | 4 +- tests/failpoint_tests.rs | 2 +- tests/integration_tests.rs | 47 +++++----- tests/mock_tikv_tests.rs | 10 +-- tikv-client-common/src/errors.rs | 4 + tikv-client-pd/src/cluster.rs | 105 +++++++++++++++++------ 20 files changed, 444 insertions(+), 175 deletions(-) create mode 100644 src/util/client.rs diff --git a/examples/pessimistic.rs b/examples/pessimistic.rs index 15a69dea..565942c1 100644 --- a/examples/pessimistic.rs +++ b/examples/pessimistic.rs @@ -23,7 +23,7 @@ async fn main() { }; // init - let client = Client::new_with_config(args.pd, config, ApiV1::default(), None) + let client = Client::::new_with_config(args.pd, config, None) .await .expect("Could not connect to tikv"); diff --git a/examples/raw.rs b/examples/raw.rs index 673aa45c..00eb59a5 100644 --- a/examples/raw.rs +++ b/examples/raw.rs @@ -28,7 +28,7 @@ async fn main() -> Result<()> { // When we first create a client we receive a `Connect` structure which must be resolved before // the client is actually connected and usable. - let client = Client::new_with_config(args.pd, config, ApiV1::default(), None).await?; + let client = Client::::new_with_config(args.pd, config, None).await?; // Requests are created from the connected client. These calls return structures which // implement `Future`. This means the `Future` must be resolved before the action ever takes diff --git a/examples/transaction.rs b/examples/transaction.rs index 4b040ca0..6aff1179 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -84,7 +84,7 @@ async fn main() { Config::default() }; - let txn = Client::new_with_config(args.pd, config, ApiV1::default(), None) + let txn = Client::::new_with_config(args.pd, config, None) .await .expect("Could not connect to tikv"); diff --git a/src/lib.rs b/src/lib.rs index 4a579aac..eedc2f6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,7 +68,7 @@ //! # fn main() -> Result<()> { //! # use tikv_client::raw::ApiV1; //! futures::executor::block_on(async { -//! let client = RawClient::new(vec!["127.0.0.1:2379"], ApiV1::default(), None).await?; +//! let client = RawClient::::new(vec!["127.0.0.1:2379"], None).await?; //! client.put("key".to_owned(), "value".to_owned()).await?; //! let value = client.get("key".to_owned()).await?; //! # Ok(()) @@ -83,7 +83,7 @@ //! # fn main() -> Result<()> { //! # use tikv_client::transaction::ApiV1; //! futures::executor::block_on(async { -//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"], ApiV1::default(), None).await?; +//! let txn_client = TransactionClient::::new(vec!["127.0.0.1:2379"], None).await?; //! let mut txn = txn_client.begin_optimistic().await?; //! txn.put("key".to_owned(), "value".to_owned()).await?; //! let value = txn.get("key".to_owned()).await?; @@ -94,6 +94,8 @@ #![feature(min_specialization)] #![feature(core_intrinsics)] +#![feature(async_closure)] +#![feature(get_mut_unchecked)] #[macro_use] pub mod request; diff --git a/src/mock.rs b/src/mock.rs index d0c8e3cb..cf313496 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -42,7 +42,7 @@ pub async fn pd_rpc_client() -> PdRpcClient { MockCluster, )) }, - ApiV1::default(), + async move |_| Ok(ApiV1::default()), logger, ) .await diff --git a/src/pd/client.rs b/src/pd/client.rs index 021f20f4..acdd3779 100644 --- a/src/pd/client.rs +++ b/src/pd/client.rs @@ -254,19 +254,23 @@ impl PdClient for PdRpc } impl PdRpcClient { - pub async fn connect( + pub async fn connect( pd_endpoints: &[String], config: Config, - codec: C, + codec_factory: F, logger: Logger, - ) -> Result> { + ) -> Result> + where + F: Fn(Arc) -> Fut, + Fut: Future>, + { PdRpcClient::new( config.clone(), |env, security_mgr| TikvConnect::new(env, security_mgr, config.timeout), |env, security_mgr| { RetryClient::connect(env, pd_endpoints, security_mgr, config.timeout) }, - codec, + codec_factory, logger, ) .await @@ -283,17 +287,19 @@ fn thread_name(prefix: &str) -> String { } impl PdRpcClient { - pub async fn new( + pub async fn new( config: Config, kv_connect: MakeKvC, pd: MakePd, - codec: C, + codec: MakeCodec, logger: Logger, ) -> Result> where PdFut: Future>>, MakeKvC: FnOnce(Arc, Arc) -> KvC, MakePd: FnOnce(Arc, Arc) -> PdFut, + MakeCodec: Fn(Arc>) -> CodecFut, + CodecFut: Future>, { let env = Arc::new( EnvBuilder::new() @@ -313,11 +319,12 @@ impl PdRpcClient { let pd = Arc::new(pd(env.clone(), security_mgr.clone()).await?); let kv_client_cache = Default::default(); + Ok(PdRpcClient { pd: pd.clone(), kv_client_cache, kv_connect: kv_connect(env, security_mgr), - region_cache: RegionCache::new(codec, pd), + region_cache: RegionCache::new(codec(pd.clone()).await?, pd), logger, }) } diff --git a/src/pd/retry.rs b/src/pd/retry.rs index cbe5fecb..9b743aa1 100644 --- a/src/pd/retry.rs +++ b/src/pd/retry.rs @@ -17,9 +17,8 @@ use std::{ }; use tikv_client_pd::{Cluster, Connection}; use tikv_client_proto::{ - metapb, + keyspacepb, metapb, pdpb::{self, Timestamp}, - keyspacepb }; use tokio::sync::RwLock; @@ -45,7 +44,8 @@ pub trait RetryClientTrait { async fn update_safepoint(self: Arc, safepoint: u64) -> Result; - async fn load_keyspace + Send>(self: Arc, name: T) -> Result; + async fn load_keyspace(self: Arc, name: &str) + -> Result; } /// Client for communication with a PD cluster. Has the facility to reconnect to the cluster. pub struct RetryClient { @@ -186,11 +186,12 @@ impl RetryClientTrait for RetryClient { }) } - async fn load_keyspace + Send>(self: Arc, name: T) -> Result { + async fn load_keyspace( + self: Arc, + name: &str, + ) -> Result { retry!(self, "load_keyspace", |cluster| async { - cluster - .load_keyspace(name, self.timeout) - .await + cluster.load_keyspace(name.to_string(), self.timeout).await }) } } diff --git a/src/raw/client.rs b/src/raw/client.rs index 37538dbf..9015840d 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -1,9 +1,9 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use core::ops::Range; -use std::{marker::PhantomData, str::FromStr, sync::Arc, u32}; +use std::{future::Future, marker::PhantomData, str::FromStr, sync::Arc, u32}; -use slog::{Drain, Logger}; +use slog::Logger; use tikv_client_common::Error; use tikv_client_proto::metapb; @@ -11,9 +11,10 @@ use tikv_client_proto::metapb; use crate::{ backoff::DEFAULT_REGION_BACKOFF, config::Config, - pd::{PdClient, PdRpcClient}, - raw::lowering::*, + pd::{PdClient, PdRpcClient, RetryClient}, + raw::{lowering::*, ApiV2}, request::{codec::RawCodec, Collect, CollectSingle, Plan}, + util::client::ClientContext, Backoff, BoundRange, ColumnFamily, Key, KvPair, Result, Value, }; @@ -47,6 +48,55 @@ impl Clone for Client { } } +impl Client { + /// Create a raw [`Client`] and connect to the TiKV cluster, with `keyspace` name. + /// + /// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for + /// PD must be provided, not the TiKV nodes. It's important to include more than one PD endpoint + /// (include all endpoints, if possible), this helps avoid having a single point of failure. + /// + /// # Examples + /// + /// ```rust,no_run + /// # use tikv_client::{Config, RawClient}; + /// # use futures::prelude::*; + /// use tikv_client::raw::ApiV2; + /// # futures::executor::block_on(async { + /// let client = RawClient::::new_with_keyspace( + /// vec!["192.168.0.100"], + /// "space_for_raw", + /// Config::default(), + /// None, + /// ) + /// .await + /// .unwrap(); + /// # }); + /// ``` + pub async fn new_with_keyspace( + pd_endpoints: Vec, + keyspace: K, + config: Config, + optional_logger: Option, + ) -> Result + where + S: Into, + K: Into, + { + let keyspace = &keyspace.into(); + let this = Self::new_with_codec_factory( + pd_endpoints, + config, + async move |pd| ApiV2::with_keyspace(keyspace, pd).await, + optional_logger, + ) + .await?; + + info!(this.logger, "created raw client"; "keyspace" => keyspace); + + Ok(this) + } +} + impl Client { /// Create a raw [`Client`] and connect to the TiKV cluster. /// @@ -61,17 +111,16 @@ impl Client { /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = RawClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// # }); /// ``` pub async fn new>( pd_endpoints: Vec, - codec: C, logger: Option, ) -> Result { - Self::new_with_config(pd_endpoints, Config::default(), codec, logger).await + Self::new_with_config(pd_endpoints, Config::default(), logger).await } /// Create a raw [`Client`] with a custom configuration, and connect to the TiKV cluster. @@ -88,10 +137,9 @@ impl Client { /// # use std::time::Duration; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new_with_config( + /// let client = RawClient::::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), - /// ApiV1::default(), /// None, /// ) /// .await @@ -101,30 +149,15 @@ impl Client { pub async fn new_with_config>( pd_endpoints: Vec, config: Config, - codec: C, optional_logger: Option, ) -> Result { - let logger = optional_logger.unwrap_or_else(|| { - let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); - Logger::root( - slog_term::FullFormat::new(plain) - .build() - .filter_level(slog::Level::Info) - .fuse(), - o!(), - ) - }); - debug!(logger, "creating new raw client"); - let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); - let rpc = - Arc::new(PdRpcClient::connect(&pd_endpoints, config, codec, logger.clone()).await?); - Ok(Client { - rpc, - cf: None, - atomic: false, - logger, - _phantom: PhantomData, - }) + Self::new_with_codec_factory( + pd_endpoints, + config, + async move |_| Ok(C::default()), + optional_logger, + ) + .await } /// Create a new client which is a clone of `self`, but which uses an explicit column family for @@ -144,7 +177,7 @@ impl Client { /// # use std::convert::TryInto; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = RawClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap() /// .with_cf(ColumnFamily::Write); @@ -180,6 +213,29 @@ impl Client { _phantom: PhantomData, } } + + async fn new_with_codec_factory( + pd_endpoints: Vec, + config: Config, + codec_factory: F, + optional_logger: Option, + ) -> Result + where + S: Into, + F: Fn(Arc) -> Fut, + Fut: Future>, + { + let ClientContext { pd: rpc, logger } = + ClientContext::new(pd_endpoints, config, codec_factory, optional_logger).await?; + + Ok(Client { + rpc, + cf: None, + atomic: false, + logger, + _phantom: PhantomData, + }) + } } impl Client @@ -200,7 +256,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.get(key); /// let result: Option = req.await.unwrap(); @@ -235,7 +291,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_get(keys); /// let result: Vec = req.await.unwrap(); @@ -275,7 +331,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let val = "TiKV".to_owned(); /// let req = client.put(key, val); @@ -314,7 +370,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let kvpair1 = ("PD".to_owned(), "Go".to_owned()); /// let kvpair2 = ("TiKV".to_owned(), "Rust".to_owned()); /// let iterable = vec![kvpair1, kvpair2]; @@ -361,7 +417,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let key = "TiKV".to_owned(); /// let req = client.delete(key); /// let result: () = req.await.unwrap(); @@ -396,7 +452,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let req = client.batch_delete(keys); /// let result: () = req.await.unwrap(); @@ -434,7 +490,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.delete_range(inclusive_range.into_owned()); /// let result: () = req.await.unwrap(); @@ -475,7 +531,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -510,7 +566,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let inclusive_range = "TiKV"..="TiDB"; /// let req = client.scan_keys(inclusive_range.into_owned(), 2); /// let result: Vec = req.await.unwrap(); @@ -553,7 +609,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; @@ -598,7 +654,7 @@ where /// # use futures::prelude::*; /// use tikv_client::raw::ApiV1; /// # futures::executor::block_on(async { - /// # let client = RawClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = RawClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let inclusive_range1 = "TiDB"..="TiKV"; /// let inclusive_range2 = "TiKV"..="TiSpark"; /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; @@ -783,6 +839,7 @@ where #[cfg(test)] mod tests { + use slog::Drain; use std::{any::Any, sync::Arc}; use tikv_client_proto::kvrpcpb; diff --git a/src/region_cache.rs b/src/region_cache.rs index 7028d5d2..c7ab43d8 100644 --- a/src/region_cache.rs +++ b/src/region_cache.rs @@ -258,7 +258,7 @@ mod test { use tokio::sync::Mutex; use tikv_client_common::Error; - use tikv_client_proto::metapb; + use tikv_client_proto::{keyspacepb, metapb}; use crate::{ pd::RetryClientTrait, @@ -326,6 +326,13 @@ mod test { async fn update_safepoint(self: Arc, _safepoint: u64) -> Result { todo!() } + + async fn load_keyspace( + self: Arc, + _name: &str, + ) -> Result { + todo!() + } } #[tokio::test] diff --git a/src/request/codec.rs b/src/request/codec.rs index d90c3f22..8a6b3836 100644 --- a/src/request/codec.rs +++ b/src/request/codec.rs @@ -3,18 +3,24 @@ use std::{ borrow::Cow, marker::PhantomData, ops::{Deref, DerefMut}, + sync::Arc, }; use tikv_client_common::Error; -use tikv_client_proto::{errorpb, kvrpcpb, metapb::Region}; +use tikv_client_proto::{errorpb, keyspacepb, kvrpcpb, metapb::Region}; use crate::{kv::codec::decode_bytes_in_place, request::KvRequest, Key, Result}; +use crate::pd::{RetryClient, RetryClientTrait}; +use derive_new::new; + type Prefix = [u8; KEYSPACE_PREFIX_LEN]; const KEYSPACE_PREFIX_LEN: usize = 4; -pub trait RequestCodec: Sized + Clone + Sync + Send + 'static { +pub const DEFAULT_KEYSPACE: &str = "DEFAULT"; + +pub trait RequestCodec: Default + Sized + Clone + Sync + Send + 'static { fn encode_request<'a, R: KvRequest>(&self, req: &'a R) -> Cow<'a, R> { Cow::Borrowed(req) } @@ -201,7 +207,7 @@ pub trait RawCodec: RequestCodec {} pub trait TxnCodec: RequestCodec {} -#[derive(Clone, Copy, Default, PartialEq, Eq)] +#[derive(new, Clone, Copy, Default, PartialEq, Eq)] pub struct KeySpaceId([u8; 3]); impl Deref for KeySpaceId { @@ -218,6 +224,25 @@ impl DerefMut for KeySpaceId { } } +impl KeySpaceId { + pub async fn from_name(name: &str, pd: Arc) -> Result { + if name == DEFAULT_KEYSPACE { + return Ok(KeySpaceId::default()); + } + + let resp = pd.load_keyspace(name).await?; + let keyspace = resp.get_keyspace(); + if keyspace.get_state() == keyspacepb::KeyspaceState::Enabled { + let id = keyspace.get_id().to_be_bytes(); + Ok(KeySpaceId::new([id[1], id[2], id[3]])) + } else { + Err(Error::KeyspaceNotEnabled { + name: name.to_string(), + }) + } + } +} + pub trait Mode: Clone + Copy + Sync + Send + 'static { const PREFIX: u8; const MIN_KEY: &'static [u8] = &[Self::PREFIX, 0, 0, 0]; @@ -276,6 +301,15 @@ pub struct KeySpace { _phantom: PhantomData, } +impl KeySpace { + pub fn new(id: KeySpaceId) -> Self { + KeySpace { + id, + _phantom: PhantomData, + } + } +} + impl Default for KeySpace { fn default() -> Self { KeySpace { @@ -301,11 +335,28 @@ impl KeySpace { } } -#[derive(Default, Clone)] +#[derive(Clone)] pub struct ApiV2 { keyspace: KeySpace, } +impl ApiV2 { + pub async fn with_keyspace(name: &str, pd: Arc) -> Result { + let id = KeySpaceId::from_name(name, pd).await?; + Ok(ApiV2 { + keyspace: KeySpace::new(id), + }) + } +} + +impl Default for ApiV2 { + fn default() -> Self { + ApiV2 { + keyspace: KeySpace::default(), + } + } +} + impl RequestCodec for ApiV2 { fn encode_request<'a, R: KvRequest>(&self, req: &'a R) -> Cow<'a, R> { let mut req = req.clone(); diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 28d89c05..3ab9232d 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -1,18 +1,19 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::{marker::PhantomData, mem, sync::Arc}; +use std::{future::Future, marker::PhantomData, mem, sync::Arc}; -use slog::{Drain, Logger}; +use slog::Logger; use tikv_client_proto::{kvrpcpb, pdpb::Timestamp}; use crate::{ backoff::{DEFAULT_REGION_BACKOFF, OPTIMISTIC_BACKOFF}, config::Config, - pd::{PdClient, PdRpcClient}, + pd::{PdClient, PdRpcClient, RetryClient}, request::{codec::TxnCodec, Plan}, timestamp::TimestampExt, - transaction::{Snapshot, Transaction, TransactionOptions}, + transaction::{ApiV2, Snapshot, Transaction, TransactionOptions}, + util::client::ClientContext, Result, }; @@ -53,6 +54,55 @@ impl Clone for Client { } } +impl Client { + /// Create a transaction [`Client`] and connect to the TiKV cluster, with `keyspace` name. + /// + /// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for + /// PD must be provided, not the TiKV nodes. It's important to include more than one PD endpoint + /// (include all endpoints, if possible), this helps avoid having a single point of failure. + /// + /// # Examples + /// + /// ```rust,no_run + /// # use tikv_client::{Config, TransactionClient}; + /// # use futures::prelude::*; + /// use tikv_client::transaction::ApiV2; + /// # futures::executor::block_on(async { + /// let client = TransactionClient::::new_with_keyspace( + /// vec!["192.168.0.100"], + /// "space_for_txn", + /// Config::default(), + /// None, + /// ) + /// .await + /// .unwrap(); + /// # }); + /// ``` + pub async fn new_with_keyspace( + pd_endpoints: Vec, + keyspace: K, + config: Config, + optional_logger: Option, + ) -> Result + where + S: Into, + K: Into, + { + let keyspace = &keyspace.into(); + let this = Self::new_with_codec_factory( + pd_endpoints, + config, + async move |pd| ApiV2::with_keyspace(keyspace, pd).await, + optional_logger, + ) + .await?; + + info!(this.logger, "created transaction client"; "keyspace" => keyspace); + + Ok(this) + } +} + impl Client where C: TxnCodec, @@ -70,18 +120,17 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = TransactionClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// # }); /// ``` pub async fn new>( pd_endpoints: Vec, - codec: C, logger: Option, ) -> Result> { // debug!(self.logger, "creating transactional client"); - Self::new_with_config(pd_endpoints, Config::default(), codec, logger).await + Self::new_with_config(pd_endpoints, Config::default(), logger).await } /// Create a transactional [`Client`] with a custom configuration, and connect to the TiKV cluster. @@ -98,10 +147,9 @@ where /// # use std::time::Duration; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new_with_config( + /// let client = TransactionClient::::new_with_config( /// vec!["192.168.0.100"], /// Config::default().with_timeout(Duration::from_secs(60)), - /// ApiV1::default(), /// None, /// ) /// .await @@ -111,23 +159,31 @@ where pub async fn new_with_config>( pd_endpoints: Vec, config: Config, - codec: C, optional_logger: Option, ) -> Result> { - let logger = optional_logger.unwrap_or_else(|| { - let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); - Logger::root( - slog_term::FullFormat::new(plain) - .build() - .filter_level(slog::Level::Info) - .fuse(), - o!(), - ) - }); - debug!(logger, "creating new transactional client"); - let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); - let pd = - Arc::new(PdRpcClient::connect(&pd_endpoints, config, codec, logger.clone()).await?); + Self::new_with_codec_factory( + pd_endpoints, + config, + async move |_| Ok(C::default()), + optional_logger, + ) + .await + } + + pub async fn new_with_codec_factory( + pd_endpoints: Vec, + config: Config, + codec_factory: F, + optional_logger: Option, + ) -> Result> + where + S: Into, + F: Fn(Arc) -> Fut, + Fut: Future>, + { + let ClientContext { pd, logger } = + ClientContext::new(pd_endpoints, config, codec_factory, optional_logger).await?; + Ok(Client { pd, logger, @@ -150,7 +206,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = TransactionClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// let mut transaction = client.begin_optimistic().await.unwrap(); @@ -176,7 +232,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = TransactionClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// let mut transaction = client.begin_pessimistic().await.unwrap(); @@ -199,7 +255,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = TransactionClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// let mut transaction = client @@ -232,7 +288,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) + /// let client = TransactionClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// let timestamp = client.current_timestamp().await.unwrap(); diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 988a1e8c..627ec88e 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -54,7 +54,7 @@ use crate::{ /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { -/// let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None) +/// let client = TransactionClient::::new(vec!["192.168.0.100"], None) /// .await /// .unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); @@ -117,7 +117,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Option = txn.get(key).await.unwrap(); @@ -179,7 +179,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let key = "TiKV".to_owned(); /// let result: Value = txn.get_for_update(key).await.unwrap().unwrap(); @@ -214,7 +214,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let exists = txn.key_exists("k1".to_owned()).await.unwrap(); /// txn.commit().await.unwrap(); @@ -242,7 +242,7 @@ where /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; /// let result: HashMap = txn @@ -296,7 +296,7 @@ where /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_pessimistic().await.unwrap(); /// let keys = vec!["foo".to_owned(), "bar".to_owned()]; /// let result: Vec = txn @@ -342,7 +342,7 @@ where /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -379,7 +379,7 @@ where /// # use std::collections::HashMap; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key1: Key = b"foo".to_vec().into(); /// let key2: Key = b"bar".to_vec().into(); @@ -443,7 +443,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -475,7 +475,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// let val = "FOO".to_owned(); @@ -512,7 +512,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100", "192.168.0.101"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// let key = "foo".to_owned(); /// txn.delete(key); @@ -548,7 +548,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// txn.lock_keys(vec!["TiKV".to_owned(), "Rust".to_owned()]); /// // ... Do some actions. @@ -585,7 +585,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// let result: Timestamp = txn.commit().await.unwrap().unwrap(); @@ -644,7 +644,7 @@ where /// # use futures::prelude::*; /// use tikv_client::transaction::ApiV1; /// # futures::executor::block_on(async { - /// # let client = TransactionClient::new(vec!["192.168.0.100"], ApiV1::default(), None).await.unwrap(); + /// # let client = TransactionClient::::new(vec!["192.168.0.100"], None).await.unwrap(); /// let mut txn = client.begin_optimistic().await.unwrap(); /// // ... Do some actions. /// txn.rollback().await.unwrap(); diff --git a/src/util/client.rs b/src/util/client.rs new file mode 100644 index 00000000..4235b580 --- /dev/null +++ b/src/util/client.rs @@ -0,0 +1,45 @@ +use std::{future::Future, sync::Arc}; + +use slog::{Drain, Logger}; + +use crate::{ + pd::{PdRpcClient, RetryClient}, + Config, Result, +}; + +pub(crate) struct ClientContext { + pub logger: Logger, + pub pd: Arc>, +} + +impl ClientContext { + pub async fn new( + pd_endpoints: Vec, + config: Config, + codec_factory: F, + optional_logger: Option, + ) -> Result + where + S: Into, + F: Fn(Arc) -> Fut, + Fut: Future>, + { + let logger = optional_logger.unwrap_or_else(|| { + let plain = slog_term::PlainSyncDecorator::new(std::io::stdout()); + Logger::root( + slog_term::FullFormat::new(plain) + .build() + .filter_level(slog::Level::Info) + .fuse(), + o!(), + ) + }); + + let pd_endpoints: Vec = pd_endpoints.into_iter().map(Into::into).collect(); + let pd = Arc::new( + PdRpcClient::connect(&pd_endpoints, config, codec_factory, logger.clone()).await?, + ); + + Ok(ClientContext { pd, logger }) + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 6d3bf763..3282a7ef 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ // Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0. +pub mod client; pub mod iter; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 497e22f3..39c139f0 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -19,7 +19,7 @@ pub async fn clear_tikv() { // DEFAULT_REGION_BACKOFF is not long enough for CI environment. So set a longer backoff. let backoff = tikv_client::Backoff::no_jitter_backoff(100, 10000, 10); for cf in cfs { - let raw_client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None) + let raw_client = RawClient::::new(pd_addrs(), None) .await .unwrap() .with_cf(cf); @@ -63,7 +63,7 @@ async fn ensure_region_split( // 1. write plenty transactional keys // 2. wait until regions split - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut txn = client.begin_optimistic().await?; for key in keys.into_iter() { txn.put(key.into(), vec![0, 0, 0, 0]).await?; diff --git a/tests/failpoint_tests.rs b/tests/failpoint_tests.rs index 67061175..68524412 100644 --- a/tests/failpoint_tests.rs +++ b/tests/failpoint_tests.rs @@ -19,7 +19,7 @@ async fn txn_optimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut heartbeat_txn = client .begin_with_options( diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 33a3a6c7..a51ced4a 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -37,7 +37,7 @@ const NUM_TRNASFER: u32 = 100; #[serial] async fn txn_get_timestamp() -> Result<()> { const COUNT: usize = 1 << 8; // use a small number to make test fast - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut versions = future::join_all((0..COUNT).map(|_| client.current_timestamp())) .await @@ -58,7 +58,7 @@ async fn txn_get_timestamp() -> Result<()> { async fn txn_crud() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut txn = client.begin_optimistic().await?; // Get non-existent keys @@ -142,7 +142,7 @@ async fn txn_crud() -> Result<()> { async fn txn_insert_duplicate_keys() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; // Initialize TiKV store with {foo => bar} let mut txn = client.begin_optimistic().await?; txn.put("foo".to_owned(), "bar".to_owned()).await?; @@ -166,7 +166,7 @@ async fn txn_insert_duplicate_keys() -> Result<()> { async fn txn_pessimistic() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut txn = client.begin_pessimistic().await?; txn.put("foo".to_owned(), "foo".to_owned()).await.unwrap(); @@ -183,7 +183,7 @@ async fn txn_pessimistic() -> Result<()> { #[serial] async fn raw_bank_transfer() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; + let client = RawClient::::new(pd_addrs(), None).await?; let mut rng = thread_rng(); let people = gen_u32_keys(NUM_PEOPLE, &mut rng); @@ -235,7 +235,7 @@ async fn txn_read() -> Result<()> { let value = "large_value".repeat(10); init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -327,7 +327,7 @@ async fn txn_read() -> Result<()> { #[serial] async fn txn_bank_transfer() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut rng = thread_rng(); let options = TransactionOptions::new_optimistic() .use_async_commit() @@ -380,7 +380,7 @@ async fn txn_bank_transfer() -> Result<()> { #[serial] async fn raw_req() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; + let client = RawClient::::new(pd_addrs(), None).await?; // empty; get non-existent key let res = client.get("k1".to_owned()).await; @@ -510,7 +510,7 @@ async fn raw_req() -> Result<()> { #[serial] async fn txn_update_safepoint() -> Result<()> { init().await?; - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let res = client.gc(client.current_timestamp().await?).await?; assert!(res); Ok(()) @@ -525,7 +525,7 @@ async fn raw_write_million() -> Result<()> { let interval = 2u32.pow(32 - NUM_BITS_TXN - NUM_BITS_KEY_PER_TXN); init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; + let client = RawClient::::new(pd_addrs(), None).await?; for i in 0..2u32.pow(NUM_BITS_TXN) { let mut cur = i * 2u32.pow(32 - NUM_BITS_TXN); @@ -571,10 +571,9 @@ async fn raw_write_million() -> Result<()> { #[serial] async fn txn_pessimistic_rollback() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1::default(), None, ) .await?; @@ -609,10 +608,9 @@ async fn txn_pessimistic_rollback() -> Result<()> { #[serial] async fn txn_pessimistic_delete() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( vec!["127.0.0.1:2379"], Default::default(), - transaction::ApiV1::default(), None, ) .await?; @@ -657,10 +655,9 @@ async fn txn_pessimistic_delete() -> Result<()> { #[serial] async fn txn_lock_keys() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1::default(), None, ) .await?; @@ -697,10 +694,9 @@ async fn txn_lock_keys() -> Result<()> { #[serial] async fn txn_lock_keys_error_handle() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1::default(), None, ) .await?; @@ -740,10 +736,9 @@ async fn txn_lock_keys_error_handle() -> Result<()> { #[serial] async fn txn_get_for_update() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1::default(), None, ) .await?; @@ -793,7 +788,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { let key1 = "key1".to_owned(); let key2 = "key2".to_owned(); - let client = TransactionClient::new(pd_addrs(), transaction::ApiV1::default(), None).await?; + let client = TransactionClient::::new(pd_addrs(), None).await?; let mut heartbeat_txn = client .begin_with_options(TransactionOptions::new_pessimistic()) @@ -833,7 +828,7 @@ async fn txn_pessimistic_heartbeat() -> Result<()> { #[serial] async fn raw_cas() -> Result<()> { init().await?; - let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None) + let client = RawClient::::new(pd_addrs(), None) .await? .with_atomic_for_cas(); let key = "key".to_owned(); @@ -878,7 +873,7 @@ async fn raw_cas() -> Result<()> { client.batch_delete(vec![key.clone()]).await.err().unwrap(), Error::UnsupportedMode )); - let client = RawClient::new(pd_addrs(), raw::ApiV1::default(), None).await?; + let client = RawClient::::new(pd_addrs(), None).await?; assert!(matches!( client .compare_and_swap(key.clone(), None, vec![]) @@ -895,10 +890,9 @@ async fn raw_cas() -> Result<()> { #[serial] async fn txn_scan() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1::default(), None, ) .await?; @@ -924,10 +918,9 @@ async fn txn_scan() -> Result<()> { #[serial] async fn txn_scan_reverse() -> Result<()> { init().await?; - let client = TransactionClient::new_with_config( + let client = TransactionClient::::new_with_config( pd_addrs(), Default::default(), - transaction::ApiV1::default(), None, ) .await?; diff --git a/tests/mock_tikv_tests.rs b/tests/mock_tikv_tests.rs index 411f28d7..a855eab4 100644 --- a/tests/mock_tikv_tests.rs +++ b/tests/mock_tikv_tests.rs @@ -15,13 +15,9 @@ mod test { let mut tikv_server = start_mock_tikv_server(); let _pd_server = start_mock_pd_server(); - let client = RawClient::new( - vec![format!("localhost:{}", MOCK_PD_PORT)], - ApiV1::default(), - None, - ) - .await - .unwrap(); + let client = RawClient::::new(vec![format!("localhost:{}", MOCK_PD_PORT)], None) + .await + .unwrap(); // empty; get non-existent key let res = client.get("k1".to_owned()).await; diff --git a/tikv-client-common/src/errors.rs b/tikv-client-common/src/errors.rs index 57fff3ae..97ddb6e8 100644 --- a/tikv-client-common/src/errors.rs +++ b/tikv-client-common/src/errors.rs @@ -95,6 +95,10 @@ pub enum Error { }, #[error("Corrupted keyspace: expected: {:?}, key: {:?}", expected, key)] CorruptedKeyspace { expected: Vec, key: Vec }, + #[error("Keyspace is unsupported in the cluster")] + KeyspaceUnsupported, + #[error("Keyspace {} is not enabled", name)] + KeyspaceNotEnabled { name: String }, } impl From for Error { diff --git a/tikv-client-pd/src/cluster.rs b/tikv-client-pd/src/cluster.rs index 38b3872f..18d2c9f7 100644 --- a/tikv-client-pd/src/cluster.rs +++ b/tikv-client-pd/src/cluster.rs @@ -2,15 +2,17 @@ use crate::{timestamp::TimestampOracle, Error, Result, SecurityManager}; use async_trait::async_trait; -use grpcio::{CallOption, Environment}; +use grpcio::{CallOption, Environment, RpcStatusCode}; use std::{ collections::HashSet, sync::Arc, time::{Duration, Instant}, }; use tikv_client_common::internal_err; -use tikv_client_proto::pdpb::{self, Timestamp}; -use tikv_client_proto::keyspacepb; +use tikv_client_proto::{ + keyspacepb, + pdpb::{self, Timestamp}, +}; /// A PD cluster. pub struct Cluster { @@ -18,6 +20,7 @@ pub struct Cluster { client: pdpb::PdClient, members: pdpb::GetMembersResponse, tso: TimestampOracle, + keyspace_mgr: Option, } macro_rules! pd_request { @@ -77,13 +80,27 @@ impl Cluster { req.send(&self.client, timeout).await } - pub async fn load_keyspace>(&self, name: T, timeout: Duration) -> Result { + pub async fn load_keyspace( + &self, + name: String, + timeout: Duration, + ) -> Result { let mut req = pd_request!(self.id, keyspacepb::LoadKeyspaceRequest); - req.set_name(name.as_ref().to_owned()); - req.send(&self.client, timeout).await + let mgr = self + .keyspace_mgr + .as_ref() + .ok_or(Error::KeyspaceUnsupported)?; + req.set_name(name); + req.send(mgr, timeout).await } } +struct ConnectResponse { + client: pdpb::PdClient, + members: pdpb::GetMembersResponse, + keyspace_mgr: Option, +} + /// An object for connecting and reconnecting to a PD cluster. pub struct Connection { env: Arc, @@ -101,7 +118,11 @@ impl Connection { timeout: Duration, ) -> Result { let members = self.validate_endpoints(endpoints, timeout).await?; - let (client, members) = self.try_connect_leader(&members, timeout).await?; + let ConnectResponse { + client, + members, + keyspace_mgr, + } = self.try_connect_leader(&members, timeout).await?; let id = members.get_header().get_cluster_id(); let tso = TimestampOracle::new(id, &client)?; let cluster = Cluster { @@ -109,6 +130,7 @@ impl Connection { client, members, tso, + keyspace_mgr, }; Ok(cluster) } @@ -117,13 +139,18 @@ impl Connection { pub async fn reconnect(&self, cluster: &mut Cluster, timeout: Duration) -> Result<()> { warn!("updating pd client"); let start = Instant::now(); - let (client, members) = self.try_connect_leader(&cluster.members, timeout).await?; + let ConnectResponse { + client, + members, + keyspace_mgr, + } = self.try_connect_leader(&cluster.members, timeout).await?; let tso = TimestampOracle::new(cluster.id, &client)?; *cluster = Cluster { id: cluster.id, client, members, tso, + keyspace_mgr, }; info!("updating PD client done, spent {:?}", start.elapsed()); @@ -144,8 +171,8 @@ impl Connection { return Err(internal_err!("duplicated PD endpoint {}", ep)); } - let (_, resp) = match self.connect(ep, timeout).await { - Ok(resp) => resp, + let resp = match self.connect(ep, timeout).await { + Ok(ConnectResponse { members, .. }) => members, // Ignore failed PD node. Err(e) => { warn!("PD endpoint {} failed to respond: {:?}", ep, e); @@ -182,20 +209,39 @@ impl Connection { } } - async fn connect( - &self, - addr: &str, - timeout: Duration, - ) -> Result<(pdpb::PdClient, pdpb::GetMembersResponse)> { + async fn connect(&self, addr: &str, timeout: Duration) -> Result { let client = self .security_mgr .connect(self.env.clone(), addr, pdpb::PdClient::new)?; + + let keyspace_mgr = self.connect_keyspace_mgr(addr)?; + let option = CallOption::default().timeout(timeout); - let resp = client + let members = client .get_members_async_opt(&pdpb::GetMembersRequest::default(), option) .map_err(Error::from)? .await?; - Ok((client, resp)) + + Ok(ConnectResponse { + client, + members, + keyspace_mgr, + }) + } + + fn connect_keyspace_mgr(&self, addr: &str) -> Result> { + let result = + self.security_mgr + .connect(self.env.clone(), addr, keyspacepb::KeyspaceClient::new); + match result { + Ok(mgr) => Ok(Some(mgr)), + Err(Error::Grpc(grpcio::Error::RpcFailure(status))) + if status.code() == RpcStatusCode::UNIMPLEMENTED => + { + Ok(None) + } + Err(e) => Err(e), + } } async fn try_connect( @@ -203,10 +249,10 @@ impl Connection { addr: &str, cluster_id: u64, timeout: Duration, - ) -> Result<(pdpb::PdClient, pdpb::GetMembersResponse)> { - let (client, r) = self.connect(addr, timeout).await?; - Connection::validate_cluster_id(addr, &r, cluster_id)?; - Ok((client, r)) + ) -> Result { + let connect_resp = self.connect(addr, timeout).await?; + Connection::validate_cluster_id(addr, &connect_resp.members, cluster_id)?; + Ok(connect_resp) } fn validate_cluster_id( @@ -231,7 +277,7 @@ impl Connection { &self, previous: &pdpb::GetMembersResponse, timeout: Duration, - ) -> Result<(pdpb::PdClient, pdpb::GetMembersResponse)> { + ) -> Result { let previous_leader = previous.get_leader(); let members = previous.get_members(); let cluster_id = previous.get_header().get_cluster_id(); @@ -245,8 +291,8 @@ impl Connection { { for ep in m.get_client_urls() { match self.try_connect(ep.as_str(), cluster_id, timeout).await { - Ok((_, r)) => { - resp = Some(r); + Ok(ConnectResponse { members, .. }) => { + resp = Some(members); break 'outer; } Err(e) => { @@ -346,11 +392,14 @@ impl PdMessage for pdpb::UpdateGcSafePointRequest { #[async_trait] impl PdMessage for keyspacepb::LoadKeyspaceRequest { type Response = keyspacepb::LoadKeyspaceResponse; - type Client = pdpb::PdClient; + type Client = keyspacepb::KeyspaceClient; - async fn rpc(&self, client: &pdpb::PdClient, opt: CallOption) -> GrpcResult { - unimplemented!() - // client.load_keyspace_async_opt(self, opt)?.await + async fn rpc( + &self, + client: &keyspacepb::KeyspaceClient, + opt: CallOption, + ) -> GrpcResult { + client.load_keyspace_async_opt(self, opt)?.await } } From a2047ebf85f3e478f8cec29b728dbe5637b78a9b Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 22 Jul 2022 11:11:51 +0800 Subject: [PATCH 41/43] fix clippy Signed-off-by: iosmanthus --- src/raw/client.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raw/client.rs b/src/raw/client.rs index 9015840d..fbc7d220 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -829,11 +829,11 @@ where } fn assert_non_atomic(&self) -> Result<()> { - (!self.atomic).then(|| ()).ok_or(Error::UnsupportedMode) + (!self.atomic).then_some(()).ok_or(Error::UnsupportedMode) } fn assert_atomic(&self) -> Result<()> { - self.atomic.then(|| ()).ok_or(Error::UnsupportedMode) + self.atomic.then_some(()).ok_or(Error::UnsupportedMode) } } From 45af3c5fb9ee6bca2bc80eab33180ec8332cf2c1 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 22 Jul 2022 11:17:56 +0800 Subject: [PATCH 42/43] refine trait bound of raw::Client Signed-off-by: iosmanthus --- src/raw/client.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/raw/client.rs b/src/raw/client.rs index fbc7d220..fbc9cdc1 100644 --- a/src/raw/client.rs +++ b/src/raw/client.rs @@ -27,7 +27,11 @@ const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240; /// /// The returned results of raw request methods are [`Future`](std::future::Future)s that must be /// awaited to execute. -pub struct Client> { +pub struct Client> +where + C: RawCodec, + PdC: PdClient, +{ rpc: Arc, cf: Option, /// Whether to use the [`atomic mode`](Client::with_atomic_for_cas). From 9de6f50b44b033a4b261b4bf7f7042ad7d7cac64 Mon Sep 17 00:00:00 2001 From: iosmanthus Date: Fri, 22 Jul 2022 11:23:42 +0800 Subject: [PATCH 43/43] remove phatom of txn::Client Signed-off-by: iosmanthus --- src/transaction/client.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 3ab9232d..750d859d 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -1,6 +1,6 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::{future::Future, marker::PhantomData, mem, sync::Arc}; +use std::{future::Future, mem, sync::Arc}; use slog::Logger; @@ -41,7 +41,6 @@ const SCAN_LOCK_BATCH_SIZE: u32 = 1024; pub struct Client { pd: Arc>, logger: Logger, - _phantom: PhantomData, } impl Clone for Client { @@ -49,7 +48,6 @@ impl Clone for Client { Self { pd: self.pd.clone(), logger: self.logger.clone(), - _phantom: PhantomData, } } } @@ -184,11 +182,7 @@ where let ClientContext { pd, logger } = ClientContext::new(pd_endpoints, config, codec_factory, optional_logger).await?; - Ok(Client { - pd, - logger, - _phantom: PhantomData, - }) + Ok(Client { pd, logger }) } /// Creates a new optimistic [`Transaction`].