Files
acp/item.go
T
Samuel Cui a420324adb fix: close the two blockers the Linux review found
Both were invisible on Darwin: one needs a real Linux ENOSPC, the other needs
the command's own stderr.

- A non-linear target pre-allocates with fallocate, and a failure there was
  reported as a bare error: it never ran through mappingError, never aborted
  the device and never ended a linear target, unlike every neighbouring path.
  A volume that fills up after the disk-usage snapshot therefore reported a
  target that was "not written" instead of ErrTargetNoSpace. Classify it like
  the rest. TestFullVolumePreallocationReportsNoSpace pins it with a real
  ENOSPC on a small tmpfs (it fails on the previous revision), and
  TestNonLinearTargetOnRefusingDeviceReportsATargetFailure records that a
  device refusing fallocate reports its own refusal rather than claiming no
  space. The drain test now uses a linear target, which is the shape that
  actually queues buffers before the write fails.
- cmd/acp registered the progress bar and then the report collector, and a run
  keeps one event handler, so the bar received nothing: the command printed its
  construction frame and no update. Compose the two handlers in the command and
  pin it end to end (the new test fails on the previous revision). README now
  says a command that wants both composes them.
- item.go still promised that an empty Targets slice hashes the source; the
  default HashOff reads nothing. TESTING.md and TODO.md now describe the Linux
  suite that actually exists.
2026-09-19 16:41:25 +08:00

86 lines
3.3 KiB
Go

package acp
import (
"io/fs"
"time"
)
// Item is one unit of work owned by the caller.
//
// The caller implements Item over whatever state it owns, so the item is the handle that ties a
// result back to that state: Result.Job is the exact instance that was submitted, and no id
// lookup or payload plumbing is needed. ACP calls Source and Targets under panic protection: the
// first call describes the item, and an item whose description failed is asked for its Source once
// more when it is reported, so a failure path may read Source twice. ACP never keeps the item
// afterwards.
type Item interface {
// Source returns the exact path to read.
Source() string
// Targets returns the destinations of a copy. An empty slice writes nothing: the source is
// read and hashed only when the hash policy produces a hash, so the default HashOff reports
// neither a copy nor a hash.
Targets() []string
}
// SimpleJob is an Item that carries no state of its own: Path is the source and Dsts are the
// destinations. A caller that submits a SimpleJob finds its result by matching Result.Job
// against the pointer it submitted, because SimpleJob has no callback of its own.
type SimpleJob struct {
Path string
Dsts []string
}
// Source returns the path to read.
func (j *SimpleJob) Source() string { return j.Path }
// Targets returns the destinations; an empty slice reads without writing, and it produces a
// hash only when the run's hash policy does.
func (j *SimpleJob) Targets() []string { return j.Dsts }
// Result reports the content facts of one finished item, one outcome per requested target, and
// the item's own error.
//
// A result that carries an error is delivered as soon as it is produced; results without an
// error are buffered. Result order is unspecified: results arrive in completion order, and a
// failure may therefore arrive before a success of the same submission batch. A linear target
// still writes in request order, because one writer consumes items in that order.
type Result struct {
// Job is the exact Item instance that was submitted.
Job Item
// Err is the item-level error. A nil Err means the item completed, even when every
// requested target failed: an item that could not be processed at all is what fails,
// and its target outcomes are still reported.
Err error
// Size, Mode and ModTime describe the source facts the item observed, and WriteTime is
// when its copy stage started.
Size int64
Mode fs.FileMode
ModTime time.Time
WriteTime time.Time
// SHA256 is the hash of the bytes actually read; it is nil when the hash policy produces
// no hash. SignatureCacheHit reports that a stored hash was reused instead of computed.
SHA256 []byte
SignatureCacheHit bool
// Targets holds one outcome per requested target, in request order. A target that was
// not written still has an outcome.
Targets []TargetResult
}
// TargetResult is the outcome of one requested target.
type TargetResult struct {
Path string
// Size is the item's size as read, so a failed or partially written target reports that
// size rather than a count of the bytes that landed there.
Size int64
WriteTime time.Time
// Err is nil when the target was written. Target failures keep their error identity, so
// errors.Is(err, ErrTargetNoSpace) identifies an exhausted medium.
Err error
}