Madan Jampani

Limit the amont of work that happens on netty event loop threads.

Currently we are kryo serializing/deserializing the message envelope which can potentially limit throughput.

Change-Id: I0ae9dab53bbb765b7618ceaefda1edf4f77b0b59
...@@ -76,7 +76,7 @@ public class ClusterCommunicationManager ...@@ -76,7 +76,7 @@ public class ClusterCommunicationManager
76 @Activate 76 @Activate
77 public void activate() { 77 public void activate() {
78 ControllerNode localNode = clusterService.getLocalNode(); 78 ControllerNode localNode = clusterService.getLocalNode();
79 - NettyMessagingService netty = new NettyMessagingService(localNode.ip().toString(), localNode.tcpPort()); 79 + NettyMessagingService netty = new NettyMessagingService(localNode.ip(), localNode.tcpPort());
80 // FIXME: workaround until it becomes a service. 80 // FIXME: workaround until it becomes a service.
81 try { 81 try {
82 netty.activate(); 82 netty.activate();
...@@ -143,7 +143,7 @@ public class ClusterCommunicationManager ...@@ -143,7 +143,7 @@ public class ClusterCommunicationManager
143 private boolean unicast(MessageSubject subject, byte[] payload, NodeId toNodeId) throws IOException { 143 private boolean unicast(MessageSubject subject, byte[] payload, NodeId toNodeId) throws IOException {
144 ControllerNode node = clusterService.getNode(toNodeId); 144 ControllerNode node = clusterService.getNode(toNodeId);
145 checkArgument(node != null, "Unknown nodeId: %s", toNodeId); 145 checkArgument(node != null, "Unknown nodeId: %s", toNodeId);
146 - Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); 146 + Endpoint nodeEp = new Endpoint(node.ip(), node.tcpPort());
147 try { 147 try {
148 messagingService.sendAsync(nodeEp, subject.value(), payload); 148 messagingService.sendAsync(nodeEp, subject.value(), payload);
149 return true; 149 return true;
...@@ -166,7 +166,7 @@ public class ClusterCommunicationManager ...@@ -166,7 +166,7 @@ public class ClusterCommunicationManager
166 public ListenableFuture<byte[]> sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException { 166 public ListenableFuture<byte[]> sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException {
167 ControllerNode node = clusterService.getNode(toNodeId); 167 ControllerNode node = clusterService.getNode(toNodeId);
168 checkArgument(node != null, "Unknown nodeId: %s", toNodeId); 168 checkArgument(node != null, "Unknown nodeId: %s", toNodeId);
169 - Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); 169 + Endpoint nodeEp = new Endpoint(node.ip(), node.tcpPort());
170 try { 170 try {
171 return messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message)); 171 return messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message));
172 172
......
...@@ -19,9 +19,11 @@ package org.onlab.netty; ...@@ -19,9 +19,11 @@ package org.onlab.netty;
19 * State transitions a decoder goes through as it is decoding an incoming message. 19 * State transitions a decoder goes through as it is decoding an incoming message.
20 */ 20 */
21 public enum DecoderState { 21 public enum DecoderState {
22 - READ_HEADER_VERSION, 22 + READ_MESSAGE_ID,
23 - READ_PREAMBLE, 23 + READ_SENDER_IP_VERSION,
24 + READ_SENDER_IP,
25 + READ_SENDER_PORT,
26 + READ_MESSAGE_TYPE,
24 READ_CONTENT_LENGTH, 27 READ_CONTENT_LENGTH,
25 - READ_SERIALIZER_VERSION,
26 READ_CONTENT 28 READ_CONTENT
27 } 29 }
......
...@@ -15,8 +15,12 @@ ...@@ -15,8 +15,12 @@
15 */ 15 */
16 package org.onlab.netty; 16 package org.onlab.netty;
17 17
18 +import static com.google.common.base.Preconditions.*;
19 +
18 import java.util.Objects; 20 import java.util.Objects;
19 21
22 +import org.onlab.packet.IpAddress;
23 +
20 import com.google.common.base.MoreObjects; 24 import com.google.common.base.MoreObjects;
21 25
22 /** 26 /**
...@@ -25,15 +29,15 @@ import com.google.common.base.MoreObjects; ...@@ -25,15 +29,15 @@ import com.google.common.base.MoreObjects;
25 public final class Endpoint { 29 public final class Endpoint {
26 30
27 private final int port; 31 private final int port;
28 - private final String host; 32 + private final IpAddress ip;
29 33
30 - public Endpoint(String host, int port) { 34 + public Endpoint(IpAddress host, int port) {
31 - this.host = host; 35 + this.ip = checkNotNull(host);
32 this.port = port; 36 this.port = port;
33 } 37 }
34 38
35 - public String host() { 39 + public IpAddress host() {
36 - return host; 40 + return ip;
37 } 41 }
38 42
39 public int port() { 43 public int port() {
...@@ -43,14 +47,14 @@ public final class Endpoint { ...@@ -43,14 +47,14 @@ public final class Endpoint {
43 @Override 47 @Override
44 public String toString() { 48 public String toString() {
45 return MoreObjects.toStringHelper(getClass()) 49 return MoreObjects.toStringHelper(getClass())
46 - .add("host", host) 50 + .add("ip", ip)
47 .add("port", port) 51 .add("port", port)
48 .toString(); 52 .toString();
49 } 53 }
50 54
51 @Override 55 @Override
52 public int hashCode() { 56 public int hashCode() {
53 - return Objects.hash(host, port); 57 + return Objects.hash(ip, port);
54 } 58 }
55 59
56 @Override 60 @Override
...@@ -66,6 +70,6 @@ public final class Endpoint { ...@@ -66,6 +70,6 @@ public final class Endpoint {
66 } 70 }
67 Endpoint that = (Endpoint) obj; 71 Endpoint that = (Endpoint) obj;
68 return Objects.equals(this.port, that.port) && 72 return Objects.equals(this.port, that.port) &&
69 - Objects.equals(this.host, that.host); 73 + Objects.equals(this.ip, that.ip);
70 } 74 }
71 } 75 }
......
...@@ -27,18 +27,19 @@ import com.google.common.base.MoreObjects; ...@@ -27,18 +27,19 @@ import com.google.common.base.MoreObjects;
27 */ 27 */
28 public final class InternalMessage implements Message { 28 public final class InternalMessage implements Message {
29 29
30 - public static final String REPLY_MESSAGE_TYPE = "NETTY_MESSAGING_REQUEST_REPLY"; 30 + public static final long REPLY_MESSAGE_TYPE =
31 + NettyMessagingService.hashToLong("NETTY_MESSAGING_REQUEST_REPLY");
31 32
32 private long id; 33 private long id;
33 private Endpoint sender; 34 private Endpoint sender;
34 - private String type; 35 + private long type;
35 private byte[] payload; 36 private byte[] payload;
36 private transient NettyMessagingService messagingService; 37 private transient NettyMessagingService messagingService;
37 38
38 // Must be created using the Builder. 39 // Must be created using the Builder.
39 private InternalMessage() {} 40 private InternalMessage() {}
40 41
41 - InternalMessage(long id, Endpoint sender, String type, byte[] payload) { 42 + InternalMessage(long id, Endpoint sender, long type, byte[] payload) {
42 this.id = id; 43 this.id = id;
43 this.sender = sender; 44 this.sender = sender;
44 this.type = type; 45 this.type = type;
...@@ -49,7 +50,7 @@ public final class InternalMessage implements Message { ...@@ -49,7 +50,7 @@ public final class InternalMessage implements Message {
49 return id; 50 return id;
50 } 51 }
51 52
52 - public String type() { 53 + public long type() {
53 return type; 54 return type;
54 } 55 }
55 56
...@@ -103,7 +104,7 @@ public final class InternalMessage implements Message { ...@@ -103,7 +104,7 @@ public final class InternalMessage implements Message {
103 return this; 104 return this;
104 } 105 }
105 106
106 - public Builder withType(String type) { 107 + public Builder withType(long type) {
107 message.type = type; 108 message.type = type;
108 return this; 109 return this;
109 } 110 }
......
1 -/*
2 - * Copyright 2014 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.netty;
17 -
18 -import org.onlab.util.KryoNamespace;
19 -
20 -import com.esotericsoftware.kryo.Kryo;
21 -import com.esotericsoftware.kryo.Serializer;
22 -import com.esotericsoftware.kryo.io.Input;
23 -import com.esotericsoftware.kryo.io.Output;
24 -
25 -import java.nio.ByteBuffer;
26 -
27 -/**
28 - * Kryo Serializer.
29 - */
30 -public class KryoSerializer {
31 -
32 - private KryoNamespace serializerPool;
33 -
34 - public KryoSerializer() {
35 - setupKryoPool();
36 - }
37 -
38 - /**
39 - * Sets up the common serialzers pool.
40 - */
41 - protected void setupKryoPool() {
42 - serializerPool = KryoNamespace.newBuilder()
43 - .register(byte[].class)
44 - .register(new InternalMessageSerializer(), InternalMessage.class)
45 - .register(new EndPointSerializer(), Endpoint.class)
46 - .build();
47 - }
48 -
49 -
50 - public <T> T decode(byte[] data) {
51 - return serializerPool.deserialize(data);
52 - }
53 -
54 - public byte[] encode(Object payload) {
55 - return serializerPool.serialize(payload);
56 - }
57 -
58 - public <T> T decode(ByteBuffer buffer) {
59 - return serializerPool.deserialize(buffer);
60 - }
61 -
62 - public void encode(Object obj, ByteBuffer buffer) {
63 - serializerPool.serialize(obj, buffer);
64 - }
65 -
66 - public static final class InternalMessageSerializer
67 - extends Serializer<InternalMessage> {
68 -
69 - @Override
70 - public void write(Kryo kryo, Output output, InternalMessage object) {
71 - output.writeLong(object.id());
72 - kryo.writeClassAndObject(output, object.sender());
73 - output.writeString(object.type());
74 - output.writeInt(object.payload().length, true);
75 - output.writeBytes(object.payload());
76 - }
77 -
78 - @Override
79 - public InternalMessage read(Kryo kryo, Input input,
80 - Class<InternalMessage> type) {
81 - long id = input.readLong();
82 - Endpoint sender = (Endpoint) kryo.readClassAndObject(input);
83 - String msgtype = input.readString();
84 - int length = input.readInt(true);
85 - byte[] payload = input.readBytes(length);
86 - return new InternalMessage(id, sender, msgtype, payload);
87 - }
88 -
89 - }
90 -
91 - public static final class EndPointSerializer extends Serializer<Endpoint> {
92 -
93 - @Override
94 - public void write(Kryo kryo, Output output, Endpoint object) {
95 - output.writeString(object.host());
96 - output.writeInt(object.port());
97 - }
98 -
99 - @Override
100 - public Endpoint read(Kryo kryo, Input input, Class<Endpoint> type) {
101 - String host = input.readString();
102 - int port = input.readInt();
103 - return new Endpoint(host, port);
104 - }
105 - }
106 -}
...@@ -20,9 +20,10 @@ import io.netty.buffer.ByteBuf; ...@@ -20,9 +20,10 @@ import io.netty.buffer.ByteBuf;
20 import io.netty.channel.ChannelHandlerContext; 20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.handler.codec.ReplayingDecoder; 21 import io.netty.handler.codec.ReplayingDecoder;
22 22
23 -import java.util.Arrays;
24 import java.util.List; 23 import java.util.List;
25 24
25 +import org.onlab.packet.IpAddress;
26 +import org.onlab.packet.IpAddress.Version;
26 import org.slf4j.Logger; 27 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory; 28 import org.slf4j.LoggerFactory;
28 29
...@@ -35,12 +36,15 @@ public class MessageDecoder extends ReplayingDecoder<DecoderState> { ...@@ -35,12 +36,15 @@ public class MessageDecoder extends ReplayingDecoder<DecoderState> {
35 36
36 private final NettyMessagingService messagingService; 37 private final NettyMessagingService messagingService;
37 38
38 - private static final KryoSerializer SERIALIZER = new KryoSerializer(); 39 + private long messageId;
39 - 40 + private Version ipVersion;
41 + private IpAddress senderIp;
42 + private int senderPort;
40 private int contentLength; 43 private int contentLength;
44 + private long messageType;
41 45
42 public MessageDecoder(NettyMessagingService messagingService) { 46 public MessageDecoder(NettyMessagingService messagingService) {
43 - super(DecoderState.READ_HEADER_VERSION); 47 + super(DecoderState.READ_MESSAGE_ID);
44 this.messagingService = messagingService; 48 this.messagingService = messagingService;
45 } 49 }
46 50
...@@ -51,27 +55,37 @@ public class MessageDecoder extends ReplayingDecoder<DecoderState> { ...@@ -51,27 +55,37 @@ public class MessageDecoder extends ReplayingDecoder<DecoderState> {
51 List<Object> out) throws Exception { 55 List<Object> out) throws Exception {
52 56
53 switch (state()) { 57 switch (state()) {
54 - case READ_HEADER_VERSION: 58 + case READ_MESSAGE_ID:
55 - int headerVersion = buffer.readInt(); 59 + messageId = buffer.readLong();
56 - checkState(headerVersion == MessageEncoder.HEADER_VERSION, "Unexpected header version"); 60 + checkpoint(DecoderState.READ_SENDER_IP_VERSION);
57 - checkpoint(DecoderState.READ_PREAMBLE); 61 + case READ_SENDER_IP_VERSION:
58 - case READ_PREAMBLE: 62 + ipVersion = buffer.readByte() == 0x0 ? Version.INET : Version.INET6;
59 - byte[] preamble = new byte[MessageEncoder.PREAMBLE.length]; 63 + checkpoint(DecoderState.READ_SENDER_IP);
60 - buffer.readBytes(preamble); 64 + case READ_SENDER_IP:
61 - checkState(Arrays.equals(MessageEncoder.PREAMBLE, preamble), "Message has wrong preamble"); 65 + byte[] octects = new byte[IpAddress.byteLength(ipVersion)];
66 + buffer.readBytes(octects);
67 + senderIp = IpAddress.valueOf(ipVersion, octects);
68 + checkpoint(DecoderState.READ_SENDER_PORT);
69 + case READ_SENDER_PORT:
70 + senderPort = buffer.readInt();
71 + checkpoint(DecoderState.READ_MESSAGE_TYPE);
72 + case READ_MESSAGE_TYPE:
73 + messageType = buffer.readLong();
62 checkpoint(DecoderState.READ_CONTENT_LENGTH); 74 checkpoint(DecoderState.READ_CONTENT_LENGTH);
63 case READ_CONTENT_LENGTH: 75 case READ_CONTENT_LENGTH:
64 contentLength = buffer.readInt(); 76 contentLength = buffer.readInt();
65 - checkpoint(DecoderState.READ_SERIALIZER_VERSION);
66 - case READ_SERIALIZER_VERSION:
67 - int serializerVersion = buffer.readInt();
68 - checkState(serializerVersion == MessageEncoder.SERIALIZER_VERSION, "Unexpected serializer version");
69 checkpoint(DecoderState.READ_CONTENT); 77 checkpoint(DecoderState.READ_CONTENT);
70 case READ_CONTENT: 78 case READ_CONTENT:
71 - InternalMessage message = SERIALIZER.decode(buffer.readBytes(contentLength).nioBuffer()); 79 + byte[] payload = new byte[contentLength];
80 + buffer.readBytes(payload);
81 + InternalMessage message = new InternalMessage(
82 + messageId,
83 + new Endpoint(senderIp, senderPort),
84 + messageType,
85 + payload);
72 message.setMessagingService(messagingService); 86 message.setMessagingService(messagingService);
73 out.add(message); 87 out.add(message);
74 - checkpoint(DecoderState.READ_HEADER_VERSION); 88 + checkpoint(DecoderState.READ_MESSAGE_ID);
75 break; 89 break;
76 default: 90 default:
77 checkState(false, "Must not be here"); 91 checkState(false, "Must not be here");
......
...@@ -15,17 +15,18 @@ ...@@ -15,17 +15,18 @@
15 */ 15 */
16 package org.onlab.netty; 16 package org.onlab.netty;
17 17
18 -import java.io.IOException;
19 -import java.nio.charset.StandardCharsets;
20 -
21 -import org.slf4j.Logger;
22 -import org.slf4j.LoggerFactory;
23 -
24 import io.netty.buffer.ByteBuf; 18 import io.netty.buffer.ByteBuf;
25 import io.netty.channel.ChannelHandler.Sharable; 19 import io.netty.channel.ChannelHandler.Sharable;
26 import io.netty.channel.ChannelHandlerContext; 20 import io.netty.channel.ChannelHandlerContext;
27 import io.netty.handler.codec.MessageToByteEncoder; 21 import io.netty.handler.codec.MessageToByteEncoder;
28 22
23 +import java.io.IOException;
24 +
25 +import org.onlab.packet.IpAddress;
26 +import org.onlab.packet.IpAddress.Version;
27 +import org.slf4j.Logger;
28 +import org.slf4j.LoggerFactory;
29 +
29 /** 30 /**
30 * Encode InternalMessage out into a byte buffer. 31 * Encode InternalMessage out into a byte buffer.
31 */ 32 */
...@@ -34,34 +35,36 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -34,34 +35,36 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
34 35
35 private final Logger log = LoggerFactory.getLogger(getClass()); 36 private final Logger log = LoggerFactory.getLogger(getClass());
36 37
37 - // onosiscool in ascii
38 - static final byte[] PREAMBLE = "onosiscool".getBytes(StandardCharsets.US_ASCII);
39 - public static final int HEADER_VERSION = 1;
40 - public static final int SERIALIZER_VERSION = 1;
41 -
42 -
43 - private static final KryoSerializer SERIALIZER = new KryoSerializer();
44 -
45 @Override 38 @Override
46 protected void encode( 39 protected void encode(
47 ChannelHandlerContext context, 40 ChannelHandlerContext context,
48 InternalMessage message, 41 InternalMessage message,
49 ByteBuf out) throws Exception { 42 ByteBuf out) throws Exception {
50 43
51 - // write version 44 + // write message id
52 - out.writeInt(HEADER_VERSION); 45 + out.writeLong(message.id());
53 46
54 - // write preamble 47 + Endpoint sender = message.sender();
55 - out.writeBytes(PREAMBLE);
56 48
57 - byte[] payload = SERIALIZER.encode(message); 49 + IpAddress senderIp = sender.host();
50 + if (senderIp.version() == Version.INET) {
51 + out.writeByte(0);
52 + } else {
53 + out.writeByte(1);
54 + }
55 + out.writeBytes(senderIp.toOctets());
56 +
57 + // write sender port
58 + out.writeInt(sender.port());
59 +
60 + // write message type.
61 + out.writeLong(message.type());
62 +
63 + byte[] payload = message.payload();
58 64
59 // write payload length 65 // write payload length
60 out.writeInt(payload.length); 66 out.writeInt(payload.length);
61 67
62 - // write payloadSerializer version
63 - out.writeInt(SERIALIZER_VERSION);
64 -
65 // write payload. 68 // write payload.
66 out.writeBytes(payload); 69 out.writeBytes(payload);
67 } 70 }
......
...@@ -37,6 +37,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; ...@@ -37,6 +37,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
37 import io.netty.channel.socket.nio.NioSocketChannel; 37 import io.netty.channel.socket.nio.NioSocketChannel;
38 38
39 import java.io.IOException; 39 import java.io.IOException;
40 +import java.net.InetAddress;
40 import java.net.UnknownHostException; 41 import java.net.UnknownHostException;
41 import java.util.concurrent.ConcurrentHashMap; 42 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.concurrent.ConcurrentMap; 43 import java.util.concurrent.ConcurrentMap;
...@@ -46,13 +47,18 @@ import java.util.concurrent.atomic.AtomicLong; ...@@ -46,13 +47,18 @@ import java.util.concurrent.atomic.AtomicLong;
46 47
47 import org.apache.commons.pool.KeyedPoolableObjectFactory; 48 import org.apache.commons.pool.KeyedPoolableObjectFactory;
48 import org.apache.commons.pool.impl.GenericKeyedObjectPool; 49 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
50 +import org.onlab.packet.IpAddress;
49 import org.slf4j.Logger; 51 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory; 52 import org.slf4j.LoggerFactory;
51 53
54 +import com.google.common.base.Charsets;
52 import com.google.common.cache.Cache; 55 import com.google.common.cache.Cache;
53 import com.google.common.cache.CacheBuilder; 56 import com.google.common.cache.CacheBuilder;
57 +import com.google.common.cache.CacheLoader;
58 +import com.google.common.cache.LoadingCache;
54 import com.google.common.cache.RemovalListener; 59 import com.google.common.cache.RemovalListener;
55 import com.google.common.cache.RemovalNotification; 60 import com.google.common.cache.RemovalNotification;
61 +import com.google.common.hash.Hashing;
56 import com.google.common.util.concurrent.ListenableFuture; 62 import com.google.common.util.concurrent.ListenableFuture;
57 import com.google.common.util.concurrent.SettableFuture; 63 import com.google.common.util.concurrent.SettableFuture;
58 64
...@@ -64,7 +70,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -64,7 +70,7 @@ public class NettyMessagingService implements MessagingService {
64 private final Logger log = LoggerFactory.getLogger(getClass()); 70 private final Logger log = LoggerFactory.getLogger(getClass());
65 71
66 private final Endpoint localEp; 72 private final Endpoint localEp;
67 - private final ConcurrentMap<String, MessageHandler> handlers = new ConcurrentHashMap<>(); 73 + private final ConcurrentMap<Long, MessageHandler> handlers = new ConcurrentHashMap<>();
68 private final AtomicLong messageIdGenerator = new AtomicLong(0); 74 private final AtomicLong messageIdGenerator = new AtomicLong(0);
69 private final Cache<Long, SettableFuture<byte[]>> responseFutures = CacheBuilder.newBuilder() 75 private final Cache<Long, SettableFuture<byte[]>> responseFutures = CacheBuilder.newBuilder()
70 .maximumSize(100000) 76 .maximumSize(100000)
...@@ -78,6 +84,17 @@ public class NettyMessagingService implements MessagingService { ...@@ -78,6 +84,17 @@ public class NettyMessagingService implements MessagingService {
78 } 84 }
79 }) 85 })
80 .build(); 86 .build();
87 +
88 + private final LoadingCache<String, Long> messageTypeLookupCache = CacheBuilder.newBuilder()
89 + .softValues()
90 + .build(new CacheLoader<String, Long>() {
91 +
92 + @Override
93 + public Long load(String type) {
94 + return hashToLong(type);
95 + }
96 + });
97 +
81 private final GenericKeyedObjectPool<Endpoint, Channel> channels 98 private final GenericKeyedObjectPool<Endpoint, Channel> channels
82 = new GenericKeyedObjectPool<Endpoint, Channel>(new OnosCommunicationChannelFactory()); 99 = new GenericKeyedObjectPool<Endpoint, Channel>(new OnosCommunicationChannelFactory());
83 100
...@@ -103,7 +120,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -103,7 +120,7 @@ public class NettyMessagingService implements MessagingService {
103 clientChannelClass = NioSocketChannel.class; 120 clientChannelClass = NioSocketChannel.class;
104 } 121 }
105 122
106 - public NettyMessagingService(String ip, int port) { 123 + public NettyMessagingService(IpAddress ip, int port) {
107 localEp = new Endpoint(ip, port); 124 localEp = new Endpoint(ip, port);
108 } 125 }
109 126
...@@ -113,7 +130,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -113,7 +130,7 @@ public class NettyMessagingService implements MessagingService {
113 130
114 public NettyMessagingService(int port) { 131 public NettyMessagingService(int port) {
115 try { 132 try {
116 - localEp = new Endpoint(java.net.InetAddress.getLocalHost().getHostName(), port); 133 + localEp = new Endpoint(IpAddress.valueOf(InetAddress.getLocalHost()), port);
117 } catch (UnknownHostException e) { 134 } catch (UnknownHostException e) {
118 // Cannot resolve the local host, something is very wrong. Bailing out. 135 // Cannot resolve the local host, something is very wrong. Bailing out.
119 throw new IllegalStateException("Cannot resolve local host", e); 136 throw new IllegalStateException("Cannot resolve local host", e);
...@@ -146,7 +163,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -146,7 +163,7 @@ public class NettyMessagingService implements MessagingService {
146 InternalMessage message = new InternalMessage.Builder(this) 163 InternalMessage message = new InternalMessage.Builder(this)
147 .withId(messageIdGenerator.incrementAndGet()) 164 .withId(messageIdGenerator.incrementAndGet())
148 .withSender(localEp) 165 .withSender(localEp)
149 - .withType(type) 166 + .withType(messageTypeLookupCache.getUnchecked(type))
150 .withPayload(payload) 167 .withPayload(payload)
151 .build(); 168 .build();
152 sendAsync(ep, message); 169 sendAsync(ep, message);
...@@ -178,7 +195,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -178,7 +195,7 @@ public class NettyMessagingService implements MessagingService {
178 InternalMessage message = new InternalMessage.Builder(this) 195 InternalMessage message = new InternalMessage.Builder(this)
179 .withId(messageId) 196 .withId(messageId)
180 .withSender(localEp) 197 .withSender(localEp)
181 - .withType(type) 198 + .withType(messageTypeLookupCache.getUnchecked(type))
182 .withPayload(payload) 199 .withPayload(payload)
183 .build(); 200 .build();
184 try { 201 try {
...@@ -192,7 +209,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -192,7 +209,7 @@ public class NettyMessagingService implements MessagingService {
192 209
193 @Override 210 @Override
194 public void registerHandler(String type, MessageHandler handler) { 211 public void registerHandler(String type, MessageHandler handler) {
195 - handlers.putIfAbsent(type, handler); 212 + handlers.putIfAbsent(hashToLong(type), handler);
196 } 213 }
197 214
198 @Override 215 @Override
...@@ -200,7 +217,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -200,7 +217,7 @@ public class NettyMessagingService implements MessagingService {
200 handlers.remove(type); 217 handlers.remove(type);
201 } 218 }
202 219
203 - private MessageHandler getMessageHandler(String type) { 220 + private MessageHandler getMessageHandler(long type) {
204 return handlers.get(type); 221 return handlers.get(type);
205 } 222 }
206 223
...@@ -245,7 +262,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -245,7 +262,7 @@ public class NettyMessagingService implements MessagingService {
245 bootstrap.option(ChannelOption.SO_KEEPALIVE, true); 262 bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
246 bootstrap.handler(new OnosCommunicationChannelInitializer()); 263 bootstrap.handler(new OnosCommunicationChannelInitializer());
247 // Start the client. 264 // Start the client.
248 - ChannelFuture f = bootstrap.connect(ep.host(), ep.port()).sync(); 265 + ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()).sync();
249 return f.channel(); 266 return f.channel();
250 } 267 }
251 268
...@@ -295,8 +312,8 @@ public class NettyMessagingService implements MessagingService { ...@@ -295,8 +312,8 @@ public class NettyMessagingService implements MessagingService {
295 312
296 @Override 313 @Override
297 protected void channelRead0(ChannelHandlerContext ctx, InternalMessage message) throws Exception { 314 protected void channelRead0(ChannelHandlerContext ctx, InternalMessage message) throws Exception {
298 - String type = message.type(); 315 + long type = message.type();
299 - if (type.equals(InternalMessage.REPLY_MESSAGE_TYPE)) { 316 + if (type == InternalMessage.REPLY_MESSAGE_TYPE) {
300 try { 317 try {
301 SettableFuture<byte[]> futureResponse = 318 SettableFuture<byte[]> futureResponse =
302 NettyMessagingService.this.responseFutures.getIfPresent(message.id()); 319 NettyMessagingService.this.responseFutures.getIfPresent(message.id());
...@@ -326,4 +343,13 @@ public class NettyMessagingService implements MessagingService { ...@@ -326,4 +343,13 @@ public class NettyMessagingService implements MessagingService {
326 context.close(); 343 context.close();
327 } 344 }
328 } 345 }
346 +
347 + /**
348 + * Returns the md5 hash of the specified input string as a long.
349 + * @param input input string.
350 + * @return md5 hash as long.
351 + */
352 + public static long hashToLong(String input) {
353 + return Hashing.md5().hashBytes(input.getBytes(Charsets.UTF_8)).asLong();
354 + }
329 } 355 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -15,15 +15,16 @@ ...@@ -15,15 +15,16 @@
15 */ 15 */
16 package org.onlab.netty; 16 package org.onlab.netty;
17 17
18 +import static org.junit.Assert.assertArrayEquals;
19 +
20 +import java.net.InetAddress;
18 import java.util.concurrent.Future; 21 import java.util.concurrent.Future;
19 import java.util.concurrent.TimeUnit; 22 import java.util.concurrent.TimeUnit;
20 23
21 import org.apache.commons.lang3.RandomUtils; 24 import org.apache.commons.lang3.RandomUtils;
22 -
23 -import static org.junit.Assert.*;
24 -
25 import org.junit.Ignore; 25 import org.junit.Ignore;
26 import org.junit.Test; 26 import org.junit.Test;
27 +import org.onlab.packet.IpAddress;
27 28
28 /** 29 /**
29 * Simple ping-pong test that exercises NettyMessagingService. 30 * Simple ping-pong test that exercises NettyMessagingService.
...@@ -40,7 +41,9 @@ public class PingPongTest { ...@@ -40,7 +41,9 @@ public class PingPongTest {
40 ponger.activate(); 41 ponger.activate();
41 ponger.registerHandler("echo", new EchoHandler()); 42 ponger.registerHandler("echo", new EchoHandler());
42 byte[] payload = RandomUtils.nextBytes(100); 43 byte[] payload = RandomUtils.nextBytes(100);
43 - Future<byte[]> responseFuture = pinger.sendAndReceive(new Endpoint("localhost", 9086), "echo", payload); 44 + Future<byte[]> responseFuture =
45 + pinger.sendAndReceive(
46 + new Endpoint(IpAddress.valueOf(InetAddress.getLocalHost()), 9086), "echo", payload);
44 assertArrayEquals(payload, responseFuture.get(10000, TimeUnit.MILLISECONDS)); 47 assertArrayEquals(payload, responseFuture.get(10000, TimeUnit.MILLISECONDS));
45 } finally { 48 } finally {
46 pinger.deactivate(); 49 pinger.deactivate();
......