فهرست منبع

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 <aaron.lehmann@docker.com>
Aaron Lehmann 9 سال پیش
والد
کامیت
39589800b4
1فایلهای تغییر یافته به همراه15 افزوده شده و 8 حذف شده
  1. 15 8
      distribution/pull_v2.go

+ 15 - 8
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