Added simple multithreading

This commit is contained in:
p11 2023-07-21 20:29:46 +02:00
parent fdfeae97b2
commit 1b039b0494

View File

@ -5,6 +5,8 @@ use std::{
io::{prelude::*, BufReader, Error, ErrorKind, Result}, io::{prelude::*, BufReader, Error, ErrorKind, Result},
net::{TcpListener, TcpStream}, net::{TcpListener, TcpStream},
path::Path, path::Path,
sync::{Arc, Mutex},
thread,
}; };
use data_stream::{ use data_stream::{
@ -43,12 +45,13 @@ fn fail(mut stream: TcpStream) {
let _ = writeln!(stream, "Page not found!"); let _ = writeln!(stream, "Page not found!");
} }
#[derive(Clone)]
struct Comment { struct Comment {
name: Box<str>, name: Box<str>,
text: Box<str>, text: Box<str>,
} }
#[derive(Default)] #[derive(Default, Clone)]
struct SiteInfo { struct SiteInfo {
comments: Vec<Comment>, comments: Vec<Comment>,
visits: usize, visits: usize,
@ -111,7 +114,7 @@ impl<S: SizeSettings> FromStream<S> for SiteInfo {
#[derive(Default)] #[derive(Default)]
struct Context { struct Context {
infos: HashMap<Box<str>, SiteInfo>, infos: HashMap<Box<str>, Arc<Mutex<SiteInfo>>>,
} }
impl Context { impl Context {
@ -192,17 +195,21 @@ impl Context {
use Entry::*; use Entry::*;
let info = match self.infos.entry(relative_path.clone().into_boxed_str()) { let info = match self.infos.entry(relative_path.clone().into_boxed_str()) {
Occupied(o) => o.into_mut(), Occupied(o) => o.get().clone(),
Vacant(v) => v.insert( Vacant(v) => v
.insert(Arc::new(Mutex::new(
File::open(&data_path) File::open(&data_path)
.map(|mut file| { .map(|mut file| {
from_stream::<PortableSettings, _, _>(&mut file).unwrap_or_default() from_stream::<PortableSettings, _, _>(&mut file).unwrap_or_default()
}) })
.unwrap_or_default(), .unwrap_or_default(),
), )))
.clone(),
}; };
info.handle_connection( thread::spawn(move || {
handle_relative_connection(
info,
stream, stream,
&request.body, &request.body,
&relative_path, &relative_path,
@ -212,12 +219,12 @@ impl Context {
&data_path, &data_path,
start_level, start_level,
) )
});
} }
} }
impl SiteInfo { fn handle_relative_connection(
fn handle_connection( info: Arc<Mutex<SiteInfo>>,
&mut self,
mut stream: TcpStream, mut stream: TcpStream,
body: &str, body: &str,
relative_path: &str, relative_path: &str,
@ -230,6 +237,9 @@ impl SiteInfo {
let mut name = None; let mut name = None;
let mut text = None; let mut text = None;
let mut up = false;
let mut down = false;
for entry in body.split('&') { for entry in body.split('&') {
let Some((key, input)) = entry.split_once('=') else { let Some((key, input)) = entry.split_once('=') else {
continue; continue;
@ -263,20 +273,32 @@ impl SiteInfo {
.into(), .into(),
); );
} }
"up" => self.up += 1, "up" => up = true,
"down" => self.down += 1, "down" => down = true,
_ => (), _ => (),
} }
} }
let info = if let Ok(mut info) = info.lock() {
if let (Some(name), Some(text)) = (name, text) { if let (Some(name), Some(text)) = (name, text) {
self.comments.push(Comment { name, text }); info.comments.push(Comment { name, text });
}
if up {
info.up += 1;
}
if down {
info.down += 1;
} }
self.visits += 1; info.visits += 1;
info.clone()
} else {
return;
};
if let Ok(mut file) = File::create(data_path) { if let Ok(mut file) = File::create(data_path) {
if to_stream::<PortableSettings, _, _>(self, &mut file).is_err() { if to_stream::<PortableSettings, _, _>(&info, &mut file).is_err() {
eprintln!("Error saving data!"); eprintln!("Error saving data!");
eprintln!(); eprintln!();
} }
@ -289,7 +311,7 @@ impl SiteInfo {
let _ = writeln!( let _ = writeln!(
stream, stream,
"<p>👁️{} 💖️{} 💔️{}</p>", "<p>👁️{} 💖️{} 💔️{}</p>",
self.visits, self.up, self.down info.visits, info.up, info.down
); );
let title = relative_path let title = relative_path
@ -386,11 +408,10 @@ impl SiteInfo {
}; };
let _ = stream.write_all(html.into_string().as_bytes()); let _ = stream.write_all(html.into_string().as_bytes());
for Comment { name, text } in &self.comments { for Comment { name, text } in &info.comments {
let _ = writeln!(stream, "<fieldset><legend>{name}</legend>{text}</fieldset>"); let _ = writeln!(stream, "<fieldset><legend>{name}</legend>{text}</fieldset>");
} }
let _ = writeln!(stream, "<hr>"); let _ = writeln!(stream, "<hr>");
let _ = writeln!(stream, "<a href=\"/{parent_path}\">&lt;&lt; Back</a>"); let _ = writeln!(stream, "<a href=\"/{parent_path}\">&lt;&lt; Back</a>");
} }
}