make database code generic

main
Ziyang Hu 2 years ago
parent ecc97542bd
commit e270ad8f3c

@ -16,6 +16,9 @@ exclude = [
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
storage-rocksdb = []
storage-sled = []
storage-tikv = []
jemalloc = ["tikv-jemallocator-global", "cozorocks/jemalloc"] jemalloc = ["tikv-jemallocator-global", "cozorocks/jemalloc"]
io-uring = ["cozorocks/io-uring"] io-uring = ["cozorocks/io-uring"]

@ -27,12 +27,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct BetweennessCentrality; pub(crate) struct BetweennessCentrality;
impl AlgoImpl for BetweennessCentrality { impl AlgoImpl for BetweennessCentrality {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;
@ -97,12 +97,12 @@ impl AlgoImpl for BetweennessCentrality {
pub(crate) struct ClosenessCentrality; pub(crate) struct ClosenessCentrality;
impl AlgoImpl for ClosenessCentrality { impl AlgoImpl for ClosenessCentrality {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -24,12 +24,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct ShortestPathAStar; pub(crate) struct ShortestPathAStar;
impl AlgoImpl for ShortestPathAStar { impl AlgoImpl for ShortestPathAStar {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation_with_min_len(0, 3, tx, stores)?; let edges = algo.relation_with_min_len(0, 3, tx, stores)?;
@ -81,14 +81,14 @@ impl AlgoImpl for ShortestPathAStar {
} }
} }
fn astar( fn astar<'a>(
starting: &Tuple, starting: &Tuple,
goal: &Tuple, goal: &Tuple,
edges: &MagicAlgoRuleArg, edges: &'a MagicAlgoRuleArg,
nodes: &MagicAlgoRuleArg, nodes: &'a MagicAlgoRuleArg,
heuristic: &Expr, heuristic: &Expr,
tx: &SessionTx, tx: &'a SessionTx,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
poison: Poison, poison: Poison,
) -> Result<(f64, Vec<DataValue>)> { ) -> Result<(f64, Vec<DataValue>)> {
let start_node = &starting.0[0]; let start_node = &starting.0[0];

@ -21,12 +21,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct Bfs; pub(crate) struct Bfs;
impl AlgoImpl for Bfs { impl AlgoImpl for Bfs {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation_with_min_len(0, 2, tx, stores)?; let edges = algo.relation_with_min_len(0, 2, tx, stores)?;

@ -21,12 +21,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct DegreeCentrality; pub(crate) struct DegreeCentrality;
impl AlgoImpl for DegreeCentrality { impl AlgoImpl for DegreeCentrality {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let it = algo let it = algo

@ -21,12 +21,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct Dfs; pub(crate) struct Dfs;
impl AlgoImpl for Dfs { impl AlgoImpl for Dfs {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation_with_min_len(0, 2, tx, stores)?; let edges = algo.relation_with_min_len(0, 2, tx, stores)?;

@ -25,12 +25,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct MinimumSpanningForestKruskal; pub(crate) struct MinimumSpanningForestKruskal;
impl AlgoImpl for MinimumSpanningForestKruskal { impl AlgoImpl for MinimumSpanningForestKruskal {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -23,12 +23,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct LabelPropagation; pub(crate) struct LabelPropagation;
impl AlgoImpl for LabelPropagation { impl AlgoImpl for LabelPropagation {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -23,12 +23,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct CommunityDetectionLouvain; pub(crate) struct CommunityDetectionLouvain;
impl AlgoImpl for CommunityDetectionLouvain { impl AlgoImpl for CommunityDetectionLouvain {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -60,12 +60,12 @@ pub(crate) mod triangles;
pub(crate) mod yen; pub(crate) mod yen;
pub(crate) trait AlgoImpl { pub(crate) trait AlgoImpl {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()>; ) -> Result<()>;
fn arity( fn arity(
@ -191,12 +191,12 @@ pub(crate) struct BadExprValueError(
pub(crate) struct AlgoNotFoundError(pub(crate) String, #[label] pub(crate) SourceSpan); pub(crate) struct AlgoNotFoundError(pub(crate) String, #[label] pub(crate) SourceSpan);
impl MagicAlgoRuleArg { impl MagicAlgoRuleArg {
pub(crate) fn convert_edge_to_weighted_graph( pub(crate) fn convert_edge_to_weighted_graph<'a>(
&self, &'a self,
undirected: bool, undirected: bool,
allow_negative_edges: bool, allow_negative_edges: bool,
tx: &SessionTx, tx: &'a SessionTx,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
) -> Result<( ) -> Result<(
Vec<Vec<(usize, f64)>>, Vec<Vec<(usize, f64)>>,
Vec<DataValue>, Vec<DataValue>,
@ -276,11 +276,11 @@ impl MagicAlgoRuleArg {
} }
Ok((graph, indices, inv_indices, has_neg_edge)) Ok((graph, indices, inv_indices, has_neg_edge))
} }
pub(crate) fn convert_edge_to_graph( pub(crate) fn convert_edge_to_graph<'a>(
&self, &'a self,
undirected: bool, undirected: bool,
tx: &SessionTx, tx: &'a SessionTx,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
) -> Result<(Vec<Vec<usize>>, Vec<DataValue>, BTreeMap<DataValue, usize>)> { ) -> Result<(Vec<Vec<usize>>, Vec<DataValue>, BTreeMap<DataValue, usize>)> {
let mut graph: Vec<Vec<usize>> = vec![]; let mut graph: Vec<Vec<usize>> = vec![];
let mut indices: Vec<DataValue> = vec![]; let mut indices: Vec<DataValue> = vec![];

@ -24,12 +24,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct PageRank; pub(crate) struct PageRank;
impl AlgoImpl for PageRank { impl AlgoImpl for PageRank {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -26,12 +26,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct MinimumSpanningTreePrim; pub(crate) struct MinimumSpanningTreePrim;
impl AlgoImpl for MinimumSpanningTreePrim { impl AlgoImpl for MinimumSpanningTreePrim {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -24,12 +24,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct RandomWalk; pub(crate) struct RandomWalk;
impl AlgoImpl for RandomWalk { impl AlgoImpl for RandomWalk {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation_with_min_len(0, 2, tx, stores)?; let edges = algo.relation_with_min_len(0, 2, tx, stores)?;

@ -23,12 +23,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct ReorderSort; pub(crate) struct ReorderSort;
impl AlgoImpl for ReorderSort { impl AlgoImpl for ReorderSort {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let in_rel = algo.relation(0)?; let in_rel = algo.relation(0)?;

@ -28,12 +28,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct ShortestPathDijkstra; pub(crate) struct ShortestPathDijkstra;
impl AlgoImpl for ShortestPathDijkstra { impl AlgoImpl for ShortestPathDijkstra {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -31,12 +31,12 @@ impl StronglyConnectedComponent {
} }
impl AlgoImpl for StronglyConnectedComponent { impl AlgoImpl for StronglyConnectedComponent {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -21,12 +21,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct TopSort; pub(crate) struct TopSort;
impl AlgoImpl for TopSort { impl AlgoImpl for TopSort {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -22,12 +22,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct ClusteringCoefficients; pub(crate) struct ClusteringCoefficients;
impl AlgoImpl for ClusteringCoefficients { impl AlgoImpl for ClusteringCoefficients {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -24,12 +24,12 @@ use crate::runtime::transact::SessionTx;
pub(crate) struct KShortestPathYen; pub(crate) struct KShortestPathYen;
impl AlgoImpl for KShortestPathYen { impl AlgoImpl for KShortestPathYen {
fn run( fn run<'a>(
&mut self, &mut self,
tx: &SessionTx, tx: &'a SessionTx,
algo: &MagicAlgoApply, algo: &'a MagicAlgoApply,
stores: &BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
out: &InMemRelation, out: &'a InMemRelation,
poison: Poison, poison: Poison,
) -> Result<()> { ) -> Result<()> {
let edges = algo.relation(0)?; let edges = algo.relation(0)?;

@ -14,7 +14,7 @@ use log::{error, info};
use rand::Rng; use rand::Rng;
use rouille::{router, try_or_400, Request, Response}; use rouille::{router, try_or_400, Request, Response};
use cozo::Db; use cozo::new_cozo_rocksdb;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[clap(version, about, long_about = None)] #[clap(version, about, long_about = None)]
@ -39,7 +39,7 @@ fn main() {
eprintln!("{}", SECURITY_WARNING); eprintln!("{}", SECURITY_WARNING);
} }
let db = Db::new(args.path.as_str()).unwrap(); let db = new_cozo_rocksdb(args.path.as_str()).unwrap();
let mut path_buf = PathBuf::from(&args.path); let mut path_buf = PathBuf::from(&args.path);
path_buf.push("auth.txt"); path_buf.push("auth.txt");

@ -13,7 +13,7 @@ use crate::runtime::relation::RelationId;
pub(crate) const KEY_PREFIX_LEN: usize = 9; pub(crate) const KEY_PREFIX_LEN: usize = 9;
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Default)] #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Default)]
pub(crate) struct Tuple(pub(crate) Vec<DataValue>); pub struct Tuple(pub(crate) Vec<DataValue>);
impl Debug for Tuple { impl Debug for Tuple {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {

@ -19,6 +19,8 @@
pub use miette::Error; pub use miette::Error;
pub use runtime::db::Db; pub use runtime::db::Db;
pub use runtime::db::new_cozo_rocksdb;
pub use storage::rocks::RocksDbStorage;
pub(crate) mod algo; pub(crate) mod algo;
pub(crate) mod data; pub(crate) mod data;

@ -20,8 +20,8 @@ use crate::data::value::DataValue;
use crate::parse::parse_script; use crate::parse::parse_script;
use crate::runtime::relation::{AccessLevel, InputRelationHandle, InsufficientAccessLevel}; use crate::runtime::relation::{AccessLevel, InputRelationHandle, InsufficientAccessLevel};
use crate::runtime::transact::SessionTx; use crate::runtime::transact::SessionTx;
use crate::storage::Storage;
use crate::Db; use crate::Db;
use crate::storage::StoreTx;
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("attempting to write into relation {0} of arity {1} with data of arity {2}")] #[error("attempting to write into relation {0} of arity {1} with data of arity {2}")]
@ -29,14 +29,17 @@ use crate::storage::StoreTx;
struct RelationArityMismatch(String, usize, usize); struct RelationArityMismatch(String, usize, usize);
impl SessionTx { impl SessionTx {
pub(crate) fn execute_relation<'a>( pub(crate) fn execute_relation<S: Storage>(
&'a mut self, &mut self,
db: &Db, db: &Db<S>,
res_iter: impl Iterator<Item = Result<Tuple>> + 'a, res_iter: impl Iterator<Item = Result<Tuple>>,
op: RelationOp, op: RelationOp,
meta: &InputRelationHandle, meta: &InputRelationHandle,
headers: &[Symbol], headers: &[Symbol],
) -> Result<Vec<(Vec<u8>, Vec<u8>)>> { ) -> Result<Vec<(Vec<u8>, Vec<u8>)>>
where
<S as Storage>::Tx: 'static,
{
let mut to_clear = vec![]; let mut to_clear = vec![];
let mut replaced_old_triggers = None; let mut replaced_old_triggers = None;
if op == RelationOp::Replace { if op == RelationOp::Replace {

@ -67,14 +67,17 @@ const CURRENT_STORAGE_VERSION: u64 = 1;
/// The database object of Cozo. /// The database object of Cozo.
#[derive(Clone)] #[derive(Clone)]
pub struct Db { pub struct Db<S> {
db: RocksDbStorage, db: S,
relation_store_id: Arc<AtomicU64>, relation_store_id: Arc<AtomicU64>,
queries_count: Arc<AtomicU64>, queries_count: Arc<AtomicU64>,
running_queries: Arc<Mutex<BTreeMap<u64, RunningQueryHandle>>>, running_queries: Arc<Mutex<BTreeMap<u64, RunningQueryHandle>>>,
} }
impl Debug for Db { impl<S> Debug for Db<S>
where
S: Storage,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Db") write!(f, "Db")
} }
@ -91,64 +94,73 @@ lazy_static! {
static ref JSON_ERR_HANDLER: JSONReportHandler = miette::JSONReportHandler::new(); static ref JSON_ERR_HANDLER: JSONReportHandler = miette::JSONReportHandler::new();
} }
impl Db { /// Creates a database object.
/// Creates a database object. pub fn new_cozo_rocksdb(path: impl AsRef<str>) -> Result<Db<RocksDbStorage>> {
pub fn new(path: impl AsRef<str>) -> Result<Self> { let builder = DbBuilder::default().path(path.as_ref());
let builder = DbBuilder::default().path(path.as_ref()); let path = builder.opts.db_path;
let path = builder.opts.db_path; fs::create_dir_all(path)
fs::create_dir_all(path) .map_err(|err| BadDbInit(format!("cannot create directory {}: {}", path, err)))?;
.map_err(|err| BadDbInit(format!("cannot create directory {}: {}", path, err)))?; let path_buf = PathBuf::from(path);
let path_buf = PathBuf::from(path);
let is_new = {
let is_new = { let mut manifest_path = path_buf.clone();
let mut manifest_path = path_buf.clone(); manifest_path.push("manifest");
manifest_path.push("manifest");
if manifest_path.exists() {
if manifest_path.exists() { let existing: DbManifest = rmp_serde::from_slice(
let existing: DbManifest = rmp_serde::from_slice( &fs::read(manifest_path)
&fs::read(manifest_path)
.into_diagnostic()
.wrap_err_with(|| "when reading manifest")?,
)
.into_diagnostic()
.wrap_err_with(|| "when reading manifest")?;
assert_eq!(
existing.storage_version, CURRENT_STORAGE_VERSION,
"Unknown storage version {}",
existing.storage_version
);
false
} else {
fs::write(
manifest_path,
rmp_serde::to_vec_named(&DbManifest {
storage_version: CURRENT_STORAGE_VERSION,
})
.into_diagnostic() .into_diagnostic()
.wrap_err_with(|| "when serializing manifest")?, .wrap_err_with(|| "when reading manifest")?,
) )
.into_diagnostic() .into_diagnostic()
.wrap_err_with(|| "when serializing manifest")?; .wrap_err_with(|| "when reading manifest")?;
true assert_eq!(
} existing.storage_version, CURRENT_STORAGE_VERSION,
}; "Unknown storage version {}",
existing.storage_version
let mut store_path = path_buf;
store_path.push("data");
let db_builder = builder
.create_if_missing(is_new)
.use_capped_prefix_extractor(true, KEY_PREFIX_LEN)
.use_bloom_filter(true, 9.9, true)
.path(
store_path
.to_str()
.ok_or_else(|| miette!("bad path name"))?,
); );
false
} else {
fs::write(
manifest_path,
rmp_serde::to_vec_named(&DbManifest {
storage_version: CURRENT_STORAGE_VERSION,
})
.into_diagnostic()
.wrap_err_with(|| "when serializing manifest")?,
)
.into_diagnostic()
.wrap_err_with(|| "when serializing manifest")?;
true
}
};
let mut store_path = path_buf;
store_path.push("data");
let db_builder = builder
.create_if_missing(is_new)
.use_capped_prefix_extractor(true, KEY_PREFIX_LEN)
.use_bloom_filter(true, 9.9, true)
.path(
store_path
.to_str()
.ok_or_else(|| miette!("bad path name"))?,
);
let db = db_builder.build()?;
Db::new(RocksDbStorage::new(db))
}
let db = db_builder.build()?; impl<S> Db<S>
where
S: Storage,
<S as Storage>::Tx: 'static,
{
/// create a new database with the specified storage
pub fn new(storage: S) -> Result<Self> {
let ret = Self { let ret = Self {
db: RocksDbStorage::new(db), db: storage,
relation_store_id: Arc::new(Default::default()), relation_store_id: Arc::new(Default::default()),
queries_count: Arc::new(Default::default()), queries_count: Arc::new(Default::default()),
running_queries: Arc::new(Mutex::new(Default::default())), running_queries: Arc::new(Mutex::new(Default::default())),
@ -156,7 +168,6 @@ impl Db {
ret.load_last_ids()?; ret.load_last_ids()?;
Ok(ret) Ok(ret)
} }
fn compact_relation(&self) -> Result<()> { fn compact_relation(&self) -> Result<()> {
let l = Tuple::default().encode_as_key(RelationId(0)); let l = Tuple::default().encode_as_key(RelationId(0));
let u = Tuple(vec![DataValue::Bot]).encode_as_key(RelationId(u64::MAX)); let u = Tuple(vec![DataValue::Bot]).encode_as_key(RelationId(u64::MAX));
@ -172,7 +183,7 @@ impl Db {
} }
fn transact(&self) -> Result<SessionTx> { fn transact(&self) -> Result<SessionTx> {
let ret = SessionTx { let ret = SessionTx {
tx: self.db.transact()?, tx: Box::new(self.db.transact()?),
mem_store_id: Default::default(), mem_store_id: Default::default(),
relation_store_id: self.relation_store_id.clone(), relation_store_id: self.relation_store_id.clone(),
}; };
@ -180,7 +191,7 @@ impl Db {
} }
fn transact_write(&self) -> Result<SessionTx> { fn transact_write(&self) -> Result<SessionTx> {
let ret = SessionTx { let ret = SessionTx {
tx: self.db.transact()?, tx: Box::new(self.db.transact()?),
mem_store_id: Default::default(), mem_store_id: Default::default(),
relation_store_id: self.relation_store_id.clone(), relation_store_id: self.relation_store_id.clone(),
}; };

@ -19,7 +19,6 @@ use crate::data::tuple::{Tuple, ENCODED_KEY_MIN_LEN};
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::transact::SessionTx; use crate::runtime::transact::SessionTx;
use crate::storage::StoreTx;
#[derive( #[derive(
Copy, Copy,
@ -233,8 +232,7 @@ impl RelationHandle {
let prefix_encoded = Tuple(lower).encode_as_key(self.id); let prefix_encoded = Tuple(lower).encode_as_key(self.id);
let upper_encoded = Tuple(upper).encode_as_key(self.id); let upper_encoded = Tuple(upper).encode_as_key(self.id);
// RelationIterator::new(tx, &prefix_encoded, &upper_encoded) // RelationIterator::new(tx, &prefix_encoded, &upper_encoded)
tx.tx tx.tx.range_scan(&prefix_encoded, &upper_encoded)
.range_scan(&prefix_encoded, &upper_encoded)
} }
pub(crate) fn scan_bounded_prefix( pub(crate) fn scan_bounded_prefix(
&self, &self,
@ -250,8 +248,7 @@ impl RelationHandle {
upper_t.0.push(DataValue::Bot); upper_t.0.push(DataValue::Bot);
let lower_encoded = lower_t.encode_as_key(self.id); let lower_encoded = lower_t.encode_as_key(self.id);
let upper_encoded = upper_t.encode_as_key(self.id); let upper_encoded = upper_t.encode_as_key(self.id);
tx.tx tx.tx.range_scan(&lower_encoded, &upper_encoded)
.range_scan(&lower_encoded, &upper_encoded)
} }
} }

@ -2,8 +2,8 @@
* Copyright 2022, The Cozo Project Authors. Licensed under MPL-2.0. * Copyright 2022, The Cozo Project Authors. Licensed under MPL-2.0.
*/ */
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering}; use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
use std::sync::Arc;
use miette::Result; use miette::Result;
@ -14,11 +14,10 @@ use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::in_mem::{InMemRelation, StoredRelationId}; use crate::runtime::in_mem::{InMemRelation, StoredRelationId};
use crate::runtime::relation::RelationId; use crate::runtime::relation::RelationId;
use crate::storage::rocks::RocksDbTx;
use crate::storage::StoreTx; use crate::storage::StoreTx;
pub struct SessionTx { pub struct SessionTx {
pub(crate) tx: RocksDbTx, pub(crate) tx: Box<dyn StoreTx>,
pub(crate) relation_store_id: Arc<AtomicU64>, pub(crate) relation_store_id: Arc<AtomicU64>,
pub(crate) mem_store_id: Arc<AtomicU32>, pub(crate) mem_store_id: Arc<AtomicU32>,
} }

@ -10,25 +10,28 @@ pub(crate) mod rocks;
pub(crate) mod sled; pub(crate) mod sled;
pub(crate) mod tikv; pub(crate) mod tikv;
pub(crate) trait Storage<'a> { pub trait Storage {
type Tx: StoreTx<'a>; type Tx: StoreTx;
fn transact(&'a self) -> Result<Self::Tx>; fn transact(&self) -> Result<Self::Tx>;
fn del_range(&self, lower: &[u8], upper: &[u8]) -> Result<()>; fn del_range(&self, lower: &[u8], upper: &[u8]) -> Result<()>;
fn range_compact(&self, lower: &[u8], upper: &[u8]) -> Result<()>; fn range_compact(&self, lower: &[u8], upper: &[u8]) -> Result<()>;
} }
pub(crate) trait StoreTx<'a> { pub trait StoreTx {
type ReadSlice: AsRef<[u8]>; fn get(&self, key: &[u8], for_update: bool) -> Result<Option<Vec<u8>>>;
type KVIter: Iterator<Item = Result<Tuple>>;
type KVIterRaw: Iterator<Item = Result<(Vec<u8>, Vec<u8>)>>;
fn get(&self, key: &[u8], for_update: bool) -> Result<Option<Self::ReadSlice>>;
fn put(&mut self, key: &[u8], val: &[u8]) -> Result<()>; fn put(&mut self, key: &[u8], val: &[u8]) -> Result<()>;
fn del(&mut self, key: &[u8]) -> Result<()>; fn del(&mut self, key: &[u8]) -> Result<()>;
fn exists(&self, key: &[u8], for_update: bool) -> Result<bool>; fn exists(&self, key: &[u8], for_update: bool) -> Result<bool>;
fn commit(&mut self) -> Result<()>; fn commit(&mut self) -> Result<()>;
fn range_scan(&'a self, lower: &[u8], upper: &[u8]) -> Self::KVIter; fn range_scan(
fn range_scan_raw(&'a self, lower: &[u8], upper: &[u8]) -> Self::KVIterRaw; &self,
lower: &[u8],
upper: &[u8],
) -> Box<dyn Iterator<Item = Result<Tuple>>>;
fn range_scan_raw(
&self,
lower: &[u8],
upper: &[u8],
) -> Box<dyn Iterator<Item = Result<(Vec<u8>, Vec<u8>)>>>;
} }

@ -4,15 +4,16 @@
use miette::{IntoDiagnostic, Result}; use miette::{IntoDiagnostic, Result};
use cozorocks::{DbIter, PinSlice, RocksDb, Tx}; use cozorocks::{DbIter, RocksDb, Tx};
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;
/// RocksDB storage engine
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct RocksDbStorage { pub struct RocksDbStorage {
db: RocksDb, db: RocksDb,
} }
@ -22,7 +23,7 @@ impl RocksDbStorage {
} }
} }
impl Storage<'_> for RocksDbStorage { impl Storage for RocksDbStorage {
type Tx = RocksDbTx; type Tx = RocksDbTx;
fn transact(&self) -> Result<Self::Tx> { fn transact(&self) -> Result<Self::Tx> {
@ -39,18 +40,14 @@ impl Storage<'_> for RocksDbStorage {
} }
} }
pub(crate) struct RocksDbTx { pub struct RocksDbTx {
db_tx: Tx, db_tx: Tx,
} }
impl StoreTx<'_> for RocksDbTx { impl StoreTx for RocksDbTx {
type ReadSlice = PinSlice;
type KVIter = RocksDbIterator;
type KVIterRaw = RocksDbIteratorRaw;
#[inline] #[inline]
fn get(&self, key: &[u8], for_update: bool) -> Result<Option<Self::ReadSlice>> { fn get(&self, key: &[u8], for_update: bool) -> Result<Option<Vec<u8>>> {
Ok(self.db_tx.get(key, for_update)?) Ok(self.db_tx.get(key, for_update)?.map(|v| v.to_vec()))
} }
#[inline] #[inline]
@ -72,24 +69,28 @@ impl StoreTx<'_> for RocksDbTx {
Ok(self.db_tx.commit()?) Ok(self.db_tx.commit()?)
} }
fn range_scan(&self, lower: &[u8], upper: &[u8]) -> Self::KVIter { fn range_scan(&self, lower: &[u8], upper: &[u8]) -> Box<dyn Iterator<Item = Result<Tuple>>> {
let mut inner = self.db_tx.iterator().upper_bound(upper).start(); let mut inner = self.db_tx.iterator().upper_bound(upper).start();
inner.seek(lower); inner.seek(lower);
RocksDbIterator { Box::new(RocksDbIterator {
inner, inner,
started: false, started: false,
upper_bound: upper.to_vec(), upper_bound: upper.to_vec(),
} })
} }
fn range_scan_raw(&self, lower: &[u8], upper: &[u8]) -> Self::KVIterRaw { fn range_scan_raw(
&self,
lower: &[u8],
upper: &[u8],
) -> Box<dyn Iterator<Item = Result<(Vec<u8>, Vec<u8>)>>> {
let mut inner = self.db_tx.iterator().upper_bound(upper).start(); let mut inner = self.db_tx.iterator().upper_bound(upper).start();
inner.seek(lower); inner.seek(lower);
RocksDbIteratorRaw { Box::new(RocksDbIteratorRaw {
inner, inner,
started: false, started: false,
upper_bound: upper.to_vec(), upper_bound: upper.to_vec(),
} })
} }
} }

@ -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())
} // }
} // }

@ -9,15 +9,16 @@ use approx::AbsDiffEq;
use env_logger::Env; use env_logger::Env;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde_json::json; use serde_json::json;
use cozo::RocksDbStorage;
use cozo::Db; use cozo::{new_cozo_rocksdb, Db};
lazy_static! { lazy_static! {
static ref TEST_DB: Db = { static ref TEST_DB: Db<RocksDbStorage> = {
let creation = Instant::now(); let creation = Instant::now();
let path = "_test_air_routes"; let path = "_test_air_routes";
_ = std::fs::remove_dir_all(path); _ = std::fs::remove_dir_all(path);
let db = Db::new(path).unwrap(); let db = new_cozo_rocksdb(path).unwrap();
dbg!(creation.elapsed()); dbg!(creation.elapsed());
let init = Instant::now(); let init = Instant::now();

@ -11,16 +11,19 @@ use std::sync::Mutex;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use cozo::Db; use cozo::RocksDbStorage;
use cozo::{new_cozo_rocksdb, Db};
#[derive(Default)] struct Handles<S> {
struct Handles {
current: AtomicI32, current: AtomicI32,
dbs: Mutex<BTreeMap<i32, Db>>, dbs: Mutex<BTreeMap<i32, Db<S>>>,
} }
lazy_static! { lazy_static! {
static ref HANDLES: Handles = Handles::default(); static ref HANDLES: Handles<RocksDbStorage> = Handles {
current: Default::default(),
dbs: Mutex::new(Default::default())
};
} }
/// Open a database. /// Open a database.
@ -38,7 +41,7 @@ pub unsafe extern "C" fn cozo_open_db(path: *const c_char, db_id: &mut i32) -> *
Err(err) => return CString::new(format!("{}", err)).unwrap().into_raw(), Err(err) => return CString::new(format!("{}", err)).unwrap().into_raw(),
}; };
match Db::new(path) { match new_cozo_rocksdb(path) {
Ok(db) => { Ok(db) => {
let id = HANDLES.current.fetch_add(1, Ordering::AcqRel); let id = HANDLES.current.fetch_add(1, Ordering::AcqRel);
let mut dbs = HANDLES.dbs.lock().unwrap(); let mut dbs = HANDLES.dbs.lock().unwrap();

@ -9,15 +9,19 @@ use lazy_static::lazy_static;
use robusta_jni::bridge; use robusta_jni::bridge;
use cozo::Db; use cozo::Db;
use cozo::RocksDbStorage;
#[derive(Default)] #[derive(Default)]
struct Handles { struct Handles<S> {
current: AtomicI32, current: AtomicI32,
dbs: Mutex<BTreeMap<i32, Db>>, dbs: Mutex<BTreeMap<i32, Db<S>>>,
} }
lazy_static! { lazy_static! {
static ref HANDLES: Handles = Handles::default(); static ref HANDLES: Handles<RocksDbStorage> = Handles {
current: Default::default(),
dbs: Mutex::new(Default::default())
};
} }
#[bridge] #[bridge]
@ -29,7 +33,7 @@ mod jni {
use robusta_jni::jni::errors::Result as JniResult; use robusta_jni::jni::errors::Result as JniResult;
use robusta_jni::jni::objects::AutoLocal; use robusta_jni::jni::objects::AutoLocal;
use cozo::Db; use cozo::{new_cozo_rocksdb};
use crate::HANDLES; use crate::HANDLES;
@ -42,7 +46,7 @@ mod jni {
impl<'env: 'borrow, 'borrow> CozoDb<'env, 'borrow> { impl<'env: 'borrow, 'borrow> CozoDb<'env, 'borrow> {
pub extern "jni" fn openDb(path: String) -> JniResult<i32> { pub extern "jni" fn openDb(path: String) -> JniResult<i32> {
match Db::new(path) { match new_cozo_rocksdb(path) {
Ok(db) => { Ok(db) => {
let id = HANDLES.current.fetch_add(1, Ordering::AcqRel); let id = HANDLES.current.fetch_add(1, Ordering::AcqRel);
let mut dbs = HANDLES.dbs.lock().unwrap(); let mut dbs = HANDLES.dbs.lock().unwrap();

Loading…
Cancel
Save