use std::io;
use std::path::Path;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Routing {
KevyHash,
Slots,
}
impl Routing {
fn tag(self) -> &'static str {
match self {
Routing::KevyHash => "kevyhash",
Routing::Slots => "slots",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ShardsMeta {
pub n: usize,
pub routing: Routing,
}
pub fn read_shards_meta(path: &Path) -> Option<ShardsMeta> {
let text = std::fs::read_to_string(path).ok()?;
let mut lines = text.lines();
let n: usize = lines.next()?.trim().parse().ok()?;
let routing = match lines.next().map(str::trim) {
None | Some("") => Routing::KevyHash,
Some("kevyhash") => Routing::KevyHash,
Some("slots") => Routing::Slots,
Some(_) => return None,
};
Some(ShardsMeta { n, routing })
}
pub fn write_shards_meta(path: &Path, meta: ShardsMeta) -> io::Result<()> {
std::fs::write(path, format!("{}\n{}\n", meta.n, meta.routing.tag()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn v2_round_trip() {
let dir = std::env::temp_dir().join(format!("kevy-meta-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let p = dir.join("shards.meta");
for meta in [
ShardsMeta { n: 1, routing: Routing::KevyHash },
ShardsMeta { n: 8, routing: Routing::Slots },
] {
write_shards_meta(&p, meta).unwrap();
assert_eq!(read_shards_meta(&p), Some(meta));
}
std::fs::remove_dir_all(&dir).unwrap();
}
#[test]
fn v1_bare_count_reads_as_kevyhash() {
let dir = std::env::temp_dir().join(format!("kevy-meta-v1-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let p = dir.join("shards.meta");
std::fs::write(&p, "4").unwrap();
assert_eq!(
read_shards_meta(&p),
Some(ShardsMeta { n: 4, routing: Routing::KevyHash })
);
std::fs::write(&p, "4\nfuture-scheme\n").unwrap();
assert_eq!(read_shards_meta(&p), None);
std::fs::remove_dir_all(&dir).unwrap();
}
}