Search in sources :

Example 1 with S3ObjectMetadata

use of com.formkiq.aws.s3.S3ObjectMetadata in project pravega by pravega.

the class ExtendedS3Storage method doCreate.

private SegmentHandle doCreate(String streamSegmentName) throws StreamSegmentExistsException {
    long traceId = LoggerHelpers.traceEnter(log, "create", streamSegmentName);
    Timer timer = new Timer();
    if (!client.listObjects(config.getBucket(), config.getPrefix() + streamSegmentName).getObjects().isEmpty()) {
        throw new StreamSegmentExistsException(streamSegmentName);
    }
    S3ObjectMetadata metadata = new S3ObjectMetadata();
    metadata.setContentLength((long) 0);
    PutObjectRequest request = new PutObjectRequest(config.getBucket(), config.getPrefix() + streamSegmentName, null);
    AccessControlList acl = new AccessControlList();
    acl.addGrants(new Grant(new CanonicalUser(config.getAccessKey(), config.getAccessKey()), READ_WRITE_PERMISSION));
    request.setAcl(acl);
    /* Default behavior of putObject is to overwrite an existing object. This behavior can cause data loss.
         * Here is one of the scenarios in which data loss is observed:
         * 1. Host A owns the container and gets a create operation. It has not executed the putObject operation yet.
         * 2. Ownership changes and host B becomes the owner of the container. It picks up putObject from the queue, executes it.
         * 3. Host B gets a write operation which executes successfully.
         * 4. Now host A schedules the putObject. This will overwrite the write by host B.
         *
         * The solution for this issue is to implement put-if-absent behavior by using Set-If-None-Match header as described here:
         * http://www.emc.com/techpubs/api/ecs/v3-0-0-0/S3ObjectOperations_createOrUpdateObject_7916bd6f789d0ae0ff39961c0e660d00_ba672412ac371bb6cf4e69291344510e_detail.htm
         * But this does not work. Currently all the calls to putObject API fail if made with reqest.setIfNoneMatch("*").
         * once the issue with extended S3 API is fixed, addition of this one line will ensure put-if-absent semantics.
         * See: https://github.com/pravega/pravega/issues/1564
         *
         * This issue is fixed in some versions of extended S3 implementation. The following code sets the IfNoneMatch
         * flag based on configuration.
         */
    if (config.isUseNoneMatch()) {
        request.setIfNoneMatch("*");
    }
    client.putObject(request);
    Duration elapsed = timer.getElapsed();
    ExtendedS3Metrics.CREATE_LATENCY.reportSuccessEvent(elapsed);
    ExtendedS3Metrics.CREATE_COUNT.inc();
    log.debug("Create segment={} latency={}.", streamSegmentName, elapsed.toMillis());
    LoggerHelpers.traceLeave(log, "create", traceId);
    return ExtendedS3SegmentHandle.getWriteHandle(streamSegmentName);
}
Also used : AccessControlList(com.emc.object.s3.bean.AccessControlList) Grant(com.emc.object.s3.bean.Grant) StreamSegmentExistsException(io.pravega.segmentstore.contracts.StreamSegmentExistsException) Timer(io.pravega.common.Timer) S3ObjectMetadata(com.emc.object.s3.S3ObjectMetadata) Duration(java.time.Duration) CanonicalUser(com.emc.object.s3.bean.CanonicalUser) PutObjectRequest(com.emc.object.s3.request.PutObjectRequest)

Example 2 with S3ObjectMetadata

use of com.formkiq.aws.s3.S3ObjectMetadata in project pravega by pravega.

the class ExtendedS3Storage method doGetStreamSegmentInfo.

private StreamSegmentInformation doGetStreamSegmentInfo(String streamSegmentName) {
    long traceId = LoggerHelpers.traceEnter(log, "getStreamSegmentInfo", streamSegmentName);
    S3ObjectMetadata result = client.getObjectMetadata(config.getBucket(), config.getPrefix() + streamSegmentName);
    AccessControlList acls = client.getObjectAcl(config.getBucket(), config.getPrefix() + streamSegmentName);
    boolean canWrite = acls.getGrants().stream().anyMatch(grant -> grant.getPermission().compareTo(Permission.WRITE) >= 0);
    StreamSegmentInformation information = StreamSegmentInformation.builder().name(streamSegmentName).length(result.getContentLength()).sealed(!canWrite).lastModified(new ImmutableDate(result.getLastModified().toInstant().toEpochMilli())).build();
    LoggerHelpers.traceLeave(log, "getStreamSegmentInfo", traceId, streamSegmentName);
    return information;
}
Also used : AccessControlList(com.emc.object.s3.bean.AccessControlList) StreamSegmentInformation(io.pravega.segmentstore.contracts.StreamSegmentInformation) ImmutableDate(io.pravega.common.util.ImmutableDate) S3ObjectMetadata(com.emc.object.s3.S3ObjectMetadata)

Example 3 with S3ObjectMetadata

use of com.formkiq.aws.s3.S3ObjectMetadata in project pravega by pravega.

the class ExtendedS3ChunkStorage method doCreate.

@Override
protected ChunkHandle doCreate(String chunkName) throws ChunkStorageException {
    Preconditions.checkState(supportsAppend, "supportsAppend is false.");
    try {
        if (!client.listObjects(config.getBucket(), getObjectPath(chunkName)).getObjects().isEmpty()) {
            throw new ChunkAlreadyExistsException(chunkName, "Chunk already exists");
        }
        S3ObjectMetadata metadata = new S3ObjectMetadata();
        metadata.setContentLength((long) 0);
        PutObjectRequest request = new PutObjectRequest(config.getBucket(), getObjectPath(chunkName), null).withObjectMetadata(metadata);
        if (config.isUseNoneMatch()) {
            request.setIfNoneMatch("*");
        }
        client.putObject(request);
        return ChunkHandle.writeHandle(chunkName);
    } catch (Exception e) {
        throw convertException(chunkName, "doCreate", e);
    }
}
Also used : ChunkAlreadyExistsException(io.pravega.segmentstore.storage.chunklayer.ChunkAlreadyExistsException) S3ObjectMetadata(com.emc.object.s3.S3ObjectMetadata) PutObjectRequest(com.emc.object.s3.request.PutObjectRequest) InvalidOffsetException(io.pravega.segmentstore.storage.chunklayer.InvalidOffsetException) S3Exception(com.emc.object.s3.S3Exception) ChunkStorageException(io.pravega.segmentstore.storage.chunklayer.ChunkStorageException) ChunkNotFoundException(io.pravega.segmentstore.storage.chunklayer.ChunkNotFoundException) ChunkAlreadyExistsException(io.pravega.segmentstore.storage.chunklayer.ChunkAlreadyExistsException)

Example 4 with S3ObjectMetadata

use of com.formkiq.aws.s3.S3ObjectMetadata in project pravega by pravega.

the class ExtendedS3ChunkStorage method doGetInfo.

@Override
protected ChunkInfo doGetInfo(String chunkName) throws ChunkStorageException {
    try {
        S3ObjectMetadata result = client.getObjectMetadata(config.getBucket(), getObjectPath(chunkName));
        ChunkInfo information = ChunkInfo.builder().name(chunkName).length(result.getContentLength()).build();
        return information;
    } catch (Exception e) {
        throw convertException(chunkName, "doGetInfo", e);
    }
}
Also used : ChunkInfo(io.pravega.segmentstore.storage.chunklayer.ChunkInfo) S3ObjectMetadata(com.emc.object.s3.S3ObjectMetadata) InvalidOffsetException(io.pravega.segmentstore.storage.chunklayer.InvalidOffsetException) S3Exception(com.emc.object.s3.S3Exception) ChunkStorageException(io.pravega.segmentstore.storage.chunklayer.ChunkStorageException) ChunkNotFoundException(io.pravega.segmentstore.storage.chunklayer.ChunkNotFoundException) ChunkAlreadyExistsException(io.pravega.segmentstore.storage.chunklayer.ChunkAlreadyExistsException)

Example 5 with S3ObjectMetadata

use of com.formkiq.aws.s3.S3ObjectMetadata in project pravega by pravega.

the class ExtendedS3ChunkStorage method doCreateWithContent.

@Override
protected ChunkHandle doCreateWithContent(String chunkName, int length, InputStream data) throws ChunkStorageException {
    try {
        val objectPath = getObjectPath(chunkName);
        S3ObjectMetadata metadata = new S3ObjectMetadata().withContentType("application/octet-stream").withContentLength(length);
        val request = new PutObjectRequest(this.config.getBucket(), objectPath, data).withObjectMetadata(metadata);
        client.putObject(request);
        return ChunkHandle.writeHandle(chunkName);
    } catch (Exception e) {
        throw convertException(chunkName, "doCreateWithContent", e);
    }
}
Also used : lombok.val(lombok.val) S3ObjectMetadata(com.emc.object.s3.S3ObjectMetadata) PutObjectRequest(com.emc.object.s3.request.PutObjectRequest) InvalidOffsetException(io.pravega.segmentstore.storage.chunklayer.InvalidOffsetException) S3Exception(com.emc.object.s3.S3Exception) ChunkStorageException(io.pravega.segmentstore.storage.chunklayer.ChunkStorageException) ChunkNotFoundException(io.pravega.segmentstore.storage.chunklayer.ChunkNotFoundException) ChunkAlreadyExistsException(io.pravega.segmentstore.storage.chunklayer.ChunkAlreadyExistsException)

Aggregations

S3ObjectMetadata (com.emc.object.s3.S3ObjectMetadata)16 S3Exception (com.emc.object.s3.S3Exception)7 S3ObjectMetadata (com.formkiq.aws.s3.S3ObjectMetadata)7 S3ObjectMetadata (uk.nhs.digital.externalstorage.s3.S3ObjectMetadata)7 S3Client (software.amazon.awssdk.services.s3.S3Client)5 AccessControlList (com.emc.object.s3.bean.AccessControlList)4 PutObjectRequest (com.emc.object.s3.request.PutObjectRequest)4 Test (org.junit.Test)4 CopyPartResult (com.emc.object.s3.bean.CopyPartResult)3 MultipartPartETag (com.emc.object.s3.bean.MultipartPartETag)3 PutObjectResult (com.emc.object.s3.bean.PutObjectResult)3 CompleteMultipartUploadRequest (com.emc.object.s3.request.CompleteMultipartUploadRequest)3 CopyPartRequest (com.emc.object.s3.request.CopyPartRequest)3 ChunkAlreadyExistsException (io.pravega.segmentstore.storage.chunklayer.ChunkAlreadyExistsException)3 ChunkNotFoundException (io.pravega.segmentstore.storage.chunklayer.ChunkNotFoundException)3 ChunkStorageException (io.pravega.segmentstore.storage.chunklayer.ChunkStorageException)3 InvalidOffsetException (io.pravega.segmentstore.storage.chunklayer.InvalidOffsetException)3 Date (java.util.Date)3 TreeSet (java.util.TreeSet)3 CanonicalUser (com.emc.object.s3.bean.CanonicalUser)2