69 lines
2.0 KiB
Rust
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(())
|
|
}
|
|
}
|