Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ When building on Solaris, use `gmake`:
A file `target/snappy-java-$(version).jar` is the product additionally containing the native library built for your platform.

## Miscellaneous Notes

### Using pure-java Snappy implementation

snappy-java can optionally use a pure-java implementation of Snappy based on [aircompressor](https://github.com/airlift/aircompressor/tree/master/src/main/java/io/airlift/compress/snappy). This implementation is selected when no native Snappy library for your platform is found. You can also force using this pure-java implementation by setting a JVM property `org.xerial.snappy.purejava=true` before loading any class of Snappy (e.g., using `-Dorg.xerial.snappy.purejava=true` option when launching JVM).


### Using snappy-java with Tomcat 6 (or higher) Web Server

Simply put the snappy-java's jar to WEB-INF/lib folder of your web application. Usual JNI-library specific problem no longer exists since snappy-java version 1.0.3 or higher can be loaded by multiple class loaders.
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ enablePlugins(SbtOsgi)

osgiSettings

OsgiKeys.exportPackage := Seq("org.xerial.snappy", "org.xerial.snappy.buffer", "org.xerial.snappy.pool")
OsgiKeys.exportPackage := Seq("org.xerial.snappy", "org.xerial.snappy.buffer", "org.xerial.snappy.pool", "org.xerial.snappy.pure")
OsgiKeys.bundleSymbolicName := "org.xerial.snappy.snappy-java"
OsgiKeys.bundleActivator := Option("org.xerial.snappy.SnappyBundleActivator")
OsgiKeys.importPackage := Seq("""org.osgi.framework;version="[1.5,2)"""")
Expand Down
22 changes: 14 additions & 8 deletions src/main/java/org/xerial/snappy/Snappy.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
// Snappy.java
// Since: 2011/03/29
//
// $URL$
// $URL$
// $Author$
//--------------------------------------
package org.xerial.snappy;

import org.xerial.snappy.pure.PureJavaSnappy;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
Expand All @@ -43,18 +45,13 @@
public class Snappy
{
static {
try {
impl = SnappyLoader.loadSnappyApi();
}
catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
init();
}

/**
* An instance of SnappyNative
*/
private static SnappyNative impl;
private static SnappyApi impl;

/**
* Clean up a temporary file (native lib) generated by snappy-java.
Expand All @@ -69,6 +66,15 @@ public static void cleanUp()
SnappyLoader.setSnappyApi(null);
}

static void init() {
try {
impl = SnappyLoader.loadSnappyApi();
}
catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}

/**
* Copy bytes from source to destination
*
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/org/xerial/snappy/SnappyApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.xerial.snappy;

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

/**
* Snappy compressor/decompressor interface. The implementation can be JNI binding or pure-java Snappy implementation.
*/
public interface SnappyApi
{
// ------------------------------------------------------------------------
// Generic compression/decompression routines.
// ------------------------------------------------------------------------
long rawCompress(long inputAddr, long inputSize, long destAddr)
throws IOException;

long rawUncompress(long inputAddr, long inputSize, long destAddr)
throws IOException;

int rawCompress(ByteBuffer input, int inputOffset, int inputLength, ByteBuffer compressed,
int outputOffset)
throws IOException;

int rawCompress(Object input, int inputOffset, int inputByteLength, Object output, int outputOffset)
throws IOException;

int rawUncompress(ByteBuffer compressed, int inputOffset, int inputLength, ByteBuffer uncompressed,
int outputOffset)
throws IOException;

int rawUncompress(Object input, int inputOffset, int inputLength, Object output, int outputOffset)
throws IOException;

// Returns the maximal size of the compressed representation of
// input data that is "source_bytes" bytes in length;
int maxCompressedLength(int source_bytes);

// This operation takes O(1) time.
int uncompressedLength(ByteBuffer compressed, int offset, int len)
throws IOException;

int uncompressedLength(Object input, int offset, int len)
throws IOException;

long uncompressedLength(long inputAddr, long len)
throws IOException;

boolean isValidCompressedBuffer(ByteBuffer compressed, int offset, int len)
throws IOException;

boolean isValidCompressedBuffer(Object input, int offset, int len)
throws IOException;

boolean isValidCompressedBuffer(long inputAddr, long offset, long len)
throws IOException;

void arrayCopy(Object src, int offset, int byteLength, Object dest, int dOffset)
throws IOException;

}
3 changes: 2 additions & 1 deletion src/main/java/org/xerial/snappy/SnappyErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public enum SnappyErrorCode
FAILED_TO_UNCOMPRESS(5),
EMPTY_INPUT(6),
INCOMPATIBLE_VERSION(7),
INVALID_CHUNK_SIZE(8);
INVALID_CHUNK_SIZE(8),
UNSUPPORTED_PLATFORM(9);

public final int id;

Expand Down
37 changes: 28 additions & 9 deletions src/main/java/org/xerial/snappy/SnappyLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
// SnappyLoader.java
// Since: 2011/03/29
//
// $URL$
// $URL$
// $Author$
//--------------------------------------
package org.xerial.snappy;

import org.xerial.snappy.pure.PureJavaSnappy;

import java.io.*;
import java.net.URL;
import java.util.Enumeration;
Expand Down Expand Up @@ -75,13 +77,14 @@ public class SnappyLoader
public static final String SNAPPY_SYSTEM_PROPERTIES_FILE = "org-xerial-snappy.properties";
public static final String KEY_SNAPPY_LIB_PATH = "org.xerial.snappy.lib.path";
public static final String KEY_SNAPPY_LIB_NAME = "org.xerial.snappy.lib.name";
public static final String KEY_SNAPPY_PUREJAVA = "org.xerial.snappy.purejava";
public static final String KEY_SNAPPY_TEMPDIR = "org.xerial.snappy.tempdir";
public static final String KEY_SNAPPY_USE_SYSTEMLIB = "org.xerial.snappy.use.systemlib";
public static final String KEY_SNAPPY_DISABLE_BUNDLED_LIBS = "org.xerial.snappy.disable.bundled.libs"; // Depreciated, but preserved for backward compatibility

private static boolean isLoaded = false;

private static volatile SnappyNative snappyApi = null;
private static volatile SnappyApi snappyApi = null;
private static volatile BitShuffleNative bitshuffleApi = null;

private static File nativeLibFile = null;
Expand All @@ -101,11 +104,11 @@ static void cleanUpExtractedNativeLib()
/**
* Set the `snappyApi` instance.
*
* @param nativeCode
* @param apiImpl
*/
static synchronized void setSnappyApi(SnappyNative nativeCode)
static synchronized void setSnappyApi(SnappyApi apiImpl)
{
snappyApi = nativeCode;
snappyApi = apiImpl;
}

/**
Expand Down Expand Up @@ -146,13 +149,29 @@ private static void loadSnappySystemProperties()
loadSnappySystemProperties();
}

static synchronized SnappyNative loadSnappyApi()
static synchronized boolean isPureJava() {
return snappyApi != null && PureJavaSnappy.class.isAssignableFrom(snappyApi.getClass());
}

static synchronized SnappyApi loadSnappyApi()
{
if (snappyApi != null) {
return snappyApi;
}
loadNativeLibrary();
setSnappyApi(new SnappyNative());
try {
if(Boolean.parseBoolean(System.getProperty(KEY_SNAPPY_PUREJAVA, "false"))) {
// Use pure-java Snappy implementation
setSnappyApi(new PureJavaSnappy());
}
else {
loadNativeLibrary();
setSnappyApi(new SnappyNative());
}
}
catch(Exception e) {
// Fall-back to pure-java Snappy implementation
setSnappyApi(new PureJavaSnappy());
}
return snappyApi;
}

Expand Down Expand Up @@ -311,7 +330,7 @@ static File findNativeLibrary()
String snappyNativeLibraryPath = System.getProperty(KEY_SNAPPY_LIB_PATH);
String snappyNativeLibraryName = System.getProperty(KEY_SNAPPY_LIB_NAME);

// Resolve the library file name with a suffix (e.g., dll, .so, etc.)
// Resolve the library file name with a suffix (e.g., dll, .so, etc.)
if (snappyNativeLibraryName == null) {
snappyNativeLibraryName = System.mapLibraryName("snappyjava");
}
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/org/xerial/snappy/SnappyNative.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// SnappyNative.java
// Since: 2011/03/30
//
// $URL$
// $URL$
// $Author$
//--------------------------------------
package org.xerial.snappy;
Expand All @@ -38,57 +38,71 @@
*
* @author leo
*/
public class SnappyNative
public class SnappyNative implements SnappyApi
{

public native String nativeLibraryVersion();

// ------------------------------------------------------------------------
// Generic compression/decompression routines.
// ------------------------------------------------------------------------
@Override
public native long rawCompress(long inputAddr, long inputSize, long destAddr)
throws IOException;

@Override
public native long rawUncompress(long inputAddr, long inputSize, long destAddr)
throws IOException;

@Override
public native int rawCompress(ByteBuffer input, int inputOffset, int inputLength, ByteBuffer compressed,
int outputOffset)
throws IOException;

@Override
public native int rawCompress(Object input, int inputOffset, int inputByteLength, Object output, int outputOffset)
throws IOException;

@Override
public native int rawUncompress(ByteBuffer compressed, int inputOffset, int inputLength, ByteBuffer uncompressed,
int outputOffset)
throws IOException;

@Override
public native int rawUncompress(Object input, int inputOffset, int inputLength, Object output, int outputOffset)
throws IOException;

// Returns the maximal size of the compressed representation of
// input data that is "source_bytes" bytes in length;
@Override
public native int maxCompressedLength(int source_bytes);

// This operation takes O(1) time.
@Override
public native int uncompressedLength(ByteBuffer compressed, int offset, int len)
throws IOException;

@Override
public native int uncompressedLength(Object input, int offset, int len)
throws IOException;

@Override
public native long uncompressedLength(long inputAddr, long len)
throws IOException;

@Override
public native boolean isValidCompressedBuffer(ByteBuffer compressed, int offset, int len)
throws IOException;

@Override
public native boolean isValidCompressedBuffer(Object input, int offset, int len)
throws IOException;

@Override
public native boolean isValidCompressedBuffer(long inputAddr, long offset, long len)
throws IOException;

@Override
public native void arrayCopy(Object src, int offset, int byteLength, Object dest, int dOffset)
throws IOException;

Expand Down
Loading