1use crate::{config::Config, error::Result, network::Connection};
2use feoxdb::FeoxStore;
3use std::net::TcpListener;
4use std::os::fd::{AsRawFd, RawFd};
5use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
6use std::sync::Arc;
7use std::thread;
8use tracing::{debug, error, info};
9
10pub struct Server {
12 config: Config,
13 store: Arc<FeoxStore>,
14 shutdown: AtomicBool,
15 active_connections: AtomicUsize,
16}
17
18impl Server {
19 pub fn new(config: Config) -> Result<Self> {
21 config.validate()?;
22
23 let store = if let Some(ref data_path) = config.data_path {
25 let mut builder = FeoxStore::builder()
26 .device_path(data_path.clone())
27 .max_memory(config.max_memory_per_shard.unwrap_or(1024 * 1024 * 1024))
28 .enable_ttl(config.enable_ttl);
29
30 if let Some(file_size) = config.file_size {
32 builder = builder.file_size(file_size);
33 }
34
35 Arc::new(builder.build()?)
36 } else {
37 Arc::new(
38 FeoxStore::builder()
39 .max_memory(config.max_memory_per_shard.unwrap_or(1024 * 1024 * 1024))
40 .enable_ttl(config.enable_ttl)
41 .build()?,
42 )
43 };
44
45 Ok(Self {
46 config,
47 store,
48 shutdown: AtomicBool::new(false),
49 active_connections: AtomicUsize::new(0),
50 })
51 }
52
53 pub fn run(self: Arc<Self>) -> Result<()> {
57 let listener =
59 TcpListener::bind(format!("{}:{}", self.config.bind_addr, self.config.port))?;
60
61 listener.set_nonblocking(true)?;
62 let listener_fd = listener.as_raw_fd();
63
64 info!(
65 "Server listening on {}:{}",
66 self.config.bind_addr, self.config.port
67 );
68
69 let mut handles = Vec::new();
71
72 for thread_id in 0..self.config.threads {
73 let server = Arc::clone(&self);
74 let store = Arc::clone(&self.store);
75 let handle = thread::spawn(move || {
76 if let Err(e) = server.run_worker(thread_id, listener_fd, store) {
77 error!("Worker {} failed: {}", thread_id, e);
78 }
79 });
80 handles.push(handle);
81 }
82
83 for handle in handles {
85 let _ = handle.join();
86 }
87
88 Ok(())
89 }
90
91 pub fn shutdown(&self) {
93 info!("Initiating server shutdown");
94 self.shutdown.store(true, Ordering::Release);
95 }
96
97 pub fn active_connections(&self) -> usize {
99 self.active_connections.load(Ordering::Acquire)
100 }
101
102 fn run_worker(
103 self: &Arc<Self>,
104 thread_id: usize,
105 listener_fd: RawFd,
106 store: Arc<FeoxStore>,
107 ) -> Result<()> {
108 use mio::net::{TcpListener as MioTcpListener, TcpStream as MioTcpStream};
109 use mio::{Events, Interest, Poll, Token};
110 use std::collections::HashMap;
111 use std::io::{ErrorKind, Read, Write};
112 use std::os::fd::FromRawFd;
113
114 let mut poll = Poll::new()?;
116 let mut events = Events::with_capacity(1024);
117
118 let std_listener = unsafe { TcpListener::from_raw_fd(listener_fd) };
120 std_listener.set_nonblocking(true)?;
121 let mut listener = MioTcpListener::from_std(std_listener);
122
123 const SERVER: Token = Token(0);
125 poll.registry()
126 .register(&mut listener, SERVER, Interest::READABLE)?;
127
128 let mut connections: HashMap<Token, (MioTcpStream, Connection)> = HashMap::new();
130 let mut next_token = 1usize;
131
132 info!("Worker {} started", thread_id);
133
134 while !self.shutdown.load(Ordering::Acquire) {
136 poll.poll(&mut events, Some(std::time::Duration::from_millis(100)))?;
138
139 for event in events.iter() {
140 match event.token() {
141 SERVER => {
142 loop {
144 match listener.accept() {
145 Ok((mut stream, addr)) => {
146 debug!("New connection from {:?}", addr);
147
148 stream.set_nodelay(self.config.tcp_nodelay)?;
150
151 let token = Token(next_token);
152 next_token += 1;
153
154 poll.registry().register(
156 &mut stream,
157 token,
158 Interest::READABLE,
159 )?;
160
161 let connection = Connection::new(
162 0, self.config.connection_buffer_size,
164 Arc::clone(&store),
165 );
166
167 connections.insert(token, (stream, connection));
168 self.active_connections.fetch_add(1, Ordering::Relaxed);
169 }
170 Err(e) if e.kind() == ErrorKind::WouldBlock => break,
171 Err(e) => {
172 error!("Error accepting connection: {}", e);
173 break;
174 }
175 }
176 }
177 }
178 token => {
179 let should_close = if let Some((stream, connection)) =
181 connections.get_mut(&token)
182 {
183 let mut should_close = false;
184
185 if event.is_readable() {
186 let mut buffer = vec![0u8; 8192];
188
189 match stream.read(&mut buffer) {
190 Ok(0) => {
191 should_close = true;
193 }
194 Ok(n) => {
195 if let Err(e) = connection.process_read(&buffer[..n]) {
197 error!("Error processing read: {}", e);
198 should_close = true;
199 } else {
200 while let Some(response_data) =
202 connection.pending_writes()
203 {
204 let response_len = response_data.len();
205 match stream.write(response_data) {
206 Ok(n) => {
207 connection.consume_writes(n);
208 if n < response_len {
209 break;
211 }
212 }
213 Err(e) if e.kind() == ErrorKind::WouldBlock => {
214 break;
215 }
216 Err(e) => {
217 error!("Error writing: {}", e);
218 should_close = true;
219 break;
220 }
221 }
222 }
223 }
224
225 if connection.is_closed() {
226 should_close = true;
227 }
228 }
229 Err(e) if e.kind() != ErrorKind::WouldBlock => {
230 if e.kind() != ErrorKind::ConnectionReset {
231 error!("Error reading: {}", e);
232 }
233 should_close = true;
234 }
235 Err(_) => {} }
237 }
238
239 should_close
240 } else {
241 false
242 };
243
244 if should_close {
245 if let Some((mut stream, mut connection)) = connections.remove(&token) {
246 let _ = poll.registry().deregister(&mut stream);
247 connection.close();
248 self.active_connections.fetch_sub(1, Ordering::Relaxed);
249 }
250 }
251 }
252 }
253 }
254 }
255
256 for (_, (mut stream, mut connection)) in connections {
258 let _ = poll.registry().deregister(&mut stream);
259 connection.close();
260 }
261
262 info!("Worker {} shutting down", thread_id);
263 Ok(())
264 }
265}