This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new f7bfdf19b63 HDDS-16659. Reuse destination OzoneBucket in streaming S3
CopyObject (#11383)
f7bfdf19b63 is described below
commit f7bfdf19b630814fca448565ef374283045c011f
Author: KUAN-HAO HUANG <[email protected]>
AuthorDate: Fri Oct 2 21:29:07 2026 +0800
HDDS-16659. Reuse destination OzoneBucket in streaming S3 CopyObject
(#11383)
Generated-by: Codex (GPT-6)
---
.../hadoop/ozone/s3/endpoint/ObjectEndpoint.java | 13 +++++++------
.../hadoop/ozone/s3/endpoint/TestObjectPut.java | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
index 430300163c5..e911b07eee1 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
@@ -238,7 +238,7 @@ Response handlePutRequest(ObjectRequestContext context,
String keyPath, InputStr
//Copy object, as copy source available.
context.setAction(S3GAction.COPY_OBJECT);
CopyObjectResponse copyObjectResponse = copyObject(volume,
- bucketName, keyPath, replicationConfig, perf);
+ bucket, keyPath, replicationConfig, perf);
return Response.status(Status.OK).entity(copyObjectResponse).header(
"Connection", "close").build();
}
@@ -1136,7 +1136,7 @@ uploadID, getChunkSize(), multiDigestInputStream, perf,
getHeaders(),
*/
@SuppressWarnings("checkstyle:ParameterNumber")
CopyResult copy(OzoneVolume volume, DigestInputStream src, String
reusedETag, long srcKeyLen,
- String destKey, String destBucket,
+ String destKey, OzoneBucket destBucket,
ReplicationConfig replication,
Map<String, String> metadata,
PerformanceStringBuilder perf, long startNanos,
@@ -1151,7 +1151,7 @@ CopyResult copy(OzoneVolume volume, DigestInputStream
src, String reusedETag, lo
srcKeyLen > getDatastreamMinLength()) {
perf.appendStreamMode();
final CopyResult copyResult = ObjectEndpointStreaming
- .copyKeyWithStream(volume.getBucket(destBucket), destKey, srcKeyLen,
+ .copyKeyWithStream(destBucket, destKey, srcKeyLen,
getChunkSize(), replication, metadata, src, reusedETag, perf,
startNanos, tags,
writeConditions);
eTag = copyResult.getETag();
@@ -1160,7 +1160,7 @@ srcKeyLen > getDatastreamMinLength()) {
} else {
final long expectedLength = srcKeyLen;
final OzoneOutputStream destStream = openKeyForPut(
- volume.getName(), destBucket, destKey, expectedLength,
+ volume.getName(), destBucket.getName(), destKey, expectedLength,
replication, metadata, tags, writeConditions, false);
try (S3ObjectWriteGuard dest = new S3ObjectWriteGuard(destStream,
expectedLength, destKey)) {
long metadataLatencyNs =
@@ -1179,9 +1179,10 @@ srcKeyLen > getDatastreamMinLength()) {
}
private CopyObjectResponse copyObject(OzoneVolume volume,
- String destBucket, String destkey, ReplicationConfig replicationConfig,
+ OzoneBucket destinationBucket, String destkey, ReplicationConfig
replicationConfig,
PerformanceStringBuilder perf)
throws OS3Exception, IOException {
+ String destBucket = destinationBucket.getName();
String copyHeader = getHeaders().getHeaderString(COPY_SOURCE_HEADER);
String storageType = getHeaders().getHeaderString(STORAGE_CLASS_HEADER);
boolean storageTypeDefault = StringUtils.isEmpty(storageType);
@@ -1294,7 +1295,7 @@ private CopyObjectResponse copyObject(OzoneVolume volume,
sourceDigestInputStream.on(false);
}
final CopyResult copyResult = runWithS3ActionString("PutObject", () ->
- copy(volume, sourceDigestInputStream, reusedETag, sourceKeyLen,
destkey, destBucket,
+ copy(volume, sourceDigestInputStream, reusedETag, sourceKeyLen,
destkey, destinationBucket,
replicationConfig, customMetadata, perf, startNanos, tags,
writeConditions));
getMetrics().updateCopyObjectSuccessStats(startNanos);
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
index 4ac538a4a7d..8e48c6ca1f9 100644
---
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
@@ -59,6 +59,7 @@
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
@@ -737,6 +738,25 @@ public void
testCopyObjectMessageDigestResetDuringException() throws Exception {
}
}
+ @Test
+ void testStreamingCopyReusesDestinationBucket() throws Exception {
+ assertSucceeds(() -> putObject(CONTENT));
+ objectEndpoint.init();
+ OzoneVolume volume = spy(objectEndpoint.getVolume());
+ doReturn(volume).when(objectEndpoint).getVolume();
+ doReturn(true).when(objectEndpoint).isDatastreamEnabled();
+ doReturn(0L).when(objectEndpoint).getDatastreamMinLength();
+ when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(BUCKET_NAME +
"/" + urlEncode(KEY_NAME));
+
+ try (Response response = put(objectEndpoint, DEST_BUCKET_NAME, DEST_KEY,
CONTENT)) {
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
+ assertThat(((CopyObjectResponse)
response.getEntity()).getETag()).isEqualTo("\"" + contentMd5Hex() + "\"");
+ }
+ assertKeyContent(destBucket, DEST_KEY, CONTENT);
+
assertThat(destBucket.getKey(DEST_KEY).getMetadata().get(OzoneConsts.ETAG)).isEqualTo(contentMd5Hex());
+ verify(volume).getBucket(DEST_BUCKET_NAME);
+ }
+
@Test
void testCopyObjectReusesSourceETagWithoutRehashing() throws Exception {
assertSucceeds(() -> putObject(CONTENT));
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]