-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #373 from tri-adam/compaction
refactor: improve compaction logic
- Loading branch information
Showing
11 changed files
with
103 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved. | ||
// Copyright (c) 2018-2024, Sylabs Inc. All rights reserved. | ||
// Copyright (c) 2017, SingularityWare, LLC. All rights reserved. | ||
// Copyright (c) 2017, Yannick Cote <[email protected]> All rights reserved. | ||
// This software is licensed under a 3-clause BSD license. Please consult the | ||
|
@@ -55,6 +55,20 @@ func writeDataObjectAt(ws io.WriteSeeker, offsetUnaligned int64, di DescriptorIn | |
return nil | ||
} | ||
|
||
// calculatedDataSize calculates the size of the data section based on the in-use descriptors. | ||
func (f *FileImage) calculatedDataSize() int64 { | ||
dataEnd := f.DataOffset() | ||
|
||
f.WithDescriptors(func(d Descriptor) bool { | ||
if objectEnd := d.Offset() + d.Size(); dataEnd < objectEnd { | ||
dataEnd = objectEnd | ||
} | ||
return false | ||
}) | ||
|
||
return dataEnd - f.DataOffset() | ||
} | ||
|
||
var ( | ||
errInsufficientCapacity = errors.New("insufficient descriptor capacity to add data object(s) to image") | ||
errPrimaryPartition = errors.New("image already contains a primary partition") | ||
|
@@ -80,6 +94,8 @@ func (f *FileImage) writeDataObject(i int, di DescriptorInput, t time.Time) erro | |
d := &f.rds[i] | ||
d.ID = uint32(i) + 1 | ||
|
||
f.h.DataSize = f.calculatedDataSize() | ||
|
||
if err := writeDataObjectAt(f.rw, f.h.DataOffset+f.h.DataSize, di, t, d); err != nil { | ||
return err | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved. | ||
// Copyright (c) 2018-2024, Sylabs Inc. All rights reserved. | ||
// Copyright (c) 2017, SingularityWare, LLC. All rights reserved. | ||
// Copyright (c) 2017, Yannick Cote <[email protected]> All rights reserved. | ||
// This software is licensed under a 3-clause BSD license. Please consult the | ||
|
@@ -8,32 +8,16 @@ | |
package sif | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io" | ||
"time" | ||
) | ||
|
||
// isLast return true if the data object associated with d is the last in f. | ||
func (f *FileImage) isLast(d *rawDescriptor) bool { | ||
isLast := true | ||
|
||
end := d.Offset + d.Size | ||
f.WithDescriptors(func(d Descriptor) bool { | ||
isLast = d.Offset()+d.Size() <= end | ||
return !isLast | ||
}) | ||
|
||
return isLast | ||
} | ||
|
||
// zeroReader is an io.Reader that returns a stream of zero-bytes. | ||
type zeroReader struct{} | ||
|
||
func (zeroReader) Read(b []byte) (int, error) { | ||
for i := range b { | ||
b[i] = 0 | ||
} | ||
clear(b) | ||
return len(b), nil | ||
} | ||
|
||
|
@@ -47,13 +31,6 @@ func (f *FileImage) zero(d *rawDescriptor) error { | |
return err | ||
} | ||
|
||
// truncateAt truncates f at the start of the padded data object described by d. | ||
func (f *FileImage) truncateAt(d *rawDescriptor) error { | ||
start := d.Offset + d.Size - d.SizeWithPadding | ||
|
||
return f.rw.Truncate(start) | ||
} | ||
|
||
// deleteOpts accumulates object deletion options. | ||
type deleteOpts struct { | ||
zero bool | ||
|
@@ -97,8 +74,6 @@ func OptDeleteWithTime(t time.Time) DeleteOpt { | |
} | ||
} | ||
|
||
var errCompactNotImplemented = errors.New("compact not implemented for non-last object") | ||
|
||
// DeleteObject deletes the data object with id, according to opts. | ||
// | ||
// To zero the data region of the deleted object, use OptDeleteZero. To compact the file following | ||
|
@@ -125,24 +100,12 @@ func (f *FileImage) DeleteObject(id uint32, opts ...DeleteOpt) error { | |
return fmt.Errorf("%w", err) | ||
} | ||
|
||
if do.compact && !f.isLast(d) { | ||
return fmt.Errorf("%w", errCompactNotImplemented) | ||
} | ||
|
||
if do.zero { | ||
if err := f.zero(d); err != nil { | ||
return fmt.Errorf("%w", err) | ||
} | ||
} | ||
|
||
if do.compact { | ||
if err := f.truncateAt(d); err != nil { | ||
return fmt.Errorf("%w", err) | ||
} | ||
|
||
f.h.DataSize -= d.SizeWithPadding | ||
} | ||
|
||
f.h.DescriptorsFree++ | ||
f.h.ModifiedAt = do.t.Unix() | ||
|
||
|
@@ -156,6 +119,14 @@ func (f *FileImage) DeleteObject(id uint32, opts ...DeleteOpt) error { | |
// Reset rawDescripter with empty struct | ||
*d = rawDescriptor{} | ||
|
||
if do.compact { | ||
f.h.DataSize = f.calculatedDataSize() | ||
|
||
if err := f.rw.Truncate(f.h.DataOffset + f.h.DataSize); err != nil { | ||
return fmt.Errorf("%w", err) | ||
} | ||
} | ||
|
||
if err := f.writeDescriptors(); err != nil { | ||
return fmt.Errorf("%w", err) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file renamed
BIN
+31.4 KB
...sif/testdata/TestDeleteObject/Zero.golden → ...stdata/TestDeleteObject/TwoCompact.golden
Binary file not shown.
Binary file not shown.
Binary file renamed
BIN
+31.4 KB
...tdata/TestDeleteObject/ZeroCompact.golden → ...ta/TestDeleteObject/TwoZeroCompact.golden
Binary file not shown.
Binary file modified
BIN
-3 Bytes
(100%)
pkg/sif/testdata/TestDeleteObjectAndAddObject/NoCompact.golden
Binary file not shown.
Binary file not shown.