From 39589800b4750bf28078efe57f7f1e74d971248f Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Thu, 3 Dec 2015 18:23:21 -0800 Subject: [PATCH] Avoid a HEAD request for each layer in a v2 pull We were calling Stat for each layer to get the size so we could indicate progress, but https://github.com/docker/distribution/pull/1226 made it possible to get the length from the GET request that Open initiates. Saving one round-trip per layer should make pull operations slightly faster and more robust. Signed-off-by: Aaron Lehmann --- distribution/pull_v2.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go index fb25545c11..0c65d8d744 100644 --- a/distribution/pull_v2.go +++ b/distribution/pull_v2.go @@ -130,14 +130,6 @@ func (p *v2Puller) download(di *downloadInfo) { blobs := p.repo.Blobs(context.Background()) - desc, err := blobs.Stat(context.Background(), di.digest) - if err != nil { - logrus.Debugf("Error statting layer: %v", err) - di.err <- err - return - } - di.size = desc.Size - layerDownload, err := blobs.Open(context.Background(), di.digest) if err != nil { logrus.Debugf("Error fetching layer: %v", err) @@ -146,6 +138,21 @@ func (p *v2Puller) download(di *downloadInfo) { } defer layerDownload.Close() + di.size, err = layerDownload.Seek(0, os.SEEK_END) + if err != nil { + // Seek failed, perhaps because there was no Content-Length + // header. This shouldn't fail the download, because we can + // still continue without a progress bar. + di.size = 0 + } else { + // Restore the seek offset at the beginning of the stream. + _, err = layerDownload.Seek(0, os.SEEK_SET) + if err != nil { + di.err <- err + return + } + } + verifier, err := digest.NewDigestVerifier(di.digest) if err != nil { di.err <- err