Add sdel concurrency tests

next
Sayan Nandan 3 years ago
parent 62b58f1a9f
commit a8b716c892

@ -39,3 +39,6 @@ pub use self::{sdel::sdel, sset::sset, supdate::supdate};
mod sdel; mod sdel;
mod sset; mod sset;
mod supdate; mod supdate;
#[cfg(test)]
mod tests;

@ -56,7 +56,11 @@ action! {
/// Snapshot the current status and then delete maintaining concurrency /// Snapshot the current status and then delete maintaining concurrency
/// guarantees. `(all_okay, enc_err)` /// guarantees. `(all_okay, enc_err)`
fn snapshot_and_del(kve: &KVEngine, key_encoder: SingleEncoder, act: ActionIter) -> (bool, bool) { pub(super) fn snapshot_and_del(
kve: &KVEngine,
key_encoder: SingleEncoder,
act: ActionIter,
) -> (bool, bool) {
let mut snapshots = Vec::with_capacity(act.len()); let mut snapshots = Vec::with_capacity(act.len());
let mut err_enc = false; let mut err_enc = false;
let iter_stat_ok; let iter_stat_ok;
@ -75,6 +79,10 @@ fn snapshot_and_del(kve: &KVEngine, key_encoder: SingleEncoder, act: ActionIter)
} }
}); });
} }
cfg_test!({
// give the caller 10 seconds to do some crap
do_sleep!(10 s);
});
if iter_stat_ok { if iter_stat_ok {
// nice, all keys exist; let's plonk 'em // nice, all keys exist; let's plonk 'em
let kve = kve; let kve = kve;

@ -35,7 +35,7 @@ action! {
/// ///
/// This either returns `Okay` if all the keys were set, or it returns an /// This either returns `Okay` if all the keys were set, or it returns an
/// `Overwrite Error` or code `2` /// `Overwrite Error` or code `2`
fn sset(handle: &crate::corestore::Corestore, con: &mut T, mut act: ActionIter) { fn sset(handle: &crate::corestore::Corestore, con: &mut T, act: ActionIter) {
let howmany = act.len(); let howmany = act.len();
if is_lowbit_set!(howmany) || howmany == 0 { if is_lowbit_set!(howmany) || howmany == 0 {
return con.write_response(responses::groups::ACTION_ERR).await; return con.write_response(responses::groups::ACTION_ERR).await;
@ -79,6 +79,10 @@ fn snapshot_and_insert(
} }
}); });
} }
cfg_test!({
// give the caller 5 seconds to do some crap
do_sleep!(5 s);
});
if key_iter_stat_ok { if key_iter_stat_ok {
let _kve = kve; let _kve = kve;
let lowtable = lowtable; let lowtable = lowtable;

@ -35,7 +35,7 @@ action! {
/// ///
/// This either returns `Okay` if all the keys were updated, or it returns `Nil` /// This either returns `Okay` if all the keys were updated, or it returns `Nil`
/// or code `1` /// or code `1`
fn supdate(handle: &crate::corestore::Corestore, con: &mut T, mut act: ActionIter) { fn supdate(handle: &crate::corestore::Corestore, con: &mut T, act: ActionIter) {
let howmany = act.len(); let howmany = act.len();
if is_lowbit_set!(howmany) || howmany == 0 { if is_lowbit_set!(howmany) || howmany == 0 {
return con.write_response(responses::groups::ACTION_ERR).await; return con.write_response(responses::groups::ACTION_ERR).await;

@ -0,0 +1,63 @@
/*
* Created on Fri Jul 30 2021
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2021, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
mod sdel_concurrency_tests {
use super::super::sdel;
use crate::corestore::Data;
use crate::kvengine::KVEngine;
use std::sync::Arc;
use std::thread;
#[test]
fn test_snapshot_okay() {
let kve = KVEngine::init(true, true);
let encoder = kve.get_key_encoder();
let it = bi!("k1", "v1", "k2", "v2");
sdel::snapshot_and_del(&kve, encoder, it);
}
#[test]
fn test_snapshot_fail_with_t2() {
let kve = Arc::new(KVEngine::init(true, true));
let kve1 = kve.clone();
let encoder = kve.get_key_encoder();
{
kve.upsert(Data::from("k1"), Data::from("v1")).unwrap();
kve.upsert(Data::from("k2"), Data::from("v2")).unwrap();
}
let it = bi!("k1", "k2");
// sdel will wait 10s for us
let t1handle = thread::spawn(move || sdel::snapshot_and_del(&kve1, encoder, it));
// we have 10s: we sleep 5 to let the snapshot complete (thread spawning takes time)
do_sleep!(5 s);
assert!(kve
.update(Data::from("k1"), Data::from("updated-v1"))
.unwrap());
// let us join t1
t1handle.join().unwrap();
// although we told sdel to delete it, it shouldn't because we externally
// updated the value
assert!(kve.exists(Data::from("k1")).unwrap());
}
}

@ -283,7 +283,7 @@ impl Corestore {
Some(ks) => { Some(ks) => {
let tbl = Table::from_model_code(modelcode, volatile); let tbl = Table::from_model_code(modelcode, volatile);
if let Some(tbl) = tbl { if let Some(tbl) = tbl {
if ks.create_table(tblid.clone(), tbl) { if ks.create_table(tblid, tbl) {
Ok(()) Ok(())
} else { } else {
Err(DdlError::AlreadyExists) Err(DdlError::AlreadyExists)
@ -300,7 +300,7 @@ impl Corestore {
Some(kspace) => { Some(kspace) => {
let tbl = Table::from_model_code(modelcode, volatile); let tbl = Table::from_model_code(modelcode, volatile);
if let Some(tbl) = tbl { if let Some(tbl) = tbl {
if kspace.create_table(tblid.clone(), tbl) { if kspace.create_table(tblid, tbl) {
Ok(()) Ok(())
} else { } else {
Err(DdlError::AlreadyExists) Err(DdlError::AlreadyExists)

@ -26,17 +26,6 @@
use super::parser; use super::parser;
macro_rules! byt {
($f:expr) => {
bytes::Bytes::from($f)
};
}
macro_rules! bi {
($($x:expr),+ $(,)?) => {{
vec![$(bytes::Bytes::from($x),)*].into_iter()
}};
}
mod parser_ddl_tests { mod parser_ddl_tests {
use super::parser::parse_table_args; use super::parser::parse_table_args;
use crate::corestore::memstore::ObjectID; use crate::corestore::memstore::ObjectID;

@ -93,6 +93,10 @@ macro_rules! typedef {
#[macro_export] #[macro_export]
macro_rules! cfg_test { macro_rules! cfg_test {
($block:block) => {
#[cfg(test)]
$block
};
($($item:item)*) => { ($($item:item)*) => {
$(#[cfg(test)] $item)* $(#[cfg(test)] $item)*
}; };
@ -191,3 +195,23 @@ pub mod compiler {
b b
} }
} }
#[macro_export]
macro_rules! byt {
($f:expr) => {
bytes::Bytes::from($f)
};
}
#[macro_export]
macro_rules! bi {
($($x:expr),+ $(,)?) => {{
vec![$(bytes::Bytes::from($x),)*].into_iter()
}};
}
#[macro_export]
macro_rules! do_sleep {
($dur:literal s) => {{
std::thread::sleep(std::time::Duration::from_secs($dur));
}};
}

Loading…
Cancel
Save