2019-10-03 22:39:30 +08:00
|
|
|
use std::convert::TryInto;
|
|
|
|
use rkv::Value;
|
2019-10-03 23:33:15 +08:00
|
|
|
use crate::{update::Update, MResult};
|
2019-10-03 21:04:11 +08:00
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct Updates {
|
|
|
|
pub(crate) updates: rkv::SingleStore,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Updates {
|
2019-10-03 22:39:30 +08:00
|
|
|
// TODO we should use the MDB_LAST op but
|
|
|
|
// it is not exposed by the rkv library
|
2019-10-04 16:21:09 +08:00
|
|
|
fn last_update_id<'a>(
|
2019-10-03 22:39:30 +08:00
|
|
|
&self,
|
2019-10-04 16:21:09 +08:00
|
|
|
reader: &'a impl rkv::Readable,
|
2019-10-03 22:39:30 +08:00
|
|
|
) -> Result<Option<(u64, Option<Value<'a>>)>, rkv::StoreError>
|
|
|
|
{
|
|
|
|
let mut last = None;
|
|
|
|
let iter = self.updates.iter_start(reader)?;
|
|
|
|
for result in iter {
|
|
|
|
let (key, data) = result?;
|
|
|
|
last = Some((key, data));
|
|
|
|
}
|
|
|
|
|
|
|
|
let (last_key, last_data) = match last {
|
|
|
|
Some(entry) => entry,
|
|
|
|
None => return Ok(None),
|
|
|
|
};
|
|
|
|
|
|
|
|
let array = last_key.try_into().unwrap();
|
|
|
|
let number = u64::from_be_bytes(array);
|
|
|
|
|
|
|
|
Ok(Some((number, last_data)))
|
|
|
|
}
|
|
|
|
|
2019-10-04 16:21:09 +08:00
|
|
|
pub fn contains(
|
2019-10-03 22:54:37 +08:00
|
|
|
&self,
|
2019-10-04 16:21:09 +08:00
|
|
|
reader: &impl rkv::Readable,
|
2019-10-03 22:54:37 +08:00
|
|
|
update_id: u64,
|
|
|
|
) -> Result<bool, rkv::StoreError>
|
|
|
|
{
|
|
|
|
let update_id_bytes = update_id.to_be_bytes();
|
|
|
|
self.updates.get(reader, update_id_bytes).map(|v| v.is_some())
|
|
|
|
}
|
|
|
|
|
2019-10-03 21:04:11 +08:00
|
|
|
pub fn push_back(
|
|
|
|
&self,
|
|
|
|
writer: &mut rkv::Writer,
|
|
|
|
update: &Update,
|
2019-10-03 23:33:15 +08:00
|
|
|
) -> MResult<u64>
|
2019-10-03 21:04:11 +08:00
|
|
|
{
|
2019-10-03 22:39:30 +08:00
|
|
|
let last_update_id = self.last_update_id(writer)?;
|
|
|
|
let last_update_id = last_update_id.map_or(0, |(n, _)| n + 1);
|
|
|
|
let last_update_id_bytes = last_update_id.to_be_bytes();
|
2019-10-03 22:13:09 +08:00
|
|
|
|
2019-10-03 23:33:15 +08:00
|
|
|
let update = rmp_serde::to_vec_named(&update)?;
|
2019-10-03 22:39:30 +08:00
|
|
|
let blob = Value::Blob(&update);
|
|
|
|
self.updates.put(writer, last_update_id_bytes, &blob)?;
|
2019-10-03 22:13:09 +08:00
|
|
|
|
2019-10-03 22:39:30 +08:00
|
|
|
Ok(last_update_id)
|
2019-10-03 21:04:11 +08:00
|
|
|
}
|
|
|
|
|
2019-10-03 22:13:09 +08:00
|
|
|
pub fn pop_back(
|
2019-10-03 21:04:11 +08:00
|
|
|
&self,
|
2019-10-03 22:13:09 +08:00
|
|
|
writer: &mut rkv::Writer,
|
2019-10-03 23:33:15 +08:00
|
|
|
) -> MResult<Option<(u64, Update)>>
|
2019-10-03 21:04:11 +08:00
|
|
|
{
|
2019-10-03 22:39:30 +08:00
|
|
|
let (last_id, last_data) = match self.last_update_id(writer)? {
|
|
|
|
Some(entry) => entry,
|
|
|
|
None => return Ok(None),
|
|
|
|
};
|
|
|
|
|
|
|
|
match last_data {
|
|
|
|
Some(Value::Blob(bytes)) => {
|
2019-10-03 23:33:15 +08:00
|
|
|
let update = rmp_serde::from_read_ref(&bytes)?;
|
2019-10-03 22:39:30 +08:00
|
|
|
Ok(Some((last_id, update)))
|
|
|
|
},
|
|
|
|
Some(value) => panic!("invalid type {:?}", value),
|
|
|
|
None => Ok(None),
|
|
|
|
}
|
2019-10-03 21:04:11 +08:00
|
|
|
}
|
|
|
|
}
|