kopia lustrzana https://github.com/gaul/s3proxy
Use uploadId for stub blob name
This makes MPU overwrites of an existing blob atomic. Fixes #108.pull/114/head
rodzic
4247ae803f
commit
05bd2c1158
|
@ -1594,7 +1594,6 @@ final class S3ProxyHandler extends AbstractHandler {
|
||||||
.payload(payload);
|
.payload(payload);
|
||||||
addContentMetdataFromHttpRequest(builder, request);
|
addContentMetdataFromHttpRequest(builder, request);
|
||||||
builder.contentLength(payload.size());
|
builder.contentLength(payload.size());
|
||||||
Blob blob = builder.build();
|
|
||||||
|
|
||||||
BlobAccess access;
|
BlobAccess access;
|
||||||
String cannedAcl = request.getHeader("x-amz-acl");
|
String cannedAcl = request.getHeader("x-amz-acl");
|
||||||
|
@ -1610,13 +1609,14 @@ final class S3ProxyHandler extends AbstractHandler {
|
||||||
}
|
}
|
||||||
PutOptions options = new PutOptions().setBlobAccess(access);
|
PutOptions options = new PutOptions().setBlobAccess(access);
|
||||||
|
|
||||||
|
MultipartUpload mpu = blobStore.initiateMultipartUpload(containerName,
|
||||||
|
builder.build().getMetadata(), options);
|
||||||
|
|
||||||
// S3 requires blob metadata during the initiate call while Azure and
|
// S3 requires blob metadata during the initiate call while Azure and
|
||||||
// Swift require it in the complete call. Store a stub blob which
|
// Swift require it in the complete call. Store a stub blob which
|
||||||
// allows reproducing this metadata later.
|
// allows reproducing this metadata later.
|
||||||
blobStore.putBlob(containerName, blob, options);
|
blobStore.putBlob(containerName, builder.name(mpu.id()).build(),
|
||||||
|
options);
|
||||||
MultipartUpload mpu = blobStore.initiateMultipartUpload(containerName,
|
|
||||||
blob.getMetadata(), options);
|
|
||||||
|
|
||||||
try (Writer writer = response.getWriter()) {
|
try (Writer writer = response.getWriter()) {
|
||||||
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(
|
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(
|
||||||
|
@ -1640,8 +1640,8 @@ final class S3ProxyHandler extends AbstractHandler {
|
||||||
HttpServletResponse response, InputStream is, BlobStore blobStore,
|
HttpServletResponse response, InputStream is, BlobStore blobStore,
|
||||||
String containerName, String blobName, String uploadId)
|
String containerName, String blobName, String uploadId)
|
||||||
throws IOException, S3Exception {
|
throws IOException, S3Exception {
|
||||||
Blob stubBlob = blobStore.getBlob(containerName, blobName);
|
Blob stubBlob = blobStore.getBlob(containerName, uploadId);
|
||||||
BlobAccess access = blobStore.getBlobAccess(containerName, blobName);
|
BlobAccess access = blobStore.getBlobAccess(containerName, uploadId);
|
||||||
MultipartUpload mpu = MultipartUpload.create(containerName,
|
MultipartUpload mpu = MultipartUpload.create(containerName,
|
||||||
blobName, uploadId, stubBlob.getMetadata(),
|
blobName, uploadId, stubBlob.getMetadata(),
|
||||||
new PutOptions().setBlobAccess(access));
|
new PutOptions().setBlobAccess(access));
|
||||||
|
@ -1721,11 +1721,11 @@ final class S3ProxyHandler extends AbstractHandler {
|
||||||
HttpServletResponse response, BlobStore blobStore,
|
HttpServletResponse response, BlobStore blobStore,
|
||||||
String containerName, String blobName, String uploadId)
|
String containerName, String blobName, String uploadId)
|
||||||
throws IOException, S3Exception {
|
throws IOException, S3Exception {
|
||||||
if (!blobStore.blobExists(containerName, blobName)) {
|
if (!blobStore.blobExists(containerName, uploadId)) {
|
||||||
throw new S3Exception(S3ErrorCode.NO_SUCH_UPLOAD);
|
throw new S3Exception(S3ErrorCode.NO_SUCH_UPLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
blobStore.removeBlob(containerName, blobName);
|
blobStore.removeBlob(containerName, uploadId);
|
||||||
|
|
||||||
// TODO: how to reconstruct original mpu?
|
// TODO: how to reconstruct original mpu?
|
||||||
MultipartUpload mpu = MultipartUpload.create(containerName,
|
MultipartUpload mpu = MultipartUpload.create(containerName,
|
||||||
|
|
|
@ -44,6 +44,7 @@ import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
import com.amazonaws.services.s3.AmazonS3;
|
import com.amazonaws.services.s3.AmazonS3;
|
||||||
import com.amazonaws.services.s3.AmazonS3Client;
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
import com.amazonaws.services.s3.S3ClientOptions;
|
import com.amazonaws.services.s3.S3ClientOptions;
|
||||||
|
import com.amazonaws.services.s3.model.AbortMultipartUploadRequest;
|
||||||
import com.amazonaws.services.s3.model.AccessControlList;
|
import com.amazonaws.services.s3.model.AccessControlList;
|
||||||
import com.amazonaws.services.s3.model.AmazonS3Exception;
|
import com.amazonaws.services.s3.model.AmazonS3Exception;
|
||||||
import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest;
|
import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest;
|
||||||
|
@ -402,6 +403,33 @@ public final class S3AwsSdkTest {
|
||||||
assertThat(summary.getKey()).isEqualTo(blobName);
|
assertThat(summary.getKey()).isEqualTo(blobName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAtomicMpuAbort() throws Exception {
|
||||||
|
String key = "testAtomicMpuAbort";
|
||||||
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
|
metadata.setContentLength(BYTE_SOURCE.size());
|
||||||
|
client.putObject(containerName, key, BYTE_SOURCE.openStream(),
|
||||||
|
metadata);
|
||||||
|
|
||||||
|
InitiateMultipartUploadRequest initRequest =
|
||||||
|
new InitiateMultipartUploadRequest(containerName, key);
|
||||||
|
InitiateMultipartUploadResult initResponse =
|
||||||
|
client.initiateMultipartUpload(initRequest);
|
||||||
|
String uploadId = initResponse.getUploadId();
|
||||||
|
|
||||||
|
client.abortMultipartUpload(new AbortMultipartUploadRequest(
|
||||||
|
containerName, key, uploadId));
|
||||||
|
|
||||||
|
S3Object object = client.getObject(new GetObjectRequest(containerName,
|
||||||
|
key));
|
||||||
|
assertThat(object.getObjectMetadata().getContentLength()).isEqualTo(
|
||||||
|
BYTE_SOURCE.size());
|
||||||
|
try (InputStream actual = object.getObjectContent();
|
||||||
|
InputStream expected = BYTE_SOURCE.openStream()) {
|
||||||
|
assertThat(actual).hasContentEqualTo(expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final class NullX509TrustManager
|
private static final class NullX509TrustManager
|
||||||
implements X509TrustManager {
|
implements X509TrustManager {
|
||||||
@Override
|
@Override
|
||||||
|
|
Ładowanie…
Reference in New Issue