Package com.betfair.cougar.transport.nio

Source Code of com.betfair.cougar.transport.nio.ExecutionVenueServerHandler

/*
* Copyright 2013, The Sporting Exchange Limited
*
* Licensed 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 com.betfair.cougar.transport.nio;

import com.betfair.cougar.netutil.nio.*;
import com.betfair.cougar.netutil.nio.message.EventMessage;
import com.betfair.cougar.netutil.nio.message.RequestMessage;
import com.betfair.cougar.netutil.nio.message.ResponseMessage;
import com.betfair.cougar.transport.api.TransportCommandProcessor;
import com.betfair.cougar.transport.api.protocol.CougarObjectIOFactory;
import com.betfair.cougar.transport.api.protocol.CougarObjectInput;
import com.betfair.cougar.transport.api.protocol.CougarObjectOutput;
import com.betfair.cougar.transport.api.protocol.socket.SocketBindingDescriptor;
import com.betfair.cougar.transport.socket.SocketTransportCommand;
import com.betfair.cougar.transport.socket.SocketTransportCommandImpl;
import com.betfair.cougar.transport.socket.SocketTransportCommandProcessor;
import com.betfair.cougar.transport.socket.SocketTransportRPCCommandImpl;
import com.betfair.cougar.util.jmx.Exportable;
import com.betfair.cougar.util.jmx.JMXControl;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;

import static com.betfair.cougar.netutil.nio.NioLogger.LoggingLevel.ALL;
import static com.betfair.cougar.netutil.nio.NioLogger.LoggingLevel.SESSION;

@ManagedResource
public class ExecutionVenueServerHandler extends IoHandlerAdapter implements Exportable {

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

    private TransportCommandProcessor<SocketTransportCommand> processor;
    private final NioLogger sessionLogger;

    private final AtomicLong requestsReceived = new AtomicLong();
    private final AtomicLong eventsReceived = new AtomicLong();
    private final AtomicLong sessionsOpened = new AtomicLong();
    private final AtomicLong sessionsClosed = new AtomicLong();
    private final AtomicLong otherExceptions = new AtomicLong();
    private final AtomicLong ioExceptions = new AtomicLong();

    private final CougarObjectIOFactory objectIOFactory;
    private List<HandlerListener> listeners = new CopyOnWriteArrayList<HandlerListener>();
    private final ConcurrentHashMap<IoSession, String> sessions = new ConcurrentHashMap<IoSession, String>();

    public void addListener(HandlerListener listener) {
        listeners.add(listener);
    }

    protected ExecutionVenueServerHandler() {
        sessionLogger = null;
        objectIOFactory = null;
    }

    public ExecutionVenueServerHandler(NioLogger sessionLogger, TransportCommandProcessor<SocketTransportCommand> processor,
                                       CougarObjectIOFactory objectIOFactory) {
        this.sessionLogger = sessionLogger;
        this.processor = processor;
        this.objectIOFactory = objectIOFactory;

        export(sessionLogger.getJmxControl());
    }

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        if (message instanceof ResponseMessage) {
            ((IoHandler) session.getAttribute(RequestResponseManager.SESSION_KEY)).messageReceived(session, message);
        }
        else if (message instanceof RequestMessage) {
            RequestMessage req = (RequestMessage) message;

            final CougarObjectOutput out = objectIOFactory.newCougarObjectOutput(new ByteArrayOutputStreamWithIoSession(session, req.getCorrelationId()), CougarProtocol.getProtocolVersion(session));
            final CougarObjectInput in = objectIOFactory.newCougarObjectInput(new ByteArrayInputStream(req.getPayload()), CougarProtocol.getProtocolVersion(session));
            final String remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
            final SocketTransportCommandImpl command = new SocketTransportRPCCommandImpl(in, out, remoteAddress, session);

            requestsReceived.incrementAndGet();
            processor.process(command);

            sessionLogger.log(ALL, session, "ExecutionVenueServerHandler - Message %s processed", req.getCorrelationId());
        }
        else if (message instanceof EventMessage) {
            EventMessage em = (EventMessage) message;

            final CougarObjectInput in = objectIOFactory.newCougarObjectInput(new ByteArrayInputStream(em.getPayload()), CougarProtocol.getProtocolVersion(session));
            final String remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
            final SocketTransportCommandImpl command = new SocketTransportCommandImpl(in, remoteAddress, session);

            eventsReceived.incrementAndGet();
            processor.process(command);
        } else {
            LOG.warn("ExecutionVenueServerHandler - Received unexpected message type: " + message + " - closing session");
            sessionLogger.log(NioLogger.LoggingLevel.SESSION, session, "ExecutionVenueServerHandler - Received unexpected message type: %s - closing session", message);
            session.close();
        }

    }

    @Override
    public void sessionClosed(IoSession session) throws Exception {
        super.sessionClosed(session);

        sessionsClosed.incrementAndGet();
        sessions.remove(session);
        sessionLogger.log(SESSION, session, "ExecutionVenueServerHandler: Session closed");

        for (HandlerListener listener : listeners) {
            listener.sessionClosed(session);
        }
    }

    @Override
    public void sessionOpened(IoSession session) throws Exception {
        super.sessionOpened(session);

        sessionsOpened.incrementAndGet();
        sessions.put(session, "");
        sessionLogger.log(SESSION, session, "ExecutionVenueServerHandler: Session opened");

        for (HandlerListener listener : listeners) {
            listener.sessionOpened(session);
        }
    }

    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        if (cause instanceof IOException) {
            ioExceptions.incrementAndGet();

            // We arrive here when the output pipe is broken. Broken network connections are not
            // really exceptional and should not be reported by dumping the stack trace.
            // Instead a summary debug level log message with some relevant info
            sessionLogger.log(ALL, session, "ExecutionVenueServerHandler: IOException received on session - closing");
        } else {
            otherExceptions.incrementAndGet();
            sessionLogger.log(SESSION, session, "ExecutionVenueServerHandler: Unexpected exception from session - see main log for details");
            LOG.warn("Unexpected exception from session " + NioUtils.getSessionId(session), cause);
        }
        session.close();
    }

    public void notify(SocketBindingDescriptor bindingDescriptor) {
        processor.bind(bindingDescriptor);
    }

    /**
     * Exports this service as an MBean, if the JMXControl is available
     */
    @Override
    public void export(JMXControl jmxControl) {
        if (jmxControl != null) {
            jmxControl.registerMBean("CoUGAR.socket.transport:name=handler", this);
        }
    }

    @ManagedOperation
    public String getSessionsDetails(boolean html) {
        StringBuilder buffer = new StringBuilder();
        if (html) buffer.append("<pre>");
        for (IoSession session : sessions.keySet()) {
            buffer.append("SessionId=").append(NioUtils.getSessionId(session)).append(",")
                    .append("remoteHost=").append(session.getRemoteAddress()).append(",")
                    .append("connected=").append(session.isConnected()).append(",")
                    .append("closing=").append(session.isClosing())
                    .append('\n');
        }
        if (html) buffer.append("</pre>");
        return buffer.toString();
    }

    public long getOutstandingRequests() {
        return ((SocketTransportCommandProcessor)processor).getOutstandingRequests();
    }

    @ManagedAttribute
    public long getRequestsReceived() {
        return requestsReceived.get();
    }

    @ManagedAttribute
    public long getEventsReceived() {
        return eventsReceived.get();
    }

    @ManagedAttribute
    public long getSessionsOpened() {
        return sessionsOpened.get();
    }

    @ManagedAttribute
    public long getSessionsClosed() {
        return sessionsClosed.get();
    }

    @ManagedAttribute
    public long getIoExceptionsClosingSession() {
        return ioExceptions.get();
    }

    @ManagedAttribute
    public long getOtherExceptionsClosingSession() {
        return otherExceptions.get();
    }
}
TOP

Related Classes of com.betfair.cougar.transport.nio.ExecutionVenueServerHandler

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.