partialy implement Glue Logic

This commit is contained in:
CodeSteak 2019-05-05 20:28:35 +02:00
parent 5369304516
commit 28085f9b87
3 changed files with 109 additions and 27 deletions

View File

@ -40,6 +40,10 @@ pub enum ProtocolError {
impl From<io::Error> for ProtocolError { impl From<io::Error> for ProtocolError {
fn from(err: io::Error) -> Self { fn from(err: io::Error) -> Self {
ProtocolError::InternalServerError(err) if err.kind() == io::ErrorKind::NotFound {
ProtocolError::FileNotFound("File Not Found!".to_string())
} else {
ProtocolError::InternalServerError(err)
}
} }
} }

View File

@ -11,7 +11,7 @@ mod image_convert;
mod metadata_file; mod metadata_file;
mod search; mod search;
pub type TextureFileResult = Result<Arc<Vec<u8>>, TextureFileError>; pub type TextureFileResult = Result<Vec<u8>, TextureFileError>;
pub enum TextureFileError { pub enum TextureFileError {
NotFound, NotFound,
IoError(io::Error), IoError(io::Error),
@ -39,7 +39,7 @@ pub struct DataStore {
id_index: HashMap<String, Texture>, id_index: HashMap<String, Texture>,
name_index: HashMap<String, Texture>, name_index: HashMap<String, Texture>,
preview_cache: HashMap<(TextureFormat, Sha256), Arc<Vec<u8>>>, preview_cache: HashMap<(TextureFormat, Sha256), Vec<u8>>,
} }
impl DataStore { impl DataStore {
@ -75,7 +75,7 @@ impl DataStore {
let metadata_file = metadata_file::MetadataFile::load(base_dir)?; let metadata_file = metadata_file::MetadataFile::load(base_dir)?;
for texture in metadata_file.textures.iter() { for texture in metadata_file.textures.iter() {
match store.insert(texture.clone())? { match store.insert(texture.clone()) {
true => (), true => (),
false => { false => {
panic!("inserting {:#?} failed !!!", texture); // TODO: What should be done? panic!("inserting {:#?} failed !!!", texture); // TODO: What should be done?
@ -94,17 +94,17 @@ impl DataStore {
self.name_index.get(id).cloned() self.name_index.get(id).cloned()
} }
pub fn insert(&mut self, texture: Texture) -> io::Result<bool> { pub fn insert(&mut self, texture: Texture) -> bool {
if self.id_index.contains_key(&texture.id) { if self.id_index.contains_key(&texture.id) {
return Ok(false); return false;
} }
if self.name_index.contains_key(&texture.name) { if self.name_index.contains_key(&texture.name) {
return Ok(false); return false;
} }
if !self.is_texture_file_on_disk(&texture.texture_hash)? { if !self.is_texture_file_on_disk(&texture.texture_hash) {
return Ok(false); return false;
} }
self.id_index.insert(texture.id.clone(), texture.clone()); self.id_index.insert(texture.id.clone(), texture.clone());
@ -112,7 +112,7 @@ impl DataStore {
.insert(texture.name.clone(), texture.clone()); .insert(texture.name.clone(), texture.clone());
self.textures.insert(texture.clone()); self.textures.insert(texture.clone());
Ok(true) true
} }
/// returns true if successful /// returns true if successful
@ -132,28 +132,23 @@ impl DataStore {
} }
/// Check if the texture, given by hash, physically exists on the file system. /// Check if the texture, given by hash, physically exists on the file system.
pub fn is_texture_file_on_disk(&self, hash: &Sha256) -> io::Result<bool> { pub fn is_texture_file_on_disk(&self, hash: &Sha256) -> bool {
let file_path = self.texture_file_path(&hash); let file_path = self.texture_file_path(&hash);
Ok(file_path.is_file()) file_path.is_file()
} }
// Todo: this return type looks wrong : ImageError can't happen pub fn read_texture_file_by_hash(&self, hash: &Sha256) -> io::Result<Vec<u8>> {
pub fn read_texture_file_by_hash(&mut self, hash: &Sha256) -> TextureFileResult {
use std::fs::*; use std::fs::*;
use std::io::*; use std::io::*;
if !(self.is_texture_file_on_disk(&hash)?) {
return Err(TextureFileError::NotFound);
}
let file_path = self.texture_file_path(&hash); let file_path = self.texture_file_path(&hash);
let mut file = File::open(file_path)?; let mut file = File::open(file_path)?;
let mut buffer = Vec::new(); let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?; file.read_to_end(&mut buffer)?;
Ok(Arc::new(buffer)) Ok(buffer)
} }
pub fn store_texture_file(&mut self, data: &[u8]) -> io::Result<()> { pub fn store_texture_file(&mut self, data: &[u8]) -> io::Result<()> {

View File

@ -4,13 +4,23 @@
#![allow(dead_code)] #![allow(dead_code)]
use crate::model::*; use crate::model::*;
use crate::persistency::*;
use crate::protocol::*; use crate::protocol::*;
use std::sync::Arc; use std::path::Path;
use std::sync::*;
#[derive(Clone)] #[derive(Clone)]
pub struct ServerState { pub struct ServerState {
// ... data_store: Arc<RwLock<DataStore>>,
}
impl ServerState {
pub fn new(storage_path: &Path) -> std::io::Result<Self> {
Ok(Self {
data_store: Arc::new(RwLock::new(DataStore::new(&storage_path)?)),
})
}
} }
impl ProtocolHandler for ServerState { impl ProtocolHandler for ServerState {
@ -19,15 +29,21 @@ impl ProtocolHandler for ServerState {
} }
fn get_texture_by_id(&mut self, id: &str) -> ProtocolResult<Option<Texture>> { fn get_texture_by_id(&mut self, id: &str) -> ProtocolResult<Option<Texture>> {
unimplemented!() let data_store = self.data_store.read().unwrap();
Ok(data_store.texture_by_id(id))
} }
fn get_texture_by_name(&mut self, name: &str) -> ProtocolResult<Option<Texture>> { fn get_texture_by_name(&mut self, name: &str) -> ProtocolResult<Option<Texture>> {
unimplemented!() let data_store = self.data_store.read().unwrap();
Ok(data_store.texture_by_name(name))
} }
fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult<Vec<u8>> { fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult<Vec<u8>> {
unimplemented!() let data_store = self.data_store.read().unwrap();
let data = data_store.read_texture_file_by_hash(&hash)?;
Ok(data)
} }
fn get_texture_preview( fn get_texture_preview(
@ -35,7 +51,18 @@ impl ProtocolHandler for ServerState {
hash: Sha256, hash: Sha256,
format: TextureFormat, format: TextureFormat,
) -> ProtocolResult<Vec<u8>> { ) -> ProtocolResult<Vec<u8>> {
unimplemented!() let mut data_store = self.data_store.write().unwrap();
match data_store.get_texture_preview(&hash, format) {
Ok(data) => Ok(data),
Err(TextureFileError::NotFound) => Err(ProtocolError::FileNotFound(
"Texture not found!".to_string(),
)),
Err(TextureFileError::ImageError(_)) => Err(ProtocolError::FileNotFound(
"Didn't Find valid Texture File".to_string(),
)),
Err(TextureFileError::IoError(err)) => Err(ProtocolError::InternalServerError(err)),
}
} }
fn replace_texture( fn replace_texture(
@ -44,7 +71,63 @@ impl ProtocolHandler for ServerState {
insert: Option<Texture>, insert: Option<Texture>,
insert_texture_data: Option<Vec<u8>>, insert_texture_data: Option<Vec<u8>>,
) -> ProtocolResult<ReplaceTextureStatus> { ) -> ProtocolResult<ReplaceTextureStatus> {
// NOTE: must also check if insert_texture_data fits sha256! let mut data_store = self.data_store.write().unwrap();
unimplemented!()
match insert_texture_data {
Some(data) => {
data_store.store_texture_file(&data)?;
}
None => (),
}
match (delete, insert) {
(Some(delete), Some(insert)) => {
if !data_store.is_texture_file_on_disk(&insert.texture_hash) {
return Ok(ReplaceTextureStatus::NeedTextureData(insert.texture_hash));
}
if !data_store.delete(&delete) {
return Err(ProtocolError::Conflict(
"Delete Texture was modified!".to_string(),
));
}
if !data_store.insert(insert) {
// undo delete
// panics if texture file is delete during delete and reinsert.
// unlikely to happen.
assert!(data_store.insert(delete));
return Err(ProtocolError::Conflict(
"Name or Id already taken.".to_string(),
));
}
Ok(ReplaceTextureStatus::Ok)
}
(Some(delete), None) => {
if !data_store.delete(&delete) {
return Err(ProtocolError::Conflict(
"Delete Texture was modified!".to_string(),
));
}
Ok(ReplaceTextureStatus::Ok)
}
(None, Some(insert)) => {
if !data_store.is_texture_file_on_disk(&insert.texture_hash) {
return Ok(ReplaceTextureStatus::NeedTextureData(insert.texture_hash));
}
if !data_store.insert(insert) {
// undo delete
return Err(ProtocolError::Conflict(
"Name or Id already taken.".to_string(),
));
}
Ok(ReplaceTextureStatus::Ok)
}
(None, None) => Ok(ReplaceTextureStatus::Ok),
}
} }
} }