| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.kafka.common.utils; |
| |
| import java.lang.invoke.MethodHandle; |
| import java.lang.invoke.MethodHandles; |
| import java.lang.invoke.MethodType; |
| import java.nio.ByteBuffer; |
| import java.util.zip.Checksum; |
| |
| /** |
| * A class that can be used to compute the CRC32C (Castagnoli) of a ByteBuffer or array of bytes. |
| * |
| * We use java.util.zip.CRC32C (introduced in Java 9) if it is available and fallback to PureJavaCrc32C, otherwise. |
| * java.util.zip.CRC32C is significantly faster on reasonably modern CPUs as it uses the CRC32 instruction introduced |
| * in SSE4.2. |
| * |
| * NOTE: This class is intended for INTERNAL usage only within Kafka. |
| */ |
| public final class Crc32C { |
| |
| private static final ChecksumFactory CHECKSUM_FACTORY; |
| |
| static { |
| if (Java.IS_JAVA9_COMPATIBLE) |
| CHECKSUM_FACTORY = new Java9ChecksumFactory(); |
| else |
| CHECKSUM_FACTORY = new PureJavaChecksumFactory(); |
| } |
| |
| private Crc32C() {} |
| |
| /** |
| * Compute the CRC32C (Castagnoli) of the segment of the byte array given by the specified size and offset |
| * |
| * @param bytes The bytes to checksum |
| * @param offset the offset at which to begin the checksum computation |
| * @param size the number of bytes to checksum |
| * @return The CRC32C |
| */ |
| public static long compute(byte[] bytes, int offset, int size) { |
| Checksum crc = create(); |
| crc.update(bytes, offset, size); |
| return crc.getValue(); |
| } |
| |
| /** |
| * Compute the CRC32C (Castagnoli) of a byte buffer from a given offset (relative to the buffer's current position) |
| * |
| * @param buffer The buffer with the underlying data |
| * @param offset The offset relative to the current position |
| * @param size The number of bytes beginning from the offset to include |
| * @return The CRC32C |
| */ |
| public static long compute(ByteBuffer buffer, int offset, int size) { |
| Checksum crc = create(); |
| Checksums.update(crc, buffer, offset, size); |
| return crc.getValue(); |
| } |
| |
| public static Checksum create() { |
| return CHECKSUM_FACTORY.create(); |
| } |
| |
| private interface ChecksumFactory { |
| Checksum create(); |
| } |
| |
| private static class Java9ChecksumFactory implements ChecksumFactory { |
| private static final MethodHandle CONSTRUCTOR; |
| |
| static { |
| try { |
| Class<?> cls = Class.forName("java.util.zip.CRC32C"); |
| CONSTRUCTOR = MethodHandles.publicLookup().findConstructor(cls, MethodType.methodType(void.class)); |
| } catch (ReflectiveOperationException e) { |
| // Should never happen |
| throw new RuntimeException(e); |
| } |
| } |
| |
| @Override |
| public Checksum create() { |
| try { |
| return (Checksum) CONSTRUCTOR.invoke(); |
| } catch (Throwable throwable) { |
| // Should never happen |
| throw new RuntimeException(throwable); |
| } |
| } |
| } |
| |
| private static class PureJavaChecksumFactory implements ChecksumFactory { |
| @Override |
| public Checksum create() { |
| return new PureJavaCrc32C(); |
| } |
| } |
| } |