JCLOUDS-894: Expose S3 multipart operations

This commit is contained in:
Andrew Gaul 2015-04-25 11:19:28 -07:00
parent ca543f3cdd
commit 9128ae515f
2 changed files with 65 additions and 1 deletions

View File

@ -34,6 +34,8 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobAccess; import org.jclouds.blobstore.domain.BlobAccess;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerAccess; import org.jclouds.blobstore.domain.ContainerAccess;
import org.jclouds.blobstore.domain.MultipartPart;
import org.jclouds.blobstore.domain.MultipartUpload;
import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
@ -48,8 +50,10 @@ import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.io.ContentMetadata; import org.jclouds.io.ContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.s3.S3Client; import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.functions.BlobToObject; import org.jclouds.s3.blobstore.functions.BlobToObject;
import org.jclouds.s3.blobstore.functions.BlobToObjectMetadata;
import org.jclouds.s3.blobstore.functions.BucketToResourceList; import org.jclouds.s3.blobstore.functions.BucketToResourceList;
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions; import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
import org.jclouds.s3.blobstore.functions.ObjectToBlob; import org.jclouds.s3.blobstore.functions.ObjectToBlob;
@ -72,6 +76,8 @@ import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@Singleton @Singleton
@ -83,6 +89,7 @@ public class S3BlobStore extends BaseBlobStore {
private final ObjectToBlob object2Blob; private final ObjectToBlob object2Blob;
private final BlobToObject blob2Object; private final BlobToObject blob2Object;
private final ObjectToBlobMetadata object2BlobMd; private final ObjectToBlobMetadata object2BlobMd;
private final BlobToObjectMetadata blob2ObjectMetadata;
private final BlobToHttpGetOptions blob2ObjectGetOptions; private final BlobToHttpGetOptions blob2ObjectGetOptions;
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider; private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
private final LoadingCache<String, AccessControlList> bucketAcls; private final LoadingCache<String, AccessControlList> bucketAcls;
@ -94,6 +101,7 @@ public class S3BlobStore extends BaseBlobStore {
Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata, Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata,
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList, ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
BlobToObjectMetadata blob2ObjectMetadata,
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider, ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
LoadingCache<String, AccessControlList> bucketAcls, LoadingCache<String, AccessControlList> bucketAcls,
Provider<MultipartUploadStrategy> multipartUploadStrategy) { Provider<MultipartUploadStrategy> multipartUploadStrategy) {
@ -106,6 +114,7 @@ public class S3BlobStore extends BaseBlobStore {
this.object2Blob = checkNotNull(object2Blob, "object2Blob"); this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object"); this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd"); this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
this.blob2ObjectMetadata = checkNotNull(blob2ObjectMetadata, "blob2ObjectMetadata");
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider"); this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
this.bucketAcls = checkNotNull(bucketAcls, "bucketAcls"); this.bucketAcls = checkNotNull(bucketAcls, "bucketAcls");
this.multipartUploadStrategy = checkNotNull(multipartUploadStrategy, "multipartUploadStrategy"); this.multipartUploadStrategy = checkNotNull(multipartUploadStrategy, "multipartUploadStrategy");
@ -359,6 +368,59 @@ public class S3BlobStore extends BaseBlobStore {
sync.putObjectACL(container, name, acl); sync.putObjectACL(container, name, acl);
} }
@Override
public MultipartUpload initiateMultipartUpload(String container, BlobMetadata blobMetadata) {
String id = sync.initiateMultipartUpload(container, blob2ObjectMetadata.apply(blobMetadata));
return MultipartUpload.create(container, blobMetadata.getName(), id, blobMetadata);
}
@Override
public void abortMultipartUpload(MultipartUpload mpu) {
sync.abortMultipartUpload(mpu.containerName(), mpu.blobName(), mpu.id());
}
@Override
public String completeMultipartUpload(MultipartUpload mpu, List<MultipartPart> parts) {
ImmutableMap.Builder<Integer, String> builder = ImmutableMap.builder();
for (MultipartPart part : parts) {
builder.put(part.partNumber(), part.partETag());
}
return sync.completeMultipartUpload(mpu.containerName(), mpu.blobName(), mpu.id(), builder.build());
}
@Override
public MultipartPart uploadMultipartPart(MultipartUpload mpu, int partNumber, Payload payload) {
long partSize = -1; // TODO: how to get this from payload?
String eTag = sync.uploadPart(mpu.containerName(), mpu.blobName(), partNumber, mpu.id(), payload);
return MultipartPart.create(partNumber, partSize, eTag);
}
@Override
public List<MultipartPart> listMultipartUpload(MultipartUpload mpu) {
ImmutableList.Builder<MultipartPart> parts = ImmutableList.builder();
Map<Integer, String> s3Parts = sync.listMultipartParts(mpu.containerName(), mpu.blobName(), mpu.id());
for (Map.Entry<Integer, String> entry : s3Parts.entrySet()) {
long partSize = -1; // TODO: could call getContentLength but did not above
parts.add(MultipartPart.create(entry.getKey(), partSize, "\"" + entry.getValue() + "\""));
}
return parts.build();
}
@Override
public long getMinimumMultipartPartSize() {
return 5 * 1024 * 1024;
}
@Override
public long getMaximumMultipartPartSize() {
return 5L * 1024L * 1024L * 1024L;
}
@Override
public int getMaximumNumberOfParts() {
return 10 * 1000;
}
/** /**
* This implementation invokes {@link S3Utils#deleteAndVerifyContainerGone} * This implementation invokes {@link S3Utils#deleteAndVerifyContainerGone}
*/ */

View File

@ -40,6 +40,7 @@ import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.s3.blobstore.S3BlobStore; import org.jclouds.s3.blobstore.S3BlobStore;
import org.jclouds.s3.blobstore.functions.BlobToObject; import org.jclouds.s3.blobstore.functions.BlobToObject;
import org.jclouds.s3.blobstore.functions.BlobToObjectMetadata;
import org.jclouds.s3.blobstore.functions.BucketToResourceList; import org.jclouds.s3.blobstore.functions.BucketToResourceList;
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions; import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
import org.jclouds.s3.blobstore.functions.ObjectToBlob; import org.jclouds.s3.blobstore.functions.ObjectToBlob;
@ -69,12 +70,13 @@ public class AWSS3BlobStore extends S3BlobStore {
Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata, Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata,
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList, ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
BlobToObjectMetadata blob2ObjectMetadata,
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider, ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
LoadingCache<String, AccessControlList> bucketAcls, LoadingCache<String, AccessControlList> bucketAcls,
Provider<MultipartUploadStrategy> multipartUploadStrategy) { Provider<MultipartUploadStrategy> multipartUploadStrategy) {
super(context, blobUtils, defaultLocation, locations, sync, convertBucketsToStorageMetadata, super(context, blobUtils, defaultLocation, locations, sync, convertBucketsToStorageMetadata,
container2BucketListOptions, bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object, container2BucketListOptions, bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object,
object2BlobMd, fetchBlobMetadataProvider, bucketAcls, blob2ObjectMetadata, object2BlobMd, fetchBlobMetadataProvider, bucketAcls,
multipartUploadStrategy); multipartUploadStrategy);
this.bucketAcls = bucketAcls; this.bucketAcls = bucketAcls;
this.blob2Object = blob2Object; this.blob2Object = blob2Object;