Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add server-mvp #23

Merged
merged 2 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"

members = [
"memcrab",
"memcrab-cache",
"memcrab-server",
"memcrab-protocol",
"memcrab-cli",
]
Expand Down
9 changes: 0 additions & 9 deletions memcrab-cache/Cargo.toml

This file was deleted.

3 changes: 0 additions & 3 deletions memcrab-cache/src/lib.rs

This file was deleted.

73 changes: 0 additions & 73 deletions memcrab-cache/src/mem_lru/builder.rs

This file was deleted.

6 changes: 0 additions & 6 deletions memcrab-cache/src/mem_lru/mod.rs

This file was deleted.

22 changes: 0 additions & 22 deletions memcrab-cache/tests/memlru.rs

This file was deleted.

1 change: 0 additions & 1 deletion memcrab-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ repository = "https://github.com/cospectrum/memcrab"
anyhow = "1.0.79"
clap = { version = "4.4.12", features = ["derive"] }
memcrab = { version = "0.1.0", path = "../memcrab" }
memcrab-cache = { version = "0.1.0", path = "../memcrab-cache" }
rustyline = "13.0.0"
tokio = { version = "1.35.1", features = ["full"] }
19 changes: 5 additions & 14 deletions memcrab-protocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ Clients should only send request messages and understand responses messages howe
```rs
type PayloadLen = u64; // number of bytes in payload

type Version = u16; // protocol-version
type KeyLen = u64; // number of bytes in the encoded utf8 string key
type Expirtaion = u32; // expiration in seconds

Expand All @@ -54,12 +53,11 @@ type Key = String; // utf-8
#### Requests (first byte < 128)
| Message kind | first byte | remaining 8 bytes in header | payload
| --- | --- | --- | ---
| Version | 0 | PayloadLen | Version
| Ping | 1 | zeros | none
| Get | 2 | PayloadLen | Key
| Set | 3 | PayloadLen | KeyLen, Expirtaion, Key, Value
| Delete | 4 | PayloadLen | Key
| Clear | 5 | zeros | none
| Ping | 0 | zeros | none
| Get | 1 | PayloadLen | Key
| Set | 2 | PayloadLen | KeyLen, Expirtaion, Key, Value
| Delete | 3 | PayloadLen | Key
| Clear | 4 | zeros | none

#### Responses (first byte >= 128)
| Message kind | first byte | remaining 8 bytes in header | payload
Expand All @@ -70,10 +68,3 @@ type Key = String; // utf-8
| KeyNotFound | 131 | zeros | none
| Error | 255 | PayloadLen | String (utf-8 encoded)

### Versioning
Protocol is versioned by a number and are not backwards compatible.

The current version is `0`.

The clients must send `Version` message as their first message.
The server must close the connection if the version is not compatible.
1 change: 0 additions & 1 deletion memcrab-protocol/src/alias.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub type PayloadLen = u64;

pub type Version = u16;
pub type KeyLen = u64;
pub type Expiration = u32;
11 changes: 5 additions & 6 deletions memcrab-protocol/src/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ impl TryFrom<u8> for MsgKind {
#[repr(u8)]
#[derive(Debug, Clone, Copy, TryFromPrimitive, IntoPrimitive, PartialEq, Eq)]
pub enum RequestKind {
Version = 0,
Ping = 1,
Get = 2,
Set = 3,
Delete = 4,
Clear = 5,
Ping = 0,
Get = 1,
Set = 2,
Delete = 3,
Clear = 4,
}

#[repr(u8)]
Expand Down
2 changes: 0 additions & 2 deletions memcrab-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ mod socket;

use std::mem::size_of;

use alias::Version;
use parser::Parser;

pub use err::{Error, ParseError};
Expand All @@ -17,7 +16,6 @@ pub use msg::{Msg, Request, Response};
pub use socket::Socket;

const HEADER_SIZE: usize = size_of::<u8>() + size_of::<u64>();
pub const VERSION: Version = 0;

#[cfg(test)]
mod tests {
Expand Down
3 changes: 1 addition & 2 deletions memcrab-protocol/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::alias::{Expiration, Version};
use crate::alias::Expiration;

#[derive(Debug, Clone, PartialEq)]
pub enum Msg {
Expand All @@ -8,7 +8,6 @@ pub enum Msg {

#[derive(Debug, Clone, PartialEq)]
pub enum Request {
Version(Version),
Get(String),
Set {
key: String,
Expand Down
7 changes: 1 addition & 6 deletions memcrab-protocol/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
alias::{Expiration, KeyLen, PayloadLen, Version},
alias::{Expiration, KeyLen, PayloadLen},
kind::{MsgKind, RequestKind, ResponseKind},
Msg, ParseError, Request, Response, HEADER_SIZE,
};
Expand Down Expand Up @@ -32,10 +32,6 @@ impl Parser {
fn decode_request(&self, kind: RequestKind, payload: Payload) -> Result<Request, ParseError> {
use RequestKind as Kind;
Ok(match kind {
Kind::Version => {
let version = Version::from_be_bytes(payload.as_slice().try_into()?);
Request::Version(version)
}
Kind::Ping => Request::Ping,
Kind::Get => Request::Get(utf8(payload)?),
Kind::Set => {
Expand Down Expand Up @@ -92,7 +88,6 @@ impl Parser {

fn encode_request(&self, req: Request) -> (RequestKind, Payload) {
match req {
Request::Version(version) => (RequestKind::Version, version.to_be_bytes().to_vec()),
Request::Ping => (RequestKind::Ping, vec![]),
Request::Clear => (RequestKind::Clear, vec![]),
Request::Get(key) => (RequestKind::Get, key.into()),
Expand Down
5 changes: 0 additions & 5 deletions memcrab-protocol/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ mod test {
// boilerplate somehow
// TODO!: tests for encoding

let mut data = vec![MsgKind::Request(RequestKind::Version).into()];
data.extend(2u64.to_be_bytes());
data.extend([0, 1]);
assert_parsed(data, Msg::Request(Request::Version(1))).await;

let mut data = vec![MsgKind::Request(RequestKind::Ping).into()];
data.extend(zero_u64_bytes);
assert_parsed(data, Msg::Request(Request::Ping)).await;
Expand Down
13 changes: 13 additions & 0 deletions memcrab-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "memcrab-server"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio = { workspace = true, features = ["full"] }
memcrab-protocol = { version = "0.1.0", path = "../memcrab-protocol" }
lru = "0.12.1"
thiserror.workspace = true
typed-builder = "0.18.1"
18 changes: 18 additions & 0 deletions memcrab-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# memcrab-server

```rs
use memcrab_server::{Server, CacheCfg};

#[tokio::main]
async fn main() {
let gb = 2_usize.pow(30);
let cfg = CacheCfg::builder()
.segments(10)
.max_bytesize(gb)
.build();

let addr = "127.0.0.1:9900".parse().unwrap();
let server = Server::from(cfg);
server.start(addr).await.unwrap();
}
```
48 changes: 48 additions & 0 deletions memcrab-server/src/cache/api/cfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::sync::Mutex;
use typed_builder::TypedBuilder;

use crate::cache::map::Map;

use super::{MemLru, Value};

#[derive(TypedBuilder)]
pub struct CacheCfg {
segments: usize,
#[builder(default=None, setter(strip_option))]
max_len: Option<usize>,
max_bytesize: usize,
}

impl CacheCfg {
pub(super) fn map(self) -> Map<String, Value> {
assert!(self.segments > 0);

let new_segment = |max_bytesize: usize, max_len: Option<usize>| {
Mutex::new(match max_len {
Some(max_len) => {
if max_len == 0 {
MemLru::with_max_bytesize(max_bytesize)
} else {
MemLru::with_max_bytesize_and_max_len(max_bytesize, max_len)
}
}
None => MemLru::with_max_bytesize(max_bytesize),
})
};

let mut segments = Vec::with_capacity(self.segments);
let segment = new_segment(
self.max_bytesize / self.segments + self.max_bytesize % self.segments,
self.max_len.map(|l| l / self.segments + l % self.segments),
);
segments.push(segment);
for _ in 1..self.segments {
let segment = new_segment(
self.max_bytesize / self.segments,
self.max_len.map(|l| l / self.segments),
);
segments.push(segment);
}
Map::from_segments(segments)
}
}
Loading