From 4f63b1db7661e06343841ab1283e58568240afd7 Mon Sep 17 00:00:00 2001 From: Arne H Juul Date: Mon, 29 May 2017 14:36:47 +0200 Subject: add TeeInputStream --- .../src/main/java/com/yahoo/io/TeeInputStream.java | 96 ++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java (limited to 'vespajlib/src/main') diff --git a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java new file mode 100644 index 00000000000..7ecd6f0ccea --- /dev/null +++ b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java @@ -0,0 +1,96 @@ +package com.yahoo.io; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * Forwards input from a source InputStream while making a copy of it into an outputstream. + * Note that it also does read-ahead and copies up to 64K of data more than was used. + */ +class TeeInputStream extends InputStream { + final InputStream src; + final OutputStream dst; + + static final int CAPACITY = 65536; + + byte[] buf = new byte[CAPACITY]; + int readPos = 0; + int writePos = 0; + + private int inBuf() { return writePos - readPos; } + + private void fillBuf(boolean block) throws IOException { + if (readPos == writePos) { + readPos = 0; + writePos = 0; + } + if (readPos * 3 > CAPACITY) { + int had = inBuf(); + System.arraycopy(buf, readPos, buf, 0, had); + readPos = 0; + writePos = had; + } + int wantToRead = CAPACITY - writePos; + if (inBuf() > 0 || !block) { + wantToRead = Math.min(wantToRead, src.available()); + } + if (wantToRead > 0) { + int got = src.read(buf, writePos, wantToRead); + if (got > 0) { + dst.write(buf, writePos, got); + writePos += got; + } + } + } + + /** Construct a Tee */ + public TeeInputStream(InputStream from, OutputStream to) { + super(); + this.src = from; + this.dst = to; + } + + public @Override int available() throws IOException { + return inBuf() + src.available(); + } + + public @Override void close() throws IOException { + fillBuf(false); + src.close(); + dst.close(); + } + + public @Override void mark(int readlimit) {} + public @Override boolean markSupported() { return false; } + public @Override void reset() {} + + public @Override int read() throws IOException { + fillBuf(true); + if (inBuf() > 0) { + int r = buf[readPos++]; + return r & 0xff; + } + return -1; + } + + public @Override int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + public @Override int read(byte[] b, int off, int len) throws IOException { + if (len <= 0) { + return 0; + } + fillBuf(true); + int had = inBuf(); + if (had > 0) { + len = Math.min(len, had); + System.arraycopy(buf, readPos, b, off, len); + readPos += len; + return len; + } + return -1; + } + +} -- cgit v1.2.3 From 98a59a3bc5dd2136f416417cf329678fd7c71051 Mon Sep 17 00:00:00 2001 From: Arne H Juul Date: Tue, 30 May 2017 08:47:48 +0200 Subject: not really needed to fillBuf() in close() --- vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'vespajlib/src/main') diff --git a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java index 7ecd6f0ccea..8da0a017ec0 100644 --- a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java +++ b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java @@ -20,7 +20,7 @@ class TeeInputStream extends InputStream { private int inBuf() { return writePos - readPos; } - private void fillBuf(boolean block) throws IOException { + private void fillBuf() throws IOException { if (readPos == writePos) { readPos = 0; writePos = 0; @@ -32,7 +32,7 @@ class TeeInputStream extends InputStream { writePos = had; } int wantToRead = CAPACITY - writePos; - if (inBuf() > 0 || !block) { + if (inBuf() > 0) { wantToRead = Math.min(wantToRead, src.available()); } if (wantToRead > 0) { @@ -56,17 +56,12 @@ class TeeInputStream extends InputStream { } public @Override void close() throws IOException { - fillBuf(false); src.close(); dst.close(); } - public @Override void mark(int readlimit) {} - public @Override boolean markSupported() { return false; } - public @Override void reset() {} - public @Override int read() throws IOException { - fillBuf(true); + fillBuf(); if (inBuf() > 0) { int r = buf[readPos++]; return r & 0xff; @@ -82,7 +77,7 @@ class TeeInputStream extends InputStream { if (len <= 0) { return 0; } - fillBuf(true); + fillBuf(); int had = inBuf(); if (had > 0) { len = Math.min(len, had); -- cgit v1.2.3 From 52bf2c5ecde5dfc97f9773a2240285062ddfa59f Mon Sep 17 00:00:00 2001 From: Arne H Juul Date: Tue, 30 May 2017 08:50:47 +0200 Subject: move override annotation --- vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java | 15 ++++++++++----- .../src/test/java/com/yahoo/io/TeeInputStreamTest.java | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'vespajlib/src/main') diff --git a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java index 8da0a017ec0..18fbc3ac37a 100644 --- a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java +++ b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java @@ -51,16 +51,19 @@ class TeeInputStream extends InputStream { this.dst = to; } - public @Override int available() throws IOException { + @Override + public int available() throws IOException { return inBuf() + src.available(); } - public @Override void close() throws IOException { + @Override + public void close() throws IOException { src.close(); dst.close(); } - public @Override int read() throws IOException { + @Override + public int read() throws IOException { fillBuf(); if (inBuf() > 0) { int r = buf[readPos++]; @@ -69,11 +72,13 @@ class TeeInputStream extends InputStream { return -1; } - public @Override int read(byte[] b) throws IOException { + @Override + public int read(byte[] b) throws IOException { return read(b, 0, b.length); } - public @Override int read(byte[] b, int off, int len) throws IOException { + @Override + public int read(byte[] b, int off, int len) throws IOException { if (len <= 0) { return 0; } diff --git a/vespajlib/src/test/java/com/yahoo/io/TeeInputStreamTest.java b/vespajlib/src/test/java/com/yahoo/io/TeeInputStreamTest.java index 315e8d5f8d4..728359bc2d1 100644 --- a/vespajlib/src/test/java/com/yahoo/io/TeeInputStreamTest.java +++ b/vespajlib/src/test/java/com/yahoo/io/TeeInputStreamTest.java @@ -34,7 +34,8 @@ public class TeeInputStreamTest { private class Generator implements Runnable { private OutputStream dst; public Generator(OutputStream dst) { this.dst = dst; } - public @Override void run() { + @Override + public void run() { for (int i = 0; i < 123456789; i++) { int b = i & 0x7f; if (b < 32) continue; -- cgit v1.2.3 From a57528a5acab7a96f637222239f6b5d6aeaadf34 Mon Sep 17 00:00:00 2001 From: Arne H Juul Date: Tue, 30 May 2017 08:50:56 +0200 Subject: move override annotation --- .../main/java/com/yahoo/io/reader/NamedReader.java | 33 ++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'vespajlib/src/main') diff --git a/vespajlib/src/main/java/com/yahoo/io/reader/NamedReader.java b/vespajlib/src/main/java/com/yahoo/io/reader/NamedReader.java index 65201a02bae..7b93429acdb 100644 --- a/vespajlib/src/main/java/com/yahoo/io/reader/NamedReader.java +++ b/vespajlib/src/main/java/com/yahoo/io/reader/NamedReader.java @@ -28,21 +28,32 @@ public class NamedReader extends Reader { public Reader getReader() { return reader; } /** Returns the name */ - public @Override String toString() { + @Override + public String toString() { return name; } // The rest is reader method implementations which delegates to the wrapped reader - public @Override int read(java.nio.CharBuffer charBuffer) throws java.io.IOException { return reader.read(charBuffer); } - public @Override int read() throws java.io.IOException { return reader.read(); } - public @Override int read(char[] chars) throws java.io.IOException { return reader.read(chars); } - public @Override int read(char[] chars, int i, int i1) throws java.io.IOException { return reader.read(chars,i,i1); } - public @Override long skip(long l) throws java.io.IOException { return reader.skip(l); } - public @Override boolean ready() throws java.io.IOException { return reader.ready(); } - public @Override boolean markSupported() { return reader.markSupported(); } - public @Override void mark(int i) throws java.io.IOException { reader.mark(i); } - public @Override void reset() throws java.io.IOException { reader.reset(); } - public @Override void close() throws java.io.IOException { reader.close(); } + @Override + public int read(java.nio.CharBuffer charBuffer) throws java.io.IOException { return reader.read(charBuffer); } + @Override + public int read() throws java.io.IOException { return reader.read(); } + @Override + public int read(char[] chars) throws java.io.IOException { return reader.read(chars); } + @Override + public int read(char[] chars, int i, int i1) throws java.io.IOException { return reader.read(chars,i,i1); } + @Override + public long skip(long l) throws java.io.IOException { return reader.skip(l); } + @Override + public boolean ready() throws java.io.IOException { return reader.ready(); } + @Override + public boolean markSupported() { return reader.markSupported(); } + @Override + public void mark(int i) throws java.io.IOException { reader.mark(i); } + @Override + public void reset() throws java.io.IOException { reader.reset(); } + @Override + public void close() throws java.io.IOException { reader.close(); } /** Convenience method for closing a list of readers. Does nothing if the given reader list is null. */ public static void closeAll(List readers) { -- cgit v1.2.3 From a8471a5ccca7570b7f556b1b2829ff0977c997dd Mon Sep 17 00:00:00 2001 From: Arne H Juul Date: Tue, 30 May 2017 09:00:01 +0200 Subject: add comment --- vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java | 1 + 1 file changed, 1 insertion(+) (limited to 'vespajlib/src/main') diff --git a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java index 18fbc3ac37a..f9e803df08f 100644 --- a/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java +++ b/vespajlib/src/main/java/com/yahoo/io/TeeInputStream.java @@ -33,6 +33,7 @@ class TeeInputStream extends InputStream { } int wantToRead = CAPACITY - writePos; if (inBuf() > 0) { + // if we have data already, do not block, read only what is available wantToRead = Math.min(wantToRead, src.available()); } if (wantToRead > 0) { -- cgit v1.2.3