pkg/blobinfocache/boltdb/boltdb.go
func (bdc *cache) CandidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute bool) []types.BICReplacementCandidate {
	res := []prioritize.CandidateWithTime{}
	var uncompressedDigestValue digest.Digest // = ""
	if err := bdc.view(func(tx *bolt.Tx) error {
		scopeBucket := tx.Bucket(knownLocationsBucket)
		if scopeBucket == nil {
			return nil
		}
		scopeBucket = scopeBucket.Bucket([]byte(transport.Name()))
		if scopeBucket == nil {
			return nil
		}
		scopeBucket = scopeBucket.Bucket([]byte(scope.Opaque))
		if scopeBucket == nil {
			return nil
		}

		res = bdc.appendReplacementCandidates(res, scopeBucket, primaryDigest)
		if canSubstitute {
			if uncompressedDigestValue = bdc.uncompressedDigest(tx, primaryDigest); uncompressedDigestValue != "" {
				b := tx.Bucket(digestByUncompressedBucket)
				if b != nil {
					b = b.Bucket([]byte(uncompressedDigestValue.String()))
					if b != nil {
						if err := b.ForEach(func(k, _ []byte) error {
							d, err := digest.Parse(string(k))
							if err != nil {
								return err
							}
							if d != primaryDigest && d != uncompressedDigestValue {
								res = bdc.appendReplacementCandidates(res, scopeBucket, d)
							}
							return nil
						}); err != nil {
							return err
						}
					}
				}
				if uncompressedDigestValue != primaryDigest {
					res = bdc.appendReplacementCandidates(res, scopeBucket, uncompressedDigestValue)
				}
			}
		}
		return nil
	}); err != nil { // Including os.IsNotExist(err)
		return []types.BICReplacementCandidate{} // FIXME? Log err (but throttle the log volume on repeated accesses)?
	}

	return prioritize.DestructivelyPrioritizeReplacementCandidates(res, primaryDigest, uncompressedDigestValue)
}
func (bdc *cache) CandidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute bool) []types.BICReplacementCandidate {
	res := []prioritize.CandidateWithTime{}
	var uncompressedDigestValue digest.Digest // = ""
	if err := bdc.view(func(tx *bolt.Tx) error {
		scopeBucket := tx.Bucket(knownLocationsBucket)
		if scopeBucket == nil {
			return nil
		}
		scopeBucket = scopeBucket.Bucket([]byte(transport.Name()))
		if scopeBucket == nil {
			return nil
		}
		scopeBucket = scopeBucket.Bucket([]byte(scope.Opaque))
		if scopeBucket == nil {
			return nil
		}

		res = bdc.appendReplacementCandidates(res, scopeBucket, primaryDigest)
		if canSubstitute {
			if uncompressedDigestValue = bdc.uncompressedDigest(tx, primaryDigest); uncompressedDigestValue != "" {
				b := tx.Bucket(digestByUncompressedBucket)
				if b != nil {
					b = b.Bucket([]byte(uncompressedDigestValue.String()))
					if b != nil {
						if err := b.ForEach(func(k, _ []byte) error {
							d, err := digest.Parse(string(k))
							if err != nil {
								return err
							}
							if d != primaryDigest && d != uncompressedDigestValue {
								res = bdc.appendReplacementCandidates(res, scopeBucket, d)
							}
							return nil
						}); err != nil {
							return err
						}
					}
				}
				if uncompressedDigestValue != primaryDigest {
					res = bdc.appendReplacementCandidates(res, scopeBucket, uncompressedDigestValue)
				}
			}
		}
		return nil
	}); err != nil { // Including os.IsNotExist(err)
		return []types.BICReplacementCandidate{} // FIXME? Log err (but throttle the log volume on repeated accesses)?
	}

	return prioritize.DestructivelyPrioritizeReplacementCandidates(res, primaryDigest, uncompressedDigestValue)
}
func ( bdc * cache ) CandidateLocations ( transport types . ImageTransport , scope types . BICTransportScope , primaryDigest digest . Digest , canSubstitute bool ) [ ] types . BICReplacementCandidate { res := [ ] prioritize . CandidateWithTime { } var uncompressedDigestValue digest . Digest // = "" if err := bdc . view ( func ( tx * bolt . Tx ) error { scopeBucket := tx . Bucket ( knownLocationsBucket ) if scopeBucket == nil { return nil } scopeBucket = scopeBucket . Bucket ( [ ] byte ( transport . Name ( ) ) ) if scopeBucket == nil { return nil } scopeBucket = scopeBucket . Bucket ( [ ] byte ( scope . Opaque ) ) if scopeBucket == nil { return nil } res = bdc . appendReplacementCandidates ( res , scopeBucket , primaryDigest ) if canSubstitute { if uncompressedDigestValue = bdc . uncompressedDigest ( tx , primaryDigest ) ; uncompressedDigestValue != " " { b := tx . Bucket ( digestByUncompressedBucket ) if b != nil { b = b . Bucket ( [ ] byte ( uncompressedDigestValue . String ( ) ) ) if b != nil { if err := b . ForEach ( func ( k , _ [ ] byte ) error { d , err := digest . Parse ( string ( k ) ) if err != nil { return err } if d != primaryDigest && d != uncompressedDigestValue { res = bdc . appendReplacementCandidates ( res , scopeBucket , d ) } return nil } ) ; err != nil { return err } } } if uncompressedDigestValue != primaryDigest { res = bdc . appendReplacementCandidates ( res , scopeBucket , uncompressedDigestValue ) } } } return nil } ) ; err != nil { // Including os.IsNotExist(err) return [ ] types . BICReplacementCandidate { } // FIXME? Log err (but throttle the log volume on repeated accesses)? } return prioritize . DestructivelyPrioritizeReplacementCandidates ( res , primaryDigest , uncompressedDigestValue ) }
// CandidateLocations returns a prioritized, limited, number of blobs and their locations that could possibly be reused
// within the specified (transport scope) (if they still exist, which is not guaranteed).
//
// If !canSubstitute, the returned cadidates will match the submitted digest exactly; if canSubstitute,
// data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same
// uncompressed digest.
CandidateLocations returns a prioritized limited number of blobs and their locations that could possibly be reused within the specified ( transport scope ) ( if they still exist which is not guaranteed ) . If !canSubstitute the returned cadidates will match the submitted digest exactly ; if canSubstitute data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same uncompressed digest .