mirror of https://github.com/tikv/client-rust.git
Merge remote-tracking branch 'origin/atomic' into atomic
This commit is contained in:
commit
873fde5e00
|
@ -1,58 +1,36 @@
|
||||||
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
|
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
|
||||||
|
|
||||||
use crate::{BoundRange, Key, KvPair, Result, Value};
|
use crate::{BoundRange, Key, KvPair, Result, Value};
|
||||||
use derive_new::new;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{btree_map::Entry, BTreeMap, HashMap},
|
collections::{btree_map::Entry, BTreeMap, HashMap},
|
||||||
future::Future,
|
future::Future,
|
||||||
};
|
};
|
||||||
use tikv_client_proto::kvrpcpb;
|
use tikv_client_proto::kvrpcpb;
|
||||||
use tokio::sync::{Mutex, MutexGuard};
|
|
||||||
|
|
||||||
#[derive(new)]
|
|
||||||
struct InnerBuffer {
|
|
||||||
#[new(default)]
|
|
||||||
primary_key: Option<Key>,
|
|
||||||
#[new(default)]
|
|
||||||
entry_map: BTreeMap<Key, BufferEntry>,
|
|
||||||
is_pessimistic: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InnerBuffer {
|
|
||||||
fn insert(&mut self, key: impl Into<Key>, entry: BufferEntry) {
|
|
||||||
let key = key.into();
|
|
||||||
if !matches!(entry, BufferEntry::Cached(_) | BufferEntry::CheckNotExist) {
|
|
||||||
self.primary_key.get_or_insert_with(|| key.clone());
|
|
||||||
}
|
|
||||||
self.entry_map.insert(key, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the primary key if it is not set
|
|
||||||
pub fn primary_key_or(&mut self, key: &Key) {
|
|
||||||
self.primary_key.get_or_insert(key.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A caching layer which buffers reads and writes in a transaction.
|
/// A caching layer which buffers reads and writes in a transaction.
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
inner: Mutex<InnerBuffer>,
|
primary_key: Option<Key>,
|
||||||
|
entry_map: BTreeMap<Key, BufferEntry>,
|
||||||
|
is_pessimistic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
pub fn new(is_pessimistic: bool) -> Buffer {
|
pub fn new(is_pessimistic: bool) -> Buffer {
|
||||||
Buffer {
|
Buffer {
|
||||||
inner: Mutex::new(InnerBuffer::new(is_pessimistic)),
|
primary_key: None,
|
||||||
|
entry_map: BTreeMap::new(),
|
||||||
|
is_pessimistic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the primary key of the buffer.
|
/// Get the primary key of the buffer.
|
||||||
pub async fn get_primary_key(&self) -> Option<Key> {
|
pub async fn get_primary_key(&self) -> Option<Key> {
|
||||||
self.inner.lock().await.primary_key.clone()
|
self.primary_key.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the primary key if it is not set
|
/// Set the primary key if it is not set
|
||||||
pub async fn primary_key_or(&self, key: &Key) {
|
pub async fn primary_key_or(&mut self, key: &Key) {
|
||||||
self.inner.lock().await.primary_key_or(key);
|
self.primary_key.get_or_insert_with(|| key.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a value from the buffer.
|
/// Get a value from the buffer.
|
||||||
|
@ -66,7 +44,7 @@ impl Buffer {
|
||||||
|
|
||||||
/// Get a value from the buffer. If the value is not present, run `f` to get
|
/// Get a value from the buffer. If the value is not present, run `f` to get
|
||||||
/// the value.
|
/// the value.
|
||||||
pub async fn get_or_else<F, Fut>(&self, key: Key, f: F) -> Result<Option<Value>>
|
pub async fn get_or_else<F, Fut>(&mut self, key: Key, f: F) -> Result<Option<Value>>
|
||||||
where
|
where
|
||||||
F: FnOnce(Key) -> Fut,
|
F: FnOnce(Key) -> Fut,
|
||||||
Fut: Future<Output = Result<Option<Value>>>,
|
Fut: Future<Output = Result<Option<Value>>>,
|
||||||
|
@ -75,8 +53,7 @@ impl Buffer {
|
||||||
MutationValue::Determined(value) => Ok(value),
|
MutationValue::Determined(value) => Ok(value),
|
||||||
MutationValue::Undetermined => {
|
MutationValue::Undetermined => {
|
||||||
let value = f(key.clone()).await?;
|
let value = f(key.clone()).await?;
|
||||||
let mut mutations = self.inner.lock().await;
|
self.update_cache(key, value.clone());
|
||||||
Self::update_cache(&mut mutations, key, value.clone());
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +64,7 @@ impl Buffer {
|
||||||
///
|
///
|
||||||
/// only used for snapshot read (i.e. not for `batch_get_for_update`)
|
/// only used for snapshot read (i.e. not for `batch_get_for_update`)
|
||||||
pub async fn batch_get_or_else<F, Fut>(
|
pub async fn batch_get_or_else<F, Fut>(
|
||||||
&self,
|
&mut self,
|
||||||
keys: impl Iterator<Item = Key>,
|
keys: impl Iterator<Item = Key>,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Result<impl Iterator<Item = KvPair>>
|
) -> Result<impl Iterator<Item = KvPair>>
|
||||||
|
@ -96,7 +73,6 @@ impl Buffer {
|
||||||
Fut: Future<Output = Result<Vec<KvPair>>>,
|
Fut: Future<Output = Result<Vec<KvPair>>>,
|
||||||
{
|
{
|
||||||
let (cached_results, undetermined_keys) = {
|
let (cached_results, undetermined_keys) = {
|
||||||
let mutations = self.inner.lock().await;
|
|
||||||
// Partition the keys into those we have buffered and those we have to
|
// Partition the keys into those we have buffered and those we have to
|
||||||
// get from the store.
|
// get from the store.
|
||||||
let (undetermined_keys, cached_results): (
|
let (undetermined_keys, cached_results): (
|
||||||
|
@ -104,7 +80,7 @@ impl Buffer {
|
||||||
Vec<(Key, MutationValue)>,
|
Vec<(Key, MutationValue)>,
|
||||||
) = keys
|
) = keys
|
||||||
.map(|key| {
|
.map(|key| {
|
||||||
let value = mutations
|
let value = self
|
||||||
.entry_map
|
.entry_map
|
||||||
.get(&key)
|
.get(&key)
|
||||||
.map(BufferEntry::get_value)
|
.map(BufferEntry::get_value)
|
||||||
|
@ -122,11 +98,10 @@ impl Buffer {
|
||||||
};
|
};
|
||||||
|
|
||||||
let fetched_results = f(Box::new(undetermined_keys)).await?;
|
let fetched_results = f(Box::new(undetermined_keys)).await?;
|
||||||
let mut mutations = self.inner.lock().await;
|
|
||||||
for kvpair in &fetched_results {
|
for kvpair in &fetched_results {
|
||||||
let key = kvpair.0.clone();
|
let key = kvpair.0.clone();
|
||||||
let value = Some(kvpair.1.clone());
|
let value = Some(kvpair.1.clone());
|
||||||
Self::update_cache(&mut mutations, key, value);
|
self.update_cache(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let results = cached_results.chain(fetched_results.into_iter());
|
let results = cached_results.chain(fetched_results.into_iter());
|
||||||
|
@ -135,7 +110,7 @@ impl Buffer {
|
||||||
|
|
||||||
/// Run `f` to fetch entries in `range` from TiKV. Combine them with mutations in local buffer. Returns the results.
|
/// Run `f` to fetch entries in `range` from TiKV. Combine them with mutations in local buffer. Returns the results.
|
||||||
pub async fn scan_and_fetch<F, Fut>(
|
pub async fn scan_and_fetch<F, Fut>(
|
||||||
&self,
|
&mut self,
|
||||||
range: BoundRange,
|
range: BoundRange,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
f: F,
|
f: F,
|
||||||
|
@ -145,8 +120,7 @@ impl Buffer {
|
||||||
Fut: Future<Output = Result<Vec<KvPair>>>,
|
Fut: Future<Output = Result<Vec<KvPair>>>,
|
||||||
{
|
{
|
||||||
// read from local buffer
|
// read from local buffer
|
||||||
let mut mutations = self.inner.lock().await;
|
let mutation_range = self.entry_map.range(range.clone());
|
||||||
let mutation_range = mutations.entry_map.range(range.clone());
|
|
||||||
|
|
||||||
// fetch from TiKV
|
// fetch from TiKV
|
||||||
// fetch more entries because some of them may be deleted.
|
// fetch more entries because some of them may be deleted.
|
||||||
|
@ -177,7 +151,7 @@ impl Buffer {
|
||||||
|
|
||||||
// update local buffer
|
// update local buffer
|
||||||
for (k, v) in &results {
|
for (k, v) in &results {
|
||||||
Self::update_cache(&mut mutations, k.clone(), Some(v.clone()));
|
self.update_cache(k.clone(), Some(v.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut res = results
|
let mut res = results
|
||||||
|
@ -190,10 +164,9 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lock the given key if necessary.
|
/// Lock the given key if necessary.
|
||||||
pub async fn lock(&self, key: Key) {
|
pub async fn lock(&mut self, key: Key) {
|
||||||
let mutations = &mut self.inner.lock().await;
|
self.primary_key.get_or_insert_with(|| key.clone());
|
||||||
mutations.primary_key.get_or_insert_with(|| key.clone());
|
let value = self
|
||||||
let value = mutations
|
|
||||||
.entry_map
|
.entry_map
|
||||||
.entry(key)
|
.entry(key)
|
||||||
// Mutated keys don't need a lock.
|
// Mutated keys don't need a lock.
|
||||||
|
@ -205,27 +178,25 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a value into the buffer (does not write through).
|
/// Insert a value into the buffer (does not write through).
|
||||||
pub async fn put(&self, key: Key, value: Value) {
|
pub async fn put(&mut self, key: Key, value: Value) {
|
||||||
self.inner.lock().await.insert(key, BufferEntry::Put(value));
|
self.insert_entry(key, BufferEntry::Put(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark a value as Insert mutation into the buffer (does not write through).
|
/// Mark a value as Insert mutation into the buffer (does not write through).
|
||||||
pub async fn insert(&self, key: Key, value: Value) {
|
pub async fn insert(&mut self, key: Key, value: Value) {
|
||||||
let mut mutations = self.inner.lock().await;
|
let mut entry = self.entry_map.entry(key.clone());
|
||||||
let mut entry = mutations.entry_map.entry(key.clone());
|
|
||||||
match entry {
|
match entry {
|
||||||
Entry::Occupied(ref mut o) if matches!(o.get(), BufferEntry::Del) => {
|
Entry::Occupied(ref mut o) if matches!(o.get(), BufferEntry::Del) => {
|
||||||
o.insert(BufferEntry::Put(value));
|
o.insert(BufferEntry::Put(value));
|
||||||
}
|
}
|
||||||
_ => mutations.insert(key, BufferEntry::Insert(value)),
|
_ => self.insert_entry(key, BufferEntry::Insert(value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark a value as deleted.
|
/// Mark a value as deleted.
|
||||||
pub async fn delete(&self, key: Key) {
|
pub async fn delete(&mut self, key: Key) {
|
||||||
let mut mutations = self.inner.lock().await;
|
let is_pessimistic = self.is_pessimistic;
|
||||||
let is_pessimistic = mutations.is_pessimistic;
|
let mut entry = self.entry_map.entry(key.clone());
|
||||||
let mut entry = mutations.entry_map.entry(key.clone());
|
|
||||||
|
|
||||||
match entry {
|
match entry {
|
||||||
Entry::Occupied(ref mut o)
|
Entry::Occupied(ref mut o)
|
||||||
|
@ -233,40 +204,32 @@ impl Buffer {
|
||||||
{
|
{
|
||||||
o.insert(BufferEntry::CheckNotExist);
|
o.insert(BufferEntry::CheckNotExist);
|
||||||
}
|
}
|
||||||
_ => mutations.insert(key, BufferEntry::Del),
|
_ => self.insert_entry(key, BufferEntry::Del),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the buffered mutations to the proto buffer version
|
/// Converts the buffered mutations to the proto buffer version
|
||||||
pub async fn to_proto_mutations(&self) -> Vec<kvrpcpb::Mutation> {
|
pub async fn to_proto_mutations(&self) -> Vec<kvrpcpb::Mutation> {
|
||||||
self.inner
|
self.entry_map
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.entry_map
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(key, mutation)| mutation.to_proto_with_key(key))
|
.filter_map(|(key, mutation)| mutation.to_proto_with_key(key))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_from_mutations(&self, key: &Key) -> MutationValue {
|
async fn get_from_mutations(&self, key: &Key) -> MutationValue {
|
||||||
self.inner
|
self.entry_map
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.entry_map
|
|
||||||
.get(&key)
|
.get(&key)
|
||||||
.map(BufferEntry::get_value)
|
.map(BufferEntry::get_value)
|
||||||
.unwrap_or(MutationValue::Undetermined)
|
.unwrap_or(MutationValue::Undetermined)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_cache(buffer: &mut MutexGuard<InnerBuffer>, key: Key, value: Option<Value>) {
|
fn update_cache(&mut self, key: Key, value: Option<Value>) {
|
||||||
match buffer.entry_map.get(&key) {
|
match self.entry_map.get(&key) {
|
||||||
Some(BufferEntry::Locked(None)) => {
|
Some(BufferEntry::Locked(None)) => {
|
||||||
buffer
|
self.entry_map.insert(key, BufferEntry::Locked(Some(value)));
|
||||||
.entry_map
|
|
||||||
.insert(key, BufferEntry::Locked(Some(value)));
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
buffer.entry_map.insert(key, BufferEntry::Cached(value));
|
self.entry_map.insert(key, BufferEntry::Cached(value));
|
||||||
}
|
}
|
||||||
Some(BufferEntry::Cached(v)) | Some(BufferEntry::Locked(Some(v))) => {
|
Some(BufferEntry::Cached(v)) | Some(BufferEntry::Locked(Some(v))) => {
|
||||||
assert!(&value == v);
|
assert!(&value == v);
|
||||||
|
@ -285,6 +248,14 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_entry(&mut self, key: impl Into<Key>, entry: BufferEntry) {
|
||||||
|
let key = key.into();
|
||||||
|
if !matches!(entry, BufferEntry::Cached(_) | BufferEntry::CheckNotExist) {
|
||||||
|
self.primary_key.get_or_insert_with(|| key.clone());
|
||||||
|
}
|
||||||
|
self.entry_map.insert(key, entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The state of a key-value pair in the buffer.
|
// The state of a key-value pair in the buffer.
|
||||||
|
@ -388,7 +359,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
async fn set_and_get_from_buffer() {
|
async fn set_and_get_from_buffer() {
|
||||||
let buffer = Buffer::new(false);
|
let mut buffer = Buffer::new(false);
|
||||||
buffer
|
buffer
|
||||||
.put(b"key1".to_vec().into(), b"value1".to_vec())
|
.put(b"key1".to_vec().into(), b"value1".to_vec())
|
||||||
.await;
|
.await;
|
||||||
|
@ -421,7 +392,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
async fn insert_and_get_from_buffer() {
|
async fn insert_and_get_from_buffer() {
|
||||||
let buffer = Buffer::new(false);
|
let mut buffer = Buffer::new(false);
|
||||||
buffer
|
buffer
|
||||||
.insert(b"key1".to_vec().into(), b"value1".to_vec())
|
.insert(b"key1".to_vec().into(), b"value1".to_vec())
|
||||||
.await;
|
.await;
|
||||||
|
@ -463,13 +434,13 @@ mod tests {
|
||||||
let v2: Value = b"value2".to_vec();
|
let v2: Value = b"value2".to_vec();
|
||||||
let v2_ = v2.clone();
|
let v2_ = v2.clone();
|
||||||
|
|
||||||
let buffer = Buffer::new(false);
|
let mut buffer = Buffer::new(false);
|
||||||
let r1 = block_on(buffer.get_or_else(k1.clone(), move |_| ready(Ok(Some(v1_)))));
|
let r1 = block_on(buffer.get_or_else(k1.clone(), move |_| ready(Ok(Some(v1_)))));
|
||||||
let r2 = block_on(buffer.get_or_else(k1.clone(), move |_| ready(panic!())));
|
let r2 = block_on(buffer.get_or_else(k1.clone(), move |_| ready(panic!())));
|
||||||
assert_eq!(r1.unwrap().unwrap(), v1);
|
assert_eq!(r1.unwrap().unwrap(), v1);
|
||||||
assert_eq!(r2.unwrap().unwrap(), v1);
|
assert_eq!(r2.unwrap().unwrap(), v1);
|
||||||
|
|
||||||
let buffer = Buffer::new(false);
|
let mut buffer = Buffer::new(false);
|
||||||
let r1 = block_on(
|
let r1 = block_on(
|
||||||
buffer.batch_get_or_else(vec![k1.clone(), k2.clone()].into_iter(), move |_| {
|
buffer.batch_get_or_else(vec![k1.clone(), k2.clone()].into_iter(), move |_| {
|
||||||
ready(Ok(vec![(k1_, v1__).into(), (k2_, v2_).into()]))
|
ready(Ok(vec![(k1_, v1__).into(), (k2_, v2_).into()]))
|
||||||
|
|
|
@ -19,18 +19,18 @@ pub struct Snapshot {
|
||||||
|
|
||||||
impl Snapshot {
|
impl Snapshot {
|
||||||
/// Get the value associated with the given key.
|
/// Get the value associated with the given key.
|
||||||
pub async fn get(&self, key: impl Into<Key>) -> Result<Option<Value>> {
|
pub async fn get(&mut self, key: impl Into<Key>) -> Result<Option<Value>> {
|
||||||
self.transaction.get(key).await
|
self.transaction.get(key).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the key exists.
|
/// Check whether the key exists.
|
||||||
pub async fn key_exists(&self, key: impl Into<Key>) -> Result<bool> {
|
pub async fn key_exists(&mut self, key: impl Into<Key>) -> Result<bool> {
|
||||||
self.transaction.key_exists(key).await
|
self.transaction.key_exists(key).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the values associated with the given keys.
|
/// Get the values associated with the given keys.
|
||||||
pub async fn batch_get(
|
pub async fn batch_get(
|
||||||
&self,
|
&mut self,
|
||||||
keys: impl IntoIterator<Item = impl Into<Key>>,
|
keys: impl IntoIterator<Item = impl Into<Key>>,
|
||||||
) -> Result<impl Iterator<Item = KvPair>> {
|
) -> Result<impl Iterator<Item = KvPair>> {
|
||||||
self.transaction.batch_get(keys).await
|
self.transaction.batch_get(keys).await
|
||||||
|
@ -38,7 +38,7 @@ impl Snapshot {
|
||||||
|
|
||||||
/// Scan a range, return at most `limit` key-value pairs that lying in the range.
|
/// Scan a range, return at most `limit` key-value pairs that lying in the range.
|
||||||
pub async fn scan(
|
pub async fn scan(
|
||||||
&self,
|
&mut self,
|
||||||
range: impl Into<BoundRange>,
|
range: impl Into<BoundRange>,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
) -> Result<impl Iterator<Item = KvPair>> {
|
) -> Result<impl Iterator<Item = KvPair>> {
|
||||||
|
@ -47,7 +47,7 @@ impl Snapshot {
|
||||||
|
|
||||||
/// Scan a range, return at most `limit` keys that lying in the range.
|
/// Scan a range, return at most `limit` keys that lying in the range.
|
||||||
pub async fn scan_keys(
|
pub async fn scan_keys(
|
||||||
&self,
|
&mut self,
|
||||||
range: impl Into<BoundRange>,
|
range: impl Into<BoundRange>,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
) -> Result<impl Iterator<Item = Key>> {
|
) -> Result<impl Iterator<Item = Key>> {
|
||||||
|
@ -56,7 +56,7 @@ impl Snapshot {
|
||||||
|
|
||||||
/// Unimplemented. Similar to scan, but in the reverse direction.
|
/// Unimplemented. Similar to scan, but in the reverse direction.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn scan_reverse(&self, range: impl RangeBounds<Key>) -> BoxStream<Result<KvPair>> {
|
fn scan_reverse(&mut self, range: impl RangeBounds<Key>) -> BoxStream<Result<KvPair>> {
|
||||||
self.transaction.scan_reverse(range)
|
self.transaction.scan_reverse(range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl<PdC: PdClient> Transaction<PdC> {
|
||||||
/// txn.commit().await.unwrap();
|
/// txn.commit().await.unwrap();
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn get(&self, key: impl Into<Key>) -> Result<Option<Value>> {
|
pub async fn get(&mut self, key: impl Into<Key>) -> Result<Option<Value>> {
|
||||||
self.check_allow_operation().await?;
|
self.check_allow_operation().await?;
|
||||||
let timestamp = self.timestamp.clone();
|
let timestamp = self.timestamp.clone();
|
||||||
let rpc = self.rpc.clone();
|
let rpc = self.rpc.clone();
|
||||||
|
@ -184,7 +184,7 @@ impl<PdC: PdClient> Transaction<PdC> {
|
||||||
/// txn.commit().await.unwrap();
|
/// txn.commit().await.unwrap();
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn key_exists(&self, key: impl Into<Key>) -> Result<bool> {
|
pub async fn key_exists(&mut self, key: impl Into<Key>) -> Result<bool> {
|
||||||
let key = key.into();
|
let key = key.into();
|
||||||
Ok(self.scan_keys(key.clone()..=key, 1).await?.next().is_some())
|
Ok(self.scan_keys(key.clone()..=key, 1).await?.next().is_some())
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ impl<PdC: PdClient> Transaction<PdC> {
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn batch_get(
|
pub async fn batch_get(
|
||||||
&self,
|
&mut self,
|
||||||
keys: impl IntoIterator<Item = impl Into<Key>>,
|
keys: impl IntoIterator<Item = impl Into<Key>>,
|
||||||
) -> Result<impl Iterator<Item = KvPair>> {
|
) -> Result<impl Iterator<Item = KvPair>> {
|
||||||
self.check_allow_operation().await?;
|
self.check_allow_operation().await?;
|
||||||
|
@ -307,7 +307,7 @@ impl<PdC: PdClient> Transaction<PdC> {
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn scan(
|
pub async fn scan(
|
||||||
&self,
|
&mut self,
|
||||||
range: impl Into<BoundRange>,
|
range: impl Into<BoundRange>,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
) -> Result<impl Iterator<Item = KvPair>> {
|
) -> Result<impl Iterator<Item = KvPair>> {
|
||||||
|
@ -341,7 +341,7 @@ impl<PdC: PdClient> Transaction<PdC> {
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn scan_keys(
|
pub async fn scan_keys(
|
||||||
&self,
|
&mut self,
|
||||||
range: impl Into<BoundRange>,
|
range: impl Into<BoundRange>,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
) -> Result<impl Iterator<Item = Key>> {
|
) -> Result<impl Iterator<Item = Key>> {
|
||||||
|
@ -602,7 +602,7 @@ impl<PdC: PdClient> Transaction<PdC> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn scan_inner(
|
async fn scan_inner(
|
||||||
&self,
|
&mut self,
|
||||||
range: impl Into<BoundRange>,
|
range: impl Into<BoundRange>,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
key_only: bool,
|
key_only: bool,
|
||||||
|
|
|
@ -103,7 +103,7 @@ async fn crud() -> Result<()> {
|
||||||
txn.commit().await?;
|
txn.commit().await?;
|
||||||
|
|
||||||
// Read again from TiKV
|
// Read again from TiKV
|
||||||
let snapshot = client.snapshot(
|
let mut snapshot = client.snapshot(
|
||||||
client.current_timestamp().await?,
|
client.current_timestamp().await?,
|
||||||
// TODO needed because pessimistic does not check locks (#235)
|
// TODO needed because pessimistic does not check locks (#235)
|
||||||
TransactionOptions::new_optimistic(),
|
TransactionOptions::new_optimistic(),
|
||||||
|
@ -339,9 +339,9 @@ async fn txn_bank_transfer() -> Result<()> {
|
||||||
.await?;
|
.await?;
|
||||||
let chosen_people = people.iter().choose_multiple(&mut rng, 2);
|
let chosen_people = people.iter().choose_multiple(&mut rng, 2);
|
||||||
let alice = chosen_people[0];
|
let alice = chosen_people[0];
|
||||||
let mut alice_balance = get_txn_u32(&txn, alice.clone()).await?;
|
let mut alice_balance = get_txn_u32(&mut txn, alice.clone()).await?;
|
||||||
let bob = chosen_people[1];
|
let bob = chosen_people[1];
|
||||||
let mut bob_balance = get_txn_u32(&txn, bob.clone()).await?;
|
let mut bob_balance = get_txn_u32(&mut txn, bob.clone()).await?;
|
||||||
if alice_balance == 0 {
|
if alice_balance == 0 {
|
||||||
txn.rollback().await?;
|
txn.rollback().await?;
|
||||||
continue;
|
continue;
|
||||||
|
@ -360,7 +360,7 @@ async fn txn_bank_transfer() -> Result<()> {
|
||||||
let mut new_sum = 0;
|
let mut new_sum = 0;
|
||||||
let mut txn = client.begin_optimistic().await?;
|
let mut txn = client.begin_optimistic().await?;
|
||||||
for person in people.iter() {
|
for person in people.iter() {
|
||||||
new_sum += get_txn_u32(&txn, person.clone()).await?;
|
new_sum += get_txn_u32(&mut txn, person.clone()).await?;
|
||||||
}
|
}
|
||||||
assert_eq!(sum, new_sum);
|
assert_eq!(sum, new_sum);
|
||||||
txn.commit().await?;
|
txn.commit().await?;
|
||||||
|
@ -827,7 +827,7 @@ async fn get_u32(client: &RawClient, key: Vec<u8>) -> Result<u32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function
|
// helper function
|
||||||
async fn get_txn_u32(txn: &Transaction, key: Vec<u8>) -> Result<u32> {
|
async fn get_txn_u32(txn: &mut Transaction, key: Vec<u8>) -> Result<u32> {
|
||||||
let x = txn.get(key).await?.unwrap();
|
let x = txn.get(key).await?.unwrap();
|
||||||
let boxed_slice = x.into_boxed_slice();
|
let boxed_slice = x.into_boxed_slice();
|
||||||
let array: Box<[u8; 4]> = boxed_slice
|
let array: Box<[u8; 4]> = boxed_slice
|
||||||
|
|
Loading…
Reference in New Issue