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;
}
}
}
});
}
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;
}
}
}
});
}
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);
}
Aggregations