Skip to content

Commit 0076243

Browse files
committed
Add WritableBuffer interface for zero copy data writes. Fixes grpc#8
WritableBuffer is a generic interface that allows to transfer data from gRPC directly to the native transport's buffer implementation.
1 parent ee19f06 commit 0076243

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1167
-272
lines changed

core/src/main/java/io/grpc/ChannelImpl.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@
3333

3434
import com.google.common.base.Preconditions;
3535
import com.google.common.base.Throwables;
36-
import com.google.common.util.concurrent.MoreExecutors;
37-
import com.google.common.util.concurrent.Service.Listener;
38-
import com.google.common.util.concurrent.Service.State;
3936

4037
import io.grpc.transport.ClientStream;
4138
import io.grpc.transport.ClientStreamListener;
@@ -48,7 +45,6 @@
4845
import java.util.Collection;
4946
import java.util.concurrent.ExecutorService;
5047
import java.util.concurrent.TimeUnit;
51-
import java.util.logging.Level;
5248
import java.util.logging.Logger;
5349

5450
import javax.annotation.concurrent.GuardedBy;

core/src/main/java/io/grpc/transport/AbstractClientStream.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import io.grpc.Status;
3939

4040
import java.io.InputStream;
41-
import java.nio.ByteBuffer;
4241
import java.util.logging.Level;
4342
import java.util.logging.Logger;
4443

@@ -67,7 +66,9 @@ public abstract class AbstractClientStream<IdT> extends AbstractStream<IdT>
6766
*
6867
* @param listener the listener to receive notifications
6968
*/
70-
protected AbstractClientStream(ClientStreamListener listener) {
69+
protected AbstractClientStream(WritableBufferAllocator bufferAllocator,
70+
ClientStreamListener listener) {
71+
super(bufferAllocator);
7172
this.listener = Preconditions.checkNotNull(listener);
7273
}
7374

@@ -122,7 +123,7 @@ protected void inboundHeadersReceived(Metadata.Headers headers) {
122123
*
123124
* @param frame the received data frame. Its ownership is transferred to this method.
124125
*/
125-
protected void inboundDataReceived(Buffer frame) {
126+
protected void inboundDataReceived(ReadableBuffer frame) {
126127
Preconditions.checkNotNull(frame, "frame");
127128
boolean needToCloseFrame = true;
128129
try {
@@ -173,7 +174,7 @@ protected void inboundTrailersReceived(Metadata.Trailers trailers, Status status
173174
// remoteEndClosed
174175
this.status = status;
175176
this.trailers = trailers;
176-
deframe(Buffers.empty(), true);
177+
deframe(ReadableBuffers.empty(), true);
177178
}
178179

179180
@Override
@@ -182,7 +183,7 @@ protected void remoteEndClosed() {
182183
}
183184

184185
@Override
185-
protected final void internalSendFrame(ByteBuffer frame, boolean endOfStream) {
186+
protected final void internalSendFrame(WritableBuffer frame, boolean endOfStream) {
186187
sendFrame(frame, endOfStream);
187188
}
188189

@@ -193,7 +194,7 @@ protected final void internalSendFrame(ByteBuffer frame, boolean endOfStream) {
193194
* @param endOfStream if {@code true} indicates that no more data will be sent on the stream by
194195
* this endpoint.
195196
*/
196-
protected abstract void sendFrame(ByteBuffer frame, boolean endOfStream);
197+
protected abstract void sendFrame(WritableBuffer frame, boolean endOfStream);
197198

198199
/**
199200
* Report stream closure with status to the application layer if not already reported. This method

core/src/main/java/io/grpc/transport/AbstractBuffer.java renamed to core/src/main/java/io/grpc/transport/AbstractReadableBuffer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
package io.grpc.transport;
3333

3434
/**
35-
* Abstract base class for {@link Buffer} implementations.
35+
* Abstract base class for {@link ReadableBuffer} implementations.
3636
*/
37-
public abstract class AbstractBuffer implements Buffer {
37+
public abstract class AbstractReadableBuffer implements ReadableBuffer {
3838

3939
@Override
4040
public final int readUnsignedMedium() {

core/src/main/java/io/grpc/transport/AbstractServerStream.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import io.grpc.Status;
3838

3939
import java.io.InputStream;
40-
import java.nio.ByteBuffer;
4140
import java.util.logging.Level;
4241
import java.util.logging.Logger;
4342

@@ -62,7 +61,8 @@ public abstract class AbstractServerStream<IdT> extends AbstractStream<IdT>
6261
/** Saved trailers from close() that need to be sent once the framer has sent all messages. */
6362
private Metadata.Trailers stashedTrailers;
6463

65-
protected AbstractServerStream(IdT id) {
64+
protected AbstractServerStream(WritableBufferAllocator bufferAllocator, IdT id) {
65+
super(bufferAllocator);
6666
id(id);
6767
}
6868

@@ -125,7 +125,7 @@ private void writeStatusToTrailers(Status status) {
125125
* be retained.
126126
* @param endOfStream {@code true} if no more data will be received on the stream.
127127
*/
128-
public void inboundDataReceived(Buffer frame, boolean endOfStream) {
128+
public void inboundDataReceived(ReadableBuffer frame, boolean endOfStream) {
129129
if (inboundPhase() == Phase.STATUS) {
130130
frame.close();
131131
return;
@@ -142,8 +142,8 @@ protected final void deframeFailed(Throwable cause) {
142142
}
143143

144144
@Override
145-
protected final void internalSendFrame(ByteBuffer frame, boolean endOfStream) {
146-
if (frame.hasRemaining()) {
145+
protected final void internalSendFrame(WritableBuffer frame, boolean endOfStream) {
146+
if (frame.readableBytes() > 0) {
147147
sendFrame(frame, false);
148148
}
149149
if (endOfStream) {
@@ -167,7 +167,7 @@ protected final void internalSendFrame(ByteBuffer frame, boolean endOfStream) {
167167
* @param endOfStream if {@code true} indicates that no more data will be sent on the stream by
168168
* this endpoint.
169169
*/
170-
protected abstract void sendFrame(ByteBuffer frame, boolean endOfStream);
170+
protected abstract void sendFrame(WritableBuffer frame, boolean endOfStream);
171171

172172
/**
173173
* Sends trailers to the remote end point. This call implies end of stream.

core/src/main/java/io/grpc/transport/AbstractStream.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import com.google.common.base.Preconditions;
3737

3838
import java.io.InputStream;
39-
import java.nio.ByteBuffer;
4039

4140
import javax.annotation.Nullable;
4241

@@ -65,7 +64,7 @@ protected enum Phase {
6564
*/
6665
private Phase outboundPhase = Phase.HEADERS;
6766

68-
AbstractStream() {
67+
AbstractStream(WritableBufferAllocator bufferAllocator) {
6968
MessageDeframer.Listener inboundMessageHandler = new MessageDeframer.Listener() {
7069
@Override
7170
public void bytesRead(int numBytes) {
@@ -87,14 +86,14 @@ public void endOfStream() {
8786
remoteEndClosed();
8887
}
8988
};
90-
MessageFramer.Sink<ByteBuffer> outboundFrameHandler = new MessageFramer.Sink<ByteBuffer>() {
89+
MessageFramer.Sink outboundFrameHandler = new MessageFramer.Sink() {
9190
@Override
92-
public void deliverFrame(ByteBuffer frame, boolean endOfStream) {
91+
public void deliverFrame(WritableBuffer frame, boolean endOfStream) {
9392
internalSendFrame(frame, endOfStream);
9493
}
9594
};
9695

97-
framer = new MessageFramer(outboundFrameHandler, 4096);
96+
framer = new MessageFramer(outboundFrameHandler, bufferAllocator, 4096);
9897
this.deframer = new MessageDeframer(inboundMessageHandler);
9998
}
10099

@@ -168,7 +167,7 @@ public void dispose() {
168167
* @param endOfStream if {@code true} indicates that no more data will be sent on the stream by
169168
* this endpoint.
170169
*/
171-
protected abstract void internalSendFrame(ByteBuffer frame, boolean endOfStream);
170+
protected abstract void internalSendFrame(WritableBuffer frame, boolean endOfStream);
172171

173172
/**
174173
* Handles a message that was just deframed.
@@ -194,7 +193,7 @@ public void dispose() {
194193
protected abstract void returnProcessedBytes(int processedBytes);
195194

196195
/**
197-
* Called when a {@link #deframe(Buffer, boolean)} operation failed.
196+
* Called when a {@link #deframe(ReadableBuffer, boolean)} operation failed.
198197
*
199198
* @param cause the actual failure
200199
*/
@@ -212,7 +211,7 @@ protected final void closeDeframer() {
212211
* Called to parse a received frame and attempt delivery of any completed
213212
* messages. Must be called from the transport thread.
214213
*/
215-
protected final void deframe(Buffer frame, boolean endOfStream) {
214+
protected final void deframe(ReadableBuffer frame, boolean endOfStream) {
216215
try {
217216
deframer.deframe(frame, endOfStream);
218217
} catch (Throwable t) {

core/src/main/java/io/grpc/transport/CompositeBuffer.java renamed to core/src/main/java/io/grpc/transport/CompositeReadableBuffer.java

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,34 +38,34 @@
3838
import java.util.Queue;
3939

4040
/**
41-
* A {@link Buffer} that is composed of 0 or more {@link Buffer}s. This provides a facade that
41+
* A {@link ReadableBuffer} that is composed of 0 or more {@link ReadableBuffer}s. This provides a facade that
4242
* allows multiple buffers to be treated as one.
4343
*
4444
* <p>When a buffer is added to a composite, its life cycle is controlled by the composite. Once
4545
* the composite has read past the end of a given buffer, that buffer is automatically closed and
4646
* removed from the composite.
4747
*/
48-
public class CompositeBuffer extends AbstractBuffer {
48+
public class CompositeReadableBuffer extends AbstractReadableBuffer {
4949

5050
private int readableBytes;
51-
private final Queue<Buffer> buffers = new ArrayDeque<Buffer>();
51+
private final Queue<ReadableBuffer> buffers = new ArrayDeque<ReadableBuffer>();
5252

5353
/**
54-
* Adds a new {@link Buffer} at the end of the buffer list. After a buffer is added, it is
54+
* Adds a new {@link ReadableBuffer} at the end of the buffer list. After a buffer is added, it is
5555
* expected that this {@code CompositeBuffer} has complete ownership. Any attempt to modify the
5656
* buffer (i.e. modifying the readable bytes) may result in corruption of the internal state of
5757
* this {@code CompositeBuffer}.
5858
*/
59-
public void addBuffer(Buffer buffer) {
60-
if (!(buffer instanceof CompositeBuffer)) {
59+
public void addBuffer(ReadableBuffer buffer) {
60+
if (!(buffer instanceof CompositeReadableBuffer)) {
6161
buffers.add(buffer);
6262
readableBytes += buffer.readableBytes();
6363
return;
6464
}
6565

66-
CompositeBuffer compositeBuffer = (CompositeBuffer) buffer;
66+
CompositeReadableBuffer compositeBuffer = (CompositeReadableBuffer) buffer;
6767
while (!compositeBuffer.buffers.isEmpty()) {
68-
Buffer subBuffer = compositeBuffer.buffers.remove();
68+
ReadableBuffer subBuffer = compositeBuffer.buffers.remove();
6969
buffers.add(subBuffer);
7070
}
7171
readableBytes += compositeBuffer.readableBytes;
@@ -82,7 +82,7 @@ public int readableBytes() {
8282
public int readUnsignedByte() {
8383
ReadOperation op = new ReadOperation() {
8484
@Override
85-
int readInternal(Buffer buffer, int length) {
85+
int readInternal(ReadableBuffer buffer, int length) {
8686
return buffer.readUnsignedByte();
8787
}
8888
};
@@ -94,7 +94,7 @@ int readInternal(Buffer buffer, int length) {
9494
public void skipBytes(int length) {
9595
execute(new ReadOperation() {
9696
@Override
97-
public int readInternal(Buffer buffer, int length) {
97+
public int readInternal(ReadableBuffer buffer, int length) {
9898
buffer.skipBytes(length);
9999
return 0;
100100
}
@@ -106,7 +106,7 @@ public void readBytes(final byte[] dest, final int destOffset, int length) {
106106
execute(new ReadOperation() {
107107
int currentOffset = destOffset;
108108
@Override
109-
public int readInternal(Buffer buffer, int length) {
109+
public int readInternal(ReadableBuffer buffer, int length) {
110110
buffer.readBytes(dest, currentOffset, length);
111111
currentOffset += length;
112112
return 0;
@@ -118,7 +118,7 @@ public int readInternal(Buffer buffer, int length) {
118118
public void readBytes(final ByteBuffer dest) {
119119
execute(new ReadOperation() {
120120
@Override
121-
public int readInternal(Buffer buffer, int length) {
121+
public int readInternal(ReadableBuffer buffer, int length) {
122122
// Change the limit so that only lengthToCopy bytes are available.
123123
int prevLimit = dest.limit();
124124
dest.limit(dest.position() + length);
@@ -135,7 +135,7 @@ public int readInternal(Buffer buffer, int length) {
135135
public void readBytes(final OutputStream dest, int length) throws IOException {
136136
ReadOperation op = new ReadOperation() {
137137
@Override
138-
public int readInternal(Buffer buffer, int length) throws IOException {
138+
public int readInternal(ReadableBuffer buffer, int length) throws IOException {
139139
buffer.readBytes(dest, length);
140140
return 0;
141141
}
@@ -149,13 +149,13 @@ public int readInternal(Buffer buffer, int length) throws IOException {
149149
}
150150

151151
@Override
152-
public CompositeBuffer readBytes(int length) {
152+
public CompositeReadableBuffer readBytes(int length) {
153153
checkReadable(length);
154154
readableBytes -= length;
155155

156-
CompositeBuffer newBuffer = new CompositeBuffer();
156+
CompositeReadableBuffer newBuffer = new CompositeReadableBuffer();
157157
while (length > 0) {
158-
Buffer buffer = buffers.peek();
158+
ReadableBuffer buffer = buffers.peek();
159159
if (buffer.readableBytes() > length) {
160160
newBuffer.addBuffer(buffer.readBytes(length));
161161
length = 0;
@@ -175,14 +175,14 @@ public void close() {
175175
}
176176

177177
/**
178-
* Executes the given {@link ReadOperation} against the {@link Buffer}s required to satisfy the
178+
* Executes the given {@link ReadOperation} against the {@link ReadableBuffer}s required to satisfy the
179179
* requested {@code length}.
180180
*/
181181
private void execute(ReadOperation op, int length) {
182182
checkReadable(length);
183183

184184
for (; length > 0 && !buffers.isEmpty(); advanceBufferIfNecessary()) {
185-
Buffer buffer = buffers.peek();
185+
ReadableBuffer buffer = buffers.peek();
186186
int lengthToCopy = Math.min(length, buffer.readableBytes());
187187

188188
// Perform the read operation for this buffer.
@@ -205,28 +205,28 @@ private void execute(ReadOperation op, int length) {
205205
* If the current buffer is exhausted, removes and closes it.
206206
*/
207207
private void advanceBufferIfNecessary() {
208-
Buffer buffer = buffers.peek();
208+
ReadableBuffer buffer = buffers.peek();
209209
if (buffer.readableBytes() == 0) {
210210
buffers.remove().close();
211211
}
212212
}
213213

214214
/**
215-
* A simple read operation to perform on a single {@link Buffer}. All state management for the
216-
* buffers is done by {@link CompositeBuffer#execute(ReadOperation, int)}.
215+
* A simple read operation to perform on a single {@link ReadableBuffer}. All state management for the
216+
* buffers is done by {@link CompositeReadableBuffer#execute(ReadOperation, int)}.
217217
*/
218218
private abstract class ReadOperation {
219219
/**
220-
* Only used by {@link CompositeBuffer#readUnsignedByte()}.
220+
* Only used by {@link CompositeReadableBuffer#readUnsignedByte()}.
221221
*/
222222
int value;
223223

224224
/**
225-
* Only used by {@link CompositeBuffer#readBytes(OutputStream, int)};
225+
* Only used by {@link CompositeReadableBuffer#readBytes(OutputStream, int)};
226226
*/
227227
IOException ex;
228228

229-
final void read(Buffer buffer, int length) {
229+
final void read(ReadableBuffer buffer, int length) {
230230
try {
231231
value = readInternal(buffer, length);
232232
} catch (IOException e) {
@@ -238,6 +238,6 @@ final boolean isError() {
238238
return ex != null;
239239
}
240240

241-
abstract int readInternal(Buffer buffer, int length) throws IOException;
241+
abstract int readInternal(ReadableBuffer buffer, int length) throws IOException;
242242
}
243243
}

core/src/main/java/io/grpc/transport/ForwardingBuffer.java renamed to core/src/main/java/io/grpc/transport/ForwardingReadableBuffer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,21 @@
3838
import java.nio.ByteBuffer;
3939

4040
/**
41-
* Base class for a wrapper around another {@link Buffer}.
41+
* Base class for a wrapper around another {@link ReadableBuffer}.
4242
*
4343
* <p>This class just passes every operation through to the underlying buffer. Subclasses may
4444
* override methods to intercept concertain operations.
4545
*/
46-
public abstract class ForwardingBuffer implements Buffer {
46+
public abstract class ForwardingReadableBuffer implements ReadableBuffer {
4747

48-
private final Buffer buf;
48+
private final ReadableBuffer buf;
4949

5050
/**
5151
* Constructor.
5252
*
5353
* @param buf the underlying buffer
5454
*/
55-
public ForwardingBuffer(Buffer buf) {
55+
public ForwardingReadableBuffer(ReadableBuffer buf) {
5656
this.buf = Preconditions.checkNotNull(buf, "buf");
5757
}
5858

@@ -102,7 +102,7 @@ public void readBytes(OutputStream dest, int length) throws IOException {
102102
}
103103

104104
@Override
105-
public Buffer readBytes(int length) {
105+
public ReadableBuffer readBytes(int length) {
106106
return buf.readBytes(length);
107107
}
108108

0 commit comments

Comments
 (0)