diff --git a/Cargo.lock b/Cargo.lock index 444c0e1..4797ad9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytes" @@ -164,6 +170,16 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -219,6 +235,29 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -319,8 +358,10 @@ name = "rcommunity_core" version = "0.0.1" dependencies = [ "async-trait", + "parking_lot", "thiserror", "tokio", + "tracing", ] [[package]] @@ -352,6 +393,21 @@ dependencies = [ "url", ] +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.130" @@ -378,6 +434,12 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + [[package]] name = "socket2" version = "0.4.4" @@ -477,6 +539,38 @@ dependencies = [ "tokio", ] +[[package]] +name = "tracing" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +dependencies = [ + "lazy_static", +] + [[package]] name = "unicode-bidi" version = "0.3.7" diff --git a/rcommunity_core/Cargo.toml b/rcommunity_core/Cargo.toml index a97948d..cc1e412 100644 --- a/rcommunity_core/Cargo.toml +++ b/rcommunity_core/Cargo.toml @@ -8,7 +8,9 @@ edition = "2021" [dependencies] async-trait = "0.1.56" +parking_lot = "0.12.1" thiserror = "1.0.31" +tracing = "0.1.34" [dev-dependencies] tokio = { version = "1.19.0", features = ["macros", "rt-multi-thread"] } diff --git a/rcommunity_core/src/backend.rs b/rcommunity_core/src/backend.rs index 6e22a80..ccf88ea 100644 --- a/rcommunity_core/src/backend.rs +++ b/rcommunity_core/src/backend.rs @@ -1,8 +1,7 @@ use async_trait::async_trait; use crate::{ - error::Error, query::reaction, Enumerable, ItemType, Multiple, Numerical, Once, ReactionType, - UserType, WithData, + error::Error, Enumerable, ItemType, Multiple, Numerical, Once, ReactionType, UserType, WithData, }; #[async_trait] diff --git a/rcommunity_core/src/lib.rs b/rcommunity_core/src/lib.rs index 4fce4a1..a4d2a3d 100644 --- a/rcommunity_core/src/lib.rs +++ b/rcommunity_core/src/lib.rs @@ -1,6 +1,9 @@ +// clippy settings +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +// toggle unstable features +#![allow(incomplete_features)] #![feature(specialization)] -#![feature(associated_type_defaults)] -#![feature(negative_impls)] pub mod error; pub mod traits; diff --git a/rcommunity_core/src/markers/mod.rs b/rcommunity_core/src/markers/mod.rs index 1e00afd..63d11f9 100644 --- a/rcommunity_core/src/markers/mod.rs +++ b/rcommunity_core/src/markers/mod.rs @@ -21,10 +21,11 @@ impl store::Storable for T { } default async fn store_unique_index( &self, - txn: &mut impl Transaction, - user: &impl UserType, - item: &impl ItemType, + _txn: &mut impl Transaction, + _user: &impl UserType, + _item: &impl ItemType, ) -> Result<()> { + // by default do nothing Ok(()) } } diff --git a/rcommunity_core/src/store/memory.rs b/rcommunity_core/src/store/memory.rs index 38b9e4a..6c0fb38 100644 --- a/rcommunity_core/src/store/memory.rs +++ b/rcommunity_core/src/store/memory.rs @@ -1,22 +1,32 @@ use async_trait::async_trait; -use std::sync::RwLock; +use parking_lot::Mutex; use std::{collections::BTreeMap, sync::Arc}; use crate::error::Result; use super::{Store, Transaction}; -type StringMap = Arc>>; +type StringMap = BTreeMap; -#[derive(Debug, Default)] pub struct MemoryStore { - pub store: StringMap, + pub store: Arc>, +} + +impl Default for MemoryStore { + fn default() -> Self { + MemoryStore { + store: Arc::new(Mutex::new(StringMap::new())), + } + } } #[async_trait] impl Store for MemoryStore { type Trans = MemoryTransaction; async fn txn_begin(&self) -> Result { + // remain locked for this whole transaction + let guard = self.store.lock(); + std::mem::forget(guard); Ok(MemoryTransaction { store: self.store.clone(), }) @@ -24,16 +34,28 @@ impl Store for MemoryStore { } pub struct MemoryTransaction { - store: StringMap, + store: Arc>, +} + +impl MemoryTransaction { + fn get_map(&self) -> &StringMap { + unsafe { self.store.data_ptr().as_ref().unwrap() } + } + fn get_map_mut(&mut self) -> &mut StringMap { + unsafe { self.store.data_ptr().as_mut().unwrap() } + } } #[async_trait] impl Transaction for MemoryTransaction { async fn get(&self, key: String) -> Result> { - Ok(self.store.read().unwrap().get(&key).map(String::from)) + Ok(self.get_map().get(&key).map(String::from)) + } + async fn get_for_update(&mut self, key: String) -> Result> { + self.get(key).await } async fn put(&mut self, key: String, value: String) -> Result<()> { - self.store.write().unwrap().insert(key, value); + self.get_map_mut().insert(key, value); Ok(()) } async fn commit(&mut self) -> Result<()> { @@ -43,3 +65,9 @@ impl Transaction for MemoryTransaction { unimplemented!(); } } + +impl Drop for MemoryTransaction { + fn drop(&mut self) { + unsafe { self.store.force_unlock() }; + } +} diff --git a/rcommunity_core/src/store/mod.rs b/rcommunity_core/src/store/mod.rs index a0b2d6c..171ce5c 100644 --- a/rcommunity_core/src/store/mod.rs +++ b/rcommunity_core/src/store/mod.rs @@ -13,6 +13,7 @@ pub trait Store { #[async_trait] pub trait Transaction: Send { async fn get(&self, key: String) -> Result>; + async fn get_for_update(&mut self, key: String) -> Result>; async fn put(&mut self, key: String, value: String) -> Result<()>; async fn commit(&mut self) -> Result<()>; async fn rollback(&mut self) -> Result<()>; diff --git a/rcommunity_core/src/traits.rs b/rcommunity_core/src/traits.rs index 76e5ad2..507f6f0 100644 --- a/rcommunity_core/src/traits.rs +++ b/rcommunity_core/src/traits.rs @@ -6,9 +6,6 @@ pub trait UserType: Clone + Sync + Unique {} pub trait ItemType: Clone + Sync + Unique {} pub trait ReactionType: Clone + Sync {} -// user type can't be reaction type -impl !UserType for T where T: ReactionType {} - pub trait WithData: Unique + ReactionType { type Item; } @@ -23,5 +20,3 @@ pub trait Once: ReactionType { const IS_ONCE: bool = true; } pub trait Multiple: ReactionType {} -// reaction is either once or multiple -impl !Once for T where T: Multiple {}