diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-01-19 20:10:51 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-01-19 21:29:56 +0900 |
| commit | d933234784bf3bd511869d55fb145dc1d9601ce1 (patch) | |
| tree | a898f3c84b35155e0154b95c56016cd866b26228 /internal/pkg/pkg.go | |
| parent | 1c49c75f95855a6b75689f1962dc918ed67c2ccc (diff) | |
internal/pkg: make checksum available to cure
This enables deduplication by value as implemented in execArtifact.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/pkg.go')
| -rw-r--r-- | internal/pkg/pkg.go | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index 65bf5e17..738eb5c0 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -187,7 +187,7 @@ type FContext struct { TContext // Cured top-level dependencies looked up by Pathname. - deps map[Artifact]*check.Absolute + deps map[Artifact]cureRes } // InvalidLookupError is the identifier of non-dependency [Artifact] looked up @@ -200,15 +200,17 @@ func (e InvalidLookupError) Error() string { var _ error = InvalidLookupError{} -// Pathname returns the identifier pathname of an [Artifact]. Calling Pathname -// with an [Artifact] not part of the slice returned by [Artifact.Dependencies] -// panics. -func (f *FContext) Pathname(a Artifact) *check.Absolute { - if p, ok := f.deps[a]; ok { - return p - } else { - panic(InvalidLookupError(f.cache.Ident(a).Value())) +// GetArtifact returns the identifier pathname and checksum of an [Artifact]. +// Calling Pathname with an [Artifact] not part of the slice returned by +// [Artifact.Dependencies] panics. +func (f *FContext) GetArtifact(a Artifact) ( + pathname *check.Absolute, + checksum unique.Handle[Checksum], +) { + if res, ok := f.deps[a]; ok { + return res.pathname, res.checksum } + panic(InvalidLookupError(f.cache.Ident(a).Value())) } // An Artifact is a read-only reference to a piece of data that may be created @@ -378,6 +380,12 @@ const ( checksumLinknamePrefix = "../" + dirChecksum + "/" ) +// cureRes are the non-error results returned by [Cache.Cure]. +type cureRes struct { + pathname *check.Absolute + checksum unique.Handle[Checksum] +} + // A pendingArtifactDep is a dependency [Artifact] pending concurrent curing, // subject to the cures limit. Values pointed to by result addresses are safe // to access after the [sync.WaitGroup] associated with this pendingArtifactDep @@ -389,7 +397,7 @@ type pendingArtifactDep struct { // Address of result pathname populated during [Cache.Cure] and dereferenced // if curing succeeds. - resP **check.Absolute + resP *cureRes // Address of result error slice populated during [Cache.Cure], dereferenced // after acquiring errsMu if curing fails. No additional action is taken, @@ -437,7 +445,7 @@ type Cache struct { checksumMu sync.RWMutex // Identifier to content pair cache. - ident map[unique.Handle[ID]]Checksum + ident map[unique.Handle[ID]]unique.Handle[Checksum] // Identifier to error pair for unrecoverably faulted [Artifact]. identErr map[unique.Handle[ID]]error // Pending identifiers, accessed through Cure for entries not in ident. @@ -650,7 +658,7 @@ func (c *Cache) Scrub(checks int) error { c.checksumMu.Lock() defer c.checksumMu.Unlock() - c.ident = make(map[unique.Handle[ID]]Checksum) + c.ident = make(map[unique.Handle[ID]]unique.Handle[Checksum]) c.identErr = make(map[unique.Handle[ID]]error) c.artifact.Clear() @@ -848,7 +856,7 @@ func (c *Cache) Scrub(checks int) error { // identifier is stored in identPending and a non-nil channel is returned. func (c *Cache) loadOrStoreIdent(id unique.Handle[ID]) ( done chan<- struct{}, - checksum Checksum, + checksum unique.Handle[Checksum], err error, ) { var ok bool @@ -887,14 +895,14 @@ func (c *Cache) loadOrStoreIdent(id unique.Handle[ID]) ( func (c *Cache) finaliseIdent( done chan<- struct{}, id unique.Handle[ID], - checksum *Checksum, + checksum unique.Handle[Checksum], err error, ) { c.identMu.Lock() if err != nil { c.identErr[id] = err } else { - c.ident[id] = *checksum + c.ident[id] = checksum } delete(c.identPending, id) c.identMu.Unlock() @@ -1091,7 +1099,7 @@ func (e DependencyError) Error() string { // calls to Cure are not subject to the cures limit. func (c *Cache) Cure(a Artifact) ( pathname *check.Absolute, - checksum Checksum, + checksum unique.Handle[Checksum], err error, ) { if c.threshold > 0 { @@ -1181,7 +1189,7 @@ func (e *DependencyCureError) Error() string { // cure implements Cure without checking the full dependency graph. func (c *Cache) cure(a Artifact) ( pathname *check.Absolute, - checksum Checksum, + checksum unique.Handle[Checksum], err error, ) { id := c.Ident(a) @@ -1193,7 +1201,7 @@ func (c *Cache) cure(a Artifact) ( defer func() { if err != nil { pathname = nil - checksum = Checksum{} + checksum = unique.Handle[Checksum]{} } }() @@ -1202,7 +1210,7 @@ func (c *Cache) cure(a Artifact) ( if done == nil { return } else { - defer func() { c.finaliseIdent(done, id, &checksum, err) }() + defer func() { c.finaliseIdent(done, id, checksum, err) }() } _, err = os.Lstat(pathname.String()) @@ -1211,7 +1219,12 @@ func (c *Cache) cure(a Artifact) ( if name, err = os.Readlink(pathname.String()); err != nil { return } - err = Decode(&checksum, path.Base(name)) + buf := c.getIdentBuf() + err = Decode((*Checksum)(buf[:]), path.Base(name)) + if err == nil { + checksum = unique.Make(Checksum(buf[:])) + } + c.putIdentBuf(buf) return } if !errors.Is(err, os.ErrNotExist) { @@ -1234,8 +1247,8 @@ func (c *Cache) cure(a Artifact) ( var checksumPathname *check.Absolute var checksumFi os.FileInfo if kc, ok := a.(KnownChecksum); ok { - checksum = kc.Checksum() - checksums = Encode(checksum) + checksum = unique.Make(kc.Checksum()) + checksums = Encode(checksum.Value()) checksumPathname = c.base.Append( dirChecksum, checksums, @@ -1288,8 +1301,11 @@ func (c *Cache) cure(a Artifact) ( if checksumPathname == nil { h := sha512.New384() h.Write(data) - h.Sum(checksum[:0]) - checksums = Encode(checksum) + buf := c.getIdentBuf() + h.Sum(buf[:0]) + checksum = unique.Make(Checksum(buf[:])) + checksums = Encode(Checksum(buf[:])) + c.putIdentBuf(buf) checksumPathname = c.base.Append( dirChecksum, checksums, @@ -1297,10 +1313,10 @@ func (c *Cache) cure(a Artifact) ( } else if c.IsStrict() { h := sha512.New384() h.Write(data) - if got := Checksum(h.Sum(nil)); got != checksum { + if got := Checksum(h.Sum(nil)); got != checksum.Value() { err = &ChecksumMismatchError{ Got: got, - Want: checksum, + Want: checksum.Value(), } return } @@ -1355,11 +1371,11 @@ func (c *Cache) cure(a Artifact) ( case FloodArtifact: deps := a.Dependencies() - f := FContext{t, make(map[Artifact]*check.Absolute, len(deps))} + f := FContext{t, make(map[Artifact]cureRes, len(deps))} var wg sync.WaitGroup wg.Add(len(deps)) - res := make([]*check.Absolute, len(deps)) + res := make([]cureRes, len(deps)) errs := make(DependencyCureError, 0, len(deps)) var errsMu sync.Mutex for i, d := range deps { @@ -1422,20 +1438,18 @@ func (c *Cache) cure(a Artifact) ( } if checksumPathname == nil { - checksum = gotChecksum - checksums = Encode(checksum) + checksum = unique.Make(gotChecksum) + checksums = Encode(gotChecksum) checksumPathname = c.base.Append( dirChecksum, checksums, ) - } else { - if gotChecksum != checksum { - err = &ChecksumMismatchError{ - Got: gotChecksum, - Want: checksum, - } - return + } else if gotChecksum != checksum.Value() { + err = &ChecksumMismatchError{ + Got: gotChecksum, + Want: checksum.Value(), } + return } if err = os.Chmod(t.work.String(), 0700); err != nil { @@ -1470,9 +1484,9 @@ func (c *Cache) cure(a Artifact) ( func (pending *pendingArtifactDep) cure(c *Cache) { defer pending.Done() - pathname, _, err := c.cure(pending.a) + var err error + pending.resP.pathname, pending.resP.checksum, err = c.cure(pending.a) if err == nil { - *pending.resP = pathname return } @@ -1536,7 +1550,7 @@ func open( msg: msg, base: base, - ident: make(map[unique.Handle[ID]]Checksum), + ident: make(map[unique.Handle[ID]]unique.Handle[Checksum]), identErr: make(map[unique.Handle[ID]]error), identPending: make(map[unique.Handle[ID]]<-chan struct{}), } |
