package redis.server.netty;
import com.sampullara.cli.Args;
import com.sampullara.cli.Argument;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
/**
* Redis server
*/
public class Main {
@Argument(alias = "p")
private static Integer port = 6380;
public static void main(String[] args) throws InterruptedException {
try {
Args.parse(Main.class, args);
} catch (IllegalArgumentException e) {
Args.usage(Main.class);
System.exit(1);
}
// Only execute the command handler in a single thread
final RedisCommandHandler commandHandler = new RedisCommandHandler(new SimpleRedisServer());
// Configure the server.
ServerBootstrap b = new ServerBootstrap();
final DefaultEventExecutorGroup group = new DefaultEventExecutorGroup(1);
try {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.localAddress(port)
.childOption(ChannelOption.TCP_NODELAY, true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
// p.addLast(new ByteLoggingHandler(LogLevel.INFO));
p.addLast(new RedisCommandDecoder());
p.addLast(new RedisReplyEncoder());
p.addLast(group, commandHandler);
}
});
// Start the server.
ChannelFuture f = b.bind().sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
group.shutdownGracefully();
}
}
}