1use std::io;
15use std::sync::RwLockWriteGuard;
16
17use crate::shard::shard_idx;
18use crate::store::{Inner, Store, commit_write, store_err};
19
20#[cfg(not(target_arch = "wasm32"))]
21use crate::replica_glue::ensure_writable;
22
23#[cfg(target_arch = "wasm32")]
24fn ensure_writable(_s: &Store) -> io::Result<()> { Ok(()) }
25
26pub struct AtomicAllShards<'a> {
29 guards: Vec<RwLockWriteGuard<'a, Inner>>,
30 log: Vec<(usize, Vec<Vec<u8>>)>,
32}
33
34impl<'a> AtomicAllShards<'a> {
35 fn idx(&self, key: &[u8]) -> usize {
36 shard_idx(key, self.guards.len())
37 }
38
39 fn log_arg(&mut self, idx: usize, parts: &[&[u8]]) {
40 self.log
41 .push((idx, parts.iter().map(|p| p.to_vec()).collect()));
42 }
43
44 pub fn set(&mut self, key: &[u8], value: &[u8]) -> bool {
48 let i = self.idx(key);
49 let ok = self.guards[i]
50 .store
51 .set(key, value.to_vec(), None, false, false);
52 self.log_arg(i, &[b"SET", key, value]);
53 ok
54 }
55
56 pub fn get(&mut self, key: &[u8]) -> io::Result<Option<Vec<u8>>> {
58 let i = self.idx(key);
59 self.guards[i]
60 .store
61 .get(key)
62 .map(|opt| opt.as_deref().map(<[u8]>::to_vec))
63 .map_err(store_err)
64 }
65
66 pub fn incr(&mut self, key: &[u8]) -> io::Result<i64> {
68 let i = self.idx(key);
69 let n = self.guards[i].store.incr_by(key, 1).map_err(store_err)?;
70 self.log_arg(i, &[b"INCR", key]);
71 Ok(n)
72 }
73
74 pub fn incr_by(&mut self, key: &[u8], delta: i64) -> io::Result<i64> {
76 let i = self.idx(key);
77 let n = self.guards[i].store.incr_by(key, delta).map_err(store_err)?;
78 let s = format!("{delta}");
79 self.log_arg(i, &[b"INCRBY", key, s.as_bytes()]);
80 Ok(n)
81 }
82
83 pub fn hset(&mut self, key: &[u8], pairs: &[(&[u8], &[u8])]) -> io::Result<usize> {
88 let i = self.idx(key);
89 let owned: Vec<(Vec<u8>, Vec<u8>)> = pairs
90 .iter()
91 .map(|(f, v)| (f.to_vec(), v.to_vec()))
92 .collect();
93 let n = self.guards[i]
94 .store
95 .hset(key, &owned)
96 .map_err(store_err)?;
97 let mut parts: Vec<&[u8]> = Vec::with_capacity(2 + pairs.len() * 2);
98 parts.push(b"HSET");
99 parts.push(key);
100 for (f, v) in pairs {
101 parts.push(f);
102 parts.push(v);
103 }
104 self.log_arg(i, &parts);
105 Ok(n)
106 }
107
108 pub fn hget(&mut self, key: &[u8], field: &[u8]) -> io::Result<Option<Vec<u8>>> {
110 let i = self.idx(key);
111 Ok(self.guards[i]
112 .store
113 .hget(key, field)
114 .map_err(store_err)?
115 .map(<[u8]>::to_vec))
116 }
117
118 pub fn hincrby(&mut self, key: &[u8], field: &[u8], delta: i64) -> io::Result<i64> {
120 let i = self.idx(key);
121 let n = self.guards[i]
122 .store
123 .hincrby(key, field, delta)
124 .map_err(store_err)?;
125 let s = format!("{delta}");
126 self.log_arg(i, &[b"HINCRBY", key, field, s.as_bytes()]);
127 Ok(n)
128 }
129
130 pub fn zadd(&mut self, key: &[u8], pairs: &[(f64, &[u8])]) -> io::Result<usize> {
135 let i = self.idx(key);
136 let owned: Vec<(f64, Vec<u8>)> =
137 pairs.iter().map(|(s, m)| (*s, m.to_vec())).collect();
138 let n = self.guards[i]
139 .store
140 .zadd(key, &owned)
141 .map_err(store_err)?;
142 let score_strs: Vec<Vec<u8>> = pairs
143 .iter()
144 .map(|(s, _)| format!("{s}").into_bytes())
145 .collect();
146 let mut parts: Vec<&[u8]> = Vec::with_capacity(2 + pairs.len() * 2);
147 parts.push(b"ZADD");
148 parts.push(key);
149 for (j, (_, m)) in pairs.iter().enumerate() {
150 parts.push(&score_strs[j]);
151 parts.push(m);
152 }
153 self.log_arg(i, &parts);
154 Ok(n)
155 }
156
157 pub fn zincrby(&mut self, key: &[u8], delta: f64, member: &[u8]) -> io::Result<f64> {
159 let i = self.idx(key);
160 let n = self.guards[i]
161 .store
162 .zincrby(key, delta, member)
163 .map_err(store_err)?;
164 let s = format!("{delta}");
165 self.log_arg(i, &[b"ZINCRBY", key, s.as_bytes(), member]);
166 Ok(n)
167 }
168
169 pub fn zscore(&mut self, key: &[u8], member: &[u8]) -> io::Result<Option<f64>> {
171 let i = self.idx(key);
172 self.guards[i].store.zscore(key, member).map_err(store_err)
173 }
174
175 pub fn del(&mut self, keys: &[&[u8]]) -> usize {
180 let mut n = 0;
181 for k in keys {
182 let i = self.idx(k);
183 if self.guards[i].store.del_borrowed(&[k]) > 0 {
184 n += 1;
185 self.log_arg(i, &[b"DEL", k]);
186 }
187 }
188 n
189 }
190
191 pub fn exists(&mut self, keys: &[&[u8]]) -> usize {
193 keys.iter()
194 .filter(|k| {
195 let i = self.idx(k);
196 self.guards[i].store.key_exists(k)
197 })
198 .count()
199 }
200
201 pub fn hdel(&mut self, key: &[u8], fields: &[&[u8]]) -> io::Result<usize> {
205 let i = self.idx(key);
206 let owned: Vec<Vec<u8>> = fields.iter().map(|f| f.to_vec()).collect();
207 let removed = self.guards[i].store.hdel(key, &owned).map_err(store_err)?;
208 if removed > 0 {
209 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + fields.len());
210 argv.push(b"HDEL");
211 argv.push(key);
212 argv.extend_from_slice(fields);
213 self.log_arg(i, &argv);
214 }
215 Ok(removed)
216 }
217
218 pub fn hgetall(&mut self, key: &[u8]) -> io::Result<Vec<(Vec<u8>, Vec<u8>)>> {
220 let i = self.idx(key);
221 let flat = self.guards[i].store.hgetall(key).map_err(store_err)?;
222 let mut out = Vec::with_capacity(flat.len() / 2);
223 let mut it = flat.into_iter();
224 while let (Some(f), Some(v)) = (it.next(), it.next()) {
225 out.push((f, v));
226 }
227 Ok(out)
228 }
229
230 pub fn hmget(&mut self, key: &[u8], fields: &[&[u8]]) -> io::Result<Vec<Option<Vec<u8>>>> {
232 let i = self.idx(key);
233 self.guards[i].store.hmget_borrowed(key, fields).map_err(store_err)
234 }
235
236 pub fn hexists(&mut self, key: &[u8], field: &[u8]) -> io::Result<bool> {
238 let i = self.idx(key);
239 self.guards[i].store.hexists(key, field).map_err(store_err)
240 }
241
242 pub fn sadd(&mut self, key: &[u8], members: &[&[u8]]) -> io::Result<usize> {
246 let i = self.idx(key);
247 let owned: Vec<Vec<u8>> = members.iter().map(|m| m.to_vec()).collect();
248 let added = self.guards[i].store.sadd(key, &owned).map_err(store_err)?;
249 if added > 0 {
250 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + members.len());
251 argv.push(b"SADD");
252 argv.push(key);
253 argv.extend_from_slice(members);
254 self.log_arg(i, &argv);
255 }
256 Ok(added)
257 }
258
259 pub fn srem(&mut self, key: &[u8], members: &[&[u8]]) -> io::Result<usize> {
261 let i = self.idx(key);
262 let owned: Vec<Vec<u8>> = members.iter().map(|m| m.to_vec()).collect();
263 let removed = self.guards[i].store.srem(key, &owned).map_err(store_err)?;
264 if removed > 0 {
265 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + members.len());
266 argv.push(b"SREM");
267 argv.push(key);
268 argv.extend_from_slice(members);
269 self.log_arg(i, &argv);
270 }
271 Ok(removed)
272 }
273
274 pub fn lpush(&mut self, key: &[u8], values: &[&[u8]]) -> io::Result<usize> {
278 let i = self.idx(key);
279 let owned: Vec<Vec<u8>> = values.iter().map(|v| v.to_vec()).collect();
280 let len = self.guards[i].store.lpush(key, &owned).map_err(store_err)?;
281 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + values.len());
282 argv.push(b"LPUSH");
283 argv.push(key);
284 argv.extend_from_slice(values);
285 self.log_arg(i, &argv);
286 Ok(len)
287 }
288
289 pub fn rpush(&mut self, key: &[u8], values: &[&[u8]]) -> io::Result<usize> {
291 let i = self.idx(key);
292 let owned: Vec<Vec<u8>> = values.iter().map(|v| v.to_vec()).collect();
293 let len = self.guards[i].store.rpush(key, &owned).map_err(store_err)?;
294 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + values.len());
295 argv.push(b"RPUSH");
296 argv.push(key);
297 argv.extend_from_slice(values);
298 self.log_arg(i, &argv);
299 Ok(len)
300 }
301
302 pub fn zrem(&mut self, key: &[u8], members: &[&[u8]]) -> io::Result<usize> {
306 let i = self.idx(key);
307 let owned: Vec<Vec<u8>> = members.iter().map(|m| m.to_vec()).collect();
308 let removed = self.guards[i].store.zrem(key, &owned).map_err(store_err)?;
309 if removed > 0 {
310 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + members.len());
311 argv.push(b"ZREM");
312 argv.push(key);
313 argv.extend_from_slice(members);
314 self.log_arg(i, &argv);
315 }
316 Ok(removed)
317 }
318
319 pub fn zcard(&mut self, key: &[u8]) -> io::Result<usize> {
321 let i = self.idx(key);
322 self.guards[i].store.zcard(key).map_err(store_err)
323 }
324
325 pub fn zadd_flags(
328 &mut self,
329 key: &[u8],
330 pairs: &[(f64, &[u8])],
331 flags: kevy_store::ZaddFlags,
332 ) -> io::Result<kevy_store::ZaddReport> {
333 if !flags.valid() {
334 return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid ZADD flag combo"));
335 }
336 let i = self.idx(key);
337 let rep = self.guards[i]
338 .store
339 .zadd_flags_borrowed(key, pairs, flags)
340 .map_err(store_err)?;
341 if !rep.applied.is_empty() {
342 let score_strs: Vec<Vec<u8>> = rep
343 .applied
344 .iter()
345 .map(|(s, _)| format!("{s}").into_bytes())
346 .collect();
347 let mut parts: Vec<&[u8]> = Vec::with_capacity(2 + rep.applied.len() * 2);
348 parts.push(b"ZADD");
349 parts.push(key);
350 for (j, (_, m)) in rep.applied.iter().enumerate() {
351 parts.push(&score_strs[j]);
352 parts.push(m);
353 }
354 self.log_arg(i, &parts);
355 }
356 Ok(rep)
357 }
358}
359
360impl Store {
361 pub fn atomic_all_shards<R>(
370 &self,
371 body: impl FnOnce(&mut AtomicAllShards<'_>) -> io::Result<R>,
372 ) -> io::Result<R> {
373 ensure_writable(self)?;
374 let guards: Vec<RwLockWriteGuard<'_, Inner>> = self
377 .shards
378 .iter()
379 .map(|s| s.write().expect("lock poisoned"))
380 .collect();
381 let mut ctx = AtomicAllShards { guards, log: Vec::new() };
382 let r = body(&mut ctx)?;
383 let log = std::mem::take(&mut ctx.log);
385 for (idx, parts) in log {
386 let g = &mut ctx.guards[idx];
387 let refs: Vec<&[u8]> = parts.iter().map(|v| v.as_slice()).collect();
388 commit_write(g, &refs)?;
389 }
390 Ok(r)
391 }
392}
393
394#[cfg_attr(not(test), allow(dead_code))]
398pub(crate) const ATOMIC_ALL_OPS: &[&str] = &[
399 "SET", "GET", "INCR", "INCRBY", "HSET", "HGET", "HINCRBY", "ZADD",
400 "ZINCRBY", "ZSCORE", "DEL", "EXISTS", "HDEL", "HGETALL", "HMGET",
401 "HEXISTS", "SADD", "SREM", "LPUSH", "RPUSH", "ZREM", "ZCARD",
402];