|
@@ -1,46 +1,51 @@
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
use mini_redis::{Connection, Frame};
|
|
use mini_redis::{Connection, Frame};
|
|
|
|
|
|
|
|
+use bytes::Bytes;
|
|
|
|
+use std::collections::HashMap;
|
|
|
|
+use std::sync::{Arc, Mutex};
|
|
|
|
+
|
|
|
|
+type Db = Arc<Mutex<HashMap<String, Bytes>>>;
|
|
|
|
+
|
|
#[tokio::main]
|
|
#[tokio::main]
|
|
async fn main() {
|
|
async fn main() {
|
|
// Bind the listener to the address
|
|
// Bind the listener to the address
|
|
let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();
|
|
let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();
|
|
|
|
|
|
|
|
+ println!("Listening");
|
|
|
|
+
|
|
|
|
+ let db = Arc::new(Mutex::new(HashMap::new()));
|
|
|
|
+
|
|
loop {
|
|
loop {
|
|
let (socket, _) = listener.accept().await.unwrap();
|
|
let (socket, _) = listener.accept().await.unwrap();
|
|
- // A new task is spawned for each inbound socket. The socket is
|
|
|
|
- // moved to the new task and processed there.
|
|
|
|
|
|
+ // Clone the handle to the hash map.
|
|
|
|
+ let db = db.clone();
|
|
|
|
+
|
|
|
|
+ println!("Accepted");
|
|
tokio::spawn(async move {
|
|
tokio::spawn(async move {
|
|
- process(socket).await;
|
|
|
|
|
|
+ process(socket, db).await;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-async fn process(socket: TcpStream) {
|
|
|
|
|
|
+async fn process(socket: TcpStream, db: Db) {
|
|
use mini_redis::Command::{self, Get, Set};
|
|
use mini_redis::Command::{self, Get, Set};
|
|
- use std::collections::HashMap;
|
|
|
|
-
|
|
|
|
- // A hashmap is used to store data
|
|
|
|
- let mut db = HashMap::new();
|
|
|
|
|
|
|
|
// Connection, provided by `mini-redis`, handles parsing frames from
|
|
// Connection, provided by `mini-redis`, handles parsing frames from
|
|
// the socket
|
|
// the socket
|
|
let mut connection = Connection::new(socket);
|
|
let mut connection = Connection::new(socket);
|
|
|
|
|
|
- // Use `read_frame` to receive a command from the connection.
|
|
|
|
while let Some(frame) = connection.read_frame().await.unwrap() {
|
|
while let Some(frame) = connection.read_frame().await.unwrap() {
|
|
let response = match Command::from_frame(frame).unwrap() {
|
|
let response = match Command::from_frame(frame).unwrap() {
|
|
Set(cmd) => {
|
|
Set(cmd) => {
|
|
- // The value is stored as `Vec<u8>`
|
|
|
|
- db.insert(cmd.key().to_string(), cmd.value().to_vec());
|
|
|
|
|
|
+ let mut db = db.lock().unwrap();
|
|
|
|
+ db.insert(cmd.key().to_string(), cmd.value().clone());
|
|
Frame::Simple("OK".to_string())
|
|
Frame::Simple("OK".to_string())
|
|
}
|
|
}
|
|
Get(cmd) => {
|
|
Get(cmd) => {
|
|
|
|
+ let db = db.lock().unwrap();
|
|
if let Some(value) = db.get(cmd.key()) {
|
|
if let Some(value) = db.get(cmd.key()) {
|
|
- // `Frame::Bulk` expects data to be of type `Bytes`. This
|
|
|
|
- // type will be covered later in the tutorial. For now,
|
|
|
|
- // `&Vec<u8>` is converted to `Bytes` using `into()`.
|
|
|
|
- Frame::Bulk(value.clone().into())
|
|
|
|
|
|
+ Frame::Bulk(value.clone())
|
|
} else {
|
|
} else {
|
|
Frame::Null
|
|
Frame::Null
|
|
}
|
|
}
|