From 29d83e616f33679506e354c10b48e0a6142249cf Mon Sep 17 00:00:00 2001 From: Niko PLP Date: Mon, 29 Apr 2024 15:02:15 +0300 Subject: [PATCH] fix KCV store, adds MultiMapColumn --- ng-broker/src/server_storage/core/topic.rs | 18 +- ng-repo/src/kcv_storage.rs | 209 +++++++++++++++++---- ng-verifier/src/user_storage/branch.rs | 5 +- 3 files changed, 184 insertions(+), 48 deletions(-) diff --git a/ng-broker/src/server_storage/core/topic.rs b/ng-broker/src/server_storage/core/topic.rs index 5ae624f..7d8ed56 100644 --- a/ng-broker/src/server_storage/core/topic.rs +++ b/ng-broker/src/server_storage/core/topic.rs @@ -48,8 +48,8 @@ impl<'a> Topic<'a> { const REPO: ExistentialValueColumn = ExistentialValueColumn::new(b'r'); const ROOT_COMMIT: SingleValueColumn = SingleValueColumn::new(b'o'); - // Topic <-> Users who pinned it - pub const USERS: MultiValueColumn = MultiValueColumn::new(b'u'); + // Topic <-> Users who pinned it (with boolean: R or W) + pub const USERS: MultiMapColumn = MultiMapColumn::new(b'u'); // Topic <-> heads pub const HEADS: MultiValueColumn = MultiValueColumn::new(b'h'); @@ -142,18 +142,18 @@ impl<'a> Topic<'a> { Self::HEADS.get_all(self) } - pub fn add_user(&mut self, user: &UserId) -> Result<(), StorageError> { - Self::USERS.add(self, user) + pub fn add_user(&mut self, user: &UserId, publisher: bool) -> Result<(), StorageError> { + Self::USERS.add(self, user, &publisher) } - pub fn remove_user(&mut self, user: &UserId) -> Result<(), StorageError> { - Self::USERS.remove(self, user) + pub fn remove_user(&mut self, user: &UserId, publisher: bool) -> Result<(), StorageError> { + Self::USERS.remove(self, user, &publisher) } - pub fn has_user(&mut self, user: &UserId) -> Result<(), StorageError> { - Self::USERS.has(self, user) + pub fn has_user(&mut self, user: &UserId, publisher: bool) -> Result<(), StorageError> { + Self::USERS.has(self, user, &publisher) } - pub fn get_all_users(&mut self) -> Result, StorageError> { + pub fn get_all_users(&mut self) -> Result, StorageError> { Self::USERS.get_all(self) } } diff --git a/ng-repo/src/kcv_storage.rs b/ng-repo/src/kcv_storage.rs index b2f4548..7107b1a 100644 --- a/ng-repo/src/kcv_storage.rs +++ b/ng-repo/src/kcv_storage.rs @@ -125,6 +125,7 @@ pub struct MultiValueColumn< prefix: u8, phantom: PhantomData, model: PhantomData, + value_size: usize, } impl< @@ -137,45 +138,56 @@ impl< prefix, phantom: PhantomData, model: PhantomData, + value_size: to_vec(&Column::default()) + .expect("serialization of default Column value") + .len(), } } + + fn compute_key(model: &Model, column: &Column) -> Result, StorageError> { + let model_key = model.key(); + let mut column_ser = to_vec(column)?; + let mut key = Vec::with_capacity(model_key.len() + column_ser.len()); + key.append(&mut model_key.to_vec()); + key.append(&mut column_ser); + Ok(key) + } + pub fn add(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { model.check_exists()?; - model - .storage() - .put(self.prefix, model.key(), None, &to_vec(column)?, &None) + let key = Self::compute_key(model, column)?; + model.storage().put(self.prefix, &key, None, &vec![], &None) } pub fn remove(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { model.check_exists()?; - model - .storage() - .del_property_value(self.prefix, model.key(), None, &to_vec(column)?, &None) + let key = Self::compute_key(model, column)?; + model.storage().del(self.prefix, &key, None, &None) } pub fn has(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { model.check_exists()?; + let key = Self::compute_key(model, column)?; model .storage() - .has_property_value(self.prefix, model.key(), None, &to_vec(column)?, &None) + .has_property_value(self.prefix, &key, None, &vec![], &None) } pub fn get_all(&self, model: &mut Model) -> Result, StorageError> { model.check_exists()?; let key_prefix = model.key(); - let value_size = to_vec(&Column::default())?.len(); - + let key_prefix_len = key_prefix.len(); let mut res: HashSet = HashSet::new(); - let total_size = key_prefix.len() + value_size; - for user in model.storage().get_all_keys_and_values( + let total_size = key_prefix_len + self.value_size; + for val in model.storage().get_all_keys_and_values( self.prefix, total_size, key_prefix.to_vec(), None, &None, )? { - if user.0.len() == total_size + 1 { - let user: Column = from_slice(&user.0[1..user.0.len()])?; - res.insert(user); + if val.0.len() == total_size + 1 { + let val: Column = from_slice(&val.0[1 + key_prefix_len..total_size + 1])?; + res.insert(val); } } Ok(res) @@ -194,6 +206,129 @@ impl< } } +pub struct MultiMapColumn< + Model: IModel, + Column: Eq + PartialEq + Hash + Serialize + Default + for<'a> Deserialize<'a>, + Value: Serialize + for<'a> Deserialize<'a>, +> { + prefix: u8, + phantom_column: PhantomData, + phantom_model: PhantomData, + phantom_value: PhantomData, + value_size: usize, +} + +impl< + Model: IModel, + Column: Eq + PartialEq + Hash + Serialize + Default + for<'d> Deserialize<'d>, + Value: Serialize + for<'a> Deserialize<'a>, + > MultiMapColumn +{ + pub fn new(prefix: u8) -> Self { + MultiMapColumn { + prefix, + phantom_column: PhantomData, + phantom_model: PhantomData, + phantom_value: PhantomData, + value_size: to_vec(&Column::default()) + .expect("serialization of default Column value") + .len(), + } + } + pub fn add( + &self, + model: &mut Model, + column: &Column, + value: &Value, + ) -> Result<(), StorageError> { + model.check_exists()?; + let key = MultiValueColumn::compute_key(model, column)?; + model + .storage() + .put(self.prefix, &key, None, &to_vec(value)?, &None) + } + pub fn remove( + &self, + model: &mut Model, + column: &Column, + value: &Value, + ) -> Result<(), StorageError> { + model.check_exists()?; + let key = MultiValueColumn::compute_key(model, column)?; + model + .storage() + .del_property_value(self.prefix, &key, None, &to_vec(value)?, &None) + } + pub fn remove_regardless_value( + &self, + model: &mut Model, + column: &Column, + ) -> Result<(), StorageError> { + model.check_exists()?; + let key = MultiValueColumn::compute_key(model, column)?; + model.storage().del(self.prefix, &key, None, &None) + } + + pub fn has( + &self, + model: &mut Model, + column: &Column, + value: &Value, + ) -> Result<(), StorageError> { + model.check_exists()?; + let key = MultiValueColumn::compute_key(model, column)?; + model + .storage() + .has_property_value(self.prefix, &key, None, &to_vec(value)?, &None) + } + + pub fn has_regardless_value( + &self, + model: &mut Model, + column: &Column, + ) -> Result<(), StorageError> { + model.check_exists()?; + let key = MultiValueColumn::compute_key(model, column)?; + model.storage().get(self.prefix, &key, None, &None)?; + Ok(()) + } + + pub fn get_all(&self, model: &mut Model) -> Result, StorageError> { + model.check_exists()?; + let key_prefix = model.key(); + let key_prefix_len = key_prefix.len(); + let mut res: HashMap = HashMap::new(); + let total_size = key_prefix_len + self.value_size; + for val in model.storage().get_all_keys_and_values( + self.prefix, + total_size, + key_prefix.to_vec(), + None, + &None, + )? { + if val.0.len() == total_size + 1 { + let col: Column = from_slice(&val.0[1 + key_prefix_len..total_size + 1])?; + let val = from_slice(&val.1)?; + res.insert(col, val); + } + } + Ok(res) + } +} +impl< + Model: IModel, + Column: Eq + PartialEq + Hash + Serialize + Default + for<'d> Deserialize<'d>, + Value: Serialize + for<'a> Deserialize<'a>, + > IMultiValueColumn for MultiMapColumn +{ + fn value_size(&self) -> Result { + Ok(to_vec(&Column::default())?.len()) + } + fn prefix(&self) -> u8 { + self.prefix + } +} + pub trait ISingleValueColumn { fn suffix(&self) -> u8; } @@ -203,20 +338,6 @@ pub trait IMultiValueColumn { fn value_size(&self) -> Result; } -pub struct SingleValueColumn Deserialize<'a>> { - suffix: u8, - phantom: PhantomData, - model: PhantomData, -} - -impl Deserialize<'d>> ISingleValueColumn - for SingleValueColumn -{ - fn suffix(&self) -> u8 { - self.suffix - } -} - pub struct ExistentialValueColumn { suffix: u8, } @@ -233,43 +354,57 @@ impl ExistentialValueColumn { } } -impl Deserialize<'d>> SingleValueColumn { +pub struct SingleValueColumn Deserialize<'a>> { + suffix: u8, + phantom_value: PhantomData, + phantom_model: PhantomData, +} + +impl Deserialize<'d>> ISingleValueColumn + for SingleValueColumn +{ + fn suffix(&self) -> u8 { + self.suffix + } +} + +impl Deserialize<'d>> SingleValueColumn { pub fn new(suffix: u8) -> Self { SingleValueColumn { suffix, - phantom: PhantomData, - model: PhantomData, + phantom_value: PhantomData, + phantom_model: PhantomData, } } - pub fn set(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { + pub fn set(&self, model: &mut Model, value: &Value) -> Result<(), StorageError> { model.check_exists()?; model.storage().replace( model.prefix(), model.key(), Some(self.suffix), - &to_vec(column)?, + &to_vec(value)?, &None, ) } - pub fn get(&self, model: &mut Model) -> Result { + pub fn get(&self, model: &mut Model) -> Result { model.check_exists()?; match model .storage() .get(model.prefix(), model.key(), Some(self.suffix), &None) { - Ok(res) => Ok(from_slice::(&res)?), + Ok(res) => Ok(from_slice::(&res)?), Err(e) => Err(e), } } - pub fn has(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { + pub fn has(&self, model: &mut Model, value: &Value) -> Result<(), StorageError> { model.check_exists()?; model.storage().has_property_value( model.prefix(), model.key(), Some(self.suffix), - &to_vec(column)?, + &to_vec(value)?, &None, ) } diff --git a/ng-verifier/src/user_storage/branch.rs b/ng-verifier/src/user_storage/branch.rs index 0396912..77f6a11 100644 --- a/ng-verifier/src/user_storage/branch.rs +++ b/ng-verifier/src/user_storage/branch.rs @@ -154,8 +154,9 @@ impl<'a> BranchStorage<'a> { ) -> Result, StorageError> { let size = to_vec(&ObjectRef::nil())?.len(); let key_prefix = to_vec(id).unwrap(); + let key_prefix_len = key_prefix.len(); let mut res: Vec = vec![]; - let total_size = key_prefix.len() + size; + let total_size = key_prefix_len + size; for head in storage.get_all_keys_and_values( Self::PREFIX_HEADS, total_size, @@ -164,7 +165,7 @@ impl<'a> BranchStorage<'a> { &None, )? { if head.0.len() == total_size + 1 { - let head: ObjectRef = from_slice(&head.0[1..head.0.len()])?; + let head: ObjectRef = from_slice(&head.0[1 + key_prefix_len..total_size + 1])?; res.push(head); } }