Search in sources :

Example 1 with Http2Ping

use of io.grpc.internal.Http2Ping in project grpc-java by grpc.

the class NettyClientHandler method sendPingFrame.

/**
   * Sends a PING frame. If a ping operation is already outstanding, the callback in the message is
   * registered to be called when the existing operation completes, and no new frame is sent.
   */
private void sendPingFrame(ChannelHandlerContext ctx, SendPingCommand msg, ChannelPromise promise) {
    // Don't check lifecycleManager.getShutdownStatus() since we want to allow pings after shutdown
    // but before termination. After termination, messages will no longer arrive because the
    // pipeline clears all handlers on channel close.
    PingCallback callback = msg.callback();
    Executor executor = msg.executor();
    // any outstanding operation
    if (ping != null) {
        promise.setSuccess();
        ping.addCallback(callback, executor);
        return;
    }
    // Use a new promise to prevent calling the callback twice on write failure: here and in
    // NettyClientTransport.ping(). It may appear strange, but it will behave the same as if
    // ping != null above.
    promise.setSuccess();
    promise = ctx().newPromise();
    // set outstanding operation
    long data = USER_PING_PAYLOAD;
    ByteBuf buffer = ctx.alloc().buffer(8);
    buffer.writeLong(data);
    Stopwatch stopwatch = Stopwatch.createStarted(ticker);
    ping = new Http2Ping(data, stopwatch);
    ping.addCallback(callback, executor);
    // and then write the ping
    encoder().writePing(ctx, false, buffer, promise);
    ctx.flush();
    final Http2Ping finalPing = ping;
    promise.addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (!future.isSuccess()) {
                Throwable cause = future.cause();
                if (cause instanceof ClosedChannelException) {
                    cause = lifecycleManager.getShutdownThrowable();
                    if (cause == null) {
                        cause = Status.UNKNOWN.withDescription("Ping failed but for unknown reason.").withCause(future.cause()).asException();
                    }
                }
                finalPing.failed(cause);
                if (ping == finalPing) {
                    ping = null;
                }
            }
        }
    });
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) ClosedChannelException(java.nio.channels.ClosedChannelException) Executor(java.util.concurrent.Executor) Http2Ping(io.grpc.internal.Http2Ping) Stopwatch(com.google.common.base.Stopwatch) PingCallback(io.grpc.internal.ClientTransport.PingCallback) ByteBuf(io.netty.buffer.ByteBuf) ChannelFutureListener(io.netty.channel.ChannelFutureListener) Http2Exception(io.netty.handler.codec.http2.Http2Exception) StatusException(io.grpc.StatusException) ClosedChannelException(java.nio.channels.ClosedChannelException)

Example 2 with Http2Ping

use of io.grpc.internal.Http2Ping in project grpc-java by grpc.

the class NettyClientHandler method sendPingFrameTraced.

/**
 * Sends a PING frame. If a ping operation is already outstanding, the callback in the message is
 * registered to be called when the existing operation completes, and no new frame is sent.
 */
private void sendPingFrameTraced(ChannelHandlerContext ctx, SendPingCommand msg, ChannelPromise promise) {
    // Don't check lifecycleManager.getShutdownStatus() since we want to allow pings after shutdown
    // but before termination. After termination, messages will no longer arrive because the
    // pipeline clears all handlers on channel close.
    PingCallback callback = msg.callback();
    Executor executor = msg.executor();
    // any outstanding operation
    if (ping != null) {
        promise.setSuccess();
        ping.addCallback(callback, executor);
        return;
    }
    // Use a new promise to prevent calling the callback twice on write failure: here and in
    // NettyClientTransport.ping(). It may appear strange, but it will behave the same as if
    // ping != null above.
    promise.setSuccess();
    promise = ctx().newPromise();
    // set outstanding operation
    long data = USER_PING_PAYLOAD;
    Stopwatch stopwatch = stopwatchFactory.get();
    stopwatch.start();
    ping = new Http2Ping(data, stopwatch);
    ping.addCallback(callback, executor);
    // and then write the ping
    encoder().writePing(ctx, false, USER_PING_PAYLOAD, promise);
    ctx.flush();
    final Http2Ping finalPing = ping;
    promise.addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (future.isSuccess()) {
                transportTracer.reportKeepAliveSent();
            } else {
                Throwable cause = future.cause();
                if (cause instanceof ClosedChannelException) {
                    cause = lifecycleManager.getShutdownThrowable();
                    if (cause == null) {
                        cause = Status.UNKNOWN.withDescription("Ping failed but for unknown reason.").withCause(future.cause()).asException();
                    }
                }
                finalPing.failed(cause);
                if (ping == finalPing) {
                    ping = null;
                }
            }
        }
    });
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) ClosedChannelException(java.nio.channels.ClosedChannelException) Executor(java.util.concurrent.Executor) Http2Ping(io.grpc.internal.Http2Ping) Stopwatch(com.google.common.base.Stopwatch) PingCallback(io.grpc.internal.ClientTransport.PingCallback) ChannelFutureListener(io.netty.channel.ChannelFutureListener) Http2Exception(io.netty.handler.codec.http2.Http2Exception) StatusException(io.grpc.StatusException) ClosedChannelException(java.nio.channels.ClosedChannelException)

Example 3 with Http2Ping

use of io.grpc.internal.Http2Ping in project grpc-java by grpc.

the class OkHttpClientTransport method ping.

@Override
public void ping(final PingCallback callback, Executor executor) {
    long data = 0;
    Http2Ping p;
    boolean writePing;
    synchronized (lock) {
        checkState(frameWriter != null);
        if (stopped) {
            Http2Ping.notifyFailed(callback, executor, getPingFailure());
            return;
        }
        if (ping != null) {
            // we only allow one outstanding ping at a time, so just add the callback to
            // any outstanding operation
            p = ping;
            writePing = false;
        } else {
            // set outstanding operation and then write the ping after releasing lock
            data = random.nextLong();
            Stopwatch stopwatch = stopwatchFactory.get();
            stopwatch.start();
            p = ping = new Http2Ping(data, stopwatch);
            writePing = true;
            transportTracer.reportKeepAliveSent();
        }
        if (writePing) {
            frameWriter.ping(false, (int) (data >>> 32), (int) data);
        }
    }
    // If transport concurrently failed/stopped since we released the lock above, this could
    // immediately invoke callback (which we shouldn't do while holding a lock)
    p.addCallback(callback, executor);
}
Also used : Http2Ping(io.grpc.internal.Http2Ping) Stopwatch(com.google.common.base.Stopwatch)

Aggregations

Stopwatch (com.google.common.base.Stopwatch)3 Http2Ping (io.grpc.internal.Http2Ping)3 StatusException (io.grpc.StatusException)2 PingCallback (io.grpc.internal.ClientTransport.PingCallback)2 ChannelFuture (io.netty.channel.ChannelFuture)2 ChannelFutureListener (io.netty.channel.ChannelFutureListener)2 Http2Exception (io.netty.handler.codec.http2.Http2Exception)2 ClosedChannelException (java.nio.channels.ClosedChannelException)2 Executor (java.util.concurrent.Executor)2 ByteBuf (io.netty.buffer.ByteBuf)1