save_many code
This commit is contained in:
1 parent
d99fd337da
commit
3eba0c93d4
1 file changed
+102
-28
+102
-28
@@ -1,15 +1,16 @@
|
|||||||
use crate::data::Id;
|
use crate::data::Id;
|
||||||
use crate::data::entities::{EntityData, EntityHandle, WordData};
|
use crate::data::entities::{EntityData, EntityHandle};
|
||||||
use crate::notification::MaybeError;
|
use crate::notification::MaybeError;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use iced::application::IntoBoot;
|
|
||||||
use rusqlite::fallible_iterator::Iterator;
|
|
||||||
|
|
||||||
pub trait Repository<T, D> where D : DbLayer<T> {
|
pub trait Repository<T, D>
|
||||||
|
where
|
||||||
|
D: DbLayer<T>,
|
||||||
|
{
|
||||||
fn get(&self, handle: &mut EntityHandle<T>) -> Option<T>;
|
fn get(&self, handle: &mut EntityHandle<T>) -> Option<T>;
|
||||||
fn get_ref(&self, handle: &mut EntityHandle<T>) -> Option<&T>;
|
fn get_ref(&self, handle: &mut EntityHandle<T>) -> Option<&T>;
|
||||||
fn get_mut(&mut self, handle: &mut EntityHandle<T>) -> Option<&mut T>;
|
fn get_mut(&mut self, handle: &mut EntityHandle<T>) -> Option<&mut T>;
|
||||||
@@ -21,11 +22,13 @@ pub trait Repository<T, D> where D : DbLayer<T> {
|
|||||||
fn reload(&mut self) -> MaybeError;
|
fn reload(&mut self) -> MaybeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BatchedRepository<T, D> where D : BatchedDbLayer<T>, T: EntityData
|
pub trait BatchedRepository<T, D>
|
||||||
|
where
|
||||||
|
D: BatchedDbLayer<T>,
|
||||||
|
T: EntityData,
|
||||||
{
|
{
|
||||||
fn save_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError;
|
fn save_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError;
|
||||||
fn delete_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError;
|
fn delete_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DbLayer<T> {
|
pub trait DbLayer<T> {
|
||||||
@@ -35,12 +38,14 @@ pub trait DbLayer<T> {
|
|||||||
fn load_all(&self, storage: &mut Vec<T>, connection: &Connection) -> MaybeError;
|
fn load_all(&self, storage: &mut Vec<T>, connection: &Connection) -> MaybeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BatchedDbLayer<T> where T : EntityData{
|
pub trait BatchedDbLayer<T>
|
||||||
|
where
|
||||||
|
T: EntityData,
|
||||||
|
{
|
||||||
fn delete_many(&mut self, ids: &[Id], connection: &Connection) -> MaybeError;
|
fn delete_many(&mut self, ids: &[Id], connection: &Connection) -> MaybeError;
|
||||||
fn add_many_entity(&mut self, entity: &mut [T], connection: &Connection) -> MaybeError;
|
fn add_many_entity(&mut self, entity: &mut [T], connection: &Connection) -> MaybeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DataRepository<T, D> {
|
pub struct DataRepository<T, D> {
|
||||||
inner: Arc<RwLock<DataRepositoryInner<T, D>>>,
|
inner: Arc<RwLock<DataRepositoryInner<T, D>>>,
|
||||||
@@ -94,7 +99,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_by_id(&self, id: Id) -> EntityHandle<T> {
|
fn handle_by_id(&self, id: Id) -> EntityHandle<T> {
|
||||||
EntityHandle{
|
EntityHandle {
|
||||||
_phantom: Default::default(),
|
_phantom: Default::default(),
|
||||||
id,
|
id,
|
||||||
real: true,
|
real: true,
|
||||||
@@ -149,11 +154,13 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError {
|
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError {
|
||||||
if entity.real {
|
if entity.real {
|
||||||
let data = self.get_ref(entity).unwrap();
|
let data = self.get_ref(entity).unwrap();
|
||||||
self.data_layer.write_entity(data, &self.connection.lock())?;
|
self.data_layer
|
||||||
|
.write_entity(data, &self.connection.lock())?;
|
||||||
} else {
|
} else {
|
||||||
let index = fast_position_of(self.temporal.as_slice(), entity).unwrap();
|
let index = fast_position_of(self.temporal.as_slice(), entity).unwrap();
|
||||||
let mut value = self.temporal.remove(index);
|
let mut value = self.temporal.remove(index);
|
||||||
self.data_layer.add_entity(&mut value, &self.connection.lock())?;
|
self.data_layer
|
||||||
|
.add_entity(&mut value, &self.connection.lock())?;
|
||||||
entity.real = true;
|
entity.real = true;
|
||||||
entity.id = value.id();
|
entity.id = value.id();
|
||||||
entity.index = self.cache.len() as u32;
|
entity.index = self.cache.len() as u32;
|
||||||
@@ -164,9 +171,9 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn delete(&mut self, mut handle: EntityHandle<T>) -> MaybeError {
|
fn delete(&mut self, mut handle: EntityHandle<T>) -> MaybeError {
|
||||||
|
|
||||||
let vec = if handle.real {
|
let vec = if handle.real {
|
||||||
self.data_layer.delete_entity(handle.id, &self.connection.lock())?;
|
self.data_layer
|
||||||
|
.delete_entity(handle.id, &self.connection.lock())?;
|
||||||
&mut self.cache
|
&mut self.cache
|
||||||
} else {
|
} else {
|
||||||
&mut self.temporal
|
&mut self.temporal
|
||||||
@@ -178,7 +185,8 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self) -> MaybeError {
|
fn init(&mut self) -> MaybeError {
|
||||||
self.data_layer.load_all(&mut self.cache, &self.connection.lock())?;
|
self.data_layer
|
||||||
|
.load_all(&mut self.cache, &self.connection.lock())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,36 +197,85 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: EntityData + Clone, D: BatchedDbLayer<T>> BatchedRepository<T, D> for DataRepositoryInner<T, D> {
|
impl<T: EntityData + Clone, D: BatchedDbLayer<T> + DbLayer<T>> BatchedRepository<T, D>
|
||||||
|
for DataRepositoryInner<T, D>
|
||||||
|
{
|
||||||
fn save_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError {
|
fn save_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError {
|
||||||
|
let mut temp = Vec::with_capacity(handles.len() / 2);
|
||||||
|
let mut cached = Vec::with_capacity(handles.len() / 2);
|
||||||
|
handles.sort_by_key(|a| a.id);
|
||||||
|
handles.iter_mut().for_each(|handle| {
|
||||||
|
if handle.real {
|
||||||
|
cached.push(handle)
|
||||||
|
} else {
|
||||||
|
temp.push(handle)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut values = Vec::with_capacity(temp.len());
|
||||||
|
let mut cell = 0;
|
||||||
|
let len = temp.len();
|
||||||
|
self.temporal.retain(|x| {
|
||||||
|
if cell == len {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let find = temp[cell].id;
|
||||||
|
let remove = x.id() == find;
|
||||||
|
if remove || find > x.id() {
|
||||||
|
cell += 1;
|
||||||
|
values.push(x.clone());
|
||||||
|
}
|
||||||
|
!remove
|
||||||
|
});
|
||||||
|
|
||||||
|
self.data_layer
|
||||||
|
.add_many_entity(&mut values, &self.connection.lock())?;
|
||||||
|
let mut index = self.cache.len();
|
||||||
|
values
|
||||||
|
.iter()
|
||||||
|
.zip(temp)
|
||||||
|
.for_each(|(x, y)| {
|
||||||
|
y.id = x.id();
|
||||||
|
y.index = index as u32;
|
||||||
|
index += 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
for in_cache in cached {
|
||||||
|
let value = self.get_ref(in_cache).unwrap();
|
||||||
|
self.data_layer.write_entity(value, &self.connection.lock())?;
|
||||||
|
}
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError {
|
fn delete_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError {
|
||||||
let mut temp = Vec::with_capacity(handles.len() / 2);
|
let (cached, temp) = split_temp_real(handles, |e| e.id);
|
||||||
let mut cached = Vec::with_capacity(handles.len() / 2);
|
|
||||||
let mut cell = 0;
|
|
||||||
handles.sort_by(|a, b| {a.id.cmp(&b.id)});
|
|
||||||
handles.iter().for_each(|handle| if handle.real { cached.push(handle.id)} else {
|
|
||||||
temp.push(handle.id)
|
|
||||||
});
|
|
||||||
|
|
||||||
|
let mut cell = 0;
|
||||||
let len = temp.len();
|
let len = temp.len();
|
||||||
self.temporal.retain(|x| {
|
self.temporal.retain(|x| {
|
||||||
if cell == len { return true; }
|
if cell == len {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let find = temp[cell];
|
let find = temp[cell];
|
||||||
let remove = x.id() == find;
|
let remove = x.id() == find;
|
||||||
if remove { cell += 1; }
|
if remove || find > x.id() {
|
||||||
|
cell += 1;
|
||||||
|
}
|
||||||
!remove
|
!remove
|
||||||
});
|
});
|
||||||
self.data_layer.delete_many(cached.as_slice(), &self.connection.lock())?;
|
self.data_layer
|
||||||
|
.delete_many(cached.as_slice(), &self.connection.lock())?;
|
||||||
let len = cached.len();
|
let len = cached.len();
|
||||||
cell = 0;
|
cell = 0;
|
||||||
self.cache.retain(|x| {
|
self.cache.retain(|x| {
|
||||||
if cell == len { return true; }
|
if cell == len {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let find = cached[cell];
|
let find = cached[cell];
|
||||||
let remove = x.id() == find;
|
let remove = x.id() == find;
|
||||||
if remove { cell += 1; }
|
if remove || find > x.id() {
|
||||||
|
cell += 1;
|
||||||
|
}
|
||||||
!remove
|
!remove
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -226,6 +283,23 @@ impl<T: EntityData + Clone, D: BatchedDbLayer<T>> BatchedRepository<T, D> for Da
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_temp_real<T, F, V>(handles: &mut [EntityHandle<T>], getter: F) -> (Vec<V>, Vec<V>)
|
||||||
|
where
|
||||||
|
F: Fn(&EntityHandle<T>) -> V,
|
||||||
|
{
|
||||||
|
let mut temp = Vec::with_capacity(handles.len() / 2);
|
||||||
|
let mut cached = Vec::with_capacity(handles.len() / 2);
|
||||||
|
handles.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
|
handles.iter().for_each(|handle| {
|
||||||
|
if handle.real {
|
||||||
|
cached.push(getter(handle))
|
||||||
|
} else {
|
||||||
|
temp.push(getter(handle))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(cached, temp)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fast_position_of<E: EntityData>(
|
pub fn fast_position_of<E: EntityData>(
|
||||||
storage: &[E],
|
storage: &[E],
|
||||||
handle: &mut EntityHandle<E>,
|
handle: &mut EntityHandle<E>,
|
||||||
|
|||||||
Reference in new issue
Block a user