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
use Keyspace;
use crateError;
use crateNamespace;
use crateOid;
// What a repository holds, answerable from a listing instead of a request per
// object.
//
// A listing reports each key's own length, and a marker is empty, so the size of
// the object a marker claims is not in the listing at all. It is on the content
// key, which lives somewhere else entirely and under a name the repository
// prefix does not reach. That is why measuring a repository cost one `HEAD` per
// object, and why one holding fifty thousand of them cost fifty thousand
// requests every time the cached figure expired.
//
// So the number goes into a key name, where a listing can read it: one empty
// object per marker at `{org}/{repo}/.sizes/{oid}.{size}`, and the total is the
// sum of what the names say.
//
// The same move `.refs/` made for the reverse lookup, for the same reason. The
// bucket is the only database here, and an index is what a database would have
// given for nothing.
const PREFIX: &str = ".sizes/";
pub
// A key of this index rather than a marker. Both live under the repository's
// prefix, and everything that walks that prefix has to tell them apart: read as
// a marker, one of these is a claim on an object whose name ends in a number.
pub
// The oid and the size a key carries, or None if it carries neither.
pub
// After the marker, always. The marker is what a repository holding an object
// means, and this only says how big it is: a size with no marker is counted by
// nobody, where a marker with no size is measured the old way and indexed on the
// next reading. Neither costs anything but a request.
pub async