Skip to content

Commit 361278b

Browse files
committed
storage: rework applyDiffWithOptions()
Split it into multiple function to make it reusable without having a layer and so that it can be used unlocked see the following commits. Signed-off-by: Paul Holzinger <[email protected]>
1 parent a6fa507 commit 361278b

File tree

1 file changed

+94
-56
lines changed

1 file changed

+94
-56
lines changed

storage/layers.go

Lines changed: 94 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ type stagedLayerOptions struct {
203203
DiffOptions *drivers.ApplyDiffWithDifferOpts
204204
}
205205

206+
type applyDiffResult struct {
207+
compressedDigest digest.Digest
208+
compressedSize int64
209+
compressionType archive.Compression
210+
uncompressedDigest digest.Digest
211+
uncompressedSize int64
212+
size int64
213+
uids []uint32
214+
gids []uint32
215+
}
216+
206217
// roLayerStore wraps a graph driver, adding the ability to refer to layers by
207218
// name, and keeping track of parent-child relationships, along with a list of
208219
// all known layers.
@@ -2406,37 +2417,27 @@ func createTarSplitFile(r *layerStore, layerID string) (*os.File, error) {
24062417
return os.OpenFile(r.tspath(layerID), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600)
24072418
}
24082419

2409-
// Requires startWriting.
2410-
func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions, diff io.Reader) (size int64, err error) {
2411-
if !r.lockfile.IsReadWrite() {
2412-
return -1, fmt.Errorf("not allowed to modify layer contents at %q: %w", r.layerdir, ErrStoreIsReadOnly)
2413-
}
2414-
2415-
layer, ok := r.lookup(to)
2416-
if !ok {
2417-
return -1, ErrLayerUnknown
2418-
}
2419-
2420+
func applyDiff(layerOptions *LayerOptions, diff io.Reader, tarSplitFile *os.File, applyDriverFunc func(io.Reader) (int64, error)) (*applyDiffResult, error) {
24202421
header := make([]byte, 10240)
24212422
n, err := diff.Read(header)
24222423
if err != nil && err != io.EOF {
2423-
return -1, err
2424+
return nil, err
24242425
}
24252426
compression := archive.DetectCompression(header[:n])
24262427
defragmented := io.MultiReader(bytes.NewReader(header[:n]), diff)
24272428

2428-
// Decide if we need to compute digests
2429-
var compressedDigest, uncompressedDigest digest.Digest // = ""
2429+
result := applyDiffResult{}
2430+
24302431
var compressedDigester, uncompressedDigester digest.Digester // = nil
24312432
if layerOptions != nil && layerOptions.OriginalDigest != "" &&
24322433
layerOptions.OriginalDigest.Algorithm() == digest.Canonical {
2433-
compressedDigest = layerOptions.OriginalDigest
2434+
result.compressedDigest = layerOptions.OriginalDigest
24342435
} else {
24352436
compressedDigester = digest.Canonical.Digester()
24362437
}
24372438
if layerOptions != nil && layerOptions.UncompressedDigest != "" &&
24382439
layerOptions.UncompressedDigest.Algorithm() == digest.Canonical {
2439-
uncompressedDigest = layerOptions.UncompressedDigest
2440+
result.uncompressedDigest = layerOptions.UncompressedDigest
24402441
} else if compression != archive.Uncompressed {
24412442
uncompressedDigester = digest.Canonical.Digester()
24422443
}
@@ -2450,18 +2451,13 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
24502451
compressedCounter := ioutils.NewWriteCounter(compressedWriter)
24512452
defragmented = io.TeeReader(defragmented, compressedCounter)
24522453

2453-
tarSplitFile, err := createTarSplitFile(r, layer.ID)
2454-
if err != nil {
2455-
return -1, err
2456-
}
2457-
defer tarSplitFile.Close()
24582454
tarSplitWriter := pools.BufioWriter32KPool.Get(tarSplitFile)
24592455

24602456
uidLog := make(map[uint32]struct{})
24612457
gidLog := make(map[uint32]struct{})
24622458
var uncompressedCounter *ioutils.WriteCounter
24632459

2464-
size, err = func() (int64, error) { // A scope for defer
2460+
size, err := func() (int64, error) { // A scope for defer
24652461
compressor, err := pgzip.NewWriterLevel(tarSplitWriter, pgzip.BestSpeed)
24662462
if err != nil {
24672463
return -1, err
@@ -2495,63 +2491,105 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
24952491
if err != nil {
24962492
return -1, err
24972493
}
2498-
options := drivers.ApplyDiffOpts{
2499-
Diff: payload,
2500-
Mappings: r.layerMappings(layer),
2501-
MountLabel: layer.MountLabel,
2502-
}
2503-
size, err := r.driver.ApplyDiff(layer.ID, layer.Parent, options)
2504-
if err != nil {
2505-
return -1, err
2506-
}
2507-
return size, err
2494+
2495+
return applyDriverFunc(payload)
25082496
}()
25092497
if err != nil {
2510-
return -1, err
2498+
return nil, err
25112499
}
25122500

25132501
if err := tarSplitWriter.Flush(); err != nil {
2514-
return -1, fmt.Errorf("failed to flush tar split writer buffer: %w", err)
2515-
}
2516-
if err := tarSplitFile.Sync(); err != nil {
2517-
return -1, fmt.Errorf("sync tar split file: %w", err)
2502+
return nil, fmt.Errorf("failed to flush tar split writer buffer: %w", err)
25182503
}
25192504

25202505
if compressedDigester != nil {
2521-
compressedDigest = compressedDigester.Digest()
2506+
result.compressedDigest = compressedDigester.Digest()
25222507
}
25232508
if uncompressedDigester != nil {
2524-
uncompressedDigest = uncompressedDigester.Digest()
2509+
result.uncompressedDigest = uncompressedDigester.Digest()
25252510
}
2526-
if uncompressedDigest == "" && compression == archive.Uncompressed {
2527-
uncompressedDigest = compressedDigest
2511+
if result.uncompressedDigest == "" && compression == archive.Uncompressed {
2512+
result.uncompressedDigest = result.compressedDigest
25282513
}
25292514

2530-
updateDigestMap(&r.bycompressedsum, layer.CompressedDigest, compressedDigest, layer.ID)
2531-
layer.CompressedDigest = compressedDigest
25322515
if layerOptions != nil && layerOptions.OriginalDigest != "" && layerOptions.OriginalSize != nil {
2533-
layer.CompressedSize = *layerOptions.OriginalSize
2516+
result.compressedSize = *layerOptions.OriginalSize
25342517
} else {
2535-
layer.CompressedSize = compressedCounter.Count
2518+
result.compressedSize = compressedCounter.Count
25362519
}
2537-
updateDigestMap(&r.byuncompressedsum, layer.UncompressedDigest, uncompressedDigest, layer.ID)
2538-
layer.UncompressedDigest = uncompressedDigest
2539-
layer.UncompressedSize = uncompressedCounter.Count
2540-
layer.CompressionType = compression
2541-
layer.UIDs = make([]uint32, 0, len(uidLog))
2520+
result.uncompressedSize = uncompressedCounter.Count
2521+
result.compressionType = compression
2522+
2523+
result.uids = make([]uint32, 0, len(uidLog))
25422524
for uid := range uidLog {
2543-
layer.UIDs = append(layer.UIDs, uid)
2525+
result.uids = append(result.uids, uid)
25442526
}
2545-
slices.Sort(layer.UIDs)
2546-
layer.GIDs = make([]uint32, 0, len(gidLog))
2527+
slices.Sort(result.uids)
2528+
result.gids = make([]uint32, 0, len(gidLog))
25472529
for gid := range gidLog {
2548-
layer.GIDs = append(layer.GIDs, gid)
2530+
result.gids = append(result.gids, gid)
25492531
}
2550-
slices.Sort(layer.GIDs)
2532+
slices.Sort(result.gids)
2533+
2534+
result.size = size
2535+
2536+
return &result, err
2537+
}
2538+
2539+
// Requires startWriting.
2540+
func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions, diff io.Reader) (int64, error) {
2541+
if !r.lockfile.IsReadWrite() {
2542+
return -1, fmt.Errorf("not allowed to modify layer contents at %q: %w", r.layerdir, ErrStoreIsReadOnly)
2543+
}
2544+
2545+
layer, ok := r.lookup(to)
2546+
if !ok {
2547+
return -1, ErrLayerUnknown
2548+
}
2549+
2550+
tarSplitFile, err := createTarSplitFile(r, layer.ID)
2551+
if err != nil {
2552+
return -1, err
2553+
}
2554+
defer tarSplitFile.Close()
2555+
2556+
result, err := applyDiff(layerOptions, diff, tarSplitFile, func(payload io.Reader) (int64, error) {
2557+
options := drivers.ApplyDiffOpts{
2558+
Diff: payload,
2559+
Mappings: r.layerMappings(layer),
2560+
MountLabel: layer.MountLabel,
2561+
}
2562+
return r.driver.ApplyDiff(layer.ID, layer.Parent, options)
2563+
})
2564+
if err != nil {
2565+
return -1, err
2566+
}
2567+
2568+
if err := tarSplitFile.Sync(); err != nil {
2569+
return -1, fmt.Errorf("sync tar split file: %w", err)
2570+
}
2571+
2572+
applyDiffResultToLayer(r, layer, layerOptions, result)
25512573

25522574
err = r.saveFor(layer)
25532575

2554-
return size, err
2576+
return result.size, err
2577+
}
2578+
2579+
func applyDiffResultToLayer(r *layerStore, layer *Layer, layerOptions *LayerOptions, result *applyDiffResult) {
2580+
updateDigestMap(&r.bycompressedsum, layer.CompressedDigest, result.compressedDigest, layer.ID)
2581+
layer.CompressedDigest = result.compressedDigest
2582+
if layerOptions != nil && layerOptions.OriginalDigest != "" && layerOptions.OriginalSize != nil {
2583+
layer.CompressedSize = *layerOptions.OriginalSize
2584+
} else {
2585+
layer.CompressedSize = result.compressedSize
2586+
}
2587+
updateDigestMap(&r.byuncompressedsum, layer.UncompressedDigest, result.uncompressedDigest, layer.ID)
2588+
layer.UncompressedDigest = result.uncompressedDigest
2589+
layer.UncompressedSize = result.uncompressedSize
2590+
layer.CompressionType = result.compressionType
2591+
layer.UIDs = result.uids
2592+
layer.GIDs = result.gids
25552593
}
25562594

25572595
// Requires (startReading or?) startWriting.

0 commit comments

Comments
 (0)