containerd/content/content.go
Stephen J Day d99756a8a2
content: allow reset via Truncate
To make restarting after failed pull less racy, we define `Truncate(size
int64) error` on `content.Writer` for the zero offset. Truncating a
writer will dump any existing data and digest state and start from the
beginning. All subsequent writes will start from the zero offset.

For the service, we support this by defining the behavior for a write
that changes the offset. To keep this narrow, we only support writes out
of order at the offset 0, which causes the writer to dump existing data
and reset the local hash.

This makes restarting failed pulls much smoother when there was a
previously encountered error and the source doesn't support arbitrary
seeks or reads at arbitrary offsets. By allowing this to be done while
holding the write lock on a ref, we can restart the full download
without causing a race condition.

Once we implement seeking on the `io.Reader` returned by the fetcher,
this will be less useful, but it is good to ensure that our protocol
properly supports this use case for when streaming is the only option.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-02-28 10:40:02 -08:00

60 lines
1 KiB
Go

package content
import (
"context"
"io"
"sync"
"time"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)
var (
errNotFound = errors.New("content: not found")
errExists = errors.New("content: exists")
BufPool = sync.Pool{
New: func() interface{} {
return make([]byte, 1<<20)
},
}
)
type Info struct {
Digest digest.Digest
Size int64
CommittedAt time.Time
}
type Provider interface {
Reader(ctx context.Context, dgst digest.Digest) (io.ReadCloser, error)
}
type Status struct {
Ref string
Offset int64
Total int64
StartedAt time.Time
UpdatedAt time.Time
}
type Writer interface {
io.WriteCloser
Status() (Status, error)
Digest() digest.Digest
Commit(size int64, expected digest.Digest) error
Truncate(size int64) error
}
type Ingester interface {
Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (Writer, error)
}
func IsNotFound(err error) bool {
return errors.Cause(err) == errNotFound
}
func IsExists(err error) bool {
return errors.Cause(err) == errExists
}