[#844] [#867] Add UDT transport

This commit is contained in:
Andrei.Pozolotin 2013-01-07 09:44:41 -06:00 committed by Norman Maurer
parent 26595471fb
commit 20aa2e1968
67 changed files with 5691 additions and 5 deletions

7
example/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
#
# native udt library extract location
#
/lib

View File

@ -17,6 +17,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
@ -54,7 +55,6 @@
<artifactId>netty-codec-socks</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
@ -64,6 +64,17 @@
<artifactId>netty-metrics-yammer</artifactId>
<version>${project.version}</version>
</dependency>
<!-- see https://github.com/netty/netty/issues/874 -->
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport-udt</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,106 @@
/*
* 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.example.udt.echo.bytes;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.example.udt.util.UtilConsoleReporter;
import io.netty.example.udt.util.UtilThreadFactory;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.net.InetSocketAddress;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* UDT Byte Stream Client
* <p>
* Sends one message when a connection is open and echoes back any received data
* to the server. Simply put, the echo client initiates the ping-pong traffic
* between the echo client and server by sending the first message to the
* server.
*/
public class ByteEchoClient {
private static final Logger log = LoggerFactory
.getLogger(ByteEchoClient.class);
private final String host;
private final int port;
private final int messageSize;
public ByteEchoClient(final String host, final int port,
final int messageSize) {
this.host = host;
this.port = port;
this.messageSize = messageSize;
}
public void run() throws Exception {
// Configure the client.
final Bootstrap boot = new Bootstrap();
final ThreadFactory connectFactory = new UtilThreadFactory("connect");
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.BYTE_PROVIDER);
try {
boot.group(connectGroup)
.channelFactory(NioUdtProvider.BYTE_CONNECTOR)
.localAddress("localhost", 0)
.remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch)
throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new ByteEchoClientHandler(messageSize));
}
});
// Start the client.
final ChannelFuture f = boot.connect().sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
boot.shutdown();
}
}
public static void main(final String[] args) throws Exception {
log.info("init");
// client is reporting metrics
UtilConsoleReporter.enable(3, TimeUnit.SECONDS);
final String host = "localhost";
final int port = 1234;
final int messageSize = 64 * 1024;
new ByteEchoClient(host, port, messageSize).run();
log.info("done");
}
}

View File

@ -0,0 +1,87 @@
/*
* 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.example.udt.echo.bytes;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundByteHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server on activation.
*/
public class ByteEchoClientHandler extends ChannelInboundByteHandlerAdapter {
private static final Logger log = LoggerFactory
.getLogger(ByteEchoClientHandler.class.getName());
private final ByteBuf message;
final Meter meter = Metrics.newMeter(ByteEchoClientHandler.class, "rate",
"bytes", TimeUnit.SECONDS);
public ByteEchoClientHandler(final int messageSize) {
message = Unpooled.buffer(messageSize);
for (int i = 0; i < message.capacity(); i++) {
message.writeByte((byte) i);
}
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
ctx.write(message);
}
@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx,
final ByteBuf in) {
meter.mark(in.readableBytes());
final ByteBuf out = ctx.nextOutboundByteBuffer();
out.discardReadBytes();
out.writeBytes(in);
ctx.flush();
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable cause) {
log.error("close the connection when an exception is raised", cause);
ctx.close();
}
@Override
public ByteBuf newInboundBuffer(final ChannelHandlerContext ctx)
throws Exception {
return ctx.alloc().directBuffer(
ctx.channel().config().getOption(ChannelOption.SO_RCVBUF));
}
}

View File

@ -0,0 +1,94 @@
/*
* 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.example.udt.echo.bytes;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.example.udt.util.UtilThreadFactory;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.util.concurrent.ThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* UDT Byte Stream Server
* <p>
* Echoes back any received data from a client.
*/
public class ByteEchoServer {
private static final Logger log = LoggerFactory
.getLogger(ByteEchoServer.class);
private final int port;
public ByteEchoServer(final int port) {
this.port = port;
}
public void run() throws Exception {
final ThreadFactory acceptFactory = new UtilThreadFactory("accept");
final ThreadFactory connectFactory = new UtilThreadFactory("connect");
final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1,
acceptFactory, NioUdtProvider.BYTE_PROVIDER);
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.BYTE_PROVIDER);
// Configure the server.
final ServerBootstrap boot = new ServerBootstrap();
try {
boot.group(acceptGroup, connectGroup)
.channelFactory(NioUdtProvider.BYTE_ACCEPTOR)
.option(ChannelOption.SO_BACKLOG, 10)
.localAddress("localhost", port)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch)
throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new ByteEchoServerHandler());
}
});
// Start the server.
final ChannelFuture future = boot.bind().sync();
// Wait until the server socket is closed.
future.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
boot.shutdown();
}
}
public static void main(final String[] args) throws Exception {
log.info("init");
final int port = 1234;
new ByteEchoServer(port).run();
log.info("done");
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.example.udt.echo.bytes;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundByteHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.transport.udt.nio.NioUdtProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handler implementation for the echo server.
*/
@Sharable
public class ByteEchoServerHandler extends ChannelInboundByteHandlerAdapter {
private static final Logger log = LoggerFactory
.getLogger(ByteEchoServerHandler.class.getName());
@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx,
final ByteBuf in) {
final ByteBuf out = ctx.nextOutboundByteBuffer();
out.discardReadBytes();
out.writeBytes(in);
ctx.flush();
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable cause) {
log.error("close the connection when an exception is raised", cause);
ctx.close();
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
}
@Override
public ByteBuf newInboundBuffer(final ChannelHandlerContext ctx)
throws Exception {
return ctx.alloc().directBuffer(
ctx.channel().config().getOption(ChannelOption.SO_RCVBUF));
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Examples show how to use UDT Byte Streams.
*/
package io.netty.example.udt.echo.bytes;

View File

@ -0,0 +1,106 @@
/*
* 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.example.udt.echo.message;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.example.udt.util.UtilConsoleReporter;
import io.netty.example.udt.util.UtilThreadFactory;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.net.InetSocketAddress;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* UDT Message Flow client
* <p>
* Sends one message when a connection is open and echoes back any received data
* to the server. Simply put, the echo client initiates the ping-pong traffic
* between the echo client and server by sending the first message to the
* server.
*/
public class MsgEchoClient {
private static final Logger log = LoggerFactory
.getLogger(MsgEchoClient.class);
private final String host;
private final int port;
private final int messageSize;
public MsgEchoClient(final String host, final int port,
final int messageSize) {
this.host = host;
this.port = port;
this.messageSize = messageSize;
}
public void run() throws Exception {
// Configure the client.
final Bootstrap boot = new Bootstrap();
final ThreadFactory connectFactory = new UtilThreadFactory("connect");
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
try {
boot.group(connectGroup)
.channelFactory(NioUdtProvider.MESSAGE_CONNECTOR)
.localAddress("localhost", 0)
.remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch)
throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new MsgEchoClientHandler(messageSize));
}
});
// Start the client.
final ChannelFuture f = boot.connect().sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
boot.shutdown();
}
}
public static void main(final String[] args) throws Exception {
log.info("init");
// client is reporting metrics
UtilConsoleReporter.enable(3, TimeUnit.SECONDS);
final String host = "localhost";
final int port = 1234;
final int messageSize = 64 * 1024;
new MsgEchoClient(host, port, messageSize).run();
log.info("done");
}
}

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.example.udt.echo.message;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.transport.udt.UdtMessage;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server on activation.
*/
public class MsgEchoClientHandler extends
ChannelInboundMessageHandlerAdapter<UdtMessage> {
private static final Logger log = LoggerFactory
.getLogger(MsgEchoClientHandler.class.getName());
private final UdtMessage message;
public MsgEchoClientHandler(final int messageSize) {
final ByteBuf byteBuf = Unpooled.buffer(messageSize);
for (int i = 0; i < byteBuf.capacity(); i++) {
byteBuf.writeByte((byte) i);
}
message = new UdtMessage(byteBuf);
}
final Meter meter = Metrics.newMeter(MsgEchoClientHandler.class, "rate",
"bytes", TimeUnit.SECONDS);
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable cause) {
log.error("close the connection when an exception is raised", cause);
ctx.close();
}
@Override
protected void messageReceived(final ChannelHandlerContext ctx,
final UdtMessage message) throws Exception {
final ByteBuf byteBuf = message.data();
meter.mark(byteBuf.readableBytes());
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
}

View File

@ -0,0 +1,94 @@
/*
* 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.example.udt.echo.message;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.example.udt.util.UtilThreadFactory;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.util.concurrent.ThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* UDT Message Flow Server
* <p>
* Echoes back any received data from a client.
*/
public class MsgEchoServer {
private static final Logger log = LoggerFactory
.getLogger(MsgEchoServer.class);
private final int port;
public MsgEchoServer(final int port) {
this.port = port;
}
public void run() throws Exception {
final ThreadFactory acceptFactory = new UtilThreadFactory("accept");
final ThreadFactory connectFactory = new UtilThreadFactory("connect");
final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1,
acceptFactory, NioUdtProvider.MESSAGE_PROVIDER);
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
// Configure the server.
final ServerBootstrap boot = new ServerBootstrap();
try {
boot.group(acceptGroup, connectGroup)
.channelFactory(NioUdtProvider.MESSAGE_ACCEPTOR)
.option(ChannelOption.SO_BACKLOG, 10)
.localAddress("localhost", port)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch)
throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new MsgEchoServerHandler());
}
});
// Start the server.
final ChannelFuture future = boot.bind().sync();
// Wait until the server socket is closed.
future.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
boot.shutdown();
}
}
public static void main(final String[] args) throws Exception {
log.info("init");
final int port = 1234;
new MsgEchoServer(port).run();
log.info("done");
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.example.udt.echo.message;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.transport.udt.UdtMessage;
import io.netty.transport.udt.nio.NioUdtProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handler implementation for the echo server.
*/
@Sharable
public class MsgEchoServerHandler extends
ChannelInboundMessageHandlerAdapter<UdtMessage> {
private static final Logger log = LoggerFactory
.getLogger(MsgEchoServerHandler.class.getName());
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable cause) {
log.error("close the connection when an exception is raised", cause);
ctx.close();
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
}
@Override
protected void messageReceived(final ChannelHandlerContext ctx,
final UdtMessage message) throws Exception {
final ByteBuf byteBuf = message.data();
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Examples show how to use UDT Message Flows.
*/
package io.netty.example.udt.echo.message;

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Examples show how to use UDT with simple Echo Handlers.
*/
package io.netty.example.udt.echo;

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.example.udt.echo.rendevous;
/**
* Peer to Peer Config
*/
public final class Config {
private Config() {
}
public static final String hostOne = "localhost";
public static final int portOne = 1231;
public static final String hostTwo = "localhost";
public static final int portTwo = 1232;
}

View File

@ -0,0 +1,85 @@
/*
* 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.example.udt.echo.rendevous;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.example.udt.util.UtilThreadFactory;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.net.InetSocketAddress;
import java.util.concurrent.ThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* UDT Message Flow Peer
* <p>
* Sends one message when a connection is open and echoes back any received data
* to the other peer.
*/
public abstract class MsgEchoPeerBase {
protected static final Logger log = LoggerFactory
.getLogger(MsgEchoPeerBase.class);
protected final int messageSize;
protected final InetSocketAddress self;
protected final InetSocketAddress peer;
public MsgEchoPeerBase(final InetSocketAddress self,
final InetSocketAddress peer, final int messageSize) {
this.messageSize = messageSize;
this.self = self;
this.peer = peer;
}
public void run() throws Exception {
// Configure the peer.
final Bootstrap boot = new Bootstrap();
final ThreadFactory connectFactory = new UtilThreadFactory("rendezvous");
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
try {
boot.group(connectGroup)
.channelFactory(NioUdtProvider.MESSAGE_RENDEZVOUS)
.localAddress(self).remoteAddress(peer)
.handler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch)
throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new MsgEchoPeerHandler(messageSize));
}
});
// Start the peer.
final ChannelFuture f = boot.connect().sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
boot.shutdown();
}
}
}

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.example.udt.echo.rendevous;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.transport.udt.UdtMessage;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
/**
* Handler implementation for the echo peer. It initiates the ping-pong traffic
* between the echo peers by sending the first message to the other peer on
* activation.
*/
public class MsgEchoPeerHandler extends
ChannelInboundMessageHandlerAdapter<UdtMessage> {
private static final Logger log = LoggerFactory
.getLogger(MsgEchoPeerHandler.class.getName());
private final UdtMessage message;
public MsgEchoPeerHandler(final int messageSize) {
final ByteBuf byteBuf = Unpooled.buffer(messageSize);
for (int i = 0; i < byteBuf.capacity(); i++) {
byteBuf.writeByte((byte) i);
}
message = new UdtMessage(byteBuf);
}
final Meter meter = Metrics.newMeter(MsgEchoPeerHandler.class, "rate",
"bytes", TimeUnit.SECONDS);
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable cause) {
log.error("close the connection when an exception is raised", cause);
ctx.close();
}
@Override
protected void messageReceived(final ChannelHandlerContext ctx,
final UdtMessage message) throws Exception {
final ByteBuf byteBuf = message.data();
meter.mark(byteBuf.readableBytes());
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.example.udt.echo.rendevous;
import java.net.InetSocketAddress;
/**
* UDT Message Flow Peer
* <p>
* Sends one message when a connection is open and echoes back any received data
* to the other peer.
*/
public class MsgEchoPeerOne extends MsgEchoPeerBase {
public MsgEchoPeerOne(final InetSocketAddress self,
final InetSocketAddress peer, final int messageSize) {
super(self, peer, messageSize);
}
public static void main(final String[] args) throws Exception {
log.info("init");
// peer one is not reporting metrics
// ConsoleReporterUDT.enable(3, TimeUnit.SECONDS);
final int messageSize = 64 * 1024;
final InetSocketAddress self = new InetSocketAddress(Config.hostOne,
Config.portOne);
final InetSocketAddress peer = new InetSocketAddress(Config.hostTwo,
Config.portTwo);
new MsgEchoPeerOne(self, peer, messageSize).run();
log.info("done");
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.example.udt.echo.rendevous;
import io.netty.example.udt.util.UtilConsoleReporter;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
/**
* UDT Message Flow Peer
* <p>
* Sends one message when a connection is open and echoes back any received data
* to the other peer.
*/
public class MsgEchoPeerTwo extends MsgEchoPeerBase {
public MsgEchoPeerTwo(final InetSocketAddress self,
final InetSocketAddress peer, final int messageSize) {
super(self, peer, messageSize);
}
public static void main(final String[] args) throws Exception {
log.info("init");
// peer two is reporting metrics
UtilConsoleReporter.enable(3, TimeUnit.SECONDS);
final int messageSize = 64 * 1024;
final InetSocketAddress self = new InetSocketAddress(Config.hostTwo,
Config.portTwo);
final InetSocketAddress peer = new InetSocketAddress(Config.hostOne,
Config.portOne);
new MsgEchoPeerTwo(self, peer, messageSize).run();
log.info("done");
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Examples show how to use UDT Message Rendezvous.
*/
package io.netty.example.udt.echo.rendevous;

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Examples show how to use UDT.
*/
package io.netty.example.udt;

View File

@ -0,0 +1,250 @@
/*
* 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.example.udt.util;
import java.io.PrintStream;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Clock;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.core.Histogram;
import com.yammer.metrics.core.Metered;
import com.yammer.metrics.core.Metric;
import com.yammer.metrics.core.MetricName;
import com.yammer.metrics.core.MetricPredicate;
import com.yammer.metrics.core.MetricProcessor;
import com.yammer.metrics.core.MetricsRegistry;
import com.yammer.metrics.core.Timer;
import com.yammer.metrics.reporting.AbstractPollingReporter;
import com.yammer.metrics.stats.Snapshot;
/**
* A simple reporters which prints out application metrics to a
* {@link PrintStream} periodically.
*/
public class UtilConsoleReporter extends AbstractPollingReporter implements
MetricProcessor<PrintStream> {
private static final int CONSOLE_WIDTH = 80;
/**
* Enables the console reporter for the default metrics registry, and causes
* it to print to STDOUT with the specified period.
*/
public static void enable(final long period, final TimeUnit unit) {
enable(Metrics.defaultRegistry(), period, unit);
}
/**
* Enables the console reporter for the given metrics registry, and causes
* it to print to STDOUT with the specified period and unrestricted output.
*/
public static void enable(final MetricsRegistry metricsRegistry,
final long period, final TimeUnit unit) {
final UtilConsoleReporter reporter = new UtilConsoleReporter(
metricsRegistry, System.out, MetricPredicate.ALL);
reporter.start(period, unit);
}
private final PrintStream out;
private final MetricPredicate predicate;
private final Clock clock;
private final TimeZone timeZone;
private final Locale locale;
/**
* Creates a new {@link UtilConsoleReporter} for the default metrics
* registry, with unrestricted output.
*/
public UtilConsoleReporter(final PrintStream out) {
this(Metrics.defaultRegistry(), out, MetricPredicate.ALL);
}
/**
* Creates a new {@link UtilConsoleReporter} for a given metrics registry.
*/
public UtilConsoleReporter(final MetricsRegistry metricsRegistry,
final PrintStream out, final MetricPredicate predicate) {
this(metricsRegistry, out, predicate, Clock.defaultClock(), TimeZone
.getDefault());
}
/**
* Creates a new {@link UtilConsoleReporter} for a given metrics registry.
*/
public UtilConsoleReporter(final MetricsRegistry metricsRegistry,
final PrintStream out, final MetricPredicate predicate,
final Clock clock, final TimeZone timeZone) {
this(metricsRegistry, out, predicate, clock, timeZone, Locale
.getDefault());
}
/**
* Creates a new {@link UtilConsoleReporter} for a given metrics registry.
*/
public UtilConsoleReporter(final MetricsRegistry metricsRegistry,
final PrintStream out, final MetricPredicate predicate,
final Clock clock, final TimeZone timeZone, final Locale locale) {
super(metricsRegistry, "console-reporter");
this.out = out;
this.predicate = predicate;
this.clock = clock;
this.timeZone = timeZone;
this.locale = locale;
}
@Override
public void run() {
try {
final DateFormat format = DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.MEDIUM, locale);
format.setTimeZone(timeZone);
final String dateTime = format.format(new Date(clock.time()));
out.print(dateTime);
out.print(' ');
for (int i = 0; i < (CONSOLE_WIDTH - dateTime.length() - 1); i++) {
out.print('=');
}
out.println();
for (final Entry<String, SortedMap<MetricName, Metric>> entry : getMetricsRegistry()
.groupedMetrics(predicate).entrySet()) {
out.print(entry.getKey());
out.println(':');
for (final Entry<MetricName, Metric> subEntry : entry
.getValue().entrySet()) {
out.print(" ");
out.print(subEntry.getKey().getName());
out.println(':');
subEntry.getValue().processWith(this, subEntry.getKey(),
out);
out.println();
}
out.println();
}
out.println();
out.flush();
} catch (final Exception e) {
e.printStackTrace(out);
}
}
@Override
public void processGauge(final MetricName name, final Gauge<?> gauge,
final PrintStream stream) {
stream.printf(locale, " value = %s\n", gauge.value());
}
@Override
public void processCounter(final MetricName name, final Counter counter,
final PrintStream stream) {
stream.printf(locale, " count = %,d\n", counter.count());
}
@Override
public void processMeter(final MetricName name, final Metered meter,
final PrintStream stream) {
final String unit = abbrev(meter.rateUnit());
stream.printf(locale, " count = %,d\n", meter.count());
stream.printf(locale, " mean rate = %,2.2f %s/%s\n",
meter.meanRate(), meter.eventType(), unit);
stream.printf(locale, " 1-minute rate = %,2.2f %s/%s\n",
meter.oneMinuteRate(), meter.eventType(), unit);
stream.printf(locale, " 5-minute rate = %,2.2f %s/%s\n",
meter.fiveMinuteRate(), meter.eventType(), unit);
stream.printf(locale, " 15-minute rate = %,2.2f %s/%s\n",
meter.fifteenMinuteRate(), meter.eventType(), unit);
}
@Override
public void processHistogram(final MetricName name,
final Histogram histogram, final PrintStream stream) {
final Snapshot snapshot = histogram.getSnapshot();
stream.printf(locale, " min = %,2.2f\n", histogram.min());
stream.printf(locale, " max = %,2.2f\n", histogram.max());
stream.printf(locale, " mean = %,2.2f\n", histogram.mean());
stream.printf(locale, " stddev = %,2.2f\n",
histogram.stdDev());
stream.printf(locale, " median = %,2.2f\n",
snapshot.getMedian());
stream.printf(locale, " 75%% <= %,2.2f\n",
snapshot.get75thPercentile());
stream.printf(locale, " 95%% <= %,2.2f\n",
snapshot.get95thPercentile());
stream.printf(locale, " 98%% <= %,2.2f\n",
snapshot.get98thPercentile());
stream.printf(locale, " 99%% <= %,2.2f\n",
snapshot.get99thPercentile());
stream.printf(locale, " 99.9%% <= %,2.2f\n",
snapshot.get999thPercentile());
}
@Override
public void processTimer(final MetricName name, final Timer timer,
final PrintStream stream) {
processMeter(name, timer, stream);
final String durationUnit = abbrev(timer.durationUnit());
final Snapshot snapshot = timer.getSnapshot();
stream.printf(locale, " min = %,2.2f %s\n", timer.min(),
durationUnit);
stream.printf(locale, " max = %,2.2f %s\n", timer.max(),
durationUnit);
stream.printf(locale, " mean = %,2.2f %s\n", timer.mean(),
durationUnit);
stream.printf(locale, " stddev = %,2.2f %s\n",
timer.stdDev(), durationUnit);
stream.printf(locale, " median = %,2.2f %s\n",
snapshot.getMedian(), durationUnit);
stream.printf(locale, " 75%% <= %,2.2f %s\n",
snapshot.get75thPercentile(), durationUnit);
stream.printf(locale, " 95%% <= %,2.2f %s\n",
snapshot.get95thPercentile(), durationUnit);
stream.printf(locale, " 98%% <= %,2.2f %s\n",
snapshot.get98thPercentile(), durationUnit);
stream.printf(locale, " 99%% <= %,2.2f %s\n",
snapshot.get99thPercentile(), durationUnit);
stream.printf(locale, " 99.9%% <= %,2.2f %s\n",
snapshot.get999thPercentile(), durationUnit);
}
private String abbrev(final TimeUnit unit) {
switch (unit) {
case NANOSECONDS:
return "ns";
case MICROSECONDS:
return "us";
case MILLISECONDS:
return "ms";
case SECONDS:
return "s";
case MINUTES:
return "m";
case HOURS:
return "h";
case DAYS:
return "d";
default:
throw new IllegalArgumentException("Unrecognized TimeUnit: " + unit);
}
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.example.udt.util;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Custom thread factory to use with examples.
*/
public class UtilThreadFactory implements ThreadFactory {
private static final AtomicInteger counter = new AtomicInteger();
private final String name;
public UtilThreadFactory(final String name) {
this.name = name;
}
@Override
public Thread newThread(final Runnable runnable) {
return new Thread(runnable, name + "-" + counter.getAndIncrement());
};
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Utilities for UDT examples.
*/
package io.netty.example.udt.util;

View File

@ -80,6 +80,7 @@
<module>codec-socks</module>
<module>transport</module>
<module>transport-sctp</module>
<module>transport-udt</module>
<module>handler</module>
<module>metrics-yammer</module>
<module>example</module>
@ -220,9 +221,9 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.6</version>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.9</version>
<scope>test</scope>
</dependency>
</dependencies>

7
transport-udt/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
#
# native udt library extract location
#
/lib

101
transport-udt/pom.xml Normal file
View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
<version>4.0.0.Beta1-SNAPSHOT</version>
</parent>
<artifactId>netty-transport-udt</artifactId>
<packaging>jar</packaging>
<name>Netty/Transport/UDT</name>
<dependencies>
<!-- MAIN -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-buffer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-transport</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.barchart.udt</groupId>
<artifactId>barchart-udt-bundle</artifactId>
<version>2.2.0</version>
</dependency>
<!-- TEST -->
<!-- see https://github.com/netty/netty/issues/874 -->
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.caliper</groupId>
<artifactId>caliper</artifactId>
<version>0.5-rc1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,250 @@
/*
* 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.transport.udt;
import static io.netty.channel.ChannelOption.*;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import java.io.IOException;
import java.util.Map;
import com.barchart.udt.OptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.nio.ChannelUDT;
/**
* The default {@link UdtChannelConfig} implementation.
*/
public class DefaultUdtChannelConfig extends DefaultChannelConfig implements
UdtChannelConfig {
private static final int K = 1024;
private static final int M = K * K;
private volatile int protocolReceiveBuferSize = 10 * M;
private volatile int protocolSendBuferSize = 10 * M;
private volatile int systemReceiveBufferSize = 1 * M;
private volatile int systemSendBuferSize = 1 * M;
private volatile int allocatorReceiveBufferSize = 128 * K;
private volatile int allocatorSendBufferSize = 128 * K;
private volatile int backlog = 64;
private volatile int soLinger;
private volatile boolean reuseAddress = true;
public DefaultUdtChannelConfig(final UdtChannel channel,
final ChannelUDT channelUDT, final boolean apply)
throws IOException {
super(channel);
if (apply) {
apply(channelUDT);
}
}
protected void apply(final ChannelUDT channelUDT) throws IOException {
final SocketUDT socketUDT = channelUDT.socketUDT();
socketUDT.setReuseAddress(isReuseAddress());
socketUDT.setSendBufferSize(getSendBufferSize());
if (getSoLinger() <= 0) {
socketUDT.setSoLinger(false, 0);
} else {
socketUDT.setSoLinger(true, getSoLinger());
}
socketUDT.setOption(OptionUDT.Protocol_Receive_Buffer_Size,
getProtocolReceiveBufferSize());
socketUDT.setOption(OptionUDT.Protocol_Send_Buffer_Size,
getProtocolSendBufferSize());
socketUDT.setOption(OptionUDT.System_Receive_Buffer_Size,
getSystemReceiveBufferSize());
socketUDT.setOption(OptionUDT.System_Send_Buffer_Size,
getSystemSendBufferSize());
}
@Override
public int getProtocolReceiveBufferSize() {
return protocolReceiveBuferSize;
}
@Override
public int getBacklog() {
return backlog;
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(final ChannelOption<T> option) {
if (option == PROTOCOL_RECEIVE_BUFFER_SIZE) {
return (T) Integer.valueOf(getProtocolReceiveBufferSize());
}
if (option == PROTOCOL_SEND_BUFFER_SIZE) {
return (T) Integer.valueOf(getProtocolSendBufferSize());
}
if (option == SYSTEM_RECEIVE_BUFFER_SIZE) {
return (T) Integer.valueOf(getSystemReceiveBufferSize());
}
if (option == SYSTEM_SEND_BUFFER_SIZE) {
return (T) Integer.valueOf(getSystemSendBufferSize());
}
if (option == SO_RCVBUF) {
return (T) Integer.valueOf(getReceiveBufferSize());
}
if (option == SO_SNDBUF) {
return (T) Integer.valueOf(getSendBufferSize());
}
if (option == SO_REUSEADDR) {
return (T) Boolean.valueOf(isReuseAddress());
}
if (option == SO_LINGER) {
return (T) Integer.valueOf(getSoLinger());
}
if (option == SO_BACKLOG) {
return (T) Integer.valueOf(getBacklog());
}
return super.getOption(option);
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(super.getOptions(), PROTOCOL_RECEIVE_BUFFER_SIZE,
PROTOCOL_SEND_BUFFER_SIZE, SYSTEM_RECEIVE_BUFFER_SIZE,
SYSTEM_SEND_BUFFER_SIZE, SO_RCVBUF, SO_SNDBUF, SO_REUSEADDR,
SO_LINGER, SO_BACKLOG);
}
@Override
public int getReceiveBufferSize() {
return allocatorReceiveBufferSize;
}
@Override
public int getSendBufferSize() {
return allocatorSendBufferSize;
}
@Override
public int getSoLinger() {
return soLinger;
}
@Override
public boolean isReuseAddress() {
return reuseAddress;
}
@Override
public UdtChannelConfig setProtocolReceiveBufferSize(final int allocator) {
this.protocolReceiveBuferSize = allocator;
return this;
}
@Override
public UdtChannelConfig setBacklog(final int backlog) {
this.backlog = backlog;
return this;
}
@Override
public <T> boolean setOption(final ChannelOption<T> option, final T value) {
validate(option, value);
if (option == PROTOCOL_RECEIVE_BUFFER_SIZE) {
setProtocolReceiveBufferSize((Integer) value);
} else if (option == PROTOCOL_SEND_BUFFER_SIZE) {
setProtocolSendBufferSize((Integer) value);
} else if (option == SYSTEM_RECEIVE_BUFFER_SIZE) {
setSystemReceiveBufferSize((Integer) value);
} else if (option == SYSTEM_SEND_BUFFER_SIZE) {
setSystemSendBufferSize((Integer) value);
} else if (option == SO_RCVBUF) {
setReceiveBufferSize((Integer) value);
} else if (option == SO_SNDBUF) {
setSendBufferSize((Integer) value);
} else if (option == SO_REUSEADDR) {
setReuseAddress((Boolean) value);
} else if (option == SO_LINGER) {
setSoLinger((Integer) value);
} else if (option == SO_BACKLOG) {
setBacklog((Integer) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public UdtChannelConfig setReceiveBufferSize(final int receiveBufferSize) {
allocatorReceiveBufferSize = receiveBufferSize;
return this;
}
@Override
public UdtChannelConfig setReuseAddress(final boolean reuseAddress) {
this.reuseAddress = reuseAddress;
return this;
}
@Override
public UdtChannelConfig setSendBufferSize(final int sendBufferSize) {
allocatorSendBufferSize = sendBufferSize;
return this;
}
@Override
public UdtChannelConfig setSoLinger(final int soLinger) {
this.soLinger = soLinger;
return this;
}
@Override
public int getSystemReceiveBufferSize() {
return systemReceiveBufferSize;
}
@Override
public UdtChannelConfig setSystemSendBufferSize(
final int systemReceiveBufferSize) {
this.systemReceiveBufferSize = systemReceiveBufferSize;
return this;
}
@Override
public int getProtocolSendBufferSize() {
return protocolSendBuferSize;
}
@Override
public UdtChannelConfig setProtocolSendBufferSize(
final int protocolSendBuferSize) {
this.protocolSendBuferSize = protocolSendBuferSize;
return this;
}
@Override
public UdtChannelConfig setSystemReceiveBufferSize(
final int systemSendBuferSize) {
this.systemSendBuferSize = systemSendBuferSize;
return this;
}
@Override
public int getSystemSendBufferSize() {
return systemSendBuferSize;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.transport.udt;
import io.netty.channel.Channel;
import io.netty.transport.udt.nio.NioUdtProvider;
/**
* UDT {@link Channel}.
* <p>
* Supported UDT {@link UdtChannel} are available via {@link NioUdtProvider}.
*/
public interface UdtChannel extends Channel {
/**
* Returns the {@link UdtChannelConfig} of the channel.
*/
@Override
UdtChannelConfig config();
}

View File

@ -0,0 +1,185 @@
/*
* 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.transport.udt;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import com.barchart.udt.OptionUDT;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.KindUDT;
/**
* A {@link ChannelConfig} for a {@link UdtChannel}.
* <p>
* <h3>Available options</h3>
* In addition to the options provided by {@link ChannelConfig},
* {@link UdtChannelConfig} allows the following options in the option map:
* <p>
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th>
* <th>Associated setter method</th>
* </tr>
* <tr>
* <td>{@code "reuseAddress"}</td>
* <td>{@link #setReuseAddress(boolean)}</td>
* </tr>
* <tr>
* <td>{@code "soLinger"}</td>
* <td>{@link #setSoLinger(int)}</td>
* </tr>
* <tr>
* <td>{@code "receiveBufferSize"}</td>
* <td>{@link #setReceiveBufferSize(int)}</td>
* </tr>
* <tr>
* <td>{@code "sendBufferSize"}</td>
* <td>{@link #setSendBufferSize(int)}</td>
* </tr>
* <tr>
* <td>{@code "protocolReceiveBuferSize"}</td>
* <td>{@link #setProtocolBufferSize(int)}</td>
* <tr>
* <tr>
* <td>{@code "systemReceiveBufferSize"}</td>
* <td>{@link #setSystemBufferSize(int)}</td>
* <tr>
* </table>
* <p>
* Note that {@link TypeUDT#DATAGRAM} message oriented channels treat
* {@code "receiveBufferSize"} and {@code "sendBufferSize"} as maximum message
* size. If received or sent message does not fit specified sizes,
* {@link ChannelException} will be thrown.
*/
public interface UdtChannelConfig extends ChannelConfig {
/**
* See {@link OptionUDT#Protocol_Receive_Buffer_Size}.
*/
ChannelOption<Integer> PROTOCOL_RECEIVE_BUFFER_SIZE = new ChannelOption<Integer>(
"PROTOCOL_RECEIVE_BUFFER_SIZE");
/**
* See {@link OptionUDT#Protocol_Send_Buffer_Size}.
*/
ChannelOption<Integer> PROTOCOL_SEND_BUFFER_SIZE = new ChannelOption<Integer>(
"PROTOCOL_SEND_BUFFER_SIZE");
/**
* See {@link OptionUDT#System_Receive_Buffer_Size}.
*/
ChannelOption<Integer> SYSTEM_RECEIVE_BUFFER_SIZE = new ChannelOption<Integer>(
"SYSTEM_RECEIVE_BUFFER_SIZE");
/**
* See {@link OptionUDT#System_Send_Buffer_Size}.
*/
ChannelOption<Integer> SYSTEM_SEND_BUFFER_SIZE = new ChannelOption<Integer>(
"SYSTEM_SEND_BUFFER_SIZE");
/**
* Gets {@link KindUDT#ACCEPTOR} channel backlog.
*/
int getBacklog();
/**
* Gets {@link OptionUDT#Protocol_Receive_Buffer_Size}
*/
int getProtocolReceiveBufferSize();
/**
* Gets {@link OptionUDT#Protocol_Send_Buffer_Size}
*/
int getProtocolSendBufferSize();
/**
* Gets the {@link ChannelOption#SO_RCVBUF} option.
*/
int getReceiveBufferSize();
/**
* Gets the {@link ChannelOption#SO_SNDBUF} option.
*/
int getSendBufferSize();
/**
* Gets the {@link ChannelOption#SO_LINGER} option.
*/
int getSoLinger();
/**
* Gets {@link OptionUDT#System_Receive_Buffer_Size}
*/
int getSystemReceiveBufferSize();
/**
* Gets {@link OptionUDT#System_Send_Buffer_Size}
*/
int getSystemSendBufferSize();
/**
* Gets the {@link ChannelOption#SO_REUSEADDR} option.
*/
boolean isReuseAddress();
/**
* Sets {@link KindUDT#ACCEPTOR} channel backlog.
*/
UdtChannelConfig setBacklog(int backlog);
/**
* Sets {@link OptionUDT#Protocol_Receive_Buffer_Size}
*/
UdtChannelConfig setProtocolReceiveBufferSize(int size);
/**
* Sets {@link OptionUDT#Protocol_Send_Buffer_Size}
*/
UdtChannelConfig setProtocolSendBufferSize(int size);
/**
* Sets the {@link ChannelOption#SO_RCVBUF} option.
*/
UdtChannelConfig setReceiveBufferSize(int receiveBufferSize);
/**
* Sets the {@link ChannelOption#SO_REUSEADDR} option.
*/
UdtChannelConfig setReuseAddress(boolean reuseAddress);
/**
* Sets the {@link ChannelOption#SO_SNDBUF} option.
*/
UdtChannelConfig setSendBufferSize(int sendBufferSize);
/**
* Sets the {@link ChannelOption#SO_LINGER} option.
*/
UdtChannelConfig setSoLinger(int soLinger);
/**
* Sets {@link OptionUDT#System_Receive_Buffer_Size}
*/
UdtChannelConfig setSystemReceiveBufferSize(int size);
/**
* Sets {@link OptionUDT#System_Send_Buffer_Size}
*/
UdtChannelConfig setSystemSendBufferSize(int size);
}

View File

@ -0,0 +1,40 @@
/*
* 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.transport.udt;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
import io.netty.transport.udt.nio.NioUdtProvider;
import com.barchart.udt.TypeUDT;
/**
* The message container that is used for {@link TypeUDT#DATAGRAM} messages.
* @see {@link NioUdtProvider#MESSAGE_CONNECTOR}
* @see {@link NioUdtProvider#MESSAGE_RENDEZVOUS}
*/
public final class UdtMessage extends DefaultByteBufHolder {
public UdtMessage(final ByteBuf data) {
super(data);
}
@Override
public UdtMessage copy() {
return new UdtMessage(data().copy());
}
}

View File

@ -0,0 +1,128 @@
/*
* 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.transport.udt.nio;
import static java.nio.channels.SelectionKey.*;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelException;
import io.netty.channel.socket.nio.AbstractNioMessageChannel;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import io.netty.transport.udt.DefaultUdtChannelConfig;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.UdtChannelConfig;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.ServerSocketChannelUDT;
/**
* Common base for Netty Byte/Message UDT Stream/Datagram acceptors.
*/
public abstract class NioUdtAcceptorChannel extends AbstractNioMessageChannel
implements UdtChannel {
protected static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtAcceptorChannel.class);
private final UdtChannelConfig config;
protected NioUdtAcceptorChannel(final ServerSocketChannelUDT channelUDT) {
super(null, channelUDT.socketUDT().id(), channelUDT, OP_ACCEPT);
try {
channelUDT.configureBlocking(false);
config = new DefaultUdtChannelConfig(this, channelUDT, true);
} catch (final Exception e) {
try {
channelUDT.close();
} catch (final Exception e2) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close channel.", e2);
}
}
throw new ChannelException("Failed configure channel.", e);
}
}
protected NioUdtAcceptorChannel(final TypeUDT type) {
this(NioUdtProvider.newAcceptorChannelUDT(type));
}
@Override
public UdtChannelConfig config() {
return config;
}
@Override
protected void doBind(final SocketAddress localAddress) throws Exception {
javaChannel().socket().bind(localAddress, config.getBacklog());
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected boolean doConnect(final SocketAddress remoteAddress,
final SocketAddress localAddress) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected void doDisconnect() throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected void doFinishConnect() throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected int doWriteMessages(final MessageBuf<Object> buf,
final boolean lastSpin) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public boolean isActive() {
return javaChannel().socket().isBound();
}
@Override
protected ServerSocketChannelUDT javaChannel() {
return (ServerSocketChannelUDT) super.javaChannel();
}
@Override
protected SocketAddress localAddress0() {
return javaChannel().socket().getLocalSocketAddress();
}
@Override
public InetSocketAddress remoteAddress() {
return null;
}
@Override
protected SocketAddress remoteAddress0() {
return null;
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.transport.udt.nio;
import io.netty.buffer.BufType;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelMetadata;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.SocketChannelUDT;
/**
* Byte Channel Acceptor for UDT Streams.
*/
public class NioUdtByteAcceptorChannel extends NioUdtAcceptorChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtByteAcceptorChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(
BufType.BYTE, false);
public NioUdtByteAcceptorChannel() {
super(TypeUDT.STREAM);
}
@Override
protected int doReadMessages(final MessageBuf<Object> buf) throws Exception {
final SocketChannelUDT channelUDT = javaChannel().accept();
if (channelUDT == null) {
return 0;
} else {
buf.add(new NioUdtByteConnectorChannel(this, channelUDT.socketUDT()
.id(), channelUDT));
return 1;
}
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
}

View File

@ -0,0 +1,194 @@
/*
* 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.transport.udt.nio;
import static java.nio.channels.SelectionKey.*;
import io.netty.buffer.BufType;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.socket.nio.AbstractNioByteChannel;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import io.netty.transport.udt.DefaultUdtChannelConfig;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.UdtChannelConfig;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.SocketChannelUDT;
/**
* Byte Channel Connector for UDT Streams.
*/
public class NioUdtByteConnectorChannel extends AbstractNioByteChannel
implements UdtChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtByteConnectorChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(
BufType.BYTE, false);
private final UdtChannelConfig config;
public NioUdtByteConnectorChannel() {
this(TypeUDT.STREAM);
}
public NioUdtByteConnectorChannel(final Channel parent, final Integer id,
final SocketChannelUDT channelUDT) {
super(parent, id, channelUDT);
try {
channelUDT.configureBlocking(false);
switch (channelUDT.socketUDT().status()) {
case INIT:
case OPENED:
config = new DefaultUdtChannelConfig(this, channelUDT, true);
break;
default:
config = new DefaultUdtChannelConfig(this, channelUDT, false);
break;
}
} catch (final Exception e) {
try {
channelUDT.close();
} catch (final Exception e2) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close channel.", e2);
}
}
throw new ChannelException("Failed to configure channel.", e);
}
}
public NioUdtByteConnectorChannel(final SocketChannelUDT channelUDT) {
this(null, channelUDT.socketUDT().id(), channelUDT);
}
public NioUdtByteConnectorChannel(final TypeUDT type) {
this(NioUdtProvider.newConnectorChannelUDT(type));
}
@Override
public UdtChannelConfig config() {
return config;
}
@Override
protected void doBind(final SocketAddress localAddress) throws Exception {
javaChannel().bind(localAddress);
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected boolean doConnect(final SocketAddress remoteAddress,
final SocketAddress localAddress) throws Exception {
doBind(localAddress);
boolean success = false;
try {
final boolean connected = javaChannel().connect(remoteAddress);
if (!connected) {
selectionKey().interestOps(
selectionKey().interestOps() | OP_CONNECT);
}
success = true;
return connected;
} finally {
if (!success) {
doClose();
}
}
}
@Override
protected void doDisconnect() throws Exception {
doClose();
}
@Override
protected void doFinishConnect() throws Exception {
if (javaChannel().finishConnect()) {
selectionKey().interestOps(
selectionKey().interestOps() & ~OP_CONNECT);
} else {
throw new Error(
"Provider error: failed to finish connect. Provider library should be upgraded.");
}
}
@Override
protected int doReadBytes(final ByteBuf byteBuf) throws Exception {
return byteBuf.writeBytes(javaChannel(), byteBuf.writableBytes());
}
@Override
protected int doWriteBytes(final ByteBuf byteBuf, final boolean lastSpin)
throws Exception {
final int pendingBytes = byteBuf.readableBytes();
final int writtenBytes = byteBuf.readBytes(javaChannel(), pendingBytes);
final SelectionKey key = selectionKey();
final int interestOps = key.interestOps();
if (writtenBytes >= pendingBytes) {
// wrote the buffer completely - clear OP_WRITE.
if ((interestOps & OP_WRITE) != 0) {
key.interestOps(interestOps & ~OP_WRITE);
}
} else {
// wrote partial or nothing - ensure OP_WRITE
if (writtenBytes > 0 || lastSpin) {
if ((interestOps & OP_WRITE) == 0) {
key.interestOps(interestOps | OP_WRITE);
}
}
}
return writtenBytes;
}
@Override
public boolean isActive() {
final SocketChannelUDT channelUDT = javaChannel();
return channelUDT.isOpen() && channelUDT.isConnectFinished();
}
@Override
protected SocketChannelUDT javaChannel() {
return (SocketChannelUDT) super.javaChannel();
}
@Override
protected SocketAddress localAddress0() {
return javaChannel().socket().getLocalSocketAddress();
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
protected SocketAddress remoteAddress0() {
return javaChannel().socket().getRemoteSocketAddress();
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.transport.udt.nio;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import io.netty.transport.udt.UdtChannel;
import com.barchart.udt.TypeUDT;
/**
* Byte Channel Rendezvous for UDT Streams.
*/
public class NioUdtByteRendezvousChannel extends NioUdtByteConnectorChannel
implements UdtChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtByteRendezvousChannel.class);
public NioUdtByteRendezvousChannel() {
super(NioUdtProvider.newRendezvousChannelUDT(TypeUDT.STREAM));
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.transport.udt.nio;
import io.netty.buffer.BufType;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelMetadata;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.SocketChannelUDT;
/**
* Message Channel Acceptor for UDT Datagrams.
*/
public class NioUdtMessageAcceptorChannel extends NioUdtAcceptorChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtMessageAcceptorChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(
BufType.MESSAGE, false);
public NioUdtMessageAcceptorChannel() {
super(TypeUDT.DATAGRAM);
}
@Override
protected int doReadMessages(final MessageBuf<Object> buf) throws Exception {
final SocketChannelUDT channelUDT = javaChannel().accept();
if (channelUDT == null) {
return 0;
} else {
buf.add(new NioUdtMessageConnectorChannel(this, channelUDT
.socketUDT().id(), channelUDT));
return 1;
}
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
}

View File

@ -0,0 +1,249 @@
/*
* 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.transport.udt.nio;
import static java.nio.channels.SelectionKey.*;
import io.netty.buffer.BufType;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.socket.nio.AbstractNioMessageChannel;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import io.netty.transport.udt.DefaultUdtChannelConfig;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.UdtChannelConfig;
import io.netty.transport.udt.UdtMessage;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.SocketChannelUDT;
/**
* Message Connector for UDT Datagrams.
* <p>
* Note: send/receive must use {@link UdtMessage} in the pipeline
*/
public class NioUdtMessageConnectorChannel extends AbstractNioMessageChannel
implements UdtChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtMessageConnectorChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(
BufType.MESSAGE, false);
private final UdtChannelConfig config;
public NioUdtMessageConnectorChannel() {
this(TypeUDT.DATAGRAM);
}
public NioUdtMessageConnectorChannel(final Channel parent,
final Integer id, final SocketChannelUDT channelUDT) {
super(parent, id, channelUDT, OP_READ);
try {
channelUDT.configureBlocking(false);
switch (channelUDT.socketUDT().status()) {
case INIT:
case OPENED:
config = new DefaultUdtChannelConfig(this, channelUDT, true);
break;
default:
config = new DefaultUdtChannelConfig(this, channelUDT, false);
break;
}
} catch (final Exception e) {
try {
channelUDT.close();
} catch (final Exception e2) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close channel.", e2);
}
}
throw new ChannelException("Failed to configure channel.", e);
}
}
public NioUdtMessageConnectorChannel(final SocketChannelUDT channelUDT) {
this(null, channelUDT.socketUDT().id(), channelUDT);
}
public NioUdtMessageConnectorChannel(final TypeUDT type) {
this(NioUdtProvider.newConnectorChannelUDT(type));
}
@Override
public UdtChannelConfig config() {
return config;
}
@Override
protected void doBind(final SocketAddress localAddress) throws Exception {
javaChannel().bind(localAddress);
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected boolean doConnect(final SocketAddress remoteAddress,
final SocketAddress localAddress) throws Exception {
doBind(localAddress);
boolean success = false;
try {
final boolean connected = javaChannel().connect(remoteAddress);
if (!connected) {
selectionKey().interestOps(
selectionKey().interestOps() | OP_CONNECT);
}
success = true;
return connected;
} finally {
if (!success) {
doClose();
}
}
}
@Override
protected void doDisconnect() throws Exception {
doClose();
}
@Override
protected void doFinishConnect() throws Exception {
if (javaChannel().finishConnect()) {
selectionKey().interestOps(
selectionKey().interestOps() & ~OP_CONNECT);
} else {
throw new Error(
"Provider error: failed to finish connect. Provider library should be upgraded.");
}
}
@Override
protected int doReadMessages(final MessageBuf<Object> buf) throws Exception {
final int maximumMessageSize = config.getReceiveBufferSize();
final ByteBuf byteBuf = config.getAllocator().directBuffer(
maximumMessageSize);
final int receivedMessageSize = byteBuf.writeBytes(javaChannel(),
maximumMessageSize);
if (receivedMessageSize <= 0) {
byteBuf.free();
return 0;
}
if (receivedMessageSize >= maximumMessageSize) {
javaChannel().close();
throw new ChannelException(
"Invalid config : increase receive buffer size to avoid message truncation");
}
// delivers a message
buf.add(new UdtMessage(byteBuf));
return 1;
}
@Override
protected int doWriteMessages(final MessageBuf<Object> messageQueue,
final boolean lastSpin) throws Exception {
// expects a message
final UdtMessage message = (UdtMessage) messageQueue.peek();
final ByteBuf byteBuf = message.data();
final int messageSize = byteBuf.readableBytes();
final long writtenBytes;
if (byteBuf.nioBufferCount() == 1) {
writtenBytes = javaChannel().write(byteBuf.nioBuffer());
} else {
writtenBytes = javaChannel().write(byteBuf.nioBuffers());
}
final SelectionKey key = selectionKey();
final int interestOps = key.interestOps();
// did not write the message
if (writtenBytes <= 0 && messageSize > 0) {
if (lastSpin) {
if ((interestOps & OP_WRITE) == 0) {
key.interestOps(interestOps | OP_WRITE);
}
}
return 0;
}
// wrote message completely
if (writtenBytes != messageSize) {
throw new Error(
"Provider error: failed to write message. Provider library should be upgraded.");
}
// wrote the message queue completely - clear OP_WRITE.
if (messageQueue.isEmpty()) {
if ((interestOps & OP_WRITE) != 0) {
key.interestOps(interestOps & ~OP_WRITE);
}
}
messageQueue.remove();
message.free();
return 1;
}
@Override
public boolean isActive() {
final SocketChannelUDT channelUDT = javaChannel();
return channelUDT.isOpen() && channelUDT.isConnectFinished();
}
@Override
protected SocketChannelUDT javaChannel() {
return (SocketChannelUDT) super.javaChannel();
}
@Override
protected SocketAddress localAddress0() {
return javaChannel().socket().getLocalSocketAddress();
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
protected SocketAddress remoteAddress0() {
return javaChannel().socket().getRemoteSocketAddress();
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.transport.udt.nio;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import io.netty.transport.udt.UdtChannel;
import io.netty.transport.udt.UdtMessage;
import com.barchart.udt.TypeUDT;
/**
* Message Rendezvous for UDT Datagrams.
* <p>
* Note: send/receive must use {@link UdtMessage} in the pipeline
*/
public class NioUdtMessageRendezvousChannel extends
NioUdtMessageConnectorChannel implements UdtChannel {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtMessageConnectorChannel.class);
public NioUdtMessageRendezvousChannel() {
super(NioUdtProvider.newRendezvousChannelUDT(TypeUDT.DATAGRAM));
}
}

View File

@ -0,0 +1,247 @@
/*
* 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.transport.udt.nio;
import io.netty.bootstrap.AbstractBootstrap.ChannelFactory;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import io.netty.transport.udt.UdtChannel;
import java.io.IOException;
import java.nio.channels.spi.SelectorProvider;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.nio.ChannelUDT;
import com.barchart.udt.nio.KindUDT;
import com.barchart.udt.nio.RendezvousChannelUDT;
import com.barchart.udt.nio.SelectorProviderUDT;
import com.barchart.udt.nio.ServerSocketChannelUDT;
import com.barchart.udt.nio.SocketChannelUDT;
/**
* UDT NIO components provider:
* <p>
* Provides {@link ChannelFactory} for UDT channels.
* <p>
* Provides {@link SelectorProvider} for UDT channels.
*/
public final class NioUdtProvider implements ChannelFactory {
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(NioUdtProvider.class);
/**
* {@link ChannelFactory} for UDT Byte Acceptor. See {@link TypeUDT#STREAM}
* and {@link KindUDT#ACCEPTOR}.
*/
public static final ChannelFactory BYTE_ACCEPTOR = new NioUdtProvider(
TypeUDT.STREAM, KindUDT.ACCEPTOR);
/**
* {@link ChannelFactory} for UDT Byte Connector. See {@link TypeUDT#STREAM}
* and {@link KindUDT#CONNECTOR}.
*/
public static final ChannelFactory BYTE_CONNECTOR = new NioUdtProvider(
TypeUDT.STREAM, KindUDT.CONNECTOR);
/**
* {@link SelectorProvider} for UDT Byte channels. See
* {@link TypeUDT#STREAM}.
*/
public static final SelectorProvider BYTE_PROVIDER = SelectorProviderUDT.STREAM;
/**
* {@link ChannelFactory} for UDT Byte Rendezvous. See
* {@link TypeUDT#STREAM} and {@link KindUDT#RENDEZVOUS}.
*/
public static final ChannelFactory BYTE_RENDEZVOUS = new NioUdtProvider(
TypeUDT.STREAM, KindUDT.RENDEZVOUS);
/**
* {@link ChannelFactory} for UDT Message Acceptor. See
* {@link TypeUDT#DATAGRAM} and {@link KindUDT#ACCEPTOR}.
*/
public static final ChannelFactory MESSAGE_ACCEPTOR = new NioUdtProvider(
TypeUDT.DATAGRAM, KindUDT.ACCEPTOR);
/**
* {@link ChannelFactory} for UDT Message Connector. See
* {@link TypeUDT#DATAGRAM} and {@link KindUDT#CONNECTOR}.
*/
public static final ChannelFactory MESSAGE_CONNECTOR = new NioUdtProvider(
TypeUDT.DATAGRAM, KindUDT.CONNECTOR);
/**
* {@link SelectorProvider} for UDT Message channels. See
* {@link TypeUDT#DATAGRAM}.
*/
public static final SelectorProvider MESSAGE_PROVIDER = SelectorProviderUDT.DATAGRAM;
/**
* {@link ChannelFactory} for UDT Message Rendezvous. See
* {@link TypeUDT#DATAGRAM} and {@link KindUDT#RENDEZVOUS}.
*/
public static final ChannelFactory MESSAGE_RENDEZVOUS = new NioUdtProvider(
TypeUDT.DATAGRAM, KindUDT.RENDEZVOUS);
/**
* Expose underlying {@link ChannelUDT} for debugging and monitoring.
* <p>
* @return underlying {@link ChannelUDT} or null, if parameter is not
* {@link UdtChannel}
*/
public static ChannelUDT channelUDT(final Channel channel) {
// bytes
if (channel instanceof NioUdtByteAcceptorChannel) {
return ((NioUdtByteAcceptorChannel) channel).javaChannel();
}
if (channel instanceof NioUdtByteConnectorChannel) {
return ((NioUdtByteConnectorChannel) channel).javaChannel();
}
if (channel instanceof NioUdtByteRendezvousChannel) {
return ((NioUdtByteRendezvousChannel) channel).javaChannel();
}
// message
if (channel instanceof NioUdtMessageAcceptorChannel) {
return ((NioUdtMessageAcceptorChannel) channel).javaChannel();
}
if (channel instanceof NioUdtMessageConnectorChannel) {
return ((NioUdtMessageConnectorChannel) channel).javaChannel();
}
if (channel instanceof NioUdtMessageRendezvousChannel) {
return ((NioUdtMessageRendezvousChannel) channel).javaChannel();
}
return null;
}
/**
* Convenience factory for {@link KindUDT#ACCEPTOR} channels.
*/
protected static ServerSocketChannelUDT newAcceptorChannelUDT(
final TypeUDT type) {
try {
return SelectorProviderUDT.from(type).openServerSocketChannel();
} catch (final IOException e) {
throw new ChannelException("Failed to open channel");
}
}
/**
* Convenience factory for {@link KindUDT#CONNECTOR} channels.
*/
protected static SocketChannelUDT newConnectorChannelUDT(final TypeUDT type) {
try {
return SelectorProviderUDT.from(type).openSocketChannel();
} catch (final IOException e) {
throw new ChannelException("Failed to open channel");
}
}
/**
* Convenience factory for {@link KindUDT#RENDEZVOUS} channels.
*/
protected static RendezvousChannelUDT newRendezvousChannelUDT(
final TypeUDT type) {
try {
return SelectorProviderUDT.from(type).openRendezvousChannel();
} catch (final IOException e) {
throw new ChannelException("Failed to open channel");
}
}
/**
* Expose underlying {@link SocketUDT} for debugging and monitoring.
* <p>
* @return underlying {@link SocketUDT} or null, if parameter is not
* {@link UdtChannel}
*/
public static SocketUDT socketUDT(final Channel channel) {
final ChannelUDT channelUDT = channelUDT(channel);
if (channelUDT == null) {
return null;
} else {
return channelUDT.socketUDT();
}
}
private final KindUDT kind;
private final TypeUDT type;
/**
* {@link ChannelFactory} for given {@link TypeUDT} and {@link KindUDT}
*/
private NioUdtProvider(final TypeUDT type, final KindUDT kind) {
this.type = type;
this.kind = kind;
}
/**
* UDT Channel Kind. See {@link KindUDT}
*/
public KindUDT kind() {
return kind;
}
/**
* Produce new {@link UdtChannel} based on factory {@link #kind()} and
* {@link #type()}
*/
@Override
public UdtChannel newChannel() {
switch (kind) {
case ACCEPTOR:
switch (type) {
case DATAGRAM:
return new NioUdtMessageAcceptorChannel();
case STREAM:
return new NioUdtByteAcceptorChannel();
default:
throw new IllegalStateException("wrong type=" + type);
}
case CONNECTOR:
switch (type) {
case DATAGRAM:
return new NioUdtMessageConnectorChannel();
case STREAM:
return new NioUdtByteConnectorChannel();
default:
throw new IllegalStateException("wrong type=" + type);
}
case RENDEZVOUS:
switch (type) {
case DATAGRAM:
return new NioUdtMessageRendezvousChannel();
case STREAM:
return new NioUdtByteRendezvousChannel();
default:
throw new IllegalStateException("wrong type=" + type);
}
default:
throw new IllegalStateException("wrong kind=" + kind);
}
}
/**
* UDT Socket Type. See {@link TypeUDT}
*/
public TypeUDT type() {
return type;
}
}

View File

@ -0,0 +1,22 @@
/*
* 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.
*/
/**
* UDT Transport for NIO Channels.
* <p>
* @see /netty/example/src/main/java/io/netty/example/udt
*/
package io.netty.transport.udt.nio;

View File

@ -0,0 +1,22 @@
/*
* 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.
*/
/**
* UDT Transport for OIO Channels.
* <p>
* @see /netty/example/src/main/java/io/netty/example/udt
*/
package io.netty.transport.udt.oio;

View File

@ -0,0 +1,22 @@
/*
* 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.
*/
/**
* UDT Transport.
* <p>
* @see /netty/example/src/main/java/io/netty/example/udt
*/
package io.netty.transport.udt;

View File

@ -0,0 +1,50 @@
/*
* 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.transport.udt.bench;
import io.netty.transport.udt.util.CaliperBench;
import io.netty.transport.udt.util.CaliperRunner;
import io.netty.transport.udt.util.TrafficControl;
import java.util.List;
/**
* perform two way native udt socket send/recv
*/
public abstract class BenchXfer extends CaliperBench {
/** introduce network latency */
protected static List<String> latencyList() {
if (TrafficControl.isAvailable()) {
return CaliperRunner.valueList("0,10,30");
} else {
return CaliperRunner.valueList("0");
}
}
/** verify different message sizes */
protected static List<String> messageList() {
return CaliperRunner
.valueList("500,1500,3000,5000,10000,20000,50000,100000");
}
/** benchmark run time per each configuration */
protected static List<String> durationList() {
return CaliperRunner.valueList("30000");
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* UDT Benchmarks
*/
package io.netty.transport.udt.bench;

View File

@ -0,0 +1,66 @@
/*
* 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.transport.udt.bench.xfer;
import io.netty.transport.udt.bench.BenchXfer;
import io.netty.transport.udt.util.CaliperRunner;
import io.netty.transport.udt.util.TrafficControl;
import java.util.List;
import com.google.caliper.Param;
/**
* perform two way native TCP socket send/recv
*/
public class TcpNative extends BenchXfer {
@Param
private volatile int latency;
protected static List<String> latencyValues() {
return BenchXfer.latencyList();
}
@Param
private volatile int message;
protected static List<String> messageValues() {
return BenchXfer.messageList();
}
@Param
private volatile int duration;
protected static List<String> durationValues() {
return BenchXfer.durationList();
}
public void timeRun(final int reps) throws Exception {
log.info("init");
TrafficControl.delay(latency);
TrafficControl.delay(0);
log.info("done");
}
public static void main(final String[] args) throws Exception {
CaliperRunner.execute(TcpNative.class);
}
}

View File

@ -0,0 +1,270 @@
/*
* 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.transport.udt.bench.xfer;
import static io.netty.transport.udt.util.UnitHelp.*;
import io.netty.transport.udt.bench.BenchXfer;
import io.netty.transport.udt.util.CaliperRunner;
import io.netty.transport.udt.util.TrafficControl;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.StatusUDT;
import com.barchart.udt.TypeUDT;
import com.google.caliper.Param;
/**
* perform two way native UDT socket send/recv
*/
public class UdtNative extends BenchXfer {
@Param
private volatile int latency;
protected static List<String> latencyValues() {
return BenchXfer.latencyList();
}
@Param
private volatile int message;
protected static List<String> messageValues() {
return BenchXfer.messageList();
}
@Param
private volatile int duration;
protected static List<String> durationValues() {
return BenchXfer.durationList();
}
private volatile SocketUDT peer1;
private volatile SocketUDT peer2;
@Override
protected void setUp() throws Exception {
log.info("init");
TrafficControl.delay(latency);
final InetSocketAddress addr1 = localSocketAddress();
final InetSocketAddress addr2 = localSocketAddress();
peer1 = new SocketUDT(TypeUDT.DATAGRAM);
peer2 = new SocketUDT(TypeUDT.DATAGRAM);
peer1.setBlocking(false);
peer2.setBlocking(false);
peer1.setRendezvous(true);
peer2.setRendezvous(true);
peer1.bind(addr1);
peer2.bind(addr2);
socketAwait(peer1, StatusUDT.OPENED);
socketAwait(peer2, StatusUDT.OPENED);
peer1.connect(addr2);
peer2.connect(addr1);
socketAwait(peer1, StatusUDT.CONNECTED);
socketAwait(peer2, StatusUDT.CONNECTED);
peer1.setBlocking(true);
peer2.setBlocking(true);
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
peer1.setBlocking(false);
peer2.setBlocking(false);
peer1.close();
peer2.close();
socketAwait(peer1, StatusUDT.CLOSED, StatusUDT.BROKEN);
socketAwait(peer2, StatusUDT.CLOSED, StatusUDT.BROKEN);
TrafficControl.delay(0);
log.info("done");
}
/** benchmark invocation */
public void timeMain(final int reps) throws Exception {
final int threadCount = 4;
final CountDownLatch completion = new CountDownLatch(threadCount);
final AtomicBoolean isOn = new AtomicBoolean(true);
final Runnable sendPeer1 = new Runnable() {
@Override
public void run() {
try {
while (isOn.get()) {
runCore();
}
} catch (final Exception e) {
log.error("", e);
} finally {
completion.countDown();
}
}
final ByteBuffer buffer = ByteBuffer.allocateDirect(message);
long sequence;
void runCore() throws Exception {
buffer.rewind();
buffer.putLong(0, sequence++);
final int count = peer1.send(buffer);
if (count != message) {
throw new Exception("count");
}
measure().rate().mark(count);
}
};
final Runnable sendPeer2 = new Runnable() {
@Override
public void run() {
try {
while (isOn.get()) {
runCore();
}
} catch (final Exception e) {
log.error("", e);
} finally {
completion.countDown();
}
}
final ByteBuffer buffer = ByteBuffer.allocateDirect(message);
long sequence;
void runCore() throws Exception {
buffer.rewind();
buffer.putLong(0, sequence++);
final int count = peer2.send(buffer);
if (count != message) {
throw new Exception("count");
}
}
};
final Runnable recvPeer1 = new Runnable() {
@Override
public void run() {
try {
while (isOn.get()) {
runCore();
}
} catch (final Exception e) {
log.error("", e);
} finally {
completion.countDown();
}
}
final ByteBuffer buffer = ByteBuffer.allocateDirect(message);
long sequence;
void runCore() throws Exception {
buffer.rewind();
final int count = peer1.receive(buffer);
if (count != message) {
throw new Exception("count");
}
if (this.sequence++ != buffer.getLong(0)) {
throw new Exception("sequence");
}
}
};
final Runnable recvPeer2 = new Runnable() {
@Override
public void run() {
try {
while (isOn.get()) {
runCore();
}
} catch (final Exception e) {
log.error("", e);
} finally {
completion.countDown();
}
}
final ByteBuffer buffer = ByteBuffer.allocateDirect(message);
long sequence;
void runCore() throws Exception {
buffer.rewind();
final int count = peer2.receive(buffer);
if (count != message) {
throw new Exception("count");
}
if (this.sequence++ != buffer.getLong(0)) {
throw new Exception("sequence");
}
}
};
final ExecutorService executor = Executors
.newFixedThreadPool(threadCount);
executor.submit(recvPeer1);
executor.submit(recvPeer2);
executor.submit(sendPeer1);
executor.submit(sendPeer2);
markWait(duration);
isOn.set(false);
completion.await();
executor.shutdownNow();
}
public static void main(final String[] args) throws Exception {
CaliperRunner.execute(UdtNative.class);
}
}

View File

@ -0,0 +1,137 @@
/*
* 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.transport.udt.bench.xfer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.logging.InternalLoggerFactory;
import io.netty.logging.Slf4JLoggerFactory;
import io.netty.transport.udt.util.BootHelp;
import io.netty.transport.udt.util.CustomReporter;
import io.netty.transport.udt.util.EchoMessageHandler;
import io.netty.transport.udt.util.TrafficControl;
import io.netty.transport.udt.util.UnitHelp;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.core.Meter;
/**
* perform two way netty send/recv
*/
public final class UdtNetty {
private UdtNetty() {
}
static final Logger log = LoggerFactory.getLogger(UdtNetty.class);
/**
* use slf4j provider for io.netty.logging.InternalLogger
*/
static {
final InternalLoggerFactory defaultFactory = new Slf4JLoggerFactory();
InternalLoggerFactory.setDefaultFactory(defaultFactory);
log.info("InternalLoggerFactory={}", InternalLoggerFactory
.getDefaultFactory().getClass().getName());
}
/** benchmark duration */
static final int time = 10 * 60 * 1000;
/** transfer chunk size */
static final int size = 64 * 1024;
static final Counter benchTime = Metrics.newCounter(UdtNetty.class,
"bench time");
static final Counter benchSize = Metrics.newCounter(UdtNetty.class,
"bench size");
static {
benchTime.inc(time);
benchSize.inc(size);
}
static final Meter rate = Metrics.newMeter(UdtNetty.class, "rate",
"bytes", TimeUnit.SECONDS);
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
TrafficControl.delay(0);
} catch (final Exception e) {
log.error("", e);
}
}
});
}
public static void main(final String[] args) throws Exception {
log.info("init");
TrafficControl.delay(0);
final AtomicBoolean isOn = new AtomicBoolean(true);
final InetSocketAddress addr1 = UnitHelp.localSocketAddress();
final InetSocketAddress addr2 = UnitHelp.localSocketAddress();
final ChannelHandler handler1 = new EchoMessageHandler(rate, size);
final ChannelHandler handler2 = new EchoMessageHandler(null, size);
final Bootstrap peerBoot1 = BootHelp.messagePeerBoot(addr1, addr2,
handler1);
final Bootstrap peerBoot2 = BootHelp.messagePeerBoot(addr2, addr1,
handler2);
final ChannelFuture peerFuture1 = peerBoot1.connect();
final ChannelFuture peerFuture2 = peerBoot2.connect();
CustomReporter.enable(3, TimeUnit.SECONDS);
Thread.sleep(time);
isOn.set(false);
Thread.sleep(1 * 1000);
peerFuture1.channel().close().sync();
peerFuture2.channel().close().sync();
Thread.sleep(1 * 1000);
peerBoot1.shutdown();
peerBoot2.shutdown();
Metrics.defaultRegistry().shutdown();
TrafficControl.delay(0);
log.info("done");
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* UDT Transfer Speed Benchmarks
*/
package io.netty.transport.udt.bench.xfer;

View File

@ -0,0 +1,42 @@
/*
* 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.transport.udt.nio;
import io.netty.logging.InternalLoggerFactory;
import io.netty.logging.Slf4JLoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* shared test base
*/
public abstract class TestAny {
protected static final Logger log = LoggerFactory.getLogger(TestAny.class);
/**
* use slf4j provider for io.netty.logging.InternalLogger
*/
static {
final InternalLoggerFactory defaultFactory = new Slf4JLoggerFactory();
InternalLoggerFactory.setDefaultFactory(defaultFactory);
log.info("InternalLoggerFactory={}", InternalLoggerFactory
.getDefaultFactory().getClass().getName());
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import io.netty.buffer.BufType;
import org.junit.Test;
public class TestNioUdtByteAcceptorChannel extends TestAny {
/**
* verify channel meta data
*/
@Test
public void metadata() throws Exception {
assertEquals(BufType.BYTE, new NioUdtByteAcceptorChannel().metadata()
.bufferType());
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import io.netty.buffer.BufType;
import org.junit.Test;
public class TestNioUdtByteConnectorChannel extends TestAny {
/**
* verify channel meta data
*/
@Test
public void metadata() throws Exception {
assertEquals(BufType.BYTE, new NioUdtByteConnectorChannel().metadata()
.bufferType());
}
}

View File

@ -0,0 +1,103 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.BufType;
import io.netty.channel.ChannelFuture;
import io.netty.transport.udt.util.BootHelp;
import io.netty.transport.udt.util.EchoByteHandler;
import io.netty.transport.udt.util.UnitHelp;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
public class TestNioUdtByteRendezvousChannel extends TestAny {
/**
* verify channel meta data
*/
@Test
public void metadata() throws Exception {
assertEquals(BufType.BYTE, new NioUdtByteRendezvousChannel().metadata()
.bufferType());
}
/**
* verify basic echo byte rendezvous
*/
@Test(timeout = 10 * 1000)
public void basicEcho() throws Exception {
final int messageSize = 64 * 1024;
final int transferLimit = messageSize * 16;
final Meter rate1 = Metrics.newMeter(
TestNioUdtMessageRendezvousChannel.class, "send rate", "bytes",
TimeUnit.SECONDS);
final Meter rate2 = Metrics.newMeter(
TestNioUdtMessageRendezvousChannel.class, "send rate", "bytes",
TimeUnit.SECONDS);
final InetSocketAddress addr1 = UnitHelp.localSocketAddress();
final InetSocketAddress addr2 = UnitHelp.localSocketAddress();
final EchoByteHandler handler1 = new EchoByteHandler(rate1, messageSize);
final EchoByteHandler handler2 = new EchoByteHandler(rate2, messageSize);
final Bootstrap boot1 = BootHelp.bytePeerBoot(addr1, addr2, handler1);
final Bootstrap boot2 = BootHelp.bytePeerBoot(addr2, addr1, handler2);
final ChannelFuture connectFuture1 = boot1.connect();
final ChannelFuture connectFuture2 = boot2.connect();
while (handler1.meter().count() < transferLimit
&& handler2.meter().count() < transferLimit) {
log.info("progress : {} {}", handler1.meter().count(), handler2
.meter().count());
Thread.sleep(1000);
}
connectFuture1.channel().close().sync();
connectFuture2.channel().close().sync();
log.info("handler1 : {}", handler1.meter().count());
log.info("handler2 : {}", handler2.meter().count());
assertTrue(handler1.meter().count() >= transferLimit);
assertTrue(handler2.meter().count() >= transferLimit);
assertEquals(handler1.meter().count(), handler2.meter().count());
boot1.shutdown();
boot2.shutdown();
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import io.netty.buffer.BufType;
import org.junit.Test;
public class TestNioUdtMessageAcceptorChannel extends TestAny {
/**
* verify channel meta data
*/
@Test
public void metadata() throws Exception {
assertEquals(BufType.MESSAGE, new NioUdtMessageAcceptorChannel()
.metadata().bufferType());
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import io.netty.buffer.BufType;
import org.junit.Test;
public class TestNioUdtMessageConnectorChannel extends TestAny {
/**
* verify channel meta data
*/
@Test
public void metadata() throws Exception {
assertEquals(BufType.MESSAGE, new NioUdtMessageConnectorChannel()
.metadata().bufferType());
}
}

View File

@ -0,0 +1,107 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.BufType;
import io.netty.channel.ChannelFuture;
import io.netty.transport.udt.util.BootHelp;
import io.netty.transport.udt.util.EchoMessageHandler;
import io.netty.transport.udt.util.UnitHelp;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
public class TestNioUdtMessageRendezvousChannel extends TestAny {
/**
* verify channel meta data
*/
@Test
public void metadata() throws Exception {
assertEquals(BufType.MESSAGE, new NioUdtMessageRendezvousChannel()
.metadata().bufferType());
}
/**
* verify basic echo message rendezvous
*/
@Test(timeout = 10 * 1000)
public void basicEcho() throws Exception {
final int messageSize = 64 * 1024;
final int transferLimit = messageSize * 16;
final Meter rate1 = Metrics.newMeter(
TestNioUdtMessageRendezvousChannel.class, "send rate", "bytes",
TimeUnit.SECONDS);
final Meter rate2 = Metrics.newMeter(
TestNioUdtMessageRendezvousChannel.class, "send rate", "bytes",
TimeUnit.SECONDS);
final InetSocketAddress addr1 = UnitHelp.localSocketAddress();
final InetSocketAddress addr2 = UnitHelp.localSocketAddress();
final EchoMessageHandler handler1 = new EchoMessageHandler(rate1,
messageSize);
final EchoMessageHandler handler2 = new EchoMessageHandler(rate2,
messageSize);
final Bootstrap boot1 = BootHelp
.messagePeerBoot(addr1, addr2, handler1);
final Bootstrap boot2 = BootHelp
.messagePeerBoot(addr2, addr1, handler2);
final ChannelFuture connectFuture1 = boot1.connect();
final ChannelFuture connectFuture2 = boot2.connect();
while (handler1.meter().count() < transferLimit
&& handler2.meter().count() < transferLimit) {
log.info("progress : {} {}", handler1.meter().count(), handler2
.meter().count());
Thread.sleep(1000);
}
connectFuture1.channel().close().sync();
connectFuture2.channel().close().sync();
log.info("handler1 : {}", handler1.meter().count());
log.info("handler2 : {}", handler2.meter().count());
assertTrue(handler1.meter().count() >= transferLimit);
assertTrue(handler2.meter().count() >= transferLimit);
assertEquals(handler1.meter().count(), handler2.meter().count());
boot1.shutdown();
boot2.shutdown();
}
}

View File

@ -0,0 +1,43 @@
/*
* 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.transport.udt.nio;
import static org.junit.Assert.*;
import org.junit.Test;
public class TestNioUdtProvider extends TestAny {
/**
* verify factory
*/
@Test
public void provideFactory() {
// bytes
assertNotNull(NioUdtProvider.BYTE_ACCEPTOR.newChannel());
assertNotNull(NioUdtProvider.BYTE_CONNECTOR.newChannel());
assertNotNull(NioUdtProvider.BYTE_RENDEZVOUS.newChannel());
// message
assertNotNull(NioUdtProvider.MESSAGE_ACCEPTOR.newChannel());
assertNotNull(NioUdtProvider.MESSAGE_CONNECTOR.newChannel());
assertNotNull(NioUdtProvider.MESSAGE_RENDEZVOUS.newChannel());
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.transport.udt.util;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandler;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.transport.udt.nio.NioUdtProvider;
import java.net.InetSocketAddress;
import java.util.concurrent.ThreadFactory;
/**
* Bootstrap utilities.
*/
public class BootHelp {
/**
* bootstrap for byte rendezvous peer
*/
public static Bootstrap bytePeerBoot(final InetSocketAddress self,
final InetSocketAddress peer, final ChannelHandler handler) {
final Bootstrap boot = new Bootstrap();
final ThreadFactory connectFactory = new UtilThreadFactory("peer");
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.BYTE_PROVIDER);
boot.group(connectGroup).channelFactory(NioUdtProvider.BYTE_RENDEZVOUS)
.localAddress(self).remoteAddress(peer).handler(handler);
return boot;
}
/**
* bootstrap for message rendezvous peer
*/
public static Bootstrap messagePeerBoot(final InetSocketAddress self,
final InetSocketAddress peer, final ChannelHandler handler) {
final Bootstrap boot = new Bootstrap();
final ThreadFactory connectFactory = new UtilThreadFactory("peer");
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
boot.group(connectGroup)
.channelFactory(NioUdtProvider.MESSAGE_RENDEZVOUS)
.localAddress(self).remoteAddress(peer).handler(handler);
return boot;
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.transport.udt.util;
import io.netty.logging.InternalLoggerFactory;
import io.netty.logging.Slf4JLoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.caliper.SimpleBenchmark;
/**
* Base class for caliper/metrics benchmarks.
*/
public abstract class CaliperBench extends SimpleBenchmark {
/**
* Ensure no network latency after JVM shutdown
*/
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
TrafficControl.delay(0);
} catch (final Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Use slf4j logging.
*/
static {
final InternalLoggerFactory defaultFactory = new Slf4JLoggerFactory();
InternalLoggerFactory.setDefaultFactory(defaultFactory);
}
protected final Logger log = LoggerFactory.getLogger(getClass());
private volatile CaliperMeasure measure;
/**
* Caliper metrics wrapper.
*/
protected CaliperMeasure measure() {
return measure;
}
/**
* Start measurement.
*/
@Override
protected void setUp() throws Exception {
measure = new CaliperMeasure();
}
/**
* Finish measurement.
*/
@Override
protected void tearDown() throws Exception {
measure.shutdown();
}
/**
* Measure time step and minimum run time.
*/
protected long markStep() {
return 3 * 1000;
}
/**
* Measure progress while in sleep.
*/
protected void markWait(final long time) throws Exception {
final long timeStart = System.currentTimeMillis();
while (true) {
Thread.sleep(markStep());
measure().mark();
final long timeFinish = System.currentTimeMillis();
if (timeFinish - timeStart >= time) {
System.out.print("+\n");
return;
} else {
System.out.print("-");
continue;
}
}
}
}

View File

@ -0,0 +1,224 @@
/*
* 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.transport.udt.util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.caliper.Measurement;
import com.google.caliper.MeasurementSet;
import com.google.caliper.Run;
import com.google.caliper.Scenario;
import com.google.caliper.ScenarioResult;
import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.core.Meter;
import com.yammer.metrics.core.MetricsRegistry;
import com.yammer.metrics.core.Timer;
/**
* Caliper measure with Metrics provider.
* <p>
* measure up to 3 values: {@link #rate()}, {@link #time()}, {@link #size()}
*/
public class CaliperMeasure {
private final static Logger log = LoggerFactory
.getLogger(CaliperMeasure.class);
/**
* Gauge any double value
*/
public static class SizeGuage extends Gauge<Double> {
private volatile Double size = 0.0;
@Override
public Double value() {
return size;
}
public void value(final double number) {
this.size = number;
}
}
/**
* Default rate measurement units.
*/
private static final Map<String, Integer> RATE_UNIT = new HashMap<String, Integer>();
static {
RATE_UNIT.put("Rate B/s", 1);
RATE_UNIT.put("Rate KB/s", 1024);
RATE_UNIT.put("Rate MB/s", 1024 * 1024);
RATE_UNIT.put("Rate GB/s", 1024 * 1024 * 1024);
}
/**
* Default time measurement units.
*/
private static final Map<String, Integer> TIME_UNIT = new HashMap<String, Integer>();
static {
TIME_UNIT.put("Time ns", 1);
TIME_UNIT.put("Time us", 1000);
TIME_UNIT.put("Time ms", 1000 * 1000);
TIME_UNIT.put("Time s ", 1000 * 1000 * 1000);
}
/**
* Default size measurement units.
*/
private static final Map<String, Integer> SIZE_UNIT = new HashMap<String, Integer>();
static {
SIZE_UNIT.put("Size B", 1);
SIZE_UNIT.put("Size KB", 1024);
SIZE_UNIT.put("Size MB", 1024 * 1024);
SIZE_UNIT.put("Size GB", 1024 * 1024 * 1024);
}
private final Map<Long, Measurement> rateMap = new HashMap<Long, Measurement>();
private final Map<Long, Measurement> timeMap = new HashMap<Long, Measurement>();
private final Map<Long, Measurement> sizeMap = new HashMap<Long, Measurement>();
private final MetricsRegistry metrics = new MetricsRegistry();
private final Meter rate = metrics.newMeter(getClass(), "rate", "bytes",
TimeUnit.SECONDS);
private final Timer time = metrics.newTimer(getClass(), "time",
TimeUnit.NANOSECONDS, TimeUnit.SECONDS);
private final SizeGuage size = new SizeGuage();
{
metrics.newGauge(getClass(), "", size);
}
/**
* Rate meter.
*/
public Meter rate() {
return rate;
}
/**
* Time meter.
*/
public Timer time() {
return time;
}
/**
* Size meter.
*/
public SizeGuage size() {
return size;
}
/**
* Workaround: zero breaks gwt web app.
*/
private double filter(final double value) {
if (value <= 0.0) {
return 1.0;
} else {
return value;
}
}
/**
* Perform measurement; convert from metrics into caliper.
*/
public void mark() {
final double rateValue = filter(rate.oneMinuteRate());
final double timeValue = filter(time.mean());
final double sizeValue = filter(size.value());
if (rateValue == 1.0 && timeValue == 1.0 && sizeValue == 1.0) {
/** ignore complete blank entries */
return;
}
{
final Measurement mark = new Measurement(RATE_UNIT, rateValue,
rateValue);
rateMap.put(System.nanoTime(), mark);
}
{
final Measurement mark = new Measurement(TIME_UNIT, timeValue,
timeValue);
timeMap.put(System.nanoTime(), mark);
}
{
final Measurement mark = new Measurement(SIZE_UNIT, sizeValue,
sizeValue);
sizeMap.put(System.nanoTime(), mark);
}
}
private final Map<String, String> variables = new HashMap<String, String>();
/**
* Caliper scenario variables.
*/
public Map<String, String> variables() {
return variables;
}
private MeasurementSet measurementSet(final Map<Long, Measurement> map) {
final Measurement[] array = map.values().toArray(new Measurement[0]);
final MeasurementSet set = new MeasurementSet(array);
return set;
}
/**
* Attach this measure to parent caliper run.
*/
public void appendTo(final Run run) {
final Scenario scenario = new Scenario(variables());
/** display rate as caliper durations */
final MeasurementSet timeSet = measurementSet(rateMap);
final String timeLog = null;
/** display time as caliper instances */
final MeasurementSet instSet = measurementSet(timeMap);
final String instLog = null;
/** display size as caliper memory */
final MeasurementSet heapSet = measurementSet(sizeMap);
final String heapLog = null;
final ScenarioResult scenarioResult = new ScenarioResult(timeSet,
timeLog, instSet, instLog, heapSet, heapLog);
final Map<Scenario, ScenarioResult> measurements = run
.getMeasurements();
measurements.put(scenario, scenarioResult);
}
/**
* Terminate metrics resources.
*/
public void shutdown() {
rate.stop();
time.stop();
metrics.shutdown();
}
}

View File

@ -0,0 +1,245 @@
/*
* 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.transport.udt.util;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.caliper.ConfiguredBenchmark;
import com.google.caliper.Environment;
import com.google.caliper.EnvironmentGetter;
import com.google.caliper.Json;
import com.google.caliper.Result;
import com.google.caliper.Run;
import com.google.caliper.Runner;
import com.google.caliper.Scenario;
import com.google.caliper.ScenarioResult;
import com.google.caliper.SimpleBenchmark;
import com.yammer.metrics.core.TimerContext;
/**
* Custom caliper runner for {@link CaliperBench}.
*/
public final class CaliperRunner {
private final static Logger log = LoggerFactory
.getLogger(CaliperRunner.class);
private CaliperRunner() {
}
/**
* Parse bench parameters.
*/
public static List<String> valueList(final String valueText) {
return Arrays.asList(valueText.split(","));
}
/**
* Execute full cycle: warm up, execute and publish benchmark.
*/
public static void execute(final Class<? extends CaliperBench> klaz)
throws Exception {
Run run;
run = execute("WARMUP", klaz);
run = execute("REPORT", klaz);
publish(newResult(run));
}
/**
* Execute benchmark for all parameter combinations.
*/
public static Run execute(final String name,
final Class<? extends CaliperBench> klaz) throws Exception {
final CaliperBench booter = klaz.newInstance();
final List<Map<String, String>> varsSet = product(booter);
final Run run = newRun(klaz.getName());
int index = 0;
for (final Map<String, String> vars : varsSet) {
final int done = 100 * index++ / varsSet.size();
log.info("{} {}% {}", name, done, vars);
/** call setUp() */
final ConfiguredBenchmark runner = booter.createBenchmark(vars);
final CaliperBench bench = (CaliperBench) runner.getBenchmark();
final CaliperMeasure measure = bench.measure();
measure.variables().putAll(vars);
/** call timeXXX() */
runner.run(0);
/** call tearDown() */
runner.close();
measure.appendTo(run);
}
return run;
}
/**
* Convert caliper result into JSON string.
*/
public static String json(final Result result) {
return Json.getGsonInstance().toJson(result);
}
/**
* Map signature based on map values.
*/
public static String signature(final Map<String, String> map) {
final StringBuilder text = new StringBuilder();
for (final String item : map.values()) {
text.append(String.format("%20s", item));
}
return text.toString();
}
/**
* Generate all parameter combinations for {@link SimpleBenchmark}.
*/
public static List<Map<String, String>> product(final SimpleBenchmark bench) {
final Set<Map<String, String>> collect = new HashSet<Map<String, String>>();
final Map<String, Set<String>> pending = new TreeMap<String, Set<String>>();
for (final String name : new TreeSet<String>(bench.parameterNames())) {
pending.put(name, bench.parameterValues(name));
}
final List<Map<String, String>> list = new ArrayList<Map<String, String>>(
product(collect, pending));
final Comparator<Map<String, String>> comp = new Comparator<Map<String, String>>() {
@Override
public int compare(final Map<String, String> o1,
final Map<String, String> o2) {
return signature(o1).compareTo(signature(o2));
}
};
Collections.sort(list, comp);
return list;
}
/**
* Calculate ordered Cartesian product of sets.
*/
public static Set<Map<String, String>> product(
final Set<Map<String, String>> collect,
final Map<String, Set<String>> pending) {
if (pending.isEmpty()) {
return collect;
}
final Set<Map<String, String>> extract = new HashSet<Map<String, String>>();
final String key = pending.keySet().iterator().next();
for (final String value : pending.remove(key)) {
final Map<String, String> map = new TreeMap<String, String>();
map.put(key, value);
extract.add(map);
}
if (collect.isEmpty()) {
collect.addAll(extract);
return product(collect, pending);
} else {
final Set<Map<String, String>> inject = new HashSet<Map<String, String>>();
for (final Map<String, String> mapExtr : extract) {
for (final Map<String, String> mapColl : collect) {
final Map<String, String> mapProd = new TreeMap<String, String>();
mapProd.putAll(mapExtr);
mapProd.putAll(mapColl);
inject.add(mapProd);
}
}
return product(inject, pending);
}
}
/**
* Publish result on http://microbenchmarks.appspot.com
*/
public static void publish(final Result result) throws Exception {
final Runner runner = new Runner();
final Method method = runner.getClass().getDeclaredMethod(
"postResults", Result.class);
method.setAccessible(true);
method.invoke(runner, result);
}
/**
* Provide new named run instance.
*/
public static Run newRun(final String benchmarkName) {
final Map<Scenario, ScenarioResult> measurements = new HashMap<Scenario, ScenarioResult>();
final Date executedTimestamp = new Date();
final Run run = new Run(measurements, benchmarkName, executedTimestamp);
return run;
}
/**
* Make new result from run.
*/
public static Result newResult(final Run run) {
final Environment env = new EnvironmentGetter()
.getEnvironmentSnapshot();
final Result result = new Result(run, env);
return result;
}
/**
* Verify measure publication manually.
*/
public static void main(final String[] args) throws Exception {
final Run run = newRun("test-main");
for (int param = 0; param < 5; param++) {
final CaliperMeasure measure = new CaliperMeasure();
measure.variables().put("param", "" + param);
for (int step = 0; step < 5; step++) {
measure.rate().mark(50 + step);
final TimerContext time = measure.time().time();
Thread.sleep(15);
time.stop();
measure.size().value(50 + step);
measure.mark();
}
measure.appendTo(run);
}
final Result result = newResult(run);
publish(result);
System.out.println(json(result));
}
}

View File

@ -0,0 +1,250 @@
/*
* 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.transport.udt.util;
import java.io.PrintStream;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Clock;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.core.Histogram;
import com.yammer.metrics.core.Metered;
import com.yammer.metrics.core.Metric;
import com.yammer.metrics.core.MetricName;
import com.yammer.metrics.core.MetricPredicate;
import com.yammer.metrics.core.MetricProcessor;
import com.yammer.metrics.core.MetricsRegistry;
import com.yammer.metrics.core.Timer;
import com.yammer.metrics.reporting.AbstractPollingReporter;
import com.yammer.metrics.stats.Snapshot;
/**
* A simple reporters which prints out application metrics to a
* {@link PrintStream} periodically.
*/
public class CustomReporter extends AbstractPollingReporter implements
MetricProcessor<PrintStream> {
private static final int CONSOLE_WIDTH = 80;
/**
* Enables the console reporter for the default metrics registry, and causes
* it to print to STDOUT with the specified period.
*/
public static void enable(final long period, final TimeUnit unit) {
enable(Metrics.defaultRegistry(), period, unit);
}
/**
* Enables the console reporter for the given metrics registry, and causes
* it to print to STDOUT with the specified period and unrestricted output.
*/
public static void enable(final MetricsRegistry metricsRegistry,
final long period, final TimeUnit unit) {
final CustomReporter reporter = new CustomReporter(
metricsRegistry, System.out, MetricPredicate.ALL);
reporter.start(period, unit);
}
private final PrintStream out;
private final MetricPredicate predicate;
private final Clock clock;
private final TimeZone timeZone;
private final Locale locale;
/**
* Creates a new {@link CustomReporter} for the default metrics
* registry, with unrestricted output.
*/
public CustomReporter(final PrintStream out) {
this(Metrics.defaultRegistry(), out, MetricPredicate.ALL);
}
/**
* Creates a new {@link CustomReporter} for a given metrics registry.
*/
public CustomReporter(final MetricsRegistry metricsRegistry,
final PrintStream out, final MetricPredicate predicate) {
this(metricsRegistry, out, predicate, Clock.defaultClock(), TimeZone
.getDefault());
}
/**
* Creates a new {@link CustomReporter} for a given metrics registry.
*/
public CustomReporter(final MetricsRegistry metricsRegistry,
final PrintStream out, final MetricPredicate predicate,
final Clock clock, final TimeZone timeZone) {
this(metricsRegistry, out, predicate, clock, timeZone, Locale
.getDefault());
}
/**
* Creates a new {@link CustomReporter} for a given metrics registry.
*/
public CustomReporter(final MetricsRegistry metricsRegistry,
final PrintStream out, final MetricPredicate predicate,
final Clock clock, final TimeZone timeZone, final Locale locale) {
super(metricsRegistry, "console-reporter");
this.out = out;
this.predicate = predicate;
this.clock = clock;
this.timeZone = timeZone;
this.locale = locale;
}
@Override
public void run() {
try {
final DateFormat format = DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.MEDIUM, locale);
format.setTimeZone(timeZone);
final String dateTime = format.format(new Date(clock.time()));
out.print(dateTime);
out.print(' ');
for (int i = 0; i < (CONSOLE_WIDTH - dateTime.length() - 1); i++) {
out.print('=');
}
out.println();
for (final Entry<String, SortedMap<MetricName, Metric>> entry : getMetricsRegistry()
.groupedMetrics(predicate).entrySet()) {
out.print(entry.getKey());
out.println(':');
for (final Entry<MetricName, Metric> subEntry : entry
.getValue().entrySet()) {
out.print(" ");
out.print(subEntry.getKey().getName());
out.println(':');
subEntry.getValue().processWith(this, subEntry.getKey(),
out);
out.println();
}
out.println();
}
out.println();
out.flush();
} catch (final Exception e) {
e.printStackTrace(out);
}
}
@Override
public void processGauge(final MetricName name, final Gauge<?> gauge,
final PrintStream stream) {
stream.printf(locale, " value = %s\n", gauge.value());
}
@Override
public void processCounter(final MetricName name, final Counter counter,
final PrintStream stream) {
stream.printf(locale, " count = %,d\n", counter.count());
}
@Override
public void processMeter(final MetricName name, final Metered meter,
final PrintStream stream) {
final String unit = abbrev(meter.rateUnit());
stream.printf(locale, " count = %,d\n", meter.count());
stream.printf(locale, " mean rate = %,2.2f %s/%s\n",
meter.meanRate(), meter.eventType(), unit);
stream.printf(locale, " 1-minute rate = %,2.2f %s/%s\n",
meter.oneMinuteRate(), meter.eventType(), unit);
stream.printf(locale, " 5-minute rate = %,2.2f %s/%s\n",
meter.fiveMinuteRate(), meter.eventType(), unit);
stream.printf(locale, " 15-minute rate = %,2.2f %s/%s\n",
meter.fifteenMinuteRate(), meter.eventType(), unit);
}
@Override
public void processHistogram(final MetricName name,
final Histogram histogram, final PrintStream stream) {
final Snapshot snapshot = histogram.getSnapshot();
stream.printf(locale, " min = %,2.2f\n", histogram.min());
stream.printf(locale, " max = %,2.2f\n", histogram.max());
stream.printf(locale, " mean = %,2.2f\n", histogram.mean());
stream.printf(locale, " stddev = %,2.2f\n",
histogram.stdDev());
stream.printf(locale, " median = %,2.2f\n",
snapshot.getMedian());
stream.printf(locale, " 75%% <= %,2.2f\n",
snapshot.get75thPercentile());
stream.printf(locale, " 95%% <= %,2.2f\n",
snapshot.get95thPercentile());
stream.printf(locale, " 98%% <= %,2.2f\n",
snapshot.get98thPercentile());
stream.printf(locale, " 99%% <= %,2.2f\n",
snapshot.get99thPercentile());
stream.printf(locale, " 99.9%% <= %,2.2f\n",
snapshot.get999thPercentile());
}
@Override
public void processTimer(final MetricName name, final Timer timer,
final PrintStream stream) {
processMeter(name, timer, stream);
final String durationUnit = abbrev(timer.durationUnit());
final Snapshot snapshot = timer.getSnapshot();
stream.printf(locale, " min = %,2.2f %s\n", timer.min(),
durationUnit);
stream.printf(locale, " max = %,2.2f %s\n", timer.max(),
durationUnit);
stream.printf(locale, " mean = %,2.2f %s\n", timer.mean(),
durationUnit);
stream.printf(locale, " stddev = %,2.2f %s\n",
timer.stdDev(), durationUnit);
stream.printf(locale, " median = %,2.2f %s\n",
snapshot.getMedian(), durationUnit);
stream.printf(locale, " 75%% <= %,2.2f %s\n",
snapshot.get75thPercentile(), durationUnit);
stream.printf(locale, " 95%% <= %,2.2f %s\n",
snapshot.get95thPercentile(), durationUnit);
stream.printf(locale, " 98%% <= %,2.2f %s\n",
snapshot.get98thPercentile(), durationUnit);
stream.printf(locale, " 99%% <= %,2.2f %s\n",
snapshot.get99thPercentile(), durationUnit);
stream.printf(locale, " 99.9%% <= %,2.2f %s\n",
snapshot.get999thPercentile(), durationUnit);
}
private String abbrev(final TimeUnit unit) {
switch (unit) {
case NANOSECONDS:
return "ns";
case MICROSECONDS:
return "us";
case MILLISECONDS:
return "ms";
case SECONDS:
return "s";
case MINUTES:
return "m";
case HOURS:
return "h";
case DAYS:
return "d";
default:
throw new IllegalArgumentException("Unrecognized TimeUnit: " + unit);
}
}
}

View File

@ -0,0 +1,110 @@
/*
* 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.transport.udt.util;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundByteHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.transport.udt.nio.NioUdtProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yammer.metrics.core.Meter;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server on activation.
*/
public class EchoByteHandler extends ChannelInboundByteHandlerAdapter {
private static final Logger log = LoggerFactory
.getLogger(EchoByteHandler.class.getName());
private final ByteBuf message;
private final Meter meter;
public Meter meter() {
return meter;
}
public EchoByteHandler(final Meter meter, final int messageSize) {
this.meter = meter;
message = Unpooled.buffer(messageSize);
for (int i = 0; i < message.capacity(); i++) {
message.writeByte((byte) i);
}
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
ctx.write(message);
ctx.flush();
}
@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx,
final ByteBuf in) {
if (meter != null) {
meter.mark(in.readableBytes());
}
final ByteBuf out = ctx.nextOutboundByteBuffer();
out.discardReadBytes(); // FIXME
out.writeBytes(in);
ctx.flush();
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable e) {
log.error("exception : {}", e.getMessage());
ctx.close();
}
@Override
public ByteBuf newInboundBuffer(final ChannelHandlerContext ctx)
throws Exception {
return ctx.alloc().directBuffer(
ctx.channel().config().getOption(ChannelOption.SO_RCVBUF));
}
}

View File

@ -0,0 +1,108 @@
/*
* 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.transport.udt.util;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.transport.udt.UdtMessage;
import io.netty.transport.udt.nio.NioUdtProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yammer.metrics.core.Meter;
/**
* Handler implementation for the echo peer. It initiates the ping-pong traffic
* between the echo peers by sending the first message to the other peer on
* activation.
*/
public class EchoMessageHandler extends
ChannelInboundMessageHandlerAdapter<UdtMessage> {
private static final Logger log = LoggerFactory
.getLogger(EchoMessageHandler.class.getName());
private final Meter meter;
private final UdtMessage message;
public Meter meter() {
return meter;
}
public EchoMessageHandler(final Meter meter, final int messageSize) {
super(UdtMessage.class);
this.meter = meter;
final ByteBuf byteBuf = Unpooled.buffer(messageSize);
for (int i = 0; i < byteBuf.capacity(); i++) {
byteBuf.writeByte((byte) i);
}
this.message = new UdtMessage(byteBuf);
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
log.info("ECHO active {}", NioUdtProvider.socketUDT(ctx.channel())
.toStringOptions());
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable e) {
log.error("exception : {}", e.getMessage());
ctx.close();
}
@Override
protected void messageReceived(final ChannelHandlerContext ctx,
final UdtMessage message) throws Exception {
final ByteBuf byteBuf = message.data();
if (meter != null) {
meter.mark(byteBuf.readableBytes());
}
final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(message);
ctx.flush();
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.transport.udt.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Introduce traffic control, such as transfer latency.
* <p>
* requires sudo setup for /sbin/tc under current account
* <p>
* see http://www.davidverhasselt.com/2008/01/27/passwordless-sudo/
*/
public final class TrafficControl {
private static final Logger log = LoggerFactory
.getLogger(TrafficControl.class.getName());
private TrafficControl() {
}
private static final String TC_DELAY = "sudo tc qdisc add dev %s root netem delay %sms limit %s";
private static final String TC_RESET = "sudo tc qdisc del dev %s root";
/**
* verify if traffic control is available
*/
public static boolean isAvailable() {
try {
final int millis = 100;
final int margin = 20;
delay(0);
final long time1 = UnitHelp.ping("localhost");
delay(millis);
final long time2 = UnitHelp.ping("localhost");
delay(0);
final long time3 = UnitHelp.ping("localhost");
return time2 >= time1 + millis - margin
&& time2 >= time3 + millis - margin;
} catch (final Throwable e) {
log.debug("", e);
return false;
}
}
/**
* Introduce round-trip delay on local host
* @param time - delay in milliseconds; use zero to remove delay.
*/
public static void delay(final int time) throws Exception {
if (time < 0) {
throw new IllegalArgumentException("negative latency");
}
final int delay = time / 2;
if (delay == 0) {
UnitHelp.process(String.format(TC_RESET, "lo"));
} else {
/** extend packet buffer queue to avoid packet loss due to latency */
final int limit = 1024 * 1024;
UnitHelp.process(String.format(TC_RESET, "lo"));
UnitHelp.process(String.format(TC_DELAY, "lo", delay, limit));
}
}
}

View File

@ -0,0 +1,262 @@
/*
* 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.transport.udt.util;
import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.IntBuffer;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.StatusUDT;
/**
* Unit test helper.
*/
public final class UnitHelp {
private static final Logger log = LoggerFactory.getLogger(UnitHelp.class);
/**
* Zero out buffer.
*/
public static void clear(final IntBuffer buffer) {
for (int index = 0; index < buffer.capacity(); index++) {
buffer.put(index, 0);
}
}
/**
* Measure ping time to a host.
*/
public static long ping(final String host) throws Exception {
final String name = System.getProperty("os.name").toLowerCase();
final String command;
if (name.contains("linux")) {
command = "ping -c 1 " + host;
} else if (name.contains("mac os x")) {
command = "ping -c 1 " + host;
} else if (name.contains("windows")) {
command = "ping -n 1 " + host;
} else {
throw new Exception("unknown platform");
}
final long timeStart = System.currentTimeMillis();
process(command);
final long timeFinish = System.currentTimeMillis();
final long timeDiff = timeFinish - timeStart;
return timeDiff;
}
/**
* Invoke external process and wait for completion.
*/
public static void process(final String command) throws Exception {
final ProcessBuilder builder = new ProcessBuilder(command.split("\\s+"));
final Process process = builder.start();
process.waitFor();
}
/**
* @return newly allocated address or null for failure
*/
public static synchronized InetSocketAddress findLocalAddress(
final String host) {
ServerSocket socket = null;
try {
final InetAddress address = InetAddress.getByName(host);
socket = new ServerSocket(0, 3, address);
return (InetSocketAddress) socket.getLocalSocketAddress();
} catch (final Exception e) {
log.error("Failed to find addess.");
return null;
} finally {
if (socket != null) {
try {
socket.close();
} catch (final Exception e) {
log.error("Failed to close socket.");
}
}
}
}
/**
* Find named address on local host.
*/
public static InetSocketAddress hostedSocketAddress(final String host)
throws Exception {
for (int k = 0; k < 10; k++) {
final InetSocketAddress address = findLocalAddress(host);
if (address == null) {
Thread.sleep(500);
continue;
}
return address;
}
throw new Exception("Failed to allocate address.");
}
/**
* Allocate available local address / port or throw exception.
*/
public static InetSocketAddress localSocketAddress() throws Exception {
return hostedSocketAddress("localhost");
}
/**
* Display contents of a buffer.
*/
public static void logBuffer(final String title, final IntBuffer buffer) {
for (int index = 0; index < buffer.capacity(); index++) {
final int value = buffer.get(index);
if (value == 0) {
continue;
}
log.info(String.format("%s [id: 0x%08x]", title, value));
}
}
/**
* Display java.class.path
*/
public static void logClassPath() {
final String classPath = System.getProperty("java.class.path");
final String[] entries = classPath.split(File.pathSeparator);
final StringBuilder text = new StringBuilder(1024);
for (final String item : entries) {
text.append("\n\t");
text.append(item);
}
log.info("\n\t[java.class.path]{}", text);
}
/**
* Display java.library.path
*/
public static void logLibraryPath() {
final String classPath = System.getProperty("java.library.path");
final String[] entries = classPath.split(File.pathSeparator);
final StringBuilder text = new StringBuilder(1024);
for (final String item : entries) {
text.append("\n\t");
text.append(item);
}
log.info("\n\t[java.library.path]{}", text);
}
/**
* Display current OS/ARCH.
*/
public static void logOsArch() {
final StringBuilder text = new StringBuilder(1024);
text.append("\n\t");
text.append(System.getProperty("os.name"));
text.append("\n\t");
text.append(System.getProperty("os.arch"));
log.info("\n\t[os/arch]{}", text);
}
/**
* Display contents of a set.
*/
public static void logSet(final Set<?> set) {
@SuppressWarnings({ "rawtypes", "unchecked" })
final TreeSet<?> treeSet = new TreeSet(set);
for (final Object item : treeSet) {
log.info("-> {}", item);
}
}
public static String property(final String name) {
final String value = System.getProperty(name);
if (value == null) {
log.error("property '{}' not defined; terminating", name);
System.exit(1);
}
return value;
}
public static int[] randomIntArray(final int length, final int range) {
final int[] array = new int[length];
final Random generator = new Random(0);
for (int i = 0; i < array.length; i++) {
array[i] = generator.nextInt(range);
}
return array;
}
public static String randomString() {
return "" + System.currentTimeMillis();
}
public static String randomSuffix(final String name) {
return name + "-" + System.currentTimeMillis();
}
/**
* Block till socket reaches given state.
*/
public static void socketAwait(final SocketUDT socket,
final StatusUDT... statusArray) throws Exception {
while (true) {
for (final StatusUDT status : statusArray) {
if (socket.status() == status) {
return;
} else {
Thread.sleep(50);
}
}
}
}
public static Set<Integer> socketIndexSet(final IntBuffer buffer) {
final Set<Integer> set = new HashSet<Integer>();
while (buffer.hasRemaining()) {
set.add(buffer.get());
}
return set;
}
public static boolean socketPresent(final SocketUDT socket,
final IntBuffer buffer) {
for (int index = 0; index < buffer.capacity(); index++) {
if (buffer.get(index) == socket.id()) {
return true;
}
}
return false;
}
private UnitHelp() {
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.transport.udt.util;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Thread factory for tests.
*/
public class UtilThreadFactory implements ThreadFactory {
private static final AtomicInteger counter = new AtomicInteger();
private final String name;
public UtilThreadFactory(final String name) {
this.name = name;
}
@Override
public Thread newThread(final Runnable runnable) {
return new Thread(runnable, name + "-" + counter.getAndIncrement());
}
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* UDT Benchmarks and Tests Utilities
*/
package io.netty.transport.udt.util;

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="false">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ss.SSS} [%5.5thread] %-5level %16.16class{16} %-16.16method{16} %3.3line - %message%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
<logger name="com.barchart.udt.EpollUDT" level="INFO" />
</configuration>