Skip to main content

yo_kv/
keyspace.rs

1//! One database, and the parts of it that are not about any particular type.
2//!
3//! This is the `dict` a Redis `SELECT` picks between, and one of these is what a
4//! shard owns. It was called `Strings` while strings were the only thing in it,
5//! which was accurate for M2 and stopped being accurate the moment a set needed
6//! somewhere to live.
7//!
8//! The commands hang off this as separate `impl` blocks, one file per type, so
9//! that `SET` lives in [`strings`](crate::strings) next to the other twenty five
10//! string commands rather than in a file that is the whole of Redis. They are
11//! methods on the keyspace and not on some per type object because a key belongs
12//! to the database and not to a type: `DEL` does not care what it is deleting,
13//! and `SADD` against a string has to be able to see that it is a string.
14//!
15//! # Not Sync
16//!
17//! Like everything a stripe holds. One of these is worked on by one thread at a
18//! time and the lock around it is what says which, so nothing in here takes a
19//! lock or an atomic of its own.
20//!
21//! It is `Send`, because which thread that is changes from one command to the
22//! next: a stripe goes to whoever takes it. Nothing in here is tied to a
23//! particular thread, and the arena underneath says the same thing for the same
24//! reason.
25
26use std::sync::atomic::{AtomicU64, Ordering};
27
28use yo_common::{Addr, Code, Error, Result, Rng, bytes_eq};
29use yo_index::RawMap;
30
31use crate::Clock;
32use crate::access::{Access, Lfu, Policy};
33use crate::array::Array;
34use crate::cold::Store;
35use crate::evict;
36use crate::foreign::Foreign;
37use crate::hash::{self, Hash};
38use crate::list::{self, List};
39use crate::set::{self, Set};
40use crate::slab::{Bytes, Slab};
41use crate::stream::{self, Stream};
42use crate::tier::{self, Faulted, Relief, Tier};
43use crate::ttl::{self, Applied, Ask, Cond};
44use crate::value::{self, Kind, Str};
45use crate::zset::{self, Zset};
46
47/// Every collection already answered this question, and this is the answer said
48/// once more in a shape the slab can ask for without knowing what it is holding.
49///
50/// Here rather than in the five type files because it is one fact about the
51/// keyspace and not five facts about five types, and because a reader looking
52/// for how the memory total is kept should find it next to the slabs it counts.
53macro_rules! bytes {
54    ($($t:ty),*) => { $(impl Bytes for $t {
55        #[inline]
56        fn memory_bytes(&self) -> usize {
57            <$t>::memory_bytes(self)
58        }
59    })* };
60}
61bytes!(Set, Hash, List, Zset, Array, Stream);
62
63/// A foreign body counts what it says it counts, plus the box around it.
64///
65/// Not through the macro, because the macro calls an inherent method of the
66/// same name and this one is a trait method reached through a vtable. The
67/// pointer itself is two words on top of whatever the engine reports, which is
68/// the price of the escape and is worth naming rather than losing.
69impl Bytes for Box<dyn Foreign> {
70    #[inline]
71    fn memory_bytes(&self) -> usize {
72        self.as_ref().memory_bytes() + std::mem::size_of::<Box<dyn Foreign>>()
73    }
74}
75
76/// One database: every key, whatever type it holds.
77pub struct Keyspace {
78    pub(crate) map: RawMap,
79    pub(crate) clock: Clock,
80    /// Keys that were found dead on the way to answering something else.
81    pub(crate) expired: u64,
82    /// Keys thrown away to make room, which is a different number entirely.
83    ///
84    /// Redis keeps `expired_keys` and `evicted_keys` apart in `INFO` and the
85    /// distinction is the one people watch: expiry is the client getting what it
86    /// asked for, and eviction is the server deciding it cannot keep a promise
87    /// nobody asked it to break.
88    pub(crate) evicted: u64,
89    /// Every set in this database, addressed by the number in its record.
90    pub(crate) sets: Slab<Set>,
91    /// Every hash in this database, addressed the same way.
92    ///
93    /// A slab per type rather than one slab of an enum, so that a record's four
94    /// bytes index a `Hash` directly and reaching one is a load and not a load
95    /// followed by a discriminant check. The type tag in the record already
96    /// says which slab to look in, so the discriminant would be a second copy
97    /// of a fact the record has.
98    pub(crate) hashes: Slab<Hash>,
99    /// Every list in this database, addressed the same way.
100    pub(crate) lists: Slab<List>,
101    /// Every sorted set in this database, addressed the same way.
102    pub(crate) zsets: Slab<Zset>,
103    /// Every sparse array in this database, addressed the same way.
104    pub(crate) arrays: Slab<Array>,
105    /// Every stream in this database, addressed the same way.
106    pub(crate) streams: Slab<Stream>,
107    /// Every foreign body in this database, addressed the same way.
108    ///
109    /// A box per slot rather than a value, because the thing in it is not sized
110    /// here and could not be. That is one indirection more than the other
111    /// slabs pay, and it buys the graph, document and vector engines a place in
112    /// the keyspace without this crate depending on any of them. See
113    /// [`crate::foreign`].
114    ///
115    /// Empty on a server that has never held one, which is every server today,
116    /// and an empty slab is three words.
117    pub(crate) foreign: Slab<Box<dyn Foreign>>,
118    /// How many keys hold a body that is in a slab right now.
119    ///
120    /// Not how many hold something that is not a string, which is what it used to
121    /// be and what it still is on a database with no file behind it. A collection
122    /// that has been demoted has no slab slot, so it does not count here, and
123    /// that is what every reader of this number wants: [`Keyspace::free_body`]
124    /// has nothing to free for one, and a sweep has nothing to move.
125    ///
126
127    /// This exists so that a database of nothing but strings, which is every
128    /// benchmark today and most of what `SET` sees, can skip the body check in
129    /// [`Keyspace::free_body`] on one predictable branch against a field that is
130    /// already hot, rather than paying a second lookup per write forever.
131    pub(crate) bodies: usize,
132    /// Where a set changes representation.
133    pub(crate) limits: set::Limits,
134    /// Where a hash changes representation.
135    pub(crate) hash_limits: hash::Limits,
136    /// Where a list changes representation.
137    pub(crate) list_limits: list::Limits,
138    /// Where a sorted set changes representation.
139    pub(crate) zset_limits: zset::Limits,
140    /// Where a stream starts a new node, which is two `CONFIG` values.
141    pub(crate) stream_limits: stream::Limits,
142    /// What this database would evict, and therefore what a read writes back.
143    ///
144    /// One server wide setting in Redis, carried per database here for the same
145    /// reason the size ladder is: a `Keyspace` is reached without a server and
146    /// has to be able to answer on its own. `CONFIG SET maxmemory-policy` writes
147    /// it to all of them.
148    pub(crate) policy: Policy,
149    /// The two numbers the LFU counter moves by, which are `CONFIG` values.
150    pub(crate) lfu: Lfu,
151    /// How many keys a round of eviction sampling looks at.
152    ///
153    /// `maxmemory-samples`, carried per database for the same reason the policy
154    /// is. See [`evict::SAMPLES`] for why the default is five.
155    pub(crate) samples: usize,
156    /// The good candidates from earlier rounds of eviction sampling.
157    ///
158    /// See [`evict::Pool`]. Empty and costing nothing until the first eviction,
159    /// which on most databases is never.
160    pub(crate) pool: evict::Pool,
161    /// Where `SPOP` and `SRANDMEMBER` draw from.
162    pub(crate) rng: Rng,
163    /// Where a demoted value goes and comes back from, if this database has one.
164    ///
165    /// `None` on a database with no file behind it, which is every embedded
166    /// caller that never opened one and every test that does not care, and on
167    /// such a database no record is ever cold and every check against this is a
168    /// null test on a field in the same cache line as the map.
169    ///
170    /// Boxed rather than a type parameter on `Keyspace`. The parameter would
171    /// have to be named by `yo-resp`, by the typed API and by every caller of
172    /// either, all to spell a type that only the code opening the file knows,
173    /// and it would be a parameter on the hot path to describe the cold one. See
174    /// [`Blocks`].
175    pub(crate) tier: Option<Tier<Store>>,
176    /// The last value read off the file, for the read that is being answered.
177    ///
178    /// A demoted value that is served rather than promoted has to live
179    /// somewhere for the length of one command, because the record it came from
180    /// holds an address and the caller was promised bytes. One buffer, cleared
181    /// and refilled, on the same argument as [`Keyspace::scratch`]: a fault is
182    /// already a device read and a malloc on top of it is free by comparison,
183    /// but it is also unnecessary.
184    ///
185    /// It holds the value of the last key that was faulted and nothing says
186    /// which key that was, which is why nothing reads it without having faulted
187    /// in the same call. Everything that does goes through
188    /// [`Keyspace::warm`].
189    pub(crate) cold: Vec<u8>,
190    /// Whose value is in [`Keyspace::cold`].
191    ///
192    /// Only ever read by a debug assertion, and it is there because the failure
193    /// it catches is silent: a read that forgets to warm and then finds a cold
194    /// record would hand back whatever the last fault put in the buffer, which
195    /// is a real value belonging to a different key. A test would see plausible
196    /// bytes and pass. The copy costs a key's worth of memcpy on a path that
197    /// has just read a device, which is nothing next to what it is guarding.
198    pub(crate) cold_key: Vec<u8>,
199    /// A collection body on its way to the file or on its way back.
200    ///
201    /// Not [`Keyspace::cold`], which holds the value of the last string that was
202    /// faulted and is read after the fact by [`Keyspace::value_of`]. This buffer
203    /// is written and consumed inside one call and nothing looks at it
204    /// afterwards, so sharing the other one would mean a `SADD` on a demoted set
205    /// quietly replacing the bytes a `GET` in the same pipeline was about to hand
206    /// back. One `Vec` each, cleared and refilled, is three words of a struct
207    /// that already has a hundred.
208    pub(crate) frozen: Vec<u8>,
209    /// The last collection key that was resolved, for the command behind it.
210    memo: Memo,
211    /// One buffer for the commands that have to hold an element while the
212    /// structure it came out of is being written.
213    ///
214    /// [`Keyspace::lmove`] is the reason this is here: it takes an element out
215    /// of one list and puts it into another, so there is a moment where the
216    /// bytes belong to nothing, and the borrow it would need to avoid that is a
217    /// borrow of two lists at once when the two lists may be the same one. A
218    /// `Vec` per call is the obvious way to cover that moment and it is a malloc
219    /// and a free on a command that a queue sends millions of. This is the same
220    /// `Vec` every time, cleared rather than freed, so the steady state is no
221    /// allocator call at all.
222    ///
223    /// [`Keyspace::append`], [`Keyspace::setrange`] and the string arm of
224    /// [`Keyspace::set_expiry`] use it for the same shape of problem: each of
225    /// them has to hold the old value while it writes the new record, and each
226    /// of them was doing that with a fresh `Vec` of the whole value. They cannot
227    /// overlap, because each one puts the buffer back before it returns and one
228    /// command runs at a time.
229    ///
230    /// It lives on the database and not on the caller because the callers are
231    /// wire handlers that are handed a `&mut Keyspace` and nothing else.
232    ///
233    /// It starts at [`SCRATCH`] bytes rather than empty. An empty one grows on
234    /// the first command that uses it, and that growth is a real allocation on a
235    /// command path even though it happens once. Buying it here, where nobody is
236    /// waiting, makes the rule Y7 enforces true without an exception written for
237    /// it. A value larger than that still grows it, and that one is allocation
238    /// proportional to what the caller sent rather than overhead per command.
239    pub(crate) scratch: Vec<u8>,
240
241    /// The same idea for indices rather than bytes.
242    ///
243    /// `ZRANDMEMBER` with a positive count under the size of the set does a
244    /// partial Fisher-Yates, and that needs the permutation somewhere while it
245    /// draws from it. One buffer, cleared and refilled, rather than one `Vec`
246    /// per call, because sampling is a thing callers do in a loop.
247    ///
248    /// It does not start at a capacity, unlike [`Keyspace::scratch`]. There is
249    /// no size to guess: the buffer has to be as long as the set, so the first
250    /// call on a set larger than anything seen before grows it whatever it was
251    /// given to start with. That growth is proportional to the data rather than
252    /// per command.
253    pub(crate) rows: Vec<usize>,
254
255    /// The tables set algebra fills in, kept rather than built per call.
256    ///
257    /// Same idea again, one level up: a union walks everything into a hash
258    /// table and lets the table be the duplicate check, and building that table
259    /// was the largest single allocation left on any command path. See
260    /// [`setops::Scratch`], which is where the two tables and the argument for
261    /// them live.
262    ///
263    /// It is one table per database and not one per command, so a database that
264    /// has answered a union over a million members holds a million member table
265    /// until it answers a smaller one. That is the trade and it is the right way
266    /// round: the same database had to build that table anyway, and the version
267    /// that threw it away afterwards built it again on the next call.
268    pub(crate) setops: crate::setops::Scratch,
269
270    /// What the last geo search found, kept for the same reason.
271    ///
272    /// A search cannot answer in the order it walks: the nine hash boxes come
273    /// out in hash order and the reply is in distance order, so every candidate
274    /// has to be in hand before the first one can be written. See
275    /// [`crate::geos::Scratch`], which is the two buffers and the argument for
276    /// keeping them here.
277    pub(crate) geo: crate::geos::Scratch,
278}
279
280/// How big [`Keyspace::scratch`] starts.
281///
282/// A kibibyte, which covers a value of any ordinary size and costs one
283/// allocation per database. The number is not tuned and does not need to be: too
284/// small only means the buffer grows once more on some later command, and too
285/// large only means a kibibyte nobody used.
286const SCRATCH: usize = 1024;
287
288/// How many segments one call to [`Keyspace::victim`] will draw from.
289///
290/// A round is a whole segment, and a segment is sixty four buckets of seven
291/// entries each before its overflow chains are counted, so one round almost
292/// always answers. The retries are for the case where a round came back with
293/// nothing usable, which happens when the segment it drew was empty or when a
294/// `volatile` policy filtered out everything in it.
295///
296/// Four rather than more, because a round that comes back with nothing is
297/// telling you something a fifth round will not change. That used to be the
298/// wrong shape for the `volatile` policies, which could draw four rounds of
299/// keys with no deadline on a database that had almost none, on a path where a
300/// client is waiting. Those policies now draw from the second index of just the
301/// keys that carry a deadline, the way Redis draws from `db->expires`, so every
302/// key a round looks at is a key it is allowed to take.
303const ROUNDS: usize = 4;
304
305/// Where the last collection key resolved to, if it still resolves there.
306///
307/// Y13 says a batch of `SADD` on one key should be one table growth check, and
308/// the same argument applies a step earlier: it should be one resolve. A
309/// resolve is a hash, a bucket walk and a record read, and on a hot key every
310/// command in the batch was paying for all three to be told the same answer the
311/// command in front of it got.
312///
313/// One entry and not a cache, because one entry is the shape of the problem.
314/// Single key `SADD` is the case with no spread to exploit, so the only reuse
315/// there is to find is the command immediately before, and a bigger structure
316/// would cost a lookup to avoid a lookup.
317///
318/// It holds a slot rather than reaching the body through an address, because a
319/// slot is an index into the slab for its type and stays right for as long as
320/// the key is there. That is also why nothing here memoizes a string: a string
321/// lives in the record itself and moves when the record does.
322///
323/// It does carry the record's address alongside, and that is safe for a narrower
324/// reason than the slot is. An address is only good until the next write, and
325/// this whole memo is thrown away by the next write, so inside the window where
326/// the memo answers at all the address is exactly as valid as the slot. What it
327/// buys is the eviction stamp: a memo hit skips the probe, and without an address
328/// the stamp would have to put the probe back and there would be no memo left.
329///
330/// What it is worth is measured rather than argued about, by the pair of rows
331/// `engine/sadd` and `engine/sadd-alternating` in `yo-resp`'s `engine` bench.
332/// The second one alternates between two keys, which defeats this on every
333/// command and leaves both keys as warm in the cache as the one key was, so the
334/// difference between the rows is close to this and nothing else. On an Apple M4
335/// it is about nineteen nanoseconds a command, which is 1.25x at pipeline 64.
336struct Memo {
337    /// What the map's write counter said when this was taken.
338    writes: u64,
339    /// Whether there is anything here. Separate from the length because the
340    /// empty key is a key, and `SADD "" m` is a command Redis accepts.
341    live: bool,
342    /// The type the key held, so a hit can still answer `WRONGTYPE`.
343    kind: Kind,
344    /// Where the body is in the slab for `kind`.
345    slot: u32,
346    /// Where the record is, for the stamp a hit still owes.
347    addr: Addr,
348    /// How much of `key` is the key.
349    len: u8,
350    key: [u8; Memo::MAX],
351}
352
353impl Memo {
354    /// The longest key worth remembering.
355    ///
356    /// Thirty two bytes is half a cache line and covers every hot key anyone
357    /// writes down, including the `myset:{tag}` the generators send. A longer
358    /// key is not memoized rather than heap allocated, because the whole point
359    /// of this is to not touch memory it does not have to.
360    const MAX: usize = 32;
361
362    const fn empty() -> Memo {
363        Memo {
364            writes: 0,
365            live: false,
366            kind: Kind::String,
367            slot: 0,
368            addr: Addr::NONE,
369            len: 0,
370            key: [0; Memo::MAX],
371        }
372    }
373
374    /// What `key` resolved to last time, if that answer still stands.
375    ///
376    /// `writes` is the map's counter now. Any write at all since this was taken
377    /// and the answer is thrown away, which is stricter than it has to be and is
378    /// the version that cannot be wrong.
379    #[inline]
380    fn get(&self, writes: u64, key: &[u8]) -> Option<(Kind, u32, Addr)> {
381        if !self.live || self.writes != writes || key.len() != self.len as usize {
382            return None;
383        }
384        // `bytes_eq` and not `==`, which is a call into the platform's `memcmp`
385        // for a key of a length the compiler cannot see. This is the one
386        // comparison the hot key path always does, and on a profile of `SADD`
387        // it was most of what the lookup cost.
388        bytes_eq(&self.key[..key.len()], key).then_some((self.kind, self.slot, self.addr))
389    }
390
391    /// Remember that `key` is at `slot`, in the record at `addr`.
392    #[inline]
393    fn put(&mut self, writes: u64, key: &[u8], kind: Kind, slot: u32, addr: Addr) {
394        if key.len() > Memo::MAX {
395            self.live = false;
396            return;
397        }
398        self.writes = writes;
399        self.live = true;
400        self.kind = kind;
401        self.slot = slot;
402        self.addr = addr;
403        self.len = key.len() as u8;
404        self.key[..key.len()].copy_from_slice(key);
405    }
406}
407
408/// How many databases this process has made.
409///
410/// Mixed into a new database's seed so that the eight shards a server starts in
411/// the same millisecond do not all draw the same members in the same order. It
412/// is the only atomic in this file and it is touched once per database rather
413/// than once per command, so it is not on any path Y1 cares about.
414static MADE: AtomicU64 = AtomicU64::new(0);
415
416impl Keyspace {
417    /// An empty database on the system clock.
418    #[must_use]
419    pub fn new() -> Keyspace {
420        Keyspace::with_clock(Clock::system())
421    }
422
423    /// An empty database on a clock of the caller's choosing.
424    #[must_use]
425    pub fn with_clock(clock: Clock) -> Keyspace {
426        let made = MADE.fetch_add(1, Ordering::Relaxed);
427        let seed = clock.now_ms() ^ made.wrapping_mul(0x9e37_79b9_7f4a_7c15);
428        Keyspace {
429            map: RawMap::new(),
430            clock,
431            expired: 0,
432            evicted: 0,
433            sets: Slab::new(),
434            hashes: Slab::new(),
435            lists: Slab::new(),
436            zsets: Slab::new(),
437            arrays: Slab::new(),
438            streams: Slab::new(),
439            foreign: Slab::new(),
440            bodies: 0,
441            limits: set::Limits::DEFAULT,
442            hash_limits: hash::Limits::DEFAULT,
443            list_limits: list::Limits::default(),
444            zset_limits: zset::Limits::DEFAULT,
445            stream_limits: stream::Limits::default(),
446            policy: Policy::default(),
447            lfu: Lfu::DEFAULT,
448            samples: evict::SAMPLES,
449            pool: evict::Pool::new(),
450            rng: Rng::new(seed),
451            tier: None,
452            cold: Vec::new(),
453            cold_key: Vec::new(),
454            frozen: Vec::new(),
455            memo: Memo::empty(),
456            scratch: Vec::with_capacity(SCRATCH),
457            rows: Vec::new(),
458            setops: crate::setops::Scratch::new(),
459            geo: crate::geos::Scratch::default(),
460        }
461    }
462
463    /// Pin what `SPOP` and `SRANDMEMBER` draw.
464    ///
465    /// A database seeds itself from the clock and a counter, which is what a
466    /// server wants and what a test cannot assert against. Every test in this
467    /// crate that cares which member comes back calls this first, the same way
468    /// every expiry test drives a fixed clock, and for the same reason: the one
469    /// input that makes a result unrepeatable is better handed in than reached
470    /// for.
471    ///
472    /// It is public because reproducing a bug report is the same problem. A
473    /// seed printed in a crash report is worth having somewhere to put.
474    #[inline]
475    pub const fn seed(&mut self, seed: u64) {
476        self.rng = Rng::new(seed);
477    }
478
479    /// The next number from that same stream.
480    ///
481    /// For a command whose value lives in a [`Foreign`] body and so cannot
482    /// reach the draw any other way. `VRANDMEMBER` is the one, and it should be
483    /// as repeatable under [`Keyspace::seed`] as `SRANDMEMBER` is, which it
484    /// would not be if it carried a generator of its own.
485    #[inline]
486    pub const fn random(&mut self) -> u64 {
487        self.rng.next_u64()
488    }
489
490    /// What this database would evict, which is `CONFIG GET maxmemory-policy`.
491    #[inline]
492    #[must_use]
493    pub const fn policy(&self) -> Policy {
494        self.policy
495    }
496
497    /// Change what this database would evict.
498    ///
499    /// Every key already stored keeps whatever is in its access field, which is
500    /// why Redis warns on `OBJECT FREQ` that switching at runtime takes time to
501    /// adjust. Under the new policy those bits mean something else, and the only
502    /// honest thing to do about it is to let them be corrected by use. A key
503    /// nobody has touched since the switch reads as freshly used rather than as
504    /// stale, which is the safe direction: the other one evicts the working set
505    /// on the first pass after an operator changes a setting.
506    ///
507    /// The candidate pool does go, because a score only means anything against
508    /// another score under the same rule and every number in there was worked
509    /// out under the old one.
510    #[inline]
511    pub fn set_policy(&mut self, policy: Policy) {
512        if policy != self.policy {
513            self.pool.clear();
514        }
515        self.policy = policy;
516    }
517
518    /// The two numbers the LFU counter moves by, which are two `CONFIG` values.
519    #[inline]
520    #[must_use]
521    pub const fn lfu(&self) -> Lfu {
522        self.lfu
523    }
524
525    /// Change how fast the LFU counter climbs and decays.
526    #[inline]
527    pub const fn set_lfu(&mut self, lfu: Lfu) {
528        self.lfu = lfu;
529    }
530
531    /// Seconds since `key` was last used, which is `OBJECT IDLETIME`.
532    ///
533    /// `None` for a key that is not there. A key that has never been stamped
534    /// reads as zero rather than as ancient, which is what
535    /// [`Access::is_unset`] is for.
536    ///
537    /// This does not count as a use. Redis looks the key up with its no touch
538    /// flag here, and it has to: a diagnostic that resets the number it reports
539    /// would answer zero every time it was asked.
540    pub fn idle_secs(&mut self, key: &[u8]) -> Option<u64> {
541        let addr = self.live_rec_untouched(key)?;
542        let now = self.clock.now_ms();
543        Some(self.access_at(addr).idle_secs(now))
544    }
545
546    /// How often `key` is used, which is `OBJECT FREQ`.
547    ///
548    /// The eight bit counter, decayed to now, on the same terms as
549    /// [`Keyspace::idle_secs`]: `None` for a key that is not there, and asking
550    /// is not using.
551    ///
552    /// The caller is the one that has to check the policy first. This reports
553    /// what the bits say, and under a policy that is not LFU they say something
554    /// else, which is a refusal on the wire rather than a number.
555    pub fn freq(&mut self, key: &[u8]) -> Option<u8> {
556        let addr = self.live_rec_untouched(key)?;
557        let (now, lfu) = (self.clock.now_ms(), self.lfu);
558        Some(self.access_at(addr).freq(now, lfu))
559    }
560
561    /// Write a record under `key`, with the access field the policy wants on it.
562    ///
563    /// Every record this crate writes goes through here, which is the point of
564    /// it. A record is written fresh whenever a key is created and whenever a
565    /// string's value changes, and a fresh record starts with the blank field
566    /// [`value::write_record`] leaves behind. Blank reads as freshly used, which
567    /// is right at the moment of writing and wrong a minute later, so something
568    /// has to stamp it and this is the only place that knows the clock.
569    ///
570    /// Redis stamps at the same moment, in `createObject`, and for the same
571    /// reason.
572    pub(crate) fn write_rec(
573        &mut self,
574        key: &[u8],
575        len: usize,
576        fill: impl FnOnce(&mut [u8]),
577    ) -> Option<usize> {
578        let a = self.access_for_write(key);
579        // The one bit in the record that says the key has a deadline, handed
580        // straight back to the map. What the map does with it is keep a second
581        // index of just those records, so the expire cycle and the volatile
582        // eviction policies have somewhere to sample from that is not the whole
583        // keyspace. Nothing here counts anything: the map's own count of marked
584        // records is the number, and a number kept in two places is a number
585        // that eventually disagrees with itself.
586        self.map.set_with(
587            key,
588            len,
589            |_| {},
590            |out| {
591                fill(out);
592                value::set_access(out, a);
593                value::has_expiry(out)
594            },
595        )
596    }
597
598    /// Take `key` out of the map, keeping the deadline count right.
599    ///
600    /// The other half of [`Keyspace::write_rec`], and every path that removes a
601    /// record goes through one of the two. That is `DEL`, lazy expiry, eviction
602    /// and the source key of a `RENAME`, and the last one is why this is not
603    /// simply folded into [`Keyspace::drop_key`]: a rename hands the body to the
604    /// destination and must not free it, so it deletes the source record without
605    /// dropping the key, and it still has to be counted.
606    #[inline]
607    pub(crate) fn del_rec(&mut self, key: &[u8]) -> bool {
608        self.map.del(key)
609    }
610
611    /// What the access field of a record about to be written should say.
612    ///
613    /// Under the eight policies that read the field as a clock this is the time,
614    /// with no probe and no thought: writing a key is using it, and under the LRM
615    /// pair writing it is the only thing that counts as using it.
616    ///
617    /// Under LFU it is the counter that is already there, carried across the
618    /// rewrite unchanged. Unchanged rather than incremented, because the lookup
619    /// that resolved the key for this write already counted the access, and
620    /// counting it twice would rank a key that is written more highly than a key
621    /// that is read the same number of times. A key that is not there yet starts
622    /// at [`crate::access::LFU_INIT`], which is where Redis starts a new object.
623    ///
624    /// The probe is the reason this is written as two cases rather than one. It
625    /// is paid only under an LFU policy, so the default policy and every other
626    /// one write a record for exactly what it cost before.
627    fn access_for_write(&mut self, key: &[u8]) -> Access {
628        let now = self.clock.now_ms();
629        if !self.policy.is_lfu() {
630            return Access::lru(now);
631        }
632        match self.map.get(key).and_then(value::access) {
633            Some(a) if !a.is_unset() => a,
634            _ => Access::lfu(now),
635        }
636    }
637
638    /// The access field of the record at `addr`, or the unset one for a record
639    /// written before the field existed.
640    #[inline]
641    fn access_at(&self, addr: Addr) -> Access {
642        value::access(self.map.value_at(addr)).unwrap_or_default()
643    }
644
645    /// Write the access field back to the record at `addr`.
646    ///
647    /// The whole reason the field exists, and it runs on nearly every command,
648    /// so what it does is a load, an arithmetic step and a three byte store into
649    /// a cache line the caller has just read. It does not count as a write to the
650    /// map, because nothing moves and counting it would throw the [`Memo`] away
651    /// once per command. See [`RawMap::value_at_mut`].
652    ///
653    /// The LFU arm reads before it writes, because the counter it produces is a
654    /// function of the counter that is there. The clock arm does not, because the
655    /// time is the time whatever the record used to say.
656    #[inline]
657    fn stamp(&mut self, addr: Addr) {
658        let now = self.clock.now_ms();
659        if self.policy.is_lfu() {
660            let (lfu, current) = (self.lfu, self.access_at(addr));
661            let next = current.touched(now, lfu, &mut self.rng);
662            value::set_access(self.map.value_at_mut(addr), next);
663        } else {
664            value::set_access(self.map.value_at_mut(addr), Access::lru(now));
665        }
666    }
667
668    /// Where a set changes representation, which is three `CONFIG` values.
669    #[inline]
670    pub const fn limits(&self) -> &set::Limits {
671        &self.limits
672    }
673
674    /// Change where a set changes representation.
675    ///
676    /// Moving these does not rewrite the sets that already exist, which is what
677    /// Redis does too: `CONFIG SET set-max-listpack-entries 0` leaves every
678    /// listpack alone and only decides what the next `SADD` builds.
679    #[inline]
680    pub const fn set_limits(&mut self, limits: set::Limits) {
681        self.limits = limits;
682    }
683
684    /// Where a hash changes representation, which is two `CONFIG` values.
685    #[inline]
686    pub const fn hash_limits(&self) -> &hash::Limits {
687        &self.hash_limits
688    }
689
690    /// Change where a hash changes representation.
691    ///
692    /// Same rule as the set: moving these leaves every hash that already exists
693    /// exactly as it is, and only decides what the next `HSET` builds.
694    #[inline]
695    pub const fn set_hash_limits(&mut self, limits: hash::Limits) {
696        self.hash_limits = limits;
697    }
698
699    /// Where a list changes representation, which is one `CONFIG` value.
700    #[inline]
701    pub const fn list_limits(&self) -> &list::Limits {
702        &self.list_limits
703    }
704
705    /// Change where a list changes representation.
706    ///
707    /// Same rule again: this decides what the next `LPUSH` builds and leaves
708    /// every list that already exists alone. `list-max-listpack-size` is one
709    /// number rather than two, and [`list::Limits::of`] is what turns it into
710    /// the pair this holds.
711    #[inline]
712    pub const fn set_list_limits(&mut self, limits: list::Limits) {
713        self.list_limits = limits;
714    }
715
716    /// Where a stream starts a new node, which is two `CONFIG` values.
717    #[inline]
718    pub const fn stream_limits(&self) -> &stream::Limits {
719        &self.stream_limits
720    }
721
722    /// Change where a stream starts a new node.
723    ///
724    /// Same rule as the other four: this decides what the next `XADD` builds
725    /// and leaves every node that is already full exactly as it is, which is
726    /// also what Redis does, since a node is never resized after it is written.
727    #[inline]
728    pub const fn set_stream_limits(&mut self, limits: stream::Limits) {
729        self.stream_limits = limits;
730    }
731
732    /// Where a sorted set changes representation, which is two `CONFIG` values.
733    #[inline]
734    pub const fn zset_limits(&self) -> &zset::Limits {
735        &self.zset_limits
736    }
737
738    /// Change where a sorted set changes representation.
739    ///
740    /// Same rule as the other three: this decides what the next `ZADD` builds
741    /// and leaves every sorted set that already exists exactly as it is.
742    #[inline]
743    pub const fn set_zset_limits(&mut self, limits: zset::Limits) {
744        self.zset_limits = limits;
745    }
746
747    /// The clock expiry compares against.
748    #[inline]
749    pub const fn clock(&self) -> &Clock {
750        &self.clock
751    }
752
753    /// The map underneath, for statistics and for compaction.
754    #[inline]
755    pub const fn map(&self) -> &RawMap {
756        &self.map
757    }
758
759    /// How many keys are stored, including any that are dead and not yet
760    /// noticed. This is Redis's `DBSIZE`, which counts the same way.
761    #[inline]
762    pub fn len(&self) -> usize {
763        self.map.len()
764    }
765
766    /// Whether anything is stored.
767    #[inline]
768    pub fn is_empty(&self) -> bool {
769        self.map.is_empty()
770    }
771
772    /// What `key` holds, or `None` if there is nothing under it.
773    ///
774    /// This is `TYPE`. A key past its deadline is reaped first, so a dead key
775    /// answers `None` and not the type it used to be.
776    ///
777    /// One lookup, because the tag and the deadline are both in the record the
778    /// lookup returned. Reading the kind out before the reap rather than after
779    /// is what keeps it to one.
780    ///
781    /// It does not go through the lookup that stamps, and so it leaves the
782    /// eviction clock where it was, which is right and is worth saying rather than
783    /// leaving to be inferred from the shape of the code. `TYPE` is one of the
784    /// commands Redis looks up with its no touch flag, along with the `OBJECT`
785    /// subcommands underneath this, which read through `reap` for the same
786    /// reason.
787    pub fn kind_of(&mut self, key: &[u8]) -> Option<Kind> {
788        let now = self.clock.now_ms();
789        let (kind, dead) = self
790            .map
791            .get(key)
792            .map(|rec| (value::kind(rec), value::is_expired(rec, now)))?;
793        if dead {
794            self.drop_key(key);
795            self.expired += 1;
796            return None;
797        }
798        Some(kind)
799    }
800
801    /// How a set is represented, or `None` if `key` is not a set.
802    ///
803    /// This follows the slot and asks the body rather than reading the record,
804    /// because the record only holds a number. Putting a copy of the
805    /// representation in the record's two spare encoding bits would mean
806    /// rewriting the record every time a set was promoted, for the sake of a
807    /// command nobody calls in a loop, and would leave two places able to
808    /// disagree about the same fact.
809    /// A demoted set is brought back to answer, which is the one thing this
810    /// costs that the others do not. The word is a property of the body and the
811    /// body is on the device, so there is nothing else to read it off. It is one
812    /// device read for a command nobody sends in a loop, and the alternative is a
813    /// copy of the word in the record's two spare encoding bits with two places
814    /// then able to disagree about it.
815    pub fn set_encoding(&mut self, key: &[u8]) -> Option<set::Encoding> {
816        self.reap(key);
817        let rec = self.map.get(key)?;
818        if value::kind(rec) != Kind::Set {
819            return None;
820        }
821        let cold = value::Meta::from_byte(rec[0]).is_cold();
822        let at = if cold {
823            // The record is given up here, because promotion writes a new one.
824            self.promote_body(key).ok()??
825        } else {
826            value::slot(rec)
827        };
828        Some(self.sets.get(at)?.encoding())
829    }
830
831    /// How a hash is represented, or `None` if `key` is not a hash.
832    ///
833    /// The same shape as [`Keyspace::set_encoding`] and for the same reason: the
834    /// record holds a slot number and the body is the thing that knows which of
835    /// the two it currently is. A demoted hash is brought back to answer, which
836    /// is the same trade the set makes.
837    pub fn hash_encoding(&mut self, key: &[u8]) -> Option<hash::Encoding> {
838        self.reap(key);
839        let rec = self.map.get(key)?;
840        if value::kind(rec) != Kind::Hash {
841            return None;
842        }
843        let cold = value::Meta::from_byte(rec[0]).is_cold();
844        let at = if cold {
845            self.promote_body(key).ok()??
846        } else {
847            value::slot(rec)
848        };
849        Some(self.hashes.get(at)?.encoding())
850    }
851
852    /// How a list is represented, or `None` if `key` is not a list.
853    ///
854    /// The same shape as [`Keyspace::set_encoding`], and the same argument for
855    /// asking the body rather than reading a copy out of the record. A demoted
856    /// list is brought back to answer, as the set and the hash are.
857    pub fn list_encoding(&mut self, key: &[u8]) -> Option<list::Encoding> {
858        self.reap(key);
859        let rec = self.map.get(key)?;
860        if value::kind(rec) != Kind::List {
861            return None;
862        }
863        let cold = value::Meta::from_byte(rec[0]).is_cold();
864        let at = if cold {
865            self.promote_body(key).ok()??
866        } else {
867            value::slot(rec)
868        };
869        Some(self.lists.get(at)?.encoding())
870    }
871
872    /// How a sorted set is represented, or `None` if `key` is not one.
873    pub fn zset_encoding(&mut self, key: &[u8]) -> Option<zset::Encoding> {
874        self.reap(key);
875        let rec = self.map.get(key)?;
876        if value::kind(rec) != Kind::Zset {
877            return None;
878        }
879        let cold = value::Meta::from_byte(rec[0]).is_cold();
880        let at = if cold {
881            self.promote_body(key).ok()??
882        } else {
883            value::slot(rec)
884        };
885        Some(self.zsets.get(at)?.encoding())
886    }
887
888    /// Put a foreign body under `key`, over whatever was there.
889    ///
890    /// The keyspace takes the box and frees it when the key goes, which is the
891    /// whole reason a graph lives in here rather than in a table beside it. See
892    /// [`crate::foreign`] for why that mattered enough to spend the last tag
893    /// pattern on.
894    ///
895    /// Overwriting is allowed and is what a caller that has just decided to
896    /// replace a key wants. A caller that did not mean to overwrite asks
897    /// [`Keyspace::kind_of`] first, which is what the commands above do so they
898    /// can answer WRONGTYPE rather than quietly throw a hash away.
899    pub fn put_foreign(&mut self, key: &[u8], body: Box<dyn Foreign>) -> u32 {
900        self.free_body(key);
901        let at = self.foreign.insert(body);
902        let len = value::slot_record_len(false);
903        self.write_rec(key, len, |out| {
904            value::write_slot_record(out, Kind::Foreign, at, None);
905        });
906        self.bodies += 1;
907        at
908    }
909
910    /// The foreign body under `key`.
911    ///
912    /// `None` for a key that is not there or has expired, an error for a key
913    /// holding something this crate does understand, which is the same three
914    /// way answer every other type's entry point gives.
915    ///
916    /// The caller turns the `&dyn Foreign` back into its own type with
917    /// [`downcast_ref`], and a `None` from that is a key holding a different
918    /// foreign body, which is also WRONGTYPE and is the caller's to report
919    /// because only it knows which one it wanted.
920    ///
921    /// [`downcast_ref`]: crate::Foreign
922    pub fn foreign(&mut self, key: &[u8]) -> Result<Option<&dyn Foreign>> {
923        let Some(at) = self.live_slot(key, Kind::Foreign)? else {
924            return Ok(None);
925        };
926        Ok(Some(
927            self.foreign
928                .get(at)
929                .expect("the record points at its body")
930                .as_ref(),
931        ))
932    }
933
934    /// The same, with a mutable borrow.
935    pub fn foreign_mut(&mut self, key: &[u8]) -> Result<Option<&mut dyn Foreign>> {
936        let Some(at) = self.live_slot(key, Kind::Foreign)? else {
937            return Ok(None);
938        };
939        Ok(Some(
940            self.foreign
941                .get_mut(at)
942                .expect("the record points at its body")
943                .as_mut(),
944        ))
945    }
946
947    /// Drop `key` if the foreign body under it has gone empty.
948    ///
949    /// Redis deletes a key when its collection empties, and a client can see
950    /// the difference, so every command that removes something calls this
951    /// afterwards rather than each of them deciding what empty means.
952    pub fn reap_foreign(&mut self, key: &[u8]) {
953        let gone = matches!(self.foreign(key), Ok(Some(b)) if b.is_empty());
954        if gone {
955            self.drop_key(key);
956        }
957    }
958
959    /// The foreign body under `key`, without the reap or the type check.
960    ///
961    /// For the arms that already have a live record in hand and only want the
962    /// body, where going through [`Keyspace::foreign`] would mean reaping a key
963    /// that was read a line ago.
964    fn foreign_at(&mut self, key: &[u8]) -> Option<&dyn Foreign> {
965        let rec = self.map.get(key)?;
966        let at = value::slot(rec);
967        Some(self.foreign.get(at)?.as_ref())
968    }
969
970    /// What `TYPE` should say about `key`.
971    ///
972    /// [`Kind::name`] for everything this crate knows, and the body's own word
973    /// for a foreign one, because a client asking about a graph is told `graph`
974    /// and not `foreign`. `None` for a key that is not there, which is the
975    /// `none` Redis answers with.
976    pub fn type_name(&mut self, key: &[u8]) -> Option<&'static str> {
977        match self.kind_of(key)? {
978            Kind::Foreign => self.foreign_at(key).map(Foreign::type_name),
979            kind => Some(kind.name()),
980        }
981    }
982
983    /// `OBJECT ENCODING key`, as the word Redis puts on the wire.
984    ///
985    /// One place that knows every type's answer, so that adding the hash means
986    /// adding an arm here and not finding the four callers that each worked it
987    /// out for themselves.
988    pub fn encoding_name(&mut self, key: &[u8]) -> Option<&'static str> {
989        match self.kind_of(key)? {
990            Kind::String => self.encoding(key).map(value::Encoding::name),
991            Kind::Set => self.set_encoding(key).map(set::Encoding::name),
992            Kind::Hash => self.hash_encoding(key).map(hash::Encoding::name),
993            Kind::List => self.list_encoding(key).map(list::Encoding::name),
994            Kind::Zset => self.zset_encoding(key).map(zset::Encoding::name),
995            // The one type with one encoding, so there is nothing to ask.
996            Kind::Array => Some("sliced-array"),
997            // The same, and Redis's word for it rather than a description of
998            // the node layout.
999            Kind::Stream => Some("stream"),
1000            // The body knows and this does not, which is the whole point of it.
1001            Kind::Foreign => self.foreign_at(key).map(Foreign::encoding),
1002        }
1003    }
1004
1005    /// Put a deadline on `key`, or take one off. Answers whether it was there.
1006    ///
1007    /// Any type. A deadline lives in the record and changes its length, so this
1008    /// writes the record again rather than patching it, and for a set that is
1009    /// five bytes or thirteen and never the members. The body is left exactly
1010    /// where it is, which is why this writes through the map instead of taking
1011    /// the free the body path an overwrite takes.
1012    ///
1013    /// This is the raw write. [`Keyspace::expire`] and [`Keyspace::persist`] are
1014    /// what `EXPIRE` and its family call, and they come through here once they
1015    /// have worked out whether the deadline is allowed to move.
1016    pub fn set_expiry(&mut self, key: &[u8], at: Option<u64>) -> bool {
1017        self.reap(key);
1018        let Some(rec) = self.map.get(key) else {
1019            return false;
1020        };
1021        if value::expire_at(rec) == at {
1022            return true;
1023        }
1024        // A deadline does not move a value that is on the file, it changes the
1025        // eight bytes in front of the address. So this writes a new pointer
1026        // rather than reading the value back to write it out again, and `EXPIRE`
1027        // on a demoted key costs no device read at all. That is the same promise
1028        // `TTL` and `STRLEN` keep and it is why the header stayed in memory.
1029        //
1030        // Ahead of the type split rather than inside the string arm, because a
1031        // demoted set is a pointer in exactly the same way and writing a slot
1032        // record over one would leave a record pointing at a slab slot that
1033        // belongs to something else.
1034        if let Some(c) = value::cold(rec) {
1035            let m = value::Meta::from_byte(rec[0]);
1036            let (kind, enc) = (m.kind(), m.encoding());
1037            let was = value::access(rec).unwrap_or_default();
1038            self.map.set_with(
1039                key,
1040                value::cold_record_len(at.is_some()),
1041                |_| {},
1042                |out| {
1043                    value::write_cold_record(out, kind, enc, c.at, c.len, at);
1044                    value::set_access(out, was);
1045                    value::has_expiry(out)
1046                },
1047            );
1048            return true;
1049        }
1050        // Read what has to survive out of the record before writing over it.
1051        match value::kind(rec) {
1052            Kind::String => {
1053                // Through the scratch buffer rather than a fresh `Vec`, since
1054                // `EXPIRE` on a string is a command a cache sends as often as
1055                // the `SET` before it.
1056                let mut bytes = std::mem::take(&mut self.scratch);
1057                bytes.clear();
1058                value::read(rec).write_to(&mut bytes);
1059                self.store(key, &bytes, at);
1060                self.scratch = bytes;
1061            }
1062            // Every body type writes the same record: a tag and a slot number.
1063            // The body is not touched and does not need to be, which is the
1064            // whole point of keeping it out of the record.
1065            kind @ (Kind::Set
1066            | Kind::Hash
1067            | Kind::List
1068            | Kind::Zset
1069            | Kind::Array
1070            | Kind::Stream
1071            | Kind::Foreign) => {
1072                let slot = value::slot(rec);
1073                let len = value::slot_record_len(at.is_some());
1074                self.write_rec(key, len, |out| {
1075                    value::write_slot_record(out, kind, slot, at);
1076                });
1077            }
1078        }
1079        true
1080    }
1081
1082    /// The key's deadline, as the three way answer `TTL` and `PTTL` are built on.
1083    ///
1084    /// [`Ask::Missing`] for a key that is not there, [`Ask::NoDeadline`] for one
1085    /// that is and has no deadline, and the absolute millisecond otherwise. A key
1086    /// past its deadline is reaped on the way through, so it answers `Missing`
1087    /// and not the moment that has gone.
1088    ///
1089    /// Asking when a key dies is not using it, so this does not stamp the
1090    /// eviction clock. Redis reads the key with its no touch flag here for the
1091    /// same reason, and it matters more than it looks: a client polling `TTL` on
1092    /// a key would otherwise keep that key at the top of the working set for as
1093    /// long as it kept asking whether it was about to go.
1094    pub fn deadline_of(&mut self, key: &[u8]) -> Ask {
1095        let Some(addr) = self.live_rec_untouched(key) else {
1096            return Ask::Missing;
1097        };
1098        match value::expire_at(self.map.value_at(addr)) {
1099            Some(at) => Ask::At(at),
1100            None => Ask::NoDeadline,
1101        }
1102    }
1103
1104    /// Move `key`'s deadline to `at`, if `cond` lets it.
1105    ///
1106    /// This is `EXPIRE`, `PEXPIRE`, `EXPIREAT` and `PEXPIREAT`, which differ only
1107    /// in the unit and the origin of the number. All four turn it into one
1108    /// absolute millisecond before they get here, so the condition rules live in
1109    /// one place and the four commands cannot drift apart.
1110    ///
1111    /// A deadline that has already passed deletes the key rather than being
1112    /// stored, and the answer says so. `EXPIRE` cannot report the difference
1113    /// because it replies 1 either way, but the caller is not always `EXPIRE`,
1114    /// and a delete is a different thing from a deadline.
1115    ///
1116    /// The condition is checked before the past check, which is the order Redis
1117    /// uses and is the one that matters: `EXPIRE key 0 XX` on a key with no
1118    /// deadline answers 0 and leaves the key alone, rather than deleting it.
1119    pub fn expire(&mut self, key: &[u8], at: u64, cond: Cond) -> Applied {
1120        let prev = match self.deadline_of(key) {
1121            Ask::Missing => return Applied::Missing,
1122            Ask::NoDeadline => None,
1123            Ask::At(at) => Some(at),
1124        };
1125        let done = ttl::decide(prev, at, cond, self.clock.now_ms());
1126        match done {
1127            Applied::Ok => {
1128                self.set_expiry(key, Some(at));
1129            }
1130            // The structure that answered `Deleted` for a field only holds
1131            // deadlines, so its caller has to remove the field. Here the caller
1132            // is us and the key is ours, so it goes now.
1133            Applied::Deleted => {
1134                self.drop_key(key);
1135            }
1136            Applied::Missing | Applied::NotMet => {}
1137        }
1138        done
1139    }
1140
1141    /// Take `key`'s deadline off. Answers whether there was one to take.
1142    ///
1143    /// This is `PERSIST`, and the reply is the same 0 for a key that is not there
1144    /// and a key that was never going to expire, which is Redis's answer and not
1145    /// a shortcut here.
1146    pub fn persist(&mut self, key: &[u8]) -> bool {
1147        if !matches!(self.deadline_of(key), Ask::At(_)) {
1148            return false;
1149        }
1150        self.set_expiry(key, None);
1151        true
1152    }
1153
1154    /// Give back whatever `key` holds outside its record, if it holds anything.
1155    ///
1156    /// Every path that deletes a key or writes over one has to come through
1157    /// here, because a set that loses its record without losing its slab slot is
1158    /// a leak that nothing ever notices: the memory is reachable, the slot is
1159    /// never reused, and `DBSIZE` looks right. Six delete sites and four string
1160    /// writers each remembering to do it themselves is five chances to forget,
1161    /// and one of them would be forgotten. So this is the funnel, and when the
1162    /// hash type lands the only place that changes is the match below.
1163    ///
1164    /// The record is left alone. This frees the body and the caller either
1165    /// deletes the record or writes a new one over it.
1166    pub(crate) fn free_body(&mut self, key: &[u8]) {
1167        if self.bodies == 0 {
1168            return;
1169        }
1170        let Some(rec) = self.map.get(key) else {
1171            return;
1172        };
1173        // A body that has been moved to the file has no slab slot to give back,
1174        // and the four bytes where the slot number would be are the front of an
1175        // address. Reading them as a slot and freeing it would hand back a slot
1176        // belonging to a different key. The chunks on the file are left where
1177        // they are, which is what the log's compaction collects. See
1178        // [`crate::tier`].
1179        if value::Meta::from_byte(rec[0]).is_cold() {
1180            return;
1181        }
1182        match value::kind(rec) {
1183            Kind::String => {}
1184            Kind::Set => {
1185                let at = value::slot(rec);
1186                self.sets.remove(at);
1187                self.bodies -= 1;
1188            }
1189            Kind::Hash => {
1190                let at = value::slot(rec);
1191                self.hashes.remove(at);
1192                self.bodies -= 1;
1193            }
1194            Kind::List => {
1195                let at = value::slot(rec);
1196                self.lists.remove(at);
1197                self.bodies -= 1;
1198            }
1199            Kind::Zset => {
1200                let at = value::slot(rec);
1201                self.zsets.remove(at);
1202                self.bodies -= 1;
1203            }
1204            Kind::Array => {
1205                let at = value::slot(rec);
1206                self.arrays.remove(at);
1207                self.bodies -= 1;
1208            }
1209            Kind::Stream => {
1210                let at = value::slot(rec);
1211                self.streams.remove(at);
1212                self.bodies -= 1;
1213            }
1214            Kind::Foreign => {
1215                let at = value::slot(rec);
1216                self.foreign.remove(at);
1217                self.bodies -= 1;
1218            }
1219        }
1220    }
1221
1222    /// Delete `key` and whatever it held. Answers whether it was there.
1223    #[inline]
1224    pub(crate) fn drop_key(&mut self, key: &[u8]) -> bool {
1225        self.free_body(key);
1226        self.del_rec(key)
1227    }
1228
1229    /// Drop `key` if its deadline has passed.
1230    ///
1231    /// This is lazy expiry and it is half of the story. The other half is
1232    /// [`Keyspace::expire_cycle`], which the maintenance slice runs and which is
1233    /// what stops a key nobody ever reads again from holding its memory forever
1234    /// (`14` section 1).
1235    ///
1236    /// Every public read calls this first, whatever type it is reading, which
1237    /// is why it is here and not in the file for any one type.
1238    #[inline]
1239    pub(crate) fn reap(&mut self, key: &[u8]) {
1240        let now = self.clock.now_ms();
1241        let dead = self.map.get(key).is_some_and(|r| value::is_expired(r, now));
1242        if dead {
1243            self.drop_key(key);
1244            self.expired += 1;
1245        }
1246    }
1247
1248    /// Give this database somewhere to keep values that are not in memory.
1249    ///
1250    /// Until this is called nothing is ever demoted, no record is ever cold and
1251    /// every command takes exactly the path it took before, which is why a
1252    /// database that never opens a file pays nothing for this existing.
1253    ///
1254    /// The store is whatever the caller wants it to be. In a server it is the
1255    /// shard's log. In a test it is a vector. This crate does not depend on
1256    /// either and does not want to: [`Blocks`](crate::cold::Blocks) is an append
1257    /// that hands back an address and a read that takes one, and that is the whole
1258    /// of the contract between the memory engine and whatever is under it.
1259    pub fn attach(&mut self, blocks: Store) {
1260        self.tier = Some(Tier::new(blocks));
1261    }
1262
1263    /// The tier, if one was attached, for its counters.
1264    #[must_use]
1265    pub const fn tier(&self) -> Option<&Tier<Store>> {
1266        self.tier.as_ref()
1267    }
1268
1269    /// The tier, mutably, for a caller driving a sweep.
1270    pub const fn tier_mut(&mut self) -> Option<&mut Tier<Store>> {
1271        self.tier.as_mut()
1272    }
1273
1274    /// Move one key's value out to the file.
1275    ///
1276    /// Answers whether it went. A key that is not there, one that is int
1277    /// encoded, one holding a type that does not move yet and one whose value is
1278    /// shorter than the pointer that would replace it all answer false, and so
1279    /// does every key on a database with nothing attached.
1280    ///
1281    /// This is the single key form, which is what a test and a `DEBUG`
1282    /// subcommand want. What a server under memory pressure wants is
1283    /// [`Keyspace::relieve`].
1284    ///
1285    /// One entry point for both kinds of value, because a caller naming a key
1286    /// should not have to know whether its body is in the record or in a slab.
1287    /// The two paths underneath are different all the way down: a string goes
1288    /// through the tier, and a collection goes through `demote_body` beside
1289    /// this, which frees a slab slot and grows a record.
1290    ///
1291    /// # Errors
1292    ///
1293    /// Whatever the store says when it will not take the bytes.
1294    pub fn demote(&mut self, key: &[u8]) -> Result<bool> {
1295        if self.tier.is_none() {
1296            return Ok(false);
1297        }
1298        let Some(addr) = self.map.find(key) else {
1299            return Ok(false);
1300        };
1301        if value::kind(self.map.value_at(addr)).is_body() {
1302            return self.demote_body(key);
1303        }
1304        let tier = self.tier.as_mut().expect("checked at the top");
1305        tier.demote(&mut self.map, key)
1306    }
1307
1308    /// How many bytes the attached store is holding, or `None` if there is not
1309    /// one.
1310    ///
1311    /// `None` and `Some(0)` are different answers and the difference is the one
1312    /// `maxstore` turns on. A database with nothing attached cannot migrate and
1313    /// has to evict, and a database with an empty file attached can migrate the
1314    /// moment it needs to.
1315    #[must_use]
1316    pub fn store_bytes(&self) -> Option<u64> {
1317        self.tier.as_ref().map(Tier::store_bytes)
1318    }
1319
1320    /// Move values out to the file until at least `shed` bytes of memory have
1321    /// gone.
1322    ///
1323    /// Answers with a [`Relief`], which is how many keys went and how much
1324    /// memory that gave back. This is `maxmemory` under the inversion `14`
1325    /// describes: the limit that used to throw keys away now moves them, and
1326    /// what a client stored is still there afterwards.
1327    ///
1328    /// Bytes to shed rather than a target to reach, because the caller with the
1329    /// limit is a server holding sixteen databases against one number and what
1330    /// it knows is how far over it is, not what any one database should be
1331    /// holding. `usize::MAX` means everything that can go, which is what a sweep
1332    /// wants.
1333    ///
1334    /// Victims are chosen by the same policy `maxmemory-policy` names, so a
1335    /// database set to `allkeys-lru` demotes the coldest keys and one set to
1336    /// `volatile-ttl` demotes the ones closest to expiring. See
1337    /// [`Tier::relieve`] for what a sweep does and where it stops.
1338    ///
1339    /// # Why `noeviction` still moves values
1340    ///
1341    /// Because it says do not lose data, and moving a value to the file does not
1342    /// lose any. The policy is two things at once in Redis, whether to give
1343    /// memory back at all and which keys to take it from, and only the second of
1344    /// those means anything here. So the default policy picks victims the way
1345    /// `allkeys-lru` does and the promise it was set for is kept: every key a
1346    /// client stored is still readable afterwards.
1347    ///
1348    /// The alternative is a server that was given a file, was given a limit, and
1349    /// answers writes with OOM until somebody finds the third setting that turns
1350    /// the file on. That is a trap and not a default.
1351    ///
1352    /// # Two passes, because the two kinds of value are counted in different
1353    /// places
1354    ///
1355    /// Strings go first, through [`Tier::relieve`], which measures itself against
1356    /// the arena because a string is its record and moving one makes the arena
1357    /// smaller. Collections cannot be swept that way. A collection's body is in a
1358    /// slab the arena knows nothing about, and moving one makes the arena
1359    /// **bigger**, because a twenty byte pointer replaces an eight byte slot
1360    /// number. A loop that watched the arena would demote every collection in the
1361    /// database, watch its number go up the whole time, and never stop.
1362    ///
1363    /// So the second pass is here rather than in the tier, and it measures itself
1364    /// against [`Keyspace::memory_bytes`], which is the arena and the slabs
1365    /// together. That is the only number that goes down when a body moves, and it
1366    /// is the number the server's limit is compared against anyway.
1367    ///
1368    /// # Errors
1369    ///
1370    /// Whatever the store says when it will not take the bytes.
1371    pub fn relieve(&mut self, shed: usize) -> Result<Relief> {
1372        if self.tier.is_none() {
1373            return Ok(Relief::default());
1374        }
1375        let now = self.clock.now_ms();
1376        let policy = match self.policy {
1377            Policy::NoEviction => Policy::AllKeysLru,
1378            chosen => chosen,
1379        };
1380        let lfu = self.lfu;
1381        let start = self.memory_bytes();
1382        let target = start.saturating_sub(shed);
1383        let budget = self.map.memory_bytes().saturating_sub(shed);
1384        let tier = self.tier.as_mut().expect("checked just above");
1385        let mut relief = tier.relieve(&mut self.map, budget, policy, now, lfu)?;
1386        // A sweep compacts the arena, which moves records, and the memo holds a
1387        // record's address. It is normally thrown away by the map's write
1388        // counter moving, and a sweep that demoted nothing and compacted anyway
1389        // is the one case where that counter does not move.
1390        self.memo = Memo::empty();
1391        if self.bodies > 0 && self.memory_bytes() > target {
1392            relief.moved += self.shed_bodies(target, policy, now, lfu)?;
1393        }
1394        relief.freed = start.saturating_sub(self.memory_bytes());
1395        Ok(relief)
1396    }
1397
1398    /// Sample the keyspace for collection bodies and move them out until
1399    /// [`Keyspace::memory_bytes`] is under `target`.
1400    ///
1401    /// The same shape as [`Tier::relieve`]'s loop, with the same stop rule and
1402    /// for the same reason: a round that finds nothing is a collision rather than
1403    /// a conclusion, so it takes [`tier::BARREN`] of them in a row to give up.
1404    /// What is different is the number being watched, which is explained on
1405    /// [`Keyspace::relieve`], and that there is no compaction step in here. The
1406    /// arena grows on this path rather than shrinking, so there is nothing for a
1407    /// compaction to hand back that the string pass has not already taken.
1408    fn shed_bodies(
1409        &mut self,
1410        target: usize,
1411        policy: Policy,
1412        now_ms: u64,
1413        lfu: Lfu,
1414    ) -> Result<usize> {
1415        let mut moved = 0;
1416        let mut barren = 0;
1417        // The pool comes out of the keyspace for the length of the sweep, because
1418        // it hands back a borrow of itself and demoting one victim needs the
1419        // whole keyspace. `kb` is the same borrow copied somewhere it can live
1420        // across that call, and it is one allocation for the sweep rather than
1421        // one per victim.
1422        let mut pool = core::mem::take(&mut self.pool);
1423        let mut kb: Vec<u8> = Vec::new();
1424        while self.memory_bytes() > target {
1425            pool.clear();
1426            let r = self.rng.next_u64();
1427            let pool = &mut pool;
1428            let mut seen = 0usize;
1429            let mut found = 0usize;
1430            // The body check is on the record and not on the slab, so the sample
1431            // closure does not need a second borrow of the keyspace. A record
1432            // that turns out to hold a body too small to be worth moving is
1433            // refused by `demote_body`, which has the slab in hand by then.
1434            self.map.sample(r, |k, v, _| {
1435                seen += 1;
1436                let m = value::Meta::from_byte(v[0]);
1437                if !m.is_cold() && moves(m.kind()) {
1438                    pool.offer(k, evict::score(v, policy, now_ms, lfu));
1439                    found += 1;
1440                }
1441                found < evict::CANDIDATES && seen < tier::WALK
1442            });
1443
1444            let mut round = 0;
1445            while let Some(k) = pool.take() {
1446                kb.clear();
1447                kb.extend_from_slice(k);
1448                if self.demote_body(&kb)? {
1449                    round += 1;
1450                }
1451            }
1452            if round == 0 {
1453                barren += 1;
1454                if barren == tier::BARREN {
1455                    break;
1456                }
1457                continue;
1458            }
1459            barren = 0;
1460            moved += round;
1461        }
1462        self.pool = pool;
1463        // Every demotion rewrote a record, so nothing the memo holds is worth
1464        // keeping and one of the slot numbers in it is now a freed slab slot.
1465        self.memo = Memo::empty();
1466        Ok(moved)
1467    }
1468
1469    /// Move `key`'s collection body out to the file.
1470    ///
1471    /// `Ok(false)` for a key that is not there, that holds a type this does not
1472    /// move yet, that is already on the file, or whose body is smaller than the
1473    /// pointer that would replace it. None of those is an error, for the same
1474    /// reason none of them is in [`crate::tier::demote`](Tier::demote): a sweep
1475    /// asks about a lot of keys and most of the answers are no.
1476    ///
1477    /// # What is different from a string
1478    ///
1479    /// A string's value is its record, so the tier can read it, write it out and
1480    /// rewrite the record without anyone else being involved. A collection's body
1481    /// is in a slab and its record holds a four byte number, so three things have
1482    /// to happen here and only here: the body is turned into bytes that mean
1483    /// something on a device, the slab slot is freed, and the record grows from
1484    /// eight bytes to twenty because an address and a length are longer than a
1485    /// slot number.
1486    ///
1487    /// That last part is why the memory a sweep frees does not show up in the
1488    /// arena. Demoting a collection makes the arena bigger and the slab smaller,
1489    /// and it is the sum that goes down. See [`Keyspace::relieve`].
1490    ///
1491    /// # Errors
1492    ///
1493    /// Whatever the store says when it cannot take the bytes.
1494    pub(crate) fn demote_body(&mut self, key: &[u8]) -> Result<bool> {
1495        if self.tier.is_none() {
1496            return Ok(false);
1497        }
1498        let Some(addr) = self.map.find(key) else {
1499            return Ok(false);
1500        };
1501        let rec = self.map.value_at(addr);
1502        let m = value::Meta::from_byte(rec[0]);
1503        if m.is_cold() || !moves(m.kind()) {
1504            return Ok(false);
1505        }
1506        let kind = m.kind();
1507        let expire_at = value::expire_at(rec);
1508        // Carried across and not restamped, as in `Tier::demote`. A key that was
1509        // moved out was not used, and a demotion that looked like a use would
1510        // make the next sweep pick the wrong victim.
1511        let was = value::access(rec).unwrap_or_default();
1512        let slot = value::slot(rec);
1513        // The same arithmetic the string side uses and not a tunable: a body
1514        // that costs less to keep than the pointer to it would is left where it
1515        // is. It is even more favourable here, because what a table costs in
1516        // memory is well above what its members weigh on a device.
1517        let grows_by = value::cold_record_len(expire_at.is_some())
1518            - value::slot_record_len(expire_at.is_some());
1519
1520        let mut buf = core::mem::take(&mut self.frozen);
1521        buf.clear();
1522        let worth = self.freeze_body(kind, slot, grows_by, &mut buf);
1523        let stashed = if worth {
1524            let tier = self.tier.as_mut().expect("checked at the top");
1525            Some(tier.stash(&buf))
1526        } else {
1527            None
1528        };
1529        self.frozen = buf;
1530        let Some(wrote) = stashed else {
1531            return Ok(false);
1532        };
1533        let chain = wrote?;
1534
1535        self.free_slot(kind, slot);
1536        self.bodies -= 1;
1537        let len = chain.len as u32;
1538        let wrote = self.map.set_with(
1539            key,
1540            value::cold_record_len(expire_at.is_some()),
1541            |_| {},
1542            |out| {
1543                // The encoding bits mean nothing on a collection record, which
1544                // is what `Meta::slot` already writes and says. `OBJECT
1545                // ENCODING` on a demoted body brings it back and asks the body,
1546                // which is one device read for a command nobody sends in a
1547                // loop, and is one place holding the fact rather than two.
1548                value::write_cold_record(out, kind, value::Encoding::Int, chain.at, len, expire_at);
1549                value::set_access(out, was);
1550                value::has_expiry(out)
1551            },
1552        );
1553        debug_assert!(wrote.is_some(), "the key was found a moment ago");
1554        // Not cleared by hand. Writing the record moves the map's write counter
1555        // and that is what the memo checks, so the slot number it is holding for
1556        // this key is already unreachable.
1557        Ok(true)
1558    }
1559
1560    /// Turn the body in `slot` into bytes, or say it is not worth moving.
1561    ///
1562    /// The one place that knows which slab a kind indexes on the way out, and
1563    /// the size check is in here because it needs the body in hand and the body
1564    /// is the thing this is holding. `false` leaves `buf` in whatever state it
1565    /// was, which the caller does not read.
1566    fn freeze_body(&self, kind: Kind, slot: u32, grows_by: usize, buf: &mut Vec<u8>) -> bool {
1567        match kind {
1568            Kind::Set => match self.sets.get(slot) {
1569                Some(body) if body.memory_bytes() > grows_by => {
1570                    body.freeze(buf);
1571                    true
1572                }
1573                Some(_) => false,
1574                None => {
1575                    debug_assert!(false, "a set record with no set behind it");
1576                    false
1577                }
1578            },
1579            Kind::Hash => match self.hashes.get(slot) {
1580                Some(body) if body.memory_bytes() > grows_by => {
1581                    body.freeze(buf);
1582                    true
1583                }
1584                Some(_) => false,
1585                None => {
1586                    debug_assert!(false, "a hash record with no hash behind it");
1587                    false
1588                }
1589            },
1590            Kind::List => match self.lists.get(slot) {
1591                Some(body) if body.memory_bytes() > grows_by => {
1592                    body.freeze(buf);
1593                    true
1594                }
1595                Some(_) => false,
1596                None => {
1597                    debug_assert!(false, "a list record with no list behind it");
1598                    false
1599                }
1600            },
1601            Kind::Zset => match self.zsets.get(slot) {
1602                Some(body) if body.memory_bytes() > grows_by => {
1603                    body.freeze(buf);
1604                    true
1605                }
1606                Some(_) => false,
1607                None => {
1608                    debug_assert!(false, "a sorted set record with no sorted set behind it");
1609                    false
1610                }
1611            },
1612            Kind::Array => match self.arrays.get(slot) {
1613                Some(body) if body.memory_bytes() > grows_by => {
1614                    body.freeze(buf);
1615                    true
1616                }
1617                Some(_) => false,
1618                None => {
1619                    debug_assert!(false, "an array record with no array behind it");
1620                    false
1621                }
1622            },
1623            Kind::Stream => match self.streams.get(slot) {
1624                Some(body) if body.memory_bytes() > grows_by => {
1625                    body.freeze(buf);
1626                    true
1627                }
1628                Some(_) => false,
1629                None => {
1630                    debug_assert!(false, "a stream record with no stream behind it");
1631                    false
1632                }
1633            },
1634            _ => {
1635                debug_assert!(false, "a kind `moves` said yes to and this does not know");
1636                false
1637            }
1638        }
1639    }
1640
1641    /// Give a slab slot back once its body has been written out.
1642    ///
1643    /// The twin of [`Keyspace::freeze_body`], kept beside it so that adding a
1644    /// type means touching two arms next to each other rather than hunting for
1645    /// the second one.
1646    fn free_slot(&mut self, kind: Kind, slot: u32) {
1647        match kind {
1648            Kind::Set => {
1649                self.sets.remove(slot);
1650            }
1651            Kind::Hash => {
1652                self.hashes.remove(slot);
1653            }
1654            Kind::List => {
1655                self.lists.remove(slot);
1656            }
1657            Kind::Zset => {
1658                self.zsets.remove(slot);
1659            }
1660            Kind::Array => {
1661                self.arrays.remove(slot);
1662            }
1663            Kind::Stream => {
1664                self.streams.remove(slot);
1665            }
1666            _ => debug_assert!(false, "freeing a slot in a slab that was never found"),
1667        }
1668    }
1669
1670    /// Send a cold record that holds a body back to [`Keyspace::promote_body`],
1671    /// and say whether that is what happened.
1672    ///
1673    /// The guard in front of both fault entry points, and it is here rather than
1674    /// in the tier because the tier cannot do this job. [`Tier::fault`] puts a
1675    /// value back by writing a string record, so handing it a demoted set would
1676    /// turn the set into a string holding the bytes a set freezes to. The kind is
1677    /// in the record and only this side has a slab to put a body in.
1678    ///
1679    /// One probe of the map on a path that is about to read a device, on a
1680    /// database that has a file at all. Every other database is refused by the
1681    /// caller before it gets here.
1682    ///
1683    /// # Errors
1684    ///
1685    /// Whatever the store says when the chain will not read back.
1686    fn body_came_back(&mut self, key: &[u8]) -> Result<bool> {
1687        let Some(addr) = self.map.find(key) else {
1688            return Ok(false);
1689        };
1690        let m = value::Meta::from_byte(self.map.value_at(addr)[0]);
1691        if !m.is_cold() || !m.kind().is_body() {
1692            return Ok(false);
1693        }
1694        self.promote_body(key)?;
1695        Ok(true)
1696    }
1697
1698    /// Bring `key`'s collection body back into a slab and answer its new slot.
1699    ///
1700    /// The record has to be rewritten either way, because a resident collection
1701    /// is a slot number and there is no way to hold one without being in the
1702    /// slab, so the doorkeeper does not get a vote. See [`Tier::fetch`].
1703    ///
1704    /// # Errors
1705    ///
1706    /// Whatever the store says when the chain will not read back, and
1707    /// [`Code::Corrupt`] when it reads back as something that is not a body.
1708    fn promote_body(&mut self, key: &[u8]) -> Result<Option<u32>> {
1709        let Some(addr) = self.map.find(key) else {
1710            return Ok(None);
1711        };
1712        let rec = self.map.value_at(addr);
1713        let Some(c) = value::cold(rec) else {
1714            return Ok(None);
1715        };
1716        let kind = value::kind(rec);
1717        let expire_at = value::expire_at(rec);
1718        let was = value::access(rec).unwrap_or_default();
1719        let Some(tier) = self.tier.as_mut() else {
1720            debug_assert!(false, "a cold record on a database with no file");
1721            return Ok(None);
1722        };
1723
1724        let mut buf = core::mem::take(&mut self.frozen);
1725        let read = tier.fetch(
1726            crate::cold::Chain {
1727                at: c.at,
1728                len: u64::from(c.len),
1729            },
1730            &mut buf,
1731        );
1732        self.frozen = buf;
1733        read?;
1734
1735        let slot = match kind {
1736            Kind::Set => {
1737                let set = Set::thaw(&self.frozen).map_err(|e| {
1738                    Error::new(Code::Corrupt, "a demoted set did not read back")
1739                        .with_detail(e.to_string())
1740                })?;
1741                self.sets.insert(set)
1742            }
1743            Kind::Hash => {
1744                let hash = Hash::thaw(&self.frozen).map_err(|e| {
1745                    Error::new(Code::Corrupt, "a demoted hash did not read back")
1746                        .with_detail(e.to_string())
1747                })?;
1748                self.hashes.insert(hash)
1749            }
1750            Kind::List => {
1751                let list = List::thaw(&self.frozen).map_err(|e| {
1752                    Error::new(Code::Corrupt, "a demoted list did not read back")
1753                        .with_detail(e.to_string())
1754                })?;
1755                self.lists.insert(list)
1756            }
1757            Kind::Zset => {
1758                let zset = Zset::thaw(&self.frozen).map_err(|e| {
1759                    Error::new(Code::Corrupt, "a demoted sorted set did not read back")
1760                        .with_detail(e.to_string())
1761                })?;
1762                self.zsets.insert(zset)
1763            }
1764            Kind::Array => {
1765                let array = Array::thaw(&self.frozen).map_err(|e| {
1766                    Error::new(Code::Corrupt, "a demoted array did not read back")
1767                        .with_detail(e.to_string())
1768                })?;
1769                self.arrays.insert(array)
1770            }
1771            Kind::Stream => {
1772                let stream = Stream::thaw(&self.frozen).map_err(|e| {
1773                    Error::new(Code::Corrupt, "a demoted stream did not read back")
1774                        .with_detail(e.to_string())
1775                })?;
1776                self.streams.insert(stream)
1777            }
1778            // Nothing else is written cold with a body yet, so arriving here
1779            // means a record that says one thing and a demoter that did another.
1780            _ => {
1781                return Err(Error::new(
1782                    Code::Corrupt,
1783                    "a demoted body of a type that is not moved out",
1784                )
1785                .with_detail(kind.name().to_string()));
1786            }
1787        };
1788        self.bodies += 1;
1789        let wrote = self.map.set_with(
1790            key,
1791            value::slot_record_len(expire_at.is_some()),
1792            |_| {},
1793            |out| {
1794                value::write_slot_record(out, kind, slot, expire_at);
1795                value::set_access(out, was);
1796                value::has_expiry(out)
1797            },
1798        );
1799        debug_assert!(wrote.is_some(), "the key was found a moment ago");
1800        Ok(Some(slot))
1801    }
1802
1803    /// Read `key`'s value off the file into [`Keyspace::cold`], if that is where
1804    /// it is.
1805    ///
1806    /// The doorkeeper decides whether the value also goes back into memory, so
1807    /// after this the record under `key` is either resident or still cold with
1808    /// its bytes in the buffer, and [`Keyspace::value_of`] is what tells the two
1809    /// apart. The address the caller was holding is not valid afterwards on the
1810    /// promoting path, because promotion rewrites the record.
1811    ///
1812    /// # Errors
1813    ///
1814    /// Whatever the store says when the chain will not read back.
1815    pub(crate) fn warm(&mut self, key: &[u8]) -> Result<Faulted> {
1816        if self.tier.is_none() {
1817            return Ok(Faulted::Warm);
1818        }
1819        if self.body_came_back(key)? {
1820            return Ok(Faulted::Promoted);
1821        }
1822        let tier = self.tier.as_mut().expect("checked at the top");
1823        let mut buf = core::mem::take(&mut self.cold);
1824        let r = tier.fault(&mut self.map, key, &mut buf);
1825        self.cold = buf;
1826        if r == Ok(Faulted::Served) {
1827            self.cold_key.clear();
1828            self.cold_key.extend_from_slice(key);
1829        }
1830        r
1831    }
1832
1833    /// Put `key`'s value back in memory if it was not there, for a command that
1834    /// is about to write it.
1835    ///
1836    /// See [`Tier::thaw`] for why the doorkeeper does not get a vote here. The
1837    /// short of it is that a read modify write leaves a resident record either
1838    /// way, so there is nothing for an answer to change.
1839    ///
1840    /// A caller can carry on exactly as it did before after this returns, with
1841    /// no cold case left to handle, which is why it is one line at the top of
1842    /// `APPEND` and `INCR` rather than a second path through them.
1843    ///
1844    /// # Errors
1845    ///
1846    /// Whatever the store says when the chain will not read back.
1847    pub(crate) fn thaw(&mut self, key: &[u8]) -> Result<()> {
1848        if self.tier.is_none() {
1849            return Ok(());
1850        }
1851        if self.body_came_back(key)? {
1852            return Ok(());
1853        }
1854        let tier = self.tier.as_mut().expect("checked at the top");
1855        let mut buf = core::mem::take(&mut self.cold);
1856        let r = tier.thaw(&mut self.map, key, &mut buf);
1857        self.cold = buf;
1858        r.map(|_| ())
1859    }
1860
1861    /// The value in a record that may have been left on the file.
1862    ///
1863    /// Only correct straight after a [`Keyspace::warm`] of the same key, since
1864    /// the buffer holds one value at a time. A debug build says so rather than
1865    /// handing back a value that belongs to somebody else.
1866    pub(crate) fn value_of<'a>(&'a self, key: &[u8], rec: &'a [u8]) -> Str<'a> {
1867        if value::cold(rec).is_some() {
1868            debug_assert!(
1869                bytes_eq(&self.cold_key, key),
1870                "a read found a value on the file without faulting it in first"
1871            );
1872            Str::Bytes(&self.cold)
1873        } else {
1874            value::read(rec)
1875        }
1876    }
1877
1878    /// [`Keyspace::warm`] and then the value, for the readers that do nothing
1879    /// else with the record.
1880    ///
1881    /// `None` when the key went away, which it cannot do here but which the
1882    /// second lookup has to allow for anyway: the first lookup's address does
1883    /// not survive a promotion, so this has to find the key again rather than
1884    /// trust a number from before.
1885    ///
1886    /// # Errors
1887    ///
1888    /// Whatever the store says when the chain will not read back.
1889    pub(crate) fn warmed(&mut self, key: &[u8]) -> Result<Option<Str<'_>>> {
1890        self.warm(key)?;
1891        let Some(addr) = self.map.find(key) else {
1892            return Ok(None);
1893        };
1894        Ok(Some(self.value_of(key, self.map.value_at(addr))))
1895    }
1896
1897    /// Where `key`'s record is, having thrown the key away first if it is dead.
1898    ///
1899    /// The same fold as [`Keyspace::live_slot`] for a caller that wants the
1900    /// record itself rather than a slot number, which is every string command.
1901    /// `GET` used to be a reap, then a type check, then a read, and each of the
1902    /// three hashed the key and walked a bucket for the same record. It is one
1903    /// walk now and two arena reads, and an arena read at a known address is a
1904    /// load.
1905    ///
1906    /// The address dies at the next write, which is why this is `pub(crate)`
1907    /// and why every caller reads it and drops it inside one command.
1908    ///
1909    /// Finding a key counts as using it, so this stamps the access field on the
1910    /// way past under every policy that wants it stamped, which is eight of the
1911    /// ten. A command that has to look at a key without using it calls
1912    /// [`Keyspace::live_rec_untouched`] instead, and the list of those is short
1913    /// and is Redis's list rather than ours.
1914    pub(crate) fn live_rec(&mut self, key: &[u8]) -> Option<Addr> {
1915        let addr = self.live_rec_untouched(key)?;
1916        if self.policy.stamps_on_read() {
1917            self.stamp(addr);
1918        }
1919        Some(addr)
1920    }
1921
1922    /// [`Keyspace::live_rec`] for a command that is asking about a key rather
1923    /// than using it.
1924    ///
1925    /// `TYPE`, `EXISTS`, the `TTL` family and every `OBJECT` subcommand look
1926    /// without touching, which is Redis's `LOOKUP_NOTOUCH` and is not an
1927    /// optimisation. `OBJECT IDLETIME` that counted as a use would report zero
1928    /// every time, and `EXISTS` in a health check loop would keep a dead key at
1929    /// the top of the working set forever.
1930    ///
1931    /// Untouched means the access field only. A key past its deadline is still
1932    /// reaped here, because a command asking whether a key exists has to be told
1933    /// that it does not.
1934    pub(crate) fn live_rec_untouched(&mut self, key: &[u8]) -> Option<Addr> {
1935        let now = self.clock.now_ms();
1936        let addr = self.map.find(key)?;
1937        if value::is_expired(self.map.value_at(addr), now) {
1938            self.drop_key(key);
1939            self.expired += 1;
1940            return None;
1941        }
1942        Some(addr)
1943    }
1944
1945    /// The slot under `key`, having thrown the key away first if it is dead.
1946    ///
1947    /// `None` for a key that is not there or that was and is now reaped, and
1948    /// `WRONGTYPE` for a key holding something other than `want`.
1949    ///
1950    /// One probe of the map, where a [`Keyspace::reap`] followed by a `get`
1951    /// costs two. That pair is how every collection command used to start, so a
1952    /// pipeline of sixty four `SADD` on one key hashed and probed for that key a
1953    /// hundred and twenty eight times to do sixty four inserts. The reap has to
1954    /// read the record and the command has to read the same record, and there
1955    /// was never a reason for those to be two visits.
1956    ///
1957    /// It answers a number rather than the record it just read because of the
1958    /// borrow checker and not because a number is nicer. A method that hands
1959    /// back a borrow of the map on one path and takes a mutable borrow to reap
1960    /// on the other is the case the borrow checker still refuses without
1961    /// Polonius. A slot is four bytes and copies out, so the borrow ends here
1962    /// and the caller reaches its body through the slab.
1963    ///
1964    /// And no probe at all when the command in front of it asked for the same
1965    /// key and nothing has been written since, which is the [`Memo`] and is what
1966    /// Y13 asks for on single key `SADD`.
1967    pub(crate) fn live_slot(&mut self, key: &[u8], want: Kind) -> Result<Option<u32>> {
1968        // A memo hit skips the record, so the stamp has to happen on the way out
1969        // of it as well. It is the same address every time, which is what makes
1970        // this cheap: no probe, just the store. Getting this wrong is the trap
1971        // worth naming, because the key that hits the memo most often is the
1972        // hottest key in the database, and it is the one that would have looked
1973        // steadily more idle the harder it was used.
1974        if let Some((kind, slot, addr)) = self.memo.get(self.map.writes(), key) {
1975            if kind != want {
1976                return Err(wrong_type());
1977            }
1978            if self.policy.stamps_on_read() {
1979                self.stamp(addr);
1980            }
1981            return Ok(Some(slot));
1982        }
1983        // `find` and then `value_at` rather than `get`, which is the same two
1984        // steps, so that the address is still in hand for the stamp below. `get`
1985        // would mean probing a second time for a record already read.
1986        let now = self.clock.now_ms();
1987        let Some(addr) = self.map.find(key) else {
1988            return Ok(None);
1989        };
1990        let rec = self.map.value_at(addr);
1991        if value::is_expired(rec, now) {
1992            self.drop_key(key);
1993            self.expired += 1;
1994            return Ok(None);
1995        }
1996        if value::kind(rec) != want {
1997            return Err(wrong_type());
1998        }
1999        // One test of a bit in a byte that is already in a register, on the
2000        // funnel every collection command comes through. A database with no file
2001        // behind it never sets it and pays that test and nothing else.
2002        if value::Meta::from_byte(rec[0]).is_cold() {
2003            return self.promote_body(key);
2004        }
2005        let slot = value::slot(rec);
2006        // A key with a deadline is not memoized. The memo is invalidated by
2007        // writes and a deadline passes without one, so remembering a dated key
2008        // would be remembering it past the moment it should have been reaped.
2009        // Both of these are read off the record before the stamp, which needs it
2010        // mutably and is the end of this borrow.
2011        let dated = value::expire_at(rec).is_some();
2012        if self.policy.stamps_on_read() {
2013            self.stamp(addr);
2014        }
2015        if !dated {
2016            self.memo.put(self.map.writes(), key, want, slot, addr);
2017        }
2018        Ok(Some(slot))
2019    }
2020
2021    /// Where `key` is, when either of two types will do.
2022    ///
2023    /// Every input to a sorted set operation may be a sorted set or a plain set,
2024    /// which is Redis's rule and means the type check there is a membership test
2025    /// rather than an equality. The kind comes back with the slot because the
2026    /// caller has to know which slab the number indexes.
2027    pub(crate) fn live_slot_either(
2028        &mut self,
2029        key: &[u8],
2030        a: Kind,
2031        b: Kind,
2032    ) -> Result<Option<(Kind, u32)>> {
2033        if let Some((kind, slot, addr)) = self.memo.get(self.map.writes(), key) {
2034            if kind != a && kind != b {
2035                return Err(wrong_type());
2036            }
2037            if self.policy.stamps_on_read() {
2038                self.stamp(addr);
2039            }
2040            return Ok(Some((kind, slot)));
2041        }
2042        let now = self.clock.now_ms();
2043        let Some(addr) = self.map.find(key) else {
2044            return Ok(None);
2045        };
2046        let rec = self.map.value_at(addr);
2047        if value::is_expired(rec, now) {
2048            self.drop_key(key);
2049            self.expired += 1;
2050            return Ok(None);
2051        }
2052        let kind = value::kind(rec);
2053        if kind != a && kind != b {
2054            return Err(wrong_type());
2055        }
2056        // As in `live_slot`, and the kind was read before the record was given
2057        // up because promotion rewrites it.
2058        if value::Meta::from_byte(rec[0]).is_cold() {
2059            return Ok(self.promote_body(key)?.map(|slot| (kind, slot)));
2060        }
2061        let slot = value::slot(rec);
2062        let dated = value::expire_at(rec).is_some();
2063        if self.policy.stamps_on_read() {
2064            self.stamp(addr);
2065        }
2066        if !dated {
2067            self.memo.put(self.map.writes(), key, kind, slot, addr);
2068        }
2069        Ok(Some((kind, slot)))
2070    }
2071
2072    /// Throw every key away. This is `FLUSHDB` on one database.
2073    ///
2074    /// The expiry counter is not reset, because Redis does not reset it either:
2075    /// `expired_keys` in `INFO stats` counts what this process has expired since
2076    /// it started, and emptying a database is not expiring anything. The count of
2077    /// keys that carry a deadline is a different number and it does go to zero,
2078    /// because it is a fact about what is in the database right now and there is
2079    /// nothing in it.
2080    pub fn clear(&mut self) {
2081        self.map.clear();
2082        self.sets.clear();
2083        self.hashes.clear();
2084        self.lists.clear();
2085        self.zsets.clear();
2086        self.arrays.clear();
2087        self.streams.clear();
2088        self.foreign.clear();
2089        self.pool.clear();
2090        self.bodies = 0;
2091    }
2092
2093    /// Keys reclaimed by running into them after their deadline.
2094    ///
2095    /// Redis calls this `expired_keys` in `INFO stats` and counts both lazy and
2096    /// active expiry into it, and so does this. [`Keyspace::expire_cycle`] is
2097    /// the active half and it counts into the same number, which is what makes
2098    /// this the total a dashboard can compare against a write rate rather than
2099    /// the share of it that happened to be reclaimed by a read.
2100    #[inline]
2101    pub const fn expired_keys(&self) -> u64 {
2102        self.expired
2103    }
2104
2105    /// Keys thrown away to make room.
2106    ///
2107    /// Redis calls this `evicted_keys` in `INFO stats`. It stays at zero under
2108    /// `noeviction`, which is the whole point of that policy, and a monitoring
2109    /// dashboard that sees it move on a server configured that way is looking at
2110    /// a bug rather than at load.
2111    #[inline]
2112    pub const fn evicted_keys(&self) -> u64 {
2113        self.evicted
2114    }
2115
2116    /// How many live keys carry a deadline.
2117    ///
2118    /// This is what `INFO keyspace` reports as `expires=`, and it is the live
2119    /// count rather than a running total: a key that gets a `TTL` and then has it
2120    /// taken away with `PERSIST` is in it and then is not.
2121    ///
2122    /// The map keeps it, because the map keeps the second index these keys are
2123    /// in. Nothing in this file counts it, which is deliberate: a count kept
2124    /// alongside the thing it counts is a count that eventually disagrees with
2125    /// it, and the one place that can be wrong should be the one place that owns
2126    /// the entries.
2127    #[inline]
2128    pub fn expires(&self) -> usize {
2129        self.map.tagged_len()
2130    }
2131
2132    /// How many keys a round of eviction sampling looks at.
2133    #[inline]
2134    pub const fn samples(&self) -> usize {
2135        self.samples
2136    }
2137
2138    /// Set how many keys a round of eviction sampling looks at.
2139    ///
2140    /// Zero is not refused here, because the caller doing the refusing is
2141    /// `CONFIG SET` and it has a message to produce. A zero that reaches here
2142    /// samples one bucket and takes the best of it, because the loop runs its
2143    /// body before it checks, which is a better answer than dividing by nothing.
2144    #[inline]
2145    pub const fn set_samples(&mut self, samples: usize) {
2146        self.samples = samples;
2147    }
2148
2149    /// Throw away one key, chosen by the policy. Answers whether one went.
2150    ///
2151    /// This is one step and not a loop on purpose. The caller is the thing that
2152    /// knows how much room it needs back, and a loop in here would either take
2153    /// too much or have to be told the same number twice. It also means the
2154    /// caller can put a bound on how long it spends evicting before it answers
2155    /// the client, which matters because the client is waiting on a write that
2156    /// this is making room for.
2157    ///
2158    /// It answers false without doing anything under `noeviction`, and also when
2159    /// a `volatile` policy is set on a database where nothing has a deadline.
2160    /// Those are the same answer to the caller and they mean the same thing: this
2161    /// server cannot give memory back and is about to have to refuse a write.
2162    pub fn evict_one(&mut self) -> bool {
2163        let Some(addr) = self.victim() else {
2164            return false;
2165        };
2166        // The key has to outlive the borrow that found it, because deleting is a
2167        // write and the address came out of a read. One copy into the scratch
2168        // buffer rather than a `Vec` per eviction, for the reason written on
2169        // [`Keyspace::scratch`]: this runs in a loop when it runs at all.
2170        let mut buf = core::mem::take(&mut self.scratch);
2171        buf.clear();
2172        buf.extend_from_slice(self.map.entry_at(addr).0);
2173        let gone = self.drop_key(&buf);
2174        self.scratch = buf;
2175        if gone {
2176            self.evicted += 1;
2177        }
2178        gone
2179    }
2180
2181    /// Where the key this policy would throw away lives, if there is one.
2182    ///
2183    /// The sampling loop. It draws buckets until it has looked at `samples` keys
2184    /// the policy would consider, scores each one, and hands back the best. See
2185    /// [`evict`] for what the score means and [`yo_index::RawMap::sample`] for
2186    /// why a bucket is the unit.
2187    ///
2188    /// The round cap is the part that is not obvious. A database with a hundred
2189    /// keys in a directory sized for a million is mostly empty buckets, and a
2190    /// `volatile` policy on a database where nothing has a deadline has no
2191    /// eligible keys at all however many buckets it looks in. Without the cap the
2192    /// second case is an infinite loop, and it is not a rare configuration, it is
2193    /// the classic eviction surprise. With it, the worst case is a fixed number
2194    /// of cache misses and a false, which is exactly what the caller needs to
2195    /// hear.
2196    ///
2197    /// A key past its deadline is skipped rather than taken. It is dead memory
2198    /// and evicting it would look like a win, but it would be counted as an
2199    /// eviction when it is an expiry, and those two numbers are watched
2200    /// separately for a reason. Lazy expiry takes it the next time anything asks
2201    /// for it, and the active cycle takes it before that.
2202    ///
2203    /// What comes back is not only the worst of this round. Everything sampled
2204    /// goes into [`evict::Pool`], which holds the sixteen best across rounds, so
2205    /// the answer is the worst key seen since the pool was last emptied. The
2206    /// price is that a candidate is a key rather than an address and so has to
2207    /// be looked up and rechecked here, because it can have been deleted or have
2208    /// expired or have lost its deadline since the round that spotted it.
2209    fn victim(&mut self) -> Option<Addr> {
2210        if matches!(self.policy, Policy::NoEviction) || self.map.is_empty() {
2211            self.pool.clear();
2212            return None;
2213        }
2214        // The classic eviction surprise, answered before it costs anything. A
2215        // `volatile` policy on a database where no key has a deadline has no
2216        // eligible key anywhere, and the loop below can only find that out by
2217        // drawing four rounds of buckets and being told so by every key in them,
2218        // on a path where a client is waiting for the write this is making room
2219        // for. The count knows.
2220        if self.policy.volatile_only() && self.expires() == 0 {
2221            self.pool.clear();
2222            return None;
2223        }
2224        let now = self.clock.now_ms();
2225        let (policy, lfu, want) = (self.policy, self.lfu, self.samples);
2226        if policy.is_random() {
2227            return self.draw(now, want);
2228        }
2229        // Which index to draw from. The `volatile` policies can only take a key
2230        // that has a deadline, and the map keeps a second index of exactly
2231        // those, so drawing from the whole keyspace and then throwing most of it
2232        // away is work with a cheaper alternative sitting right there. The
2233        // `allkeys` policies draw from everything, because everything is
2234        // eligible.
2235        let volatile = policy.volatile_only();
2236        let mut seen = 0usize;
2237        for _ in 0..ROUNDS {
2238            let r = self.rng.next_u64();
2239            let pool = &mut self.pool;
2240            // By reference, so the same closure can go to either sampler. A
2241            // `&mut F` is an `FnMut` when `F` is, which is what makes the two
2242            // calls below one closure rather than two copies of it.
2243            let mut offer = |key: &[u8], rec: &[u8], _addr: Addr| {
2244                if !value::is_expired(rec, now) && evict::eligible(rec, policy) {
2245                    seen += 1;
2246                    pool.offer(key, evict::score(rec, policy, now, lfu));
2247                }
2248                seen < want
2249            };
2250            if volatile {
2251                self.map.sample_tagged(r, &mut offer);
2252            } else {
2253                self.map.sample(r, &mut offer);
2254            }
2255            if seen >= want {
2256                break;
2257            }
2258        }
2259        while let Some(key) = self.pool.take() {
2260            let Some(addr) = self.map.find(key) else {
2261                continue;
2262            };
2263            let rec = self.map.value_at(addr);
2264            if value::is_expired(rec, now) || !evict::eligible(rec, policy) {
2265                continue;
2266            }
2267            return Some(addr);
2268        }
2269        None
2270    }
2271
2272    /// A fair draw among the eligible keys, which is what the random pair want.
2273    ///
2274    /// No pool, because there is no ordering for one to approximate: under
2275    /// `allkeys-random` and `volatile-random` every eligible key is as good a
2276    /// victim as every other, and remembering sixteen of them across rounds
2277    /// would only mean the same sixteen going first. The sampling is what does
2278    /// the choosing, so the address it lands on is used straight away and the
2279    /// key never has to be copied at all.
2280    fn draw(&mut self, now: u64, want: usize) -> Option<Addr> {
2281        let policy = self.policy;
2282        let volatile = policy.volatile_only();
2283        let mut best = evict::Best::EMPTY;
2284        let mut seen = 0usize;
2285        for _ in 0..ROUNDS {
2286            let r = self.rng.next_u64();
2287            let mut offer = |_key: &[u8], rec: &[u8], addr: Addr| {
2288                if !value::is_expired(rec, now) && evict::eligible(rec, policy) {
2289                    seen += 1;
2290                    best.offer(addr, evict::ANY);
2291                }
2292                seen < want
2293            };
2294            if volatile {
2295                self.map.sample_tagged(r, &mut offer);
2296            } else {
2297                self.map.sample(r, &mut offer);
2298            }
2299            if seen >= want {
2300                break;
2301            }
2302        }
2303        (!best.is_empty()).then_some(best.addr)
2304    }
2305
2306    /// Bytes held by the index, the arena and every body hanging off them.
2307    ///
2308    /// Asks every collection, so this is O(the number of collections) and is for
2309    /// the places that want the number exactly and are asked for it rarely:
2310    /// `INFO memory`, `MEMORY USAGE` and the tests.
2311    /// [`Keyspace::settled_memory_bytes`] is the one a memory limit uses.
2312    #[inline]
2313    pub fn memory_bytes(&self) -> usize {
2314        self.slab_bytes()
2315            + self.sets.value_bytes()
2316            + self.hashes.value_bytes()
2317            + self.lists.value_bytes()
2318            + self.zsets.value_bytes()
2319            + self.arrays.value_bytes()
2320            + self.streams.value_bytes()
2321            + self.foreign.value_bytes()
2322    }
2323
2324    /// The same number, asked only of the collections that could have moved.
2325    ///
2326    /// See [`Slab::track_bytes`] for how that is known. With tracking on this
2327    /// costs what the batch touched instead of what the database holds, which is
2328    /// what lets a server with a `maxmemory` ask once a batch. With tracking off
2329    /// it is [`Keyspace::memory_bytes`] and the two cannot disagree, because
2330    /// they are the same sum over the same values either way.
2331    #[inline]
2332    pub fn settled_memory_bytes(&mut self) -> usize {
2333        self.slab_bytes()
2334            + self.sets.settled_bytes()
2335            + self.hashes.settled_bytes()
2336            + self.lists.settled_bytes()
2337            + self.zsets.settled_bytes()
2338            + self.arrays.settled_bytes()
2339            + self.streams.settled_bytes()
2340            + self.foreign.settled_bytes()
2341    }
2342
2343    /// Start or stop keeping the running total in every slab.
2344    ///
2345    /// One call for all seven, because a limit is a property of the server and
2346    /// not of a type, and a database tracking its sets but not its hashes would
2347    /// answer a number that is neither of the two things it could mean.
2348    pub fn track_memory(&mut self, on: bool) {
2349        self.sets.track_bytes(on);
2350        self.hashes.track_bytes(on);
2351        self.lists.track_bytes(on);
2352        self.zsets.track_bytes(on);
2353        self.arrays.track_bytes(on);
2354        self.streams.track_bytes(on);
2355        self.foreign.track_bytes(on);
2356    }
2357
2358    /// The index, the arena and the slot arrays, none of which need asking
2359    /// twice, plus the tier when there is one.
2360    ///
2361    /// The tier is in here because a doorkeeper and a directory buffer are real
2362    /// memory and a limit that did not count them would be a limit on part of
2363    /// the server. It is also the honest way round: the thing that gives memory
2364    /// back costs some to keep, and both numbers belong in the same total.
2365    #[inline]
2366    fn slab_bytes(&self) -> usize {
2367        self.tier.as_ref().map_or(0, Tier::memory_bytes)
2368            + self.map.memory_bytes()
2369            + self.sets.slot_bytes()
2370            + self.hashes.slot_bytes()
2371            + self.lists.slot_bytes()
2372            + self.zsets.slot_bytes()
2373            + self.arrays.slot_bytes()
2374            + self.streams.slot_bytes()
2375            + self.foreign.slot_bytes()
2376    }
2377
2378    /// Give back one segment's worth of space if one has gone mostly dead.
2379    ///
2380    /// Overwriting a key does not reuse its bytes, it writes the new record at
2381    /// the bump pointer and counts the old one as dead, so a workload that sets
2382    /// the same keys over and over holds far more than it is storing until
2383    /// something compacts. This is that something, and it does at most one
2384    /// segment per call so that the loop can afford to ask every turn.
2385    #[inline]
2386    pub fn compact_step(&mut self) -> Option<usize> {
2387        self.map.compact_step()
2388    }
2389
2390    /// The same, for a store that is over a memory limit and has to give pages
2391    /// back rather than wait for a segment to be worth collecting.
2392    ///
2393    /// See [`RawMap::compact_hard`] for why the choice of segment changes and
2394    /// why it only changes under pressure.
2395    #[inline]
2396    pub fn compact_hard(&mut self) -> Option<usize> {
2397        self.map.compact_hard()
2398    }
2399
2400    /// Ask the cache for the bucket this key will land in.
2401    ///
2402    /// The first of the loop's two walks (`04` section 3) calls this.
2403    #[inline]
2404    pub fn prefetch(&self, hash: u64) {
2405        self.map.prefetch(hash);
2406    }
2407
2408    /// The hash this database files `key` under.
2409    #[inline]
2410    #[must_use]
2411    pub fn hash_of(key: &[u8]) -> u64 {
2412        RawMap::hash_of(key)
2413    }
2414}
2415
2416/// Whether a body of this kind can leave memory yet.
2417///
2418/// One list rather than a check in each of the three places that need it, so a
2419/// type that gains a `freeze` cannot be demotable in the sweep and unreadable on
2420/// the way back. A kind that is not in here stays in memory, which costs a
2421/// demotion that did not happen and is never a wrong answer.
2422const fn moves(kind: Kind) -> bool {
2423    matches!(
2424        kind,
2425        Kind::Set | Kind::Hash | Kind::List | Kind::Zset | Kind::Array | Kind::Stream
2426    )
2427}
2428
2429/// What Redis says when a command is sent at a key holding another type.
2430///
2431/// The text is Redis's, word for word, because it goes on the wire verbatim and
2432/// clients match on it. The `WRONGTYPE` at the front is not part of the message:
2433/// the protocol layer puts it there from the [`Code`], which is what lets an
2434/// embedded caller match on a value instead of on a string (P5).
2435pub fn wrong_type() -> Error {
2436    Error::new(
2437        Code::WrongType,
2438        "Operation against a key holding the wrong kind of value",
2439    )
2440}
2441
2442impl Default for Keyspace {
2443    fn default() -> Keyspace {
2444        Keyspace::new()
2445    }
2446}
2447
2448#[cfg(test)]
2449mod tests {
2450    use super::*;
2451
2452    fn db() -> Keyspace {
2453        Keyspace::with_clock(Clock::fixed(1_000))
2454    }
2455
2456    #[test]
2457    fn type_answers_string_for_a_string_and_nothing_for_a_missing_key() {
2458        let mut d = db();
2459        d.set_plain(b"k", b"v").expect("room");
2460        assert_eq!(d.kind_of(b"k"), Some(Kind::String));
2461        assert_eq!(d.kind_of(b"nope"), None);
2462    }
2463
2464    #[test]
2465    fn type_does_not_report_a_key_whose_deadline_has_gone() {
2466        let mut d = db();
2467        d.psetex(b"k", 100, b"v").expect("room");
2468        assert_eq!(d.kind_of(b"k"), Some(Kind::String));
2469
2470        d.clock().advance(100);
2471        assert_eq!(
2472            d.kind_of(b"k"),
2473            None,
2474            "the deadline was 1100 and it is 1100"
2475        );
2476        assert_eq!(d.len(), 0, "and asking reaped it rather than leaving it");
2477        assert_eq!(d.expired_keys(), 1);
2478    }
2479
2480    /// The default policy evicts nothing and still keeps the clock, which is
2481    /// Redis's behaviour and is the configuration nearly every server runs.
2482    #[test]
2483    fn the_clock_runs_under_the_default_policy() {
2484        let mut d = db();
2485        assert_eq!(d.policy(), Policy::NoEviction);
2486        d.set_plain(b"k", b"v").expect("room");
2487        assert_eq!(d.idle_secs(b"k"), Some(0));
2488
2489        d.clock().advance(60_000);
2490        assert_eq!(d.idle_secs(b"k"), Some(60), "a minute of nobody asking");
2491
2492        d.get(b"k").expect("a string").expect("still there");
2493        assert_eq!(d.idle_secs(b"k"), Some(0), "and reading it is using it");
2494    }
2495
2496    /// The commands that ask about a key rather than use it. Getting this wrong
2497    /// makes `OBJECT IDLETIME` answer zero every time it is called, because
2498    /// calling it would be the most recent use.
2499    #[test]
2500    fn asking_about_a_key_is_not_using_it() {
2501        let mut d = db();
2502        d.set_plain(b"k", b"v").expect("room");
2503        d.clock().advance(30_000);
2504
2505        assert!(d.exists(b"k"));
2506        assert_eq!(d.kind_of(b"k"), Some(Kind::String));
2507        assert_eq!(d.encoding_name(b"k"), Some("embstr"));
2508        assert_eq!(d.deadline_of(b"k"), Ask::NoDeadline);
2509        assert_eq!(d.expire_at(b"k"), None);
2510        assert_eq!(d.idle_secs(b"k"), Some(30));
2511
2512        assert_eq!(
2513            d.idle_secs(b"k"),
2514            Some(30),
2515            "and asking twice is still not using it"
2516        );
2517    }
2518
2519    /// Least recently modified is the one policy where a read must leave the
2520    /// clock where it is, because the clock is the only thing it measures.
2521    #[test]
2522    fn a_read_moves_the_clock_under_lru_and_leaves_it_under_lrm() {
2523        for (policy, idle_after_read) in [(Policy::AllKeysLru, 0), (Policy::AllKeysLrm, 45)] {
2524            let mut d = db();
2525            d.set_policy(policy);
2526            d.set_plain(b"k", b"v").expect("room");
2527            d.clock().advance(45_000);
2528
2529            d.get(b"k").expect("a string").expect("still there");
2530            assert_eq!(
2531                d.idle_secs(b"k"),
2532                Some(idle_after_read),
2533                "{}",
2534                policy.name()
2535            );
2536
2537            // Both of them move it on a write, which is the whole of what LRM
2538            // is measuring and is a side effect of the resolve under LRU.
2539            d.set_plain(b"k", b"w").expect("room");
2540            assert_eq!(
2541                d.idle_secs(b"k"),
2542                Some(0),
2543                "{} after a write",
2544                policy.name()
2545            );
2546        }
2547    }
2548
2549    /// The trap the memo sets. A hit skips the record entirely, so a stamp that
2550    /// only happened on a miss would leave the hottest key in the database
2551    /// looking steadily more idle the harder it was used.
2552    #[test]
2553    fn the_hot_key_path_still_stamps() {
2554        let mut d = db();
2555        d.set_policy(Policy::AllKeysLru);
2556        d.sadd(b"s", [&b"a"[..]].into_iter()).expect("room");
2557
2558        // Warm the memo, then run the key hard with nothing written in between,
2559        // which is the case the memo exists for.
2560        d.scard(b"s").expect("a set");
2561        d.clock().advance(120_000);
2562        for _ in 0..64 {
2563            d.scard(b"s").expect("a set");
2564        }
2565        assert_eq!(d.idle_secs(b"s"), Some(0), "the memo swallowed the stamp");
2566    }
2567
2568    /// Under LFU the same bits are a counter, and it climbs with use rather than
2569    /// resetting to now.
2570    #[test]
2571    fn the_counter_climbs_under_an_lfu_policy() {
2572        let mut d = db();
2573        d.set_policy(Policy::AllKeysLfu);
2574        d.seed(7);
2575        d.set_plain(b"k", b"v").expect("room");
2576        let start = d.freq(b"k").expect("there");
2577
2578        for _ in 0..200 {
2579            d.get(b"k").expect("a string").expect("still there");
2580        }
2581        let hot = d.freq(b"k").expect("there");
2582        assert!(hot > start, "{hot} did not climb from {start}");
2583
2584        // And a key nobody reads decays rather than holding its place forever.
2585        d.set_plain(b"cold", b"v").expect("room");
2586        d.clock().advance(60_000 * 10);
2587        assert!(d.freq(b"cold").expect("there") < start);
2588    }
2589
2590    /// Nothing goes under `noeviction`, which is the only promise that policy
2591    /// makes and the reason it is the default.
2592    #[test]
2593    fn noeviction_evicts_nothing() {
2594        let mut d = db();
2595        for i in 0..200u32 {
2596            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2597        }
2598        assert!(!d.evict_one());
2599        assert_eq!(d.len(), 200);
2600        assert_eq!(d.evicted_keys(), 0);
2601    }
2602
2603    /// A volatile policy on a database where nothing has a deadline is the
2604    /// classic surprise: it looks configured and it cannot free a byte.
2605    #[test]
2606    fn a_volatile_policy_with_no_deadlines_anywhere_cannot_evict() {
2607        let mut d = db();
2608        d.set_policy(Policy::VolatileLru);
2609        for i in 0..200u32 {
2610            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2611        }
2612        assert!(!d.evict_one(), "it found a key it had no business taking");
2613        assert_eq!(d.len(), 200);
2614
2615        // Give one key a deadline and it becomes the only thing that can go,
2616        // however many rounds of sampling that takes.
2617        let deadline = d.clock().now_ms() + 100_000;
2618        d.set_expiry(b"k7", Some(deadline));
2619        assert!(d.evict_one());
2620        assert!(!d.exists(b"k7"));
2621        assert_eq!(d.evicted_keys(), 1);
2622    }
2623
2624    /// The count against a walk, over everything that can move it. If these two
2625    /// ever disagree the count is worse than useless, because `INFO` would be
2626    /// reporting a number that looks like a measurement.
2627    #[test]
2628    fn the_deadline_count_says_what_a_walk_of_the_keyspace_says() {
2629        let mut d = db();
2630        let now = d.clock().now_ms();
2631        let check = |d: &mut Keyspace, note: &str| {
2632            let mut names = Vec::new();
2633            d.keys(|k| names.push(k.to_vec()));
2634            let walked = names
2635                .iter()
2636                .filter(|k| matches!(d.deadline_of(k), Ask::At(_)))
2637                .count();
2638            assert_eq!(d.expires(), walked, "{note}");
2639        };
2640
2641        for i in 0..40u32 {
2642            d.set_plain(format!("s{i}").as_bytes(), b"v").expect("room");
2643            d.sadd(format!("c{i}").as_bytes(), [b"m".as_slice()].into_iter())
2644                .expect("room");
2645        }
2646        check(&mut d, "nothing has a deadline yet");
2647        assert_eq!(d.expires(), 0);
2648
2649        // On, on again with a different deadline, and off.
2650        for i in (0..40u32).step_by(2) {
2651            d.set_expiry(format!("s{i}").as_bytes(), Some(now + 500_000));
2652            d.set_expiry(format!("c{i}").as_bytes(), Some(now + 500_000));
2653        }
2654        check(&mut d, "half of each type has one");
2655        assert_eq!(d.expires(), 40);
2656        for i in (0..40u32).step_by(4) {
2657            d.set_expiry(format!("s{i}").as_bytes(), Some(now + 900_000));
2658        }
2659        check(&mut d, "moving a deadline is not gaining one");
2660        assert_eq!(d.expires(), 40);
2661        for i in (0..40u32).step_by(4) {
2662            d.set_expiry(format!("c{i}").as_bytes(), None);
2663        }
2664        check(&mut d, "and PERSIST gives them back");
2665        assert_eq!(d.expires(), 30);
2666
2667        // Written over, which is the path where the record loses its deadline
2668        // without anybody saying so.
2669        d.set_plain(b"s2", b"fresh").expect("room");
2670        check(&mut d, "a plain SET drops the deadline it wrote over");
2671
2672        // Renamed, deleted, expired and evicted.
2673        d.rename(b"s6", b"s6new", false);
2674        check(&mut d, "a rename moved one rather than losing it");
2675        d.drop_key(b"s6new");
2676        d.drop_key(b"c2");
2677        check(&mut d, "two deleted");
2678        d.psetex(b"gone", 50, b"v").expect("room");
2679        check(&mut d, "and one more with a short deadline");
2680        d.clock().advance(60);
2681        assert_eq!(d.kind_of(b"gone"), None, "which the read reaped");
2682        check(&mut d, "so the count lost it too");
2683        d.set_policy(Policy::VolatileRandom);
2684        assert!(d.evict_one());
2685        check(&mut d, "eviction under a volatile policy takes one of them");
2686
2687        d.clear();
2688        assert_eq!(d.expires(), 0, "and FLUSHDB takes the lot");
2689    }
2690
2691    /// The point of the count on the eviction path. A volatile policy with
2692    /// nothing to evict answers on the comparison rather than on four rounds of
2693    /// buckets, and it has to still answer `false`.
2694    #[test]
2695    fn a_volatile_policy_asks_the_count_before_it_samples() {
2696        let mut d = db();
2697        d.set_policy(Policy::VolatileLfu);
2698        for i in 0..500u32 {
2699            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2700        }
2701        assert_eq!(d.expires(), 0);
2702        assert!(!d.evict_one(), "nothing is eligible and nothing went");
2703        assert_eq!(d.len(), 500);
2704
2705        // And the fast path gets out of the way the moment one key qualifies.
2706        d.set_expiry(b"k123", Some(d.clock().now_ms() + 100_000));
2707        assert_eq!(d.expires(), 1);
2708        assert!(d.evict_one());
2709        assert!(!d.exists(b"k123"));
2710        assert_eq!(d.expires(), 0, "and the count went with it");
2711    }
2712
2713    /// A needle in a haystack, which is the case sampling the whole keyspace
2714    /// could not do.
2715    ///
2716    /// Fifty thousand keys and three of them with a deadline. Under a volatile
2717    /// policy those three are the only ones that may go, and four rounds of
2718    /// sixty four buckets drawn from the whole index would land on one of them
2719    /// about once in a hundred tries. Drawn from the index of just the keys that
2720    /// carry a deadline it is the only thing there is to land on.
2721    ///
2722    /// Three of them and not one, so that the test is about finding an eligible
2723    /// key rather than about a table with a single entry in it.
2724    #[test]
2725    fn a_volatile_policy_finds_the_one_key_in_a_database_that_is_not_volatile() {
2726        let mut d = db();
2727        d.set_policy(Policy::VolatileLru);
2728        for i in 0..50_000u32 {
2729            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2730        }
2731        let deadline = d.clock().now_ms() + 100_000;
2732        for k in [b"k7".as_slice(), b"k30000", b"k49999"] {
2733            assert!(d.set_expiry(k, Some(deadline)));
2734        }
2735        assert_eq!(d.expires(), 3);
2736
2737        for round in 0..3 {
2738            assert!(d.evict_one(), "round {round} found nothing to take");
2739        }
2740        assert_eq!(d.expires(), 0, "all three went");
2741        assert_eq!(d.len(), 50_000 - 3, "and nothing else did");
2742        assert!(!d.evict_one(), "and now there is nothing eligible left");
2743        assert_eq!(d.len(), 50_000 - 3);
2744    }
2745
2746    /// The direction of the score, which is the thing worth pinning. A test that
2747    /// only checked something was evicted would pass just as happily on a cache
2748    /// that keeps the cold keys and throws away the hot ones.
2749    #[test]
2750    fn the_stale_key_goes_before_the_fresh_one() {
2751        let mut d = db();
2752        d.set_policy(Policy::AllKeysLru);
2753        // Two keys is a small enough database that a bucket holds both of them
2754        // and the pick is between them rather than between whatever turned up.
2755        d.set_plain(b"cold", b"v").expect("room");
2756        d.clock().advance(600_000);
2757        d.set_plain(b"hot", b"v").expect("room");
2758
2759        assert!(d.evict_one());
2760        assert!(!d.exists(b"cold"), "it kept the stale one");
2761        assert!(d.exists(b"hot"), "it took the fresh one");
2762    }
2763
2764    /// Under `volatile-ttl` the ordering is by deadline and not by use, so the
2765    /// key about to expire anyway is the one that goes.
2766    #[test]
2767    fn the_soonest_deadline_goes_first() {
2768        let mut d = db();
2769        d.set_policy(Policy::VolatileTtl);
2770        let now = d.clock().now_ms();
2771        d.set_plain(b"soon", b"v").expect("room");
2772        d.set_plain(b"later", b"v").expect("room");
2773        d.set_expiry(b"soon", Some(now + 10_000));
2774        d.set_expiry(b"later", Some(now + 900_000));
2775
2776        assert!(d.evict_one());
2777        assert!(!d.exists(b"soon"));
2778        assert!(d.exists(b"later"));
2779    }
2780
2781    /// Under LFU the key nobody reads goes, even though it was written more
2782    /// recently than the one that survives. That is the difference between the
2783    /// two families and it is invisible to a test written against the clock.
2784    #[test]
2785    fn the_least_used_key_goes_under_lfu() {
2786        let mut d = db();
2787        d.set_policy(Policy::AllKeysLfu);
2788        d.seed(11);
2789        d.set_plain(b"popular", b"v").expect("room");
2790        for _ in 0..300 {
2791            d.get(b"popular").expect("a string").expect("still there");
2792        }
2793        // Written after the reads above, so under any clock policy this would be
2794        // the freshest key in the database and the last thing to go.
2795        d.set_plain(b"ignored", b"v").expect("room");
2796
2797        assert!(d.evict_one());
2798        assert!(!d.exists(b"ignored"));
2799        assert!(d.exists(b"popular"));
2800    }
2801
2802    /// Sampling has to keep working when almost every bucket it looks in is
2803    /// empty, which is what a database looks like after most of it is deleted.
2804    #[test]
2805    fn a_nearly_empty_database_still_gives_up_a_key() {
2806        let mut d = db();
2807        d.set_policy(Policy::AllKeysRandom);
2808        for i in 0..4000u32 {
2809            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2810        }
2811        for i in 0..3999u32 {
2812            d.drop_key(format!("k{i}").as_bytes());
2813        }
2814        assert_eq!(d.len(), 1);
2815
2816        // One key in a directory sized for four thousand. It may take more than
2817        // one round to land on it, and it may take more than one call, but the
2818        // rounds are bounded and so is this loop.
2819        let mut went = false;
2820        for _ in 0..500 {
2821            if d.evict_one() {
2822                went = true;
2823                break;
2824            }
2825        }
2826        assert!(went, "sampling never found the one key that was left");
2827        assert_eq!(d.len(), 0);
2828        assert!(!d.evict_one(), "and an empty database has nothing to give");
2829    }
2830
2831    /// Eviction and expiry are counted apart, so a key that was already dead
2832    /// when sampling found it is not billed as an eviction.
2833    #[test]
2834    fn a_dead_key_is_not_evicted() {
2835        let mut d = db();
2836        d.set_policy(Policy::AllKeysLru);
2837        let now = d.clock().now_ms();
2838        d.set_plain(b"k", b"v").expect("room");
2839        d.set_expiry(b"k", Some(now + 1000));
2840        d.clock().advance(5000);
2841
2842        assert!(!d.evict_one(), "it evicted a key that was already dead");
2843        assert_eq!(d.evicted_keys(), 0);
2844    }
2845
2846    /// The point of the pool. A round looks at five keys, takes one, and used to
2847    /// throw the other four away, so the second worst key in the database had to
2848    /// be found again from scratch every time.
2849    #[test]
2850    fn a_candidate_that_was_not_taken_is_still_in_the_running() {
2851        let mut d = db();
2852        d.set_policy(Policy::AllKeysLru);
2853        for i in 0..40u32 {
2854            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2855            d.clock().advance(1000);
2856        }
2857        assert!(d.pool.is_empty(), "nothing has sampled anything yet");
2858
2859        assert!(d.evict_one());
2860        assert!(
2861            !d.pool.is_empty(),
2862            "every key it looked at and did not take was thrown away"
2863        );
2864    }
2865
2866    /// A candidate is a key and not an address, so it can stop being a key
2867    /// between the round that spotted it and the round that wants it. Every one
2868    /// of them going at once is the worst case, and the answer has to be the
2869    /// live key rather than a shrug.
2870    #[test]
2871    fn a_candidate_that_went_away_is_stepped_over() {
2872        let mut d = db();
2873        d.set_policy(Policy::AllKeysLru);
2874        for i in 0..40u32 {
2875            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2876            d.clock().advance(1000);
2877        }
2878        assert!(d.evict_one());
2879        assert!(!d.pool.is_empty());
2880
2881        // By hand, so every candidate still held names a key that is not there.
2882        for i in 0..40u32 {
2883            d.drop_key(format!("k{i}").as_bytes());
2884        }
2885        assert_eq!(d.len(), 0);
2886        d.set_plain(b"fresh", b"v").expect("room");
2887
2888        assert!(d.evict_one(), "it gave up on a database with a key in it");
2889        assert!(!d.exists(b"fresh"));
2890        assert!(d.pool.is_empty(), "and the stale ones went with it");
2891    }
2892
2893    /// A score only means something against another score under the same rule,
2894    /// so a pool full of them is worth nothing the moment the rule changes.
2895    #[test]
2896    fn changing_the_policy_throws_the_candidates_away() {
2897        let mut d = db();
2898        d.set_policy(Policy::AllKeysLru);
2899        let now = d.clock().now_ms();
2900        for i in 0..40u32 {
2901            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2902            d.set_expiry(
2903                format!("k{i}").as_bytes(),
2904                Some(now + 100_000 + u64::from(i)),
2905            );
2906            d.clock().advance(1000);
2907        }
2908        assert!(d.evict_one());
2909        assert!(!d.pool.is_empty());
2910
2911        d.set_policy(Policy::VolatileTtl);
2912        assert!(d.pool.is_empty(), "idle seconds against a countdown");
2913
2914        // And the same policy set again is not a change and costs nothing.
2915        d.set_policy(Policy::VolatileTtl);
2916        assert!(d.evict_one());
2917        assert!(!d.pool.is_empty());
2918        d.set_policy(Policy::VolatileTtl);
2919        assert!(!d.pool.is_empty());
2920    }
2921
2922    /// A fair draw has no ordering for a pool to get closer to, so the random
2923    /// pair never copy a key at all.
2924    #[test]
2925    fn a_random_policy_keeps_no_candidates() {
2926        let mut d = db();
2927        d.set_policy(Policy::AllKeysRandom);
2928        for i in 0..40u32 {
2929            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2930        }
2931
2932        assert!(d.evict_one());
2933        assert_eq!(d.len(), 39);
2934        assert!(d.pool.is_empty());
2935        assert_eq!(
2936            d.pool.memory_bytes(),
2937            0,
2938            "and it allocated nothing to do it"
2939        );
2940    }
2941
2942    /// A flush leaves the pool naming keys that are all gone, which the recheck
2943    /// would survive and would pay sixteen lookups for.
2944    #[test]
2945    fn a_flush_takes_the_candidates_with_it() {
2946        let mut d = db();
2947        d.set_policy(Policy::AllKeysLru);
2948        for i in 0..40u32 {
2949            d.set_plain(format!("k{i}").as_bytes(), b"v").expect("room");
2950            d.clock().advance(1000);
2951        }
2952        assert!(d.evict_one());
2953        assert!(!d.pool.is_empty());
2954
2955        d.clear();
2956        assert!(d.pool.is_empty());
2957    }
2958}