Package de.bwaldvogel.mongo

Source Code of de.bwaldvogel.mongo.MongoServer

package de.bwaldvogel.mongo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.bwaldvogel.mongo.backend.MongoBackend;
import de.bwaldvogel.mongo.backend.memory.MemoryBackend;
import de.bwaldvogel.mongo.wire.MongoDatabaseHandler;
import de.bwaldvogel.mongo.wire.MongoExceptionHandler;
import de.bwaldvogel.mongo.wire.MongoWireEncoder;
import de.bwaldvogel.mongo.wire.MongoWireProtocolHandler;

public class MongoServer {

    private static final Logger log = LoggerFactory.getLogger(MongoServer.class);

    private MongoBackend backend;

    private EventLoopGroup bossGroup;

    private EventLoopGroup workerGroup;

    private ChannelGroup channelGroup;

    private Channel channel;

    public static void main(String[] args) throws Exception {
        final MongoServer mongoServer = new MongoServer();
        mongoServer.bind(new InetSocketAddress(InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }), 27017));
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                log.info("shutting down {}", mongoServer);
                mongoServer.shutdownNow();
            }
        });
    }

    /**
     * creates a mongo server with in-memory backend
     */
    public MongoServer() {
        this(new MemoryBackend());
    }

    public MongoServer(MongoBackend backend) {
        this.backend = backend;
    }

    public void bind(SocketAddress socketAddress) {

        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();
        channelGroup = new DefaultChannelGroup("mongodb-channels", workerGroup.next());

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap//
                    .group(bossGroup, workerGroup)//
                    .channel(NioServerSocketChannel.class)//
                    .option(ChannelOption.SO_BACKLOG, 100)//
                    .localAddress(socketAddress)//
                    .childOption(ChannelOption.TCP_NODELAY, true)//
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new MongoWireEncoder());
                            ch.pipeline().addLast(new MongoWireProtocolHandler());
                            ch.pipeline().addLast(new MongoDatabaseHandler(backend, channelGroup));
                            ch.pipeline().addLast(new MongoExceptionHandler());
                        }
                    });

            channel = bootstrap.bind().syncUninterruptibly().channel();

            log.info("started {}", this);
        } catch (RuntimeException e) {
            shutdownNow();
            throw e;
        }
    }

    /**
     * starts and binds the server on a local random port
     *
     * @return the random local address the server was bound to
     */
    public InetSocketAddress bind() {
        bind(new InetSocketAddress("localhost", 0));
        return getLocalAddress();
    }

    /**
     * @return the local address the server was bound or null if the server is
     *         not listening
     */
    public InetSocketAddress getLocalAddress() {
        if (channel == null)
            return null;
        return (InetSocketAddress) channel.localAddress();
    }

    /**
     * Stop accepting new clients. Wait until all resources (such as client
     * connection) are closed and then shutdown. This method blocks until all
     * clients are finished. Use {@link #shutdownNow()} if the shutdown should
     * be forced.
     */
    public void shutdown() {
        stopListenting();

        // Shut down all event loops to terminate all threads.
        bossGroup.shutdownGracefully(0, 5, TimeUnit.SECONDS);
        workerGroup.shutdownGracefully(0, 5, TimeUnit.SECONDS);

        bossGroup.terminationFuture().syncUninterruptibly();
        workerGroup.terminationFuture().syncUninterruptibly();

        log.info("completed shutdown of {}", this);
    }

    /**
     * Closes the server socket. No new clients are accepted afterwards.
     */
    public void stopListenting() {
        if (channel != null) {
            log.info("closing server channel");
            channel.close().syncUninterruptibly();
            channel = null;
        }
    }

    /**
     * Stops accepting new clients, closes all clients and finally shuts down
     * the server In contrast to {@link #shutdown()}, this method should not
     * block.
     */
    public void shutdownNow() {
        stopListenting();
        closeClients();
        shutdown();
    }

    private void closeClients() {
        final int numClients = channelGroup.size();
        if (numClients > 0) {
            log.warn("Closing {} clients", numClients);
        }
        channelGroup.close().syncUninterruptibly();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
        sb.append("(");
        InetSocketAddress socketAddress = getLocalAddress();
        if (socketAddress != null) {
            sb.append("port: ").append(socketAddress.getPort());
        }
        sb.append(")");
        return sb.toString();
    }
}
TOP

Related Classes of de.bwaldvogel.mongo.MongoServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.