ZlibCompressor.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:10k
源码类别:

网格计算

开发平台:

Java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.io.compress.zlib;
  19. import java.io.IOException;
  20. import java.nio.Buffer;
  21. import java.nio.ByteBuffer;
  22. import org.apache.hadoop.io.compress.Compressor;
  23. import org.apache.hadoop.util.NativeCodeLoader;
  24. /**
  25.  * A {@link Compressor} based on the popular 
  26.  * zlib compression algorithm.
  27.  * http://www.zlib.net/
  28.  * 
  29.  */
  30. public class ZlibCompressor implements Compressor {
  31.   private static final int DEFAULT_DIRECT_BUFFER_SIZE = 64*1024;
  32.   // HACK - Use this as a global lock in the JNI layer
  33.   private static Class clazz = ZlibCompressor.class;
  34.   private long stream;
  35.   private CompressionLevel level;
  36.   private CompressionStrategy strategy;
  37.   private CompressionHeader windowBits;
  38.   private int directBufferSize;
  39.   private byte[] userBuf = null;
  40.   private int userBufOff = 0, userBufLen = 0;
  41.   private Buffer uncompressedDirectBuf = null;
  42.   private int uncompressedDirectBufOff = 0, uncompressedDirectBufLen = 0;
  43.   private Buffer compressedDirectBuf = null;
  44.   private boolean finish, finished;
  45.   /**
  46.    * The compression level for zlib library.
  47.    */
  48.   public static enum CompressionLevel {
  49.     /**
  50.      * Compression level for no compression.
  51.      */
  52.     NO_COMPRESSION (0),
  53.     
  54.     /**
  55.      * Compression level for fastest compression.
  56.      */
  57.     BEST_SPEED (1),
  58.     
  59.     /**
  60.      * Compression level for best compression.
  61.      */
  62.     BEST_COMPRESSION (9),
  63.     
  64.     /**
  65.      * Default compression level.
  66.      */
  67.     DEFAULT_COMPRESSION (-1);
  68.     
  69.     
  70.     private final int compressionLevel;
  71.     
  72.     CompressionLevel(int level) {
  73.       compressionLevel = level;
  74.     }
  75.     
  76.     int compressionLevel() {
  77.       return compressionLevel;
  78.     }
  79.   };
  80.   
  81.   /**
  82.    * The compression level for zlib library.
  83.    */
  84.   public static enum CompressionStrategy {
  85.     /**
  86.      * Compression strategy best used for data consisting mostly of small
  87.      * values with a somewhat random distribution. Forces more Huffman coding
  88.      * and less string matching.
  89.      */
  90.     FILTERED (1),
  91.     
  92.     /**
  93.      * Compression strategy for Huffman coding only.
  94.      */
  95.     HUFFMAN_ONLY (2),
  96.     
  97.     /**
  98.      * Compression strategy to limit match distances to one
  99.      * (run-length encoding).
  100.      */
  101.     RLE (3),
  102.     /**
  103.      * Compression strategy to prevent the use of dynamic Huffman codes, 
  104.      * allowing for a simpler decoder for special applications.
  105.      */
  106.     FIXED (4),
  107.     /**
  108.      * Default compression strategy.
  109.      */
  110.     DEFAULT_STRATEGY (0);
  111.     
  112.     
  113.     private final int compressionStrategy;
  114.     
  115.     CompressionStrategy(int strategy) {
  116.       compressionStrategy = strategy;
  117.     }
  118.     
  119.     int compressionStrategy() {
  120.       return compressionStrategy;
  121.     }
  122.   };
  123.   /**
  124.    * The type of header for compressed data.
  125.    */
  126.   public static enum CompressionHeader {
  127.     /**
  128.      * No headers/trailers/checksums.
  129.      */
  130.     NO_HEADER (-15),
  131.     
  132.     /**
  133.      * Default headers/trailers/checksums.
  134.      */
  135.     DEFAULT_HEADER (15),
  136.     
  137.     /**
  138.      * Simple gzip headers/trailers.
  139.      */
  140.     GZIP_FORMAT (31);
  141.     private final int windowBits;
  142.     
  143.     CompressionHeader(int windowBits) {
  144.       this.windowBits = windowBits;
  145.     }
  146.     
  147.     public int windowBits() {
  148.       return windowBits;
  149.     }
  150.   }
  151.   
  152.   private static boolean nativeZlibLoaded = false;
  153.   
  154.   static {
  155.     if (NativeCodeLoader.isNativeCodeLoaded()) {
  156.       try {
  157.         // Initialize the native library
  158.         initIDs();
  159.         nativeZlibLoaded = true;
  160.       } catch (Throwable t) {
  161.         // Ignore failure to load/initialize native-zlib
  162.       }
  163.     }
  164.   }
  165.   
  166.   static boolean isNativeZlibLoaded() {
  167.     return nativeZlibLoaded;
  168.   }
  169.   /** 
  170.    * Creates a new compressor using the specified compression level.
  171.    * Compressed data will be generated in ZLIB format.
  172.    * 
  173.    * @param level Compression level #CompressionLevel
  174.    * @param strategy Compression strategy #CompressionStrategy
  175.    * @param header Compression header #CompressionHeader
  176.    * @param directBufferSize Size of the direct buffer to be used.
  177.    */
  178.   public ZlibCompressor(CompressionLevel level, CompressionStrategy strategy, 
  179.                         CompressionHeader header, int directBufferSize) {
  180.     this.level = level;
  181.     this.strategy = strategy;
  182.     this.windowBits = header;
  183.     this.directBufferSize = directBufferSize;
  184.     
  185.     uncompressedDirectBuf = ByteBuffer.allocateDirect(directBufferSize);
  186.     compressedDirectBuf = ByteBuffer.allocateDirect(directBufferSize);
  187.     compressedDirectBuf.position(directBufferSize);
  188.     
  189.     stream = init(this.level.compressionLevel(), 
  190.                   this.strategy.compressionStrategy(), 
  191.                   this.windowBits.windowBits());
  192.   }
  193.   
  194.   /**
  195.    * Creates a new compressor with the default compression level.
  196.    * Compressed data will be generated in ZLIB format.
  197.    */
  198.   public ZlibCompressor() {
  199.     this(CompressionLevel.DEFAULT_COMPRESSION, 
  200.          CompressionStrategy.DEFAULT_STRATEGY, 
  201.          CompressionHeader.DEFAULT_HEADER, 
  202.          DEFAULT_DIRECT_BUFFER_SIZE);
  203.   }
  204.   
  205.   public synchronized void setInput(byte[] b, int off, int len) {
  206.     if (b== null) {
  207.       throw new NullPointerException();
  208.     }
  209.     if (off < 0 || len < 0 || off > b.length - len) {
  210.       throw new ArrayIndexOutOfBoundsException();
  211.     }
  212.     
  213.     this.userBuf = b;
  214.     this.userBufOff = off;
  215.     this.userBufLen = len;
  216.     setInputFromSavedData();
  217.     
  218.     // Reinitialize zlib's output direct buffer 
  219.     compressedDirectBuf.limit(directBufferSize);
  220.     compressedDirectBuf.position(directBufferSize);
  221.   }
  222.   
  223.   synchronized void setInputFromSavedData() {
  224.     uncompressedDirectBufOff = 0;
  225.     uncompressedDirectBufLen = userBufLen;
  226.     if (uncompressedDirectBufLen > directBufferSize) {
  227.       uncompressedDirectBufLen = directBufferSize;
  228.     }
  229.     // Reinitialize zlib's input direct buffer
  230.     uncompressedDirectBuf.rewind();
  231.     ((ByteBuffer)uncompressedDirectBuf).put(userBuf, userBufOff,  
  232.                                             uncompressedDirectBufLen);
  233.     // Note how much data is being fed to zlib
  234.     userBufOff += uncompressedDirectBufLen;
  235.     userBufLen -= uncompressedDirectBufLen;
  236.   }
  237.   public synchronized void setDictionary(byte[] b, int off, int len) {
  238.     if (stream == 0 || b == null) {
  239.       throw new NullPointerException();
  240.     }
  241.     if (off < 0 || len < 0 || off > b.length - len) {
  242.       throw new ArrayIndexOutOfBoundsException();
  243.     }
  244.     setDictionary(stream, b, off, len);
  245.   }
  246.   public boolean needsInput() {
  247.     // Consume remaining compressed data?
  248.     if (compressedDirectBuf.remaining() > 0) {
  249.       return false;
  250.     }
  251.     // Check if zlib has consumed all input
  252.     if (uncompressedDirectBufLen <= 0) {
  253.       // Check if we have consumed all user-input
  254.       if (userBufLen <= 0) {
  255.         return true;
  256.       } else {
  257.         setInputFromSavedData();
  258.       }
  259.     }
  260.     
  261.     return false;
  262.   }
  263.   
  264.   public synchronized void finish() {
  265.     finish = true;
  266.   }
  267.   
  268.   public synchronized boolean finished() {
  269.     // Check if 'zlib' says its 'finished' and
  270.     // all compressed data has been consumed
  271.     return (finished && compressedDirectBuf.remaining() == 0);
  272.   }
  273.   public synchronized int compress(byte[] b, int off, int len) 
  274.     throws IOException {
  275.     if (b == null) {
  276.       throw new NullPointerException();
  277.     }
  278.     if (off < 0 || len < 0 || off > b.length - len) {
  279.       throw new ArrayIndexOutOfBoundsException();
  280.     }
  281.     
  282.     int n = 0;
  283.     
  284.     // Check if there is compressed data
  285.     n = compressedDirectBuf.remaining();
  286.     if (n > 0) {
  287.       n = Math.min(n, len);
  288.       ((ByteBuffer)compressedDirectBuf).get(b, off, n);
  289.       return n;
  290.     }
  291.     // Re-initialize the zlib's output direct buffer
  292.     compressedDirectBuf.rewind();
  293.     compressedDirectBuf.limit(directBufferSize);
  294.     // Compress data
  295.     n = deflateBytesDirect();
  296.     compressedDirectBuf.limit(n);
  297.     
  298.     // Get atmost 'len' bytes
  299.     n = Math.min(n, len);
  300.     ((ByteBuffer)compressedDirectBuf).get(b, off, n);
  301.     return n;
  302.   }
  303.   /**
  304.    * Returns the total number of compressed bytes output so far.
  305.    *
  306.    * @return the total (non-negative) number of compressed bytes output so far
  307.    */
  308.   public synchronized long getBytesWritten() {
  309.     checkStream();
  310.     return getBytesWritten(stream);
  311.   }
  312.   /**
  313.    * Returns the total number of uncompressed bytes input so far.</p>
  314.    *
  315.    * @return the total (non-negative) number of uncompressed bytes input so far
  316.    */
  317.   public synchronized long getBytesRead() {
  318.     checkStream();
  319.     return getBytesRead(stream);
  320.   }
  321.   public synchronized void reset() {
  322.     checkStream();
  323.     reset(stream);
  324.     finish = false;
  325.     finished = false;
  326.     uncompressedDirectBuf.rewind();
  327.     uncompressedDirectBufOff = uncompressedDirectBufLen = 0;
  328.     compressedDirectBuf.limit(directBufferSize);
  329.     compressedDirectBuf.position(directBufferSize);
  330.     userBufOff = userBufLen = 0;
  331.   }
  332.   
  333.   public synchronized void end() {
  334.     if (stream != 0) {
  335.       end(stream);
  336.       stream = 0;
  337.     }
  338.   }
  339.   
  340.   private void checkStream() {
  341.     if (stream == 0)
  342.       throw new NullPointerException();
  343.   }
  344.   
  345.   private native static void initIDs();
  346.   private native static long init(int level, int strategy, int windowBits);
  347.   private native static void setDictionary(long strm, byte[] b, int off,
  348.                                            int len);
  349.   private native int deflateBytesDirect();
  350.   private native static long getBytesRead(long strm);
  351.   private native static long getBytesWritten(long strm);
  352.   private native static void reset(long strm);
  353.   private native static void end(long strm);
  354. }