internal/pkg: cache flags
Some checks failed
Test / Flake checks (push) Has been cancelled
Test / Create distribution (push) Has been cancelled
Test / ShareFS (push) Has been cancelled
Test / Sandbox (race detector) (push) Has been cancelled
Test / Hakurei (push) Has been cancelled
Test / Sandbox (push) Has been cancelled
Test / Hakurei (race detector) (push) Has been cancelled
Some checks failed
Test / Flake checks (push) Has been cancelled
Test / Create distribution (push) Has been cancelled
Test / ShareFS (push) Has been cancelled
Test / Sandbox (race detector) (push) Has been cancelled
Test / Hakurei (push) Has been cancelled
Test / Sandbox (push) Has been cancelled
Test / Hakurei (race detector) (push) Has been cancelled
This is cleaner for extending the API. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -13,7 +13,6 @@ import (
|
||||
"hash"
|
||||
"io"
|
||||
"io/fs"
|
||||
"iter"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -331,23 +330,6 @@ type FloodArtifact interface {
|
||||
Artifact
|
||||
}
|
||||
|
||||
// Flood returns an iterator over the dependency tree of an [Artifact].
|
||||
func Flood(a Artifact) iter.Seq[Artifact] {
|
||||
return func(yield func(Artifact) bool) {
|
||||
for _, d := range a.Dependencies() {
|
||||
if !yield(d) {
|
||||
return
|
||||
}
|
||||
|
||||
for d0 := range Flood(d) {
|
||||
if !yield(d0) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TrivialArtifact refers to an [Artifact] that cures without requiring that
|
||||
// any other [Artifact] is cured before it. Its dependency tree is ignored after
|
||||
// computing its identifier.
|
||||
@@ -506,6 +488,23 @@ type pendingArtifactDep struct {
|
||||
*sync.WaitGroup
|
||||
}
|
||||
|
||||
const (
|
||||
// CValidateKnown causes [KnownChecksum] outcomes to be validated to match
|
||||
// its intended checksum.
|
||||
//
|
||||
// A correct implementation of [KnownChecksum] does not successfully cure
|
||||
// with output not matching its intended checksum. When an implementation
|
||||
// fails to perform this validation correctly, the on-disk format enters
|
||||
// an inconsistent state (correctable by [Cache.Scrub]).
|
||||
//
|
||||
// This flag causes [Cache.Cure] to always compute the checksum, and reject
|
||||
// a cure if it does not match the intended checksum.
|
||||
//
|
||||
// This behaviour significantly reduces performance and is not recommended
|
||||
// outside of testing a custom [Artifact] implementation.
|
||||
CValidateKnown = 1 << iota
|
||||
)
|
||||
|
||||
// Cache is a support layer that implementations of [Artifact] can use to store
|
||||
// cured [Artifact] data in a content addressed fashion.
|
||||
type Cache struct {
|
||||
@@ -525,12 +524,8 @@ type Cache struct {
|
||||
|
||||
// Directory where all [Cache] related files are placed.
|
||||
base *check.Absolute
|
||||
|
||||
// Whether to validate [FileArtifact.Cure] for a [KnownChecksum] file. This
|
||||
// significantly reduces performance.
|
||||
strict bool
|
||||
// Maximum size of a dependency graph.
|
||||
threshold uintptr
|
||||
// Immutable cure options set by [Open].
|
||||
flags int
|
||||
|
||||
// Artifact to [unique.Handle] of identifier cache.
|
||||
artifact sync.Map
|
||||
@@ -563,22 +558,6 @@ type Cache struct {
|
||||
inExec atomic.Bool
|
||||
}
|
||||
|
||||
// IsStrict returns whether the [Cache] strictly verifies checksums.
|
||||
func (c *Cache) IsStrict() bool { return c.strict }
|
||||
|
||||
// SetStrict sets whether the [Cache] strictly verifies checksums, even when
|
||||
// the implementation promises to validate them internally. This significantly
|
||||
// reduces performance and is not recommended outside of testing.
|
||||
//
|
||||
// This method is not safe for concurrent use with any other method.
|
||||
func (c *Cache) SetStrict(strict bool) { c.strict = strict }
|
||||
|
||||
// SetThreshold imposes a maximum size on the dependency graph, checked on every
|
||||
// call to Cure. The zero value disables this check entirely.
|
||||
//
|
||||
// This method is not safe for concurrent use with any other method.
|
||||
func (c *Cache) SetThreshold(threshold uintptr) { c.threshold = threshold }
|
||||
|
||||
// extIdent is a [Kind] concatenated with [ID].
|
||||
type extIdent [wordSize + len(ID{})]byte
|
||||
|
||||
@@ -1229,14 +1208,6 @@ func (e InvalidArtifactError) Error() string {
|
||||
return "artifact " + Encode(e) + " cannot be cured"
|
||||
}
|
||||
|
||||
// DependencyError refers to an artifact with a dependency tree larger than the
|
||||
// threshold specified by a previous call to [Cache.SetThreshold].
|
||||
type DependencyError struct{ A Artifact }
|
||||
|
||||
func (e DependencyError) Error() string {
|
||||
return "artifact has too many dependencies"
|
||||
}
|
||||
|
||||
// Cure cures the [Artifact] and returns its pathname and [Checksum]. Direct
|
||||
// calls to Cure are not subject to the cures limit.
|
||||
func (c *Cache) Cure(a Artifact) (
|
||||
@@ -1252,18 +1223,6 @@ func (c *Cache) Cure(a Artifact) (
|
||||
default:
|
||||
}
|
||||
|
||||
if c.threshold > 0 {
|
||||
var n uintptr
|
||||
for range Flood(a) {
|
||||
if n == c.threshold {
|
||||
err = DependencyError{a}
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
c.msg.Verbosef("visited %d artifacts", n)
|
||||
}
|
||||
|
||||
return c.cure(a, true)
|
||||
}
|
||||
|
||||
@@ -1586,7 +1545,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
}
|
||||
r, err = f.Cure(&RContext{common{c}})
|
||||
if err == nil {
|
||||
if checksumPathname == nil || c.IsStrict() {
|
||||
if checksumPathname == nil || c.flags&CValidateKnown != 0 {
|
||||
h := sha512.New384()
|
||||
hbw := c.getWriter(h)
|
||||
_, err = io.Copy(w, io.TeeReader(r, hbw))
|
||||
@@ -1603,7 +1562,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
if checksumPathname == nil {
|
||||
checksum = unique.Make(Checksum(buf[:]))
|
||||
checksums = Encode(Checksum(buf[:]))
|
||||
} else if c.IsStrict() {
|
||||
} else if c.flags&CValidateKnown != 0 {
|
||||
if got := Checksum(buf[:]); got != checksum.Value() {
|
||||
err = &ChecksumMismatchError{
|
||||
Got: got,
|
||||
@@ -1841,10 +1800,10 @@ func (c *Cache) Close() {
|
||||
func Open(
|
||||
ctx context.Context,
|
||||
msg message.Msg,
|
||||
cures int,
|
||||
flags, cures int,
|
||||
base *check.Absolute,
|
||||
) (*Cache, error) {
|
||||
return open(ctx, msg, cures, base, true)
|
||||
return open(ctx, msg, flags, cures, base, true)
|
||||
}
|
||||
|
||||
// open implements Open but allows omitting the [lockedfile] lock when called
|
||||
@@ -1852,7 +1811,7 @@ func Open(
|
||||
func open(
|
||||
ctx context.Context,
|
||||
msg message.Msg,
|
||||
cures int,
|
||||
flags, cures int,
|
||||
base *check.Absolute,
|
||||
lock bool,
|
||||
) (*Cache, error) {
|
||||
@@ -1874,6 +1833,7 @@ func open(
|
||||
|
||||
c := Cache{
|
||||
cures: make(chan struct{}, cures),
|
||||
flags: flags,
|
||||
|
||||
msg: msg,
|
||||
base: base,
|
||||
|
||||
Reference in New Issue
Block a user