diff --git a/Cargo.lock b/Cargo.lock index d369d037..94c80f4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1534,6 +1534,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "doxygen-rs" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff670ea0c9bbb8414e7efa6e23ebde2b8f520a7eef78273a3918cf1903e7505" +dependencies = [ + "phf", +] + [[package]] name = "either" version = "1.8.1" @@ -1770,16 +1779,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "futures" version = "0.3.28" @@ -2028,6 +2027,45 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heed" +version = "0.20.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae92e0d788e4b5608cddd89bec1128ad9f424e365025bd2454915aab450d7a2" +dependencies = [ + "bytemuck", + "byteorder", + "heed-traits", + "heed-types", + "libc", + "lmdb-master-sys", + "once_cell", + "page_size", + "serde", + "synchronoise", + "url", +] + +[[package]] +name = "heed-traits" +version = "0.20.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44055e6d049fb62b58671059045fe4a8a083d78ef04347818cc8a87a62d6fa1f" + +[[package]] +name = "heed-types" +version = "0.20.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d419e64e429f0bbe6d8ef3507bf137105c8cebee0e5fba59cf556de93c8ab57" +dependencies = [ + "bincode", + "bytemuck", + "byteorder", + "heed-traits", + "serde", + "serde_json", +] + [[package]] name = "hermit-abi" version = "0.3.2" @@ -2527,7 +2565,7 @@ dependencies = [ "itertools 0.11.0", "nix", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "rand", "regex", "rusqlite", @@ -2551,19 +2589,22 @@ dependencies = [ "axum", "base64 0.21.2", "bincode", + "bytemuck", "bytes 1.4.0", "bytesize", "clap", "color-eyre", "either", "futures", + "heed", + "heed-types", "hmac", "humantime", "hyper", "itertools 0.11.0", "libsqlx", "moka", - "parking_lot 0.12.1", + "parking_lot", "priority-queue", "rand", "regex", @@ -2571,7 +2612,6 @@ dependencies = [ "serde_json", "sha2", "sha3", - "sled", "tempfile", "thiserror", "tokio", @@ -2602,6 +2642,18 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +[[package]] +name = "lmdb-master-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629c123f5321b48fa4f8f4d3b868165b748d9ba79c7103fb58e3a94f736bcedd" +dependencies = [ + "cc", + "doxygen-rs", + "libc", + "pkg-config", +] + [[package]] name = "lock_api" version = "0.4.10" @@ -2778,7 +2830,7 @@ dependencies = [ "crossbeam-utils", "futures-util", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "quanta", "rustc_version", "scheduled-thread-pool", @@ -3023,21 +3075,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] -name = "parking" -version = "2.1.0" +name = "page_size" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "1b7663cbd190cfd818d08efa8497f6cd383076688c49a391ef7c0d03cd12b561" +dependencies = [ + "libc", + "winapi", +] [[package]] -name = "parking_lot" -version = "0.11.2" +name = "parking" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" [[package]] name = "parking_lot" @@ -3046,21 +3097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -3119,6 +3156,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros", "phf_shared", ] @@ -3142,6 +3180,19 @@ dependencies = [ "rand", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.25", +] + [[package]] name = "phf_shared" version = "0.11.2" @@ -3841,7 +3892,7 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" dependencies = [ - "parking_lot 0.12.1", + "parking_lot", ] [[package]] @@ -4095,22 +4146,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "sled" -version = "0.34.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" -dependencies = [ - "crc32fast", - "crossbeam-epoch", - "crossbeam-utils", - "fs2", - "fxhash", - "libc", - "log", - "parking_lot 0.11.2", -] - [[package]] name = "slice-group-by" version = "0.3.1" @@ -4192,7 +4227,7 @@ dependencies = [ "mimalloc", "nix", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "priority-queue", "proptest", "prost", @@ -4323,6 +4358,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synchronoise" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" +dependencies = [ + "crossbeam-queue", +] + [[package]] name = "system-interface" version = "0.25.9" @@ -4494,7 +4538,7 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", diff --git a/libsqlx-server/Cargo.toml b/libsqlx-server/Cargo.toml index 90b27680..89b34c74 100644 --- a/libsqlx-server/Cargo.toml +++ b/libsqlx-server/Cargo.toml @@ -11,12 +11,15 @@ async-trait = "0.1.71" axum = "0.6.18" base64 = "0.21.2" bincode = "1.3.3" +bytemuck = { version = "1.13.1", features = ["derive"] } bytes = { version = "1.4.0", features = ["serde"] } bytesize = { version = "1.2.0", features = ["serde"] } clap = { version = "4.3.11", features = ["derive"] } color-eyre = "0.6.2" either = "1.8.1" futures = "0.3.28" +heed = { version = "0.20.0-alpha.3", features = ["serde-bincode"] } +heed-types = "0.20.0-alpha.3" hmac = "0.12.1" humantime = "2.1.0" hyper = { version = "0.14.27", features = ["h2", "server"] } @@ -31,7 +34,6 @@ serde = { version = "1.0.166", features = ["derive", "rc"] } serde_json = "1.0.100" sha2 = "0.10.7" sha3 = "0.10.8" -sled = "0.34.7" tempfile = "3.6.0" thiserror = "1.0.43" tokio = { version = "1.29.1", features = ["full"] } diff --git a/libsqlx-server/src/http/admin.rs b/libsqlx-server/src/http/admin.rs index 4dd27944..ac5c9ede 100644 --- a/libsqlx-server/src/http/admin.rs +++ b/libsqlx-server/src/http/admin.rs @@ -185,7 +185,6 @@ async fn list_allocs( .handler() .store() .list_allocs() - .await .into_iter() .map(|cfg| AllocView { id: cfg.db_name }) .collect(); diff --git a/libsqlx-server/src/main.rs b/libsqlx-server/src/main.rs index 296c54c9..5a9e26da 100644 --- a/libsqlx-server/src/main.rs +++ b/libsqlx-server/src/main.rs @@ -93,7 +93,14 @@ async fn main() -> Result<()> { let mut join_set = JoinSet::new(); - let store = Arc::new(Store::new(&config.db_path)); + + let meta_path = config.db_path.join("meta"); + tokio::fs::create_dir_all(&meta_path).await?; + let env = heed::EnvOpenOptions::new() + .max_dbs(1000) + .map_size(100 * 1024 * 1024) + .open(meta_path)?; + let store = Arc::new(Store::new(env.clone())); let manager = Arc::new(Manager::new(config.db_path.clone(), store.clone(), 100)); let bus = Arc::new(Bus::new(config.cluster.id, manager.clone())); diff --git a/libsqlx-server/src/manager.rs b/libsqlx-server/src/manager.rs index 69d1376f..fb44414d 100644 --- a/libsqlx-server/src/manager.rs +++ b/libsqlx-server/src/manager.rs @@ -41,7 +41,7 @@ impl Manager { return Some(sender.clone()); } - if let Some(config) = self.meta_store.meta(&database_id).await { + if let Some(config) = self.meta_store.meta(&database_id) { let path = self.db_path.join("dbs").join(database_id.to_string()); tokio::fs::create_dir_all(&path).await.unwrap(); let (alloc_sender, inbox) = mpsc::channel(MAX_ALLOC_MESSAGE_QUEUE_LEN); @@ -73,12 +73,12 @@ impl Manager { meta: &AllocConfig, dispatcher: Arc, ) { - self.store().allocate(database_id, meta).await; + self.store().allocate(&database_id, meta); self.schedule(database_id, dispatcher).await; } pub async fn deallocate(&self, database_id: DatabaseId) { - self.meta_store.deallocate(database_id).await; + self.meta_store.deallocate(&database_id); self.cache.remove(&database_id).await; let db_path = self.db_path.join("dbs").join(database_id.to_string()); tokio::fs::remove_dir_all(db_path).await.unwrap(); diff --git a/libsqlx-server/src/meta.rs b/libsqlx-server/src/meta.rs index 0d61d04f..84a8856c 100644 --- a/libsqlx-server/src/meta.rs +++ b/libsqlx-server/src/meta.rs @@ -1,10 +1,10 @@ -use core::fmt; -use std::path::Path; +use std::fmt; +use heed::bytemuck::{Pod, Zeroable}; +use heed::types::{SerdeBincode, OwnedType}; use serde::{Deserialize, Serialize}; use sha3::digest::{ExtendableOutput, Update, XofReader}; use sha3::Shake128; -use sled::Tree; use tokio::task::block_in_place; use crate::allocation::config::AllocConfig; @@ -12,10 +12,12 @@ use crate::allocation::config::AllocConfig; type ExecFn = Box)>; pub struct Store { - meta_store: Tree, + env: heed::Env, + alloc_config_db: heed::Database, SerdeBincode>, } -#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Hash, Clone, Copy)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Hash, Clone, Copy, Pod, Zeroable)] +#[repr(transparent)] pub struct DatabaseId([u8; 16]); impl DatabaseId { @@ -47,48 +49,63 @@ impl AsRef<[u8]> for DatabaseId { } impl Store { - pub fn new(path: &Path) -> Self { - std::fs::create_dir_all(&path).unwrap(); - let path = path.join("store"); - let db = sled::open(path).unwrap(); - let meta_store = db.open_tree("meta_store").unwrap(); - - Self { meta_store } + const ALLOC_CONFIG_DB_NAME: &'static str = "alloc_conf_db"; + + pub fn new(env: heed::Env) -> Self { + let mut txn = env.write_txn().unwrap(); + let alloc_config_db = env + .create_database(&mut txn, Some(Self::ALLOC_CONFIG_DB_NAME)) + .unwrap(); + txn.commit().unwrap(); + + Self { + env, + alloc_config_db, + } } - pub async fn allocate(&self, id: DatabaseId, meta: &AllocConfig) { + pub fn allocate(&self, id: &DatabaseId, meta: &AllocConfig) { //TODO: Handle conflict block_in_place(|| { - let meta_bytes = bincode::serialize(meta).unwrap(); - self.meta_store - .compare_and_swap(id, None as Option<&[u8]>, Some(meta_bytes)) + let mut txn = self.env.write_txn().unwrap(); + if self + .alloc_config_db + .lazily_decode_data() + .get(&txn, id) .unwrap() - .unwrap(); + .is_some() + { + panic!("alloc already exists"); + }; + self.alloc_config_db.put(&mut txn, id, meta).unwrap(); + txn.commit().unwrap(); }); } - pub async fn deallocate(&self, id: DatabaseId) { - block_in_place(|| self.meta_store.remove(id).unwrap()); + pub fn deallocate(&self, id: &DatabaseId) { + block_in_place(|| { + let mut txn = self.env.write_txn().unwrap(); + self.alloc_config_db.delete(&mut txn, id).unwrap(); + txn.commit().unwrap(); + }); } - pub async fn meta(&self, database_id: &DatabaseId) -> Option { + pub fn meta(&self, id: &DatabaseId) -> Option { block_in_place(|| { - let config = self.meta_store.get(database_id).unwrap()?; - let config = bincode::deserialize(config.as_ref()).unwrap(); - Some(config) + let txn = self.env.read_txn().unwrap(); + self.alloc_config_db.get(&txn, id).unwrap() }) } - pub async fn list_allocs(&self) -> Vec { + pub fn list_allocs(&self) -> Vec { block_in_place(|| { - let mut out = Vec::new(); - for kv in self.meta_store.iter() { - let (_k, v) = kv.unwrap(); - let alloc = bincode::deserialize(&v).unwrap(); - out.push(alloc); - } - - out + let txn = self.env.read_txn().unwrap(); + self.alloc_config_db + .iter(&txn) + .unwrap() + .map(Result::unwrap) + .map(|x| x.1) + .collect() }) } }