Author: dcreager
Date: Fri Jul 26 13:40:47 2013
New Revision: 1507309

URL: http://svn.apache.org/r1507309
Log:
AVRO-896. C: Snappy compression codec.

Like all other codecs, this is optional.  It will only be activated if the
snappy C library is installed at build time.  Contributed by Grisha Trubetskoy.

Added:
    avro/trunk/lang/c/FindSnappy.cmake
Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/c/CMakeLists.txt
    avro/trunk/lang/c/src/codec.c
    avro/trunk/lang/c/src/codec.h

Modified: avro/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1507309&r1=1507308&r2=1507309&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Fri Jul 26 13:40:47 2013
@@ -14,6 +14,8 @@ Trunk (not yet released)
 
     AVRO-823: C#: Add data file support. (David McIntosh via cutting)
 
+    AVRO-896. C: Snappy compression codec. (Grisha Trubetskoy via dcreager)
+
   IMPROVEMENTS
 
     AVRO-1260. Ruby: Improve read performance. (Martin Kleppmann via cutting)

Modified: avro/trunk/lang/c/CMakeLists.txt
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/CMakeLists.txt?rev=1507309&r1=1507308&r2=1507309&view=diff
==============================================================================
--- avro/trunk/lang/c/CMakeLists.txt (original)
+++ avro/trunk/lang/c/CMakeLists.txt Fri Jul 26 13:40:47 2013
@@ -20,6 +20,8 @@ cmake_minimum_required(VERSION 2.4)
 project(AvroC)
 enable_testing()
 
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR})
+
 # Eliminates warning about linker paths when linking both zlib and
 # liblzma.
 cmake_policy(SET CMP0003 NEW)
@@ -125,6 +127,7 @@ include_directories(${AvroC_SOURCE_DIR}/
 
 
 # Enable codecs
+
 find_package(ZLIB)
 if (ZLIB_FOUND)
     set(ZLIB_PKG zlib)
@@ -136,6 +139,16 @@ else (ZLIB_FOUND)
     message("Disabled deflate codec. zlib not found.")
 endif (ZLIB_FOUND)
 
+find_package(Snappy)
+if (SNAPPY_FOUND AND ZLIB_FOUND)  # Snappy borrows crc32 from zlib
+   set(SNAPPY_PKG libsnappy)
+   add_definitions(-DSNAPPY_CODEC)
+   message("Enabled snappy codec")
+else (SNAPPY_FOUND AND ZLIB_FOUND)
+   set (SNAPPY_PKG "")
+   message("Disabled snappy codec. libsnappy not found or zlib not found.")
+endif (SNAPPY_FOUND AND ZLIB_FOUND)
+
 find_package(PkgConfig)
 pkg_check_modules(LZMA liblzma)
 if (LZMA_FOUND)
@@ -149,8 +162,8 @@ else (LZMA_FOUND)
     message("Disabled lzma codec. liblzma not found.")
 endif (LZMA_FOUND)
 
-set(CODEC_LIBRARIES ${ZLIB_LIBRARIES} ${LZMA_LIBRARIES})
-set(CODEC_PKG "@ZLIB_PKG@ @LZMA_PKG@")
+set(CODEC_LIBRARIES ${ZLIB_LIBRARIES} ${LZMA_LIBRARIES} ${SNAPPY_LIBRARIES})
+set(CODEC_PKG "@ZLIB_PKG@ @LZMA_PKG@ @SNAPPY_PKG@")
 
 
 add_subdirectory(src)

Added: avro/trunk/lang/c/FindSnappy.cmake
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/FindSnappy.cmake?rev=1507309&view=auto
==============================================================================
--- avro/trunk/lang/c/FindSnappy.cmake (added)
+++ avro/trunk/lang/c/FindSnappy.cmake Fri Jul 26 13:40:47 2013
@@ -0,0 +1,36 @@
+# Tries to find Snappy headers and libraries.
+#
+# Usage of this module as follows:
+#
+#  find_package(Snappy)
+#
+# Variables used by this module, they can change the default behaviour and need
+# to be set before calling find_package:
+#
+#  SNAPPY_ROOT_DIR  Set this variable to the root installation of
+#                    Snappy if the module has problems finding
+#                    the proper installation path.
+#
+# Variables defined by this module:
+#
+#  SNAPPY_FOUND              System has Snappy libs/headers
+#  SNAPPY_LIBRARIES          The Snappy libraries
+#  SNAPPY_INCLUDE_DIR        The location of Snappy headers
+
+find_path(SNAPPY_INCLUDE_DIR
+    NAMES snappy.h
+    HINTS ${SNAPPY_ROOT_DIR}/include)
+
+find_library(SNAPPY_LIBRARIES
+    NAMES snappy
+    HINTS ${SNAPPY_ROOT_DIR}/lib)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Snappy DEFAULT_MSG
+    SNAPPY_LIBRARIES
+    SNAPPY_INCLUDE_DIR)
+
+mark_as_advanced(
+    SNAPPY_ROOT_DIR
+    SNAPPY_LIBRARIES
+    SNAPPY_INCLUDE_DIR)

Modified: avro/trunk/lang/c/src/codec.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/codec.c?rev=1507309&r1=1507308&r2=1507309&view=diff
==============================================================================
--- avro/trunk/lang/c/src/codec.c (original)
+++ avro/trunk/lang/c/src/codec.c Fri Jul 26 13:40:47 2013
@@ -16,6 +16,10 @@
  */
 
 #include <string.h>
+#ifdef SNAPPY_CODEC
+#include <snappy-c.h>
+#include <byteswap.h>
+#endif
 #ifdef DEFLATE_CODEC
 #include <zlib.h>
 #endif
@@ -71,6 +75,112 @@ static int reset_null(avro_codec_t c)
        return 0;
 }
 
+/* Snappy codec */
+
+#ifdef SNAPPY_CODEC
+
+static int
+codec_snappy(avro_codec_t codec)
+{
+       codec->name = "snappy";
+       codec->type = AVRO_CODEC_SNAPPY;
+       codec->block_size = 0;
+       codec->used_size = 0;
+       codec->block_data = NULL;
+       codec->codec_data = NULL;
+
+       return 0;
+}
+
+static int encode_snappy(avro_codec_t c, void * data, int64_t len)
+{
+        uint32_t crc;
+        size_t outlen = snappy_max_compressed_length(len);
+
+       if (!c->block_data) {
+               c->block_data = avro_malloc(outlen+4);
+               c->block_size = outlen+4;
+       } else if (c->block_size < (int64_t) (outlen+4)) {
+            c->block_data = avro_realloc(c->block_data, c->block_size, 
(outlen+4));
+               c->block_size = outlen+4;
+       }
+
+       if (!c->block_data) {
+               avro_set_error("Cannot allocate memory for snappy");
+               return 1;
+       }
+
+        if (snappy_compress(data, len, c->block_data, &outlen) != SNAPPY_OK)
+        {
+                avro_set_error("Error compressing block with Snappy");
+               return 1;
+       }
+
+        crc = __bswap_32(crc32(0, data, len));
+        memcpy(c->block_data+outlen, &crc, 4);
+        c->used_size = outlen+4;
+
+       return 0;
+}
+
+static int decode_snappy(avro_codec_t c, void * data, int64_t len)
+{
+        uint32_t crc;
+        size_t outlen;
+
+        if (snappy_uncompressed_length(data, len-4, &outlen) != SNAPPY_OK) {
+               avro_set_error("Uncompressed length error in snappy");
+               return 1;
+        }
+
+       if (!c->block_data) {
+               c->block_data = avro_malloc(outlen);
+               c->block_size = outlen;
+       } else if ( (size_t)c->block_size < outlen) {
+               c->block_data = avro_realloc(c->block_data, c->block_size, 
outlen);
+               c->block_size = outlen;
+       }
+
+       if (!c->block_data)
+       {
+               avro_set_error("Cannot allocate memory for snappy");
+               return 1;
+       }
+
+        if (snappy_uncompress(data, len-4, c->block_data, &outlen) != 
SNAPPY_OK)
+        {
+                avro_set_error("Error uncompressing block with Snappy");
+               return 1;
+       }
+
+        crc = __bswap_32(crc32(0, c->block_data, outlen));
+        if (memcmp(&crc, (char*)data+len-4, 4))
+        {
+                avro_set_error("CRC32 check failure uncompressing block with 
Snappy");
+               return 1;
+       }
+
+        c->used_size = outlen;
+
+       return 0;
+}
+
+static int reset_snappy(avro_codec_t c)
+{
+       if (c->block_data) {
+               avro_free(c->block_data, c->block_size);
+       }
+
+       c->block_data = NULL;
+       c->block_size = 0;
+       c->used_size = 0;
+       c->codec_data = NULL;
+
+       return 0;
+}
+
+#endif // SNAPPY_CODEC
+
 /* Deflate codec */
 
 #ifdef DEFLATE_CODEC
@@ -403,6 +513,12 @@ int avro_codec(avro_codec_t codec, const
                return codec_null(codec);
        }
 
+#ifdef SNAPPY_CODEC
+       if (strcmp("snappy", type) == 0) {
+               return codec_snappy(codec);
+       }
+#endif
+
 #ifdef DEFLATE_CODEC
        if (strcmp("deflate", type) == 0) {
                return codec_deflate(codec);
@@ -429,6 +545,10 @@ int avro_codec_encode(avro_codec_t c, vo
        {
        case AVRO_CODEC_NULL:
                return encode_null(c, data, len);
+#ifdef SNAPPY_CODEC
+       case AVRO_CODEC_SNAPPY:
+               return encode_snappy(c, data, len);
+#endif
 #ifdef DEFLATE_CODEC
        case AVRO_CODEC_DEFLATE:
                return encode_deflate(c, data, len);
@@ -448,6 +568,10 @@ int avro_codec_decode(avro_codec_t c, vo
        {
        case AVRO_CODEC_NULL:
                return decode_null(c, data, len);
+#ifdef SNAPPY_CODEC
+       case AVRO_CODEC_SNAPPY:
+               return decode_snappy(c, data, len);
+#endif
 #ifdef DEFLATE_CODEC
        case AVRO_CODEC_DEFLATE:
                return decode_deflate(c, data, len);
@@ -467,6 +591,10 @@ int avro_codec_reset(avro_codec_t c)
        {
        case AVRO_CODEC_NULL:
                return reset_null(c);
+#ifdef SNAPPY_CODEC
+       case AVRO_CODEC_SNAPPY:
+               return reset_snappy(c);
+#endif
 #ifdef DEFLATE_CODEC
        case AVRO_CODEC_DEFLATE:
                return reset_deflate(c);

Modified: avro/trunk/lang/c/src/codec.h
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/codec.h?rev=1507309&r1=1507308&r2=1507309&view=diff
==============================================================================
--- avro/trunk/lang/c/src/codec.h (original)
+++ avro/trunk/lang/c/src/codec.h Fri Jul 26 13:40:47 2013
@@ -29,7 +29,8 @@ extern "C" {
 enum avro_codec_type_t {
        AVRO_CODEC_NULL,
        AVRO_CODEC_DEFLATE,
-       AVRO_CODEC_LZMA
+       AVRO_CODEC_LZMA,
+       AVRO_CODEC_SNAPPY
 };
 typedef enum avro_codec_type_t avro_codec_type_t;
 


Reply via email to