Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: xerial/snappy-java
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.1.8.2
Choose a base ref
...
head repository: xerial/snappy-java
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1.1.8.3
Choose a head ref
  • 6 commits
  • 8 files changed
  • 3 contributors

Commits on Nov 28, 2020

  1. Copy the full SHA
    2191e85 View commit details
  2. 1.1.8.2 release notes

    xerial committed Nov 28, 2020
    Copy the full SHA
    7f47cf7 View commit details

Commits on Jan 20, 2021

  1. Pool table instances to make PureJavaSnappy thread safe (#271)

    #270
    
    Co-authored-by: BO8979 <BO8979@W1971362.northamerica.cerner.net>
    bokken and BO8979 authored Jan 20, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    110727e View commit details
  2. Prefer use of java.util.zip.CRC32C for Framed format (#269)

    Co-authored-by: BO8979 <BO8979@W1971362.northamerica.cerner.net>
    bokken and BO8979 authored Jan 20, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    822513d View commit details
  3. ADd 1.1.8.3 release notes

    xerial committed Jan 20, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    44db30a View commit details
  4. Setting version to 1.1.8.3

    xerial committed Jan 20, 2021
    Copy the full SHA
    f938b2c View commit details
8 changes: 8 additions & 0 deletions Milestone.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Since version 1.1.0.x, Java 6 (1.6) or higher is required.

## snappy-java-1.1.8.3 (2021-01-20)
* Make pure-java Snappy thread-safe [#271](https://github.com/xerial/snappy-java/pull/271)
* Improved SnappyFramedInput/OutputStream performance by using java.util.zip.CRC32C [#269](https://github.com/xerial/snappy-java/pull/269)

## snappy-java-1.1.8.2 (2020-11-28)
* Support Apple Silicon (M1, Mac-aarch64)
* Fixed the pure-java Snappy fallback logic when no native library for your platform is found.

## snappy-java-1.1.8.1 (2020-11-09)
* Fixed an initialization issue when using a recent Mac OS X version [#265](https://github.com/xerial/snappy-java/pull/265)

3 changes: 1 addition & 2 deletions src/main/java/org/xerial/snappy/PureJavaCrc32C.java
Original file line number Diff line number Diff line change
@@ -48,8 +48,7 @@ public int getIntegerValue()
/** {@inheritDoc} */
public long getValue()
{
long ret = crc;
return (~ret) & 0xffffffffL;
return (~crc) & 0xffffffffL;
}

/** {@inheritDoc} */
290 changes: 165 additions & 125 deletions src/main/java/org/xerial/snappy/SnappyFramed.java
Original file line number Diff line number Diff line change
@@ -1,125 +1,165 @@
/*
* Created: Apr 12, 2013
*/
package org.xerial.snappy;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;

/**
* Constants and utilities for implementing x-snappy-framed.
*
* @author Brett Okken
* @since 1.1.0
*/
final class SnappyFramed
{
public static final int COMPRESSED_DATA_FLAG = 0x00;

public static final int UNCOMPRESSED_DATA_FLAG = 0x01;

public static final int STREAM_IDENTIFIER_FLAG = 0xff;

private static final int MASK_DELTA = 0xa282ead8;

/**
* The header consists of the stream identifier flag, 3 bytes indicating a
* length of 6, and "sNaPpY" in ASCII.
*/
public static final byte[] HEADER_BYTES = new byte[] {
(byte) STREAM_IDENTIFIER_FLAG, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61,
0x50, 0x70, 0x59};

public static int maskedCrc32c(byte[] data)
{
return maskedCrc32c(data, 0, data.length);
}

public static int maskedCrc32c(byte[] data, int offset, int length)
{
final PureJavaCrc32C crc32c = new PureJavaCrc32C();
crc32c.update(data, offset, length);
return mask(crc32c.getIntegerValue());
}

/**
* Checksums are not stored directly, but masked, as checksumming data and
* then its own checksum can be problematic. The masking is the same as used
* in Apache Hadoop: Rotate the checksum by 15 bits, then add the constant
* 0xa282ead8 (using wraparound as normal for unsigned integers). This is
* equivalent to the following C code:
* <p/>
* <pre>
* uint32_t mask_checksum(uint32_t x) {
* return ((x >> 15) | (x << 17)) + 0xa282ead8;
* }
* </pre>
*/
public static int mask(int crc)
{
// Rotate right by 15 bits and add a constant.
return ((crc >>> 15) | (crc << 17)) + MASK_DELTA;
}

static final int readBytes(ReadableByteChannel source, ByteBuffer dest)
throws IOException
{
// tells how many bytes to read.
final int expectedLength = dest.remaining();

int totalRead = 0;

// how many bytes were read.
int lastRead = source.read(dest);

totalRead = lastRead;

// if we did not read as many bytes as we had hoped, try reading again.
if (lastRead < expectedLength) {
// as long the buffer is not full (remaining() == 0) and we have not reached EOF (lastRead == -1) keep reading.
while (dest.remaining() != 0 && lastRead != -1) {
lastRead = source.read(dest);

// if we got EOF, do not add to total read.
if (lastRead != -1) {
totalRead += lastRead;
}
}
}

if (totalRead > 0) {
dest.limit(dest.position());
}
else {
dest.position(dest.limit());
}

return totalRead;
}

static int skip(final ReadableByteChannel source, final int skip, final ByteBuffer buffer)
throws IOException
{
if (skip <= 0) {
return 0;
}

int toSkip = skip;
int skipped = 0;
while (toSkip > 0 && skipped != -1) {
buffer.clear();
if (toSkip < buffer.capacity()) {
buffer.limit(toSkip);
}

skipped = source.read(buffer);
if (skipped > 0) {
toSkip -= skipped;
}
}

buffer.clear();
return skip - toSkip;
}
}
/*
* Created: Apr 12, 2013
*/
package org.xerial.snappy;

import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Checksum;

/**
* Constants and utilities for implementing x-snappy-framed.
*
* @author Brett Okken
* @since 1.1.0
*/
final class SnappyFramed
{
public static final int COMPRESSED_DATA_FLAG = 0x00;

public static final int UNCOMPRESSED_DATA_FLAG = 0x01;

public static final int STREAM_IDENTIFIER_FLAG = 0xff;

private static final int MASK_DELTA = 0xa282ead8;

private static final Supplier<Checksum> CHECKSUM_SUPPLIER;

static
{
Supplier<Checksum> supplier = null;
try
{
final Class crc32cClazz = Class.forName("java.util.zip.CRC32C");
final MethodHandles.Lookup lookup = MethodHandles.publicLookup();

final MethodHandle conHandle = lookup.findConstructor(crc32cClazz, MethodType.methodType(void.class))
.asType(MethodType.methodType(Checksum.class));
supplier = () -> {
try
{
return (Checksum) conHandle.invokeExact();
}
catch (Throwable e)
{
throw new IllegalStateException(e);
}
};
}
catch(Throwable t)
{
Logger.getLogger(SnappyFramed.class.getName())
.log(Level.FINE, "java.util.zip.CRC32C not loaded, using PureJavaCrc32C", t);
supplier = null;
}

CHECKSUM_SUPPLIER = supplier != null ? supplier : PureJavaCrc32C::new;
}

/**
* The header consists of the stream identifier flag, 3 bytes indicating a
* length of 6, and "sNaPpY" in ASCII.
*/
public static final byte[] HEADER_BYTES = new byte[] {
(byte) STREAM_IDENTIFIER_FLAG, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61,
0x50, 0x70, 0x59};

public static Checksum getCRC32C()
{
return CHECKSUM_SUPPLIER.get();
}

public static int maskedCrc32c(Checksum crc32c, byte[] data, int offset, int length)
{
crc32c.reset();
crc32c.update(data, offset, length);
return mask((int) crc32c.getValue());
}

/**
* Checksums are not stored directly, but masked, as checksumming data and
* then its own checksum can be problematic. The masking is the same as used
* in Apache Hadoop: Rotate the checksum by 15 bits, then add the constant
* 0xa282ead8 (using wraparound as normal for unsigned integers). This is
* equivalent to the following C code:
* <p/>
* <pre>
* uint32_t mask_checksum(uint32_t x) {
* return ((x >> 15) | (x << 17)) + 0xa282ead8;
* }
* </pre>
*/
public static int mask(int crc)
{
// Rotate right by 15 bits and add a constant.
return ((crc >>> 15) | (crc << 17)) + MASK_DELTA;
}

static final int readBytes(ReadableByteChannel source, ByteBuffer dest)
throws IOException
{
// tells how many bytes to read.
final int expectedLength = dest.remaining();

int totalRead = 0;

// how many bytes were read.
int lastRead = source.read(dest);

totalRead = lastRead;

// if we did not read as many bytes as we had hoped, try reading again.
if (lastRead < expectedLength) {
// as long the buffer is not full (remaining() == 0) and we have not reached EOF (lastRead == -1) keep reading.
while (dest.remaining() != 0 && lastRead != -1) {
lastRead = source.read(dest);

// if we got EOF, do not add to total read.
if (lastRead != -1) {
totalRead += lastRead;
}
}
}

if (totalRead > 0) {
dest.limit(dest.position());
}
else {
dest.position(dest.limit());
}

return totalRead;
}

static int skip(final ReadableByteChannel source, final int skip, final ByteBuffer buffer)
throws IOException
{
if (skip <= 0) {
return 0;
}

int toSkip = skip;
int skipped = 0;
while (toSkip > 0 && skipped != -1) {
buffer.clear();
if (toSkip < buffer.capacity()) {
buffer.limit(toSkip);
}

skipped = source.read(buffer);
if (skipped > 0) {
toSkip -= skipped;
}
}

buffer.clear();
return skip - toSkip;
}
}
Loading