提交 f8f31c38 编写于 作者: S sherman

4813885: RFE: GZIPOutputStream should implement flush using Z_SYNC_FLUSH

Summary: Added new constructors to allow flush() work in Z_SYNC_FLUSH mode
Reviewed-by: martin
上级 108d979b
/* /*
* Copyright 1996-2002 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -54,25 +54,82 @@ class GZIPOutputStream extends DeflaterOutputStream { ...@@ -54,25 +54,82 @@ class GZIPOutputStream extends DeflaterOutputStream {
/** /**
* Creates a new output stream with the specified buffer size. * Creates a new output stream with the specified buffer size.
*
* <p>The new output stream instance is created as if by invoking
* the 3-argument constructor GZIPOutputStream(out, size, false).
*
* @param out the output stream * @param out the output stream
* @param size the output buffer size * @param size the output buffer size
* @exception IOException If an I/O error has occurred. * @exception IOException If an I/O error has occurred.
* @exception IllegalArgumentException if size is <= 0 * @exception IllegalArgumentException if size is <= 0
*/ */
public GZIPOutputStream(OutputStream out, int size) throws IOException { public GZIPOutputStream(OutputStream out, int size) throws IOException {
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size); this(out, size, false);
}
/**
* Creates a new output stream with the specified buffer size and
* flush mode.
*
* @param out the output stream
* @param size the output buffer size
* @param syncFlush
* if {@code true} invocation of the inherited
* {@link DeflaterOutputStream#flush() flush()} method of
* this instance flushes the compressor with flush mode
* {@link Deflater#SYNC_FLUSH} before flushing the output
* stream, otherwise only flushes the output stream
* @exception IOException If an I/O error has occurred.
* @exception IllegalArgumentException if size is <= 0
*
* @since 1.7
*/
public GZIPOutputStream(OutputStream out, int size, boolean syncFlush)
throws IOException
{
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true),
size,
syncFlush);
usesDefaultDeflater = true; usesDefaultDeflater = true;
writeHeader(); writeHeader();
crc.reset(); crc.reset();
} }
/** /**
* Creates a new output stream with a default buffer size. * Creates a new output stream with a default buffer size.
*
* <p>The new output stream instance is created as if by invoking
* the 2-argument constructor GZIPOutputStream(out, false).
*
* @param out the output stream * @param out the output stream
* @exception IOException If an I/O error has occurred. * @exception IOException If an I/O error has occurred.
*/ */
public GZIPOutputStream(OutputStream out) throws IOException { public GZIPOutputStream(OutputStream out) throws IOException {
this(out, 512); this(out, 512, false);
}
/**
* Creates a new output stream with a default buffer size and
* the specified flush mode.
*
* @param out the output stream
* @param syncFlush
* if {@code true} invocation of the inherited
* {@link DeflaterOutputStream#flush() flush()} method of
* this instance flushes the compressor with flush mode
* {@link Deflater#SYNC_FLUSH} before flushing the output
* stream, otherwise only flushes the output stream
*
* @exception IOException If an I/O error has occurred.
*
* @since 1.7
*/
public GZIPOutputStream(OutputStream out, boolean syncFlush)
throws IOException
{
this(out, 512, syncFlush);
} }
/** /**
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
/** /**
* @test * @test
* @bug 4206909 * @bug 4206909 4813885
* @summary Test basic functionality of DeflaterOutputStream and InflaterInputStream including flush * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush
*/ */
import java.io.*; import java.io.*;
...@@ -79,23 +79,23 @@ public class InflateIn_DeflateOut { ...@@ -79,23 +79,23 @@ public class InflateIn_DeflateOut {
} }
private static class PairedOutputStream extends ByteArrayOutputStream { private static class PairedOutputStream extends ByteArrayOutputStream {
private PairedInputStream pairedStream = null; private PairedInputStream pairedStream = null;
public PairedOutputStream(PairedInputStream inputPair) { public PairedOutputStream(PairedInputStream inputPair) {
super(); super();
this.pairedStream = inputPair; this.pairedStream = inputPair;
} }
public void flush() { public void flush() {
if (count > 0) { if (count > 0) {
pairedStream.addBytes(buf, count); pairedStream.addBytes(buf, count);
reset(); reset();
}
} }
}
public void close() { public void close() {
flush(); flush();
} }
} }
private static boolean readFully(InputStream in, byte[] buf, int length) private static boolean readFully(InputStream in, byte[] buf, int length)
...@@ -146,27 +146,20 @@ public class InflateIn_DeflateOut { ...@@ -146,27 +146,20 @@ public class InflateIn_DeflateOut {
check(Arrays.equals(data, buf)); check(Arrays.equals(data, buf));
} }
/** Check that written, flushed and read */ private static void check(InputStream is, OutputStream os)
private static void WriteFlushRead() throws Throwable { throws Throwable
{
Random random = new Random(new Date().getTime()); Random random = new Random(new Date().getTime());
// Large writes
PairedInputStream pis = new PairedInputStream();
InflaterInputStream iis = new InflaterInputStream(pis);
PairedOutputStream pos = new PairedOutputStream(pis);
pis.setPairedOutputStream(pos);
DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
// Large writes
for (int x = 0; x < 200 ; x++) { for (int x = 0; x < 200 ; x++) {
// byte[] data = new byte[random.nextInt(1024 * 1024)]; // byte[] data = new byte[random.nextInt(1024 * 1024)];
byte[] data = new byte[1024]; byte[] data = new byte[1024];
byte[] buf = new byte[data.length]; byte[] buf = new byte[data.length];
random.nextBytes(data); random.nextBytes(data);
dos.write(data); os.write(data);
dos.flush(); os.flush();
check(readFully(iis, buf, buf.length)); check(readFully(is, buf, buf.length));
check(Arrays.equals(data, buf)); check(Arrays.equals(data, buf));
} }
...@@ -176,9 +169,9 @@ public class InflateIn_DeflateOut { ...@@ -176,9 +169,9 @@ public class InflateIn_DeflateOut {
byte[] buf = new byte[data.length]; byte[] buf = new byte[data.length];
random.nextBytes(data); random.nextBytes(data);
dos.write(data); os.write(data);
dos.flush(); os.flush();
if (!readFully(iis, buf, buf.length)) { if (!readFully(is, buf, buf.length)) {
fail("Didn't read full buffer of " + buf.length); fail("Didn't read full buffer of " + buf.length);
} }
check(Arrays.equals(data, buf)); check(Arrays.equals(data, buf));
...@@ -187,17 +180,16 @@ public class InflateIn_DeflateOut { ...@@ -187,17 +180,16 @@ public class InflateIn_DeflateOut {
String quit = "QUIT\r\n"; String quit = "QUIT\r\n";
// Close it out // Close it out
dos.write(quit.getBytes()); os.write(quit.getBytes());
dos.close(); os.close();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
check(readLineIfAvailable(iis, sb)); check(readLineIfAvailable(is, sb));
equal(sb.toString(), quit); equal(sb.toString(), quit);
} }
/** Validate that we need to use flush at least once on a line /** Check that written, flushed and read */
* oriented protocol */ private static void WriteFlushRead() throws Throwable {
private static void LineOrientedProtocol() throws Throwable {
PairedInputStream pis = new PairedInputStream(); PairedInputStream pis = new PairedInputStream();
InflaterInputStream iis = new InflaterInputStream(pis); InflaterInputStream iis = new InflaterInputStream(pis);
...@@ -205,6 +197,24 @@ public class InflateIn_DeflateOut { ...@@ -205,6 +197,24 @@ public class InflateIn_DeflateOut {
pis.setPairedOutputStream(pos); pis.setPairedOutputStream(pos);
DeflaterOutputStream dos = new DeflaterOutputStream(pos, true); DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
check(iis, dos);
}
private static void GZWriteFlushRead() throws Throwable {
PairedInputStream pis = new PairedInputStream();
PairedOutputStream pos = new PairedOutputStream(pis);
pis.setPairedOutputStream(pos);
GZIPOutputStream gos = new GZIPOutputStream(pos, true);
gos.flush(); // flush the head out, so gis can read
GZIPInputStream gis = new GZIPInputStream(pis);
check(gis, gos);
}
private static void checkLOP(InputStream is, OutputStream os)
throws Throwable
{
boolean flushed = false; boolean flushed = false;
int count = 0; int count = 0;
...@@ -212,13 +222,13 @@ public class InflateIn_DeflateOut { ...@@ -212,13 +222,13 @@ public class InflateIn_DeflateOut {
// flush means this test isn't testing anything // flush means this test isn't testing anything
while ((count < 10 && flushed) || (count < 1000 && !flushed)) { while ((count < 10 && flushed) || (count < 1000 && !flushed)) {
String command = "PING " + count + "\r\n"; String command = "PING " + count + "\r\n";
dos.write(command.getBytes()); os.write(command.getBytes());
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
if (!readLineIfAvailable(iis, buf)) { if (!readLineIfAvailable(is, buf)) {
flushed = true; flushed = true;
dos.flush(); os.flush();
check(readLineIfAvailable(iis, buf)); check(readLineIfAvailable(is, buf));
} }
equal(buf.toString(), command); equal(buf.toString(), command);
count++; count++;
...@@ -226,12 +236,37 @@ public class InflateIn_DeflateOut { ...@@ -226,12 +236,37 @@ public class InflateIn_DeflateOut {
check(flushed); check(flushed);
} }
/** Validate that we need to use flush at least once on a line
* oriented protocol */
private static void LineOrientedProtocol() throws Throwable {
PairedInputStream pis = new PairedInputStream();
InflaterInputStream iis = new InflaterInputStream(pis);
PairedOutputStream pos = new PairedOutputStream(pis);
pis.setPairedOutputStream(pos);
DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
checkLOP(iis, dos);
}
private static void GZLineOrientedProtocol() throws Throwable {
PairedInputStream pis = new PairedInputStream();
PairedOutputStream pos = new PairedOutputStream(pis);
pis.setPairedOutputStream(pos);
GZIPOutputStream gos = new GZIPOutputStream(pos, true);
gos.flush(); // flush the head out, so gis can read
GZIPInputStream gis = new GZIPInputStream(pis);
checkLOP(gis, gos);
}
public static void realMain(String[] args) throws Throwable { public static void realMain(String[] args) throws Throwable {
WriteCloseRead(); WriteCloseRead();
WriteFlushRead(); WriteFlushRead();
LineOrientedProtocol(); LineOrientedProtocol();
GZWriteFlushRead();
GZLineOrientedProtocol();
} }
//--------------------- Infrastructure --------------------------- //--------------------- Infrastructure ---------------------------
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册