# HG changeset patch # User alfadur # Date 1554840192 -10800 # Node ID 65861ba8b4e809d9dc5cdaaae51652c214d608c1 # Parent f43ab2bd76ae7da8669f96b6fe7a9b432079284d move room saves to IO thread diff -r f43ab2bd76ae -r 65861ba8b4e8 rust/hedgewars-server/src/server/core.rs --- a/rust/hedgewars-server/src/server/core.rs Tue Apr 09 21:08:35 2019 +0300 +++ b/rust/hedgewars-server/src/server/core.rs Tue Apr 09 23:03:12 2019 +0300 @@ -8,8 +8,6 @@ use log::*; use slab; -use std::fs::{File, OpenOptions}; -use std::io::{Read, Write}; use std::{borrow::BorrowMut, iter, num::NonZeroU16}; type Slab = slab::Slab; @@ -48,18 +46,16 @@ pub struct HWServer { pub clients: IndexSlab, pub rooms: Slab, - pub io: Box, pub anteroom: HWAnteroom, } impl HWServer { - pub fn new(clients_limit: usize, rooms_limit: usize, io: Box) -> Self { + pub fn new(clients_limit: usize, rooms_limit: usize) -> Self { let rooms = Slab::with_capacity(rooms_limit); let clients = IndexSlab::with_capacity(clients_limit); Self { clients, rooms, - io, anteroom: HWAnteroom::new(clients_limit), } } @@ -205,48 +201,3 @@ } } } - -pub trait HWServerIO { - fn write_file(&mut self, name: &str, content: &str) -> std::io::Result<()>; - fn read_file(&mut self, name: &str) -> std::io::Result; -} - -pub struct EmptyServerIO {} - -impl EmptyServerIO { - pub fn new() -> Self { - Self {} - } -} - -impl HWServerIO for EmptyServerIO { - fn write_file(&mut self, _name: &str, _content: &str) -> std::io::Result<()> { - Ok(()) - } - - fn read_file(&mut self, _name: &str) -> std::io::Result { - Ok("".to_string()) - } -} - -pub struct FileServerIO {} - -impl FileServerIO { - pub fn new() -> Self { - Self {} - } -} - -impl HWServerIO for FileServerIO { - fn write_file(&mut self, name: &str, content: &str) -> std::io::Result<()> { - let mut writer = OpenOptions::new().create(true).write(true).open(name)?; - writer.write_all(content.as_bytes()) - } - - fn read_file(&mut self, name: &str) -> std::io::Result { - let mut reader = File::open(name)?; - let mut result = String::new(); - reader.read_to_string(&mut result)?; - Ok(result) - } -} diff -r f43ab2bd76ae -r 65861ba8b4e8 rust/hedgewars-server/src/server/handlers.rs --- a/rust/hedgewars-server/src/server/handlers.rs Tue Apr 09 21:08:35 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers.rs Tue Apr 09 23:03:12 2019 +0300 @@ -4,11 +4,11 @@ use super::{ actions::{Destination, DestinationRoom}, core::HWServer, - coretypes::ClientId, + coretypes::{ClientId, RoomId}, room::RoomSave, }; use crate::{ - protocol::messages::{HWProtocolMessage, HWServerMessage, HWServerMessage::*}, + protocol::messages::{HWProtocolMessage, HWServerMessage, HWServerMessage::*, server_chat}, server::actions::PendingMessage, utils, }; @@ -58,10 +58,21 @@ client_salt: String, server_salt: String, }, + SaveRoom { + room_id: RoomId, + filename: String, + contents: String, + }, + LoadRoom { + room_id: RoomId, + filename: String + } } pub enum IoResult { Account(Option), + SaveRoom(RoomId, bool), + LoadRoom(RoomId, Option) } pub struct Response { @@ -250,5 +261,35 @@ response.add(Error("Authentication failed.".to_string()).send_self()); response.remove_client(client_id); } + IoResult::SaveRoom(_, true) => { + response.add(server_chat("Room configs saved successfully.".to_string()).send_self()); + } + IoResult::SaveRoom(_, false) => { + response.add( + Warning("Unable to save the room configs.".to_string()).send_self(), + ); + } + IoResult::LoadRoom(room_id, Some(contents)) => { + if let Some(ref mut room) = server.rooms.get_mut(room_id) { + match room.set_saves(&contents) { + Ok(_) => response.add( + server_chat("Room configs loaded successfully.".to_string()) + .send_self(), + ), + Err(e) => { + warn!("Error while deserializing the room configs: {}", e); + response.add( + Warning("Unable to deserialize the room configs.".to_string()) + .send_self(), + ); + } + } + } + } + IoResult::LoadRoom(_,None) => { + response.add( + Warning("Unable to load the room configs.".to_string()).send_self(), + ); + } } } diff -r f43ab2bd76ae -r 65861ba8b4e8 rust/hedgewars-server/src/server/handlers/inroom.rs --- a/rust/hedgewars-server/src/server/handlers/inroom.rs Tue Apr 09 21:08:35 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers/inroom.rs Tue Apr 09 23:03:12 2019 +0300 @@ -337,20 +337,10 @@ SaveRoom(filename) => { if client.is_admin() { match room.get_saves() { - Ok(text) => match server.io.write_file(&filename, &text) { - Ok(_) => response.add( - server_chat("Room configs saved successfully.".to_string()).send_self(), - ), - Err(e) => { - warn!( - "Error while writing the config file \"{}\": {}", - filename, e - ); - response.add( - Warning("Unable to save the room configs.".to_string()).send_self(), - ); - } - }, + Ok(contents) => + response.request_io(super::IoTask::SaveRoom { + room_id, filename, contents + }), Err(e) => { warn!("Error while serializing the room configs: {}", e); response.add( @@ -363,30 +353,10 @@ } LoadRoom(filename) => { if client.is_admin() { - match server.io.read_file(&filename) { - Ok(text) => match room.set_saves(&text) { - Ok(_) => response.add( - server_chat("Room configs loaded successfully.".to_string()) - .send_self(), - ), - Err(e) => { - warn!("Error while deserializing the room configs: {}", e); - response.add( - Warning("Unable to deserialize the room configs.".to_string()) - .send_self(), - ); - } - }, - Err(e) => { - warn!( - "Error while reading the config file \"{}\": {}", - filename, e - ); - response.add( - Warning("Unable to load the room configs.".to_string()).send_self(), - ); - } - } + response.request_io(super::IoTask::LoadRoom { + room_id, + filename + }); } } Delete(name) => { diff -r f43ab2bd76ae -r 65861ba8b4e8 rust/hedgewars-server/src/server/io.rs --- a/rust/hedgewars-server/src/server/io.rs Tue Apr 09 21:08:35 2019 +0300 +++ b/rust/hedgewars-server/src/server/io.rs Tue Apr 09 23:03:12 2019 +0300 @@ -11,6 +11,7 @@ }; use mio::{Evented, Poll, PollOpt}; use mio_extras::channel; +use log::*; pub type RequestId = u32; @@ -29,7 +30,7 @@ thread::spawn(move || { while let Ok((request_id, task)) = io_rx.try_recv() { - match task { + let response = match task { IoTask::GetAccount { nick, protocol, @@ -37,17 +38,52 @@ client_salt, server_salt, } => { - if let Ok(account) = db.get_account( + match db.get_account( &nick, protocol, &password_hash, &client_salt, &server_salt, ) { - io_tx.send((request_id, IoResult::Account(account))); + Ok(account) => { + IoResult::Account(account) + } + Err(..) => { + warn!("Unable to get account data: {}", 0); + IoResult::Account(None) + } } + }, + + IoTask::SaveRoom { room_id, filename, contents} => { + let result = match save_file(&filename, &contents) { + Ok(()) => true, + Err(e) => { + warn!( + "Error while writing the room config file \"{}\": {}", + filename, e + ); + false + } + }; + IoResult::SaveRoom(room_id, result) + }, + + IoTask::LoadRoom {room_id, filename} => { + let result = match load_file(&filename) { + Ok(contents) => Some(contents), + Err(e) => { + warn!( + "Error while writing the room config file \"{}\": {}", + filename, e + ); + None + } + }; + IoResult::LoadRoom(room_id, result) } - } + }; + io_tx.send((request_id, response)); } }); @@ -71,3 +107,15 @@ .register(poll, token, mio::Ready::readable(), PollOpt::edge()) } } + +fn save_file(filename: &str, contents: &str) -> Result<()> { + let mut writer = OpenOptions::new().create(true).write(true).open(filename)?; + writer.write_all(contents.as_bytes()) +} + +fn load_file(filename: &str) -> Result { + let mut reader = File::open(filename)?; + let mut result = String::new(); + reader.read_to_string(&mut result)?; + Ok(result) +} \ No newline at end of file diff -r f43ab2bd76ae -r 65861ba8b4e8 rust/hedgewars-server/src/server/network.rs --- a/rust/hedgewars-server/src/server/network.rs Tue Apr 09 21:08:35 2019 +0300 +++ b/rust/hedgewars-server/src/server/network.rs Tue Apr 09 23:03:12 2019 +0300 @@ -16,7 +16,7 @@ use netbuf; use slab::Slab; -use super::{core::FileServerIO, core::HWServer, coretypes::ClientId, handlers}; +use super::{core::HWServer, coretypes::ClientId, handlers}; use crate::{ protocol::{messages::*, ProtocolDecoder}, utils, @@ -303,7 +303,7 @@ impl NetworkLayer { pub fn new(listener: TcpListener, clients_limit: usize, rooms_limit: usize) -> NetworkLayer { - let server = HWServer::new(clients_limit, rooms_limit, Box::new(FileServerIO::new())); + let server = HWServer::new(clients_limit, rooms_limit); let clients = Slab::with_capacity(clients_limit); let pending = HashSet::with_capacity(2 * clients_limit); let pending_cache = Vec::with_capacity(2 * clients_limit);