Added simple multithreading
This commit is contained in:
parent
fdfeae97b2
commit
1b039b0494
57
src/main.rs
57
src/main.rs
@ -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,
|
||||||
@ -226,10 +233,13 @@ impl SiteInfo {
|
|||||||
pki_path: Option<&Path>,
|
pki_path: Option<&Path>,
|
||||||
data_path: &Path,
|
data_path: &Path,
|
||||||
start_level: usize,
|
start_level: usize,
|
||||||
) {
|
) {
|
||||||
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}\"><< Back</a>");
|
let _ = writeln!(stream, "<a href=\"/{parent_path}\"><< Back</a>");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user