poke.server.worker.comm.CommHandler.java Source code

Java tutorial

Introduction

Here is the source code for poke.server.worker.comm.CommHandler.java

Source

/*
 * copyright 2014, gash
 * 
 * Gash 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 poke.server.worker.comm;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

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

import poke.server.managers.RoutedJobManager;
import poke.server.managers.RoutingManager;
import poke.server.queue.PerChannelQueue;
import poke.server.roundrobin.RoundRobinInitilizers;

import com.google.protobuf.GeneratedMessage;

import eye.Comm.Request;

public class CommHandler extends SimpleChannelInboundHandler<eye.Comm.Request> {
    protected static Logger logger = LoggerFactory.getLogger("connect");
    protected ConcurrentMap<String, CommListener> listeners = new ConcurrentHashMap<String, CommListener>();

    public CommHandler() {
    }

    /**
     * messages pass through this method. We use a blackbox design as much as
        
     * possible to ensure we can replace the underlining communication without
     * affecting behavior.
     * 
     * @param msg
     * @return
     * @throws InterruptedException 
     */
    public boolean send(GeneratedMessage msg, Channel ch) throws InterruptedException {
        // TODO a queue is needed to prevent overloading of the socket
        // connection. For the demonstration, we don't need it 

        ChannelFuture cf = ch.writeAndFlush((Request) msg);

        cf.awaitUninterruptibly();
        logger.info(" " + cf.cause());
        if (cf.isDone() && !cf.isSuccess()) {
            logger.error("failed to poke!");
            return false;
        }
        return true;
    }

    /**
     * Notification registration. Classes/Applications receiving information
     * will register their interest in receiving content.
     * 
     * Note: Notification is serial, FIFO like. If multiple listeners are
     * present, the data (message) is passed to the listener as a mutable
     * object.
     * 
     * @param listener
     */
    public void addListener(CommListener listener) {
        if (listener == null)
            return;

        listeners.putIfAbsent(listener.getListenerID(), listener);
    }

    /**
     * a message was received from the server. Here we dispatch the message to
     * the client's thread pool to minimize the time it takes to process other
     * messages.
     * 
     * @param ctx
     *            The channel the message was received from
     * @param msg
     *            The message
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, eye.Comm.Request msg) throws Exception {

        logger.info("Reply message: \n " + msg);
        String uuid = msg.getHeader().getUniqueJobId();
        ConcurrentHashMap<String, PerChannelQueue> outgoingJOBs = RoutedJobManager.getInstance().getJobMap();
        for (String uuidsample : outgoingJOBs.keySet()) {
            if (uuidsample.equals(uuid)) {
                PerChannelQueue pq = outgoingJOBs.get(uuid);
                RoundRobinInitilizers rri = RoutingManager.getInstance().getBalancer().get(pq.getRouteNodeId());
                if (rri != null) {
                    rri.reduceJobsInQueue();
                } else {
                    logger.info("rri null");
                }

                if (pq.channel != null) {
                    pq.enqueueResponse(msg, pq.channel);
                } else {
                    logger.error("could not find channel for current reply");
                }
                outgoingJOBs.remove(uuid);
                RoutedJobManager.getInstance().setJobMap(outgoingJOBs);
                //ctx.channel().close();
            }
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("Unexpected exception occureed", cause);
        ctx.close();
    }

    //Server Timeout Event
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            if (e.state() == IdleState.READER_IDLE) {
                ctx.close();
            } else if (e.state() == IdleState.WRITER_IDLE) {
                ctx.channel().close();
            }
        }
    }
}