-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start defining cluster control commands
- Loading branch information
Showing
8 changed files
with
270 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
use std::collections::HashMap; | ||
use std::hash::{DefaultHasher, Hash, Hasher}; | ||
use std::net::TcpStream; | ||
use std::sync::{Arc, Mutex}; | ||
|
||
|
||
pub struct Cluster { | ||
self_id: String, | ||
num_buckets: u64, | ||
|
||
// bucket_id -> server_ip | ||
bucket_servers: Arc<Mutex<HashMap<String, String>>>, | ||
// server_ip -> connection | ||
server_connections: Arc<Mutex<HashMap<String, TcpStream>>>, | ||
} | ||
|
||
|
||
impl Cluster { | ||
pub fn new(num_buckets: u64, self_id: String) -> Cluster { | ||
let bucket_servers: Arc<Mutex<HashMap<String, String>>> = Arc::new(Mutex::new(HashMap::new())); | ||
let server_connections: Arc<Mutex<HashMap<String, TcpStream>>> = Arc::new(Mutex::new(HashMap::new())); | ||
|
||
// todo: init all bucket servers with server 1 | ||
|
||
Cluster { | ||
self_id, | ||
num_buckets, | ||
bucket_servers, | ||
server_connections, | ||
} | ||
} | ||
|
||
pub fn get_server_for_key(&mut self, key: &String) -> String { | ||
let bucket = self.get_bucket_for_key(key).to_string(); | ||
self.bucket_servers.lock().unwrap().get(&bucket).unwrap().clone() | ||
} | ||
|
||
pub fn add_server(&mut self, server_id: String, connection: TcpStream) { | ||
|
||
} | ||
|
||
fn get_bucket_for_key(&mut self, key: &String) -> u64 { | ||
calculate_hash(key) % self.num_buckets | ||
} | ||
} | ||
|
||
fn calculate_hash<T: Hash>(t: &T) -> u64 { | ||
let mut s = DefaultHasher::new(); | ||
t.hash(&mut s); | ||
s.finish() | ||
} | ||
|
||
// - server has hashmap bucket_id (16) -> list of keys | ||
// - server 1 has a map bucket -> server | ||
// - server 2 comes up, connects to server 1, sends `get_buckets_to_handle` request | ||
// - server 1 updates bucket -> server map, assigns buckets to server 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,104 +1,19 @@ | ||
pub enum CommandEnum { | ||
Put { | ||
pub enum CommandsEnum { | ||
JoinCluster {}, | ||
LeaveCluster {}, | ||
GetClusterState {}, | ||
GetKeysForBucket { | ||
key: String, | ||
value: String, | ||
ttl: u64, | ||
}, | ||
Get { | ||
key: String, | ||
}, | ||
Exists { | ||
key: String, | ||
}, | ||
Exit, | ||
} | ||
|
||
pub trait CommandResponse { | ||
fn serialize(&self) -> String; | ||
} | ||
|
||
pub struct PutResponse {} | ||
|
||
pub struct GetResponse { | ||
pub key: String, | ||
pub value: Option<String>, | ||
} | ||
|
||
pub struct ExistsResponse { | ||
pub exists: bool, | ||
} | ||
|
||
pub struct CommandNotFoundResponse {} | ||
|
||
impl CommandResponse for PutResponse { | ||
fn serialize(&self) -> String { | ||
String::from("OK") | ||
} | ||
} | ||
|
||
impl CommandResponse for GetResponse { | ||
fn serialize(&self) -> String { | ||
match &self.value { | ||
Some(v) => { | ||
let message = format!("Got {}", v); | ||
String::from(message) | ||
} | ||
None => { | ||
String::from("Key not found") | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
impl CommandResponse for ExistsResponse { | ||
fn serialize(&self) -> String { | ||
match &self.exists { | ||
true => { | ||
String::from("OK") | ||
} | ||
false => String::from("Key not found") | ||
} | ||
} | ||
pub struct CmdResponse { | ||
} | ||
|
||
impl CommandResponse for CommandNotFoundResponse { | ||
impl CmdResponse { | ||
fn serialize(&self) -> String { | ||
String::from("Command not found") | ||
return String::new(); | ||
} | ||
} | ||
|
||
pub const DEFAULT_TTL: u64 = 60; | ||
|
||
pub fn deserialize_command(input: String) -> CommandEnum { | ||
let parts: Vec<&str> = input.split_whitespace().collect(); | ||
let command = parts.get(0); | ||
|
||
return match command { | ||
Some(&"set") => { | ||
let key = String::from(parts[1]); | ||
let value = String::from(parts[2]); | ||
let ttl = if let Some(ttl_value) = parts.get(3) { | ||
ttl_value.parse::<u64>().unwrap_or({ | ||
DEFAULT_TTL | ||
}) | ||
} else { DEFAULT_TTL }; | ||
CommandEnum::Put { key, value, ttl } | ||
} | ||
Some(&"get") => { | ||
let key = String::from(parts[1]); | ||
CommandEnum::Get { key } | ||
} | ||
Some(&"exists") => { | ||
let key = String::from(parts[1]); | ||
CommandEnum::Exists { key } | ||
} | ||
Some(&"exit") => { | ||
CommandEnum::Exit {} | ||
} | ||
_ => { | ||
// TODO: proper handling | ||
panic!("Command {command:#?} not found."); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,41 @@ | ||
use log::warn; | ||
use crate::server::cache::Cache; | ||
use crate::server::commands; | ||
use crate::server::commands::CommandEnum; | ||
use crate::server::commands::{CmdResponse, CommandsEnum}; | ||
use crate::server::{commands, requests}; | ||
use crate::server::requests::RequestsEnum; | ||
|
||
pub fn process_command(command: CommandEnum, cache: &mut Cache) -> Box<dyn commands::CommandResponse> { | ||
match command { | ||
CommandEnum::Put { key, value, ttl } => { | ||
pub fn process_client_request(request: RequestsEnum, cache: &mut Cache) -> Box<dyn requests::ReqResponse> { | ||
match request { | ||
RequestsEnum::Put { key, value, ttl } => { | ||
cache.put(&key, &value, ttl); | ||
let response = commands::PutResponse {}; | ||
let response = requests::PutResponse {}; | ||
Box::new(response) | ||
} | ||
CommandEnum::Get { key } => { | ||
RequestsEnum::Get { key } => { | ||
let value = cache.get(&key); | ||
let response = commands::GetResponse { | ||
let response = requests::GetResponse { | ||
key, | ||
value, | ||
}; | ||
Box::new(response) | ||
} | ||
CommandEnum::Exists { key } => { | ||
RequestsEnum::Exists { key } => { | ||
let exists = cache.exists(&key); | ||
let response = commands::ExistsResponse { exists }; | ||
let response = requests::ExistsResponse { exists }; | ||
Box::new(response) | ||
} | ||
CommandEnum::Exit {} => { | ||
RequestsEnum::Exit {} => { | ||
warn!("Received EXIT command. Wrapping up."); | ||
panic!("Received EXIT command"); | ||
} | ||
} | ||
} | ||
|
||
pub fn process_command(command: CommandsEnum, cache: &mut Cache) { | ||
match command { | ||
CommandsEnum::JoinCluster { .. } => {} | ||
CommandsEnum::LeaveCluster { .. } => {} | ||
CommandsEnum::GetClusterState { .. } => {} | ||
CommandsEnum::GetKeysForBucket { .. } => {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.