peterxcli commented on code in PR #11136:
URL: https://github.com/apache/ozone/pull/11136#discussion_r3879565347


##########
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java:
##########
@@ -1115,8 +1121,9 @@ srcKeyLen > getDatastreamMinLength()) {
             getMetrics().updateCopyKeyMetadataStats(startNanos);
         perf.appendMetaLatencyNanos(metadataLatencyNs);
         copyLength = dest.copyFrom(src, getIOBufferSize(expectedLength));
-        String md5Hash = 
DatatypeConverter.printHexBinary(src.getMessageDigest().digest()).toLowerCase();
-        dest.getMetadata().put(OzoneConsts.ETAG, md5Hash);
+        String eTag = reusedETag != null ? reusedETag
+            : DatatypeConverter.printHexBinary(((DigestInputStream) 
src).getMessageDigest().digest()).toLowerCase();
+        dest.getMetadata().put(OzoneConsts.ETAG, eTag);

Review Comment:
   Good catch, fixed in 81061dd.
   
   Rather than add a runtime contract check, I went the other way and made the 
unsafe combination unrepresentable: `copy(...)` keeps its original 
`DigestInputStream` parameter type, and the reuse path switches hashing off 
with `DigestInputStream#on(false)` instead of passing a bare `InputStream`. So 
there is no cast left, and the implicit "`src` is a `DigestInputStream` iff 
`reusedETag == null`" coupling between two parameters is gone.
   
   Side benefit: the only signature change against master is now the added 
`reusedETag` parameter, so the diff is smaller than before.
   
   `TestObjectPut#testCopyObjectReusesSourceETagWithoutRehashing` already stubs 
the thread-local MD5 digest to throw if `update` is called, so it also pins the 
`on(false)` behaviour. Re-benchmarked to confirm the win survives: 64 MiB 
CopyObject 104.35 ms -> 10.32 ms (90.1%), and a counting `MessageDigest` 
confirms the reuse path still feeds 0 bytes to MD5 while the digesting path 
feeds the full 67,108,864.



##########
hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpointStreaming.java:
##########
@@ -189,8 +196,8 @@ public static long copyKeyWithStream(
       long metadataLatencyNs =
           METRICS.updateCopyKeyMetadataStats(startNanos);
       writeLen = writeGuard.copyFrom(body, bufferSize);
-      String eTag = 
DatatypeConverter.printHexBinary(body.getMessageDigest().digest())
-          .toLowerCase();
+      String eTag = reusedETag != null ? reusedETag
+          : DatatypeConverter.printHexBinary(((DigestInputStream) 
body).getMessageDigest().digest()).toLowerCase();
       perf.appendMetaLatencyNanos(metadataLatencyNs);
       writeGuard.getMetadata().put(OzoneConsts.ETAG, eTag);

Review Comment:
   Fixed in 81061dd, same approach as the sibling comment on `ObjectEndpoint`.
   
   I took the second of your two suggestions: `copyKeyWithStream(...)` keeps 
`body` typed as `DigestInputStream`, and the caller switches hashing off with 
`DigestInputStream#on(false)` when it is going to reuse the source ETag. No 
cast, no runtime check needed, and both write paths now express the same thing 
the same way.
   
   Verified on the datastream path specifically by 
`TestUploadWithStream#testUploadWithCopyReusesSourceETag` (asserts the stored 
ETag is the reused one, not a recomputed MD5) and 
`#testUploadWithCopyRecomputesETagForMultipartSource` (asserts a `-N` source 
still gets a fresh content MD5).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to