feat: connect server to the new interpreter
This commit is contained in:
parent
9b9f9f16f6
commit
f5d45f6a1d
6 changed files with 70 additions and 145 deletions
|
|
@ -17,8 +17,8 @@ pub struct Configuration {
|
|||
help = "Port for the server to listen on"
|
||||
)]
|
||||
port: u16,
|
||||
#[arg(short, long, help = "Path to the data file")]
|
||||
file: PathBuf,
|
||||
#[arg(short, long, help = "Path to the folder for database data")]
|
||||
folder: PathBuf,
|
||||
#[arg(short, long, help = "Delay between rows in milliseconds")]
|
||||
throttle: Option<u64>,
|
||||
}
|
||||
|
|
@ -30,8 +30,8 @@ impl Configuration {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_file_path(&self) -> &PathBuf {
|
||||
&self.file
|
||||
pub fn get_folder_path(&self) -> &PathBuf {
|
||||
&self.folder
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
use std::collections::HashMap;
|
||||
use std::io::ErrorKind;
|
||||
use std::sync::Arc;
|
||||
|
||||
use clap::Parser;
|
||||
use tokio::io::{BufReader, BufWriter};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use minisql::interpreter::{Response, State};
|
||||
use minisql::response_writer::{CompleteStatus, ResponseWriter};
|
||||
use minisql::interpreter2::StateHandler;
|
||||
use minisql::response_writer::ResponseWriter;
|
||||
use parser::parse_and_validate;
|
||||
use proto::handshake::errors::ServerHandshakeError;
|
||||
use proto::handshake::request::HandshakeRequest;
|
||||
|
|
@ -22,23 +21,21 @@ use proto::writer::protowriter::{ProtoFlush, ProtoWriter};
|
|||
|
||||
use crate::cancellation::ResetCancelToken;
|
||||
use crate::config::Configuration;
|
||||
use crate::persistence::state_to_file;
|
||||
use crate::proto_wrapper::ServerProtoWrapper;
|
||||
|
||||
mod cancellation;
|
||||
mod config;
|
||||
mod persistence;
|
||||
mod proto_wrapper;
|
||||
|
||||
type TokenStore = Arc<Mutex<HashMap<(i32, i32), ResetCancelToken>>>;
|
||||
type SharedDbState = Arc<RwLock<State>>;
|
||||
type SharedDbState = Arc<StateHandler>;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let config = Configuration::parse();
|
||||
let config = Arc::new(config);
|
||||
|
||||
let state = Arc::new(RwLock::new(get_state(&config).await?));
|
||||
let state = Arc::new(get_state(&config).await?);
|
||||
let tokens = Arc::new(Mutex::new(HashMap::<(i32, i32), ResetCancelToken>::new()));
|
||||
|
||||
let addr = config.get_socket_address();
|
||||
|
|
@ -59,15 +56,12 @@ async fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
async fn get_state(config: &Configuration) -> anyhow::Result<State> {
|
||||
let result = persistence::state_from_file(config.get_file_path()).await;
|
||||
match result {
|
||||
Err(ref e) if e.kind() == ErrorKind::NotFound => {
|
||||
println!("WARNING: No DB state file found, creating new one");
|
||||
Ok(State::new())
|
||||
}
|
||||
Err(e) => Err(e)?,
|
||||
Ok(state) => Ok(state),
|
||||
async fn get_state(config: &Configuration) -> anyhow::Result<StateHandler> {
|
||||
let path = config.get_folder_path();
|
||||
if StateHandler::is_existing_db(&path) {
|
||||
Ok(StateHandler::connect(path.clone()).await?)
|
||||
} else {
|
||||
Ok(StateHandler::new(path.clone()).await?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,75 +185,11 @@ where
|
|||
token.reset();
|
||||
|
||||
let operation = {
|
||||
let state = state.read().await;
|
||||
let db_schema = state.db_schema();
|
||||
let db_schema = state.read_state().await.db_schema();
|
||||
parse_and_validate(query, &db_schema)?
|
||||
};
|
||||
|
||||
let need_write = {
|
||||
let mut state = state.write().await;
|
||||
let response = state.interpret(operation)?;
|
||||
|
||||
match response {
|
||||
Response::Deleted(i) => {
|
||||
writer
|
||||
.write_command_complete(CompleteStatus::Delete(i))
|
||||
.await?;
|
||||
true
|
||||
}
|
||||
Response::Inserted => {
|
||||
writer
|
||||
.write_command_complete(CompleteStatus::Insert { oid: 0, rows: 1 })
|
||||
.await?;
|
||||
true
|
||||
}
|
||||
Response::Selected(schema, columns, mut rows) => {
|
||||
writer.write_table_header(schema, &columns).await?;
|
||||
match rows.next() {
|
||||
Some(row) => {
|
||||
writer.write_table_row(&row).await?;
|
||||
|
||||
let mut sent_rows = 1;
|
||||
for row in rows {
|
||||
sent_rows += 1;
|
||||
writer.write_table_row(&row).await?;
|
||||
if token.is_canceled() {
|
||||
token.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
writer
|
||||
.write_command_complete(CompleteStatus::Select(sent_rows))
|
||||
.await?;
|
||||
}
|
||||
_ => {
|
||||
writer
|
||||
.write_command_complete(CompleteStatus::Select(0))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
Response::TableCreated => {
|
||||
writer
|
||||
.write_command_complete(CompleteStatus::CreateTable)
|
||||
.await?;
|
||||
true
|
||||
}
|
||||
Response::IndexCreated => {
|
||||
writer
|
||||
.write_command_complete(CompleteStatus::CreateIndex)
|
||||
.await?;
|
||||
true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if need_write {
|
||||
let state = state.read().await;
|
||||
state_to_file(&state, config.get_file_path()).await?;
|
||||
}
|
||||
|
||||
// TODO: PASS DOWN RESET CANCEL TOKEN
|
||||
state.interpret(writer, operation).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
use minisql::interpreter::State;
|
||||
use std::path::PathBuf;
|
||||
use tokio::{fs, io};
|
||||
|
||||
pub async fn state_from_file(path: &PathBuf) -> io::Result<State> {
|
||||
let content = fs::read_to_string(path).await?;
|
||||
let state = serde_json::from_str(&content)?;
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
pub async fn state_to_file(state: &State, path: &PathBuf) -> io::Result<()> {
|
||||
let content = serde_json::to_string(state)?;
|
||||
fs::write(path, content).await?;
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue