Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* feat: add caller push of binary data Allows a caller to push binary data to an output stream rather than having to provide a byte array or input stream. This gives the caller more control over buffering strategy and allows explicit cleanup of off-heap buffers or other non-garbage-collected resources. * feat: Introduce ByteStreamTarget * Fix rename in PGStream * Change copyright dates of added files to 2020 Co-authored-by: Tom Dunstan <tomdcc@users.noreply.github.com>
- Loading branch information
1 parent
a44ab4b
commit db228a4
Showing
12 changed files
with
630 additions
and
0 deletions.
There are no files selected for viewing
52 changes: 52 additions & 0 deletions
52
pgjdbc/src/main/java/org/postgresql/core/FixedLengthOutputStream.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright (c) 2020, PostgreSQL Global Development Group | ||
* See the LICENSE file in the project root for more information. | ||
*/ | ||
|
||
package org.postgresql.core; | ||
|
||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
|
||
/** | ||
* A stream that refuses to write more than a maximum number of bytes. | ||
*/ | ||
public class FixedLengthOutputStream extends OutputStream { | ||
|
||
private final int size; | ||
private final OutputStream target; | ||
private int written; | ||
|
||
public FixedLengthOutputStream(int size, OutputStream target) { | ||
this.size = size; | ||
this.target = target; | ||
} | ||
|
||
@Override | ||
public void write(int b) throws IOException { | ||
verifyAllowed(1); | ||
written++; | ||
target.write(b); | ||
} | ||
|
||
public void write(byte[] buf, int offset, int len) throws IOException { | ||
if ((offset < 0) || (len < 0) || ((offset + len) > buf.length)) { | ||
throw new IndexOutOfBoundsException(); | ||
} else if (len == 0) { | ||
return; | ||
} | ||
verifyAllowed(len); | ||
target.write(buf, offset, len); | ||
written += len; | ||
} | ||
|
||
public int remaining() { | ||
return size - written; | ||
} | ||
|
||
private void verifyAllowed(int wanted) throws IOException { | ||
if (remaining() < wanted) { | ||
throw new IOException("Attempt to write more than the specified " + size + " bytes"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
pgjdbc/src/main/java/org/postgresql/util/ByteBufferByteStreamWriter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright (c) 2020, PostgreSQL Global Development Group | ||
* See the LICENSE file in the project root for more information. | ||
*/ | ||
|
||
package org.postgresql.util; | ||
|
||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.Channels; | ||
import java.nio.channels.WritableByteChannel; | ||
|
||
/** | ||
* A {@link ByteStreamWriter} that writes a {@link ByteBuffer java.nio.ByteBuffer} to a byte array | ||
* parameter. | ||
*/ | ||
public class ByteBufferByteStreamWriter implements ByteStreamWriter { | ||
|
||
private final ByteBuffer buf; | ||
private final int length; | ||
|
||
/** | ||
* Construct the writer with the given {@link ByteBuffer} | ||
* | ||
* @param buf the buffer to use. | ||
*/ | ||
public ByteBufferByteStreamWriter(ByteBuffer buf) { | ||
this.buf = buf; | ||
this.length = buf.remaining(); | ||
} | ||
|
||
@Override | ||
public int getLength() { | ||
return length; | ||
} | ||
|
||
@Override | ||
public void writeTo(ByteStreamTarget target) throws IOException { | ||
// this _does_ involve some copying to a temporary buffer, but that's unavoidable | ||
// as OutputStream itself only accepts single bytes or heap allocated byte arrays | ||
WritableByteChannel c = Channels.newChannel(target.getOutputStream()); | ||
try { | ||
c.write(buf); | ||
} finally { | ||
c.close(); | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
pgjdbc/src/main/java/org/postgresql/util/ByteStreamWriter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright (c) 2020, PostgreSQL Global Development Group | ||
* See the LICENSE file in the project root for more information. | ||
*/ | ||
|
||
package org.postgresql.util; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
|
||
/** | ||
* A class that can be used to set a byte array parameter by writing to an OutputStream. | ||
* | ||
* <p>The intended use case is wanting to write data to a byte array parameter that is stored off | ||
* heap in a direct memory pool or in some other form that is inconvenient to assemble into a single | ||
* heap-allocated buffer.</p> | ||
* <p> Users should write their own implementation depending on the | ||
* original data source. The driver provides a built-in implementation supporting the {@link | ||
* java.nio.ByteBuffer} class, see {@link ByteBufferByteStreamWriter}.</p> | ||
* <p> Intended usage is to simply pass in an instance using | ||
* {@link java.sql.PreparedStatement#setObject(int, Object)}:</p> | ||
* <pre> | ||
* int bufLength = someBufferObject.length(); | ||
* preparedStatement.setObject(1, new MyByteStreamWriter(bufLength, someBufferObject)); | ||
* </pre> | ||
* <p>The length must be known ahead of the stream being written to. </p> | ||
* <p>This provides the application more control over memory management than calling | ||
* {@link java.sql.PreparedStatement#setBinaryStream(int, InputStream)} as with the latter the | ||
* caller has no control over the buffering strategy. </p> | ||
*/ | ||
public interface ByteStreamWriter { | ||
|
||
/** | ||
* Returns the length of the stream. | ||
* | ||
* <p> This must be known ahead of calling {@link #writeTo(ByteStreamTarget)}. </p> | ||
* | ||
* @return the number of bytes in the stream. | ||
*/ | ||
int getLength(); | ||
|
||
/** | ||
* Write the data to the provided {@link OutputStream}. | ||
* | ||
* <p> Should not write more than {@link #getLength()} bytes. If attempted, the provided stream | ||
* will throw an {@link java.io.IOException}. </p> | ||
* | ||
* @param target the stream to write the data to | ||
* @throws IOException if the underlying stream throws or there is some other error. | ||
*/ | ||
void writeTo(ByteStreamTarget target) throws IOException; | ||
|
||
/** | ||
* Provides a target to write bytes to. | ||
*/ | ||
interface ByteStreamTarget { | ||
|
||
/** | ||
* Provides an output stream to write bytes to. | ||
* | ||
* @return an output stream | ||
*/ | ||
OutputStream getOutputStream(); | ||
} | ||
} |
Oops, something went wrong.