mirror of https://github.com/apache/jclouds.git
Merge pull request #644 from aledsage/Issue-936-SmallBlobAsyncMultiPart-Strike2
Issue 936: fixes async multi-part upload of small blob
This commit is contained in:
commit
997479f27a
|
@ -77,23 +77,39 @@ public class PutOptions implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* split large blobs into pieces, if supported by the provider
|
* split large blobs into pieces, if supported by the provider.
|
||||||
|
*
|
||||||
|
* Equivalent to <code>multipart(true)</code>
|
||||||
*/
|
*/
|
||||||
public PutOptions multipart() {
|
public PutOptions multipart() {
|
||||||
this.multipart = true;
|
return multipart(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether to split large blobs into pieces, if supported by the provider
|
||||||
|
*/
|
||||||
|
public PutOptions multipart(boolean val) {
|
||||||
|
this.multipart = val;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
|
public static PutOptions fromPutOptions(PutOptions putOptions) {
|
||||||
|
return multipart(putOptions.multipart);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see PutOptions#multipart()
|
* @see PutOptions#multipart()
|
||||||
*/
|
*/
|
||||||
public static PutOptions multipart() {
|
public static PutOptions multipart() {
|
||||||
PutOptions options = new PutOptions();
|
return multipart(true);
|
||||||
return options.multipart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PutOptions multipart(boolean val) {
|
||||||
|
PutOptions options = new PutOptions();
|
||||||
|
return options.multipart(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -241,7 +241,11 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
|
||||||
throw rtex;
|
throw rtex;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ListenableFuture<String> futureETag = ablobstore.putBlob(container, blob, options);
|
// Issue 936: don't just call putBlob, as that will see options=multiPart and
|
||||||
|
// recursively call this execute method again; instead mark as not multipart
|
||||||
|
// because it can all fit in one go.
|
||||||
|
PutOptions nonMultipartOptions = PutOptions.Builder.multipart(false);
|
||||||
|
ListenableFuture<String> futureETag = ablobstore.putBlob(container, blob, nonMultipartOptions);
|
||||||
return maxTime != null ?
|
return maxTime != null ?
|
||||||
futureETag.get(maxTime,TimeUnit.SECONDS) : futureETag.get();
|
futureETag.get(maxTime,TimeUnit.SECONDS) : futureETag.get();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.KeyNotFoundException;
|
import org.jclouds.blobstore.KeyNotFoundException;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
@ -44,9 +45,9 @@ import org.jclouds.s3.S3Client;
|
||||||
import org.jclouds.s3.S3ClientLiveTest;
|
import org.jclouds.s3.S3ClientLiveTest;
|
||||||
import org.jclouds.s3.domain.ListBucketResponse;
|
import org.jclouds.s3.domain.ListBucketResponse;
|
||||||
import org.jclouds.s3.domain.ObjectMetadata;
|
import org.jclouds.s3.domain.ObjectMetadata;
|
||||||
|
import org.jclouds.s3.domain.ObjectMetadata.StorageClass;
|
||||||
import org.jclouds.s3.domain.ObjectMetadataBuilder;
|
import org.jclouds.s3.domain.ObjectMetadataBuilder;
|
||||||
import org.jclouds.s3.domain.S3Object;
|
import org.jclouds.s3.domain.S3Object;
|
||||||
import org.jclouds.s3.domain.ObjectMetadata.StorageClass;
|
|
||||||
import org.testng.ITestContext;
|
import org.testng.ITestContext;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -161,6 +162,20 @@ public class AWSS3ClientLiveTest extends S3ClientLiveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMultipartAsynchronouslySmallBlob() throws IOException, InterruptedException, Exception {
|
||||||
|
String containerName = getContainerName();
|
||||||
|
|
||||||
|
try {
|
||||||
|
AsyncBlobStore asyncBlobStore = view.getAsyncBlobStore();
|
||||||
|
asyncBlobStore.createContainerInLocation(null, containerName).get();
|
||||||
|
Blob blob = asyncBlobStore.blobBuilder("small").payload("small").build();
|
||||||
|
asyncBlobStore.putBlob(containerName, blob, PutOptions.Builder.multipart()).get();
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
returnContainer(containerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testPutWithReducedRedundancyStorage() throws InterruptedException {
|
public void testPutWithReducedRedundancyStorage() throws InterruptedException {
|
||||||
String containerName = getContainerName();
|
String containerName = getContainerName();
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue