storage/storage_image.go
func (s *storageImageSource) getBlobAndLayerID(info types.BlobInfo) (rc io.ReadCloser, n int64, layerID string, err error) {
	var layer storage.Layer
	var diffOptions *storage.DiffOptions
	// We need a valid digest value.
	err = info.Digest.Validate()
	if err != nil {
		return nil, -1, "", err
	}
	// Check if the blob corresponds to a diff that was used to initialize any layers.  Our
	// callers should try to retrieve layers using their uncompressed digests, so no need to
	// check if they're using one of the compressed digests, which we can't reproduce anyway.
	layers, err := s.imageRef.transport.store.LayersByUncompressedDigest(info.Digest)
	// If it's not a layer, then it must be a data item.
	if len(layers) == 0 {
		b, err := s.imageRef.transport.store.ImageBigData(s.image.ID, info.Digest.String())
		if err != nil {
			return nil, -1, "", err
		}
		r := bytes.NewReader(b)
		logrus.Debugf("exporting opaque data as blob %q", info.Digest.String())
		return ioutil.NopCloser(r), int64(r.Len()), "", nil
	}
	// Step through the list of matching layers.  Tests may want to verify that if we have multiple layers
	// which claim to have the same contents, that we actually do have multiple layers, otherwise we could
	// just go ahead and use the first one every time.
	s.getBlobMutex.Lock()
	i := s.layerPosition[info.Digest]
	s.layerPosition[info.Digest] = i + 1
	s.getBlobMutex.Unlock()
	if len(layers) > 0 {
		layer = layers[i%len(layers)]
	}
	// Force the storage layer to not try to match any compression that was used when the layer was first
	// handed to it.
	noCompression := archive.Uncompressed
	diffOptions = &storage.DiffOptions{
		Compression: &noCompression,
	}
	if layer.UncompressedSize < 0 {
		n = -1
	} else {
		n = layer.UncompressedSize
	}
	logrus.Debugf("exporting filesystem layer %q without compression for blob %q", layer.ID, info.Digest)
	rc, err = s.imageRef.transport.store.Diff("", layer.ID, diffOptions)
	if err != nil {
		return nil, -1, "", err
	}
	return rc, n, layer.ID, err
}
func (s *storageImageSource) getBlobAndLayerID(info types.BlobInfo) (rc io.ReadCloser, n int64, layerID string, err error) {
	var layer storage.Layer
	var diffOptions *storage.DiffOptions
	// We need a valid digest value.
	err = info.Digest.Validate()
	if err != nil {
		return nil, -1, "", err
	}
	// Check if the blob corresponds to a diff that was used to initialize any layers.  Our
	// callers should try to retrieve layers using their uncompressed digests, so no need to
	// check if they're using one of the compressed digests, which we can't reproduce anyway.
	layers, err := s.imageRef.transport.store.LayersByUncompressedDigest(info.Digest)
	// If it's not a layer, then it must be a data item.
	if len(layers) == 0 {
		b, err := s.imageRef.transport.store.ImageBigData(s.image.ID, info.Digest.String())
		if err != nil {
			return nil, -1, "", err
		}
		r := bytes.NewReader(b)
		logrus.Debugf("exporting opaque data as blob %q", info.Digest.String())
		return ioutil.NopCloser(r), int64(r.Len()), "", nil
	}
	// Step through the list of matching layers.  Tests may want to verify that if we have multiple layers
	// which claim to have the same contents, that we actually do have multiple layers, otherwise we could
	// just go ahead and use the first one every time.
	s.getBlobMutex.Lock()
	i := s.layerPosition[info.Digest]
	s.layerPosition[info.Digest] = i + 1
	s.getBlobMutex.Unlock()
	if len(layers) > 0 {
		layer = layers[i%len(layers)]
	}
	// Force the storage layer to not try to match any compression that was used when the layer was first
	// handed to it.
	noCompression := archive.Uncompressed
	diffOptions = &storage.DiffOptions{
		Compression: &noCompression,
	}
	if layer.UncompressedSize < 0 {
		n = -1
	} else {
		n = layer.UncompressedSize
	}
	logrus.Debugf("exporting filesystem layer %q without compression for blob %q", layer.ID, info.Digest)
	rc, err = s.imageRef.transport.store.Diff("", layer.ID, diffOptions)
	if err != nil {
		return nil, -1, "", err
	}
	return rc, n, layer.ID, err
}
func ( s * storageImageSource ) getBlobAndLayerID ( info types . BlobInfo ) ( rc io . ReadCloser , n int64 , layerID string , err error ) { var layer storage . Layer var diffOptions * storage . DiffOptions // We need a valid digest value. err = info . Digest . Validate ( ) if err != nil { return nil , - 1 , " " , err } // Check if the blob corresponds to a diff that was used to initialize any layers.  Our // callers should try to retrieve layers using their uncompressed digests, so no need to // check if they're using one of the compressed digests, which we can't reproduce anyway. layers , err := s . imageRef . transport . store . LayersByUncompressedDigest ( info . Digest ) // If it's not a layer, then it must be a data item. if len ( layers ) == 0 { b , err := s . imageRef . transport . store . ImageBigData ( s . image . ID , info . Digest . String ( ) ) if err != nil { return nil , - 1 , " " , err } r := bytes . NewReader ( b ) logrus . Debugf ( " " , info . Digest . String ( ) ) return ioutil . NopCloser ( r ) , int64 ( r . Len ( ) ) , " " , nil } // Step through the list of matching layers.  Tests may want to verify that if we have multiple layers // which claim to have the same contents, that we actually do have multiple layers, otherwise we could // just go ahead and use the first one every time. s . getBlobMutex . Lock ( ) i := s . layerPosition [ info . Digest ] s . layerPosition [ info . Digest ] = i + 1 s . getBlobMutex . Unlock ( ) if len ( layers ) > 0 { layer = layers [ i % len ( layers ) ] } // Force the storage layer to not try to match any compression that was used when the layer was first // handed to it. noCompression := archive . Uncompressed diffOptions = & storage . DiffOptions { Compression : & noCompression , } if layer . UncompressedSize < 0 { n = - 1 } else { n = layer . UncompressedSize } logrus . Debugf ( " " , layer . ID , info . Digest ) rc , err = s . imageRef . transport . store . Diff ( " " , layer . ID , diffOptions ) if err != nil { return nil , - 1 , " " , err } return rc , n , layer . ID , err }
// getBlobAndLayer reads the data blob or filesystem layer which matches the digest and size, if given.
getBlobAndLayer reads the data blob or filesystem layer which matches the digest and size if given .