2019-04-20 01:24:19 +02:00
use crate ::model ::* ;
2019-05-05 20:28:35 +02:00
use crate ::persistency ::* ;
2019-04-20 01:24:19 +02:00
use crate ::protocol ::* ;
2019-05-07 22:43:14 +02:00
use crate ::search ::* ;
2019-04-20 01:24:19 +02:00
2019-05-05 20:28:35 +02:00
use std ::path ::Path ;
use std ::sync ::* ;
2019-04-20 01:24:19 +02:00
2019-04-24 17:01:43 +02:00
#[ derive(Clone) ]
2019-04-20 01:24:19 +02:00
pub struct ServerState {
2019-05-05 20:28:35 +02:00
data_store : Arc < RwLock < DataStore > > ,
}
impl ServerState {
2019-05-07 17:46:17 +02:00
#[ allow(dead_code) ]
2019-05-05 20:28:35 +02:00
pub fn new ( storage_path : & Path ) -> std ::io ::Result < Self > {
Ok ( Self {
data_store : Arc ::new ( RwLock ::new ( DataStore ::new ( & storage_path ) ? ) ) ,
} )
}
2019-04-20 01:24:19 +02:00
}
impl ProtocolHandler for ServerState {
2019-05-07 22:43:14 +02:00
fn query ( & mut self , query : & [ String ] ) -> ProtocolResult < Vec < Texture > > {
let q = Query ::parse ( query )
. map_err ( | e | ProtocolError ::BadRequest ( format! ( " Invalid Query String: {:?} " , e ) ) ) ? ;
let data_store = self . data_store . read ( ) . unwrap ( ) ;
let mut textures = data_store . borrow_textures ( ) ;
Ok ( q . search ( & mut textures ) )
2019-04-20 01:24:19 +02:00
}
2019-04-24 19:24:00 +02:00
fn get_texture_by_id ( & mut self , id : & str ) -> ProtocolResult < Option < Texture > > {
2019-05-05 20:28:35 +02:00
let data_store = self . data_store . read ( ) . unwrap ( ) ;
Ok ( data_store . texture_by_id ( id ) )
2019-04-20 01:24:19 +02:00
}
2019-04-24 19:24:00 +02:00
fn get_texture_by_name ( & mut self , name : & str ) -> ProtocolResult < Option < Texture > > {
2019-05-05 20:28:35 +02:00
let data_store = self . data_store . read ( ) . unwrap ( ) ;
Ok ( data_store . texture_by_name ( name ) )
2019-04-20 01:24:19 +02:00
}
2019-04-24 19:24:00 +02:00
fn get_texture_file ( & mut self , hash : Sha256 ) -> ProtocolResult < Vec < u8 > > {
2019-05-05 20:28:35 +02:00
let data_store = self . data_store . read ( ) . unwrap ( ) ;
let data = data_store . read_texture_file_by_hash ( & hash ) ? ;
Ok ( data )
2019-04-20 01:24:19 +02:00
}
2019-04-24 19:24:00 +02:00
fn get_texture_preview (
& mut self ,
hash : Sha256 ,
format : TextureFormat ,
) -> ProtocolResult < Vec < u8 > > {
2019-05-05 20:28:35 +02:00
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 ) ) ,
}
2019-04-20 01:24:19 +02:00
}
fn replace_texture (
& mut self ,
delete : Option < Texture > ,
insert : Option < Texture > ,
insert_texture_data : Option < Vec < u8 > > ,
) -> ProtocolResult < ReplaceTextureStatus > {
2019-05-05 20:28:35 +02:00
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 ( ) ,
) ) ;
}
2019-05-06 09:34:12 +02:00
data_store . flush_metadata ( ) ? ;
2019-05-05 20:28:35 +02:00
Ok ( ReplaceTextureStatus ::Ok )
}
( Some ( delete ) , None ) = > {
if ! data_store . delete ( & delete ) {
return Err ( ProtocolError ::Conflict (
" Delete Texture was modified! " . to_string ( ) ,
) ) ;
}
2019-05-06 09:34:12 +02:00
data_store . flush_metadata ( ) ? ;
2019-05-05 20:28:35 +02:00
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 ( ) ,
) ) ;
}
2019-05-06 09:34:12 +02:00
data_store . flush_metadata ( ) ? ;
2019-05-05 20:28:35 +02:00
Ok ( ReplaceTextureStatus ::Ok )
}
( None , None ) = > Ok ( ReplaceTextureStatus ::Ok ) ,
}
2019-04-20 01:24:19 +02:00
}
}