1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! The version counters of the names a cached entry reads (#1778).
//!
//! A name is a view, or a type every read of which an invalidation reaches at once. An
//! invalidation of a name takes the next number of the fence's sequence and raises that
//! name's counter to it; an entry remembers the sequence as it was before its read, and the
//! counters of its names, and is served only while none has moved past it. Nothing is
//! evicted by name: a stale entry stays in the store, refused on every hit, until a fill of
//! its key replaces it or the store's capacity policy drops it.
//!
//! Counters are exact, one per name: an entry checks them for its whole lifetime, and a
//! counter shared by two names would refuse it on every write of the other, for good.
//!
//! # Bounded by the schema
//!
//! Only a fill creates a counter, for the names its read was compiled against. An
//! invalidation of a name no fill holds stamps nothing and registers nothing, so names
//! taken from a request (an administrator's invalidation, a change feed) cannot grow the
//! registry. It is emptied with its cache: a schema reload clears the cache it keeps
//! (`on_schema_reload`), so the names of a schema no longer served leave with its entries,
//! and a tenant's cache, its own, is dropped with the tenant.
//!
//! Emptying it retires each counter, raised to `u64::MAX` under its shard's lock as it is
//! removed: an entry holding one, even a fill that took it a moment before, is never served
//! again, and nothing can take it afterwards. A fill after the clear creates a fresh one,
//! started at its floor as below.
//!
//! # Ordering
//!
//! A counter created after an invalidation of its name found none starts at that name's
//! floor: the fence's hashed slot for it, which every invalidation raises **before** looking
//! the counter up. The creation reads the floor under the map's shard lock, so either the
//! invalidation's lookup finds the counter and raises it, or it ran before the creation took
//! the lock, and the floor the creation reads already holds its stamp. Either way the counter
//! ends past it. A floor shared with another name only starts a counter later than it need,
//! which may refuse the one fill that created it, never more.
use ;
use DashMap;
/// What an invalidation of a name reaches, as a counter of its own.
pub
const KINDS: usize = 5;
/// One counter per name a stored entry reads, by kind.
pub