Skip to content

Commit

Permalink
Merge pull request containers#811 from vrothberg/fix-podman-11997
Browse files Browse the repository at this point in the history
libimage: speed up image filters
  • Loading branch information
openshift-merge-robot authored Oct 19, 2021
2 parents 4077ae5 + f745869 commit da56e47
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 16 deletions.
32 changes: 26 additions & 6 deletions libimage/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ func filterImages(images []*Image, filters []filterFunc) ([]*Image, error) {
func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) ([]filterFunc, error) {
logrus.Tracef("Parsing image filters %s", options.Filters)

var tree *layerTree
getTree := func() (*layerTree, error) {
if tree == nil {
t, err := r.layerTree()
if err != nil {
return nil, err
}
tree = t
}
return tree, nil
}

filterFuncs := []filterFunc{}
for _, filter := range options.Filters {
var key, value string
Expand Down Expand Up @@ -93,7 +105,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
if err != nil {
return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value)
}
filterFuncs = append(filterFuncs, filterDangling(ctx, dangling))
t, err := getTree()
if err != nil {
return nil, err
}
filterFuncs = append(filterFuncs, filterDangling(ctx, dangling, t))

case "id":
filterFuncs = append(filterFuncs, filterID(value))
Expand All @@ -103,7 +119,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
if err != nil {
return nil, errors.Wrapf(err, "non-boolean value %q for intermediate filter", value)
}
filterFuncs = append(filterFuncs, filterIntermediate(ctx, intermediate))
t, err := getTree()
if err != nil {
return nil, err
}
filterFuncs = append(filterFuncs, filterIntermediate(ctx, intermediate, t))

case "label":
filterFuncs = append(filterFuncs, filterLabel(ctx, value))
Expand Down Expand Up @@ -221,9 +241,9 @@ func filterContainers(value string, fn IsExternalContainerFunc) filterFunc {
}

// filterDangling creates a dangling filter for matching the specified value.
func filterDangling(ctx context.Context, value bool) filterFunc {
func filterDangling(ctx context.Context, value bool, tree *layerTree) filterFunc {
return func(img *Image) (bool, error) {
isDangling, err := img.IsDangling(ctx)
isDangling, err := img.isDangling(ctx, tree)
if err != nil {
return false, err
}
Expand All @@ -241,9 +261,9 @@ func filterID(value string) filterFunc {
// filterIntermediate creates an intermediate filter for images. An image is
// considered to be an intermediate image if it is dangling (i.e., no tags) and
// has no children (i.e., no other image depends on it).
func filterIntermediate(ctx context.Context, value bool) filterFunc {
func filterIntermediate(ctx context.Context, value bool, tree *layerTree) filterFunc {
return func(img *Image) (bool, error) {
isIntermediate, err := img.IsIntermediate(ctx)
isIntermediate, err := img.isIntermediate(ctx, tree)
if err != nil {
return false, err
}
Expand Down
36 changes: 26 additions & 10 deletions libimage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,16 @@ func (i *Image) IsReadOnly() bool {
// IsDangling returns true if the image is dangling, that is an untagged image
// without children.
func (i *Image) IsDangling(ctx context.Context) (bool, error) {
return i.isDangling(ctx, nil)
}

// isDangling returns true if the image is dangling, that is an untagged image
// without children. If tree is nil, it will created for this invocation only.
func (i *Image) isDangling(ctx context.Context, tree *layerTree) (bool, error) {
if len(i.Names()) > 0 {
return false, nil
}
children, err := i.getChildren(ctx, false)
children, err := i.getChildren(ctx, false, tree)
if err != nil {
return false, err
}
Expand All @@ -141,10 +147,17 @@ func (i *Image) IsDangling(ctx context.Context) (bool, error) {
// IsIntermediate returns true if the image is an intermediate image, that is
// an untagged image with children.
func (i *Image) IsIntermediate(ctx context.Context) (bool, error) {
return i.isIntermediate(ctx, nil)
}

// isIntermediate returns true if the image is an intermediate image, that is
// an untagged image with children. If tree is nil, it will created for this
// invocation only.
func (i *Image) isIntermediate(ctx context.Context, tree *layerTree) (bool, error) {
if len(i.Names()) > 0 {
return false, nil
}
children, err := i.getChildren(ctx, false)
children, err := i.getChildren(ctx, false, tree)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -189,7 +202,7 @@ func (i *Image) Parent(ctx context.Context) (*Image, error) {

// HasChildren returns indicates if the image has children.
func (i *Image) HasChildren(ctx context.Context) (bool, error) {
children, err := i.getChildren(ctx, false)
children, err := i.getChildren(ctx, false, nil)
if err != nil {
return false, err
}
Expand All @@ -198,21 +211,24 @@ func (i *Image) HasChildren(ctx context.Context) (bool, error) {

// Children returns the image's children.
func (i *Image) Children(ctx context.Context) ([]*Image, error) {
children, err := i.getChildren(ctx, true)
children, err := i.getChildren(ctx, true, nil)
if err != nil {
return nil, err
}
return children, nil
}

// getChildren returns a list of imageIDs that depend on the image. If all is
// false, only the first child image is returned.
func (i *Image) getChildren(ctx context.Context, all bool) ([]*Image, error) {
tree, err := i.runtime.layerTree()
if err != nil {
return nil, err
// false, only the first child image is returned. If tree is nil, it will be
// created for this invocation only.
func (i *Image) getChildren(ctx context.Context, all bool, tree *layerTree) ([]*Image, error) {
if tree == nil {
t, err := i.runtime.layerTree()
if err != nil {
return nil, err
}
tree = t
}

return tree.children(ctx, i, all)
}

Expand Down

0 comments on commit da56e47

Please sign in to comment.