use crate::aof::{emit_aof_incr, emit_aof_mset, emit_aof_rename, emit_aof_set, AofHandle};
use crate::protocol::{write_array_len, write_bulk, write_integer, write_null, write_simple, Cmd, Value};
use crate::storage::Dict;
use bytes::BytesMut;
#[repr(align(64))]
pub struct Shard {
pub id: usize,
pub dict: Dict,
pub aof: Option<AofHandle>,
}
impl Shard {
pub fn new(id: usize, aof: Option<AofHandle>) -> Self {
Self {
id,
dict: Dict::default(),
aof,
}
}
pub fn exec(&self, cmd: Cmd, out: &mut BytesMut) {
match cmd {
Cmd::Ping => write_simple("PONG", out),
Cmd::Get(k) => match self.dict.get(&k) {
Some(Value::Str(v)) | Some(Value::Blob(v)) => write_bulk(&v, out),
Some(Value::Int(i)) => write_bulk(i.to_string().as_bytes(), out),
None => write_null(out),
},
Cmd::Set(k, v) => {
if let Some(a) = &self.aof {
a.write(&emit_aof_set(&k, &v));
}
let val = if v.len() <= 20 && !v.is_empty() && (v[0].is_ascii_digit() || v[0] == b'-') {
if let Ok(s) = std::str::from_utf8(&v) {
if let Ok(i) = s.parse::<i64>() {
Value::Int(i)
} else {
Value::Str(v)
}
} else {
Value::Str(v)
}
} else {
Value::Str(v)
};
self.dict.set(k, val);
write_simple("OK", out);
}
Cmd::Del(k) => {
let removed = self.dict.del(&k) as i64;
write_integer(removed, out);
}
Cmd::Rename(from, to) => {
if self.aof.is_some() {
let ok = self.dict.rename(from.clone(), to.clone());
if ok {
if let Some(a) = &self.aof {
a.write(&emit_aof_rename(&from, &to));
}
write_simple("OK", out);
} else {
write_simple("ERR no such key", out);
}
} else {
let ok = self.dict.rename(from, to);
if ok {
write_simple("OK", out);
} else {
write_simple("ERR no such key", out);
}
}
}
Cmd::Exists(k) => write_integer(self.dict.exists(&k) as i64, out),
Cmd::Incr(k) => {
let v = self.dict.incr(&k);
if let Some(a) = &self.aof {
a.write(&emit_aof_incr(&k));
}
write_integer(v, out);
}
Cmd::MGet(keys) => {
write_array_len(keys.len(), out);
for k in keys {
match self.dict.get(&k) {
Some(Value::Str(v)) | Some(Value::Blob(v)) => write_bulk(&v, out),
Some(Value::Int(i)) => write_bulk(i.to_string().as_bytes(), out),
None => write_null(out),
}
}
}
Cmd::MSet(pairs) => {
if let Some(a) = &self.aof {
a.write(&emit_aof_mset(&pairs));
}
for (k, v) in pairs {
let val = if v.len() <= 20 && !v.is_empty() && (v[0].is_ascii_digit() || v[0] == b'-') {
if let Ok(s) = std::str::from_utf8(&v) {
if let Ok(i) = s.parse::<i64>() {
Value::Int(i)
} else {
Value::Str(v)
}
} else {
Value::Str(v)
}
} else {
Value::Str(v)
};
self.dict.set(k, val);
}
write_simple("OK", out);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_shard_alignment() {
assert_eq!(std::mem::align_of::<Shard>(), 64, "Shard struct should be aligned to 64 bytes");
}
}