fix multipart put of a blob with content md5

previously the parts will carry the content md5 of the entire
object, because unsetting the md5 of a ContentMetadata actually
didn't do anything
This commit is contained in:
Ka-Hing Cheung 2015-06-09 17:25:18 -07:00 committed by Andrew Gaul
parent 7e1838afbb
commit 05a9c79242
2 changed files with 19 additions and 7 deletions

View File

@ -47,6 +47,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import com.google.common.hash.Hashing;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.attr.ConsistencyModel;
@ -59,6 +60,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.options.CopyOptions; import org.jclouds.blobstore.options.CopyOptions;
import org.jclouds.blobstore.options.PutOptions; import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.strategy.internal.MultipartUploadSlicingAlgorithm;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
import org.jclouds.encryption.internal.JCECrypto; import org.jclouds.encryption.internal.JCECrypto;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
@ -555,7 +557,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
long length = 42; long length = 42;
ByteSource byteSource = TestUtils.randomByteSource().slice(0, length); ByteSource byteSource = TestUtils.randomByteSource().slice(0, length);
Payload payload = new ByteSourcePayload(byteSource); Payload payload = new ByteSourcePayload(byteSource);
testPut(payload, payload, length, new PutOptions()); testPut(payload, null, payload, length, new PutOptions());
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
@ -563,15 +565,22 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
long length = 42; long length = 42;
ByteSource byteSource = TestUtils.randomByteSource().slice(0, length); ByteSource byteSource = TestUtils.randomByteSource().slice(0, length);
Payload payload = new InputStreamPayload(byteSource.openStream()); Payload payload = new InputStreamPayload(byteSource.openStream());
testPut(payload, new ByteSourcePayload(byteSource), length, new PutOptions()); testPut(payload, null, new ByteSourcePayload(byteSource), length, new PutOptions());
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testPutMultipartByteSource() throws Exception { public void testPutMultipartByteSource() throws Exception {
long length = getMinimumMultipartBlobSize(); long length = 32 * 1024 * 1024 + 1; // MultipartUploadSlicingAlgorithm.DEFAULT_PART_SIZE + 1
BlobStore blobStore = view.getBlobStore();
MultipartUploadSlicingAlgorithm algorithm = new MultipartUploadSlicingAlgorithm(
blobStore.getMinimumMultipartPartSize(), blobStore.getMaximumMultipartPartSize(),
blobStore.getMaximumNumberOfParts());
// make sure that we are creating multiple parts
assertThat(algorithm.calculateChunkSize(length)).isLessThan(length);
ByteSource byteSource = TestUtils.randomByteSource().slice(0, length); ByteSource byteSource = TestUtils.randomByteSource().slice(0, length);
Payload payload = new ByteSourcePayload(byteSource); Payload payload = new ByteSourcePayload(byteSource);
testPut(payload, payload, length, new PutOptions().multipart(true)); HashCode hashCode = byteSource.hash(Hashing.md5());
testPut(payload, hashCode, payload, length, new PutOptions().multipart(true));
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
@ -579,7 +588,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
long length = getMinimumMultipartBlobSize(); long length = getMinimumMultipartBlobSize();
ByteSource byteSource = TestUtils.randomByteSource().slice(0, length); ByteSource byteSource = TestUtils.randomByteSource().slice(0, length);
Payload payload = new InputStreamPayload(byteSource.openStream()); Payload payload = new InputStreamPayload(byteSource.openStream());
testPut(payload, new ByteSourcePayload(byteSource), length, new PutOptions().multipart(true)); testPut(payload, null, new ByteSourcePayload(byteSource), length, new PutOptions().multipart(true));
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
@ -606,7 +615,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
assertThat(userMetadata1).isEqualTo(userMetadata2); assertThat(userMetadata1).isEqualTo(userMetadata2);
} }
private void testPut(Payload payload, Payload expectedPayload, long length, PutOptions options) private void testPut(Payload payload, HashCode hashCode, Payload expectedPayload, long length, PutOptions options)
throws IOException, InterruptedException { throws IOException, InterruptedException {
BlobStore blobStore = view.getBlobStore(); BlobStore blobStore = view.getBlobStore();
String blobName = "multipart-upload"; String blobName = "multipart-upload";
@ -616,6 +625,9 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
.payload(payload) .payload(payload)
.contentLength(length); .contentLength(length);
addContentMetadata(blobBuilder); addContentMetadata(blobBuilder);
if (hashCode != null) {
blobBuilder.contentMD5(payload.getContentMetadata().getContentMD5AsHashCode());
}
String container = getContainerName(); String container = getContainerName();
try { try {

View File

@ -53,8 +53,8 @@ public class ContentMetadataBuilder {
public ContentMetadataBuilder contentMD5(@Nullable HashCode contentMD5) { public ContentMetadataBuilder contentMD5(@Nullable HashCode contentMD5) {
if (contentMD5 != null) { if (contentMD5 != null) {
Preconditions.checkArgument(contentMD5.bits() == 128, "MD5 hash must have 128 bits, was: %s", contentMD5.bits()); Preconditions.checkArgument(contentMD5.bits() == 128, "MD5 hash must have 128 bits, was: %s", contentMD5.bits());
this.contentMD5 = contentMD5;
} }
this.contentMD5 = contentMD5;
return this; return this;
} }