ch.ethz.globis.distindex.middleware.net.IndexMiddleware.java Source code

Java tutorial

Introduction

Here is the source code for ch.ethz.globis.distindex.middleware.net.IndexMiddleware.java

Source

/*
This file is part of PH-Tree:
A multi-dimensional indexing and storage structure.
    
Copyright (C) 2011-2015
Eidgenssische Technische Hochschule Zrich (ETH Zurich)
Institute for Information Systems
GlobIS Group
Bogdan Vancea, Tilmann Zaeschke
zaeschke@inf.ethz.ch or zoodb@gmx.de
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.globis.distindex.middleware.net;

import ch.ethz.globis.distindex.middleware.IOHandler;
import ch.ethz.globis.distindex.middleware.IndexContext;
import ch.ethz.globis.distindex.middleware.PhTreeIndexMiddlewareFactory;
import ch.ethz.globis.distindex.middleware.api.Middleware;
import ch.ethz.globis.distindex.middleware.balancing.BalancingDaemon;
import ch.ethz.globis.distindex.orchestration.ClusterService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Distributed Index Server implemented using Netty.io
 */
public class IndexMiddleware<K, V> implements Middleware, Runnable {

    private static final Logger LOG = LoggerFactory.getLogger(IndexMiddleware.class);

    /** Wether the host joins as free or not. */
    private boolean joinedAsFree = false;

    /** The host on which the middleware is running */
    private String host;

    /** The port on which the middleware is running */
    private int port;

    /** A flag determining if the middleware is running or not.*/
    private boolean isRunning = false;

    /** The properties used to initialize the middleware. */
    private IOHandler<K, V> handler;

    /** The thread pool dealing with receiving data over network */
    private EventLoopGroup bossGroup;

    /** The thread pool dealing with handling the data received */
    private EventLoopGroup workerGroup;

    /** The cluster service used to notify */
    private ClusterService<K> clusterService;

    private IndexContext indexContext;

    private BalancingDaemon balancingDaemon;

    public IndexMiddleware(IndexContext indexContext, ClusterService<K> clusterService, IOHandler<K, V> handler,
            BalancingDaemon balancingDaemon) {
        this.clusterService = clusterService;
        this.indexContext = indexContext;
        this.port = indexContext.getPort();
        this.host = indexContext.getHost();
        this.handler = handler;
        this.balancingDaemon = balancingDaemon;
    }

    @Override
    public void run() {

        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();

        balancingDaemon.run();
        try {
            //initialize the server channels
            ServerBootstrap b = initServerBootstrap(handler);
            ChannelFuture f = b.bind(port).sync();

            //register as a viable host to the cluster service
            clusterService.connect();
            if (joinedAsFree) {
                clusterService.registerFreeHost(getHostId());
            } else {
                clusterService.registerHost(getHostId());
            }
            isRunning = true;

            f.channel().closeFuture().sync();
        } catch (InterruptedException ie) {
            LOG.error("An error occurred while operating on the channel.", ie);
            ie.printStackTrace();
        } finally {
            closeEventLoops();
            isRunning = false;
            //disconnect the cluster service
            clusterService.disconnect();
        }
    }

    @Override
    public void close() {
        while (indexContext.isBalancing()) {
            try {
                Thread.sleep(1L);
            } catch (InterruptedException e) {
                LOG.error("Error ");
            }
        }
        if (bossGroup == null || workerGroup == null) {
            throw new IllegalStateException("The thread pools are not properly initialized");
        }
        clusterService.disconnect();
        balancingDaemon.close();
        closeEventLoops();
        LOG.info("Shutting down middleware {} {} ", host, port);
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public void remove() {
        balancingDaemon.balanceAndRemove();
        close();
    }

    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println("Wrong number of parameters.");
        }

        try {
            String hostPortString = args[0];
            String zkHostPortString = args[1];
            String[] strings = hostPortString.split(":");
            int port = Integer.parseInt(strings[1]);
            String host = strings[0];

            strings = zkHostPortString.split(":");

            String zkHost = strings[0];
            int zkPort = Integer.valueOf(strings[1]);

            IndexMiddleware<long[], byte[]> middleware = PhTreeIndexMiddlewareFactory.newPhTree(host, port, zkHost,
                    zkPort);

            middleware.run();
        } catch (Exception ex) {
            System.out.println("Parameters should be: <port>, <zkHostPort>)");
        }
    }

    private ServerBootstrap initServerBootstrap(final IOHandler<K, V> handler) {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new MiddlewareMessageDecoder(),
                                new MiddlewareChannelHandler<K, V>(handler) {
                                });
                    }
                });
        return b;
    }

    private void closeEventLoops() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

    private String getHostId() {
        return host + ":" + port;
    }

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public boolean isJoinedAsFree() {
        return joinedAsFree;
    }

    public void setJoinedAsFree(boolean joinedAsFree) {
        this.joinedAsFree = joinedAsFree;
    }

}