content: refactor content store for API
After iterating on the GRPC API, the changes required for the actual implementation are now included in the content store. The begin change is the move to a single, atomic `Ingester.Writer` method for locking content ingestion on a key. From this, comes several new interface definitions. The main benefit here is the clarification between `Status` and `Info` that came out of the GPRC API. `Status` tells the status of a write, whereas `Info` is for querying metadata about various blobs. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
@@ -1,37 +1,14 @@
|
||||
package content
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Provider gives access to blob content by paths.
|
||||
//
|
||||
// Typically, this is implemented by `*Store`.
|
||||
type Provider interface {
|
||||
GetPath(dgst digest.Digest) (string, error)
|
||||
}
|
||||
|
||||
// OpenBlob opens the blob for reading identified by dgst.
|
||||
//
|
||||
// The opened blob may also implement seek. Callers can detect with io.Seeker.
|
||||
func OpenBlob(provider Provider, dgst digest.Digest) (io.ReadCloser, error) {
|
||||
path, err := provider.GetPath(dgst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fp, err := os.Open(path)
|
||||
return fp, err
|
||||
}
|
||||
|
||||
type Ingester interface {
|
||||
Begin(key string) (*Writer, error)
|
||||
}
|
||||
|
||||
// WriteBlob writes data with the expected digest into the content store. If
|
||||
// expected already exists, the method returns immediately and the reader will
|
||||
// not be consumed.
|
||||
@@ -39,11 +16,23 @@ type Ingester interface {
|
||||
// This is useful when the digest and size are known beforehand.
|
||||
//
|
||||
// Copy is buffered, so no need to wrap reader in buffered io.
|
||||
func WriteBlob(cs Ingester, r io.Reader, ref string, size int64, expected digest.Digest) error {
|
||||
cw, err := cs.Begin(ref)
|
||||
func WriteBlob(ctx context.Context, cs Ingester, r io.Reader, ref string, size int64, expected digest.Digest) error {
|
||||
cw, err := cs.Writer(ctx, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ws, err := cw.Status()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ws.Offset > 0 {
|
||||
// Arbitrary limitation for now. We can detect io.Seeker on r and
|
||||
// resume.
|
||||
return errors.Errorf("cannot resume already started write")
|
||||
}
|
||||
|
||||
buf := bufPool.Get().([]byte)
|
||||
defer bufPool.Put(buf)
|
||||
|
||||
@@ -62,3 +51,8 @@ func WriteBlob(cs Ingester, r io.Reader, ref string, size int64, expected digest
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readFileString(path string) (string, error) {
|
||||
p, err := ioutil.ReadFile(path)
|
||||
return string(p), err
|
||||
}
|
||||
|
Reference in New Issue
Block a user