From 70ab06b8640416021696d39990fc583098c70610 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Thu, 4 Dec 2014 20:55:59 -0800 Subject: [PATCH] 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. --- storage/filereader.go | 21 ++++++++++++++------- storage/layerreader.go | 7 +++---- storage/layerstore.go | 7 ------- storage/layerupload.go | 27 ++++++++++++++------------- storage/manifeststore.go | 8 ++++++-- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/storage/filereader.go b/storage/filereader.go index 8f1f5205f..bcc2614ef 100644 --- a/storage/filereader.go +++ b/storage/filereader.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "time" "github.com/docker/docker-registry/storagedriver" ) @@ -16,8 +17,9 @@ type fileReader struct { driver storagedriver.StorageDriver // identifying fields - path string - size int64 // size is the total layer size, must be set. + path string + size int64 // size is the total layer size, must be set. + modtime time.Time // mutable fields rc io.ReadCloser // remote read closer @@ -28,16 +30,21 @@ type fileReader struct { func newFileReader(driver storagedriver.StorageDriver, path string) (*fileReader, error) { // Grab the size of the layer file, ensuring existence. - size, err := driver.CurrentSize(path) + fi, err := driver.Stat(path) if err != nil { return nil, err } + if fi.IsDir() { + return nil, fmt.Errorf("cannot read a directory") + } + return &fileReader{ - driver: driver, - path: path, - size: int64(size), + driver: driver, + path: path, + size: fi.Size(), + modtime: fi.ModTime(), }, nil } @@ -126,7 +133,7 @@ func (fr *fileReader) reader() (io.Reader, error) { } // 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 { return nil, err diff --git a/storage/layerreader.go b/storage/layerreader.go index 2cc184fd8..fa2275d92 100644 --- a/storage/layerreader.go +++ b/storage/layerreader.go @@ -11,9 +11,8 @@ import ( type layerReader struct { fileReader - name string // repo name of this layer - digest digest.Digest - createdAt time.Time + name string // repo name of this layer + digest digest.Digest } var _ Layer = &layerReader{} @@ -27,5 +26,5 @@ func (lrs *layerReader) Digest() digest.Digest { } func (lrs *layerReader) CreatedAt() time.Time { - return lrs.createdAt + return lrs.modtime } diff --git a/storage/layerstore.go b/storage/layerstore.go index d731a5b8b..ddebdbcce 100644 --- a/storage/layerstore.go +++ b/storage/layerstore.go @@ -1,8 +1,6 @@ package storage import ( - "time" - "github.com/docker/docker-registry/digest" "github.com/docker/docker-registry/storagedriver" ) @@ -55,11 +53,6 @@ func (ls *layerStore) Fetch(name string, digest digest.Digest) (Layer, error) { fileReader: *fr, name: name, 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 } diff --git a/storage/layerupload.go b/storage/layerupload.go index de1a894ba..3ee593b98 100644 --- a/storage/layerupload.go +++ b/storage/layerupload.go @@ -107,9 +107,13 @@ func (luc *layerUploadController) Finish(size int64, digest digest.Digest) (Laye return nil, err } - if err := luc.writeLayer(fp, size, digest); err != nil { + if nn, err := luc.writeLayer(fp, digest); err != nil { // Cleanup? 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 @@ -281,19 +285,20 @@ func (luc *layerUploadController) validateLayer(fp layerFile, size int64, dgst d return dgst, nil } -// writeLayer actually writes the the layer file into its final destination. -// The layer should be validated before commencing the write. -func (luc *layerUploadController) writeLayer(fp layerFile, size int64, dgst digest.Digest) error { +// writeLayer actually writes the the layer file into its final destination, +// identified by dgst. The layer should be validated before commencing the +// write. +func (luc *layerUploadController) writeLayer(fp layerFile, dgst digest.Digest) (nn int64, err error) { blobPath, err := luc.layerStore.pathMapper.path(blobPathSpec{ digest: dgst, }) if err != nil { - return err + return 0, err } // 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. switch err := err.(type) { 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 // have it written. Although, we do need to verify that the // content that is there is the correct length. - return err + return 0, err } } // Seek our local layer file back now. if _, err := fp.Seek(0, os.SEEK_SET); err != nil { // Cleanup? - return err + return 0, err } // Okay: we can write the file to the blob store. - if err := luc.layerStore.driver.WriteStream(blobPath, 0, uint64(size), fp); err != nil { - return err - } - - return nil + return luc.layerStore.driver.WriteStream(blobPath, 0, fp) } // linkLayer links a valid, written layer blob into the registry under the diff --git a/storage/manifeststore.go b/storage/manifeststore.go index e1760dd8f..a6bdf3b34 100644 --- a/storage/manifeststore.go +++ b/storage/manifeststore.go @@ -22,12 +22,16 @@ func (ms *manifestStore) Exists(name, tag string) (bool, error) { return false, err } - size, err := ms.driver.CurrentSize(p) + fi, err := ms.driver.Stat(p) if err != nil { 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 }