001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.hadoop.io.compress; 020 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.OutputStream; 024 025 import org.apache.hadoop.conf.Configurable; 026 import org.apache.hadoop.conf.Configuration; 027 import org.apache.hadoop.io.compress.lz4.Lz4Compressor; 028 import org.apache.hadoop.io.compress.lz4.Lz4Decompressor; 029 import org.apache.hadoop.fs.CommonConfigurationKeys; 030 import org.apache.hadoop.util.NativeCodeLoader; 031 032 /** 033 * This class creates lz4 compressors/decompressors. 034 */ 035 public class Lz4Codec implements Configurable, CompressionCodec { 036 037 static { 038 NativeCodeLoader.isNativeCodeLoaded(); 039 } 040 041 Configuration conf; 042 043 /** 044 * Set the configuration to be used by this object. 045 * 046 * @param conf the configuration object. 047 */ 048 @Override 049 public void setConf(Configuration conf) { 050 this.conf = conf; 051 } 052 053 /** 054 * Return the configuration used by this object. 055 * 056 * @return the configuration object used by this objec. 057 */ 058 @Override 059 public Configuration getConf() { 060 return conf; 061 } 062 063 /** 064 * Are the native lz4 libraries loaded & initialized? 065 * 066 * @return true if loaded & initialized, otherwise false 067 */ 068 public static boolean isNativeCodeLoaded() { 069 return NativeCodeLoader.isNativeCodeLoaded(); 070 } 071 072 public static String getLibraryName() { 073 return Lz4Compressor.getLibraryName(); 074 } 075 076 /** 077 * Create a {@link CompressionOutputStream} that will write to the given 078 * {@link OutputStream}. 079 * 080 * @param out the location for the final output stream 081 * @return a stream the user can write uncompressed data to have it compressed 082 * @throws IOException 083 */ 084 @Override 085 public CompressionOutputStream createOutputStream(OutputStream out) 086 throws IOException { 087 return createOutputStream(out, createCompressor()); 088 } 089 090 /** 091 * Create a {@link CompressionOutputStream} that will write to the given 092 * {@link OutputStream} with the given {@link Compressor}. 093 * 094 * @param out the location for the final output stream 095 * @param compressor compressor to use 096 * @return a stream the user can write uncompressed data to have it compressed 097 * @throws IOException 098 */ 099 @Override 100 public CompressionOutputStream createOutputStream(OutputStream out, 101 Compressor compressor) 102 throws IOException { 103 if (!isNativeCodeLoaded()) { 104 throw new RuntimeException("native lz4 library not available"); 105 } 106 int bufferSize = conf.getInt( 107 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_KEY, 108 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_DEFAULT); 109 110 int compressionOverhead = Math.max((int)(bufferSize * 0.01), 10); 111 112 return new BlockCompressorStream(out, compressor, bufferSize, 113 compressionOverhead); 114 } 115 116 /** 117 * Get the type of {@link Compressor} needed by this {@link CompressionCodec}. 118 * 119 * @return the type of compressor needed by this codec. 120 */ 121 @Override 122 public Class<? extends Compressor> getCompressorType() { 123 if (!isNativeCodeLoaded()) { 124 throw new RuntimeException("native lz4 library not available"); 125 } 126 127 return Lz4Compressor.class; 128 } 129 130 /** 131 * Create a new {@link Compressor} for use by this {@link CompressionCodec}. 132 * 133 * @return a new compressor for use by this codec 134 */ 135 @Override 136 public Compressor createCompressor() { 137 if (!isNativeCodeLoaded()) { 138 throw new RuntimeException("native lz4 library not available"); 139 } 140 int bufferSize = conf.getInt( 141 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_KEY, 142 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_DEFAULT); 143 return new Lz4Compressor(bufferSize); 144 } 145 146 /** 147 * Create a {@link CompressionInputStream} that will read from the given 148 * input stream. 149 * 150 * @param in the stream to read compressed bytes from 151 * @return a stream to read uncompressed bytes from 152 * @throws IOException 153 */ 154 @Override 155 public CompressionInputStream createInputStream(InputStream in) 156 throws IOException { 157 return createInputStream(in, createDecompressor()); 158 } 159 160 /** 161 * Create a {@link CompressionInputStream} that will read from the given 162 * {@link InputStream} with the given {@link Decompressor}. 163 * 164 * @param in the stream to read compressed bytes from 165 * @param decompressor decompressor to use 166 * @return a stream to read uncompressed bytes from 167 * @throws IOException 168 */ 169 @Override 170 public CompressionInputStream createInputStream(InputStream in, 171 Decompressor decompressor) 172 throws IOException { 173 if (!isNativeCodeLoaded()) { 174 throw new RuntimeException("native lz4 library not available"); 175 } 176 177 return new BlockDecompressorStream(in, decompressor, conf.getInt( 178 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_KEY, 179 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_DEFAULT)); 180 } 181 182 /** 183 * Get the type of {@link Decompressor} needed by this {@link CompressionCodec}. 184 * 185 * @return the type of decompressor needed by this codec. 186 */ 187 @Override 188 public Class<? extends Decompressor> getDecompressorType() { 189 if (!isNativeCodeLoaded()) { 190 throw new RuntimeException("native lz4 library not available"); 191 } 192 193 return Lz4Decompressor.class; 194 } 195 196 /** 197 * Create a new {@link Decompressor} for use by this {@link CompressionCodec}. 198 * 199 * @return a new decompressor for use by this codec 200 */ 201 @Override 202 public Decompressor createDecompressor() { 203 if (!isNativeCodeLoaded()) { 204 throw new RuntimeException("native lz4 library not available"); 205 } 206 int bufferSize = conf.getInt( 207 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_KEY, 208 CommonConfigurationKeys.IO_COMPRESSION_CODEC_LZ4_BUFFERSIZE_DEFAULT); 209 return new Lz4Decompressor(bufferSize); 210 } 211 212 /** 213 * Get the default filename extension for this kind of compression. 214 * 215 * @return <code>.lz4</code>. 216 */ 217 @Override 218 public String getDefaultExtension() { 219 return ".lz4"; 220 } 221 }