diff --git a/core/src/main/java/io/grpc/internal/AbstractClientStream.java b/core/src/main/java/io/grpc/internal/AbstractClientStream.java deleted file mode 100644 index 4ea3467c26..0000000000 --- a/core/src/main/java/io/grpc/internal/AbstractClientStream.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2014, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package io.grpc.internal; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import io.grpc.Metadata; -import io.grpc.Status; -import java.io.InputStream; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * The abstract base class for {@link ClientStream} implementations. - */ -public abstract class AbstractClientStream extends AbstractStream - implements ClientStream { - - private static final Logger log = Logger.getLogger(AbstractClientStream.class.getName()); - - private final StatsTraceContext statsTraceCtx; - private ClientStreamListener listener; - private boolean listenerClosed; - - // Stored status & trailers to report when deframer completes or - // transportReportStatus is directly called. - private Status status; - private Metadata trailers; - private Runnable closeListenerTask; - private volatile boolean cancelled; - - protected AbstractClientStream(WritableBufferAllocator bufferAllocator, int maxMessageSize, - StatsTraceContext statsTraceCtx) { - super(bufferAllocator, maxMessageSize, statsTraceCtx); - this.statsTraceCtx = checkNotNull(statsTraceCtx, "statsTraceCtx"); - } - - @Override - public void setMaxInboundMessageSize(int maxSize) { - setMaxInboundMessageSizeProtected(maxSize); - } - - @Override - public void setMaxOutboundMessageSize(int maxSize) { - setMaxOutboundMessageSizeProtected(maxSize); - } - - @Override - protected final ClientStreamListener listener() { - return listener; - } - - /** - * Indicates that the stream may proceed to do traffic. Sub classes should override and invoke - * this method after they have been created. - */ - @Override - public void start(ClientStreamListener listener) { - checkState(this.listener == null, "stream already started"); - this.listener = checkNotNull(listener, "listener"); - } - - @Override - protected void receiveMessage(InputStream is) { - if (!listenerClosed) { - checkState(listener != null, "stream not started"); - listener.messageRead(is); - } - } - - /** - * The transport implementation has detected a protocol error on the stream. Transports are - * responsible for properly closing streams when protocol errors occur. - * - * @param errorStatus the error to report - * @param metadata any metadata received - */ - protected void inboundTransportError(Status errorStatus, Metadata metadata) { - Preconditions.checkNotNull(metadata, "metadata"); - if (inboundPhase() == Phase.STATUS) { - log.log(Level.INFO, "Received transport error on closed stream {0} {1}", - new Object[]{id(), errorStatus}); - return; - } - // For transport errors we immediately report status to the application layer - // and do not wait for additional payloads. - transportReportStatus(errorStatus, false, metadata); - } - - /** - * Called by transport implementations when they receive headers. - * - * @param headers the parsed headers - */ - protected void inboundHeadersReceived(Metadata headers) { - checkState(listener != null, "stream not started"); - if (inboundPhase() == Phase.STATUS) { - log.log(Level.INFO, "Received headers on closed stream {0} {1}", - new Object[]{id(), headers}); - } - - inboundPhase(Phase.MESSAGE); - listener.headersRead(headers); - } - - /** - * Processes the contents of a received data frame from the server. - * - * @param frame the received data frame. Its ownership is transferred to this method. - */ - protected void inboundDataReceived(ReadableBuffer frame) { - Preconditions.checkNotNull(frame, "frame"); - boolean needToCloseFrame = true; - try { - if (inboundPhase() == Phase.STATUS) { - return; - } - if (inboundPhase() == Phase.HEADERS) { - // Have not received headers yet so error - inboundTransportError(Status.INTERNAL - .withDescription("headers not received before payload"), new Metadata()); - return; - } - inboundPhase(Phase.MESSAGE); - - needToCloseFrame = false; - deframe(frame, false); - } finally { - if (needToCloseFrame) { - frame.close(); - } - } - } - - @Override - protected void inboundDeliveryPaused() { - runCloseListenerTask(); - } - - @Override - protected final void deframeFailed(Throwable cause) { - cancel(Status.fromThrowable(cause)); - } - - /** - * Processes the trailers and status from the server. - * - * @param trailers the received trailers - * @param status the status extracted from the trailers - */ - protected void inboundTrailersReceived(Metadata trailers, Status status) { - Preconditions.checkNotNull(trailers, "trailers"); - if (inboundPhase() == Phase.STATUS) { - log.log(Level.INFO, "Received trailers on closed stream {0}\n {1}\n {2}", - new Object[]{id(), status, trailers}); - } - // Stash the status & trailers so they can be delivered by the deframer calls - // remoteEndClosed - this.status = status; - this.trailers = trailers; - deframe(ReadableBuffers.empty(), true); - } - - @Override - protected void remoteEndClosed() { - transportReportStatus(status, true, trailers); - } - - @Override - protected final void internalSendFrame(WritableBuffer frame, boolean endOfStream, boolean flush) { - Preconditions.checkArgument(frame != null || endOfStream, "null frame before EOS"); - sendFrame(frame, endOfStream, flush); - } - - /** - * Sends an outbound frame to the remote end point. - * - * @param frame a buffer containing the chunk of data to be sent or {@code null} if the framer is - * closing and has no data to send. - * @param endOfStream if {@code true} indicates that no more data will be sent on the stream by - * this endpoint. - * @param flush {@code true} if more data may not be arriving soon - */ - protected abstract void sendFrame(WritableBuffer frame, boolean endOfStream, boolean flush); - - /** - * Report stream closure with status to the application layer if not already reported. This method - * must be called from the transport thread. - * - * @param newStatus the new status to set - * @param stopDelivery if {@code true}, interrupts any further delivery of inbound messages that - * may already be queued up in the deframer. If {@code false}, the listener will be - * notified immediately after all currently completed messages in the deframer have been - * delivered to the application. - * @param trailers new instance of {@code Trailers}, either empty or those returned by the server - */ - public void transportReportStatus(final Status newStatus, boolean stopDelivery, - final Metadata trailers) { - Preconditions.checkNotNull(newStatus, "newStatus"); - - boolean closingLater = closeListenerTask != null && !stopDelivery; - if (listenerClosed || closingLater) { - // We already closed (or are about to close) the listener. - return; - } - - inboundPhase(Phase.STATUS); - status = newStatus; - closeListenerTask = null; - - // Determine if the deframer is stalled (i.e. currently has no complete messages to deliver). - boolean deliveryStalled = isDeframerStalled(); - - if (stopDelivery || deliveryStalled) { - // Close the listener immediately. - closeListener(newStatus, trailers); - } else { - // Delay close until inboundDeliveryStalled() - closeListenerTask = newCloseListenerTask(newStatus, trailers); - } - } - - /** - * Creates a new {@link Runnable} to close the listener with the given status/trailers. - */ - private Runnable newCloseListenerTask(final Status status, final Metadata trailers) { - return new Runnable() { - @Override - public void run() { - closeListener(status, trailers); - } - }; - } - - /** - * Closes the listener if not previously closed. - * - * @throws IllegalStateException if the call has not yet been started. - */ - private void closeListener(Status newStatus, Metadata trailers) { - checkState(listener != null, "stream not started"); - if (!listenerClosed) { - listenerClosed = true; - closeDeframer(); - statsTraceCtx.streamClosed(newStatus); - listener.closed(newStatus, trailers); - } - } - - /** - * Executes the pending listener close task, if one exists. - */ - private void runCloseListenerTask() { - if (closeListenerTask != null) { - closeListenerTask.run(); - closeListenerTask = null; - } - } - - @Override - public final void halfClose() { - if (outboundPhase(Phase.STATUS) != Phase.STATUS) { - closeFramer(); - } - } - - /** - * Cancel the stream. Called by the application layer, never called by the transport. - */ - @Override - public final void cancel(Status reason) { - checkArgument(!reason.isOk(), "Should not cancel with OK status"); - cancelled = true; - sendCancel(reason); - dispose(); - } - - @Override - public final boolean isReady() { - return !cancelled && super.isReady(); - } - - /** - * Cancel the stream and send a stream cancellation message to the remote server, if necessary. - * Can be called by either the application or transport layers. This method is safe to be called - * at any time and multiple times. - */ - protected abstract void sendCancel(Status reason); - - @Override - protected MoreObjects.ToStringHelper toStringHelper() { - MoreObjects.ToStringHelper toStringHelper = super.toStringHelper(); - if (status != null) { - toStringHelper.add("status", status); - } - return toStringHelper; - } - - @Override - public boolean isClosed() { - return super.isClosed() || listenerClosed; - } -} diff --git a/core/src/main/java/io/grpc/internal/AbstractStream.java b/core/src/main/java/io/grpc/internal/AbstractStream.java deleted file mode 100644 index 84295e441d..0000000000 --- a/core/src/main/java/io/grpc/internal/AbstractStream.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright 2014, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package io.grpc.internal; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.MoreObjects; -import io.grpc.Codec; -import io.grpc.Compressor; -import io.grpc.Decompressor; -import java.io.InputStream; -import javax.annotation.concurrent.GuardedBy; - -/** - * Abstract base class for {@link Stream} implementations. - */ -public abstract class AbstractStream implements Stream { - /** - * The default number of queued bytes for a given stream, below which - * {@link StreamListener#onReady()} will be called. - */ - public static final int DEFAULT_ONREADY_THRESHOLD = 32 * 1024; - - public static final int ABSENT_ID = -1; - - /** - * Indicates the phase of the GRPC stream in one direction. - */ - protected enum Phase { - HEADERS, MESSAGE, STATUS - } - - private final MessageFramer framer; - private final MessageDeframer deframer; - - /** - * Inbound phase is exclusively written to by the transport thread. - */ - private Phase inboundPhase = Phase.HEADERS; - - /** - * Outbound phase is exclusively written to by the application thread. - */ - private Phase outboundPhase = Phase.HEADERS; - - /** - * The number of queued bytes for a given stream, below which {@link StreamListener#onReady()} - * will be called. - */ - private int onReadyThreshold = DEFAULT_ONREADY_THRESHOLD; - - /** - * The number of bytes currently queued, waiting to be sent. When this falls below - * onReadyThreshold, {@link StreamListener#onReady()} will be called. - */ - private int numSentBytesQueued; - - /** - * Indicates the stream has been created on the connection. This implies that the stream is no - * longer limited by MAX_CONCURRENT_STREAMS. - */ - @GuardedBy("onReadyLock") - private boolean allocated; - - private final Object onReadyLock = new Object(); - - @VisibleForTesting - class FramerSink implements MessageFramer.Sink { - @Override - public void deliverFrame(WritableBuffer frame, boolean endOfStream, boolean flush) { - internalSendFrame(frame, endOfStream, flush); - } - } - - @VisibleForTesting - class DeframerListener implements MessageDeframer.Listener { - @Override - public void bytesRead(int numBytes) { - returnProcessedBytes(numBytes); - } - - @Override - public void messageRead(InputStream input) { - receiveMessage(input); - } - - @Override - public void deliveryStalled() { - inboundDeliveryPaused(); - } - - @Override - public void endOfStream() { - remoteEndClosed(); - } - } - - AbstractStream(WritableBufferAllocator bufferAllocator, int maxMessageSize, - StatsTraceContext statsTraceCtx) { - framer = new MessageFramer(new FramerSink(), bufferAllocator, statsTraceCtx); - deframer = new MessageDeframer(new DeframerListener(), Codec.Identity.NONE, maxMessageSize, - statsTraceCtx, getClass().getName()); - } - - protected final void setMaxInboundMessageSizeProtected(int maxSize) { - deframer.setMaxInboundMessageSize(maxSize); - } - - protected final void setMaxOutboundMessageSizeProtected(int maxSize) { - framer.setMaxOutboundMessageSize(maxSize); - } - - @VisibleForTesting - AbstractStream(MessageFramer framer, MessageDeframer deframer) { - this.framer = framer; - this.deframer = deframer; - } - - /** - * Override this method to provide a stream listener. - */ - protected abstract StreamListener listener(); - - /** - * Returns the internal ID for this stream. Note that ID can be {@link #ABSENT_ID} for client - * streams as the transport may defer creating the stream to the remote side until it has a - * payload or metadata to send. - */ - public abstract int id(); - - /** - * The number of queued bytes for a given stream, below which {@link StreamListener#onReady()} - * will be called. Defaults to {@link #DEFAULT_ONREADY_THRESHOLD}. - */ - public int getOnReadyThreshold() { - synchronized (onReadyLock) { - return onReadyThreshold; - } - } - - @Override - public void writeMessage(InputStream message) { - checkNotNull(message, "message"); - outboundPhase(Phase.MESSAGE); - if (!framer.isClosed()) { - framer.writePayload(message); - } - } - - @Override - public final void setMessageCompression(boolean enable) { - framer.setMessageCompression(enable); - } - - @Override - public final void flush() { - if (!framer.isClosed()) { - framer.flush(); - } - } - - @Override - public boolean isReady() { - if (listener() != null && outboundPhase() != Phase.STATUS) { - synchronized (onReadyLock) { - return allocated && numSentBytesQueued < onReadyThreshold; - } - } - return false; - } - - /** - * Closes the underlying framer. - * - *
No-op if the framer has already been closed. - */ - final void closeFramer() { - if (!framer.isClosed()) { - framer.close(); - } - } - - /** - * Frees any resources associated with this stream. Subclass implementations must call this - * version. - * - *
NOTE: Can be called by both the transport thread and the application thread. Transport
- * threads need to dispose when the remote side has terminated the stream. Application threads
- * will dispose when the application decides to close the stream as part of normal processing.
- */
- public void dispose() {
- framer.dispose();
- }
-
- /**
- * Sends an outbound frame to the remote end point.
- *
- * @param frame a buffer containing the chunk of data to be sent.
- * @param endOfStream if {@code true} indicates that no more data will be sent on the stream by
- * this endpoint.
- * @param flush {@code true} if more data may not be arriving soon
- */
- protected abstract void internalSendFrame(WritableBuffer frame, boolean endOfStream,
- boolean flush);
-
- /**
- * Handles a message that was just deframed.
- *
- * @param is the stream containing the message
- */
- protected abstract void receiveMessage(InputStream is);
-
- /**
- * Handles the event that the deframer has no pending deliveries.
- */
- protected abstract void inboundDeliveryPaused();
-
- /**
- * Handles the event that the deframer has reached end of stream.
- */
- protected abstract void remoteEndClosed();
-
- /**
- * Returns the given number of processed bytes back to inbound flow control to enable receipt of
- * more data.
- */
- protected abstract void returnProcessedBytes(int processedBytes);
-
- /**
- * Called when a {@link #deframe(ReadableBuffer, boolean)} operation failed.
- *
- * @param cause the actual failure
- */
- protected abstract void deframeFailed(Throwable cause);
-
- /**
- * Closes this deframer and frees any resources. After this method is called, additional calls
- * will have no effect.
- */
- protected final void closeDeframer() {
- deframer.close();
- }
-
- /**
- * Called to parse a received frame and attempt delivery of any completed
- * messages. Must be called from the transport thread.
- */
- protected final void deframe(ReadableBuffer frame, boolean endOfStream) {
- try {
- deframer.deframe(frame, endOfStream);
- } catch (Throwable t) {
- deframeFailed(t);
- }
- }
-
- /**
- * Indicates whether delivery is currently stalled, pending receipt of more data.
- */
- protected final boolean isDeframerStalled() {
- return deframer.isStalled();
- }
-
- /**
- * Called to request the given number of messages from the deframer. Must be called
- * from the transport thread.
- */
- protected final void requestMessagesFromDeframer(int numMessages) {
- try {
- deframer.request(numMessages);
- } catch (Throwable t) {
- deframeFailed(t);
- }
- }
-
- @Override
- public final void setCompressor(Compressor compressor) {
- framer.setCompressor(checkNotNull(compressor, "compressor"));
- }
-
- @Override
- public final void setDecompressor(Decompressor decompressor) {
- deframer.setDecompressor(checkNotNull(decompressor, "decompressor"));
- }
-
- /**
- * Event handler to be called by the subclass when the stream's headers have passed any connection
- * flow control (i.e., MAX_CONCURRENT_STREAMS). It may call the listener's {@link
- * StreamListener#onReady()} handler if appropriate. This must be called from the transport
- * thread, since the listener may be called back directly.
- */
- protected final void onStreamAllocated() {
- checkState(listener() != null);
- synchronized (onReadyLock) {
- checkState(!allocated, "Already allocated");
- allocated = true;
- }
- notifyIfReady();
- }
-
- /**
- * Event handler to be called by the subclass when a number of bytes are being queued for sending
- * to the remote endpoint.
- *
- * @param numBytes the number of bytes being sent.
- */
- protected final void onSendingBytes(int numBytes) {
- synchronized (onReadyLock) {
- numSentBytesQueued += numBytes;
- }
- }
-
- /**
- * Event handler to be called by the subclass when a number of bytes has been sent to the remote
- * endpoint. May call back the listener's {@link StreamListener#onReady()} handler if appropriate.
- * This must be called from the transport thread, since the listener may be called back directly.
- *
- * @param numBytes the number of bytes that were sent.
- */
- protected final void onSentBytes(int numBytes) {
- boolean doNotify;
- synchronized (onReadyLock) {
- boolean belowThresholdBefore = numSentBytesQueued < onReadyThreshold;
- numSentBytesQueued -= numBytes;
- boolean belowThresholdAfter = numSentBytesQueued < onReadyThreshold;
- doNotify = !belowThresholdBefore && belowThresholdAfter;
- }
- if (doNotify) {
- notifyIfReady();
- }
- }
-
- @VisibleForTesting
- final void notifyIfReady() {
- boolean doNotify = false;
- synchronized (onReadyLock) {
- doNotify = isReady();
- }
- if (doNotify) {
- listener().onReady();
- }
- }
-
- final Phase inboundPhase() {
- return inboundPhase;
- }
-
- /**
- * Transitions the inbound phase to the given phase and returns the previous phase.
- *
- * @throws IllegalStateException if the transition is disallowed
- */
- final Phase inboundPhase(Phase nextPhase) {
- Phase tmp = inboundPhase;
- inboundPhase = verifyNextPhase(inboundPhase, nextPhase);
- return tmp;
- }
-
- final Phase outboundPhase() {
- return outboundPhase;
- }
-
- /**
- * Transitions the outbound phase to the given phase and returns the previous phase.
- *
- * @throws IllegalStateException if the transition is disallowed
- */
- final Phase outboundPhase(Phase nextPhase) {
- Phase tmp = outboundPhase;
- outboundPhase = verifyNextPhase(outboundPhase, nextPhase);
- return tmp;
- }
-
- @VisibleForTesting
- Phase verifyNextPhase(Phase currentPhase, Phase nextPhase) {
- if (nextPhase.ordinal() < currentPhase.ordinal()) {
- throw new IllegalStateException(
- String.format("Cannot transition phase from %s to %s", currentPhase, nextPhase));
- }
- return nextPhase;
- }
-
- /**
- * Returns {@code true} if the stream can receive data from its remote peer.
- */
- public boolean canReceive() {
- return inboundPhase() != Phase.STATUS;
- }
-
- /**
- * Returns {@code true} if the stream can send data to its remote peer.
- */
- public boolean canSend() {
- return outboundPhase() != Phase.STATUS;
- }
-
- /**
- * Whether the stream is fully closed. Note that this method is not thread-safe as {@code
- * inboundPhase} and {@code outboundPhase} are mutated in different threads. Tests must account
- * for thread coordination when calling.
- */
- @VisibleForTesting
- public boolean isClosed() {
- return inboundPhase() == Phase.STATUS && outboundPhase() == Phase.STATUS;
- }
-
- @Override
- public String toString() {
- return toStringHelper().toString();
- }
-
- protected MoreObjects.ToStringHelper toStringHelper() {
- return MoreObjects.toStringHelper(this)
- .add("id", id())
- .add("inboundPhase", inboundPhase().name())
- .add("outboundPhase", outboundPhase().name());
- }
-}
diff --git a/core/src/main/java/io/grpc/internal/AbstractStream2.java b/core/src/main/java/io/grpc/internal/AbstractStream2.java
index d50a027962..df50d1d7cb 100644
--- a/core/src/main/java/io/grpc/internal/AbstractStream2.java
+++ b/core/src/main/java/io/grpc/internal/AbstractStream2.java
@@ -34,6 +34,7 @@ package io.grpc.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import com.google.common.annotations.VisibleForTesting;
import io.grpc.Codec;
import io.grpc.Compressor;
import io.grpc.Decompressor;
@@ -119,7 +120,8 @@ public abstract class AbstractStream2 implements Stream {
* The default number of queued bytes for a given stream, below which
* {@link StreamListener#onReady()} will be called.
*/
- private static final int DEFAULT_ONREADY_THRESHOLD = 32 * 1024;
+ @VisibleForTesting
+ public static final int DEFAULT_ONREADY_THRESHOLD = 32 * 1024;
private final MessageDeframer deframer;
private final Object onReadyLock = new Object();
diff --git a/core/src/main/java/io/grpc/internal/Http2ClientStream.java b/core/src/main/java/io/grpc/internal/Http2ClientStream.java
deleted file mode 100644
index e68dbdf3f9..0000000000
--- a/core/src/main/java/io/grpc/internal/Http2ClientStream.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright 2014, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package io.grpc.internal;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import io.grpc.InternalMetadata;
-import io.grpc.Metadata;
-import io.grpc.Status;
-import java.nio.charset.Charset;
-import javax.annotation.Nullable;
-
-/**
- * Base implementation for client streams using HTTP2 as the transport.
- */
-public abstract class Http2ClientStream extends AbstractClientStream {
-
- /**
- * Metadata marshaller for HTTP status lines.
- */
- private static final InternalMetadata.TrustedAsciiMarshaller