Files
mesh-catalog/modules/artifact-store-tools/cmd/artifact-store-tools/view.go
T
jschoubben 1bf98663c6 artifact-store-tools: read the store through the registry seats' list, never its files or its read side (ADR 0632 §1, §4; issue 1966)
The docker exec listing and the HTTP door go; held and the sweep's index
skip ask the seat's list too. The store's address file is the image seat's
reach, used for the catalogue's definitions only.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 21:11:15 +01:00

132 lines
3.3 KiB
Go

package main
import (
"sort"
)
// View is the store at one moment, as its seats list it (listed.go).
type View struct {
L *Listing
// M is each manifest read, by Key.
M map[string]*Manifest
// Unread is each manifest that could not be read, by Key, with why.
Unread map[string]string
// Held is each manifest a hold on its seat keeps from retention, by Key.
Held map[string]bool
}
// Marks are the blobs one manifest keeps from the store's collector: its own content, its
// configuration and its layers, and for an index the manifests it lists. A manifest that could not be
// read marks only itself here, and the answers that rest on it say so.
func (v *View) Marks(repo, digest string) []string {
out := []string{digest}
if m := v.M[Key(repo, digest)]; m != nil {
out = append(out, m.Refs...)
out = append(out, m.Children...)
}
return out
}
// Marked is every blob some manifest marks, leaving out the manifests named in without — the
// collector's own mark, and the mark it would make once those are gone.
func (v *View) Marked(without map[string]bool) map[string]bool {
marked := map[string]bool{}
for name, r := range v.L.Repos {
for d := range r.Revisions {
if without[Key(name, d)] {
continue
}
for _, b := range v.Marks(name, d) {
marked[b] = true
}
}
}
return marked
}
// Bytes is the size of these blobs, as the store holds them; a blob the store does not hold counts
// nothing.
func (v *View) Bytes(blobs map[string]bool) int64 {
var n int64
for b := range blobs {
n += v.L.Blobs[b]
}
return n
}
// Total is the size of every blob the store holds.
func (v *View) Total() int64 {
var n int64
for _, s := range v.L.Blobs {
n += s
}
return n
}
// Unmarked is the bytes and count of the blobs no manifest marks, once the manifests in without are
// gone: what the nightly collector frees.
func (v *View) Unmarked(without map[string]bool) (int64, int) {
marked := v.Marked(without)
var n int64
count := 0
for b, s := range v.L.Blobs {
if !marked[b] {
n += s
count++
}
}
return n, count
}
// RepoBlobs are the blobs one repository's manifests mark.
func (v *View) RepoBlobs(name string) map[string]bool {
out := map[string]bool{}
if r := v.L.Repos[name]; r != nil {
for d := range r.Revisions {
for _, b := range v.Marks(name, d) {
out[b] = true
}
}
}
return out
}
// Shared are the blobs that the manifests of more than one repository mark.
func (v *View) Shared() map[string]bool {
seen := map[string]string{}
shared := map[string]bool{}
for _, name := range v.L.RepoNames() {
for b := range v.RepoBlobs(name) {
if first, ok := seen[b]; ok && first != name {
shared[b] = true
} else {
seen[b] = name
}
}
}
return shared
}
// tagsOf is a repository's tags, in order, with what each names.
func tagsOf(r *Repo) []map[string]string {
names := make([]string, 0, len(r.Tags))
for t := range r.Tags {
names = append(names, t)
}
sort.Strings(names)
out := make([]map[string]string, 0, len(names))
for _, t := range names {
out = append(out, map[string]string{"tag": t, "digest": r.Tags[t]})
}
return out
}
// taggedDigests are the manifests some tag names, in one repository.
func taggedDigests(r *Repo) map[string]bool {
out := map[string]bool{}
for _, d := range r.Tags {
out[d] = true
}
return out
}