Skip to content

Commit

Permalink
ImageDestination: add blob locking
Browse files Browse the repository at this point in the history
Extend the ImageDestination interface with methods for locking and
unlocking a blob:

1) LockBlob() for locking a given blob.

2) UnlockBlobk() for unlocking a blob.

3) SupportsBlobLocks() to indicate whether the image destination
   supports lock semantics or not.

Signed-off-by: Valentin Rothberg <[email protected]>
  • Loading branch information
vrothberg committed Mar 25, 2019
1 parent 08191c7 commit d8d52e6
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 0 deletions.
21 changes: 21 additions & 0 deletions directory/directory_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,27 @@ func (d *dirImageDestination) HasThreadSafePutBlob() bool {
return false
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *dirImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *dirImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *dirImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
21 changes: 21 additions & 0 deletions docker/docker_image_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ func (d *dockerImageDestination) HasThreadSafePutBlob() bool {
return true
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *dockerImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *dockerImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *dockerImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
21 changes: 21 additions & 0 deletions docker/tarfile/dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,27 @@ func (d *Destination) HasThreadSafePutBlob() bool {
return false
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *Destination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *Destination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *Destination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
9 changes: 9 additions & 0 deletions image/docker_schema2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,15 @@ func (d *memoryImageDest) IgnoresEmbeddedDockerReference() bool {
func (d *memoryImageDest) HasThreadSafePutBlob() bool {
panic("Unexpected call to a mock function")
}
func (d *memoryImageDest) SupportsBlobLocks() bool {
panic("Unexpected call to a mock function")
}
func (d *memoryImageDest) LockBlob(b types.BlobInfo) error {
panic("Unexpected call to a mock function")
}
func (d *memoryImageDest) UnlockBlob(b types.BlobInfo) error {
panic("Unexpected call to a mock function")
}
func (d *memoryImageDest) PutBlob(ctx context.Context, stream io.Reader, inputInfo types.BlobInfo, cache types.BlobInfoCache, isConfig bool) (types.BlobInfo, error) {
if d.storedBlobs == nil {
d.storedBlobs = make(map[digest.Digest][]byte)
Expand Down
21 changes: 21 additions & 0 deletions oci/archive/oci_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,27 @@ func (d *ociArchiveImageDestination) HasThreadSafePutBlob() bool {
return false
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *ociArchiveImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *ociArchiveImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *ociArchiveImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
21 changes: 21 additions & 0 deletions oci/layout/oci_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,27 @@ func (d *ociImageDestination) HasThreadSafePutBlob() bool {
return false
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *ociImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *ociImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *ociImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
21 changes: 21 additions & 0 deletions openshift/openshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,27 @@ func (d *openshiftImageDestination) HasThreadSafePutBlob() bool {
return false
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *openshiftImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *openshiftImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *openshiftImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
21 changes: 21 additions & 0 deletions ostree/ostree_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,27 @@ func (d *ostreeImageDestination) HasThreadSafePutBlob() bool {
return false
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *ostreeImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (d *ostreeImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (d *ostreeImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
21 changes: 21 additions & 0 deletions storage/storage_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,27 @@ func (s *storageImageDestination) HasThreadSafePutBlob() bool {
return true
}

// SupportsBlobLocks indicates whether the ImageDestination supports blob
// locking.
func (d *storageImageDestination) SupportsBlobLocks() bool {
return false
}

// LockBlob can be used to synchronize operations on it (e.g., copying).
func (s *storageImageDestination) LockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// UnlockBlob unlocks the blob. Note that it is safe to call UnlockBlob()
// multiple times. Only the first call is unlocking the blob. This is
// required to unlock a blob in the presence of errors or panics during copy
// operations.
func (s *storageImageDestination) UnlockBlob(b types.BlobInfo) error {
// NOOP for this type.
return nil
}

// PutBlob writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
Expand Down
9 changes: 9 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,15 @@ type ImageDestination interface {
// - Uploaded data MAY be visible to others before Commit() is called
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
Commit(ctx context.Context) error
// SupportsBlobLocks indicates whether the ImageDestination supports blob locking.
SupportsBlobLocks() bool
// LockBlob can be used to synchronize operations on it (e.g., copying).
LockBlob(BlobInfo) error
// UnlockBlob unlocks the blob. Note that it is safe to call
// UnlockBlob() multiple times. Only the first call is unlocking the
// blob. This is required to unlock a blob in the presence of errors
// or panics during copy operations.
UnlockBlob(BlobInfo) error
}

// ManifestTypeRejectedError is returned by ImageDestination.PutManifest if the destination is in principle available,
Expand Down

0 comments on commit d8d52e6

Please sign in to comment.