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> {
86 let i = self.idx(key);
87 let owned: Vec<(Vec<u8>, Vec<u8>)> = pairs
88 .iter()
89 .map(|(f, v)| (f.to_vec(), v.to_vec()))
90 .collect();
91 let n = self.guards[i]
92 .store
93 .hset(key, &owned)
94 .map_err(store_err)?;
95 let mut parts: Vec<&[u8]> = Vec::with_capacity(2 + pairs.len() * 2);
96 parts.push(b"HSET");
97 parts.push(key);
98 for (f, v) in pairs {
99 parts.push(f);
100 parts.push(v);
101 }
102 self.log_arg(i, &parts);
103 Ok(n)
104 }
105
106 pub fn hget(&mut self, key: &[u8], field: &[u8]) -> io::Result<Option<Vec<u8>>> {
107 let i = self.idx(key);
108 Ok(self.guards[i]
109 .store
110 .hget(key, field)
111 .map_err(store_err)?
112 .map(<[u8]>::to_vec))
113 }
114
115 pub fn hincrby(&mut self, key: &[u8], field: &[u8], delta: i64) -> io::Result<i64> {
116 let i = self.idx(key);
117 let n = self.guards[i]
118 .store
119 .hincrby(key, field, delta)
120 .map_err(store_err)?;
121 let s = format!("{delta}");
122 self.log_arg(i, &[b"HINCRBY", key, field, s.as_bytes()]);
123 Ok(n)
124 }
125
126 pub fn zadd(&mut self, key: &[u8], pairs: &[(f64, &[u8])]) -> io::Result<usize> {
129 let i = self.idx(key);
130 let owned: Vec<(f64, Vec<u8>)> =
131 pairs.iter().map(|(s, m)| (*s, m.to_vec())).collect();
132 let n = self.guards[i]
133 .store
134 .zadd(key, &owned)
135 .map_err(store_err)?;
136 let score_strs: Vec<Vec<u8>> = pairs
137 .iter()
138 .map(|(s, _)| format!("{s}").into_bytes())
139 .collect();
140 let mut parts: Vec<&[u8]> = Vec::with_capacity(2 + pairs.len() * 2);
141 parts.push(b"ZADD");
142 parts.push(key);
143 for (j, (_, m)) in pairs.iter().enumerate() {
144 parts.push(&score_strs[j]);
145 parts.push(m);
146 }
147 self.log_arg(i, &parts);
148 Ok(n)
149 }
150
151 pub fn zincrby(&mut self, key: &[u8], delta: f64, member: &[u8]) -> io::Result<f64> {
152 let i = self.idx(key);
153 let n = self.guards[i]
154 .store
155 .zincrby(key, delta, member)
156 .map_err(store_err)?;
157 let s = format!("{delta}");
158 self.log_arg(i, &[b"ZINCRBY", key, s.as_bytes(), member]);
159 Ok(n)
160 }
161
162 pub fn zscore(&mut self, key: &[u8], member: &[u8]) -> io::Result<Option<f64>> {
164 let i = self.idx(key);
165 self.guards[i].store.zscore(key, member).map_err(store_err)
166 }
167
168 pub fn del(&mut self, keys: &[&[u8]]) -> usize {
173 let mut n = 0;
174 for k in keys {
175 let i = self.idx(k);
176 if self.guards[i].store.del_borrowed(&[k]) > 0 {
177 n += 1;
178 self.log_arg(i, &[b"DEL", k]);
179 }
180 }
181 n
182 }
183
184 pub fn exists(&mut self, keys: &[&[u8]]) -> usize {
186 keys.iter()
187 .filter(|k| {
188 let i = self.idx(k);
189 self.guards[i].store.key_exists(k)
190 })
191 .count()
192 }
193
194 pub fn hdel(&mut self, key: &[u8], fields: &[&[u8]]) -> io::Result<usize> {
198 let i = self.idx(key);
199 let owned: Vec<Vec<u8>> = fields.iter().map(|f| f.to_vec()).collect();
200 let removed = self.guards[i].store.hdel(key, &owned).map_err(store_err)?;
201 if removed > 0 {
202 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + fields.len());
203 argv.push(b"HDEL");
204 argv.push(key);
205 argv.extend_from_slice(fields);
206 self.log_arg(i, &argv);
207 }
208 Ok(removed)
209 }
210
211 pub fn hgetall(&mut self, key: &[u8]) -> io::Result<Vec<(Vec<u8>, Vec<u8>)>> {
213 let i = self.idx(key);
214 let flat = self.guards[i].store.hgetall(key).map_err(store_err)?;
215 let mut out = Vec::with_capacity(flat.len() / 2);
216 let mut it = flat.into_iter();
217 while let (Some(f), Some(v)) = (it.next(), it.next()) {
218 out.push((f, v));
219 }
220 Ok(out)
221 }
222
223 pub fn hmget(&mut self, key: &[u8], fields: &[&[u8]]) -> io::Result<Vec<Option<Vec<u8>>>> {
225 let i = self.idx(key);
226 self.guards[i].store.hmget_borrowed(key, fields).map_err(store_err)
227 }
228
229 pub fn hexists(&mut self, key: &[u8], field: &[u8]) -> io::Result<bool> {
231 let i = self.idx(key);
232 self.guards[i].store.hexists(key, field).map_err(store_err)
233 }
234
235 pub fn sadd(&mut self, key: &[u8], members: &[&[u8]]) -> io::Result<usize> {
239 let i = self.idx(key);
240 let owned: Vec<Vec<u8>> = members.iter().map(|m| m.to_vec()).collect();
241 let added = self.guards[i].store.sadd(key, &owned).map_err(store_err)?;
242 if added > 0 {
243 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + members.len());
244 argv.push(b"SADD");
245 argv.push(key);
246 argv.extend_from_slice(members);
247 self.log_arg(i, &argv);
248 }
249 Ok(added)
250 }
251
252 pub fn srem(&mut self, key: &[u8], members: &[&[u8]]) -> io::Result<usize> {
254 let i = self.idx(key);
255 let owned: Vec<Vec<u8>> = members.iter().map(|m| m.to_vec()).collect();
256 let removed = self.guards[i].store.srem(key, &owned).map_err(store_err)?;
257 if removed > 0 {
258 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + members.len());
259 argv.push(b"SREM");
260 argv.push(key);
261 argv.extend_from_slice(members);
262 self.log_arg(i, &argv);
263 }
264 Ok(removed)
265 }
266
267 pub fn lpush(&mut self, key: &[u8], values: &[&[u8]]) -> io::Result<usize> {
271 let i = self.idx(key);
272 let owned: Vec<Vec<u8>> = values.iter().map(|v| v.to_vec()).collect();
273 let len = self.guards[i].store.lpush(key, &owned).map_err(store_err)?;
274 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + values.len());
275 argv.push(b"LPUSH");
276 argv.push(key);
277 argv.extend_from_slice(values);
278 self.log_arg(i, &argv);
279 Ok(len)
280 }
281
282 pub fn rpush(&mut self, key: &[u8], values: &[&[u8]]) -> io::Result<usize> {
284 let i = self.idx(key);
285 let owned: Vec<Vec<u8>> = values.iter().map(|v| v.to_vec()).collect();
286 let len = self.guards[i].store.rpush(key, &owned).map_err(store_err)?;
287 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + values.len());
288 argv.push(b"RPUSH");
289 argv.push(key);
290 argv.extend_from_slice(values);
291 self.log_arg(i, &argv);
292 Ok(len)
293 }
294
295 pub fn zrem(&mut self, key: &[u8], members: &[&[u8]]) -> io::Result<usize> {
299 let i = self.idx(key);
300 let owned: Vec<Vec<u8>> = members.iter().map(|m| m.to_vec()).collect();
301 let removed = self.guards[i].store.zrem(key, &owned).map_err(store_err)?;
302 if removed > 0 {
303 let mut argv: Vec<&[u8]> = Vec::with_capacity(2 + members.len());
304 argv.push(b"ZREM");
305 argv.push(key);
306 argv.extend_from_slice(members);
307 self.log_arg(i, &argv);
308 }
309 Ok(removed)
310 }
311
312 pub fn zcard(&mut self, key: &[u8]) -> io::Result<usize> {
314 let i = self.idx(key);
315 self.guards[i].store.zcard(key).map_err(store_err)
316 }
317
318 pub fn zadd_flags(
321 &mut self,
322 key: &[u8],
323 pairs: &[(f64, &[u8])],
324 flags: kevy_store::ZaddFlags,
325 ) -> io::Result<kevy_store::ZaddReport> {
326 if !flags.valid() {
327 return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid ZADD flag combo"));
328 }
329 let i = self.idx(key);
330 let rep = self.guards[i]
331 .store
332 .zadd_flags_borrowed(key, pairs, flags)
333 .map_err(store_err)?;
334 if !rep.applied.is_empty() {
335 let score_strs: Vec<Vec<u8>> = rep
336 .applied
337 .iter()
338 .map(|(s, _)| format!("{s}").into_bytes())
339 .collect();
340 let mut parts: Vec<&[u8]> = Vec::with_capacity(2 + rep.applied.len() * 2);
341 parts.push(b"ZADD");
342 parts.push(key);
343 for (j, (_, m)) in rep.applied.iter().enumerate() {
344 parts.push(&score_strs[j]);
345 parts.push(m);
346 }
347 self.log_arg(i, &parts);
348 }
349 Ok(rep)
350 }
351}
352
353impl Store {
354 pub fn atomic_all_shards<R>(
363 &self,
364 body: impl FnOnce(&mut AtomicAllShards<'_>) -> io::Result<R>,
365 ) -> io::Result<R> {
366 ensure_writable(self)?;
367 let guards: Vec<RwLockWriteGuard<'_, Inner>> = self
370 .shards
371 .iter()
372 .map(|s| s.write().expect("lock poisoned"))
373 .collect();
374 let mut ctx = AtomicAllShards { guards, log: Vec::new() };
375 let r = body(&mut ctx)?;
376 let log = std::mem::take(&mut ctx.log);
378 for (idx, parts) in log {
379 let g = &mut ctx.guards[idx];
380 let refs: Vec<&[u8]> = parts.iter().map(|v| v.as_slice()).collect();
381 commit_write(g, &refs)?;
382 }
383 Ok(r)
384 }
385}
386
387#[cfg_attr(not(test), allow(dead_code))]
391pub(crate) const ATOMIC_ALL_OPS: &[&str] = &[
392 "SET", "GET", "INCR", "INCRBY", "HSET", "HGET", "HINCRBY", "ZADD",
393 "ZINCRBY", "ZSCORE", "DEL", "EXISTS", "HDEL", "HGETALL", "HMGET",
394 "HEXISTS", "SADD", "SREM", "LPUSH", "RPUSH", "ZREM", "ZCARD",
395];