partialy implement Glue Logic
This commit is contained in:
		@ -40,6 +40,10 @@ pub enum ProtocolError {
 | 
			
		||||
 | 
			
		||||
impl From<io::Error> for ProtocolError {
 | 
			
		||||
    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)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ mod image_convert;
 | 
			
		||||
mod metadata_file;
 | 
			
		||||
mod search;
 | 
			
		||||
 | 
			
		||||
pub type TextureFileResult = Result<Arc<Vec<u8>>, TextureFileError>;
 | 
			
		||||
pub type TextureFileResult = Result<Vec<u8>, TextureFileError>;
 | 
			
		||||
pub enum TextureFileError {
 | 
			
		||||
    NotFound,
 | 
			
		||||
    IoError(io::Error),
 | 
			
		||||
@ -39,7 +39,7 @@ pub struct DataStore {
 | 
			
		||||
    id_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 {
 | 
			
		||||
@ -75,7 +75,7 @@ impl DataStore {
 | 
			
		||||
        let metadata_file = metadata_file::MetadataFile::load(base_dir)?;
 | 
			
		||||
 | 
			
		||||
        for texture in metadata_file.textures.iter() {
 | 
			
		||||
            match store.insert(texture.clone())? {
 | 
			
		||||
            match store.insert(texture.clone()) {
 | 
			
		||||
                true => (),
 | 
			
		||||
                false => {
 | 
			
		||||
                    panic!("inserting {:#?} failed !!!", texture); // TODO: What should be done?
 | 
			
		||||
@ -94,17 +94,17 @@ impl DataStore {
 | 
			
		||||
        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) {
 | 
			
		||||
            return Ok(false);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if self.name_index.contains_key(&texture.name) {
 | 
			
		||||
            return Ok(false);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if !self.is_texture_file_on_disk(&texture.texture_hash)? {
 | 
			
		||||
            return Ok(false);
 | 
			
		||||
        if !self.is_texture_file_on_disk(&texture.texture_hash) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.id_index.insert(texture.id.clone(), texture.clone());
 | 
			
		||||
@ -112,7 +112,7 @@ impl DataStore {
 | 
			
		||||
            .insert(texture.name.clone(), texture.clone());
 | 
			
		||||
        self.textures.insert(texture.clone());
 | 
			
		||||
 | 
			
		||||
        Ok(true)
 | 
			
		||||
        true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// returns true if successful
 | 
			
		||||
@ -132,28 +132,23 @@ impl DataStore {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// 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);
 | 
			
		||||
 | 
			
		||||
        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(&mut self, hash: &Sha256) -> TextureFileResult {
 | 
			
		||||
    pub fn read_texture_file_by_hash(&self, hash: &Sha256) -> io::Result<Vec<u8>> {
 | 
			
		||||
        use std::fs::*;
 | 
			
		||||
        use std::io::*;
 | 
			
		||||
 | 
			
		||||
        if !(self.is_texture_file_on_disk(&hash)?) {
 | 
			
		||||
            return Err(TextureFileError::NotFound);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let file_path = self.texture_file_path(&hash);
 | 
			
		||||
 | 
			
		||||
        let mut file = File::open(file_path)?;
 | 
			
		||||
        let mut buffer = Vec::new();
 | 
			
		||||
        file.read_to_end(&mut buffer)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Arc::new(buffer))
 | 
			
		||||
        Ok(buffer)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn store_texture_file(&mut self, data: &[u8]) -> io::Result<()> {
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,23 @@
 | 
			
		||||
#![allow(dead_code)]
 | 
			
		||||
 | 
			
		||||
use crate::model::*;
 | 
			
		||||
use crate::persistency::*;
 | 
			
		||||
use crate::protocol::*;
 | 
			
		||||
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use std::sync::*;
 | 
			
		||||
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
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 {
 | 
			
		||||
@ -19,15 +29,21 @@ impl ProtocolHandler for ServerState {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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>> {
 | 
			
		||||
        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>> {
 | 
			
		||||
        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(
 | 
			
		||||
@ -35,7 +51,18 @@ impl ProtocolHandler for ServerState {
 | 
			
		||||
        hash: Sha256,
 | 
			
		||||
        format: TextureFormat,
 | 
			
		||||
    ) -> 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(
 | 
			
		||||
@ -44,7 +71,63 @@ impl ProtocolHandler for ServerState {
 | 
			
		||||
        insert: Option<Texture>,
 | 
			
		||||
        insert_texture_data: Option<Vec<u8>>,
 | 
			
		||||
    ) -> ProtocolResult<ReplaceTextureStatus> {
 | 
			
		||||
        // NOTE: must also check if insert_texture_data fits sha256!
 | 
			
		||||
        unimplemented!()
 | 
			
		||||
        let mut data_store = self.data_store.write().unwrap();
 | 
			
		||||
 | 
			
		||||
        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),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user