Skip to content

Commit

Permalink
feat: prepare segcache storage crate for release (#91)
Browse files Browse the repository at this point in the history
Prepare the segcache storage crate for release.

Changes to make the metrics an optional, but default feature to
help reduce the dependency tree for embedded cases.

Remove the dependency on the `storage-types` by adding the typed
`Value`s into this crate itself.

Supporting changes for rename and versioning.
  • Loading branch information
brayniac authored Dec 19, 2023
1 parent db11f2a commit dfcbd33
Show file tree
Hide file tree
Showing 43 changed files with 459 additions and 213 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: |
export CARGO_TARGET_DIR=$(pwd)/target
for target in protocol/admin protocol/memcache protocol/ping protocol/thrift storage/seg; do
for target in protocol/admin protocol/memcache protocol/ping protocol/thrift storage/segcache; do
cd src/$target
echo "::group::Building $target"
cargo fuzz build
Expand All @@ -50,7 +50,7 @@ jobs:
protocol/ping,
protocol/resp,
protocol/thrift,
storage/seg,
storage/segcache,
]
name: fuzz-${{ matrix.os }}-${{ matrix.target }}
runs-on: ${{ matrix.os }}
Expand Down
41 changes: 20 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ members = [
"src/session",
"src/storage/bloom",
"src/storage/datatier",
"src/storage/seg",
"src/storage/segcache",
"src/storage/types",
]

Expand All @@ -51,6 +51,7 @@ bytes = "1.5.0"
clap = "4.4.6"
clocksource = "0.6.0"
crossbeam-channel = "0.5.8"
datatier = { path = "./src/storage/datatier", version = "0.1.0"}
foreign-types-shared = "0.3.1"
httparse = "1.8.0"
libc = "0.2.149"
Expand Down
4 changes: 2 additions & 2 deletions src/entrystore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repository = { workspace = true }
license = { workspace = true }

[features]
debug = ["seg/debug"]
debug = ["segcache/debug"]

[dependencies]
common = { path = "../common" }
Expand All @@ -19,4 +19,4 @@ protocol-common = { path = "../protocol/common" }
protocol-memcache = { path = "../protocol/memcache" }
protocol-ping = { path = "../protocol/ping" }
protocol-resp = { path = "../protocol/resp" }
seg = { path = "../storage/seg" }
segcache = { path = "../storage/segcache" }
4 changes: 2 additions & 2 deletions src/entrystore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
//! [`EntryStore`] and [`protocol::memcache::MemcacheStorage`].
mod noop;
mod seg;
mod segcache;

pub use self::noop::*;
pub use self::seg::*;
pub use self::segcache::*;

/// A trait defining the basic requirements of a type which may be used for
/// storage.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ impl Storage for Seg {
let o = item.optional().unwrap_or(&[0, 0, 0, 0]);
let flags = u32::from_be_bytes([o[0], o[1], o[2], o[3]]);
match item.value() {
seg::Value::Bytes(b) => {
segcache::Value::Bytes(b) => {
values.push(Value::new(item.key(), flags, None, b));
}
seg::Value::U64(v) => {
segcache::Value::U64(v) => {
values.push(Value::new(
item.key(),
flags,
Expand All @@ -67,10 +67,10 @@ impl Storage for Seg {
let o = item.optional().unwrap_or(&[0, 0, 0, 0]);
let flags = u32::from_be_bytes([o[0], o[1], o[2], o[3]]);
match item.value() {
seg::Value::Bytes(b) => {
segcache::Value::Bytes(b) => {
values.push(Value::new(item.key(), flags, Some(item.cas().into()), b));
}
seg::Value::U64(v) => {
segcache::Value::U64(v) => {
values.push(Value::new(
item.key(),
flags,
Expand Down Expand Up @@ -264,23 +264,23 @@ impl Storage for Seg {
fn incr(&mut self, incr: &Incr) -> Response {
match self.data.wrapping_add(incr.key(), incr.value()) {
Ok(item) => match item.value() {
seg::Value::U64(v) => Response::numeric(v, incr.noreply()),
segcache::Value::U64(v) => Response::numeric(v, incr.noreply()),
_ => Response::server_error(""),
},
Err(SegError::NotFound) => Response::not_found(incr.noreply()),
Err(SegError::NotNumeric) => Response::error(),
Err(SegcacheError::NotFound) => Response::not_found(incr.noreply()),
Err(SegcacheError::NotNumeric) => Response::error(),
Err(_) => Response::server_error(""),
}
}

fn decr(&mut self, decr: &Decr) -> Response {
match self.data.saturating_sub(decr.key(), decr.value()) {
Ok(item) => match item.value() {
seg::Value::U64(v) => Response::numeric(v, decr.noreply()),
segcache::Value::U64(v) => Response::numeric(v, decr.noreply()),
_ => Response::server_error(""),
},
Err(SegError::NotFound) => Response::not_found(decr.noreply()),
Err(SegError::NotNumeric) => Response::error(),
Err(SegcacheError::NotFound) => Response::not_found(decr.noreply()),
Err(SegcacheError::NotNumeric) => Response::error(),
Err(_) => Response::server_error(""),
}
}
Expand Down Expand Up @@ -323,8 +323,8 @@ impl Storage for Seg {
cas.cas() as u32,
) {
Ok(_) => Response::stored(cas.noreply()),
Err(SegError::NotFound) => Response::not_found(cas.noreply()),
Err(SegError::Exists) => Response::exists(cas.noreply()),
Err(SegcacheError::NotFound) => Response::not_found(cas.noreply()),
Err(SegcacheError::Exists) => Response::exists(cas.noreply()),
Err(_) => Response::error(),
}
} else {
Expand All @@ -336,8 +336,8 @@ impl Storage for Seg {
cas.cas() as u32,
) {
Ok(_) => Response::stored(cas.noreply()),
Err(SegError::NotFound) => Response::not_found(cas.noreply()),
Err(SegError::Exists) => Response::exists(cas.noreply()),
Err(SegcacheError::NotFound) => Response::not_found(cas.noreply()),
Err(SegcacheError::Exists) => Response::exists(cas.noreply()),
Err(_) => Response::error(),
}
}
Expand All @@ -350,8 +350,8 @@ impl Storage for Seg {
cas.cas() as u32,
) {
Ok(_) => Response::stored(cas.noreply()),
Err(SegError::NotFound) => Response::not_found(cas.noreply()),
Err(SegError::Exists) => Response::exists(cas.noreply()),
Err(SegcacheError::NotFound) => Response::not_found(cas.noreply()),
Err(SegcacheError::Exists) => Response::exists(cas.noreply()),
Err(_) => Response::error(),
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@

//! Segment-structured storage which implements efficient proactive eviction.
//! This storage type is suitable for use in simple key-value cache backends.
//! See: [`::seg`] crate for more details behind the underlying storage design.
//! See: [`::segcache`] crate for more details behind the underlying storage
//! design.
use crate::EntryStore;

use config::seg::Eviction;
use config::SegConfig;
use seg::{Policy, SegError};
use segcache::{Policy, SegcacheError};

mod memcache;
mod resp;

/// A wrapper around [`seg::Seg`] which implements `EntryStore` and storage
/// protocol traits.
pub struct Seg {
data: ::seg::Seg,
data: segcache::Segcache,
}

impl Seg {
Expand All @@ -43,7 +44,7 @@ impl Seg {
};

// build the datastructure from the config
let data = ::seg::Seg::builder()
let data = segcache::Segcache::builder()
.hash_power(config.hash_power())
.overflow_factor(config.overflow_factor())
.heap_size(config.heap_size())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//! storage commands.
use super::*;
use protocol_common::*;

use protocol_common::*;
use protocol_resp::*;

use std::time::Duration;
Expand All @@ -26,16 +26,16 @@ impl Storage for Seg {
fn get(&mut self, get: &Get) -> Response {
if let Some(item) = self.data.get(get.key()) {
match item.value() {
seg::Value::Bytes(b) => Response::bulk_string(b),
seg::Value::U64(v) => Response::bulk_string(format!("{v}").as_bytes()),
segcache::Value::Bytes(b) => Response::bulk_string(b),
segcache::Value::U64(v) => Response::bulk_string(format!("{v}").as_bytes()),
}
} else {
Response::null()
}
}

fn set(&mut self, set: &Set) -> Response {
let ttl = match set.expire_time().unwrap_or(ExpireTime::default()) {
let ttl = match set.expire_time().unwrap_or_default() {
ExpireTime::Seconds(n) => n,
_ => 0,
};
Expand Down
2 changes: 1 addition & 1 deletion src/server/segcache/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "segcache"
name = "pelikan-segcache"
description = "a Memcache protocol server with segment-structured storage"
authors = ["Brian Martin <[email protected]>"]

Expand Down
File renamed without changes.
18 changes: 10 additions & 8 deletions src/storage/seg/Cargo.toml → src/storage/segcache/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[package]
name = "seg"
description = "segment-structured in-memory storage with eager expiration"
name = "segcache"
version = "0.1.0"
description = "Pelikan segment-structured cache"
authors = ["Brian Martin <[email protected]>"]

version = { workspace = true }
edition = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
Expand All @@ -19,22 +19,24 @@ harness = false
# enables setting/checking magic strings
magic = []

# enables metrics
metrics = ["metriken"]

# metafeatures
debug = ["magic"]

# default set of enabled features
default = []
default = ["metrics"]

[dependencies]
ahash = { workspace = true }
clocksource = { workspace = true }
datatier = { path = "../datatier" }
metriken = { workspace = true }
datatier = { workspace = true }
log = { workspace = true }
metriken = { workspace = true, optional = true }
rand = { workspace = true , features = ["small_rng", "getrandom"] }
rand_chacha = { workspace = true }
rand_xoshiro = { workspace = true }
ringlog = { workspace = true }
storage-types = { path = "../types" }
thiserror = { workspace = true }

[dev-dependencies]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
use rand::RngCore;
use rand::SeedableRng;
use seg::*;
use segcache::*;

use std::time::Duration;

Expand All @@ -25,7 +25,7 @@ fn get_benchmark(c: &mut Criterion) {
let (keys, _values) = key_values(*key_size, 1_000_000, 0, 0);

// launch the server
let mut cache = Seg::builder()
let mut cache = Segcache::builder()
.hash_power(16)
.heap_size(64 * MB)
.segment_size(MB as i32)
Expand Down Expand Up @@ -82,7 +82,7 @@ fn set_benchmark(c: &mut Criterion) {
let (keys, values) = key_values(*key_size, 1_000_000, *value_size, 10_000);

// launch the server
let mut cache = Seg::builder()
let mut cache = Segcache::builder()
.hash_power(16)
.heap_size(64 * MB)
.segment_size(MB as i32)
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "storage-seg-fuzz"
name = "storage-segcache-fuzz"
version = "0.0.0"
authors = ["Automatically generated"]
publish = false
Expand All @@ -11,15 +11,15 @@ cargo-fuzz = true
[dependencies]
libfuzzer-sys = "0.4"

[dependencies.seg]
[dependencies.segcache]
path = ".."

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[[bin]]
name = "seg"
path = "fuzz_targets/seg.rs"
name = "segcache"
path = "fuzz_targets/segcache.rs"
test = false
doc = false
Loading

0 comments on commit dfcbd33

Please sign in to comment.