Introduce UniqueName, UniqueKey, and Signal

- UniqueKey removes the duplication between ChannelOption and
  AttributeKey
- UniqueName provides common name collision check for AttributeKey,
  ChannelOption, and Signal.
- Replaced ReplayError with Signal
This commit is contained in:
Trustin Lee 2012-05-18 14:30:42 +09:00
parent 5344dc242c
commit dbd973d825
8 changed files with 178 additions and 116 deletions

View File

@ -1,26 +0,0 @@
/*
* Copyright 2011 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.handler.codec;
final class ReplayError extends Error {
private static final long serialVersionUID = 2666698631187527681L;
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}

View File

@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInboundHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.util.Signal;
/**
* A specialized variation of {@link StreamToMessageDecoder} which enables implementation
@ -281,6 +282,8 @@ import io.netty.channel.ChannelPipeline;
*/
public abstract class ReplayingDecoder<O, S extends Enum<S>> extends ChannelInboundHandlerAdapter<Byte> {
static final Signal REPLAY = new Signal(ReplayingDecoder.class.getName() + ".REPLAY");
private final ChannelBufferHolder<Byte> in = ChannelBufferHolders.byteBuffer();
private final ChannelBuffer cumulation = in.byteBuffer();
private final ReplayingDecoderBuffer replayable = new ReplayingDecoderBuffer(cumulation);
@ -365,8 +368,9 @@ public abstract class ReplayingDecoder<O, S extends Enum<S>> extends ChannelInbo
in.discardReadBytes();
ctx.fireInboundBufferUpdated();
}
} catch (ReplayError replay) {
} catch (Signal replay) {
// Ignore
replay.expect(REPLAY);
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
@ -393,7 +397,8 @@ public abstract class ReplayingDecoder<O, S extends Enum<S>> extends ChannelInbo
continue;
}
}
} catch (ReplayError replay) {
} catch (Signal replay) {
replay.expect(REPLAY);
// Return to the checkpoint (or oldPosition) and retry.
int checkpoint = this.checkpoint;
if (checkpoint >= 0) {

View File

@ -15,6 +15,12 @@
*/
package io.netty.handler.codec;
import io.netty.buffer.ChannelBuffer;
import io.netty.buffer.ChannelBufferFactory;
import io.netty.buffer.ChannelBufferIndexFinder;
import io.netty.buffer.ChannelBuffers;
import io.netty.util.Signal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -24,14 +30,9 @@ import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
import io.netty.buffer.ChannelBuffer;
import io.netty.buffer.ChannelBufferFactory;
import io.netty.buffer.ChannelBufferIndexFinder;
import io.netty.buffer.ChannelBuffers;
class ReplayingDecoderBuffer implements ChannelBuffer {
private static final Error REPLAY = new ReplayError();
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
private final ChannelBuffer buffer;
private boolean terminated;
@ -119,7 +120,7 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
public ChannelBuffer duplicate() {
throw new UnreplayableOperationException();
}
@Override
public boolean getBoolean(int index) {
checkIndex(index);
@ -356,8 +357,8 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
} else {
return Integer.MAX_VALUE - buffer.readerIndex();
}
}
}
@Override
public boolean readBoolean() {
checkReadableBytes(1);
@ -511,7 +512,7 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
public void resetWriterIndex() {
throw new UnreplayableOperationException();
}
@Override
public void setBoolean(int index, boolean value) {
throw new UnreplayableOperationException();
@ -679,7 +680,7 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
public int writableBytes() {
return 0;
}
@Override
public void writeBoolean(boolean value) {
throw new UnreplayableOperationException();

View File

@ -1,51 +1,13 @@
package io.netty.util;
import java.io.Serializable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public final class AttributeKey<T> implements Serializable, Comparable<AttributeKey<T>> {
private static final long serialVersionUID = 2783354860083517323L;
public final class AttributeKey<T> extends UniqueKey<T> {
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
private final String name;
private final Class<T> valueType;
private final String strVal;
public AttributeKey(String name, Class<T> valueType) {
if (name == null) {
throw new NullPointerException("name");
}
if (valueType == null) {
throw new NullPointerException("valueType");
}
if (names.putIfAbsent(name, Boolean.TRUE) != null) {
throw new IllegalArgumentException("key name already in use: " + name);
}
this.name = name;
this.valueType = valueType;
strVal = name + '[' + valueType.getSimpleName() + ']';
}
public String name() {
return name;
}
public Class<T> valueType() {
return valueType;
}
@Override
public int compareTo(AttributeKey<T> o) {
return name().compareTo(o.name());
}
@Override
public String toString() {
return strVal;
super(names, name, valueType);
}
}

View File

@ -0,0 +1,47 @@
package io.netty.util;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public final class Signal extends Error {
private static final long serialVersionUID = -221145131122459977L;
private static final ConcurrentMap<String, Boolean> map =
new ConcurrentHashMap<String, Boolean>();
private final SignalName uname;
public Signal(String name) {
super(name);
uname = new SignalName(name);
}
public void expect(Signal signal) {
if (this != signal) {
throw new IllegalStateException("unexpected signal: " + signal);
}
}
@Override
public Throwable initCause(Throwable cause) {
return this;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
@Override
public String toString() {
return uname.name();
}
private static class SignalName extends UniqueName {
protected SignalName(String name) {
super(map, name);
}
}
}

View File

@ -0,0 +1,32 @@
package io.netty.util;
import java.util.concurrent.ConcurrentMap;
public class UniqueKey<T> extends UniqueName {
private final Class<T> valueType;
private final String strVal;
protected UniqueKey(ConcurrentMap<String, Boolean> map, String name, Class<T> valueType) {
super(map, name, valueType);
this.valueType = valueType;
strVal = name + '[' + valueType.getSimpleName() + ']';
}
@Override
protected void validateArgs(Object... args) {
super.validateArgs(args);
if (args[0] == null) {
throw new NullPointerException("valueType");
}
}
public final Class<T> valueType() {
return valueType;
}
@Override
public String toString() {
return strVal;
}
}

View File

@ -0,0 +1,74 @@
package io.netty.util;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
public class UniqueName implements Comparable<UniqueName> {
private static final AtomicInteger nextId = new AtomicInteger();
private final int id;
private final String name;
protected 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' already in use", name));
}
id = nextId.incrementAndGet();
this.name = name;
}
protected void validateArgs(Object... args) {
// Subclasses will override.
}
public final String name() {
return name;
}
@Override
public final int hashCode() {
return super.hashCode();
}
@Override
public final boolean equals(Object o) {
return super.equals(o);
}
@Override
public int compareTo(UniqueName o) {
if (this == o) {
return 0;
}
int ret = name.compareTo(o.name);
if (ret != 0) {
return ret;
}
if (id < o.id) {
return -1;
} else if (id > o.id) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
return name();
}
}

View File

@ -1,5 +1,7 @@
package io.netty.channel;
import io.netty.util.UniqueKey;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
@ -7,7 +9,7 @@ import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class ChannelOption<T> implements Comparable<ChannelOption<T>> {
public class ChannelOption<T> extends UniqueKey<T> {
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
@ -75,33 +77,8 @@ public class ChannelOption<T> implements Comparable<ChannelOption<T>> {
public static final ChannelOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
new ChannelOption<SocketAddress>("SCTP_SET_PEER_PRIMARY_ADDR", SocketAddress.class);
private final String name;
private final Class<T> valueType;
private final String strVal;
public ChannelOption(String name, Class<T> valueType) {
if (name == null) {
throw new NullPointerException("name");
}
if (valueType == null) {
throw new NullPointerException("valueType");
}
if (names.putIfAbsent(name, Boolean.TRUE) != null) {
throw new IllegalArgumentException("option name already in use: " + name);
}
this.name = name;
this.valueType = valueType;
strVal = name + '[' + valueType.getSimpleName() + ']';
}
public String name() {
return name;
}
public Class<T> valueType() {
return valueType;
super(names, name, valueType);
}
public void validate(T value) {
@ -109,14 +86,4 @@ public class ChannelOption<T> implements Comparable<ChannelOption<T>> {
throw new NullPointerException("value");
}
}
@Override
public int compareTo(ChannelOption<T> o) {
return name().compareTo(o.name());
}
@Override
public String toString() {
return strVal;
}
}