make database code generic
parent
ecc97542bd
commit
e270ad8f3c
@ -1,291 +1,291 @@
|
|||||||
/*
|
// /*
|
||||||
* Copyright 2022, The Cozo Project Authors. Licensed under MPL-2.0.
|
// * Copyright 2022, The Cozo Project Authors. Licensed under MPL-2.0.
|
||||||
*/
|
// */
|
||||||
|
//
|
||||||
use std::cmp::Ordering;
|
// use std::cmp::Ordering;
|
||||||
use std::collections::btree_map::Range;
|
// use std::collections::btree_map::Range;
|
||||||
use std::collections::BTreeMap;
|
// use std::collections::BTreeMap;
|
||||||
use std::iter::Fuse;
|
// use std::iter::Fuse;
|
||||||
use std::marker::PhantomData;
|
// use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
// use std::thread;
|
||||||
|
//
|
||||||
use miette::{IntoDiagnostic, Result};
|
// use miette::{IntoDiagnostic, Result};
|
||||||
use sled::transaction::{ConflictableTransactionError, TransactionalTree};
|
// use sled::transaction::{ConflictableTransactionError, TransactionalTree};
|
||||||
use sled::{Db, IVec, Iter};
|
// use sled::{Db, IVec, Iter};
|
||||||
|
//
|
||||||
use crate::data::tuple::Tuple;
|
// use crate::data::tuple::Tuple;
|
||||||
use crate::runtime::relation::decode_tuple_from_kv;
|
// use crate::runtime::relation::decode_tuple_from_kv;
|
||||||
use crate::storage::{Storage, StoreTx};
|
// use crate::storage::{Storage, StoreTx};
|
||||||
use crate::utils::swap_option_result;
|
// use crate::utils::swap_option_result;
|
||||||
|
//
|
||||||
#[derive(Clone)]
|
// #[derive(Clone)]
|
||||||
struct SledStorage<'a> {
|
// struct SledStorage {
|
||||||
db: Db,
|
// db: Db,
|
||||||
_phantom: PhantomData<&'a [u8]>,
|
// }
|
||||||
}
|
//
|
||||||
|
// impl Storage for SledStorage {
|
||||||
impl<'a> Storage<'a> for SledStorage<'a> {
|
// type Tx = SledTx;
|
||||||
type Tx = SledTx<'a>;
|
//
|
||||||
|
// fn transact(&self) -> Result<Self::Tx> {
|
||||||
fn transact(&'a self) -> Result<Self::Tx> {
|
// Ok(SledTx {
|
||||||
Ok(SledTx {
|
// db: self.db.clone(),
|
||||||
db: self.db.clone(),
|
// changes: Default::default(),
|
||||||
changes: Default::default(),
|
// })
|
||||||
_phantom: Default::default(),
|
// }
|
||||||
})
|
//
|
||||||
}
|
// fn del_range(&self, lower: &[u8], upper: &[u8]) -> Result<()> {
|
||||||
|
// let db = self.db.clone();
|
||||||
fn del_range(&self, lower: &[u8], upper: &[u8]) -> Result<()> {
|
// let lower_v = lower.to_vec();
|
||||||
let db = self.db.clone();
|
// let upper_v = upper.to_vec();
|
||||||
let lower_v = lower.to_vec();
|
// thread::spawn(move || -> Result<()> {
|
||||||
let upper_v = upper.to_vec();
|
// for k_res in db.range(lower_v..upper_v).keys() {
|
||||||
thread::spawn(move || -> Result<()> {
|
// db.remove(k_res.into_diagnostic()?).into_diagnostic()?;
|
||||||
for k_res in db.range(lower_v..upper_v).keys() {
|
// }
|
||||||
db.remove(k_res.into_diagnostic()?).into_diagnostic()?;
|
// Ok(())
|
||||||
}
|
// });
|
||||||
Ok(())
|
// Ok(())
|
||||||
});
|
// }
|
||||||
Ok(())
|
//
|
||||||
}
|
// fn range_compact(&self, _lower: &[u8], _upper: &[u8]) -> Result<()> {
|
||||||
|
// Ok(())
|
||||||
fn range_compact(&self, _lower: &[u8], _upper: &[u8]) -> Result<()> {
|
// }
|
||||||
Ok(())
|
// }
|
||||||
}
|
//
|
||||||
}
|
// struct SledTx {
|
||||||
|
// db: Db,
|
||||||
struct SledTx<'a> {
|
// changes: Arc<RwLock<BTreeMap<Vec<u8>, Option<Vec<u8>>>>>,
|
||||||
db: Db,
|
// }
|
||||||
changes: BTreeMap<Vec<u8>, Option<Vec<u8>>>,
|
//
|
||||||
_phantom: PhantomData<&'a [u8]>,
|
// impl StoreTx for SledTx {
|
||||||
}
|
// #[inline]
|
||||||
|
// fn get(&self, key: &[u8], _for_update: bool) -> Result<Option<Vec<u8>>> {
|
||||||
impl<'a> StoreTx<'a> for SledTx<'a> {
|
// Ok(match self.changes.read().unwrap().get(key) {
|
||||||
type ReadSlice = IVec;
|
// Some(Some(val)) => Some(val.clone()),
|
||||||
type KVIter = SledIter<'a>;
|
// Some(None) => None,
|
||||||
type KVIterRaw = SledIterRaw<'a>;
|
// None => {
|
||||||
|
// let ret = self.db.get(key).into_diagnostic()?;
|
||||||
#[inline]
|
// ret.map(|v| v.to_vec())
|
||||||
fn get(&self, key: &[u8], _for_update: bool) -> Result<Option<Self::ReadSlice>> {
|
// }
|
||||||
Ok(match self.changes.get(key) {
|
// })
|
||||||
Some(Some(val)) => Some(IVec::from(val as &[u8])),
|
// }
|
||||||
Some(None) => None,
|
//
|
||||||
None => self.db.get(key).into_diagnostic()?,
|
// #[inline]
|
||||||
})
|
// fn put(&mut self, key: &[u8], val: &[u8]) -> Result<()> {
|
||||||
}
|
// self.changes.write().unwrap().insert(key.into(), Some(val.into()));
|
||||||
|
// Ok(())
|
||||||
#[inline]
|
// }
|
||||||
fn put(&mut self, key: &[u8], val: &[u8]) -> Result<()> {
|
//
|
||||||
self.changes.insert(key.into(), Some(val.into()));
|
// #[inline]
|
||||||
Ok(())
|
// fn del(&mut self, key: &[u8]) -> Result<()> {
|
||||||
}
|
// self.changes.write().unwrap().insert(key.into(), None);
|
||||||
|
// Ok(())
|
||||||
#[inline]
|
// }
|
||||||
fn del(&mut self, key: &[u8]) -> Result<()> {
|
//
|
||||||
self.changes.insert(key.into(), None);
|
// #[inline]
|
||||||
Ok(())
|
// fn exists(&self, key: &[u8], _for_update: bool) -> Result<bool> {
|
||||||
}
|
// Ok(match self.changes.read().unwrap().get(key) {
|
||||||
|
// Some(Some(_)) => true,
|
||||||
#[inline]
|
// Some(None) => false,
|
||||||
fn exists(&self, key: &[u8], _for_update: bool) -> Result<bool> {
|
// None => self.db.get(key).into_diagnostic()?.is_some(),
|
||||||
Ok(match self.changes.get(key) {
|
// })
|
||||||
Some(Some(_)) => true,
|
// }
|
||||||
Some(None) => false,
|
//
|
||||||
None => self.db.get(key).into_diagnostic()?.is_some(),
|
// fn commit(&mut self) -> Result<()> {
|
||||||
})
|
// self.db
|
||||||
}
|
// .transaction(
|
||||||
|
// |db: &TransactionalTree| -> Result<(), ConflictableTransactionError> {
|
||||||
fn commit(&mut self) -> Result<()> {
|
// for (k, v) in self.changes.read().unwrap().iter() {
|
||||||
self.db
|
// match v {
|
||||||
.transaction(
|
// None => {
|
||||||
|db: &TransactionalTree| -> Result<(), ConflictableTransactionError> {
|
// db.remove(k as &[u8])?;
|
||||||
for (k, v) in &self.changes {
|
// }
|
||||||
match v {
|
// Some(v) => {
|
||||||
None => {
|
// db.insert(k as &[u8], v as &[u8])?;
|
||||||
db.remove(k as &[u8])?;
|
// }
|
||||||
}
|
// }
|
||||||
Some(v) => {
|
// }
|
||||||
db.insert(k as &[u8], v as &[u8])?;
|
// Ok(())
|
||||||
}
|
// },
|
||||||
}
|
// )
|
||||||
}
|
// .into_diagnostic()?;
|
||||||
Ok(())
|
// Ok(())
|
||||||
},
|
// }
|
||||||
)
|
//
|
||||||
.into_diagnostic()?;
|
// fn range_scan(&self, lower: &[u8], upper: &[u8]) -> Box<dyn Iterator<Item = Result<Tuple>>> {
|
||||||
Ok(())
|
// let change_iter = self.changes.read().unwrap().range(lower.to_vec()..upper.to_vec()).fuse();
|
||||||
}
|
// let db_iter = self.db.range(lower..upper).fuse();
|
||||||
|
// Box::new(SledIter {
|
||||||
fn range_scan(&'a self, lower: &[u8], upper: &[u8]) -> Self::KVIter {
|
// change_iter,
|
||||||
let change_iter = self.changes.range(lower.to_vec()..upper.to_vec()).fuse();
|
// db_iter,
|
||||||
let db_iter = self.db.range(lower..upper).fuse();
|
// change_cache: None,
|
||||||
SledIter {
|
// db_cache: None,
|
||||||
change_iter,
|
// })
|
||||||
db_iter,
|
// }
|
||||||
change_cache: None,
|
//
|
||||||
db_cache: None,
|
// fn range_scan_raw(
|
||||||
}
|
// &self,
|
||||||
}
|
// lower: &[u8],
|
||||||
|
// upper: &[u8],
|
||||||
fn range_scan_raw(&'a self, lower: &[u8], upper: &[u8]) -> Self::KVIterRaw {
|
// ) -> Box<dyn Iterator<Item = Result<(Vec<u8>, Vec<u8>)>>> {
|
||||||
let change_iter = self.changes.range(lower.to_vec()..upper.to_vec()).fuse();
|
// let change_iter = self.changes.read().unwrap().range(lower.to_vec()..upper.to_vec()).fuse();
|
||||||
let db_iter = self.db.range(lower..upper).fuse();
|
// let db_iter = self.db.range(lower..upper).fuse();
|
||||||
SledIterRaw {
|
// Box::new(SledIterRaw {
|
||||||
change_iter,
|
// change_iter,
|
||||||
db_iter,
|
// db_iter,
|
||||||
change_cache: None,
|
// change_cache: None,
|
||||||
db_cache: None,
|
// db_cache: None,
|
||||||
}
|
// })
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
struct SledIter<'a> {
|
// struct SledIter<'a> {
|
||||||
change_iter: Fuse<Range<'a, Vec<u8>, Option<Vec<u8>>>>,
|
// change_iter: Fuse<Range<'a, Vec<u8>, Option<Vec<u8>>>>,
|
||||||
db_iter: Fuse<Iter>,
|
// db_iter: Fuse<Iter>,
|
||||||
change_cache: Option<(Vec<u8>, Option<Vec<u8>>)>,
|
// change_cache: Option<(Vec<u8>, Option<Vec<u8>>)>,
|
||||||
db_cache: Option<(IVec, IVec)>,
|
// db_cache: Option<(IVec, IVec)>,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl<'a> SledIter<'a> {
|
// impl<'a> SledIter<'a> {
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn fill_cache(&mut self) -> Result<()> {
|
// fn fill_cache(&mut self) -> Result<()> {
|
||||||
if self.change_cache.is_none() {
|
// if self.change_cache.is_none() {
|
||||||
if let Some((k, v)) = self.change_iter.next() {
|
// if let Some((k, v)) = self.change_iter.next() {
|
||||||
self.change_cache = Some((k.to_vec(), v.clone()))
|
// self.change_cache = Some((k.to_vec(), v.clone()))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if self.db_cache.is_none() {
|
// if self.db_cache.is_none() {
|
||||||
if let Some(res) = self.db_iter.next() {
|
// if let Some(res) = self.db_iter.next() {
|
||||||
self.db_cache = Some(res.into_diagnostic()?);
|
// self.db_cache = Some(res.into_diagnostic()?);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn next_inner(&mut self) -> Result<Option<Tuple>> {
|
// fn next_inner(&mut self) -> Result<Option<Tuple>> {
|
||||||
loop {
|
// loop {
|
||||||
self.fill_cache()?;
|
// self.fill_cache()?;
|
||||||
match (&self.change_cache, &self.db_cache) {
|
// match (&self.change_cache, &self.db_cache) {
|
||||||
(None, None) => return Ok(None),
|
// (None, None) => return Ok(None),
|
||||||
(Some((_, None)), None) => {
|
// (Some((_, None)), None) => {
|
||||||
self.change_cache.take();
|
// self.change_cache.take();
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
(Some((_, Some(_))), None) => {
|
// (Some((_, Some(_))), None) => {
|
||||||
let (k, sv) = self.change_cache.take().unwrap();
|
// let (k, sv) = self.change_cache.take().unwrap();
|
||||||
let v = sv.unwrap();
|
// let v = sv.unwrap();
|
||||||
return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
// return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
||||||
}
|
// }
|
||||||
(None, Some(_)) => {
|
// (None, Some(_)) => {
|
||||||
let (k, v) = self.db_cache.take().unwrap();
|
// let (k, v) = self.db_cache.take().unwrap();
|
||||||
return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
// return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
||||||
}
|
// }
|
||||||
(Some((ck, _)), Some((dk, _))) => match ck.as_slice().cmp(dk) {
|
// (Some((ck, _)), Some((dk, _))) => match ck.as_slice().cmp(dk) {
|
||||||
Ordering::Less => {
|
// Ordering::Less => {
|
||||||
let (k, sv) = self.change_cache.take().unwrap();
|
// let (k, sv) = self.change_cache.take().unwrap();
|
||||||
match sv {
|
// match sv {
|
||||||
None => continue,
|
// None => continue,
|
||||||
Some(v) => {
|
// Some(v) => {
|
||||||
return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
// return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Ordering::Greater => {
|
// Ordering::Greater => {
|
||||||
let (k, v) = self.db_cache.take().unwrap();
|
// let (k, v) = self.db_cache.take().unwrap();
|
||||||
return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
// return Ok(Some(decode_tuple_from_kv(&k, &v)));
|
||||||
}
|
// }
|
||||||
Ordering::Equal => {
|
// Ordering::Equal => {
|
||||||
self.db_cache.take();
|
// self.db_cache.take();
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl<'a> Iterator for SledIter<'a> {
|
// impl<'a> Iterator for SledIter<'a> {
|
||||||
type Item = Result<Tuple>;
|
// type Item = Result<Tuple>;
|
||||||
|
//
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
// fn next(&mut self) -> Option<Self::Item> {
|
||||||
swap_option_result(self.next_inner())
|
// swap_option_result(self.next_inner())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
struct SledIterRaw<'a> {
|
// struct SledIterRaw<'a> {
|
||||||
change_iter: Fuse<Range<'a, Vec<u8>, Option<Vec<u8>>>>,
|
// change_iter: Fuse<Range<'a, Vec<u8>, Option<Vec<u8>>>>,
|
||||||
db_iter: Fuse<Iter>,
|
// db_iter: Fuse<Iter>,
|
||||||
change_cache: Option<(Vec<u8>, Option<Vec<u8>>)>,
|
// change_cache: Option<(Vec<u8>, Option<Vec<u8>>)>,
|
||||||
db_cache: Option<(IVec, IVec)>,
|
// db_cache: Option<(IVec, IVec)>,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl<'a> SledIterRaw<'a> {
|
// impl<'a> SledIterRaw<'a> {
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn fill_cache(&mut self) -> Result<()> {
|
// fn fill_cache(&mut self) -> Result<()> {
|
||||||
if self.change_cache.is_none() {
|
// if self.change_cache.is_none() {
|
||||||
if let Some((k, v)) = self.change_iter.next() {
|
// if let Some((k, v)) = self.change_iter.next() {
|
||||||
self.change_cache = Some((k.to_vec(), v.clone()))
|
// self.change_cache = Some((k.to_vec(), v.clone()))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if self.db_cache.is_none() {
|
// if self.db_cache.is_none() {
|
||||||
if let Some(res) = self.db_iter.next() {
|
// if let Some(res) = self.db_iter.next() {
|
||||||
self.db_cache = Some(res.into_diagnostic()?);
|
// self.db_cache = Some(res.into_diagnostic()?);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn next_inner(&mut self) -> Result<Option<(Vec<u8>, Vec<u8>)>> {
|
// fn next_inner(&mut self) -> Result<Option<(Vec<u8>, Vec<u8>)>> {
|
||||||
loop {
|
// loop {
|
||||||
self.fill_cache()?;
|
// self.fill_cache()?;
|
||||||
match (&self.change_cache, &self.db_cache) {
|
// match (&self.change_cache, &self.db_cache) {
|
||||||
(None, None) => return Ok(None),
|
// (None, None) => return Ok(None),
|
||||||
(Some((_, None)), None) => {
|
// (Some((_, None)), None) => {
|
||||||
self.change_cache.take();
|
// self.change_cache.take();
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
(Some((_, Some(_))), None) => {
|
// (Some((_, Some(_))), None) => {
|
||||||
let (k, sv) = self.change_cache.take().unwrap();
|
// let (k, sv) = self.change_cache.take().unwrap();
|
||||||
let v = sv.unwrap();
|
// let v = sv.unwrap();
|
||||||
return Ok(Some((k, v)));
|
// return Ok(Some((k, v)));
|
||||||
}
|
// }
|
||||||
(None, Some(_)) => {
|
// (None, Some(_)) => {
|
||||||
let (k, v) = self.db_cache.take().unwrap();
|
// let (k, v) = self.db_cache.take().unwrap();
|
||||||
return Ok(Some((k.to_vec(), v.to_vec())));
|
// return Ok(Some((k.to_vec(), v.to_vec())));
|
||||||
}
|
// }
|
||||||
(Some((ck, _)), Some((dk, _))) => match ck.as_slice().cmp(dk) {
|
// (Some((ck, _)), Some((dk, _))) => match ck.as_slice().cmp(dk) {
|
||||||
Ordering::Less => {
|
// Ordering::Less => {
|
||||||
let (k, sv) = self.change_cache.take().unwrap();
|
// let (k, sv) = self.change_cache.take().unwrap();
|
||||||
match sv {
|
// match sv {
|
||||||
None => continue,
|
// None => continue,
|
||||||
Some(v) => return Ok(Some((k, v))),
|
// Some(v) => return Ok(Some((k, v))),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Ordering::Greater => {
|
// Ordering::Greater => {
|
||||||
let (k, v) = self.db_cache.take().unwrap();
|
// let (k, v) = self.db_cache.take().unwrap();
|
||||||
return Ok(Some((k.to_vec(), v.to_vec())));
|
// return Ok(Some((k.to_vec(), v.to_vec())));
|
||||||
}
|
// }
|
||||||
Ordering::Equal => {
|
// Ordering::Equal => {
|
||||||
self.db_cache.take();
|
// self.db_cache.take();
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl<'a> Iterator for SledIterRaw<'a> {
|
// impl<'a> Iterator for SledIterRaw<'a> {
|
||||||
type Item = Result<(Vec<u8>, Vec<u8>)>;
|
// type Item = Result<(Vec<u8>, Vec<u8>)>;
|
||||||
|
//
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
// fn next(&mut self) -> Option<Self::Item> {
|
||||||
swap_option_result(self.next_inner())
|
// swap_option_result(self.next_inner())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
Loading…
Reference in New Issue