Merge branch 'master' into fix/keylocation-contains

This commit is contained in:
Ana Hobden 2019-05-21 14:29:00 -07:00 committed by GitHub
commit 488d151be5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 601 additions and 844 deletions

View File

@ -24,7 +24,6 @@ fxhash = "0.2"
grpcio = { version = "0.5.0-alpha", features = [ "secure", "prost-codec" ], default-features = false }
lazy_static = "0.2.1"
log = "0.3.9"
protobuf = "2"
serde = "1.0"
serde_derive = "1.0"
tokio-core = "0.1"
@ -32,7 +31,6 @@ tokio-timer = "0.2"
[dependencies.kvproto]
git = "https://github.com/pingcap/kvproto.git"
branch = "raft-0.5.0"
[dependencies.prometheus]
version = "0.4.2"

View File

@ -1,3 +1,5 @@
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
use clap::{crate_version, App, Arg};
use std::path::PathBuf;

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
mod common;

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
mod common;

83
src/config.rs Normal file
View File

@ -0,0 +1,83 @@
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
use serde_derive::{Deserialize, Serialize};
use std::{path::PathBuf, time::Duration};
/// The configuration for either a [`raw::Client`](raw/struct.Client.html) or a
/// [`transaction::Client`](transaction/struct.Client.html).
///
/// 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, if possible!)
/// This helps avoid having a *single point of failure*.
///
/// By default, this client will use an insecure connection over instead of one protected by
/// Transport Layer Security (TLS). Your deployment may have chosen to rely on security measures
/// such as a private network, or a VPN layer to provid secure transmission.
///
/// To use a TLS secured connection, use the `with_security` function to set the required
/// parameters.
///
/// TiKV does not currently offer encrypted storage (or encryption-at-rest).
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct Config {
pub(crate) pd_endpoints: Vec<String>,
pub(crate) ca_path: Option<PathBuf>,
pub(crate) cert_path: Option<PathBuf>,
pub(crate) key_path: Option<PathBuf>,
pub(crate) timeout: Duration,
}
const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(2);
impl Config {
/// Create a new [`Config`](struct.Config.html) which coordinates with the given PD endpoints.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
///
/// ```rust
/// # use tikv_client::Config;
/// let config = Config::new(vec!["192.168.0.100:2379", "192.168.0.101:2379"]);
/// ```
pub fn new(pd_endpoints: impl IntoIterator<Item = impl Into<String>>) -> Self {
Config {
pd_endpoints: pd_endpoints.into_iter().map(Into::into).collect(),
ca_path: None,
cert_path: None,
key_path: None,
timeout: DEFAULT_REQUEST_TIMEOUT,
}
}
/// Set the certificate authority, certificate, and key locations for the
/// [`Config`](struct.Config.html).
///
/// By default, TiKV connections do not utilize transport layer security. Enable it by setting
/// these values.
///
/// ```rust
/// # use tikv_client::Config;
/// let config = Config::new(vec!["192.168.0.100:2379", "192.168.0.101:2379"])
/// .with_security("root.ca", "internal.cert", "internal.key");
/// ```
pub fn with_security(
mut self,
ca_path: impl Into<PathBuf>,
cert_path: impl Into<PathBuf>,
key_path: impl Into<PathBuf>,
) -> Self {
self.ca_path = Some(ca_path.into());
self.cert_path = Some(cert_path.into());
self.key_path = Some(key_path.into());
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
}

View File

@ -1,15 +1,5 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use failure::{Backtrace, Context, Fail};
use grpcio;
use std::fmt::{self, Display};

476
src/kv.rs Normal file
View File

@ -0,0 +1,476 @@
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
use std::ops::{
Bound, Deref, DerefMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};
use std::{fmt, str, u8};
use crate::{Error, Result};
struct HexRepr<'a>(pub &'a [u8]);
impl<'a> fmt::Display for HexRepr<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for byte in self.0 {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}
/// The key part of a key/value pair.
///
/// In TiKV, keys are an ordered sequence of bytes. This has an advantage over choosing `String` as
/// valid `UTF-8` is not required. This means that the user is permitted to store any data they wish,
/// as long as it can be represented by bytes. (Which is to say, pretty much anything!)
///
/// This is a *wrapper type* that implements `Deref<Target=[u8]>` so it can be used like one transparently.
///
/// This type also implements `From` for many types. With one exception, these are all done without
/// reallocation. Using a `&'static str`, like many examples do for simplicity, has an internal
/// allocation cost.
///
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`
/// over a `&str` or `&[u8]`.
///
/// ```rust
/// use tikv_client::Key;
///
/// let static_str: &'static str = "TiKV";
/// let from_static_str = Key::from(static_str);
///
/// let string: String = String::from(static_str);
/// let from_string = Key::from(string);
/// assert_eq!(from_static_str, from_string);
///
/// let vec: Vec<u8> = static_str.as_bytes().to_vec();
/// let from_vec = Key::from(vec);
/// assert_eq!(from_static_str, from_vec);
///
/// let bytes = static_str.as_bytes().to_vec();
/// let from_bytes = Key::from(bytes);
/// assert_eq!(from_static_str, from_bytes);
/// ```
///
/// **But, you should not need to worry about all this:** Many functions which accept a `Key`
/// accept an `Into<Key>`, which means all of the above types can be passed directly to those
/// functions.
#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Key(Vec<u8>);
impl Key {
#[inline]
pub fn new(value: Vec<u8>) -> Self {
Key(value)
}
#[inline]
pub(crate) fn into_inner(self) -> Vec<u8> {
self.0
}
#[inline]
pub(crate) fn push(&mut self, v: u8) {
self.0.push(v)
}
#[inline]
pub(crate) fn pop(&mut self) {
self.0.pop();
}
}
impl From<Vec<u8>> for Key {
fn from(v: Vec<u8>) -> Self {
Key(v)
}
}
impl From<String> for Key {
fn from(v: String) -> Key {
Key(v.into_bytes())
}
}
impl From<&'static str> for Key {
fn from(v: &'static str) -> Key {
Key(v.as_bytes().to_vec())
}
}
impl AsRef<Key> for Key {
fn as_ref(&self) -> &Key {
self
}
}
impl AsMut<Key> for Key {
fn as_mut(&mut self) -> &mut Key {
self
}
}
impl AsRef<[u8]> for Key {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for Key {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl Deref for Key {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Key {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl fmt::Debug for Key {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Key({})", HexRepr(&self.0))
}
}
/// The value part of a key/value pair.
///
/// In TiKV, values are an ordered sequence of bytes. This has an advantage over choosing `String`
/// as valid `UTF-8` is not required. This means that the user is permitted to store any data they wish,
/// as long as it can be represented by bytes. (Which is to say, pretty much anything!)
///
/// This is a *wrapper type* that implements `Deref<Target=[u8]>` so it can be used like one transparently.
///
/// This type also implements `From` for many types. With one exception, these are all done without
/// reallocation. Using a `&'static str`, like many examples do for simplicity, has an internal
/// allocation cost.
///
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`
/// over a `&str` or `&[u8]`.
///
/// ```rust
/// use tikv_client::Value;
///
/// let static_str: &'static str = "TiKV";
/// let from_static_str = Value::from(static_str);
///
/// let string: String = String::from(static_str);
/// let from_string = Value::from(string);
/// assert_eq!(from_static_str, from_string);
///
/// let vec: Vec<u8> = static_str.as_bytes().to_vec();
/// let from_vec = Value::from(vec);
/// assert_eq!(from_static_str, from_vec);
///
/// let bytes = static_str.as_bytes().to_vec();
/// let from_bytes = Value::from(bytes);
/// assert_eq!(from_static_str, from_bytes);
/// ```
///
/// **But, you should not need to worry about all this:** Many functions which accept a `Value`
/// accept an `Into<Value>`, which means all of the above types can be passed directly to those
/// functions.
#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct Value(Vec<u8>);
impl Value {
#[inline]
pub fn new(value: Vec<u8>) -> Self {
Value(value)
}
#[inline]
pub(crate) fn into_inner(self) -> Vec<u8> {
self.0
}
}
impl From<Vec<u8>> for Value {
fn from(v: Vec<u8>) -> Self {
Value(v)
}
}
impl From<String> for Value {
fn from(v: String) -> Value {
Value(v.into_bytes())
}
}
impl From<&'static str> for Value {
fn from(v: &'static str) -> Value {
Value(v.as_bytes().to_vec())
}
}
impl Deref for Value {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for Value {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match str::from_utf8(&self.0) {
Ok(s) => write!(f, "Value({:?})", s),
Err(_) => write!(f, "Value({})", HexRepr(&self.0)),
}
}
}
/// A key/value pair.
///
/// ```rust
/// # use tikv_client::{Key, Value, KvPair};
/// let key = "key";
/// let value = "value";
/// let constructed = KvPair::new(key, value);
/// let from_tuple = KvPair::from((key, value));
/// assert_eq!(constructed, from_tuple);
/// ```
///
/// Many functions which accept a `KvPair` accept an `Into<KvPair>`, which means all of the above
/// types (Like a `(Key, Value)`) can be passed directly to those functions.
#[derive(Default, Clone, Eq, PartialEq)]
pub struct KvPair(Key, Value);
impl KvPair {
/// Create a new `KvPair`.
#[inline]
pub fn new(key: impl Into<Key>, value: impl Into<Value>) -> Self {
KvPair(key.into(), value.into())
}
/// Immutably borrow the `Key` part of the `KvPair`.
#[inline]
pub fn key(&self) -> &Key {
&self.0
}
/// Immutably borrow the `Value` part of the `KvPair`.
#[inline]
pub fn value(&self) -> &Value {
&self.1
}
#[inline]
pub fn into_inner(self) -> (Key, Value) {
(self.0, self.1)
}
#[inline]
pub fn into_key(self) -> Key {
self.0
}
#[inline]
pub fn into_value(self) -> Value {
self.1
}
/// Mutably borrow the `Key` part of the `KvPair`.
#[inline]
pub fn key_mut(&mut self) -> &mut Key {
&mut self.0
}
/// Mutably borrow the `Value` part of the `KvPair`.
#[inline]
pub fn value_mut(&mut self) -> &mut Value {
&mut self.1
}
/// Set the `Key` part of the `KvPair`.
#[inline]
pub fn set_key(&mut self, k: impl Into<Key>) {
self.0 = k.into();
}
/// Set the `Value` part of the `KvPair`.
#[inline]
pub fn set_value(&mut self, v: impl Into<Value>) {
self.1 = v.into();
}
}
impl<K, V> From<(K, V)> for KvPair
where
K: Into<Key>,
V: Into<Value>,
{
fn from((k, v): (K, V)) -> Self {
KvPair(k.into(), v.into())
}
}
impl fmt::Debug for KvPair {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let KvPair(key, value) = self;
match str::from_utf8(&value) {
Ok(s) => write!(f, "KvPair({}, {:?})", HexRepr(&key), s),
Err(_) => write!(f, "KvPair({}, {})", HexRepr(&key), HexRepr(&value)),
}
}
}
/// A convenience trait for expressing ranges.
///
/// In TiKV, keys are an ordered sequence of bytes. This means we can have ranges over those
/// bytes. Eg `001` is before `010`.
///
/// This trait has implementations for common range types like `a..b`, `a..=b` where `a` and `b`
/// `impl Into<Key>`. You could implement this for your own types.
///
/// ```rust
/// use tikv_client::{KeyRange, Key};
/// use std::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive, RangeFrom, RangeFull, Bound};
///
/// let explict_range: Range<Key> = Range { start: Key::from("Rust"), end: Key::from("TiKV") };
/// let from_explict_range = explict_range.into_bounds();
///
/// let range: Range<&str> = "Rust".."TiKV";
/// let from_range = range.into_bounds();
/// assert_eq!(from_explict_range, from_range);
///
/// let range: RangeInclusive<&str> = "Rust"..="TiKV";
/// let from_range = range.into_bounds();
/// assert_eq!(
/// (Bound::Included(Key::from("Rust")), Bound::Included(Key::from("TiKV"))),
/// from_range
/// );
///
/// let range_from: RangeFrom<&str> = "Rust"..;
/// let from_range_from = range_from.into_bounds();
/// assert_eq!(
/// (Bound::Included(Key::from("Rust")), Bound::Unbounded),
/// from_range_from,
/// );
///
/// let range_to: RangeTo<&str> = .."TiKV";
/// let from_range_to = range_to.into_bounds();
/// assert_eq!(
/// (Bound::Unbounded, Bound::Excluded(Key::from("TiKV"))),
/// from_range_to,
/// );
///
/// let range_to_inclusive: RangeToInclusive<&str> = ..="TiKV";
/// let from_range_to_inclusive = range_to_inclusive.into_bounds();
/// assert_eq!(
/// (Bound::Unbounded, Bound::Included(Key::from("TiKV"))),
/// from_range_to_inclusive,
/// );
///
/// let range_full: RangeFull = ..;
/// let from_range_full = range_full.into_bounds();
/// assert_eq!(
/// (Bound::Unbounded, Bound::Unbounded),
/// from_range_full
/// );
/// ```
///
/// **But, you should not need to worry about all this:** Many functions accept a `impl KeyRange`
/// which means all of the above types can be passed directly to those functions.
pub trait KeyRange: Sized {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>);
fn into_keys(self) -> Result<(Key, Option<Key>)> {
range_to_keys(self.into_bounds())
}
}
fn range_to_keys(range: (Bound<Key>, Bound<Key>)) -> Result<(Key, Option<Key>)> {
let start = match range.0 {
Bound::Included(v) => v,
Bound::Excluded(mut v) => {
match v.last_mut() {
None | Some(&mut u8::MAX) => v.push(0),
Some(v) => *v += 1,
}
v
}
Bound::Unbounded => Err(Error::invalid_key_range())?,
};
let end = match range.1 {
Bound::Included(v) => Some(v),
Bound::Excluded(mut v) => Some({
match v.last_mut() {
None => (),
Some(&mut u8::MIN) => v.pop(),
Some(v) => *v -= 1,
}
v
}),
Bound::Unbounded => None,
};
Ok((start, end))
}
impl<T: Into<Key>> KeyRange for Range<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(
Bound::Included(self.start.into()),
Bound::Excluded(self.end.into()),
)
}
}
impl<T: Into<Key>> KeyRange for RangeFrom<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Included(self.start.into()), Bound::Unbounded)
}
}
impl KeyRange for RangeFull {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Unbounded, Bound::Unbounded)
}
}
impl<T: Into<Key>> KeyRange for RangeInclusive<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
let (start, end) = self.into_inner();
(Bound::Included(start.into()), Bound::Included(end.into()))
}
}
impl<T: Into<Key>> KeyRange for RangeTo<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Unbounded, Bound::Excluded(self.end.into()))
}
}
impl<T: Into<Key>> KeyRange for RangeToInclusive<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Unbounded, Bound::Included(self.end.into()))
}
}
impl<T: Into<Key>> KeyRange for (Bound<T>, Bound<T>) {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(convert_to_bound_key(self.0), convert_to_bound_key(self.1))
}
}
fn convert_to_bound_key(b: Bound<impl Into<Key>>) -> Bound<Key> {
match b {
Bound::Included(k) => Bound::Included(k.into()),
Bound::Excluded(k) => Bound::Excluded(k.into()),
Bound::Unbounded => Bound::Unbounded,
}
}

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
// Long and nested future chains can quickly result in large generic types.
#![type_length_limit = "16777216"]
@ -109,582 +98,25 @@
//! ```
//!
//! At this point, you should seek the documentation in the related API modules.
//!
use futures::Future;
use serde_derive::*;
use std::{
fmt,
ops::{
Bound, Deref, DerefMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
RangeToInclusive,
},
path::PathBuf,
str,
time::Duration,
u8::{MAX as U8_MAX, MIN as U8_MIN},
};
mod config;
mod errors;
mod kv;
pub mod raw;
mod rpc;
pub mod transaction;
#[doc(inline)]
pub use crate::config::Config;
#[doc(inline)]
pub use crate::errors::Error;
#[doc(inline)]
pub use crate::errors::ErrorKind;
#[doc(inline)]
pub use crate::errors::Result;
struct HexRepr<'a>(pub &'a [u8]);
impl<'a> fmt::Display for HexRepr<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for byte in self.0 {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}
/// The key part of a key/value pair.
///
/// In TiKV, keys are an ordered sequence of bytes. This has an advantage over choosing `String` as
/// valid `UTF-8` is not required. This means that the user is permitted to store any data they wish,
/// as long as it can be represented by bytes. (Which is to say, pretty much anything!)
///
/// This is a *wrapper type* that implements `Deref<Target=[u8]>` so it can be used like one transparently.
///
/// This type also implements `From` for many types. With one exception, these are all done without
/// reallocation. Using a `&'static str`, like many examples do for simplicity, has an internal
/// allocation cost.
///
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`
/// over a `&str` or `&[u8]`.
///
/// ```rust
/// use tikv_client::Key;
///
/// let static_str: &'static str = "TiKV";
/// let from_static_str = Key::from(static_str);
///
/// let string: String = String::from(static_str);
/// let from_string = Key::from(string);
/// assert_eq!(from_static_str, from_string);
///
/// let vec: Vec<u8> = static_str.as_bytes().to_vec();
/// let from_vec = Key::from(vec);
/// assert_eq!(from_static_str, from_vec);
///
/// let bytes = static_str.as_bytes().to_vec();
/// let from_bytes = Key::from(bytes);
/// assert_eq!(from_static_str, from_bytes);
/// ```
///
/// **But, you should not need to worry about all this:** Many functions which accept a `Key`
/// accept an `Into<Key>`, which means all of the above types can be passed directly to those
/// functions.
#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Key(Vec<u8>);
impl Key {
#[inline]
pub fn new(value: Vec<u8>) -> Self {
Key(value)
}
#[inline]
fn into_inner(self) -> Vec<u8> {
self.0
}
#[inline]
fn push(&mut self, v: u8) {
self.0.push(v)
}
#[inline]
fn pop(&mut self) {
self.0.pop();
}
}
impl From<Vec<u8>> for Key {
fn from(v: Vec<u8>) -> Self {
Key(v)
}
}
impl From<String> for Key {
fn from(v: String) -> Key {
Key(v.into_bytes())
}
}
impl From<&'static str> for Key {
fn from(v: &'static str) -> Key {
Key(v.as_bytes().to_vec())
}
}
impl AsRef<Key> for Key {
fn as_ref(&self) -> &Key {
self
}
}
impl AsMut<Key> for Key {
fn as_mut(&mut self) -> &mut Key {
self
}
}
impl AsRef<[u8]> for Key {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for Key {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl Deref for Key {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Key {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl fmt::Debug for Key {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Key({})", HexRepr(&self.0))
}
}
/// The value part of a key/value pair.
///
/// In TiKV, values are an ordered sequence of bytes. This has an advantage over choosing `String`
/// as valid `UTF-8` is not required. This means that the user is permitted to store any data they wish,
/// as long as it can be represented by bytes. (Which is to say, pretty much anything!)
///
/// This is a *wrapper type* that implements `Deref<Target=[u8]>` so it can be used like one transparently.
///
/// This type also implements `From` for many types. With one exception, these are all done without
/// reallocation. Using a `&'static str`, like many examples do for simplicity, has an internal
/// allocation cost.
///
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`
/// over a `&str` or `&[u8]`.
///
/// ```rust
/// use tikv_client::Value;
///
/// let static_str: &'static str = "TiKV";
/// let from_static_str = Value::from(static_str);
///
/// let string: String = String::from(static_str);
/// let from_string = Value::from(string);
/// assert_eq!(from_static_str, from_string);
///
/// let vec: Vec<u8> = static_str.as_bytes().to_vec();
/// let from_vec = Value::from(vec);
/// assert_eq!(from_static_str, from_vec);
///
/// let bytes = static_str.as_bytes().to_vec();
/// let from_bytes = Value::from(bytes);
/// assert_eq!(from_static_str, from_bytes);
/// ```
///
/// **But, you should not need to worry about all this:** Many functions which accept a `Value`
/// accept an `Into<Value>`, which means all of the above types can be passed directly to those
/// functions.
#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct Value(Vec<u8>);
impl Value {
#[inline]
pub fn new(value: Vec<u8>) -> Self {
Value(value)
}
#[inline]
fn into_inner(self) -> Vec<u8> {
self.0
}
}
impl From<Vec<u8>> for Value {
fn from(v: Vec<u8>) -> Self {
Value(v)
}
}
impl From<String> for Value {
fn from(v: String) -> Value {
Value(v.into_bytes())
}
}
impl From<&'static str> for Value {
fn from(v: &'static str) -> Value {
Value(v.as_bytes().to_vec())
}
}
impl Deref for Value {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for Value {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match str::from_utf8(&self.0) {
Ok(s) => write!(f, "Value({:?})", s),
Err(_) => write!(f, "Value({})", HexRepr(&self.0)),
}
}
}
/// A key/value pair.
///
/// ```rust
/// # use tikv_client::{Key, Value, KvPair};
/// let key = "key";
/// let value = "value";
/// let constructed = KvPair::new(key, value);
/// let from_tuple = KvPair::from((key, value));
/// assert_eq!(constructed, from_tuple);
/// ```
///
/// Many functions which accept a `KvPair` accept an `Into<KvPair>`, which means all of the above
/// types (Like a `(Key, Value)`) can be passed directly to those functions.
#[derive(Default, Clone, Eq, PartialEq)]
pub struct KvPair(Key, Value);
impl KvPair {
/// Create a new `KvPair`.
#[inline]
pub fn new(key: impl Into<Key>, value: impl Into<Value>) -> Self {
KvPair(key.into(), value.into())
}
/// Immutably borrow the `Key` part of the `KvPair`.
#[inline]
pub fn key(&self) -> &Key {
&self.0
}
/// Immutably borrow the `Value` part of the `KvPair`.
#[inline]
pub fn value(&self) -> &Value {
&self.1
}
#[inline]
pub fn into_inner(self) -> (Key, Value) {
(self.0, self.1)
}
#[inline]
pub fn into_key(self) -> Key {
self.0
}
#[inline]
pub fn into_value(self) -> Value {
self.1
}
/// Mutably borrow the `Key` part of the `KvPair`.
#[inline]
pub fn key_mut(&mut self) -> &mut Key {
&mut self.0
}
/// Mutably borrow the `Value` part of the `KvPair`.
#[inline]
pub fn value_mut(&mut self) -> &mut Value {
&mut self.1
}
/// Set the `Key` part of the `KvPair`.
#[inline]
pub fn set_key(&mut self, k: impl Into<Key>) {
self.0 = k.into();
}
/// Set the `Value` part of the `KvPair`.
#[inline]
pub fn set_value(&mut self, v: impl Into<Value>) {
self.1 = v.into();
}
}
impl<K, V> From<(K, V)> for KvPair
where
K: Into<Key>,
V: Into<Value>,
{
fn from((k, v): (K, V)) -> Self {
KvPair(k.into(), v.into())
}
}
impl fmt::Debug for KvPair {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let KvPair(key, value) = self;
match str::from_utf8(&value) {
Ok(s) => write!(f, "KvPair({}, {:?})", HexRepr(&key), s),
Err(_) => write!(f, "KvPair({}, {})", HexRepr(&key), HexRepr(&value)),
}
}
}
/// The configuration for either a [`raw::Client`](raw/struct.Client.html) or a
/// [`transaction::Client`](transaction/struct.Client.html).
///
/// 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, if possible!)
/// This helps avoid having a *single point of failure*.
///
/// By default, this client will use an insecure connection over instead of one protected by
/// Transport Layer Security (TLS). Your deployment may have chosen to rely on security measures
/// such as a private network, or a VPN layer to provid secure transmission.
///
/// To use a TLS secured connection, use the `with_security` function to set the required
/// parameters.
///
/// TiKV does not currently offer encrypted storage (or encryption-at-rest).
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct Config {
pd_endpoints: Vec<String>,
ca_path: Option<PathBuf>,
cert_path: Option<PathBuf>,
key_path: Option<PathBuf>,
timeout: Duration,
}
const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(2);
impl Config {
/// Create a new [`Config`](struct.Config.html) which coordinates with the given PD endpoints.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
///
/// ```rust
/// # use tikv_client::Config;
/// let config = Config::new(vec!["192.168.0.100:2379", "192.168.0.101:2379"]);
/// ```
pub fn new(pd_endpoints: impl IntoIterator<Item = impl Into<String>>) -> Self {
Config {
pd_endpoints: pd_endpoints.into_iter().map(Into::into).collect(),
ca_path: None,
cert_path: None,
key_path: None,
timeout: DEFAULT_REQUEST_TIMEOUT,
}
}
/// Set the certificate authority, certificate, and key locations for the
/// [`Config`](struct.Config.html).
///
/// By default, TiKV connections do not utilize transport layer security. Enable it by setting
/// these values.
///
/// ```rust
/// # use tikv_client::Config;
/// let config = Config::new(vec!["192.168.0.100:2379", "192.168.0.101:2379"])
/// .with_security("root.ca", "internal.cert", "internal.key");
/// ```
pub fn with_security(
mut self,
ca_path: impl Into<PathBuf>,
cert_path: impl Into<PathBuf>,
key_path: impl Into<PathBuf>,
) -> Self {
self.ca_path = Some(ca_path.into());
self.cert_path = Some(cert_path.into());
self.key_path = Some(key_path.into());
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
}
#[doc(inline)]
pub use crate::kv::{Key, KeyRange, KvPair, Value};
pub type KvFuture<Resp> = Box<dyn Future<Item = Resp, Error = Error> + Send>;
/// A convenience trait for expressing ranges.
///
/// In TiKV, keys are an ordered sequence of bytes. This means we can have ranges over those
/// bytes. Eg `001` is before `010`.
///
/// This trait has implementations for common range types like `a..b`, `a..=b` where `a` and `b`
/// `impl Into<Key>`. You could implement this for your own types.
///
/// ```rust
/// use tikv_client::{KeyRange, Key};
/// use std::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive, RangeFrom, RangeFull, Bound};
///
/// let explict_range: Range<Key> = Range { start: Key::from("Rust"), end: Key::from("TiKV") };
/// let from_explict_range = explict_range.into_bounds();
///
/// let range: Range<&str> = "Rust".."TiKV";
/// let from_range = range.into_bounds();
/// assert_eq!(from_explict_range, from_range);
///
/// let range: RangeInclusive<&str> = "Rust"..="TiKV";
/// let from_range = range.into_bounds();
/// assert_eq!(
/// (Bound::Included(Key::from("Rust")), Bound::Included(Key::from("TiKV"))),
/// from_range
/// );
///
/// let range_from: RangeFrom<&str> = "Rust"..;
/// let from_range_from = range_from.into_bounds();
/// assert_eq!(
/// (Bound::Included(Key::from("Rust")), Bound::Unbounded),
/// from_range_from,
/// );
///
/// let range_to: RangeTo<&str> = .."TiKV";
/// let from_range_to = range_to.into_bounds();
/// assert_eq!(
/// (Bound::Unbounded, Bound::Excluded(Key::from("TiKV"))),
/// from_range_to,
/// );
///
/// let range_to_inclusive: RangeToInclusive<&str> = ..="TiKV";
/// let from_range_to_inclusive = range_to_inclusive.into_bounds();
/// assert_eq!(
/// (Bound::Unbounded, Bound::Included(Key::from("TiKV"))),
/// from_range_to_inclusive,
/// );
///
/// let range_full: RangeFull = ..;
/// let from_range_full = range_full.into_bounds();
/// assert_eq!(
/// (Bound::Unbounded, Bound::Unbounded),
/// from_range_full
/// );
/// ```
///
/// **But, you should not need to worry about all this:** Many functions accept a `impl KeyRange`
/// which means all of the above types can be passed directly to those functions.
pub trait KeyRange: Sized {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>);
fn into_keys(self) -> Result<(Key, Option<Key>)> {
range_to_keys(self.into_bounds())
}
}
fn range_to_keys(range: (Bound<Key>, Bound<Key>)) -> Result<(Key, Option<Key>)> {
let start = match range.0 {
Bound::Included(v) => v,
Bound::Excluded(mut v) => {
match v.last_mut() {
None | Some(&mut U8_MAX) => v.push(0),
Some(v) => *v += 1,
}
v
}
Bound::Unbounded => Err(Error::invalid_key_range())?,
};
let end = match range.1 {
Bound::Included(v) => Some(v),
Bound::Excluded(mut v) => Some({
match v.last_mut() {
None => (),
Some(&mut U8_MIN) => v.pop(),
Some(v) => *v -= 1,
}
v
}),
Bound::Unbounded => None,
};
Ok((start, end))
}
impl<T: Into<Key>> KeyRange for Range<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(
Bound::Included(self.start.into()),
Bound::Excluded(self.end.into()),
)
}
}
impl<T: Into<Key>> KeyRange for RangeFrom<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Included(self.start.into()), Bound::Unbounded)
}
}
impl KeyRange for RangeFull {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Unbounded, Bound::Unbounded)
}
}
impl<T: Into<Key>> KeyRange for RangeInclusive<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
let (start, end) = self.into_inner();
(Bound::Included(start.into()), Bound::Included(end.into()))
}
}
impl<T: Into<Key>> KeyRange for RangeTo<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Unbounded, Bound::Excluded(self.end.into()))
}
}
impl<T: Into<Key>> KeyRange for RangeToInclusive<T> {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(Bound::Unbounded, Bound::Included(self.end.into()))
}
}
impl<T: Into<Key>> KeyRange for (Bound<T>, Bound<T>) {
fn into_bounds(self) -> (Bound<Key>, Bound<Key>) {
(convert_to_bound_key(self.0), convert_to_bound_key(self.1))
}
}
fn convert_to_bound_key<K>(b: Bound<K>) -> Bound<Key>
where
K: Into<Key>,
{
use std::ops::Bound::*;
match b {
Included(k) => Included(k.into()),
Excluded(k) => Excluded(k.into()),
Unbounded => Unbounded,
}
}

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
//! Raw related functionality.
//!

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
// TODO: Remove this when txn is done.
#![allow(dead_code)]
@ -29,7 +18,6 @@ use futures::{
use grpcio::{EnvBuilder, Environment};
use kvproto::kvrpcpb;
use log::*;
use protobuf::Message;
use crate::{
raw::ColumnFamily,
@ -489,7 +477,7 @@ impl RegionContext {
impl From<RegionContext> for kvrpcpb::Context {
fn from(mut ctx: RegionContext) -> kvrpcpb::Context {
let mut kvctx = kvrpcpb::Context::new();
let mut kvctx = kvrpcpb::Context::default();
kvctx.set_region_id(ctx.region.id);
kvctx.set_region_epoch(ctx.region.take_region_epoch());
kvctx.set_peer(ctx.region.peer().expect("leader must exist").into_inner());

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::time::Instant;

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
#[macro_use]
mod util;

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::{
fmt,

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::ops::{Deref, DerefMut};

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::{
sync::{Arc, RwLock},
@ -28,7 +17,6 @@ use fxhash::FxHashSet as HashSet;
use grpcio::{CallOption, Environment, WriteFlags};
use kvproto::pdpb;
use log::*;
use protobuf::Message;
use tokio_core::reactor::{Core, Handle as OtherHandle};
use crate::{
@ -45,9 +33,8 @@ use crate::{
macro_rules! pd_request {
($cluster_id:expr, $type:ty) => {{
use ::protobuf::Message;
let mut request = <$type>::new();
let mut header = ::kvproto::pdpb::RequestHeader::new();
let mut request = <$type>::default();
let mut header = ::kvproto::pdpb::RequestHeader::default();
header.set_cluster_id($cluster_id);
request.set_header(header);
request
@ -365,7 +352,7 @@ fn connect(
let client = security_mgr.connect(env, addr, pdpb::PdClient::new)?;
let option = CallOption::default().timeout(timeout);
let resp = client
.get_members_opt(&pdpb::GetMembersRequest::new(), option)
.get_members_opt(&pdpb::GetMembersRequest::default(), option)
.map_err(Error::from)?;
Ok((client, resp))
}

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
// TODO: Remove this when txn is done.
#![allow(dead_code)]

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::{
result,

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::{
fs::File,

View File

@ -1,15 +1,4 @@
// Copyright 2018 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
// TODO: Remove this when txn is done.
#![allow(dead_code)]
@ -19,7 +8,6 @@ use std::{fmt, sync::Arc, time::Duration};
use futures::Future;
use grpcio::{CallOption, Environment};
use kvproto::{errorpb, kvrpcpb, tikvpb::TikvClient};
use protobuf::{self, Message};
use crate::{
rpc::{
@ -171,7 +159,7 @@ has_no_error!(kvrpcpb::RawBatchScanResponse);
macro_rules! raw_request {
($context:expr, $type:ty) => {{
let mut req = <$type>::new();
let mut req = <$type>::default();
let (region, cf) = $context.into_inner();
req.set_context(region.into());
if let Some(cf) = cf {
@ -183,7 +171,7 @@ macro_rules! raw_request {
macro_rules! txn_request {
($context:expr, $type:ty) => {{
let mut req = <$type>::new();
let mut req = <$type>::default();
req.set_context($context.into_inner().into());
req
}};
@ -191,7 +179,7 @@ macro_rules! txn_request {
impl From<Mutation> for kvrpcpb::Mutation {
fn from(mutation: Mutation) -> kvrpcpb::Mutation {
let mut pb = kvrpcpb::Mutation::new();
let mut pb = kvrpcpb::Mutation::default();
match mutation {
Mutation::Put(k, v) => {
pb.set_op(kvrpcpb::Op::Put);
@ -217,7 +205,7 @@ impl From<Mutation> for kvrpcpb::Mutation {
impl From<TxnInfo> for kvrpcpb::TxnInfo {
fn from(txn_info: TxnInfo) -> kvrpcpb::TxnInfo {
let mut pb = kvrpcpb::TxnInfo::new();
let mut pb = kvrpcpb::TxnInfo::default();
pb.set_txn(txn_info.txn);
pb.set_status(txn_info.status);
pb
@ -328,7 +316,7 @@ impl KvClient {
mutations: impl Iterator<Item = Mutation>,
commit_version: u64,
) -> impl Future<Item = kvrpcpb::ImportResponse, Error = Error> {
let mut req = kvrpcpb::ImportRequest::new();
let mut req = kvrpcpb::ImportRequest::default();
req.set_mutations(mutations.map(Into::into).collect());
req.set_commit_version(commit_version);
@ -635,7 +623,7 @@ impl KvClient {
#[inline]
fn convert_to_grpc_pair(pair: KvPair) -> kvrpcpb::KvPair {
let mut result = kvrpcpb::KvPair::new();
let mut result = kvrpcpb::KvPair::default();
let (key, value) = pair.into_inner();
result.set_key(key.into_inner());
result.set_value(value.into_inner());
@ -663,7 +651,7 @@ impl KvClient {
#[inline]
fn convert_to_grpc_range(range: (Option<Key>, Option<Key>)) -> kvrpcpb::KeyRange {
let (start, end) = range;
let mut range = kvrpcpb::KeyRange::new();
let mut range = kvrpcpb::KeyRange::default();
start.map(|k| range.set_start_key(k.into_inner())).unwrap();
end.map(|k| range.set_end_key(k.into_inner())).unwrap();
range

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use lazy_static::*;
use prometheus::*;

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
pub mod client;
pub mod context;

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
use std::{
sync::{mpsc, RwLock, RwLockReadGuard, RwLockWriteGuard},

View File

@ -1,15 +1,4 @@
// Copyright 2018 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
//! Transactional related functionality.
//!

View File

@ -1,15 +1,4 @@
// Copyright 2019 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
mod raw;

View File

@ -1,15 +1,4 @@
// Copyright 2019 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
use futures::future::Future;

View File

@ -1,15 +1,4 @@
// Copyright 2019 The TiKV Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
#[cfg(feature = "integration-tests")]
mod integration_tests;