SavePoint: Avoid calling get twice on put, putc and delc (#4731)
This commit is contained in:
parent
bfa8e98753
commit
4e2b2b9e30
7 changed files with 90 additions and 28 deletions
|
@ -36,7 +36,7 @@ impl Document {
|
|||
let mut doc = Document::new(pro.rid, pro.ir, ins.0, ins.1);
|
||||
// Optionally create a save point so we can roll back any upcoming changes
|
||||
let is_save_point = if !stm.is_select() {
|
||||
ctx.tx().lock().await.new_save_point();
|
||||
ctx.tx().lock().await.new_save_point().await;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -96,7 +96,7 @@ impl Document {
|
|||
Ok(v) => {
|
||||
// The statement is successful, we can release the savepoint
|
||||
if is_save_point {
|
||||
ctx.tx().lock().await.release_last_save_point()?;
|
||||
ctx.tx().lock().await.release_last_save_point().await?;
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ impl Document {
|
|||
let mut doc = Document::new(pro.rid, pro.ir, ins.0, ins.1);
|
||||
// Optionally create a save point so we can roll back any upcoming changes
|
||||
let is_save_point = if !stm.is_select() {
|
||||
ctx.tx().lock().await.new_save_point();
|
||||
ctx.tx().lock().await.new_save_point().await;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -90,7 +90,7 @@ impl Document {
|
|||
Ok(v) => {
|
||||
// The statement is successful, we can release the savepoint
|
||||
if is_save_point {
|
||||
ctx.tx().lock().await.release_last_save_point()?;
|
||||
ctx.tx().lock().await.release_last_save_point().await?;
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ mod cnf;
|
|||
|
||||
use crate::err::Error;
|
||||
use crate::key::debug::Sprintable;
|
||||
use crate::kvs::savepoint::{SaveOperation, SavePointImpl, SavePoints};
|
||||
use crate::kvs::savepoint::{SaveOperation, SavePointImpl, SavePoints, SavePrepare};
|
||||
use crate::kvs::Check;
|
||||
use crate::kvs::Key;
|
||||
use crate::kvs::Val;
|
||||
|
@ -332,11 +332,18 @@ impl super::api::Transaction for Transaction {
|
|||
};
|
||||
// Get the transaction
|
||||
let inner = self.inner.as_ref().unwrap();
|
||||
// Set the key if empty
|
||||
match inner.get(&key, self.snapshot()).await? {
|
||||
None => inner.set(&key, &val),
|
||||
_ => return Err(Error::TxKeyAlreadyExists),
|
||||
// Get the existing value (if any)
|
||||
let key_exists = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().is_some()
|
||||
} else {
|
||||
inner.get(&key, self.snapshot()).await?.is_some()
|
||||
};
|
||||
// If the key exists we return an error
|
||||
if key_exists {
|
||||
return Err(Error::TxKeyAlreadyExists);
|
||||
}
|
||||
// Set the key if empty
|
||||
inner.set(&key, &val);
|
||||
// Confirm the save point
|
||||
if let Some(prep) = prep {
|
||||
self.save_points.save(prep);
|
||||
|
@ -372,9 +379,15 @@ impl super::api::Transaction for Transaction {
|
|||
};
|
||||
// Get the transaction
|
||||
let inner = self.inner.as_ref().unwrap();
|
||||
// Get the existing value (if any)
|
||||
let current_val = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().cloned()
|
||||
} else {
|
||||
inner.get(&key, self.snapshot()).await?.map(|v| v.to_vec())
|
||||
};
|
||||
// Set the key if valid
|
||||
match (inner.get(&key, self.snapshot()).await?, chk) {
|
||||
(Some(v), Some(w)) if *v.as_ref() == w => inner.set(&key, &val),
|
||||
match (current_val, chk) {
|
||||
(Some(v), Some(w)) if v == w => inner.set(&key, &val),
|
||||
(None, None) => inner.set(&key, &val),
|
||||
_ => return Err(Error::TxConditionNotMet),
|
||||
};
|
||||
|
@ -444,9 +457,15 @@ impl super::api::Transaction for Transaction {
|
|||
};
|
||||
// Get the transaction
|
||||
let inner = self.inner.as_ref().unwrap();
|
||||
// Get the existing value (if any)
|
||||
let current_val = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().cloned()
|
||||
} else {
|
||||
inner.get(&key, self.snapshot()).await?.map(|v| v.to_vec())
|
||||
};
|
||||
// Delete the key if valid
|
||||
match (inner.get(&key, self.snapshot()).await?, chk) {
|
||||
(Some(v), Some(w)) if *v.as_ref() == w => inner.clear(&key),
|
||||
match (current_val, chk) {
|
||||
(Some(v), Some(w)) if v == w => inner.clear(&key),
|
||||
(None, None) => inner.clear(&key),
|
||||
_ => return Err(Error::TxConditionNotMet),
|
||||
};
|
||||
|
|
|
@ -26,6 +26,10 @@ impl SavedValue {
|
|||
last_operation: op,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_val(&self) -> Option<&Val> {
|
||||
self.saved_val.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) enum SavePrepare {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::err::Error;
|
||||
use crate::key::debug::Sprintable;
|
||||
use crate::kvs::savepoint::{SaveOperation, SavePointImpl, SavePoints};
|
||||
use crate::kvs::savepoint::{SaveOperation, SavePointImpl, SavePoints, SavePrepare};
|
||||
use crate::kvs::Check;
|
||||
use crate::kvs::Key;
|
||||
use crate::kvs::Val;
|
||||
|
@ -246,10 +246,18 @@ impl super::api::Transaction for Transaction {
|
|||
if let Some(ts) = version {
|
||||
self.inner.set_at_ts(&key, &val, ts)?;
|
||||
} else {
|
||||
match self.inner.get(&key)? {
|
||||
None => self.inner.set(&key, &val)?,
|
||||
_ => return Err(Error::TxKeyAlreadyExists),
|
||||
// Does the key exists?
|
||||
let key_exists = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().is_some()
|
||||
} else {
|
||||
self.inner.get(&key)?.is_some()
|
||||
};
|
||||
// If the key exist we return an error
|
||||
if key_exists {
|
||||
return Err(Error::TxKeyAlreadyExists);
|
||||
}
|
||||
// Set the key/value
|
||||
self.inner.set(&key, &val)?;
|
||||
}
|
||||
// Confirm the save point
|
||||
if let Some(prep) = prep {
|
||||
|
@ -284,8 +292,14 @@ impl super::api::Transaction for Transaction {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// Does the key exists?
|
||||
let current_val = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().cloned()
|
||||
} else {
|
||||
self.inner.get(&key)?
|
||||
};
|
||||
// Set the key if valid
|
||||
match (self.inner.get(&key)?, chk) {
|
||||
match (current_val, chk) {
|
||||
(Some(v), Some(w)) if v == w => self.inner.set(&key, &val)?,
|
||||
(None, None) => self.inner.set(&key, &val)?,
|
||||
_ => return Err(Error::TxConditionNotMet),
|
||||
|
@ -354,8 +368,14 @@ impl super::api::Transaction for Transaction {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// Does the key exists?
|
||||
let current_val = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().cloned()
|
||||
} else {
|
||||
self.inner.get(&key)?
|
||||
};
|
||||
// Delete the key if valid
|
||||
match (self.inner.get(&key)?, chk) {
|
||||
match (current_val, chk) {
|
||||
(Some(v), Some(w)) if v == w => self.inner.delete(&key)?,
|
||||
(None, None) => self.inner.delete(&key)?,
|
||||
_ => return Err(Error::TxConditionNotMet),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::err::Error;
|
||||
use crate::key::debug::Sprintable;
|
||||
use crate::kvs::savepoint::{SaveOperation, SavePointImpl, SavePoints};
|
||||
use crate::kvs::savepoint::{SaveOperation, SavePointImpl, SavePoints, SavePrepare};
|
||||
use crate::kvs::Check;
|
||||
use crate::kvs::Key;
|
||||
use crate::kvs::Val;
|
||||
|
@ -279,11 +279,18 @@ impl super::api::Transaction for Transaction {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// Set the key if empty
|
||||
match self.inner.key_exists(key.clone()).await? {
|
||||
false => self.inner.put(key, val).await?,
|
||||
_ => return Err(Error::TxKeyAlreadyExists),
|
||||
// Get the existing value (if any)
|
||||
let key_exists = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().is_some()
|
||||
} else {
|
||||
self.inner.key_exists(key.clone()).await?
|
||||
};
|
||||
// If the key exists we return an error
|
||||
if key_exists {
|
||||
return Err(Error::TxKeyAlreadyExists);
|
||||
}
|
||||
// Set the key if empty
|
||||
self.inner.put(key, val).await?;
|
||||
// Confirm the save point
|
||||
if let Some(prep) = prep {
|
||||
self.save_points.save(prep);
|
||||
|
@ -319,8 +326,14 @@ impl super::api::Transaction for Transaction {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// Get the existing value (if any)
|
||||
let current_val = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().cloned()
|
||||
} else {
|
||||
self.inner.get(key.clone()).await?
|
||||
};
|
||||
// Delete the key
|
||||
match (self.inner.get(key.clone()).await?, chk) {
|
||||
match (current_val, chk) {
|
||||
(Some(v), Some(w)) if v == w => self.inner.put(key, val).await?,
|
||||
(None, None) => self.inner.put(key, val).await?,
|
||||
_ => return Err(Error::TxConditionNotMet),
|
||||
|
@ -390,8 +403,14 @@ impl super::api::Transaction for Transaction {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
// Get the existing value (if any)
|
||||
let current_val = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
|
||||
sv.get_val().cloned()
|
||||
} else {
|
||||
self.inner.get(key.clone()).await?
|
||||
};
|
||||
// Delete the key
|
||||
match (self.inner.get(key.clone()).await?, chk) {
|
||||
match (current_val, chk) {
|
||||
(Some(v), Some(w)) if v == w => self.inner.delete(key).await?,
|
||||
(None, None) => self.inner.delete(key).await?,
|
||||
_ => return Err(Error::TxConditionNotMet),
|
||||
|
|
|
@ -648,7 +648,7 @@ impl Transactor {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
pub(crate) fn new_save_point(&mut self) {
|
||||
pub(crate) async fn new_save_point(&mut self) {
|
||||
expand_inner!(&mut self.inner, v => { v.new_save_point() })
|
||||
}
|
||||
|
||||
|
@ -656,7 +656,7 @@ impl Transactor {
|
|||
expand_inner!(&mut self.inner, v => { v.rollback_to_save_point().await })
|
||||
}
|
||||
|
||||
pub(crate) fn release_last_save_point(&mut self) -> Result<(), Error> {
|
||||
pub(crate) async fn release_last_save_point(&mut self) -> Result<(), Error> {
|
||||
expand_inner!(&mut self.inner, v => { v.release_last_save_point() })
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue