[#965] Allow to adjust the SO_TIMEOUT on the fly

This commit is contained in:
Norman Maurer 2013-01-21 11:47:59 +01:00
parent 29bed32a89
commit 7316a3c65c
10 changed files with 298 additions and 15 deletions

View File

@ -59,6 +59,8 @@ public class ChannelOption<T> extends UniqueName {
new ChannelOption<Integer>("SO_LINGER");
public static final ChannelOption<Integer> SO_BACKLOG =
new ChannelOption<Integer>("SO_BACKLOG");
public static final ChannelOption<Integer> SO_TIMEOUT =
new ChannelOption<Integer>("SO_TIMEOUT");
public static final ChannelOption<Integer> IP_TOS =
new ChannelOption<Integer>("IP_TOS");

View File

@ -33,7 +33,7 @@ import static io.netty.channel.ChannelOption.*;
public class DefaultServerSocketChannelConfig extends DefaultChannelConfig
implements ServerSocketChannelConfig {
private final ServerSocket javaSocket;
protected final ServerSocket javaSocket;
private volatile int backlog = NetUtil.SOMAXCONN;
/**

View File

@ -32,7 +32,7 @@ import static io.netty.channel.ChannelOption.*;
public class DefaultSocketChannelConfig extends DefaultChannelConfig
implements SocketChannelConfig {
private final Socket javaSocket;
protected final Socket javaSocket;
private volatile boolean allowHalfClosure;
/**

View File

@ -49,14 +49,25 @@ public abstract class AbstractOioByteChannel extends AbstractOioChannel {
return METADATA;
}
@Override
protected void doRead() {
/**
* Check if the input was shutdown and if so return {@code true}. The default implementation sleeps also for
* {@link #SO_TIMEOUT} milliseconds to simulate some blocking.
*/
protected boolean checkInputShutdown() {
if (inputShutdown) {
try {
Thread.sleep(SO_TIMEOUT);
} catch (InterruptedException e) {
// ignore
}
return true;
}
return false;
}
@Override
protected void doRead() {
if (checkInputShutdown()) {
return;
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.channel.socket.oio;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.DefaultServerSocketChannelConfig;
import io.netty.channel.socket.ServerSocketChannel;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Map;
import static io.netty.channel.ChannelOption.SO_TIMEOUT;
/**
* Default {@link OioServerSocketChannelConfig} implementation
*/
public class DefaultOioServerSocketChannelConfig extends DefaultServerSocketChannelConfig implements
OioServerSocketChannelConfig {
public DefaultOioServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) {
super(channel, javaSocket);
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(), SO_TIMEOUT);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(ChannelOption<T> option) {
if (option == SO_TIMEOUT) {
return (T) Integer.valueOf(getSoTimeout());
}
return super.getOption(option);
}
@Override
public <T> boolean setOption(ChannelOption<T> option, T value) {
validate(option, value);
if (option == SO_TIMEOUT) {
setSoTimeout((Integer) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public void setSoTimeout(int timeout) {
try {
javaSocket.setSoTimeout(timeout);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public int getSoTimeout() {
try {
return javaSocket.getSoTimeout();
} catch (IOException e) {
throw new ChannelException(e);
}
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.channel.socket.oio;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.DefaultSocketChannelConfig;
import io.netty.channel.socket.SocketChannel;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import static io.netty.channel.ChannelOption.*;
/**
* Default {@link OioSocketChannelConfig} implementation
*/
public class DefaultOioSocketChannelConfig extends DefaultSocketChannelConfig implements OioSocketChannelConfig {
public DefaultOioSocketChannelConfig(SocketChannel channel, Socket javaSocket) {
super(channel, javaSocket);
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(), SO_TIMEOUT);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(ChannelOption<T> option) {
if (option == SO_TIMEOUT) {
return (T) Integer.valueOf(getSoTimeout());
}
return super.getOption(option);
}
@Override
public <T> boolean setOption(ChannelOption<T> option, T value) {
validate(option, value);
if (option == SO_TIMEOUT) {
setSoTimeout((Integer) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public void setSoTimeout(int timeout) {
try {
javaSocket.setSoTimeout(timeout);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public int getSoTimeout() {
try {
return javaSocket.getSoTimeout();
} catch (IOException e) {
throw new ChannelException(e);
}
}
}

View File

@ -19,9 +19,7 @@ import io.netty.buffer.BufType;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.socket.DefaultServerSocketChannelConfig;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.ServerSocketChannelConfig;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
@ -57,7 +55,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
final ServerSocket socket;
final Lock shutdownLock = new ReentrantLock();
private final ServerSocketChannelConfig config;
private final OioServerSocketChannelConfig config;
/**
* Create a new instance with an new {@link Socket}
@ -106,9 +104,8 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
}
}
}
this.socket = socket;
config = new DefaultServerSocketChannelConfig(this, socket);
config = new DefaultOioServerSocketChannelConfig(this, socket);
}
@Override
@ -117,7 +114,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
}
@Override
public ServerSocketChannelConfig config() {
public OioServerSocketChannelConfig config() {
return config;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.channel.socket.oio;
import io.netty.channel.socket.ServerSocketChannelConfig;
/**
* A {@link ServerSocketChannelConfig} for a {@link OioServerSocketChannel}.
*
* <h3>Available options</h3>
*
* In addition to the options provided by {@link ServerSocketChannelConfig},
* {@link OioServerSocketChannelConfig} allows the following options in the
* option map:
*
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_TIMEOUT}</td><td>{@link #setSoTimeout(int)}</td>
* </tr>
* </table>
*/
public interface OioServerSocketChannelConfig extends ServerSocketChannelConfig {
/**
* Sets the maximal time a operation on the underlying socket may block.
*/
void setSoTimeout(int timeout);
/**
* Returns the maximal time a operation on the underlying socket may block.
*/
int getSoTimeout();
}

View File

@ -21,10 +21,8 @@ import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoop;
import io.netty.channel.socket.DefaultSocketChannelConfig;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.SocketChannelConfig;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
@ -44,7 +42,7 @@ public class OioSocketChannel extends StreamOioByteChannel
InternalLoggerFactory.getInstance(OioSocketChannel.class);
private final Socket socket;
private final SocketChannelConfig config;
private final OioSocketChannelConfig config;
/**
* Create a new instance with an new {@link Socket}
@ -73,7 +71,7 @@ public class OioSocketChannel extends StreamOioByteChannel
public OioSocketChannel(Channel parent, Integer id, Socket socket) {
super(parent, id);
this.socket = socket;
config = new DefaultSocketChannelConfig(this, socket);
config = new DefaultOioSocketChannelConfig(this, socket);
boolean success = false;
try {
@ -101,7 +99,7 @@ public class OioSocketChannel extends StreamOioByteChannel
}
@Override
public SocketChannelConfig config() {
public OioSocketChannelConfig config() {
return config;
}
@ -216,4 +214,17 @@ public class OioSocketChannel extends StreamOioByteChannel
protected void doClose() throws Exception {
socket.close();
}
@Override
protected boolean checkInputShutdown() {
if (isInputShutdown()) {
try {
Thread.sleep(config().getSoTimeout());
} catch (Throwable e) {
// ignore
}
return true;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.channel.socket.oio;
import io.netty.channel.ChannelConfig;
import io.netty.channel.socket.SocketChannelConfig;
/**
* A {@link ChannelConfig} for a {@link OioSocketChannel}.
*
* <h3>Available options</h3>
*
* In addition to the options provided by {@link SocketChannelConfig},
* {@link OioSocketChannelConfig} allows the following options in the
* option map:
*
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_TIMEOUT}</td><td>{@link #setSoTimeout(int)}</td>
* </tr>
* </table>
*/
public interface OioSocketChannelConfig extends SocketChannelConfig {
/**
* Sets the maximal time a operation on the underlying socket may block.
*/
void setSoTimeout(int timeout);
/**
* Returns the maximal time a operation on the underlying socket may block.
*/
int getSoTimeout();
}