Skip to content

Commit

Permalink
Use generics in readAllImageStores
Browse files Browse the repository at this point in the history
Signed-off-by: Miloslav Trmač <[email protected]>
  • Loading branch information
mtrmac committed Apr 18, 2023
1 parent 0a417fe commit 087bc92
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 75 deletions.
8 changes: 4 additions & 4 deletions check.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,10 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) {

// Walk the list of image stores, looking at each image that we didn't see in a
// previously-visited store.
if errored, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if _, _, err := readAllImageStores(s, func(store roImageStore) (struct{}, bool, error) {
images, err := store.Images()
if err != nil {
return true, err
return struct{}{}, true, err
}
isReadWrite := roImageStoreIsReallyReadWrite(store)
readWriteDesc := ""
Expand Down Expand Up @@ -564,8 +564,8 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) {
}
}
}
return false, nil
}); errored {
return struct{}{}, false, nil
}); err != nil {
return CheckReport{}, err
}

Expand Down
4 changes: 2 additions & 2 deletions check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ func TestCheckDetectWriteable(t *testing.T) {
assert.False(t, done, "unexpected error from readAllLayerStores")
assert.NoError(t, err, "unexpected error from readAllLayerStores")
assert.True(t, sawRWlayers, "unexpected error detecting which layer store is writeable")
done, err = s.readAllImageStores(func(store roImageStore) (bool, error) {
_, done, err = readAllImageStores(s, func(store roImageStore) (struct{}, bool, error) {
if roImageStoreIsReallyReadWrite(store) { // implicitly checking that the type assertion in this function doesn't panic
sawRWimages = true
}
return false, nil
return struct{}{}, false, nil
})
assert.False(t, done, "unexpected error from readAllImageStores")
assert.NoError(t, err, "unexpected error from readAllImageStores")
Expand Down
129 changes: 60 additions & 69 deletions store.go
Original file line number Diff line number Diff line change
Expand Up @@ -1211,34 +1211,35 @@ func (s *store) allImageStores() []roImageStore {
// readAllImageStores processes allImageStores() in order:
// It locks the store for reading, checks for updates, and calls
//
// (done, err) := fn(store)
// (data, done, err) := fn(store)
//
// until the callback returns done == true, and returns the data from the callback.
//
// If reading any Image store fails, it immediately returns (true, err).
// If reading any Image store fails, it immediately returns ({}, true, err).
//
// If all Image stores are processed without setting done == true, it returns (false, nil).
// If all Image stores are processed without setting done == true, it returns ({}, false, nil).
//
// Typical usage:
//
// var res T = failureValue
// if done, err := s.readAllImageStores(store, func(…) {
// if res, done, err := readAllImageStores(store, func(…) {
// …
// }; done {
// return res, err
// }
func (s *store) readAllImageStores(fn func(store roImageStore) (bool, error)) (bool, error) {
func readAllImageStores[T any](s *store, fn func(store roImageStore) (T, bool, error)) (T, bool, error) {
var zeroRes T // A zero value of T

for _, s := range s.allImageStores() {
store := s
if err := store.startReading(); err != nil {
return true, err
return zeroRes, true, err
}
defer store.stopReading()
if done, err := fn(store); done {
return true, err
if res, done, err := fn(store); done {
return res, true, err
}
}
return false, nil
return zeroRes, false, nil
}

// writeToImageStore is a convenience helper for working with store.imageStore:
Expand Down Expand Up @@ -1839,18 +1840,17 @@ func (s *store) Metadata(id string) (string, error) {
return res, err
}

var res string
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) (string, bool, error) {
if store.Exists(id) {
var err error
res, err = store.Metadata(id)
return true, err
res, err := store.Metadata(id)
return res, true, err
}
return false, nil
return "", false, nil
}); done {
return res, err
}

var res string
if done, err := s.readContainerStore(func() (bool, error) {
if s.containerStore.Exists(id) {
var err error
Expand All @@ -1866,44 +1866,41 @@ func (s *store) Metadata(id string) (string, error) {
}

func (s *store) ListImageBigData(id string) ([]string, error) {
var res []string
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) ([]string, bool, error) {
bigDataNames, err := store.BigDataNames(id)
if err == nil {
res = bigDataNames
return true, nil
return bigDataNames, true, nil
}
return false, nil
return nil, false, nil
}); done {
return res, err
}
return nil, fmt.Errorf("locating image with ID %q: %w", id, ErrImageUnknown)
}

func (s *store) ImageBigDataSize(id, key string) (int64, error) {
var res int64 = -1
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) (int64, bool, error) {
size, err := store.BigDataSize(id, key)
if err == nil {
res = size
return true, nil
return size, true, nil
}
return false, nil
return -1, false, nil
}); done {
return res, err
if err != nil {
return -1, err
}
return res, nil
}
return -1, ErrSizeUnknown
}

func (s *store) ImageBigDataDigest(id, key string) (digest.Digest, error) {
var res digest.Digest
if done, err := s.readAllImageStores(func(ristore roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(ristore roImageStore) (digest.Digest, bool, error) {
d, err := ristore.BigDataDigest(id, key)
if err == nil && d.Validate() == nil {
res = d
return true, nil
return d, true, nil
}
return false, nil
return "", false, nil
}); done {
return res, err
}
Expand All @@ -1912,17 +1909,15 @@ func (s *store) ImageBigDataDigest(id, key string) (digest.Digest, error) {

func (s *store) ImageBigData(id, key string) ([]byte, error) {
foundImage := false
var res []byte
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) ([]byte, bool, error) {
data, err := store.BigData(id, key)
if err == nil {
res = data
return true, nil
return data, true, nil
}
if store.Exists(id) {
foundImage = true
}
return false, nil
return nil, false, nil
}); done {
return res, err
}
Expand Down Expand Up @@ -2212,15 +2207,17 @@ func (s *store) Exists(id string) bool {
return true
}

var res = false
if done, _ := s.readAllImageStores(func(store roImageStore) (bool, error) {
found, _, err = readAllImageStores(s, func(store roImageStore) (bool, bool, error) {
if store.Exists(id) {
res = true
return true, nil
return true, true, nil
}
return false, nil
}); done {
return res
return false, false, nil
})
if err != nil {
return false
}
if found {
return true
}

if err := s.containerStore.startReading(); err != nil {
Expand Down Expand Up @@ -2351,13 +2348,11 @@ func (s *store) Names(id string) ([]string, error) {
return res, err
}

var res []string
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) ([]string, bool, error) {
if i, err := store.Get(id); i != nil && err == nil {
res = i.Names
return true, nil
return i.Names, true, nil
}
return false, nil
return nil, false, nil
}); done {
return res, err
}
Expand All @@ -2382,13 +2377,11 @@ func (s *store) Lookup(name string) (string, error) {
return res, err
}

var res string
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) (string, bool, error) {
if i, err := store.Get(name); i != nil && err == nil {
res = i.ID
return true, nil
return i.ID, true, nil
}
return false, nil
return "", false, nil
}); done {
return res, err
}
Expand Down Expand Up @@ -2991,13 +2984,13 @@ func (s *store) Layers() ([]Layer, error) {

func (s *store) Images() ([]Image, error) {
var images []Image
if _, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if _, _, err := readAllImageStores(s, func(store roImageStore) (struct{}, bool, error) {
storeImages, err := store.Images()
if err != nil {
return true, err
return struct{}{}, true, err
}
images = append(images, storeImages...)
return false, nil
return struct{}{}, false, nil
}); err != nil {
return nil, err
}
Expand Down Expand Up @@ -3113,8 +3106,7 @@ func (al *additionalLayer) Release() {
}

func (s *store) Image(id string) (*Image, error) {
var res *Image
if done, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if res, done, err := readAllImageStores(s, func(store roImageStore) (*Image, bool, error) {
image, err := store.Get(id)
if err == nil {
if store != s.imageStore {
Expand All @@ -3124,13 +3116,12 @@ func (s *store) Image(id string) (*Image, error) {
// store, but we have an entry with the same ID in the read-write store,
// then the name was removed when we duplicated the image's
// record into writable storage, so we should ignore this entry
return false, nil
return nil, false, nil
}
}
res = image
return true, nil
return image, true, nil
}
return false, nil
return nil, false, nil
}); done {
return res, err
}
Expand All @@ -3144,18 +3135,18 @@ func (s *store) ImagesByTopLayer(id string) ([]*Image, error) {
}

images := []*Image{}
if _, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if _, _, err := readAllImageStores(s, func(store roImageStore) (struct{}, bool, error) {
imageList, err := store.Images()
if err != nil {
return true, err
return struct{}{}, true, err
}
for _, image := range imageList {
image := image
if image.TopLayer == layer.ID || stringutils.InSlice(image.MappedTopLayers, layer.ID) {
images = append(images, &image)
}
}
return false, nil
return struct{}{}, false, nil
}); err != nil {
return nil, err
}
Expand All @@ -3164,13 +3155,13 @@ func (s *store) ImagesByTopLayer(id string) ([]*Image, error) {

func (s *store) ImagesByDigest(d digest.Digest) ([]*Image, error) {
images := []*Image{}
if _, err := s.readAllImageStores(func(store roImageStore) (bool, error) {
if _, _, err := readAllImageStores(s, func(store roImageStore) (struct{}, bool, error) {
imageList, err := store.ByDigest(d)
if err != nil && !errors.Is(err, ErrImageUnknown) {
return true, err
return struct{}{}, true, err
}
images = append(images, imageList...)
return false, nil
return struct{}{}, false, nil
}); err != nil {
return nil, err
}
Expand Down

0 comments on commit 087bc92

Please sign in to comment.