Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 56 additions & 28 deletions examples/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,66 +13,94 @@

use futures::future::Future;
use std::path::PathBuf;
use tikv_client::*;
use tikv_client::{raw::Client, Config, Key, Result, Value};

fn main() {
let config = Config::new(vec!["127.0.0.1:2379"]).with_security(
const KEY: &str = "TiKV";
const VALUE: &str = "Rust";
const CUSTOM_CF: &str = "custom_cf";

fn main() -> Result<()> {
// Create a configuration to use for the example.
// Optionally encrypt the traffic.
let config = Config::new(vec![
"192.168.0.101:3379", // Avoid a single point of failure,
"192.168.0.100:3379", // use at least two PD endpoints.
])
.with_security(
PathBuf::from("/path/to/ca.pem"),
PathBuf::from("/path/to/client.pem"),
PathBuf::from("/path/to/client-key.pem"),
);
let raw = raw::Client::new(&config)
.wait()
.expect("Could not connect to tikv");

let key: Key = b"Company".to_vec().into();
let value: Value = b"PingCAP".to_vec().into();
// When we first create a client we recieve a `Connect` structure which must be resolved before
// the client is actually connected and usable.
let unconnnected_client = Client::new(&config);
let client = unconnnected_client.wait()?;

raw.put(key.clone(), value.clone())
.cf("test_cf")
.wait()
.expect("Could not put kv pair to tikv");
println!("Successfully put {:?}:{:?} to tikv", key, value);
// 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
// place.
//
// Here we set the key `TiKV` to have the value `Rust` associated with it.
let put_request = client.put(KEY, VALUE);
let put_result: () = put_request.wait()?; // Returns a `tikv_client::Error` on failure.
println!("Put key \"{}\", value \"{}\".", KEY, VALUE);

let value = raw
.get(&key)
.cf("test_cf")
.wait()
.expect("Could not get value");
println!("Found val: {:?} for key: {:?}", value, key);
//
// Unlike a standard Rust HashMap all calls take owned values. This is because under the hood
// protobufs must take ownership of the data. If we only took a borrow we'd need to internally // clone it. This is against Rust API guidelines, so you must manage this yourself.
//
// Above, you saw we can use a `&'static str`, this is primarily for making examples short.
// This type is practical to use for real things, and usage forces an internal copy.
//
// It is best to pass a `Vec<u8>` in terms of explictness and speed. `String`s and a few other
// types are supported as well, but it all ends up as `Vec<u8>` in the end.
let key: String = String::from(KEY);
let value: Value = client.get(key.clone()).wait()?;
assert_eq!(value.as_ref(), VALUE.as_bytes());
println!("Get key \"{:?}\" returned value \"{:?}\".", value, KEY);

raw.delete(&key)
.cf("test_cf")
// You can also set the `ColumnFamily` used by the request.
// This is *advanced usage* and should have some special considerations.
let req = client
.delete(key.clone())
.cf(CUSTOM_CF)
.wait()
.expect("Could not delete value");
println!("Key: {:?} deleted", key);

raw.get(&key)
client
.get(key)
.cf("test_cf")
.wait()
.expect_err("Get returned value for not existing key");

let keys = vec![b"k1".to_vec().into(), b"k2".to_vec().into()];
let keys = vec![Key::from(b"k1".to_vec()), Key::from(b"k2".to_vec())];

let values = raw
.batch_get(&keys)
let values = client
.batch_get(keys.clone())
.cf("test_cf")
.wait()
.expect("Could not get values");
println!("Found values: {:?} for keys: {:?}", values, keys);

let start: Key = b"k1".to_vec().into();
let end: Key = b"k2".to_vec().into();
raw.scan(&start..&end, 10)
client
.scan(start.clone()..end.clone(), 10)
.cf("test_cf")
.key_only()
.wait()
.expect("Could not scan");

let ranges = [&start..&end, &start..&end];
raw.batch_scan(&ranges, 10)
let ranges = vec![start.clone()..end.clone(), start.clone()..end.clone()];
client
.batch_scan(ranges, 10)
.cf("test_cf")
.key_only()
.wait()
.expect("Could not batch scan");

// Cleanly exit.
Ok(())
}
4 changes: 2 additions & 2 deletions examples/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn puts(client: &Client, pairs: impl IntoIterator<Item = impl Into<KvPair>>) {
txn.commit().wait().expect("Could not commit transaction");
}

fn get(client: &Client, key: &Key) -> Value {
fn get(client: &Client, key: Key) -> Value {
let txn = client.begin();
txn.get(key).wait().expect("Could not get value")
}
Expand Down Expand Up @@ -88,7 +88,7 @@ fn main() {

// get
let key1: Key = b"key1".to_vec().into();
let value1 = get(&txn, &key1);
let value1 = get(&txn, key1.clone());
println!("{:?}", (key1, value1));

// scan
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
stable
stable
22 changes: 20 additions & 2 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,70 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{error, result};

use grpcio;
use quick_error::quick_error;
use std::{error, result};

quick_error! {
/// An error originating from the TiKV client or dependencies.
///
/// This client currently uses [`quick_error`](https://docs.rs/quick-error/1.2.2/quick_error/)
/// for errors. *This may change in future versions.*
#[derive(Debug)]
pub enum Error {
/// Wraps a a `std::io::Error`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wraps a std::io::Error.

Io(err: ::std::io::Error) {
from()
cause(err)
description(err.description())
}
/// Wraps a `grpcio::Error`.
Grpc(err: grpcio::Error) {
from()
cause(err)
description(err.description())
}
/// Represents that a futures oneshot channel was cancelled.
Canceled(err: ::futures::sync::oneshot::Canceled) {
from()
cause(err)
description(err.description())
}
/// An unknown error.
///
/// Generally, this is not an expected error. Please report it if encountered.
Other(err: Box<error::Error + Sync + Send>) {
from()
cause(err.as_ref())
description(err.description())
display("unknown error {:?}", err)
}
/// A region was not found for the given key.
RegionForKeyNotFound(key: Vec<u8>) {
description("region is not found")
display("region is not found for key {:?}", key)
}
/// A region was not found.
RegionNotFound(region_id: u64, message: Option<String>) {
description("region is not found")
display("region {:?} is not found. {}", region_id, message.as_ref().unwrap_or(&"".to_owned()))
}
/// The peer is not a leader of the given region.
NotLeader(region_id: u64, message: Option<String>) {
description("peer is not leader")
display("peer is not leader for region {}. {}", region_id, message.as_ref().unwrap_or(&"".to_owned()))
}
/// The store does not match.
StoreNotMatch(request_store_id: u64, actual_store_id: u64, message: String) {
description("store not match")
display("requesting store '{}' when actual store is '{}'. {}", request_store_id, actual_store_id, message)
}
/// The given key is not eithin the given region.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eithin -> within?

KeyNotInRegion(key: Vec<u8>, region_id: u64, start_key: Vec<u8>, end_key: Vec<u8>) {
description("region is not found")
display("key {:?} is not in region {:?}: [{:?}, {:?})", key, region_id, start_key, end_key)
}
/// A stale epoch.
StaleEpoch(message: Option<String>) {
description("stale epoch")
display("{}", message.as_ref().unwrap_or(&"".to_owned()))
Expand All @@ -68,10 +83,12 @@ quick_error! {
description("stale command")
display("{}", message)
}
/// The server is too busy.
ServerIsBusy(reason: String, backoff: u64) {
description("server is busy")
display("server is busy: {:?}. Backoff {} ms", reason, backoff)
}
/// The given raft entry is too large for the region.
RaftEntryTooLarge(region_id: u64, entry_size: u64, message: String) {
description("raft entry too large")
display("{:?} bytes raft entry of region {:?} is too large. {}", entry_size, region_id, message)
Expand Down Expand Up @@ -111,4 +128,5 @@ quick_error! {
}
}

/// A result holding an [`Error`](enum.Error.html).
pub type Result<T> = result::Result<T, Error>;
Loading