Index: hbase-common/src/main/java/org/apache/hadoop/hbase/io/compress/ReusableStreamGzipCodec.java =================================================================== --- hbase-common/src/main/java/org/apache/hadoop/hbase/io/compress/ReusableStreamGzipCodec.java (revision 1423062) +++ hbase-common/src/main/java/org/apache/hadoop/hbase/io/compress/ReusableStreamGzipCodec.java (working copy) @@ -77,6 +77,13 @@ } private static class ResetableGZIPOutputStream extends GZIPOutputStream { + + private static final int TRAILER_SIZE = 8; + public static final String JVMVendor= System.getProperty("java.vendor"); + public static final String JVMVersion= System.getProperty("java.version"); + private static final boolean HAS_BROKEN_FINISH = + (JVMVendor.contains("IBM") && JVMVersion.contains("1.6.0")); + public ResetableGZIPOutputStream(OutputStream out) throws IOException { super(out); } @@ -86,6 +93,62 @@ crc.reset(); out.write(GZIP_HEADER); } + + /** + * Override because IBM implementation calls def.end() which + * causes problem when reseting the stream for reuse. + */ + @Override + public void finish() throws IOException { + + if (HAS_BROKEN_FINISH) { + if (!def.finished()) { + def.finish(); + while (!def.finished()) { + int i = def.deflate(this.buf, 0, this.buf.length); + if ((def.finished()) && (i <= this.buf.length - TRAILER_SIZE)) { + writeTrailer(this.buf, i); + i += TRAILER_SIZE; + out.write(this.buf, 0, i); + + return; + } + if (i > 0) { + out.write(this.buf, 0, i); + } + } + + byte[] arrayOfByte = new byte[TRAILER_SIZE]; + writeTrailer(arrayOfByte, 0); + out.write(arrayOfByte); + } + } + else { + super.finish(); + } + } + + /** re-implement because the relative method in jdk is invisible */ + private void writeTrailer(byte[] paramArrayOfByte, int paramInt) + throws IOException { + writeInt((int)this.crc.getValue(), paramArrayOfByte, paramInt); + writeInt(this.def.getTotalIn(), paramArrayOfByte, paramInt + 4); + } + + /** re-implement because the relative method in jdk is invisible */ + private void writeInt(int paramInt1, byte[] paramArrayOfByte, int paramInt2) + throws IOException { + writeShort(paramInt1 & 0xFFFF, paramArrayOfByte, paramInt2); + writeShort(paramInt1 >> 16 & 0xFFFF, paramArrayOfByte, paramInt2 + 2); + } + + /** re-implement because the relative method in jdk is invisible */ + private void writeShort(int paramInt1, byte[] paramArrayOfByte, int paramInt2) + throws IOException { + paramArrayOfByte[paramInt2] = (byte)(paramInt1 & 0xFF); + paramArrayOfByte[(paramInt2 + 1)] = (byte)(paramInt1 >> 8 & 0xFF); + } + } public ReusableGzipOutputStream(OutputStream out) throws IOException {