org.apache.orc.impl.ZlibCodec.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.orc.impl.ZlibCodec.java

Source

/**
 * 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.orc.impl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.EnumSet;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import javax.annotation.Nullable;

import org.apache.hadoop.io.compress.DirectDecompressor;
import org.apache.orc.CompressionCodec;

public class ZlibCodec implements CompressionCodec, DirectDecompressionCodec {
    private static final HadoopShims SHIMS = HadoopShims.Factory.get();
    private Boolean direct = null;

    private final int level;
    private final int strategy;

    public ZlibCodec() {
        level = Deflater.DEFAULT_COMPRESSION;
        strategy = Deflater.DEFAULT_STRATEGY;
    }

    private ZlibCodec(int level, int strategy) {
        this.level = level;
        this.strategy = strategy;
    }

    @Override
    public boolean compress(ByteBuffer in, ByteBuffer out, ByteBuffer overflow) throws IOException {
        Deflater deflater = new Deflater(level, true);
        deflater.setStrategy(strategy);
        int length = in.remaining();
        deflater.setInput(in.array(), in.arrayOffset() + in.position(), length);
        deflater.finish();
        int outSize = 0;
        int offset = out.arrayOffset() + out.position();
        while (!deflater.finished() && (length > outSize)) {
            int size = deflater.deflate(out.array(), offset, out.remaining());
            out.position(size + out.position());
            outSize += size;
            offset += size;
            // if we run out of space in the out buffer, use the overflow
            if (out.remaining() == 0) {
                if (overflow == null) {
                    deflater.end();
                    return false;
                }
                out = overflow;
                offset = out.arrayOffset() + out.position();
            }
        }
        deflater.end();
        return length > outSize;
    }

    @Override
    public void decompress(ByteBuffer in, ByteBuffer out) throws IOException {

        if (in.isDirect() && out.isDirect()) {
            directDecompress(in, out);
            return;
        }

        Inflater inflater = new Inflater(true);
        inflater.setInput(in.array(), in.arrayOffset() + in.position(), in.remaining());
        while (!(inflater.finished() || inflater.needsDictionary() || inflater.needsInput())) {
            try {
                int count = inflater.inflate(out.array(), out.arrayOffset() + out.position(), out.remaining());
                out.position(count + out.position());
            } catch (DataFormatException dfe) {
                throw new IOException("Bad compression data", dfe);
            }
        }
        out.flip();
        inflater.end();
        in.position(in.limit());
    }

    @Override
    public boolean isAvailable() {
        if (direct == null) {
            // see nowrap option in new Inflater(boolean) which disables zlib headers
            try {
                if (SHIMS.getDirectDecompressor(HadoopShims.DirectCompressionType.ZLIB_NOHEADER) != null) {
                    direct = Boolean.valueOf(true);
                } else {
                    direct = Boolean.valueOf(false);
                }
            } catch (UnsatisfiedLinkError ule) {
                direct = Boolean.valueOf(false);
            }
        }
        return direct.booleanValue();
    }

    @Override
    public void directDecompress(ByteBuffer in, ByteBuffer out) throws IOException {
        HadoopShims.DirectDecompressor decompressShim = SHIMS
                .getDirectDecompressor(HadoopShims.DirectCompressionType.ZLIB_NOHEADER);
        decompressShim.decompress(in, out);
        out.flip(); // flip for read
    }

    @Override
    public CompressionCodec modify(@Nullable EnumSet<Modifier> modifiers) {

        if (modifiers == null) {
            return this;
        }

        int l = this.level;
        int s = this.strategy;

        for (Modifier m : modifiers) {
            switch (m) {
            case BINARY:
                /* filtered == less LZ77, more huffman */
                s = Deflater.FILTERED;
                break;
            case TEXT:
                s = Deflater.DEFAULT_STRATEGY;
                break;
            case FASTEST:
                // deflate_fast looking for 8 byte patterns
                l = Deflater.BEST_SPEED;
                break;
            case FAST:
                // deflate_fast looking for 16 byte patterns
                l = Deflater.BEST_SPEED + 1;
                break;
            case DEFAULT:
                // deflate_slow looking for 128 byte patterns
                l = Deflater.DEFAULT_COMPRESSION;
                break;
            default:
                break;
            }
        }
        return new ZlibCodec(l, s);
    }
}