Replace UniqueName with Constant and ConstantPool

- Proposed fix for #1824

UniqueName and its subtypes do not allow getting the previously registered instance.  For example, let's assume that a user is running his/her application in an OSGi container with Netty bundles and his server bundle.  Whenever the server bundle is reloaded, the server will try to create a new AttributeKey instance with the same name.  However, Netty bundles were not reloaded at all, so AttributeKey will complain that the name is taken already (by the previously loaded bundle.)

To fix this problem:

- Replaced UniqueName with Constant, AbstractConstant, and ConstantPool.  Better name and better design.

- Sctp/Udt/RxtxChannelOption is not a ChannelOption anymore.  They are just constant providers and ChannelOption is final now.  It's because caching anything that's from outside of netty-transport will lead to ClassCastException on reload, because ChannelOption's constant pool will keep all option objects for reuse.

- Signal implements Constant because we can't ensure its uniqueness anymore by relying on the exception raised by UniqueName's constructor.
This commit is contained in:
Trustin Lee 2013-10-25 19:21:53 +09:00
parent 573b54a93d
commit b533a1361b
15 changed files with 369 additions and 361 deletions

View File

@ -0,0 +1,72 @@
/*
* Copyright 2012 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.util;
/**
* Base implementation of {@link Constant}.
*/
public abstract class AbstractConstant<T extends AbstractConstant<T>> implements Constant<T> {
private final int id;
private final String name;
/**
* Creates a new instance.
*/
protected AbstractConstant(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public final String name() {
return name;
}
@Override
public final int id() {
return id;
}
@Override
public final int hashCode() {
return super.hashCode();
}
@Override
public final boolean equals(Object o) {
return super.equals(o);
}
@Override
public final int compareTo(T other) {
if (this == other) {
return 0;
}
int returnCode = name.compareTo(other.name());
if (returnCode != 0) {
return returnCode;
}
return ((Integer) id).compareTo(other.id());
}
@Override
public final String toString() {
return name();
}
}

View File

@ -15,35 +15,31 @@
*/
package io.netty.util;
import io.netty.util.internal.PlatformDependent;
import java.util.concurrent.ConcurrentMap;
/**
* Key which can be used to access {@link Attribute} out of the {@link AttributeMap}. Be aware that it is not be
* possible to have multiple keys with the same name.
*
*
* @param <T> the type of the {@link Attribute} which can be accessed via this {@link AttributeKey}.
*/
@SuppressWarnings({ "UnusedDeclaration", "deprecation" }) // 'T' is used only at compile time
public final class AttributeKey<T> extends UniqueName {
@SuppressWarnings("UnusedDeclaration") // 'T' is used only at compile time
public final class AttributeKey<T> extends AbstractConstant<AttributeKey<T>> {
private static final ConcurrentMap<String, Boolean> names = PlatformDependent.newConcurrentHashMap();
private static final ConstantPool<AttributeKey<Object>> pool = new ConstantPool<AttributeKey<Object>>() {
@Override
protected AttributeKey<Object> newConstant(int id, String name) {
return new AttributeKey<Object>(id, name);
}
};
/**
* Creates a new {@link AttributeKey} with the specified {@code name}.
* Returns the singleton instance of the {@link AttributeKey} which has the specified {@code name}.
*/
@SuppressWarnings("deprecation")
@SuppressWarnings("unchecked")
public static <T> AttributeKey<T> valueOf(String name) {
return new AttributeKey<T>(name);
return (AttributeKey<T>) pool.valueOf(name);
}
/**
* @deprecated Use {@link #valueOf(String)} instead.
*/
@Deprecated
public AttributeKey(String name) {
super(names, name);
private AttributeKey(int id, String name) {
super(id, name);
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2012 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.util;
/**
* A singleton which is safe to compare via the {@code ==} operator. Created and managed by {@link ConstantPool}.
*/
public interface Constant<T extends Constant<T>> extends Comparable<T> {
/**
* Returns the unique number assigned to this {@link Constant}.
*/
int id();
/**
* Returns the name of this {@link Constant}.
*/
String name();
}

View File

@ -0,0 +1,54 @@
/*
* 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.util;
import java.util.HashMap;
import java.util.Map;
/**
* A pool of {@link Constant}s.
*
* @param <T> the type of the constant
*/
public abstract class ConstantPool<T extends Constant<T>> {
private final Map<String, T> constants = new HashMap<String, T>();
private int nextId = 1;
/**
* Creates a new or the existing {@link Constant} mapped to the specified {@code name}.
*/
public T valueOf(String name) {
if (name == null) {
throw new NullPointerException("name");
}
synchronized (constants) {
T c = constants.get(name);
if (c == null) {
c = newConstant(nextId, name);
constants.put(name, c);
nextId ++;
}
return c;
}
}
protected abstract T newConstant(int id, String name);
}

View File

@ -16,38 +16,37 @@
package io.netty.util;
import io.netty.util.internal.PlatformDependent;
import java.util.concurrent.ConcurrentMap;
/**
* A special {@link Error} which is used to signal some state or request by throwing it.
* {@link Signal} has an empty stack trace and has no cause to save the instantiation overhead.
*/
public final class Signal extends Error {
public final class Signal extends Error implements Constant<Signal> {
private static final long serialVersionUID = -221145131122459977L;
private static final ConcurrentMap<String, Boolean> map = PlatformDependent.newConcurrentHashMap();
private static final ConstantPool<Signal> pool = new ConstantPool<Signal>() {
@Override
protected Signal newConstant(int id, String name) {
return new Signal(id, name);
}
};
@SuppressWarnings("deprecation")
private final UniqueName uname;
/**
* Returns the {@link Signal} of the specified name.
*/
public static Signal valueOf(String name) {
return pool.valueOf(name);
}
private final int id;
private final String name;
/**
* Creates a new {@link Signal} with the specified {@code name}.
*/
@SuppressWarnings("deprecation")
public static Signal valueOf(String name) {
return new Signal(name);
}
/**
* @deprecated Use {@link #valueOf(String)} instead.
*/
@Deprecated
public Signal(String name) {
super(name);
uname = new UniqueName(map, name);
private Signal(int id, String name) {
this.id = id;
this.name = name;
}
/**
@ -70,8 +69,42 @@ public final class Signal extends Error {
return this;
}
@Override
public int id() {
return id;
}
@Override
public String name() {
return name;
}
@Override
public boolean equals(Object obj) {
return this == obj;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public int compareTo(Signal other) {
if (this == other) {
return 0;
}
int returnCode = name.compareTo(other.name());
if (returnCode != 0) {
return returnCode;
}
return ((Integer) id).compareTo(other.id());
}
@Override
public String toString() {
return uname.name();
return name();
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright 2012 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.util;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @deprecated Known to have problems with class loaders.
*
* Defines a name that must be unique in the map that is provided during construction.
*/
@Deprecated
public class UniqueName implements Comparable<UniqueName> {
private static final AtomicInteger nextId = new AtomicInteger();
private final int id;
private final String name;
/**
* Constructs a new {@link UniqueName}
*
* @param map the map of names to compare with
* @param name the name of this {@link UniqueName}
* @param args the arguments to process
*/
public UniqueName(ConcurrentMap<String, Boolean> map, String name, Object... args) {
if (map == null) {
throw new NullPointerException("map");
}
if (name == null) {
throw new NullPointerException("name");
}
if (args != null && args.length > 0) {
validateArgs(args);
}
if (map.putIfAbsent(name, Boolean.TRUE) != null) {
throw new IllegalArgumentException(String.format("'%s' is already in use", name));
}
id = nextId.incrementAndGet();
this.name = name;
}
/**
* Validates the given arguments. This method does not do anything on its own, but must be
* overridden by its subclasses.
*
* @param args arguments to validate
*/
@SuppressWarnings("unused")
protected void validateArgs(Object... args) {
// Subclasses will override.
}
/**
* Returns this {@link UniqueName}'s name
*
* @return the name
*/
public final String name() {
return name;
}
/**
* Returns this {@link UniqueName}'s ID
*
* @return the id
*/
public final int id() {
return id;
}
@Override
public final int hashCode() {
return super.hashCode();
}
@Override
public final boolean equals(Object o) {
return super.equals(o);
}
@Override
public int compareTo(UniqueName other) {
if (this == other) {
return 0;
}
int returnCode = name.compareTo(other.name);
if (returnCode != 0) {
return returnCode;
}
return ((Integer) id).compareTo(other.id);
}
@Override
public String toString() {
return name();
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2012 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.util;
import org.junit.Test;
import java.util.Set;
import java.util.TreeSet;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
public class ConstantPoolTest {
static final class TestConstant extends AbstractConstant<TestConstant> {
TestConstant(int id, String name) {
super(id, name);
}
}
private static final ConstantPool<TestConstant> pool = new ConstantPool<TestConstant>() {
@Override
protected TestConstant newConstant(int id, String name) {
return new TestConstant(id, name);
}
};
@Test(expected = NullPointerException.class)
public void testCannotProvideNullName() {
pool.valueOf(null);
}
@Test
@SuppressWarnings("RedundantStringConstructorCall")
public void testUniqueness() {
TestConstant a = pool.valueOf(new String("Leroy"));
TestConstant b = pool.valueOf(new String("Leroy"));
assertThat(a, is(sameInstance(b)));
}
@Test
public void testIdUniqueness() {
TestConstant one = pool.valueOf("one");
TestConstant two = pool.valueOf("two");
assertThat(one.id(), is(not(two.id())));
}
@Test
public void testCompare() {
TestConstant a = pool.valueOf("a_alpha");
TestConstant b = pool.valueOf("b_beta");
TestConstant c = pool.valueOf("c_gamma");
TestConstant d = pool.valueOf("d_delta");
TestConstant e = pool.valueOf("e_epsilon");
Set<TestConstant> set = new TreeSet<TestConstant>();
set.add(b);
set.add(c);
set.add(e);
set.add(d);
set.add(a);
TestConstant[] array = set.toArray(new TestConstant[5]);
assertThat(array.length, is(5));
assertThat(array[0], is(sameInstance(a)));
assertThat(array[1], is(sameInstance(b)));
assertThat(array[2], is(sameInstance(c)));
assertThat(array[3], is(sameInstance(d)));
assertThat(array[4], is(sameInstance(e)));
}
}

View File

@ -1,122 +0,0 @@
/*
* Copyright 2012 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.util;
import io.netty.util.internal.PlatformDependent;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentMap;
import static org.junit.Assert.*;
public class UniqueNameTest {
/**
* A {@link ConcurrentMap} of registered names.
* This is set up before each test
*/
private ConcurrentMap<String, Boolean> names;
/**
* Registers a {@link UniqueName}
*
* @param name the name being registered
* @return the unique name
*/
public UniqueName registerName(String name) {
return new UniqueName(names, name);
}
@Before
public void initializeTest() {
names = PlatformDependent.newConcurrentHashMap();
}
@Test(expected = NullPointerException.class)
public void testCannnotProvideNullMap() {
new UniqueName(null, "Nothing");
}
@Test(expected = NullPointerException.class)
public void testCannotProvideNullName() {
new UniqueName(names, null);
}
@Test
public void testArgsCanBePassed() {
new UniqueName(names, "Argh, matey!", 2, 5, new Object());
}
@Test
public void testRegisteringName() {
registerName("Abcedrian");
assertTrue(names.get("Abcedrian"));
assertNull(names.get("Hellyes"));
}
@Test
public void testNameUniqueness() {
registerName("Leroy");
boolean failed = false;
try {
registerName("Leroy");
} catch (IllegalArgumentException ex) {
failed = true;
}
assertTrue(failed);
}
@Test
public void testIDUniqueness() {
UniqueName one = registerName("one");
UniqueName two = registerName("two");
assertNotSame(one.id(), two.id());
ArrayList<UniqueName> nameList = new ArrayList<UniqueName>();
for (int index = 0; index < 2500; index++) {
UniqueName currentName = registerName("test" + index);
nameList.add(currentName);
for (UniqueName otherName : nameList) {
if (!currentName.name().equals(otherName.name())) {
assertNotSame(currentName, otherName);
assertNotSame(currentName.hashCode(), otherName.hashCode());
assertFalse(currentName.equals(otherName));
assertNotSame(currentName.toString(), otherName.toString());
}
}
}
}
@Test
public void testCompareNames() {
UniqueName one = registerName("One");
UniqueName two = registerName("Two");
ConcurrentMap<String, Boolean> mapTwo = PlatformDependent.newConcurrentHashMap();
UniqueName three = new UniqueName(mapTwo, "One");
assertSame(one.compareTo(one), 0);
assertSame(one.compareTo(two), -5);
assertSame(one.compareTo(three), -1);
assertSame(three.compareTo(one), 1);
}
}

View File

@ -20,36 +20,22 @@ import io.netty.channel.rxtx.RxtxChannelConfig.Databits;
import io.netty.channel.rxtx.RxtxChannelConfig.Paritybit;
import io.netty.channel.rxtx.RxtxChannelConfig.Stopbits;
import static io.netty.channel.ChannelOption.*;
/**
* Option for configuring a serial port connection
*/
public final class RxtxChannelOption<T> extends ChannelOption<T> {
public static final RxtxChannelOption<Integer> BAUD_RATE =
new RxtxChannelOption<Integer>("BAUD_RATE");
public static final RxtxChannelOption<Boolean> DTR =
new RxtxChannelOption<Boolean>("DTR");
public final class RxtxChannelOption {
public static final RxtxChannelOption<Boolean> RTS =
new RxtxChannelOption<Boolean>("RTS");
public static final ChannelOption<Integer> BAUD_RATE = valueOf("BAUD_RATE");
public static final ChannelOption<Boolean> DTR = valueOf("DTR");
public static final ChannelOption<Boolean> RTS = valueOf("RTS");
public static final ChannelOption<Stopbits> STOP_BITS = valueOf("STOP_BITS");
public static final ChannelOption<Databits> DATA_BITS = valueOf("DATA_BITS");
public static final ChannelOption<Paritybit> PARITY_BIT = valueOf("PARITY_BIT");
public static final ChannelOption<Integer> WAIT_TIME = valueOf("WAIT_TIME");
public static final ChannelOption<Integer> READ_TIMEOUT = valueOf("READ_TIMEOUT");
public static final RxtxChannelOption<Stopbits> STOP_BITS =
new RxtxChannelOption<Stopbits>("STOP_BITS");
public static final RxtxChannelOption<Databits> DATA_BITS =
new RxtxChannelOption<Databits>("DATA_BITS");
public static final RxtxChannelOption<Paritybit> PARITY_BIT =
new RxtxChannelOption<Paritybit>("PARITY_BIT");
public static final RxtxChannelOption<Integer> WAIT_TIME =
new RxtxChannelOption<Integer>("WAIT_TIME");
public static final RxtxChannelOption<Integer> READ_TIMEOUT =
new RxtxChannelOption<Integer>("READ_TIMEOUT");
@SuppressWarnings("deprecation")
private RxtxChannelOption(String name) {
super(name);
}
private RxtxChannelOption() { }
}

View File

@ -29,6 +29,7 @@ import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.util.Map;
import static io.netty.channel.ChannelOption.*;
import static io.netty.channel.sctp.SctpChannelOption.*;
/**

View File

@ -16,6 +16,8 @@
package io.netty.channel.sctp;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
@ -27,8 +29,6 @@ import io.netty.util.NetUtil;
import java.io.IOException;
import java.util.Map;
import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
/**
* The default {@link SctpServerChannelConfig} implementation for SCTP.
*/
@ -76,7 +76,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
setReceiveBufferSize((Integer) value);
} else if (option == ChannelOption.SO_SNDBUF) {
setSendBufferSize((Integer) value);
} else if (option == SCTP_INIT_MAXSTREAMS) {
} else if (option == SctpChannelOption.SCTP_INIT_MAXSTREAMS) {
setInitMaxStreams((InitMaxStreams) value);
} else {
return super.setOption(option, value);
@ -88,7 +88,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
@Override
public int getSendBufferSize() {
try {
return javaChannel.getOption(SO_SNDBUF);
return javaChannel.getOption(SctpStandardSocketOptions.SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
@ -97,7 +97,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
@Override
public SctpServerChannelConfig setSendBufferSize(int sendBufferSize) {
try {
javaChannel.setOption(SO_SNDBUF, sendBufferSize);
javaChannel.setOption(SctpStandardSocketOptions.SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
@ -107,7 +107,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
@Override
public int getReceiveBufferSize() {
try {
return javaChannel.getOption(SO_RCVBUF);
return javaChannel.getOption(SctpStandardSocketOptions.SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
@ -116,7 +116,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
@Override
public SctpServerChannelConfig setReceiveBufferSize(int receiveBufferSize) {
try {
javaChannel.setOption(SO_RCVBUF, receiveBufferSize);
javaChannel.setOption(SctpStandardSocketOptions.SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
@ -126,7 +126,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
@Override
public InitMaxStreams getInitMaxStreams() {
try {
return javaChannel.getOption(SCTP_INIT_MAXSTREAMS);
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
@ -135,7 +135,7 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme
@Override
public SctpServerChannelConfig setInitMaxStreams(InitMaxStreams initMaxStreams) {
try {
javaChannel.setOption(SCTP_INIT_MAXSTREAMS, initMaxStreams);
javaChannel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}

View File

@ -15,37 +15,26 @@
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.channel.ChannelOption;
import java.net.SocketAddress;
import static io.netty.channel.ChannelOption.*;
/**
* Option for configuring the SCTP transport
*/
@SuppressWarnings("deprecation")
public class SctpChannelOption<T> extends ChannelOption<T> {
public static final SctpChannelOption<Boolean> SCTP_DISABLE_FRAGMENTS =
new SctpChannelOption<Boolean>("SCTP_DISABLE_FRAGMENTS");
public static final SctpChannelOption<Boolean> SCTP_EXPLICIT_COMPLETE =
new SctpChannelOption<Boolean>("SCTP_EXPLICIT_COMPLETE");
public static final SctpChannelOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
new SctpChannelOption<Integer>("SCTP_FRAGMENT_INTERLEAVE");
public static final SctpChannelOption<SctpStandardSocketOptions.InitMaxStreams> SCTP_INIT_MAXSTREAMS =
new SctpChannelOption<SctpStandardSocketOptions.InitMaxStreams>("SCTP_INIT_MAXSTREAMS");
public final class SctpChannelOption {
public static final SctpChannelOption<Boolean> SCTP_NODELAY =
new SctpChannelOption<Boolean>("SCTP_NODELAY");
public static final SctpChannelOption<SocketAddress> SCTP_PRIMARY_ADDR =
new SctpChannelOption<SocketAddress>("SCTP_PRIMARY_ADDR");
public static final SctpChannelOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
new SctpChannelOption<SocketAddress>("SCTP_SET_PEER_PRIMARY_ADDR");
public static final ChannelOption<Boolean> SCTP_DISABLE_FRAGMENTS = valueOf("SCTP_DISABLE_FRAGMENTS");
public static final ChannelOption<Boolean> SCTP_EXPLICIT_COMPLETE = valueOf("SCTP_EXPLICIT_COMPLETE");
public static final ChannelOption<Integer> SCTP_FRAGMENT_INTERLEAVE = valueOf("SCTP_FRAGMENT_INTERLEAVE");
public static final ChannelOption<InitMaxStreams> SCTP_INIT_MAXSTREAMS = valueOf("SCTP_INIT_MAXSTREAMS");
/**
* @deprecated Will be removed in the future release.
*/
@Deprecated
protected SctpChannelOption(String name) {
super(name);
}
public static final ChannelOption<Boolean> SCTP_NODELAY = valueOf("SCTP_NODELAY");
public static final ChannelOption<SocketAddress> SCTP_PRIMARY_ADDR = valueOf("SCTP_PRIMARY_ADDR");
public static final ChannelOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR = valueOf("SCTP_SET_PEER_PRIMARY_ADDR");
private SctpChannelOption() { }
}

View File

@ -27,6 +27,7 @@ import io.netty.channel.RecvByteBufAllocator;
import java.io.IOException;
import java.util.Map;
import static io.netty.channel.ChannelOption.*;
import static io.netty.channel.udt.UdtChannelOption.*;
/**

View File

@ -18,37 +18,36 @@ package io.netty.channel.udt;
import com.barchart.udt.OptionUDT;
import io.netty.channel.ChannelOption;
import static io.netty.channel.ChannelOption.*;
/**
* Options for the UDT transport
*/
public final class UdtChannelOption<T> extends ChannelOption<T> {
public final class UdtChannelOption {
/**
* See {@link OptionUDT#Protocol_Receive_Buffer_Size}.
*/
public static final UdtChannelOption<Integer> PROTOCOL_RECEIVE_BUFFER_SIZE = new UdtChannelOption<Integer>(
public static final ChannelOption<Integer> PROTOCOL_RECEIVE_BUFFER_SIZE = valueOf(
"PROTOCOL_RECEIVE_BUFFER_SIZE");
/**
* See {@link OptionUDT#Protocol_Send_Buffer_Size}.
*/
public static final UdtChannelOption<Integer> PROTOCOL_SEND_BUFFER_SIZE = new UdtChannelOption<Integer>(
public static final ChannelOption<Integer> PROTOCOL_SEND_BUFFER_SIZE = valueOf(
"PROTOCOL_SEND_BUFFER_SIZE");
/**
* See {@link OptionUDT#System_Receive_Buffer_Size}.
*/
public static final UdtChannelOption<Integer> SYSTEM_RECEIVE_BUFFER_SIZE = new UdtChannelOption<Integer>(
public static final ChannelOption<Integer> SYSTEM_RECEIVE_BUFFER_SIZE = valueOf(
"SYSTEM_RECEIVE_BUFFER_SIZE");
/**
* See {@link OptionUDT#System_Send_Buffer_Size}.
*/
public static final UdtChannelOption<Integer> SYSTEM_SEND_BUFFER_SIZE = new UdtChannelOption<Integer>(
public static final ChannelOption<Integer> SYSTEM_SEND_BUFFER_SIZE = valueOf(
"SYSTEM_SEND_BUFFER_SIZE");
@SuppressWarnings("deprecation")
private UdtChannelOption(String name) {
super(name);
}
private UdtChannelOption() { }
}

View File

@ -16,12 +16,11 @@
package io.netty.channel;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.UniqueName;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.AbstractConstant;
import io.netty.util.ConstantPool;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.ConcurrentMap;
/**
* A {@link ChannelOption} allows to configure a {@link ChannelConfig} in a type-safe
@ -31,10 +30,19 @@ import java.util.concurrent.ConcurrentMap;
*
* @param <T> the type of the value which is valid for the {@link ChannelOption}
*/
@SuppressWarnings("deprecation")
public class ChannelOption<T> extends UniqueName {
public final class ChannelOption<T> extends AbstractConstant<ChannelOption<T>> {
private static final ConcurrentMap<String, Boolean> names = PlatformDependent.newConcurrentHashMap();
private static final ConstantPool<ChannelOption<Object>> pool = new ConstantPool<ChannelOption<Object>>() {
@Override
protected ChannelOption<Object> newConstant(int id, String name) {
return new ChannelOption<Object>(id, name);
}
};
@SuppressWarnings("unchecked")
public static <T> ChannelOption<T> valueOf(String name) {
return (ChannelOption<T>) pool.valueOf(name);
}
public static final ChannelOption<ByteBufAllocator> ALLOCATOR = valueOf("ALLOCATOR");
public static final ChannelOption<RecvByteBufAllocator> RCVBUF_ALLOCATOR = valueOf("RCVBUF_ALLOCATOR");
@ -82,16 +90,8 @@ public class ChannelOption<T> extends UniqueName {
/**
* Creates a new {@link ChannelOption} with the specified {@code name}.
*/
public static <T> ChannelOption<T> valueOf(String name) {
return new ChannelOption<T>(name);
}
/**
* @deprecated Use {@link #valueOf(String)} instead.
*/
@Deprecated
protected ChannelOption(String name) {
super(names, name);
private ChannelOption(int id, String name) {
super(id, name);
}
/**