summaryrefslogtreecommitdiffstats
path: root/vespajlib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2023-01-25 17:45:56 +0100
committerHenning Baldersheim <balder@yahoo-inc.com>2023-01-25 17:45:56 +0100
commitb538b5cb71919e7192ac7a031bb6624c39969e11 (patch)
treeea5c9868553ae63a89b1bc9909e21372039721fa /vespajlib
parentb91c69a14bbbd54c71b36bbdaf2311186137183b (diff)
GC unused GrowableBufferOutputStream
Diffstat (limited to 'vespajlib')
-rw-r--r--vespajlib/src/main/java/com/yahoo/io/GrowableBufferOutputStream.java184
-rw-r--r--vespajlib/src/test/java/com/yahoo/io/GrowableBufferOutputStreamTestCase.java131
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());
- }
-
-}