#[cfg(feature = "var-collections")]
use armdb::VarTree;
use armdb::{Config, ConstTree};
use std::sync::Arc;
use std::thread;
use tempfile::tempdir;
#[test]
fn test_concurrent_writes() {
let dir = tempdir().expect("failed to create tempdir");
let config = Config::test();
let tree = Arc::new(
ConstTree::<[u8; 8], 8>::open(dir.path(), config).expect("failed to create const tree"),
);
let mut handles = Vec::new();
for t in 0..4u64 {
let tree = Arc::clone(&tree);
let handle = thread::spawn(move || {
let start = t * 250;
let end = start + 250;
for i in start..end {
let key = i.to_be_bytes();
let value = (i * 7).to_be_bytes();
tree.put(&key, &value).expect("put failed");
}
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("thread panicked");
}
assert_eq!(tree.len(), 1000);
for i in 0..1000u64 {
let key = i.to_be_bytes();
let expected = (i * 7).to_be_bytes();
let val = tree
.get(&key)
.unwrap_or_else(|| panic!("key {} not found", i));
assert_eq!(val, expected, "value mismatch for key {}", i);
}
}
#[test]
fn test_concurrent_read_write() {
let dir = tempdir().expect("failed to create tempdir");
let config = Config::test();
let tree = Arc::new(
ConstTree::<[u8; 8], 8>::open(dir.path(), config).expect("failed to create const tree"),
);
for i in 0..100u64 {
let key = i.to_be_bytes();
let value = (i * 7).to_be_bytes();
tree.put(&key, &value).expect("pre-populate put failed");
}
let mut handles = Vec::new();
{
let tree = Arc::clone(&tree);
let handle = thread::spawn(move || {
for i in 100..1000u64 {
let key = i.to_be_bytes();
let value = (i * 7).to_be_bytes();
tree.put(&key, &value).expect("writer put failed");
}
});
handles.push(handle);
}
for _ in 0..3 {
let tree = Arc::clone(&tree);
let handle = thread::spawn(move || {
for iter in 0..1000u64 {
let i = iter % 1000;
let key = i.to_be_bytes();
if let Some(val) = tree.get(&key) {
let expected = (i * 7).to_be_bytes();
assert_eq!(val, expected, "reader got wrong value for key {}", i);
}
}
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("thread panicked");
}
assert_eq!(tree.len(), 1000);
for i in 0..1000u64 {
let key = i.to_be_bytes();
let expected = (i * 7).to_be_bytes();
let val = tree
.get(&key)
.unwrap_or_else(|| panic!("key {} not found after join", i));
assert_eq!(val, expected, "final value mismatch for key {}", i);
}
}
#[cfg(feature = "var-collections")]
#[test]
fn test_concurrent_var_writes() {
let dir = tempdir().expect("failed to create tempdir");
let config = Config::test();
let tree =
Arc::new(VarTree::<[u8; 8]>::open(dir.path(), config).expect("failed to create var tree"));
let mut handles = Vec::new();
for t in 0..4u64 {
let tree = Arc::clone(&tree);
let handle = thread::spawn(move || {
let start = t * 250;
let end = start + 250;
for i in start..end {
let key = i.to_be_bytes();
let value = format!("val_{}", i).into_bytes();
tree.put(&key, &value).expect("var put failed");
}
});
handles.push(handle);
}
for handle in handles {
handle.join().expect("thread panicked");
}
assert_eq!(tree.len(), 1000);
for i in 0..1000u64 {
let key = i.to_be_bytes();
let expected = format!("val_{}", i).into_bytes();
let val = tree
.get(&key)
.unwrap_or_else(|| panic!("var key {} not found", i));
assert_eq!(
val.as_ref(),
expected.as_slice(),
"var value mismatch for key {}",
i
);
}
}