write our own FFI

main
Ziyang Hu 2 years ago
parent e61265d2a6
commit 85eac84a27

@ -0,0 +1 @@
rocksdb

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/cozo_parser/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/ast/op/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/cozo_parser/target" />
<excludeFolder url="file://$MODULE_DIR$/src/ast/op/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$/rocksdb">
<contentRoot DIR="$PROJECT_DIR$" />
</component>
</project>

@ -3,6 +3,7 @@
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/cozo.iml" filepath="$PROJECT_DIR$/.idea/cozo.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/cozo.iml" filepath="$PROJECT_DIR$/.idea/cozo.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/rocksdb.iml" filepath="$PROJECT_DIR$/.idea/rocksdb.iml" />
</modules> </modules>
</component> </component>
</project> </project>

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

@ -2,5 +2,6 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/rocksdb" vcs="Git" />
</component> </component>
</project> </project>

@ -11,7 +11,7 @@ pest_derive = "2.0"
ordered-float = "2.10.0" ordered-float = "2.10.0"
uuid = "0.8" uuid = "0.8"
chrono = "0.4" chrono = "0.4"
rocksdb = "0.18.0"
anyhow = "1.0" anyhow = "1.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
thiserror = "1.0.30" thiserror = "1.0.30"
cozo-rocks-sys = { path = "cozo-rocks-sys" }

@ -0,0 +1,12 @@
[package]
name = "cozo-rocks-sys"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cxx = "1.0.66"
[build-dependencies]
cxx-build = "1.0.66"

@ -0,0 +1,16 @@
fn main() {
cxx_build::bridge("src/lib.rs")
.file("src/cozorocks.cc")
.include("../rocksdb/include")
.include("include")
.flag_if_supported("-std=c++17")
.compile("rocksdb-sys");
println!("cargo:rustc-link-search=rocksdb/");
println!("cargo:rustc-link-lib=rocksdb");
println!("cargo:rustc-link-lib=z");
println!("cargo:rustc-link-lib=bz2");
println!("cargo:rerun-if-changed=src/main.rs");
println!("cargo:rerun-if-changed=src/cozorocks.cc");
println!("cargo:rerun-if-changed=include/cozorocks.h");
}

@ -0,0 +1,86 @@
//
// Created by Ziyang Hu on 2022/4/13.
//
#pragma once
#include <memory>
#include "rust/cxx.h"
#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"
#include "rocksdb/utilities/transaction.h"
#include "rocksdb/utilities/transaction_db.h"
struct Status;
typedef ROCKSDB_NAMESPACE::Status::Code StatusCode;
typedef ROCKSDB_NAMESPACE::Status::SubCode StatusSubCode;
typedef ROCKSDB_NAMESPACE::Status::Severity StatusSeverity;
std::unique_ptr<ROCKSDB_NAMESPACE::DB> new_db();
struct Options {
mutable ROCKSDB_NAMESPACE::Options inner;
public:
inline void prepare_for_bulk_load() const {
inner.PrepareForBulkLoad();
}
inline void increase_parallelism() const {
inner.IncreaseParallelism();
}
inline void optimize_level_style_compaction() const {
inner.OptimizeLevelStyleCompaction();
};
inline void set_create_if_missing(bool v) const {
inner.create_if_missing = v;
}
};
inline std::unique_ptr<Options> new_options() {
return std::unique_ptr<Options>(new Options);
}
struct PinnableSlice {
ROCKSDB_NAMESPACE::PinnableSlice inner;
inline rust::Slice<const std::uint8_t> as_bytes() const {
return rust::Slice(reinterpret_cast<const std::uint8_t *>(inner.data()), inner.size());
}
};
struct DB {
mutable ROCKSDB_NAMESPACE::DB *inner;
inline ~DB() {
if (inner != nullptr) {
delete inner;
}
}
void put(rust::Slice<const uint8_t> key, rust::Slice<const uint8_t> val, Status &status) const;
inline std::unique_ptr<PinnableSlice> get(rust::Slice<const uint8_t> key) const {
auto pinnable_val = std::make_unique<PinnableSlice>();
inner->Get(ROCKSDB_NAMESPACE::ReadOptions(),
inner->DefaultColumnFamily(),
ROCKSDB_NAMESPACE::Slice(reinterpret_cast<const char *>(key.data()), key.size()),
&pinnable_val->inner);
return pinnable_val;
}
};
inline std::unique_ptr<DB> open_db(const Options &options, const rust::Str path) {
ROCKSDB_NAMESPACE::DB *db_ptr;
ROCKSDB_NAMESPACE::Status s = ROCKSDB_NAMESPACE::DB::Open(options.inner, std::string(path), &db_ptr);
auto db = std::unique_ptr<DB>(new DB);
db->inner = db_ptr;
return db;
}

@ -0,0 +1,134 @@
//
// Created by Ziyang Hu on 2022/4/13.
//
#include <iostream>
#include "cozorocks.h"
#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"
#include "rocksdb/utilities/transaction.h"
#include "rocksdb/utilities/transaction_db.h"
#include "cozo-rocks-sys/src/lib.rs.h"
//using ROCKSDB_NAMESPACE::DB;
//using ROCKSDB_NAMESPACE::Options;
//using ROCKSDB_NAMESPACE::PinnableSlice;
//using ROCKSDB_NAMESPACE::ReadOptions;
//using ROCKSDB_NAMESPACE::Status;
//using ROCKSDB_NAMESPACE::WriteBatch;
//using ROCKSDB_NAMESPACE::WriteOptions;
//using ROCKSDB_NAMESPACE::ColumnFamilyDescriptor;
//using ROCKSDB_NAMESPACE::ColumnFamilyHandle;
//using ROCKSDB_NAMESPACE::ColumnFamilyOptions;
//using ROCKSDB_NAMESPACE::Slice;
//using ROCKSDB_NAMESPACE::Snapshot;
//using ROCKSDB_NAMESPACE::Transaction;
//using ROCKSDB_NAMESPACE::TransactionDB;
//using ROCKSDB_NAMESPACE::TransactionDBOptions;
//using ROCKSDB_NAMESPACE::TransactionOptions;
#if defined(OS_WIN)
std::string kDBPath = "C:\\Windows\\TEMP\\rocksdb_simple_example";
#else
std::string kDBPath = "/tmp/rocksdb_simple_example";
#endif
//std::unique_ptr<DB> new_db() {
// DB *db_ptr;
// Options options;
// // Optimize RocksDB. This is the easiest way to get RocksDB to perform well
// options.IncreaseParallelism();
// options.OptimizeLevelStyleCompaction();
// // create the DB if it's not already present
// options.create_if_missing = true;
//
// // open DB
// Status s = DB::Open(options, kDBPath, &db_ptr);
// std::unique_ptr<DB> db(db_ptr);
// assert(s.ok());
//
// // Put key-value
// s = db->Put(WriteOptions(), "key1", "value");
// assert(s.ok());
// std::string value;
// // get value
// s = db->Get(ReadOptions(), "key1", &value);
// assert(s.ok());
// assert(value == "value");
//
// // atomically apply a set of updates
// {
// WriteBatch batch;
// batch.Delete("key1");
// batch.Put("key2", value);
// s = db->Write(WriteOptions(), &batch);
// }
//
// s = db->Get(ReadOptions(), "key1", &value);
// assert(s.IsNotFound());
//
// db->Get(ReadOptions(), "key2", &value);
// assert(value == "value");
// std::cout << value << " and fuck!" << std::endl;
//
// {
// PinnableSlice pinnable_val;
// db->Get(ReadOptions(), db->DefaultColumnFamily(), "key2", &pinnable_val);
// assert(pinnable_val == "value");
// }
//
// {
// std::string string_val;
// // If it cannot pin the value, it copies the value to its internal buffer.
// // The intenral buffer could be set during construction.
// PinnableSlice pinnable_val(&string_val);
// db->Get(ReadOptions(), db->DefaultColumnFamily(), "key2", &pinnable_val);
// assert(pinnable_val == "value");
// // If the value is not pinned, the internal buffer must have the value.
// assert(pinnable_val.IsPinned() || string_val == "value");
// }
//
// PinnableSlice pinnable_val;
// s = db->Get(ReadOptions(), db->DefaultColumnFamily(), "key1", &pinnable_val);
// assert(s.IsNotFound());
// // Reset PinnableSlice after each use and before each reuse
// pinnable_val.Reset();
// db->Get(ReadOptions(), db->DefaultColumnFamily(), "key2", &pinnable_val);
// assert(pinnable_val == "value");
// pinnable_val.Reset();
// // The Slice pointed by pinnable_val is not valid after this point
//
// std::cout << "hello from C++" << std::endl;
//// return std::unique_ptr<BlobstoreClient>(new BlobstoreClient());
// return db;
//}
//std::unique_ptr<CozoRocksDB> open_db(const Options& options, const std::string& path) {
// DB *db_ptr;
// // Optimize RocksDB. This is the easiest way to get RocksDB to perform well
//// options.IncreaseParallelism();
//// options.OptimizeLevelStyleCompaction();
// // create the DB if it's not already present
//// options.create_if_missing = true;
//
// // open DB
// Status s = DB::Open(options, path, &db_ptr);
// std::unique_ptr<DB> db(db_ptr);
// std::unique_ptr<CozoRocksDB> cdb(new CozoRocksDB{});
// cdb->db = std::move(db);
// cdb->db_status = std::move(s);
// return cdb;
//}
void DB::put(rust::Slice<const uint8_t> key, rust::Slice<const uint8_t> val, Status &status) const {
auto s = inner->Put(ROCKSDB_NAMESPACE::WriteOptions(),
ROCKSDB_NAMESPACE::Slice(reinterpret_cast<const char *>(key.data()), key.size()),
ROCKSDB_NAMESPACE::Slice(reinterpret_cast<const char *>(val.data()), val.size()));
status.code = s.code();
status.subcode = s.subcode();
status.severity = s.severity();
}

@ -0,0 +1,95 @@
#[cxx::bridge]
mod ffi {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct Status {
code: StatusCode,
subcode: StatusSubCode,
severity: StatusSeverity
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum StatusCode {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5,
kMergeInProgress = 6,
kIncomplete = 7,
kShutdownInProgress = 8,
kTimedOut = 9,
kAborted = 10,
kBusy = 11,
kExpired = 12,
kTryAgain = 13,
kCompactionTooLarge = 14,
kColumnFamilyDropped = 15,
kMaxCode,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum StatusSubCode {
kNone = 0,
kMutexTimeout = 1,
kLockTimeout = 2,
kLockLimit = 3,
kNoSpace = 4,
kDeadlock = 5,
kStaleFile = 6,
kMemoryLimit = 7,
kSpaceLimit = 8,
kPathNotFound = 9,
KMergeOperandsInsufficientCapacity = 10,
kManualCompactionPaused = 11,
kOverwritten = 12,
kTxnNotPrepared = 13,
kIOFenced = 14,
kMaxSubCode,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum StatusSeverity {
kNoError = 0,
kSoftError = 1,
kHardError = 2,
kFatalError = 3,
kUnrecoverableError = 4,
kMaxSeverity,
}
unsafe extern "C++" {
include!("cozo-rocks-sys/include/cozorocks.h");
type DB;
type Options;
type PinnableSlice;
type StatusCode;
type StatusSubCode;
type StatusSeverity;
fn as_bytes(self: &PinnableSlice) -> &[u8];
fn new_options() -> UniquePtr<Options>;
fn prepare_for_bulk_load(self: &Options);
fn increase_parallelism(self: &Options);
fn optimize_level_style_compaction(self: &Options);
fn set_create_if_missing(self: &Options, v: bool);
fn open_db(options: &Options, path: &str) -> UniquePtr<DB>;
fn put(self: &DB, key: &[u8], val: &[u8], status: &mut Status);
fn get(self: &DB, key: &[u8]) -> UniquePtr<PinnableSlice>;
}
}
pub use ffi::*;
impl Status {
pub fn new() -> Self {
Self {
code: StatusCode::kOk,
subcode: StatusSubCode::kNone,
severity: StatusSeverity::kNoError
}
}
}

@ -1,3 +1,4 @@
use std::collections::BTreeMap;
use pest::iterators::{Pair, Pairs}; use pest::iterators::{Pair, Pairs};
use crate::ast::parse_string; use crate::ast::parse_string;
use crate::env::{Env, LayeredEnv, StructuredEnvItem}; use crate::env::{Env, LayeredEnv, StructuredEnvItem};
@ -10,7 +11,7 @@ use crate::typing::StorageStatus::{Planned, Stored};
use crate::value::{ByteArrayBuilder, ByteArrayParser, Value}; use crate::value::{ByteArrayBuilder, ByteArrayParser, Value};
use crate::parser::{Parser, Rule}; use crate::parser::{Parser, Rule};
use pest::Parser as PestParser; use pest::Parser as PestParser;
use rocksdb::IteratorMode; // use rocksdb::IteratorMode;
fn parse_ident(pair: Pair<Rule>) -> String { fn parse_ident(pair: Pair<Rule>) -> String {
pair.as_str().to_string() pair.as_str().to_string()
@ -291,106 +292,107 @@ pub enum TableKind {
impl Storage { impl Storage {
fn all_metadata(&self, env: &StructuredEnvItem) -> Result<Vec<Structured>> { fn all_metadata(&self, env: &StructuredEnvItem) -> Result<Vec<Structured>> {
let it = self.db.as_ref().ok_or(DatabaseClosed)?.full_iterator(IteratorMode::Start); todo!()
// let it = self.db.as_ref().ok_or(DatabaseClosed)?.full_iterator(IteratorMode::Start);
let mut ret = vec![]; //
for (k, v) in it { // let mut ret = vec![];
let mut key_parser = ByteArrayParser::new(&k); // for (k, v) in it {
let table_name = key_parser.parse_value().unwrap().get_string().unwrap(); // let mut key_parser = ByteArrayParser::new(&k);
// let table_name = key_parser.parse_value().unwrap().get_string().unwrap();
let mut data_parser = ByteArrayParser::new(&v); //
let table_kind = data_parser.parse_value().unwrap(); // let mut data_parser = ByteArrayParser::new(&v);
let table_id = TableId { name: table_name, global: true }; // let table_kind = data_parser.parse_value().unwrap();
match table_kind { // let table_id = TableId { name: table_name, global: true };
Value::UInt(i) if i == TableKind::Node as u64 => { // match table_kind {
let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() // Value::UInt(i) if i == TableKind::Node as u64 => {
.into_iter().map(|v| { // let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap()
let mut vs = v.get_list().unwrap().into_iter(); // .into_iter().map(|v| {
let name = vs.next().unwrap().get_string().unwrap(); // let mut vs = v.get_list().unwrap().into_iter();
let typ = vs.next().unwrap().get_string().unwrap(); // let name = vs.next().unwrap().get_string().unwrap();
let typ = env.build_type_from_str(&typ).unwrap(); // let typ = vs.next().unwrap().get_string().unwrap();
let default = vs.next().unwrap().into_owned(); // let typ = env.build_type_from_str(&typ).unwrap();
Col { // let default = vs.next().unwrap().into_owned();
name, // Col {
typ, // name,
default, // typ,
} // default,
}).collect(); // }
let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() // }).collect();
.into_iter().map(|v| { // let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap()
let mut vs = v.get_list().unwrap().into_iter(); // .into_iter().map(|v| {
let name = vs.next().unwrap().get_string().unwrap(); // let mut vs = v.get_list().unwrap().into_iter();
let typ = vs.next().unwrap().get_string().unwrap(); // let name = vs.next().unwrap().get_string().unwrap();
let typ = env.build_type_from_str(&typ).unwrap(); // let typ = vs.next().unwrap().get_string().unwrap();
let default = vs.next().unwrap().into_owned(); // let typ = env.build_type_from_str(&typ).unwrap();
Col { // let default = vs.next().unwrap().into_owned();
name, // Col {
typ, // name,
default, // typ,
} // default,
}).collect(); // }
let node = Node { // }).collect();
status: StorageStatus::Stored, // let node = Node {
id: table_id, // status: StorageStatus::Stored,
keys, // id: table_id,
cols, // keys,
out_e: vec![], // TODO fix these // cols,
in_e: vec![], // out_e: vec![], // TODO fix these
attached: vec![], // in_e: vec![],
}; // attached: vec![],
ret.push(Structured::Node(node)); // };
} // ret.push(Structured::Node(node));
Value::UInt(i) if i == TableKind::Edge as u64 => { // }
let src_name = data_parser.parse_value().unwrap().get_string().unwrap(); // Value::UInt(i) if i == TableKind::Edge as u64 => {
let dst_name = data_parser.parse_value().unwrap().get_string().unwrap(); // let src_name = data_parser.parse_value().unwrap().get_string().unwrap();
let src_id = TableId { name: src_name, global: true }; // let dst_name = data_parser.parse_value().unwrap().get_string().unwrap();
let dst_id = TableId { name: dst_name, global: true }; // let src_id = TableId { name: src_name, global: true };
let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() // let dst_id = TableId { name: dst_name, global: true };
.into_iter().map(|v| { // let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap()
let mut vs = v.get_list().unwrap().into_iter(); // .into_iter().map(|v| {
let name = vs.next().unwrap().get_string().unwrap(); // let mut vs = v.get_list().unwrap().into_iter();
let typ = vs.next().unwrap().get_string().unwrap(); // let name = vs.next().unwrap().get_string().unwrap();
let typ = env.build_type_from_str(&typ).unwrap(); // let typ = vs.next().unwrap().get_string().unwrap();
let default = vs.next().unwrap().into_owned(); // let typ = env.build_type_from_str(&typ).unwrap();
Col { // let default = vs.next().unwrap().into_owned();
name, // Col {
typ, // name,
default, // typ,
} // default,
}).collect(); // }
let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() // }).collect();
.into_iter().map(|v| { // let cols: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap()
let mut vs = v.get_list().unwrap().into_iter(); // .into_iter().map(|v| {
let name = vs.next().unwrap().get_string().unwrap(); // let mut vs = v.get_list().unwrap().into_iter();
let typ = vs.next().unwrap().get_string().unwrap(); // let name = vs.next().unwrap().get_string().unwrap();
let typ = env.build_type_from_str(&typ).unwrap(); // let typ = vs.next().unwrap().get_string().unwrap();
let default = vs.next().unwrap().into_owned(); // let typ = env.build_type_from_str(&typ).unwrap();
Col { // let default = vs.next().unwrap().into_owned();
name, // Col {
typ, // name,
default, // typ,
} // default,
}).collect(); // }
let edge = Edge { // }).collect();
status: StorageStatus::Stored, // let edge = Edge {
src: src_id, // status: StorageStatus::Stored,
dst: dst_id, // src: src_id,
id: table_id, // dst: dst_id,
keys, // id: table_id,
cols, // keys,
}; // cols,
ret.push(Structured::Edge(edge)); // };
} // ret.push(Structured::Edge(edge));
Value::UInt(i) if i == TableKind::Columns as u64 => { // }
todo!() // Value::UInt(i) if i == TableKind::Columns as u64 => {
} // todo!()
Value::UInt(i) if i == TableKind::Index as u64 => { // }
todo!() // Value::UInt(i) if i == TableKind::Index as u64 => {
} // todo!()
_ => unreachable!() // }
} // _ => unreachable!()
} // }
Ok(ret) // }
// Ok(ret)
} }
fn persist_node(&mut self, node: &mut Node) -> Result<()> { fn persist_node(&mut self, node: &mut Node) -> Result<()> {
@ -521,6 +523,10 @@ impl Evaluator {
} }
Ok(()) Ok(())
} }
pub fn insert_data(&mut self, _pairs: Pairs<Rule>, _bindings: BTreeMap<&str, Value>) -> Result<()> {
todo!()
}
} }

@ -43,8 +43,8 @@ pub enum CozoError {
#[error(transparent)] #[error(transparent)]
Parse(#[from] pest::error::Error<Rule>), Parse(#[from] pest::error::Error<Rule>),
#[error(transparent)] // #[error(transparent)]
Storage(#[from] rocksdb::Error) // Storage(#[from] rocksdb::Error)
} }
pub type Result<T> = result::Result<T, CozoError>; pub type Result<T> = result::Result<T, CozoError>;

@ -154,4 +154,13 @@ struct_def = { "struct" ~ name_in_def ~ cols_def }
definition = _{ node_def | columns_def | edge_def | struct_def | index_def } definition = _{ node_def | columns_def | edge_def | struct_def | index_def }
global_def = { "create" ~ definition } global_def = { "create" ~ definition }
local_def = { "local" ~ definition } local_def = { "local" ~ definition }
statement = _{ global_def | local_def } statement = _{ global_def | local_def }
mutation = { (insert|update|delete) ~ expr ~ ("as" ~ name_in_def)? ~
( (exclude ~ name_in_def ~ ("," ~ name_in_def)*)
| (include ~ name_in_def ~ ("," ~ name_in_def)*))? }
exclude = {"exclude"}
include = {"include"}
insert = {"insert"}
update = {"update"}
delete = {"delete"}

@ -1,75 +1,91 @@
use rocksdb::{ColumnFamilyDescriptor, DB, Options, WriteOptions};
use crate::error::CozoError::DatabaseClosed; use crate::error::CozoError::DatabaseClosed;
use crate::error::Result; use crate::error::Result;
use crate::value::cozo_comparator_v1; use crate::value::cozo_comparator_v1;
pub struct Storage { pub struct Storage {
pub db: Option<DB>, pub db: Option<()>,
path: String, path: String,
} }
//
// fn make_options() -> Options {
// let mut options = Options::default();
//
// options.create_missing_column_families(true);
// options.create_if_missing(true);
// options.set_comparator("cozo_comparator_v1", cozo_comparator_v1);
// options
// }
fn make_options() -> Options { // #[allow(dead_code)]
let mut options = Options::default(); // fn make_write_options(global: bool) -> WriteOptions {
// let mut options = WriteOptions::new();
options.create_missing_column_families(true); // options.disable_wal(!global);
options.create_if_missing(true); // options
options.set_comparator("cozo_comparator_v1", cozo_comparator_v1); // }
options
}
#[allow(dead_code)]
fn make_write_options(global: bool) -> WriteOptions {
let mut options = WriteOptions::new();
options.disable_wal(!global);
options
}
impl Storage { impl Storage {
pub fn no_storage() -> Self { pub fn no_storage() -> Self {
Self { db: None, path: "".to_string() } Self { db: None, path: "".to_string() }
} }
pub fn new(path: String) -> Result<Self> { pub fn new(path: String) -> Result<Self> {
let options = make_options(); unimplemented!()
let cfs = match DB::list_cf(&options, &path) { // let options = make_options();
Ok(cfs) => { cfs } // let cfs = match DB::list_cf(&options, &path) {
Err(_) => { vec![] } // Ok(cfs) => { cfs }
}; // Err(_) => { vec![] }
let cfs = cfs.into_iter().map(|name| { // };
ColumnFamilyDescriptor::new(name, make_options()) // let cfs = cfs.into_iter().map(|name| {
}); // ColumnFamilyDescriptor::new(name, make_options())
let db = DB::open_cf_descriptors(&options, &path, cfs)?; // });
Ok(Storage { db: Some(db), path }) // let db = DB::open_cf_descriptors(&options, &path, cfs)?;
// Ok(Storage { db: Some(db), path })
} }
pub fn delete(&mut self) -> Result<()> { pub fn delete(&mut self) -> Result<()> {
drop(self.db.take()); unimplemented!();
DB::destroy(&make_options(), &self.path)?; // drop(self.db.take());
// DB::destroy(&make_options(), &self.path)?;
Ok(()) Ok(())
} }
pub fn put_global(&self, k: &[u8], v: &[u8]) -> Result<()> { pub fn put_global(&self, k: &[u8], v: &[u8]) -> Result<()> {
let db = self.db.as_ref().ok_or(DatabaseClosed)?; // let db = self.db.as_ref().ok_or(DatabaseClosed)?;
db.put(k, v)?; // db.put(k, v)?;
unimplemented!();
Ok(()) Ok(())
} }
pub fn create_table(&mut self, name: &str, _global: bool) -> Result<()> { pub fn create_table(&mut self, name: &str, _global: bool) -> Result<()> {
let db = self.db.as_mut().ok_or(DatabaseClosed)?; unimplemented!();
db.create_cf(name, &make_options())?; // let db = self.db.as_mut().ok_or(DatabaseClosed)?;
// db.create_cf(name, &make_options())?;
Ok(()) Ok(())
} }
pub fn drop_table(&mut self, name: &str, _global: bool) -> Result<()> { pub fn drop_table(&mut self, name: &str, _global: bool) -> Result<()> {
let db = self.db.as_mut().ok_or(DatabaseClosed)?; unimplemented!();
db.drop_cf(name)?; // let db = self.db.as_mut().ok_or(DatabaseClosed)?;
// db.drop_cf(name)?;
Ok(()) Ok(())
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::str::from_utf8;
use crate::typing::BaseType::String;
use super::*; use super::*;
#[test] #[test]
fn storage() { fn import() {
let mut s = Storage::new("_path_for_rocksdb_storage".to_string()).unwrap(); use cozo_rocks_sys::*;
s.delete().unwrap();
let options = new_options();
options.increase_parallelism();
options.optimize_level_style_compaction();
options.set_create_if_missing(true);
let db = open_db(&options, "xxyyzz");
let mut status = Status::new();
db.put("A key".as_bytes(), "A motherfucking value!!! 👋👋👋".as_bytes(), &mut status);
let val = db.get("A key".as_bytes());
let val = val.as_bytes();
println!("{:?} {}", status, from_utf8(val).unwrap());
} }
} }
Loading…
Cancel
Save