fix KCV store, adds MultiMapColumn

pull/19/head
Niko PLP 7 months ago
parent 19c627e1b9
commit 29d83e616f
  1. 18
      ng-broker/src/server_storage/core/topic.rs
  2. 207
      ng-repo/src/kcv_storage.rs
  3. 5
      ng-verifier/src/user_storage/branch.rs

@ -48,8 +48,8 @@ impl<'a> Topic<'a> {
const REPO: ExistentialValueColumn = ExistentialValueColumn::new(b'r'); const REPO: ExistentialValueColumn = ExistentialValueColumn::new(b'r');
const ROOT_COMMIT: SingleValueColumn<Self, ObjectId> = SingleValueColumn::new(b'o'); const ROOT_COMMIT: SingleValueColumn<Self, ObjectId> = SingleValueColumn::new(b'o');
// Topic <-> Users who pinned it // Topic <-> Users who pinned it (with boolean: R or W)
pub const USERS: MultiValueColumn<Self, UserId> = MultiValueColumn::new(b'u'); pub const USERS: MultiMapColumn<Self, UserId, bool> = MultiMapColumn::new(b'u');
// Topic <-> heads // Topic <-> heads
pub const HEADS: MultiValueColumn<Self, ObjectId> = MultiValueColumn::new(b'h'); pub const HEADS: MultiValueColumn<Self, ObjectId> = MultiValueColumn::new(b'h');
@ -142,18 +142,18 @@ impl<'a> Topic<'a> {
Self::HEADS.get_all(self) Self::HEADS.get_all(self)
} }
pub fn add_user(&mut self, user: &UserId) -> Result<(), StorageError> { pub fn add_user(&mut self, user: &UserId, publisher: bool) -> Result<(), StorageError> {
Self::USERS.add(self, user) Self::USERS.add(self, user, &publisher)
} }
pub fn remove_user(&mut self, user: &UserId) -> Result<(), StorageError> { pub fn remove_user(&mut self, user: &UserId, publisher: bool) -> Result<(), StorageError> {
Self::USERS.remove(self, user) Self::USERS.remove(self, user, &publisher)
} }
pub fn has_user(&mut self, user: &UserId) -> Result<(), StorageError> { pub fn has_user(&mut self, user: &UserId, publisher: bool) -> Result<(), StorageError> {
Self::USERS.has(self, user) Self::USERS.has(self, user, &publisher)
} }
pub fn get_all_users(&mut self) -> Result<HashSet<UserId>, StorageError> { pub fn get_all_users(&mut self) -> Result<HashMap<UserId, bool>, StorageError> {
Self::USERS.get_all(self) Self::USERS.get_all(self)
} }
} }

@ -125,6 +125,7 @@ pub struct MultiValueColumn<
prefix: u8, prefix: u8,
phantom: PhantomData<Column>, phantom: PhantomData<Column>,
model: PhantomData<Model>, model: PhantomData<Model>,
value_size: usize,
} }
impl< impl<
@ -137,45 +138,56 @@ impl<
prefix, prefix,
phantom: PhantomData, phantom: PhantomData,
model: PhantomData, model: PhantomData,
value_size: to_vec(&Column::default())
.expect("serialization of default Column value")
.len(),
} }
} }
fn compute_key(model: &Model, column: &Column) -> Result<Vec<u8>, 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> { pub fn add(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> {
model.check_exists()?; model.check_exists()?;
model let key = Self::compute_key(model, column)?;
.storage() model.storage().put(self.prefix, &key, None, &vec![], &None)
.put(self.prefix, model.key(), None, &to_vec(column)?, &None)
} }
pub fn remove(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { pub fn remove(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> {
model.check_exists()?; model.check_exists()?;
model let key = Self::compute_key(model, column)?;
.storage() model.storage().del(self.prefix, &key, None, &None)
.del_property_value(self.prefix, model.key(), None, &to_vec(column)?, &None)
} }
pub fn has(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> { pub fn has(&self, model: &mut Model, column: &Column) -> Result<(), StorageError> {
model.check_exists()?; model.check_exists()?;
let key = Self::compute_key(model, column)?;
model model
.storage() .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<HashSet<Column>, StorageError> { pub fn get_all(&self, model: &mut Model) -> Result<HashSet<Column>, StorageError> {
model.check_exists()?; model.check_exists()?;
let key_prefix = model.key(); let key_prefix = model.key();
let value_size = to_vec(&Column::default())?.len(); let key_prefix_len = key_prefix.len();
let mut res: HashSet<Column> = HashSet::new(); let mut res: HashSet<Column> = HashSet::new();
let total_size = key_prefix.len() + value_size; let total_size = key_prefix_len + self.value_size;
for user in model.storage().get_all_keys_and_values( for val in model.storage().get_all_keys_and_values(
self.prefix, self.prefix,
total_size, total_size,
key_prefix.to_vec(), key_prefix.to_vec(),
None, None,
&None, &None,
)? { )? {
if user.0.len() == total_size + 1 { if val.0.len() == total_size + 1 {
let user: Column = from_slice(&user.0[1..user.0.len()])?; let val: Column = from_slice(&val.0[1 + key_prefix_len..total_size + 1])?;
res.insert(user); res.insert(val);
} }
} }
Ok(res) Ok(res)
@ -194,27 +206,136 @@ impl<
} }
} }
pub trait ISingleValueColumn { pub struct MultiMapColumn<
fn suffix(&self) -> u8; Model: IModel,
Column: Eq + PartialEq + Hash + Serialize + Default + for<'a> Deserialize<'a>,
Value: Serialize + for<'a> Deserialize<'a>,
> {
prefix: u8,
phantom_column: PhantomData<Column>,
phantom_model: PhantomData<Model>,
phantom_value: PhantomData<Value>,
value_size: usize,
} }
pub trait IMultiValueColumn { impl<
fn prefix(&self) -> u8; Model: IModel,
fn value_size(&self) -> Result<usize, StorageError>; Column: Eq + PartialEq + Hash + Serialize + Default + for<'d> Deserialize<'d>,
Value: Serialize + for<'a> Deserialize<'a>,
> MultiMapColumn<Model, Column, Value>
{
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 struct SingleValueColumn<Model: IModel, Column: Serialize + for<'a> Deserialize<'a>> { pub fn has(
suffix: u8, &self,
phantom: PhantomData<Column>, model: &mut Model,
model: PhantomData<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)
} }
impl<Model: IModel, Column: Serialize + for<'d> Deserialize<'d>> ISingleValueColumn pub fn has_regardless_value(
for SingleValueColumn<Model, Column> &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<HashMap<Column, Value>, StorageError> {
model.check_exists()?;
let key_prefix = model.key();
let key_prefix_len = key_prefix.len();
let mut res: HashMap<Column, Value> = 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<Model, Column, Value>
{ {
fn suffix(&self) -> u8 { fn value_size(&self) -> Result<usize, StorageError> {
self.suffix Ok(to_vec(&Column::default())?.len())
} }
fn prefix(&self) -> u8 {
self.prefix
}
}
pub trait ISingleValueColumn {
fn suffix(&self) -> u8;
}
pub trait IMultiValueColumn {
fn prefix(&self) -> u8;
fn value_size(&self) -> Result<usize, StorageError>;
} }
pub struct ExistentialValueColumn { pub struct ExistentialValueColumn {
@ -233,43 +354,57 @@ impl ExistentialValueColumn {
} }
} }
impl<Model: IModel, Column: Serialize + for<'d> Deserialize<'d>> SingleValueColumn<Model, Column> { pub struct SingleValueColumn<Model: IModel, Value: Serialize + for<'a> Deserialize<'a>> {
suffix: u8,
phantom_value: PhantomData<Value>,
phantom_model: PhantomData<Model>,
}
impl<Model: IModel, Value: Serialize + for<'d> Deserialize<'d>> ISingleValueColumn
for SingleValueColumn<Model, Value>
{
fn suffix(&self) -> u8 {
self.suffix
}
}
impl<Model: IModel, Value: Serialize + for<'d> Deserialize<'d>> SingleValueColumn<Model, Value> {
pub fn new(suffix: u8) -> Self { pub fn new(suffix: u8) -> Self {
SingleValueColumn { SingleValueColumn {
suffix, suffix,
phantom: PhantomData, phantom_value: PhantomData,
model: 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.check_exists()?;
model.storage().replace( model.storage().replace(
model.prefix(), model.prefix(),
model.key(), model.key(),
Some(self.suffix), Some(self.suffix),
&to_vec(column)?, &to_vec(value)?,
&None, &None,
) )
} }
pub fn get(&self, model: &mut Model) -> Result<Column, StorageError> { pub fn get(&self, model: &mut Model) -> Result<Value, StorageError> {
model.check_exists()?; model.check_exists()?;
match model match model
.storage() .storage()
.get(model.prefix(), model.key(), Some(self.suffix), &None) .get(model.prefix(), model.key(), Some(self.suffix), &None)
{ {
Ok(res) => Ok(from_slice::<Column>(&res)?), Ok(res) => Ok(from_slice::<Value>(&res)?),
Err(e) => Err(e), 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.check_exists()?;
model.storage().has_property_value( model.storage().has_property_value(
model.prefix(), model.prefix(),
model.key(), model.key(),
Some(self.suffix), Some(self.suffix),
&to_vec(column)?, &to_vec(value)?,
&None, &None,
) )
} }

@ -154,8 +154,9 @@ impl<'a> BranchStorage<'a> {
) -> Result<Vec<ObjectRef>, StorageError> { ) -> Result<Vec<ObjectRef>, StorageError> {
let size = to_vec(&ObjectRef::nil())?.len(); let size = to_vec(&ObjectRef::nil())?.len();
let key_prefix = to_vec(id).unwrap(); let key_prefix = to_vec(id).unwrap();
let key_prefix_len = key_prefix.len();
let mut res: Vec<ObjectRef> = vec![]; let mut res: Vec<ObjectRef> = vec![];
let total_size = key_prefix.len() + size; let total_size = key_prefix_len + size;
for head in storage.get_all_keys_and_values( for head in storage.get_all_keys_and_values(
Self::PREFIX_HEADS, Self::PREFIX_HEADS,
total_size, total_size,
@ -164,7 +165,7 @@ impl<'a> BranchStorage<'a> {
&None, &None,
)? { )? {
if head.0.len() == total_size + 1 { 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); res.push(head);
} }
} }

Loading…
Cancel
Save