Skip to content

Commit 0bf8494

Browse files
authored
Merge pull request #3371 from aws/feature/master/flexiblechecksums-v2-phase1
Releasing CRC64 and checksum refactoring change
2 parents f048671 + 820ed16 commit 0bf8494

File tree

57 files changed

+1377
-320
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1377
-320
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "deprecation",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Deprecate internal checksum algorithm classes."
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "The SDK now defaults to Java built-in CRC32 and CRC32C(if it's Java 9+) implementations, resulting in improved performance."
6+
}

build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,8 @@
303303
<!-- Retrieves and updates crc value in update() -->
304304
<Match>
305305
<Or>
306-
<Class name="software.amazon.awssdk.http.auth.aws.internal.signer.checksums.SdkCrc32CChecksum"/>
307-
<Class name="software.amazon.awssdk.http.auth.aws.internal.signer.checksums.SdkCrc32Checksum"/>
306+
<Class name="software.amazon.awssdk.checksums.internal.SdkCrc32CChecksum"/>
307+
<Class name="software.amazon.awssdk.checksums.internal.SdkCrc32Checksum"/>
308308
<Class name="software.amazon.awssdk.core.internal.checksums.factory.SdkCrc32C"/>
309309
<Class name="software.amazon.awssdk.core.internal.checksums.factory.SdkCrc32"/>
310310
</Or>

core/checksums/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@
4545
<version>${awsjavasdk.version}</version>
4646
</dependency>
4747

48+
<dependency>
49+
<groupId>software.amazon.awssdk</groupId>
50+
<artifactId>utils</artifactId>
51+
<version>${awsjavasdk.version}</version>
52+
</dependency>
53+
54+
<dependency>
55+
<groupId>software.amazon.awssdk.crt</groupId>
56+
<artifactId>aws-crt</artifactId>
57+
<version>${awscrt.version}</version>
58+
<optional>true</optional>
59+
</dependency>
60+
4861
<dependency>
4962
<groupId>org.junit.jupiter</groupId>
5063
<artifactId>junit-jupiter</artifactId>

core/checksums/src/main/java/software/amazon/awssdk/checksums/DefaultChecksumAlgorithm.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public final class DefaultChecksumAlgorithm {
2929
public static final ChecksumAlgorithm MD5 = of("MD5");
3030
public static final ChecksumAlgorithm SHA256 = of("SHA256");
3131
public static final ChecksumAlgorithm SHA1 = of("SHA1");
32+
public static final ChecksumAlgorithm CRC64NVME = of("CRC64NVME");
3233

3334
private DefaultChecksumAlgorithm() {
3435
}
Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,48 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
package software.amazon.awssdk.http.auth.aws.internal.signer.checksums;
16+
package software.amazon.awssdk.checksums;
1717

1818
import java.nio.ByteBuffer;
1919
import java.util.zip.Checksum;
20-
import software.amazon.awssdk.annotations.SdkInternalApi;
20+
import software.amazon.awssdk.annotations.SdkProtectedApi;
21+
import software.amazon.awssdk.checksums.internal.Crc32Checksum;
22+
import software.amazon.awssdk.checksums.internal.Crc32cProvider;
23+
import software.amazon.awssdk.checksums.internal.Crc64NvmeChecksum;
24+
import software.amazon.awssdk.checksums.internal.Md5Checksum;
25+
import software.amazon.awssdk.checksums.internal.Sha1Checksum;
26+
import software.amazon.awssdk.checksums.internal.Sha256Checksum;
27+
import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm;
2128

2229
/**
2330
* Extension of {@link Checksum} to support checksums and checksum validations used by the SDK that are not provided by the JDK.
2431
*/
25-
@SdkInternalApi
32+
@SdkProtectedApi
2633
public interface SdkChecksum extends Checksum {
2734

35+
/**
36+
* Returns an {@link SdkChecksum} based on the {@link ChecksumAlgorithm} provided.
37+
* UnsupportedOperationException will be thrown for unsupported algorithm.
38+
*/
39+
static SdkChecksum forAlgorithm(ChecksumAlgorithm algorithm) {
40+
switch (algorithm.algorithmId()) {
41+
case "CRC32C":
42+
return Crc32cProvider.create();
43+
case "CRC32":
44+
return new Crc32Checksum();
45+
case "SHA1":
46+
return new Sha1Checksum();
47+
case "SHA256":
48+
return new Sha256Checksum();
49+
case "MD5":
50+
return new Md5Checksum();
51+
case "CRC64NVME":
52+
return new Crc64NvmeChecksum();
53+
default:
54+
throw new UnsupportedOperationException("Unsupported checksum algorithm: " + algorithm);
55+
}
56+
}
57+
2858
/**
2959
* Returns the computed checksum in a byte array rather than the long provided by {@link #getValue()}.
3060
*
@@ -49,7 +79,6 @@ default void update(byte[] b) {
4979
update(b, 0, b.length);
5080
}
5181

52-
5382
/**
5483
* Updates the current checksum with the bytes from the specified buffer.
5584
* <p>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.checksums.internal;
17+
18+
import java.util.zip.Checksum;
19+
import software.amazon.awssdk.annotations.SdkInternalApi;
20+
import software.amazon.awssdk.checksums.SdkChecksum;
21+
22+
/**
23+
* Base class for CRC related checksums
24+
*/
25+
@SdkInternalApi
26+
public abstract class BaseCrcChecksum implements SdkChecksum {
27+
28+
private Checksum checksum;
29+
private Checksum lastMarkedChecksum;
30+
31+
public BaseCrcChecksum(Checksum checksum) {
32+
this.checksum = checksum;
33+
}
34+
35+
public Checksum getChecksum() {
36+
return checksum;
37+
}
38+
39+
@Override
40+
public void mark(int readLimit) {
41+
this.lastMarkedChecksum = cloneChecksum(checksum);
42+
}
43+
44+
@Override
45+
public void update(int b) {
46+
checksum.update(b);
47+
}
48+
49+
@Override
50+
public void update(byte[] b, int off, int len) {
51+
checksum.update(b, off, len);
52+
}
53+
54+
@Override
55+
public long getValue() {
56+
return checksum.getValue();
57+
}
58+
59+
@Override
60+
public void reset() {
61+
if (lastMarkedChecksum == null) {
62+
checksum.reset();
63+
} else {
64+
checksum = cloneChecksum(lastMarkedChecksum);
65+
}
66+
}
67+
68+
abstract Checksum cloneChecksum(Checksum checksum);
69+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.checksums.internal;
17+
18+
import java.lang.ref.WeakReference;
19+
import java.lang.reflect.Constructor;
20+
import java.util.Collections;
21+
import java.util.Map;
22+
import java.util.Optional;
23+
import java.util.WeakHashMap;
24+
import java.util.concurrent.ConcurrentHashMap;
25+
import software.amazon.awssdk.annotations.SdkInternalApi;
26+
import software.amazon.awssdk.utils.ClassLoaderHelper;
27+
import software.amazon.awssdk.utils.Logger;
28+
29+
/**
30+
* A cache that stores classes and their constructors by class name and class loader.
31+
* <p>
32+
* This cache uses weak references to both class loaders and classes, allowing them to be garbage collected
33+
* when no longer needed. It provides methods to retrieve the zero-argument constructor for a class,
34+
* based on the current thread's context class loader or the system class loader.
35+
* <p>
36+
* If a class or its zero-argument constructor cannot be found, an empty result is returned.
37+
*/
38+
@SdkInternalApi
39+
public final class ConstructorCache {
40+
private static final Logger log = Logger.loggerFor(ConstructorCache.class);
41+
42+
/**
43+
* Cache storing classes by class name and class loader.
44+
* Uses weak references to allow garbage collection when not needed.
45+
*/
46+
private final Map<String, Map<ClassLoader, Optional<WeakReference<Class<?>>>>> classesByClassName =
47+
new ConcurrentHashMap<>();
48+
49+
/**
50+
* Retrieve the class for the given class name from the context or system class loader.
51+
* Returns an empty result if the class is not found.
52+
*/
53+
private Optional<Class<?>> getClass(String className) {
54+
Map<ClassLoader, Optional<WeakReference<Class<?>>>> classesByClassLoader =
55+
classesByClassName.computeIfAbsent(className, k -> Collections.synchronizedMap(new WeakHashMap<>()));
56+
57+
ClassLoader classLoader = ClassLoaderHelper.contextClassLoader();
58+
Optional<WeakReference<Class<?>>> classRef = classesByClassLoader.computeIfAbsent(classLoader, k -> {
59+
try {
60+
Class<?> clazz = classLoader.loadClass(className);
61+
return Optional.of(new WeakReference<>(clazz));
62+
} catch (ClassNotFoundException e) {
63+
return Optional.empty();
64+
}
65+
});
66+
return classRef.map(WeakReference::get);
67+
}
68+
69+
/**
70+
* Retrieve the zero-argument constructor for the given class name.
71+
* Returns an empty result if no such constructor is found.
72+
*/
73+
public Optional<Constructor<?>> getConstructor(String className) {
74+
return getClass(className).flatMap(clazz -> {
75+
try {
76+
return Optional.of(clazz.getConstructor());
77+
} catch (NoSuchMethodException e) {
78+
log.debug(() -> "Classloader contains " + className + ", but without a zero-arg constructor.", e);
79+
return Optional.empty();
80+
}
81+
});
82+
}
83+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.checksums.internal;
17+
18+
19+
import java.util.zip.CRC32;
20+
import software.amazon.awssdk.annotations.SdkInternalApi;
21+
import software.amazon.awssdk.checksums.SdkChecksum;
22+
23+
@SdkInternalApi
24+
public final class Crc32Checksum implements SdkChecksum {
25+
private final CrcCombineOnMarkChecksum crc32;
26+
27+
public Crc32Checksum() {
28+
// Delegates to CrcCombineOnMarkChecksum with CRC32
29+
this.crc32 = new CrcCombineOnMarkChecksum(
30+
new CRC32(),
31+
SdkCrc32Checksum::combine
32+
);
33+
}
34+
35+
@Override
36+
public byte[] getChecksumBytes() {
37+
return crc32.getChecksumBytes();
38+
}
39+
40+
@Override
41+
public void mark(int readLimit) {
42+
crc32.mark(readLimit);
43+
}
44+
45+
@Override
46+
public void update(int b) {
47+
crc32.update(b);
48+
}
49+
50+
@Override
51+
public void update(byte[] b, int off, int len) {
52+
crc32.update(b, off, len);
53+
}
54+
55+
@Override
56+
public long getValue() {
57+
return crc32.getValue();
58+
}
59+
60+
@Override
61+
public void reset() {
62+
crc32.reset();
63+
}
64+
}

0 commit comments

Comments
 (0)