Update storage package to use StorageDriver.Stat

This change updates the backend storage package that consumes StorageDriver to
use the new Stat call, over CurrentSize. It also makes minor updates for using
WriteStream and ReadStream.
This commit is contained in:
Stephen J Day 2014-12-04 20:55:59 -08:00
parent 2ebc373d91
commit 70ab06b864
5 changed files with 37 additions and 33 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"time"
"github.com/docker/docker-registry/storagedriver" "github.com/docker/docker-registry/storagedriver"
) )
@ -16,8 +17,9 @@ type fileReader struct {
driver storagedriver.StorageDriver driver storagedriver.StorageDriver
// identifying fields // identifying fields
path string path string
size int64 // size is the total layer size, must be set. size int64 // size is the total layer size, must be set.
modtime time.Time
// mutable fields // mutable fields
rc io.ReadCloser // remote read closer rc io.ReadCloser // remote read closer
@ -28,16 +30,21 @@ type fileReader struct {
func newFileReader(driver storagedriver.StorageDriver, path string) (*fileReader, error) { func newFileReader(driver storagedriver.StorageDriver, path string) (*fileReader, error) {
// Grab the size of the layer file, ensuring existence. // Grab the size of the layer file, ensuring existence.
size, err := driver.CurrentSize(path) fi, err := driver.Stat(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if fi.IsDir() {
return nil, fmt.Errorf("cannot read a directory")
}
return &fileReader{ return &fileReader{
driver: driver, driver: driver,
path: path, path: path,
size: int64(size), size: fi.Size(),
modtime: fi.ModTime(),
}, nil }, nil
} }
@ -126,7 +133,7 @@ func (fr *fileReader) reader() (io.Reader, error) {
} }
// If we don't have a reader, open one up. // If we don't have a reader, open one up.
rc, err := fr.driver.ReadStream(fr.path, uint64(fr.offset)) rc, err := fr.driver.ReadStream(fr.path, fr.offset)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -11,9 +11,8 @@ import (
type layerReader struct { type layerReader struct {
fileReader fileReader
name string // repo name of this layer name string // repo name of this layer
digest digest.Digest digest digest.Digest
createdAt time.Time
} }
var _ Layer = &layerReader{} var _ Layer = &layerReader{}
@ -27,5 +26,5 @@ func (lrs *layerReader) Digest() digest.Digest {
} }
func (lrs *layerReader) CreatedAt() time.Time { func (lrs *layerReader) CreatedAt() time.Time {
return lrs.createdAt return lrs.modtime
} }

View File

@ -1,8 +1,6 @@
package storage package storage
import ( import (
"time"
"github.com/docker/docker-registry/digest" "github.com/docker/docker-registry/digest"
"github.com/docker/docker-registry/storagedriver" "github.com/docker/docker-registry/storagedriver"
) )
@ -55,11 +53,6 @@ func (ls *layerStore) Fetch(name string, digest digest.Digest) (Layer, error) {
fileReader: *fr, fileReader: *fr,
name: name, name: name,
digest: digest, digest: digest,
// TODO(stevvooe): Storage backend does not support modification time
// queries yet. Layers "never" change, so just return the zero value
// plus a nano-second.
createdAt: (time.Time{}).Add(time.Nanosecond),
}, nil }, nil
} }

View File

@ -107,9 +107,13 @@ func (luc *layerUploadController) Finish(size int64, digest digest.Digest) (Laye
return nil, err return nil, err
} }
if err := luc.writeLayer(fp, size, digest); err != nil { if nn, err := luc.writeLayer(fp, digest); err != nil {
// Cleanup? // Cleanup?
return nil, err return nil, err
} else if nn != size {
// TODO(stevvooe): Short write. Will have to delete the location and
// report an error. This error needs to be reported to the client.
return nil, fmt.Errorf("short write writing layer")
} }
// Yes! We have written some layer data. Let's make it visible. Link the // Yes! We have written some layer data. Let's make it visible. Link the
@ -281,19 +285,20 @@ func (luc *layerUploadController) validateLayer(fp layerFile, size int64, dgst d
return dgst, nil return dgst, nil
} }
// writeLayer actually writes the the layer file into its final destination. // writeLayer actually writes the the layer file into its final destination,
// The layer should be validated before commencing the write. // identified by dgst. The layer should be validated before commencing the
func (luc *layerUploadController) writeLayer(fp layerFile, size int64, dgst digest.Digest) error { // write.
func (luc *layerUploadController) writeLayer(fp layerFile, dgst digest.Digest) (nn int64, err error) {
blobPath, err := luc.layerStore.pathMapper.path(blobPathSpec{ blobPath, err := luc.layerStore.pathMapper.path(blobPathSpec{
digest: dgst, digest: dgst,
}) })
if err != nil { if err != nil {
return err return 0, err
} }
// Check for existence // Check for existence
if _, err := luc.layerStore.driver.CurrentSize(blobPath); err != nil { if _, err := luc.layerStore.driver.Stat(blobPath); err != nil {
// TODO(stevvooe): This check is kind of problematic and very racy. // TODO(stevvooe): This check is kind of problematic and very racy.
switch err := err.(type) { switch err := err.(type) {
case storagedriver.PathNotFoundError: case storagedriver.PathNotFoundError:
@ -303,22 +308,18 @@ func (luc *layerUploadController) writeLayer(fp layerFile, size int64, dgst dige
// content addressable and we should just use this to ensure we // content addressable and we should just use this to ensure we
// have it written. Although, we do need to verify that the // have it written. Although, we do need to verify that the
// content that is there is the correct length. // content that is there is the correct length.
return err return 0, err
} }
} }
// Seek our local layer file back now. // Seek our local layer file back now.
if _, err := fp.Seek(0, os.SEEK_SET); err != nil { if _, err := fp.Seek(0, os.SEEK_SET); err != nil {
// Cleanup? // Cleanup?
return err return 0, err
} }
// Okay: we can write the file to the blob store. // Okay: we can write the file to the blob store.
if err := luc.layerStore.driver.WriteStream(blobPath, 0, uint64(size), fp); err != nil { return luc.layerStore.driver.WriteStream(blobPath, 0, fp)
return err
}
return nil
} }
// linkLayer links a valid, written layer blob into the registry under the // linkLayer links a valid, written layer blob into the registry under the

View File

@ -22,12 +22,16 @@ func (ms *manifestStore) Exists(name, tag string) (bool, error) {
return false, err return false, err
} }
size, err := ms.driver.CurrentSize(p) fi, err := ms.driver.Stat(p)
if err != nil { if err != nil {
return false, err return false, err
} }
if size == 0 { if fi.IsDir() {
return false, fmt.Errorf("unexpected directory at path: %v, name=%s tag=%s", p, name, tag)
}
if fi.Size() == 0 {
return false, nil return false, nil
} }