commitLayer commits the specified layer with the given index to the storage. size can usually be -1; it can be provided if the layer is not known to be already present in blobDiffIDs. If the layer cannot be committed yet, the function returns (true, nil). Note that the previous layer is expected t
(index int, info addedLayerInfo, size int64)
| 948 | // must guarantee that, at any given time, at most one goroutine may execute |
| 949 | // `commitLayer()`. |
| 950 | func (s *storageImageDestination) commitLayer(index int, info addedLayerInfo, size int64) (bool, error) { |
| 951 | if _, alreadyCommitted := s.indexToStorageID[index]; alreadyCommitted { |
| 952 | return false, nil |
| 953 | } |
| 954 | |
| 955 | var parentLayer string // "" if no parent |
| 956 | if index != 0 { |
| 957 | // s.indexToStorageID can only be written by this function, and our caller |
| 958 | // is responsible for ensuring it can be only be called by *one* goroutine at any |
| 959 | // given time. Hence, we don't need to lock accesses. |
| 960 | prev, ok := s.indexToStorageID[index-1] |
| 961 | if !ok { |
| 962 | return false, fmt.Errorf("Internal error: commitLayer called with previous layer %d not committed yet", index-1) |
| 963 | } |
| 964 | parentLayer = prev |
| 965 | } |
| 966 | |
| 967 | if info.emptyLayer { |
| 968 | s.indexToStorageID[index] = parentLayer |
| 969 | return false, nil |
| 970 | } |
| 971 | |
| 972 | // Collect trusted parameters of the layer. |
| 973 | s.lock.Lock() |
| 974 | trusted, ok := s.trustedLayerIdentityDataLocked(index, info.digest) |
| 975 | s.lock.Unlock() |
| 976 | if !ok { |
| 977 | // Check if the layer exists already and the caller just (incorrectly) forgot to pass it to us in a PutBlob() / TryReusingBlob() / … |
| 978 | // |
| 979 | // Use none.NoCache to avoid a repeated DiffID lookup in the BlobInfoCache: a caller |
| 980 | // that relies on using a blob digest that has never been seen by the store had better call |
| 981 | // TryReusingBlob; not calling PutBlob already violates the documented API, so there’s only |
| 982 | // so far we are going to accommodate that (if we should be doing that at all). |
| 983 | // |
| 984 | // We are also ignoring lookups by TOC, and other non-trivial situations. |
| 985 | // Those can only happen using the c/image/internal/private API, |
| 986 | // so those internal callers should be fixed to follow the API instead of expanding this fallback. |
| 987 | logrus.Debugf("looking for diffID for blob=%+v", info.digest) |
| 988 | |
| 989 | // Use tryReusingBlobAsPending, not the top-level TryReusingBlobWithOptions, to prevent recursion via queueOrCommit. |
| 990 | has, _, err := s.tryReusingBlobAsPending(info.digest, size, &private.TryReusingBlobOptions{ |
| 991 | Cache: none.NoCache, |
| 992 | CanSubstitute: false, |
| 993 | }) |
| 994 | if err != nil { |
| 995 | return false, fmt.Errorf("checking for a layer based on blob %q: %w", info.digest.String(), err) |
| 996 | } |
| 997 | if !has { |
| 998 | return false, fmt.Errorf("error determining uncompressed digest for blob %q", info.digest.String()) |
| 999 | } |
| 1000 | |
| 1001 | s.lock.Lock() |
| 1002 | trusted, ok = s.trustedLayerIdentityDataLocked(index, info.digest) |
| 1003 | s.lock.Unlock() |
| 1004 | if !ok { |
| 1005 | return false, fmt.Errorf("we have blob %q, but don't know its layer ID", info.digest.String()) |
| 1006 | } |
| 1007 | } |
no test coverage detected