private StoredObject createCombinedObjectLarge(CombinedStoredObject combinedObject) { URI location = combinedObject.getLocation(); log.info("starting multipart upload: %s", location); String bucket = getS3Bucket(location); String key = getS3ObjectKey(location); String uploadId = s3Service .initiateMultipartUpload(new InitiateMultipartUploadRequest(bucket, key)) .getUploadId(); try { List<PartETag> parts = newArrayList(); int partNumber = 1; for (StoredObject newCombinedObjectPart : combinedObject.getSourceParts()) { CopyPartResult part = s3Service.copyPart( new CopyPartRequest() .withUploadId(uploadId) .withPartNumber(partNumber) .withDestinationBucketName(bucket) .withDestinationKey(key) .withSourceBucketName(getS3Bucket(newCombinedObjectPart.getLocation())) .withSourceKey(getS3ObjectKey(newCombinedObjectPart.getLocation()))); parts.add(new PartETag(partNumber, part.getETag())); partNumber++; } String etag = s3Service .completeMultipartUpload( new CompleteMultipartUploadRequest(bucket, key, uploadId, parts)) .getETag(); ObjectMetadata newObject = s3Service.getObjectMetadata(bucket, key); log.info("completed multipart upload: %s", location); if (!etag.equals(newObject.getETag())) { // this might happen in rare cases due to S3's eventual consistency throw new IllegalStateException("completed etag is different from combined object etag"); } return updateStoredObject(location, newObject); } catch (AmazonClientException e) { try { s3Service.abortMultipartUpload(new AbortMultipartUploadRequest(bucket, key, uploadId)); } catch (AmazonClientException ignored) { } throw Throwables.propagate(e); } }
@Override public StoredObject putObject(URI location, File source) { try { log.info("starting upload: %s", location); PutObjectResult result = s3Service.putObject(getS3Bucket(location), getS3ObjectKey(location), source); ObjectMetadata metadata = s3Service.getObjectMetadata(getS3Bucket(location), getS3ObjectKey(location)); if (!result.getETag().equals(metadata.getETag())) { // this might happen in rare cases due to S3's eventual consistency throw new IllegalStateException("uploaded etag is different from retrieved object etag"); } log.info("completed upload: %s", location); return updateStoredObject(location, metadata); } catch (Exception e) { throw Throwables.propagate(e); } }