Skip to content

Commit 9db21de

Browse files
committed
bugfix: avoid to re-calculate blob state for schema1
Use containerd.io/uncompressed label to avoid to re-calculate blob diffID. Signed-off-by: Wei Fu <[email protected]>
1 parent 29eab28 commit 9db21de

File tree

1 file changed

+53
-2
lines changed

1 file changed

+53
-2
lines changed

remotes/docker/schema1/converter.go

+53-2
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,14 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
272272
return err
273273
}
274274

275-
// TODO: Check if blob -> diff id mapping already exists
276-
// TODO: Check if blob empty label exists
275+
reuse, err := c.reuseLabelBlobState(ctx, desc)
276+
if err != nil {
277+
return err
278+
}
279+
280+
if reuse {
281+
return nil
282+
}
277283

278284
ra, err := c.contentStore.ReaderAt(ctx, desc)
279285
if err != nil {
@@ -343,6 +349,17 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
343349

344350
state := calc.State()
345351

352+
cinfo := content.Info{
353+
Digest: desc.Digest,
354+
Labels: map[string]string{
355+
"containerd.io/uncompressed": state.diffID.String(),
356+
},
357+
}
358+
359+
if _, err := c.contentStore.Update(ctx, cinfo, "labels.containerd.io/uncompressed"); err != nil {
360+
return errors.Wrap(err, "failed to update uncompressed label")
361+
}
362+
346363
c.mu.Lock()
347364
c.blobMap[desc.Digest] = state
348365
c.layerBlobs[state.diffID] = desc
@@ -351,6 +368,40 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
351368
return nil
352369
}
353370

371+
func (c *Converter) reuseLabelBlobState(ctx context.Context, desc ocispec.Descriptor) (bool, error) {
372+
cinfo, err := c.contentStore.Info(ctx, desc.Digest)
373+
if err != nil {
374+
return false, errors.Wrap(err, "failed to get blob info")
375+
}
376+
desc.Size = cinfo.Size
377+
378+
diffID, ok := cinfo.Labels["containerd.io/uncompressed"]
379+
if !ok {
380+
return false, nil
381+
}
382+
383+
bState := blobState{empty: false}
384+
385+
if bState.diffID, err = digest.Parse(diffID); err != nil {
386+
log.G(ctx).WithField("id", desc.Digest).Warnf("failed to parse digest from label containerd.io/uncompressed: %v", diffID)
387+
return false, nil
388+
}
389+
390+
// NOTE: there is no need to read header to get compression method
391+
// because there are only two kinds of methods.
392+
if bState.diffID == desc.Digest {
393+
desc.MediaType = images.MediaTypeDockerSchema2Layer
394+
} else {
395+
desc.MediaType = images.MediaTypeDockerSchema2LayerGzip
396+
}
397+
398+
c.mu.Lock()
399+
c.blobMap[desc.Digest] = bState
400+
c.layerBlobs[bState.diffID] = desc
401+
c.mu.Unlock()
402+
return true, nil
403+
}
404+
354405
func (c *Converter) schema1ManifestHistory() ([]ocispec.History, []digest.Digest, error) {
355406
if c.pulledManifest == nil {
356407
return nil, nil, errors.New("missing schema 1 manifest for conversion")

0 commit comments

Comments
 (0)