Correctly support SO_TIMEOUT for OioDatagramChannel

Motivation:

We need to support SO_TIMEOUT for the OioDatagramChannel but we miss this atm as we not have special handling for it in the DatagramChannelConfig impl that we use. Because of this the following log lines showed up when running the testsuite:

20:31:26.299 [main] WARN  io.netty.bootstrap.Bootstrap - Unknown channel option 'SO_TIMEOUT' for channel '[id: 0x7cb9183c]'

Modifications:

- Add OioDatagramChannelConfig and impl
- Correctly set SO_TIMEOUT in testsuite

Result:

Support SO_TIMEOUT for OioDatagramChannel and so faster execution of datagram related tests in the testsuite
This commit is contained in:
Norman Maurer 2017-08-03 20:36:41 +02:00
parent bdb0a39c8a
commit f8b495b2f2
5 changed files with 316 additions and 4 deletions

View File

@ -134,7 +134,8 @@ public class SocketTestPermutation {
new BootstrapFactory<Bootstrap>() { new BootstrapFactory<Bootstrap>() {
@Override @Override
public Bootstrap newInstance() { public Bootstrap newInstance() {
return new Bootstrap().group(oioWorkerGroup).channel(OioDatagramChannel.class); return new Bootstrap().group(oioWorkerGroup).channel(OioDatagramChannel.class)
.option(ChannelOption.SO_TIMEOUT, OIO_SO_TIMEOUT);
} }
} }
); );

View File

@ -58,6 +58,10 @@ public class DefaultDatagramChannelConfig extends DefaultChannelConfig implement
this.javaSocket = javaSocket; this.javaSocket = javaSocket;
} }
protected final DatagramSocket javaSocket() {
return javaSocket;
}
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public Map<ChannelOption<?>, Object> getOptions() { public Map<ChannelOption<?>, Object> getOptions() {

View File

@ -0,0 +1,205 @@
/*
* Copyright 2017 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.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DefaultDatagramChannelConfig;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Map;
import static io.netty.channel.ChannelOption.SO_TIMEOUT;
final class DefaultOioDatagramChannelConfig extends DefaultDatagramChannelConfig implements OioDatagramChannelConfig {
DefaultOioDatagramChannelConfig(DatagramChannel channel, DatagramSocket 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 OioDatagramChannelConfig setSoTimeout(int timeout) {
try {
javaSocket().setSoTimeout(timeout);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getSoTimeout() {
try {
return javaSocket().getSoTimeout();
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public OioDatagramChannelConfig setBroadcast(boolean broadcast) {
super.setBroadcast(broadcast);
return this;
}
@Override
public OioDatagramChannelConfig setInterface(InetAddress interfaceAddress) {
super.setInterface(interfaceAddress);
return this;
}
@Override
public OioDatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) {
super.setLoopbackModeDisabled(loopbackModeDisabled);
return this;
}
@Override
public OioDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) {
super.setNetworkInterface(networkInterface);
return this;
}
@Override
public OioDatagramChannelConfig setReuseAddress(boolean reuseAddress) {
super.setReuseAddress(reuseAddress);
return this;
}
@Override
public OioDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) {
super.setReceiveBufferSize(receiveBufferSize);
return this;
}
@Override
public OioDatagramChannelConfig setSendBufferSize(int sendBufferSize) {
super.setSendBufferSize(sendBufferSize);
return this;
}
@Override
public OioDatagramChannelConfig setTimeToLive(int ttl) {
super.setTimeToLive(ttl);
return this;
}
@Override
public OioDatagramChannelConfig setTrafficClass(int trafficClass) {
super.setTrafficClass(trafficClass);
return this;
}
@Override
public OioDatagramChannelConfig setWriteSpinCount(int writeSpinCount) {
super.setWriteSpinCount(writeSpinCount);
return this;
}
@Override
public OioDatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
super.setConnectTimeoutMillis(connectTimeoutMillis);
return this;
}
@Override
public OioDatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
super.setMaxMessagesPerRead(maxMessagesPerRead);
return this;
}
@Override
public OioDatagramChannelConfig setAllocator(ByteBufAllocator allocator) {
super.setAllocator(allocator);
return this;
}
@Override
public OioDatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
super.setRecvByteBufAllocator(allocator);
return this;
}
@Override
public OioDatagramChannelConfig setAutoRead(boolean autoRead) {
super.setAutoRead(autoRead);
return this;
}
@Override
public OioDatagramChannelConfig setAutoClose(boolean autoClose) {
super.setAutoClose(autoClose);
return this;
}
@Override
public OioDatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
return this;
}
@Override
public OioDatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
return this;
}
@Override
public OioDatagramChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
super.setWriteBufferWaterMark(writeBufferWaterMark);
return this;
}
@Override
public OioDatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
super.setMessageSizeEstimator(estimator);
return this;
}
}

View File

@ -29,7 +29,6 @@ import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramChannelConfig;
import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.DefaultDatagramChannelConfig;
import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
@ -69,7 +68,7 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
StringUtil.simpleClassName(ByteBuf.class) + ')'; StringUtil.simpleClassName(ByteBuf.class) + ')';
private final MulticastSocket socket; private final MulticastSocket socket;
private final DatagramChannelConfig config; private final OioDatagramChannelConfig config;
private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EmptyArrays.EMPTY_BYTES, 0); private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EmptyArrays.EMPTY_BYTES, 0);
private static MulticastSocket newSocket() { private static MulticastSocket newSocket() {
@ -110,7 +109,7 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
} }
this.socket = socket; this.socket = socket;
config = new DefaultDatagramChannelConfig(this, socket); config = new DefaultOioDatagramChannelConfig(this, socket);
} }
@Override @Override
@ -118,7 +117,13 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
return METADATA; return METADATA;
} }
/**
* {@inheritDoc}
*
* This can be safetly cast to {@link OioDatagramChannelConfig}.
*/
@Override @Override
// TODO: Change return type to OioDatagramChannelConfig in next major release
public DatagramChannelConfig config() { public DatagramChannelConfig config() {
return config; return config;
} }

View File

@ -0,0 +1,97 @@
/*
* Copyright 2017 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.buffer.ByteBufAllocator;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.socket.DatagramChannelConfig;
import java.net.InetAddress;
import java.net.NetworkInterface;
public interface OioDatagramChannelConfig extends DatagramChannelConfig {
/**
* Sets the maximal time a operation on the underlying socket may block.
*/
OioDatagramChannelConfig setSoTimeout(int timeout);
/**
* Returns the maximal time a operation on the underlying socket may block.
*/
int getSoTimeout();
@Override
OioDatagramChannelConfig setSendBufferSize(int sendBufferSize);
@Override
OioDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize);
@Override
OioDatagramChannelConfig setTrafficClass(int trafficClass);
@Override
OioDatagramChannelConfig setReuseAddress(boolean reuseAddress);
@Override
OioDatagramChannelConfig setBroadcast(boolean broadcast);
@Override
OioDatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled);
@Override
OioDatagramChannelConfig setTimeToLive(int ttl);
@Override
OioDatagramChannelConfig setInterface(InetAddress interfaceAddress);
@Override
OioDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface);
@Override
OioDatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead);
@Override
OioDatagramChannelConfig setWriteSpinCount(int writeSpinCount);
@Override
OioDatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis);
@Override
OioDatagramChannelConfig setAllocator(ByteBufAllocator allocator);
@Override
OioDatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator);
@Override
OioDatagramChannelConfig setAutoRead(boolean autoRead);
@Override
OioDatagramChannelConfig setAutoClose(boolean autoClose);
@Override
OioDatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator);
@Override
OioDatagramChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark);
@Override
OioDatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark);
@Override
OioDatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark);
}