diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2023-01-25 17:45:56 +0100 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2023-01-25 17:45:56 +0100 |
commit | b538b5cb71919e7192ac7a031bb6624c39969e11 (patch) | |
tree | ea5c9868553ae63a89b1bc9909e21372039721fa /vespajlib | |
parent | b91c69a14bbbd54c71b36bbdaf2311186137183b (diff) |
GC unused GrowableBufferOutputStream
Diffstat (limited to 'vespajlib')
-rw-r--r-- | vespajlib/src/main/java/com/yahoo/io/GrowableBufferOutputStream.java | 184 | ||||
-rw-r--r-- | vespajlib/src/test/java/com/yahoo/io/GrowableBufferOutputStreamTestCase.java | 131 |
2 files changed, 0 insertions, 315 deletions
diff --git a/vespajlib/src/main/java/com/yahoo/io/GrowableBufferOutputStream.java b/vespajlib/src/main/java/com/yahoo/io/GrowableBufferOutputStream.java deleted file mode 100644 index 4b7d2ba4094..00000000000 --- a/vespajlib/src/main/java/com/yahoo/io/GrowableBufferOutputStream.java +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.io; - -import java.nio.channels.WritableByteChannel; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Stack; -import java.util.LinkedList; -import java.util.Iterator; -import java.nio.ByteBuffer; - -/** - * @author Bjørn Borud - */ -public class GrowableBufferOutputStream extends OutputStream { - - private ByteBuffer lastBuffer; - private final ByteBuffer directBuffer; - private final LinkedList<ByteBuffer> bufferList = new LinkedList<>(); - private final Stack<ByteBuffer> recycledBuffers = new Stack<>(); - - private final int bufferSize; - private final int maxBuffers; - - public GrowableBufferOutputStream(int bufferSize, int maxBuffers) { - this.bufferSize = bufferSize; - this.maxBuffers = maxBuffers; - lastBuffer = ByteBuffer.allocate(bufferSize); - directBuffer = ByteBuffer.allocateDirect(bufferSize); - } - - @Override - public void write(byte[] cbuf, int off, int len) throws IOException { - if (lastBuffer.remaining() >= len) { - lastBuffer.put(cbuf, off, len); - return; - } - - int residue = len; - - while (residue > 0) { - int newOffset = len - residue; - int toWrite = Math.min(lastBuffer.remaining(), residue); - - lastBuffer.put(cbuf, newOffset, toWrite); - residue -= toWrite; - if (residue != 0) { - extend(); - } - } - } - - @Override - public void write(byte[] b) throws IOException { - write(b,0,b.length); - } - - @Override - public String toString() { - return "GrowableBufferOutputStream, writable size " + writableSize() - + " bytes, " + numWritableBuffers() + " buffers, last buffer" - + " position " + lastBuffer.position() + ", last buffer limit " - + lastBuffer.limit(); - } - - public void write(int b) { - if (lastBuffer.remaining() == 0) { - extend(); - } - lastBuffer.put((byte) b); - } - - @Override - public void flush() { - // if the last buffer is untouched we do not need to do anything; if - // it has been touched we call extend(), which enqueues the buffer - // and allocates or recycles a buffer for us - if (lastBuffer.position() > 0) { - extend(); - } - } - - @Override - public void close() { - flush(); - } - - public int channelWrite(WritableByteChannel channel) throws IOException { - ByteBuffer buffer; - int totalWritten = 0; - - while (!bufferList.isEmpty()) { - buffer = bufferList.getFirst(); - int written = 0; - - synchronized (directBuffer) { - directBuffer.clear(); - directBuffer.put(buffer); - directBuffer.flip(); - written = channel.write(directBuffer); - int left = directBuffer.remaining(); - - if (left > 0) { - int oldpos = buffer.position(); - - buffer.position(oldpos - left); - } - totalWritten += written; - } - - // if we've completed writing this buffer we can dispose of it - if (buffer.remaining() == 0) { - bufferList.removeFirst(); - recycleBuffer(buffer); - } - - // if we didn't write any bytes we terminate - if (written == 0) { - break; - } - } - - return totalWritten; - } - - public int numWritableBuffers() { - return bufferList.size(); - } - - public void clear() { - flush(); - bufferList.clear(); - } - - public void clearCache() { - recycledBuffers.clear(); - } - - public void clearAll() { - clear(); - clearCache(); - } - - public int writableSize() { - Iterator<ByteBuffer> it = bufferList.iterator(); - int size = 0; - - while (it.hasNext()) { - size += (it.next()).remaining(); - } - - return size; - } - - public ByteBuffer[] getWritableBuffers() { - flush(); - ByteBuffer[] result = new ByteBuffer[numWritableBuffers()]; - return bufferList.toArray(result); - } - - private void extend() { - enqueueBuffer(lastBuffer); - - if (recycledBuffers.empty()) { - lastBuffer = ByteBuffer.allocate(bufferSize); - } else { - lastBuffer = recycledBuffers.pop(); - lastBuffer.clear(); - } - } - - private void enqueueBuffer(ByteBuffer buffer) { - buffer.flip(); - bufferList.addLast(buffer); - } - - private void recycleBuffer(ByteBuffer buffer) { - if (recycledBuffers.size() >= maxBuffers) { - return; - } - recycledBuffers.push(buffer); - } - -} diff --git a/vespajlib/src/test/java/com/yahoo/io/GrowableBufferOutputStreamTestCase.java b/vespajlib/src/test/java/com/yahoo/io/GrowableBufferOutputStreamTestCase.java deleted file mode 100644 index 9c905979131..00000000000 --- a/vespajlib/src/test/java/com/yahoo/io/GrowableBufferOutputStreamTestCase.java +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.io; - -import java.nio.channels.WritableByteChannel; -import java.nio.ByteBuffer; -import java.io.IOException; -import com.yahoo.io.GrowableBufferOutputStream; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - - -/** - * Tests the GrowableBufferOutputStream - * - * @author Bjorn Borud - */ -public class GrowableBufferOutputStreamTestCase { - - private byte[] testData; - - static class DummyWritableByteChannel implements WritableByteChannel { - private ByteBuffer buffer; - - public DummyWritableByteChannel(ByteBuffer buffer) { - this.buffer = buffer; - } - - public int write(ByteBuffer src) { - int written = Math.min(src.remaining(), buffer.remaining()); - - if (buffer.remaining() < src.remaining()) { - ByteBuffer tmp = src.slice(); - - tmp.limit(written); - src.position(src.position() + written); - } else { - buffer.put(src); - } - return written; - } - - public boolean isOpen() { - return true; - } - - public void close() {} - } - - @Before - public void setUp() { - testData = new byte[100]; - for (int i = 0; i < 100; ++i) { - testData[i] = (byte) i; - } - } - - @Test - public void testSimple() throws IOException { - GrowableBufferOutputStream g = new GrowableBufferOutputStream(10, 5); - - g.write(testData, 0, 100); - g.flush(); - assertEquals(10, g.numWritableBuffers()); - assertEquals(100, g.writableSize()); - - ByteBuffer sink = ByteBuffer.allocate(60); - DummyWritableByteChannel channel = new DummyWritableByteChannel(sink); - int written = g.channelWrite(channel); - - assertEquals(60, written); - assertEquals(60, sink.position()); - assertEquals(40, g.writableSize()); - - // there should be 4 buffers left now - assertEquals(4, g.numWritableBuffers()); - - // ensure that we got what we expected - for (int i = 0; i < 60; ++i) { - if (((int) sink.get(i)) != i) { - fail(); - } - } - - // then we write more data - g.write(testData, 0, 100); - g.flush(); - assertEquals(140, g.writableSize()); - - // ...which implies that we should now have 14 writable buffers - assertEquals(14, g.numWritableBuffers()); - - // reset the sink so it can consume more data - sink.clear(); - - // then write more to the DummyWritableByteChannel - written = g.channelWrite(channel); - assertEquals(60, written); - assertEquals(60, sink.position()); - assertEquals(80, g.writableSize()); - - // now there should be 8 buffers - assertEquals(8, g.numWritableBuffers()); - - // ensure that we got what we expected - for (int i = 0; i < 60; ++i) { - int val = (int) sink.get(i); - int expected = (i + 60) % 100; - - if (val != expected) { - fail("Value was " + val + " and not " + i); - } - } - - // when we clear there should be no buffers - g.clear(); - assertEquals(0, g.numWritableBuffers()); - assertEquals(0, g.writableSize()); - - // ditto after flush after clear - g.flush(); - assertEquals(0, g.numWritableBuffers()); - - // flush the cache too - g.clearAll(); - assertEquals(0, g.numWritableBuffers()); - } - -} |