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