Files
herodb/src/server.rs
2025-08-16 07:18:55 +02:00

69 lines
2.0 KiB
Rust

use core::str;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use crate::cmd::Cmd;
use crate::error::DBError;
use crate::options;
use crate::protocol::Protocol;
use crate::storage::Storage;
#[derive(Clone)]
pub struct Server {
pub storage: Arc<Storage>,
pub option: options::DBOption,
}
impl Server {
pub async fn new(option: options::DBOption) -> Self {
// Create database file path with fixed filename
let db_file_path = PathBuf::from(option.dir.clone()).join("herodb.redb");
println!("will open db file path: {}", db_file_path.display());
// Initialize storage with redb
let storage = Storage::new(db_file_path).expect("Failed to initialize storage");
Server {
storage: Arc::new(storage),
option,
}
}
pub async fn handle(
&mut self,
mut stream: tokio::net::TcpStream,
) -> Result<(), DBError> {
let mut buf = [0; 512];
let mut queued_cmd: Option<Vec<(Cmd, Protocol)>> = None;
loop {
if let Ok(len) = stream.read(&mut buf).await {
if len == 0 {
println!("[handle] connection closed");
return Ok(());
}
let s = str::from_utf8(&buf[..len])?;
let (cmd, protocol) =
Cmd::from(s).unwrap_or((Cmd::Unknow, Protocol::err("unknow cmd")));
println!("got command: {:?}, protocol: {:?}", cmd, protocol);
let res = cmd
.run(self, protocol, &mut queued_cmd)
.await
.unwrap_or(Protocol::err("unknow cmd"));
print!("queued cmd {:?}", queued_cmd);
println!("going to send response {}", res.encode());
_ = stream.write(res.encode().as_bytes()).await?;
} else {
println!("[handle] going to break");
break;
}
}
Ok(())
}
}