All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.chronicle.network.ConnectorEventHandler Maven / Gradle / Ivy

There is a newer version: 2.17.4
Show newest version
/*
 * Copyright 2016 higherfrequencytrading.com
 *
 * 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 net.openhft.chronicle.network;

import net.openhft.chronicle.core.threads.EventHandler;
import net.openhft.chronicle.core.threads.EventLoop;
import net.openhft.chronicle.core.threads.HandlerPriority;
import net.openhft.chronicle.core.threads.InvalidEventHandlerException;
import net.openhft.chronicle.network.api.TcpHandler;
import net.openhft.chronicle.network.api.session.SessionDetailsProvider;
import net.openhft.chronicle.threads.LongPauser;
import net.openhft.chronicle.threads.Pauser;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Created by daniel on 09/02/2016. This class handles the creation, running and monitoring of
 * client connections
 */
public class ConnectorEventHandler implements EventHandler, Closeable {
    private static final Logger LOG = LoggerFactory.getLogger(ConnectorEventHandler.class);

    @NotNull
    private final Function tcpHandlerSupplier;
    @NotNull
    private final Supplier sessionDetailsSupplier;

    private final Map descriptionToChannel = new ConcurrentHashMap<>();
    private final Pauser pauser = new LongPauser(0, 0, 5, 5, TimeUnit.SECONDS);
    private EventLoop eventLoop;
    private Map nameToConnectionDetails;

    public ConnectorEventHandler(@NotNull Map nameToConnectionDetails,
                                 @NotNull final Function tcpHandlerSupplier,
                                 @NotNull final Supplier
                                         sessionDetailsSupplier) {
        this.nameToConnectionDetails = nameToConnectionDetails;
        this.tcpHandlerSupplier = tcpHandlerSupplier;
        this.sessionDetailsSupplier = sessionDetailsSupplier;
    }

    @Override
    public boolean action() throws InvalidEventHandlerException, InterruptedException {
        nameToConnectionDetails.forEach((k, connectionDetails) -> {
            try {
                SocketChannel socketChannel = descriptionToChannel.get(k);

                if (socketChannel == null) {
                    if (connectionDetails.isDisable()) {
                        //we shouldn't create anything
                        return;
                    }
                    socketChannel = TCPRegistry.createSocketChannel(connectionDetails.getHostNameDescription());
                    socketChannel.socket().setTcpNoDelay(true);
                    socketChannel.socket().setSendBufferSize(1 << 20);
                    socketChannel.socket().setReceiveBufferSize(1 << 20);
                    socketChannel.configureBlocking(false);
                    descriptionToChannel.put(k, socketChannel);
                    connectionDetails.setConnected(true);
                    final SessionDetailsProvider sessionDetails = sessionDetailsSupplier.get();

                    sessionDetails.clientAddress((InetSocketAddress) socketChannel.getRemoteAddress());
                    connectionDetails.socketChannel(socketChannel);
                    final TcpEventHandler evntHandler = new TcpEventHandler(connectionDetails);
                    evntHandler.tcpHandler(tcpHandlerSupplier.apply(connectionDetails));
                    eventLoop.addHandler(evntHandler);
                } else if (socketChannel.isOpen()) {
                    //the socketChannel is doing fine
                    //check whether it should be disabled
                    if (connectionDetails.isDisable()) {
                        socketChannel.close();
                        connectionDetails.setConnected(false);
                        descriptionToChannel.remove(k);
                    }
                } else {
                    //the socketChannel has disconnected
                    connectionDetails.setConnected(false);
                    descriptionToChannel.remove(k);
                }
            } catch (ConnectException e) {
                //Not a problem try again next time round
                LOG.error(k + e.getMessage());
            } catch (IOException e) {
                LOG.error(k + e.getMessage());

            }
        });

        pauser.pause();

        return false;
    }

    public void updateConnectionDetails(ConnectionDetails connectionDetails) {
        //todo this is not strictly necessary
        nameToConnectionDetails.put(connectionDetails.getID(), connectionDetails);
        forceRescan();
    }

    /**
     * By default the connections are monitored every 5 seconds If you want to force the map to
     * check immediately use forceRescan
     */
    public void forceRescan() {
        pauser.unpause();
    }

    @Override
    public void eventLoop(EventLoop eventLoop) {
        this.eventLoop = eventLoop;
    }

    @NotNull
    @Override
    public HandlerPriority priority() {
        return HandlerPriority.BLOCKING;
    }

    @Override
    public void close() throws IOException {

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy