diff --git a/src/lib.rs b/src/lib.rs index d1c6480c..2def7fbd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,7 +123,9 @@ pub use crate::backoff::Backoff; #[doc(inline)] pub use crate::kv::{BoundRange, IntoOwnedRange, Key, KvPair, Value}; #[doc(inline)] -pub use crate::raw::{lowering as raw_lowering, Client as RawClient, ColumnFamily}; +pub use crate::raw::{ + lowering as raw_lowering, Client as RawClient, ColumnFamily, SyncClient as SyncRawClient, +}; #[doc(inline)] pub use crate::request::RetryOptions; #[doc(inline)] diff --git a/src/raw/mod.rs b/src/raw/mod.rs index 3441fbbb..cf51fadb 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -9,13 +9,14 @@ //! //! **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, sync_client::SyncClient}; use crate::Error; use std::{convert::TryFrom, fmt}; mod client; pub mod lowering; mod requests; +mod sync_client; /// A [`ColumnFamily`](ColumnFamily) is an optional parameter for [`raw::Client`](Client) requests. /// diff --git a/src/raw/sync_client.rs b/src/raw/sync_client.rs new file mode 100644 index 00000000..87a6936c --- /dev/null +++ b/src/raw/sync_client.rs @@ -0,0 +1,276 @@ +// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. + +use crate::{ + config::Config, raw::client::Client, BoundRange, ColumnFamily, Key, KvPair, Result, Value, +}; +use slog::{Drain, Logger}; +use futures::executor::block_on; +use std::u32; + +#[derive(Clone)] +pub struct SyncClient { + client: Client, +} + +impl SyncClient { + /// The synchronous version of RawClient + /// + /// # Examples + /// + /// ```rust,no_run + /// # use tikv_client::SyncRawClient; + /// let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// ``` + pub fn new>(pd_endpoints: Vec, logger: Option) -> Result { + Self::new_with_config(pd_endpoints, Config::default(), logger) + } + + pub fn new_with_config>( + pd_endpoints: Vec, + config: Config, + logger: Option, + ) -> Result { + let client = block_on(Client::new_with_config(pd_endpoints, config, logger)).unwrap(); + Ok(SyncClient { client: client }) + } + + pub fn with_cf(&self, cf: ColumnFamily) -> SyncClient { + SyncClient { + client: self.client.with_cf(cf), + } + } + + pub fn with_atomic_for_cas(&self) -> SyncClient { + SyncClient { + client: self.client.with_atomic_for_cas(), + } + } + + /// Create a new 'get' request. + /// + /// Once resolved this request will result in the fetching of the value associated with the + /// given key. + /// + /// Retuning `Ok(None)` indicates the key does not exist in TiKV. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Value, Config, SyncRawClient}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let key = "TiKV".to_owned(); + /// let req = client.get(key); + /// let result: Option = req.unwrap(); + /// ``` + pub fn get(&self, key: impl Into) -> Result> { + block_on(self.client.get(key)) + } + + /// Create a new 'batch get' request. + /// + /// Once resolved this request will result in the fetching of the values associated with the + /// given keys. + /// + /// Non-existent entries will not appear in the result. The order of the keys is not retained in the result. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{KvPair, Config, SyncRawClient}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; + /// let req = client.batch_get(keys); + /// let result: Vec = req.unwrap(); + /// ``` + pub fn batch_get(&self, keys: impl IntoIterator>) -> Result> { + block_on(self.client.batch_get(keys)) + } + + /// Create a new 'put' request. + /// + /// Once resolved this request will result in the setting of the value associated with the given key. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Key, Value, Config, SyncRawClient}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let key = "TiKV".to_owned(); + /// let val = "TiKV".to_owned(); + /// let req = client.put(key, val); + /// let result: () = req.unwrap(); + /// ``` + pub fn put(&self, key: impl Into, value: impl Into) -> Result<()> { + block_on(self.client.put(key, value)) + } + + /// Create a new 'batch put' request. + /// + /// Once resolved this request will result in the setting of the values associated with the given keys. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Result, KvPair, Key, Value, Config, SyncRawClient, IntoOwnedRange}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let kvpair1 = ("PD".to_owned(), "Go".to_owned()); + /// let kvpair2 = ("TiKV".to_owned(), "Rust".to_owned()); + /// let iterable = vec![kvpair1, kvpair2]; + /// let req = client.batch_put(iterable); + /// let result: () = req.unwrap(); + /// ``` + pub fn batch_put(&self, pairs: impl IntoIterator>) -> Result<()> { + block_on(self.client.batch_put(pairs)) + } + + /// Create a new 'delete' request. + /// + /// Once resolved this request will result in the deletion of the given key. + /// + /// It does not return an error if the key does not exist in TiKV. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Key, Config, SyncRawClient}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let key = "TiKV".to_owned(); + /// let req = client.delete(key); + /// let result: () = req.unwrap(); + /// ``` + pub fn delete(&self, key: impl Into) -> Result<()> { + block_on(self.client.delete(key)) + } + + /// Create a new 'batch delete' request. + /// + /// Once resolved this request will result in the deletion of the given keys. + /// + /// It does not return an error if some of the keys do not exist and will delete the others. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Config, SyncRawClient}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let keys = vec!["TiKV".to_owned(), "TiDB".to_owned()]; + /// let req = client.batch_delete(keys); + /// let result: () = req.unwrap(); + /// ``` + pub fn batch_delete(&self, keys: impl IntoIterator>) -> Result<()> { + block_on(self.client.batch_delete(keys)) + } + + /// Create a new 'delete range' request. + /// + /// Once resolved this request will result in the deletion of all keys lying in the given range. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Key, Config, SyncRawClient, IntoOwnedRange}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let inclusive_range = "TiKV"..="TiDB"; + /// let req = client.delete_range(inclusive_range.into_owned()); + /// let result: () = req.unwrap(); + /// ``` + pub fn delete_range(&self, range: impl Into) -> Result<()> { + block_on(self.client.delete_range(range)) + } + + /// Create a new 'scan' request. + /// + /// Once resolved this request will result in a `Vec` of key-value pairs that lies in the specified range. + /// + /// If the number of eligible key-value pairs are greater than `limit`, + /// only the first `limit` pairs are returned, ordered by the key. + /// + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{KvPair, Config, SyncRawClient, IntoOwnedRange}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let inclusive_range = "TiKV"..="TiDB"; + /// let req = client.scan(inclusive_range.into_owned(), 2); + /// let result: Vec = req.unwrap(); + /// ``` + pub fn scan(&self, range: impl Into, limit: u32) -> Result> { + block_on(self.client.scan(range, limit)) + } + + /// Create a new 'scan' request that only returns the keys. + /// + /// Once resolved this request will result in a `Vec` of keys that lies in the specified range. + /// + /// If the number of eligible keys are greater than `limit`, + /// only the first `limit` pairs are returned, ordered by the key. + /// + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Key, Config, SyncRawClient, IntoOwnedRange}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let inclusive_range = "TiKV"..="TiDB"; + /// let req = client.scan_keys(inclusive_range.into_owned(), 2); + /// let result: Vec = req.unwrap(); + /// ``` + pub fn scan_keys(&self, range: impl Into, limit: u32) -> Result> { + block_on(self.client.scan_keys(range, limit)) + } + + /// Create a new 'batch scan' request. + /// + /// Once resolved this request will result in a set of scanners over the given keys. + /// + /// **Warning**: This method is experimental. The `each_limit` parameter does not work as expected. + /// It does not limit the number of results returned of each range, + /// instead it limits the number of results in each region of each range. + /// As a result, you may get **more than** `each_limit` key-value pairs for each range. + /// But you should not miss any entries. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Key, Config, SyncRawClient, IntoOwnedRange}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let inclusive_range1 = "TiDB"..="TiKV"; + /// let inclusive_range2 = "TiKV"..="TiSpark"; + /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; + /// let result = client.batch_scan(iterable, 2); + /// ``` + pub fn batch_scan( + &self, + ranges: impl IntoIterator>, + each_limit: u32, + ) -> Result> { + block_on(self.client.batch_scan(ranges, each_limit)) + } + + /// Create a new 'batch scan' request that only returns the keys. + /// + /// Once resolved this request will result in a set of scanners over the given keys. + /// + /// **Warning**: This method is experimental. + /// The `each_limit` parameter does not limit the number of results returned of each range, + /// instead it limits the number of results in each region of each range. + /// As a result, you may get **more than** `each_limit` key-value pairs for each range, + /// but you should not miss any entries. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Key, Config, SyncRawClient, IntoOwnedRange}; + /// # let client = SyncRawClient::new(vec!["192.168.0.100"]).unwrap(); + /// let inclusive_range1 = "TiDB"..="TiKV"; + /// let inclusive_range2 = "TiKV"..="TiSpark"; + /// let iterable = vec![inclusive_range1.into_owned(), inclusive_range2.into_owned()]; + /// let result = client.batch_scan(iterable, 2); + /// ``` + pub fn batch_scan_keys( + &self, + ranges: impl IntoIterator>, + each_limit: u32, + ) -> Result> { + block_on(self.client.batch_scan_keys(ranges, each_limit)) + } + + pub fn compare_and_swap( + &self, + key: impl Into, + previous_value: impl Into>, + new_value: impl Into, + ) -> Result<(Option, bool)> { + block_on(self.client.compare_and_swap(key, previous_value, new_value)) + } +}