use crate::aioserver::enhanced_stream::EnhancedStream;
use crate::aioserver::event_channel::{channel, EventedSender};
use crate::aioserver::id_generator::IdGenerator;
use crate::aioserver::worker::WorkerPool;
use crate::request::Request;
use crate::response::Response;
use std::io::ErrorKind;
use log::{error, trace};
use std::ops::Drop;
use std::collections::HashMap;
use std::sync::mpsc::Receiver;
use std::sync::{Arc, Condvar, Mutex};
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interest, Poll, Token, Waker};
const SERVER: Token = Token(0);
const SHUTDOWN: Token = Token(1);
const DELETE: Token = Token(2);
const WAKER: Token = Token(3);
type Status = Arc<(Mutex<bool>, Condvar)>;
pub(crate) type SafeStream<R> = Arc<Mutex<EnhancedStream<R>>>;
pub(crate) enum LoopTask {
Shutdown,
Close(usize),
}
pub struct AIOServer<H> {
handler: Arc<H>,
pool: WorkerPool<H>,
receiver: Receiver<LoopTask>,
handle: ServerHandle,
poll: mio::Poll,
server: TcpListener,
}
impl<H> AIOServer<H>
where
H: Send + Sync + 'static + Fn(&Request) -> Response,
{
pub fn new(size: i32, addr: &str, handler: H) -> AIOServer<H> {
let handler = Arc::from(handler);
let poll = Poll::new().unwrap();
let waker = Arc::new(Waker::new(poll.registry(), WAKER).unwrap());
let (sender, receiver) = channel(waker);
let pool = WorkerPool::new(handler.clone(), size, sender.clone());
let server = TcpListener::bind(addr.parse().unwrap()).unwrap();
AIOServer {
handler,
pool,
poll,
receiver,
handle: ServerHandle::new(sender),
server,
}
}
pub fn start(&mut self) {
let mut map = HashMap::new();
let mut events = Events::with_capacity(32768);
let mut gen = IdGenerator::new(4);
self.poll
.registry()
.register(&mut self.server, SERVER, Interest::READABLE)
.unwrap();
self.pool.start();
self.handle.set_ready(true);
loop {
trace!("Opened connection: {}", map.len());
trace!("Connection pool capacity: {}", map.capacity());
self.poll.poll(&mut events, None).unwrap();
for event in events.iter() {
match event.token() {
SERVER => loop {
let connection = match self.server.accept() {
Ok((conn, _)) => conn,
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
break;
}
Err(e) => {
error!("Error when accepting conn : {}", e);
continue;
}
};
let id = gen.id();
let token = Token(id);
let mut stream = EnhancedStream::new(id, connection);
match self
.poll
.registry()
.register(&mut stream, token, Interest::READABLE)
{
Ok(_) => {}
Err(e) => {
if stream.shutdown().is_err() {
trace!("Error when shutting down not registered connection")
}
error!("Error when registering conn : {}", e);
continue;
}
}
let stream = Arc::from(Mutex::from(stream));
map.insert(token, stream.clone());
self.pool.work(stream).unwrap();
trace!("New client with id : {}", id);
},
WAKER => {
while let Ok(task) = self.receiver.try_recv() {
match task {
LoopTask::Shutdown => {
trace!("Shutting down");
self.pool.join();
self.handle.set_ready(false);
return;
}
LoopTask::Close(id) => {
AIOServer::<H>::remove_connection(
id, &mut map, &self.poll, &mut gen,
);
}
}
}
}
token => {
trace!("Data from id : {}", token.0);
let stream = match map.get(&token) {
Some(stream) => stream.clone(),
None => {
error!("Could not retrieve stream with id : {}", token.0);
continue;
}
};
self.pool.work(stream).unwrap();
}
}
}
}
}
}
impl<H> AIOServer<H> {
pub fn handle(&self) -> ServerHandle {
self.handle.clone()
}
fn remove_connection(
id: usize,
map: &mut HashMap<Token, SafeStream<TcpStream>>,
poll: &Poll,
generator: &mut IdGenerator,
) {
let to_close = match map.remove(&Token(id)) {
Some(val) => val,
None => return,
};
let mut to_close = to_close.lock().unwrap();
match to_close.shutdown() {
Ok(_) => {}
Err(e) => {
error!("Issue when closing TCP connection {} : {}", id, e);
}
};
match poll.registry().deregister(&mut (*to_close)) {
Ok(_) => {}
Err(e) => {
error!("Issue when deregistering connection {} : {}", id, e);
}
};
generator.remove(id);
}
}
impl<H> Drop for AIOServer<H> {
fn drop(&mut self) {
self.handle.shutdown();
}
}
#[derive(Clone)]
pub struct ServerHandle {
ready: Status,
sender: EventedSender<LoopTask>,
}
impl ServerHandle {
fn new(sender: EventedSender<LoopTask>) -> Self {
ServerHandle {
ready: Arc::new((Mutex::from(false), Condvar::new())),
sender,
}
}
fn set_ready(&self, ready_val: bool) {
let (lock, cvar) = &*self.ready;
let mut ready = lock.lock().unwrap();
*ready = ready_val;
cvar.notify_all();
}
pub fn shutdown(&self) {
self.sender.send(LoopTask::Shutdown).unwrap();
let (lock, cvar) = &*self.ready;
let mut started = lock.lock().unwrap();
while *started {
started = cvar.wait(started).unwrap();
}
}
pub fn ready(&self) {
let (lock, cvar) = &*self.ready;
let mut started = lock.lock().unwrap();
while !*started {
started = cvar.wait(started).unwrap();
}
}
}