SavePoint: Avoid calling get twice on put, putc and delc ()

This commit is contained in:
Emmanuel Keller 2024-09-12 16:14:28 +01:00 committed by GitHub
parent bfa8e98753
commit 4e2b2b9e30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 90 additions and 28 deletions

View file

@ -36,7 +36,7 @@ impl Document {
let mut doc = Document::new(pro.rid, pro.ir, ins.0, ins.1); 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 // Optionally create a save point so we can roll back any upcoming changes
let is_save_point = if !stm.is_select() { let is_save_point = if !stm.is_select() {
ctx.tx().lock().await.new_save_point(); ctx.tx().lock().await.new_save_point().await;
true true
} else { } else {
false false
@ -96,7 +96,7 @@ impl Document {
Ok(v) => { Ok(v) => {
// The statement is successful, we can release the savepoint // The statement is successful, we can release the savepoint
if is_save_point { if is_save_point {
ctx.tx().lock().await.release_last_save_point()?; ctx.tx().lock().await.release_last_save_point().await?;
} }
Ok(v) Ok(v)
} }

View file

@ -30,7 +30,7 @@ impl Document {
let mut doc = Document::new(pro.rid, pro.ir, ins.0, ins.1); 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 // Optionally create a save point so we can roll back any upcoming changes
let is_save_point = if !stm.is_select() { let is_save_point = if !stm.is_select() {
ctx.tx().lock().await.new_save_point(); ctx.tx().lock().await.new_save_point().await;
true true
} else { } else {
false false
@ -90,7 +90,7 @@ impl Document {
Ok(v) => { Ok(v) => {
// The statement is successful, we can release the savepoint // The statement is successful, we can release the savepoint
if is_save_point { if is_save_point {
ctx.tx().lock().await.release_last_save_point()?; ctx.tx().lock().await.release_last_save_point().await?;
} }
Ok(v) Ok(v)
} }

View file

@ -4,7 +4,7 @@ mod cnf;
use crate::err::Error; use crate::err::Error;
use crate::key::debug::Sprintable; 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::Check;
use crate::kvs::Key; use crate::kvs::Key;
use crate::kvs::Val; use crate::kvs::Val;
@ -332,11 +332,18 @@ impl super::api::Transaction for Transaction {
}; };
// Get the transaction // Get the transaction
let inner = self.inner.as_ref().unwrap(); let inner = self.inner.as_ref().unwrap();
// Set the key if empty // Get the existing value (if any)
match inner.get(&key, self.snapshot()).await? { let key_exists = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
None => inner.set(&key, &val), sv.get_val().is_some()
_ => return Err(Error::TxKeyAlreadyExists), } 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 // Confirm the save point
if let Some(prep) = prep { if let Some(prep) = prep {
self.save_points.save(prep); self.save_points.save(prep);
@ -372,9 +379,15 @@ impl super::api::Transaction for Transaction {
}; };
// Get the transaction // Get the transaction
let inner = self.inner.as_ref().unwrap(); 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 // Set the key if valid
match (inner.get(&key, self.snapshot()).await?, chk) { match (current_val, chk) {
(Some(v), Some(w)) if *v.as_ref() == w => inner.set(&key, &val), (Some(v), Some(w)) if v == w => inner.set(&key, &val),
(None, None) => inner.set(&key, &val), (None, None) => inner.set(&key, &val),
_ => return Err(Error::TxConditionNotMet), _ => return Err(Error::TxConditionNotMet),
}; };
@ -444,9 +457,15 @@ impl super::api::Transaction for Transaction {
}; };
// Get the transaction // Get the transaction
let inner = self.inner.as_ref().unwrap(); 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 // Delete the key if valid
match (inner.get(&key, self.snapshot()).await?, chk) { match (current_val, chk) {
(Some(v), Some(w)) if *v.as_ref() == w => inner.clear(&key), (Some(v), Some(w)) if v == w => inner.clear(&key),
(None, None) => inner.clear(&key), (None, None) => inner.clear(&key),
_ => return Err(Error::TxConditionNotMet), _ => return Err(Error::TxConditionNotMet),
}; };

View file

@ -26,6 +26,10 @@ impl SavedValue {
last_operation: op, last_operation: op,
} }
} }
pub(super) fn get_val(&self) -> Option<&Val> {
self.saved_val.as_ref()
}
} }
pub(super) enum SavePrepare { pub(super) enum SavePrepare {

View file

@ -2,7 +2,7 @@
use crate::err::Error; use crate::err::Error;
use crate::key::debug::Sprintable; 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::Check;
use crate::kvs::Key; use crate::kvs::Key;
use crate::kvs::Val; use crate::kvs::Val;
@ -246,10 +246,18 @@ impl super::api::Transaction for Transaction {
if let Some(ts) = version { if let Some(ts) = version {
self.inner.set_at_ts(&key, &val, ts)?; self.inner.set_at_ts(&key, &val, ts)?;
} else { } else {
match self.inner.get(&key)? { // Does the key exists?
None => self.inner.set(&key, &val)?, let key_exists = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
_ => return Err(Error::TxKeyAlreadyExists), 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 // Confirm the save point
if let Some(prep) = prep { if let Some(prep) = prep {
@ -284,8 +292,14 @@ impl super::api::Transaction for Transaction {
} else { } else {
None 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 // 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)?, (Some(v), Some(w)) if v == w => self.inner.set(&key, &val)?,
(None, None) => self.inner.set(&key, &val)?, (None, None) => self.inner.set(&key, &val)?,
_ => return Err(Error::TxConditionNotMet), _ => return Err(Error::TxConditionNotMet),
@ -354,8 +368,14 @@ impl super::api::Transaction for Transaction {
} else { } else {
None 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 // 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)?, (Some(v), Some(w)) if v == w => self.inner.delete(&key)?,
(None, None) => self.inner.delete(&key)?, (None, None) => self.inner.delete(&key)?,
_ => return Err(Error::TxConditionNotMet), _ => return Err(Error::TxConditionNotMet),

View file

@ -2,7 +2,7 @@
use crate::err::Error; use crate::err::Error;
use crate::key::debug::Sprintable; 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::Check;
use crate::kvs::Key; use crate::kvs::Key;
use crate::kvs::Val; use crate::kvs::Val;
@ -279,11 +279,18 @@ impl super::api::Transaction for Transaction {
} else { } else {
None None
}; };
// Set the key if empty // Get the existing value (if any)
match self.inner.key_exists(key.clone()).await? { let key_exists = if let Some(SavePrepare::NewKey(_, sv)) = &prep {
false => self.inner.put(key, val).await?, sv.get_val().is_some()
_ => return Err(Error::TxKeyAlreadyExists), } 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 // Confirm the save point
if let Some(prep) = prep { if let Some(prep) = prep {
self.save_points.save(prep); self.save_points.save(prep);
@ -319,8 +326,14 @@ impl super::api::Transaction for Transaction {
} else { } else {
None 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 // 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?, (Some(v), Some(w)) if v == w => self.inner.put(key, val).await?,
(None, None) => self.inner.put(key, val).await?, (None, None) => self.inner.put(key, val).await?,
_ => return Err(Error::TxConditionNotMet), _ => return Err(Error::TxConditionNotMet),
@ -390,8 +403,14 @@ impl super::api::Transaction for Transaction {
} else { } else {
None 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 // 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?, (Some(v), Some(w)) if v == w => self.inner.delete(key).await?,
(None, None) => self.inner.delete(key).await?, (None, None) => self.inner.delete(key).await?,
_ => return Err(Error::TxConditionNotMet), _ => return Err(Error::TxConditionNotMet),

View file

@ -648,7 +648,7 @@ impl Transactor {
Ok(None) 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() }) 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 }) 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() }) expand_inner!(&mut self.inner, v => { v.release_last_save_point() })
} }
} }