#[cfg(feature = "serde")]
use serde::{
de::{Deserialize, Deserializer},
ser::{Serialize, SerializeMap, Serializer},
};
#[cfg(feature = "serde")]
use crate::utils::MapCollector;
use crate::internals::lincowcell_async::{LinCowCell, LinCowCellReadTxn, LinCowCellWriteTxn};
include!("impl.rs");
impl<K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
BptreeMap<K, V>
{
pub fn read<'x>(&'x self) -> BptreeMapReadTxn<'x, K, V> {
let inner = self.inner.read();
BptreeMapReadTxn { inner }
}
pub async fn write<'x>(&'x self) -> BptreeMapWriteTxn<'x, K, V> {
let inner = self.inner.write().await;
BptreeMapWriteTxn { inner }
}
}
impl<K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
BptreeMapWriteTxn<'_, K, V>
{
pub fn commit(self) {
self.inner.commit();
}
}
#[cfg(feature = "serde")]
impl<K, V> Serialize for BptreeMapReadTxn<'_, K, V>
where
K: Serialize + Clone + Ord + Debug + Sync + Send + 'static,
V: Serialize + Clone + Sync + Send + 'static,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_map(Some(self.len()))?;
for (key, val) in self.iter() {
state.serialize_entry(key, val)?;
}
state.end()
}
}
#[cfg(feature = "serde")]
impl<K, V> Serialize for BptreeMap<K, V>
where
K: Serialize + Clone + Ord + Debug + Sync + Send + 'static,
V: Serialize + Clone + Sync + Send + 'static,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.read().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, K, V> Deserialize<'de> for BptreeMap<K, V>
where
K: Deserialize<'de> + Clone + Ord + Debug + Sync + Send + 'static,
V: Deserialize<'de> + Clone + Sync + Send + 'static,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(MapCollector::new())
}
}
#[cfg(test)]
mod tests {
use super::BptreeMap;
use crate::internals::bptree::node::{assert_released, L_CAPACITY};
use rand::seq::SliceRandom;
#[tokio::test]
async fn test_bptree2_map_basic_write() {
let bptree: BptreeMap<usize, usize> = BptreeMap::new();
{
let mut bpwrite = bptree.write().await;
bpwrite.insert(0, 0);
bpwrite.insert(1, 1);
assert!(bpwrite.get(&0) == Some(&0));
assert!(bpwrite.get(&1) == Some(&1));
bpwrite.insert(2, 2);
bpwrite.commit();
}
{
let mut bpwrite = bptree.write().await;
bpwrite.clear();
}
{
let bpwrite = bptree.write().await;
assert!(bpwrite.get(&0) == Some(&0));
assert!(bpwrite.get(&1) == Some(&1));
}
std::mem::drop(bptree);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_cursed_get_mut() {
let bptree: BptreeMap<usize, usize> = BptreeMap::new();
{
let mut w = bptree.write().await;
w.insert(0, 0);
w.commit();
}
let r1 = bptree.read();
{
let mut w = bptree.write().await;
let cursed_zone = w.get_mut(&0).unwrap();
*cursed_zone = 1;
w.commit();
}
let r2 = bptree.read();
assert!(r1.get(&0) == Some(&0));
assert!(r2.get(&0) == Some(&1));
std::mem::drop(r1);
std::mem::drop(r2);
std::mem::drop(bptree);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_from_iter_1() {
let ins: Vec<usize> = (0..(L_CAPACITY << 4)).collect();
let map = BptreeMap::from_iter(ins.into_iter().map(|v| (v, v)));
{
let w = map.write().await;
assert!(w.verify());
println!("{:?}", w.tree_density());
}
std::mem::drop(map);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_from_iter_2() {
let mut rng = rand::rng();
let mut ins: Vec<usize> = (0..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let map = BptreeMap::from_iter(ins.into_iter().map(|v| (v, v)));
{
let w = map.write().await;
assert!(w.verify());
assert!(w.verify());
}
std::mem::drop(map);
assert_released();
}
async fn bptree_map_basic_concurrency(lower: usize, upper: usize) {
let map = BptreeMap::new();
{
let mut w = map.write().await;
w.extend((0..lower).map(|v| (v, v)));
w.commit();
}
let r = map.read();
assert!(r.len() == lower);
for i in 0..lower {
assert!(r.contains_key(&i))
}
{
let mut w = map.write().await;
w.extend((lower..upper).map(|v| (v, v)));
w.commit();
}
assert!(r.len() == lower);
let r2 = map.read();
assert!(r2.len() == upper);
for i in 0..upper {
assert!(r2.contains_key(&i))
}
{
let mut w = map.write().await;
for i in 0..upper {
assert!(w.remove(&i).is_some())
}
w.commit();
}
assert!(r.len() == lower);
assert!(r2.len() == upper);
for i in 0..upper {
assert!(r2.contains_key(&i))
}
let r3 = map.read();
assert!(r3.is_empty());
std::mem::drop(r);
std::mem::drop(r2);
std::mem::drop(r3);
std::mem::drop(map);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_acb_order() {
let map = BptreeMap::new();
{
let mut w = map.write().await;
w.extend((0..(L_CAPACITY * 2)).map(|v| (v * 2, v * 2)));
w.commit();
}
let ro_txn_a = map.read();
{
let mut w = map.write().await;
w.insert(1, 1);
w.commit();
}
let ro_txn_b = map.read();
{
let mut w = map.write().await;
w.insert(1, 10001);
w.commit();
}
let ro_txn_c = map.read();
assert!(ro_txn_b.verify());
std::mem::drop(ro_txn_b);
assert!(ro_txn_a.verify());
assert!(ro_txn_c.verify());
std::mem::drop(ro_txn_a);
std::mem::drop(ro_txn_c);
std::mem::drop(map);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_weird_txn_behaviour() {
let map: BptreeMap<usize, usize> = BptreeMap::new();
let mut wr = map.write().await;
let rd = map.read();
wr.insert(1, 1);
assert!(rd.get(&1).is_none());
wr.commit();
assert!(rd.get(&1).is_none());
}
#[tokio::test]
#[cfg_attr(miri, ignore)]
async fn test_bptree2_map_basic_concurrency_small() {
bptree_map_basic_concurrency(100, 200).await
}
#[tokio::test]
#[cfg_attr(miri, ignore)]
async fn test_bptree2_map_basic_concurrency_large() {
bptree_map_basic_concurrency(10_000, 20_000).await
}
#[cfg(feature = "serde")]
#[tokio::test]
async fn test_bptree2_serialize_deserialize() {
let map: BptreeMap<usize, usize> = vec![(10, 11), (15, 16), (20, 21)].into_iter().collect();
let value = serde_json::to_value(&map).unwrap();
assert_eq!(value, serde_json::json!({ "10": 11, "15": 16, "20": 21 }));
let map: BptreeMap<usize, usize> = serde_json::from_value(value).unwrap();
let mut vec: Vec<(usize, usize)> = map.read().iter().map(|(k, v)| (*k, *v)).collect();
vec.sort_unstable();
assert_eq!(vec, [(10, 11), (15, 16), (20, 21)]);
}
}