Files
continuwuity/src/service/rooms/state_compressor/data.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

85 lines
2.1 KiB
Rust
Raw Normal View History

2024-05-26 21:29:19 +00:00
use std::{collections::HashSet, mem::size_of, sync::Arc};
2022-10-05 12:45:54 +02:00
2024-08-08 17:18:30 +00:00
use conduit::{err, expected, utils, Result};
2024-06-28 22:51:39 +00:00
use database::{Database, Map};
2024-05-27 03:17:20 +00:00
2022-09-07 13:25:51 +02:00
use super::CompressedStateEvent;
2022-09-06 23:15:09 +02:00
2024-05-27 03:17:20 +00:00
pub(super) struct StateDiff {
pub(super) parent: Option<u64>,
pub(super) added: Arc<HashSet<CompressedStateEvent>>,
pub(super) removed: Arc<HashSet<CompressedStateEvent>>,
}
2024-06-28 22:51:39 +00:00
pub(super) struct Data {
shortstatehash_statediff: Arc<Map>,
}
2024-05-26 21:29:19 +00:00
2024-05-27 03:17:20 +00:00
impl Data {
2024-06-28 22:51:39 +00:00
pub(super) fn new(db: &Arc<Database>) -> Self {
2024-05-27 03:17:20 +00:00
Self {
2024-06-28 22:51:39 +00:00
shortstatehash_statediff: db["shortstatehash_statediff"].clone(),
2024-05-27 03:17:20 +00:00
}
}
2024-08-08 17:18:30 +00:00
pub(super) async fn get_statediff(&self, shortstatehash: u64) -> Result<StateDiff> {
const BUFSIZE: usize = size_of::<u64>();
2024-05-26 21:29:19 +00:00
let value = self
.shortstatehash_statediff
.aqry::<BUFSIZE, _>(&shortstatehash)
2024-08-08 17:18:30 +00:00
.await
.map_err(|e| err!(Database("Failed to find StateDiff from short {shortstatehash:?}: {e}")))?;
2024-05-26 21:29:19 +00:00
let parent = utils::u64_from_bytes(&value[0..size_of::<u64>()]).expect("bytes have right length");
let parent = if parent != 0 {
Some(parent)
} else {
None
};
let mut add_mode = true;
let mut added = HashSet::new();
let mut removed = HashSet::new();
2024-07-07 04:46:16 +00:00
let stride = size_of::<u64>();
let mut i = stride;
2024-08-08 17:18:30 +00:00
while let Some(v) = value.get(i..expected!(i + 2 * stride)) {
2024-05-26 21:29:19 +00:00
if add_mode && v.starts_with(&0_u64.to_be_bytes()) {
add_mode = false;
2024-08-08 17:18:30 +00:00
i = expected!(i + stride);
2024-05-26 21:29:19 +00:00
continue;
}
if add_mode {
added.insert(v.try_into().expect("we checked the size above"));
} else {
removed.insert(v.try_into().expect("we checked the size above"));
}
2024-08-08 17:18:30 +00:00
i = expected!(i + 2 * stride);
2024-05-26 21:29:19 +00:00
}
Ok(StateDiff {
parent,
added: Arc::new(added),
removed: Arc::new(removed),
})
}
2024-08-08 17:18:30 +00:00
pub(super) fn save_statediff(&self, shortstatehash: u64, diff: &StateDiff) {
2024-05-26 21:29:19 +00:00
let mut value = diff.parent.unwrap_or(0).to_be_bytes().to_vec();
for new in diff.added.iter() {
value.extend_from_slice(&new[..]);
}
if !diff.removed.is_empty() {
value.extend_from_slice(&0_u64.to_be_bytes());
for removed in diff.removed.iter() {
value.extend_from_slice(&removed[..]);
}
}
self.shortstatehash_statediff
2024-08-08 17:18:30 +00:00
.insert(&shortstatehash.to_be_bytes(), &value);
2024-05-26 21:29:19 +00:00
}
}