/*
* Copyright 2008-present MongoDB, Inc.
* Copyright 2012 The Netty Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mongodb.connection.netty;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.ReadTimeoutException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static com.mongodb.assertions.Assertions.isTrue;
import static com.mongodb.assertions.Assertions.isTrueArgument;
Passes a ReadTimeoutException
if the time between a scheduleTimeout
and removeTimeout
is longer than the set timeout. /**
* Passes a {@link ReadTimeoutException} if the time between a {@link #scheduleTimeout} and {@link #removeTimeout} is longer than the set
* timeout.
*/
final class ReadTimeoutHandler extends ChannelInboundHandlerAdapter {
private final long readTimeout;
private volatile ScheduledFuture<?> timeout;
ReadTimeoutHandler(final long readTimeout) {
isTrueArgument("readTimeout must be greater than zero.", readTimeout > 0);
this.readTimeout = readTimeout;
}
void scheduleTimeout(final ChannelHandlerContext ctx) {
isTrue("Handler called from the eventLoop", ctx.channel().eventLoop().inEventLoop());
if (timeout == null) {
timeout = ctx.executor().schedule(new ReadTimeoutTask(ctx), readTimeout, TimeUnit.MILLISECONDS);
}
}
void removeTimeout(final ChannelHandlerContext ctx) {
isTrue("Handler called from the eventLoop", ctx.channel().eventLoop().inEventLoop());
if (timeout != null) {
timeout.cancel(false);
timeout = null;
}
}
private static final class ReadTimeoutTask implements Runnable {
private final ChannelHandlerContext ctx;
ReadTimeoutTask(final ChannelHandlerContext ctx) {
this.ctx = ctx;
}
@Override
public void run() {
if (ctx.channel().isOpen()) {
try {
ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE);
ctx.close();
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
}
}
}
}