Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GC on oci.Store.Delete #653

Merged
merged 26 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
resolved comments
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
  • Loading branch information
wangxiaoxuan273 committed Dec 28, 2023
commit f593ecd42cc91ea9e5c7b1b1512e08d07e977258
27 changes: 13 additions & 14 deletions content/oci/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@
AutoSaveIndex bool

// AutoGC controls if the OCI store will automatically clean newly produced
// dangling nodes during Delete() operation. Dangling nodes are those without
// any predecessors, such as blobs whose manifests have been deleted.
// dangling (unreferenced) blobs during Delete() operation. For example the
// blobs whose manifests have been deleted. Manifests in the index will not
wangxiaoxuan273 marked this conversation as resolved.
Show resolved Hide resolved
// be deleted.
// - Default value: true.
AutoGC bool

// AutoRemoveReferrers controls if the OCI store will automatically delete its
// referrers when a manifest is deleted.
// AutoDeleteReferrers controls if the OCI store will automatically delete its
// referrers when a manifest is deleted. When set to true, the referrers will
// be deleted even if they exist in the index.
// - Default value: true.
AutoRemoveReferrers bool
AutoDeleteReferrers bool

root string
indexPath string
Expand Down Expand Up @@ -99,7 +101,7 @@
store := &Store{
AutoSaveIndex: true,
AutoGC: true,
AutoRemoveReferrers: true,
AutoDeleteReferrers: true,
root: rootAbs,
indexPath: filepath.Join(rootAbs, ocispec.ImageIndexFile),
storage: storage,
Expand Down Expand Up @@ -163,38 +165,35 @@
// is set to true, Delete will recursively remove the referrers of the manifests
// being deleted.
func (s *Store) Delete(ctx context.Context, target ocispec.Descriptor) error {
var deleteQueue []ocispec.Descriptor
deleteQueue = append(deleteQueue, target)
deleteQueue := []ocispec.Descriptor{target}

for len(deleteQueue) > 0 {
head := deleteQueue[0]
deleteQueue = deleteQueue[1:]

// get referrers if applicable
var referrers []ocispec.Descriptor
var err error
if s.AutoRemoveReferrers && descriptor.IsManifest(head) {
referrers, err = registry.Referrers(ctx, s, head, "")
if s.AutoDeleteReferrers && descriptor.IsManifest(head) {
referrers, err := registry.Referrers(ctx, s, head, "")
if err != nil {
return err
}

Check warning on line 179 in content/oci/oci.go

View check run for this annotation

Codecov / codecov/patch

content/oci/oci.go#L178-L179

Added lines #L178 - L179 were not covered by tests
deleteQueue = append(deleteQueue, referrers...)
}
deleteQueue = append(deleteQueue, referrers...)

// delete the head of queue if applicable
s.sync.Lock()

danglings, err := s.delete(ctx, head)
if err != nil {
s.sync.Unlock()
return err
wangxiaoxuan273 marked this conversation as resolved.
Show resolved Hide resolved
}

Check warning on line 190 in content/oci/oci.go

View check run for this annotation

Codecov / codecov/patch

content/oci/oci.go#L188-L190

Added lines #L188 - L190 were not covered by tests

if s.AutoGC {
for _, d := range danglings {
// do not delete existing manifests in tagResolver
_, err = s.tagResolver.Resolve(ctx, string(d.Digest))
if err == errdef.ErrNotFound {
if errors.Is(err, errdef.ErrNotFound) {
deleteQueue = append(deleteQueue, d)
}
}
Expand All @@ -220,12 +219,12 @@
if untagged && s.AutoSaveIndex {
err := s.saveIndex()
if err != nil {
return nil, err

Check warning on line 222 in content/oci/oci.go

View check run for this annotation

Codecov / codecov/patch

content/oci/oci.go#L222

Added line #L222 was not covered by tests
}
}
if err := s.storage.Delete(ctx, target); err != nil {
return nil, err
}

Check warning on line 227 in content/oci/oci.go

View check run for this annotation

Codecov / codecov/patch

content/oci/oci.go#L226-L227

Added lines #L226 - L227 were not covered by tests
return danglings, nil
}

Expand Down
4 changes: 2 additions & 2 deletions content/oci/oci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2422,7 +2422,7 @@ func TestStore_DeleteDisableAutoRemoveReferrers(t *testing.T) {
if err != nil {
t.Fatal("New() error =", err)
}
s.AutoRemoveReferrers = false
s.AutoDeleteReferrers = false
ctx := context.Background()

// generate test content
Expand Down Expand Up @@ -2577,7 +2577,7 @@ func TestStore_DeleteDisableAutoGCAndAutoRemoveReferrers(t *testing.T) {
if err != nil {
t.Fatal("New() error =", err)
}
s.AutoRemoveReferrers = false
s.AutoDeleteReferrers = false
s.AutoGC = false
ctx := context.Background()

Expand Down
6 changes: 3 additions & 3 deletions internal/graph/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,21 @@ import (

// Memory is a memory based PredecessorFinder.
type Memory struct {
// properties and behaviors of Memory.nodes:
// nodes has the following properties and behaviors:
// 1. a node exists in Memory.nodes if and only if it exists in the memory
// 2. Memory.nodes saves the ocispec.Descriptor map keys, which are used by
// the other fields.
nodes map[descriptor.Descriptor]ocispec.Descriptor

// properties and behaviors of Memory.predecessors:
// predecessors has the following properties and behaviors:
// 1. a node exists in Memory.predecessors if it has at least one predecessor
// in the memory, regardless of whether or not the node itself exists in
// the memory.
// 2. a node does not exist in Memory.predecessors, if it doesn't have any predecessors
// in the memory.
predecessors map[descriptor.Descriptor]set.Set[descriptor.Descriptor]

// properties and behaviors of Memory.successors:
// successors has the following properties and behaviors:
// 1. a node exists in Memory.successors if and only if it exists in the memory.
// 2. a node's entry in Memory.successors is always consistent with the actual
// content of the node, regardless of whether or not each successor exists
Expand Down
Loading