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

net.openhft.chronicle.network.cluster.HostConnector 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.cluster;

import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.core.threads.EventLoop;
import net.openhft.chronicle.network.NetworkContext;
import net.openhft.chronicle.network.NetworkStatsListener;
import net.openhft.chronicle.network.RemoteConnector;
import net.openhft.chronicle.network.connection.WireOutPublisher;
import net.openhft.chronicle.wire.WireType;
import net.openhft.chronicle.wire.WriteMarshallable;
import org.jetbrains.annotations.NotNull;

import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

public class HostConnector implements Closeable {

    private final WireType wireType;

    //  private final WriteMarshallable header;
    private final Function wireOutPublisherFactory;
    private final List bootstraps = new LinkedList<>();

    private final RemoteConnector remoteConnector;
    private final String connectUri;
    private final Function networkContextFactory;
    private final ClusterContext clusterContext;
    private NetworkContext nc;
    private volatile AtomicReference wireOutPublisher = new AtomicReference<>();

    @NotNull
    private EventLoop eventLoop;
    private final Function networkStatsListenerFactory;

    HostConnector(@NotNull ClusterContext clusterContext,
                  final RemoteConnector remoteConnector,
                  final HostDetails hostdetails) {
        this.clusterContext = clusterContext;
        this.remoteConnector = remoteConnector;
        this.networkStatsListenerFactory = clusterContext.networkStatsListenerFactory();
        this.networkContextFactory = clusterContext.networkContextFactory();
        this.connectUri = hostdetails.connectUri();
        this.wireType = clusterContext.wireType();
        this.wireOutPublisherFactory = clusterContext.wireOutPublisherFactory();
        this.eventLoop = clusterContext.eventLoop();
    }

    @Override
    public synchronized void close() {
        WireOutPublisher wp = wireOutPublisher.getAndSet(null);

        SocketChannel socketChannel = nc.socketChannel();
        if (socketChannel != null) {
            Closeable.closeQuietly(socketChannel);
            Closeable.closeQuietly(socketChannel.socket());
        }

        if (wp != null)
            wp.close();
    }

    public synchronized void bootstrap(WriteMarshallable subscription) {
        bootstraps.add(subscription);
        WireOutPublisher wp = wireOutPublisher.get();
        if (wp != null)
            wp.put("", subscription);
    }

    public synchronized void connect() {

        WireOutPublisher wireOutPublisher = wireOutPublisherFactory.apply(WireType.TEXT);

        if (!this.wireOutPublisher.compareAndSet(null, wireOutPublisher)) {
            wireOutPublisher.close();
            return;
        }

        // we will send the initial header as text wire, then the rest will be sent in
        // what ever wire is configured
        nc = networkContextFactory.apply(clusterContext);
        nc.wireOutPublisher(wireOutPublisher);
        nc.isAcceptor(false);
        nc.heartbeatTimeoutMs(clusterContext.heartbeatTimeoutMs() * 2);
        nc.socketReconnector(this::reconnect);

        if (networkStatsListenerFactory != null) {
            final NetworkStatsListener networkStatsListener = networkStatsListenerFactory.apply(clusterContext);
            SocketChannel socketChannel = nc.socketChannel();
            if (socketChannel != null
                    && socketChannel.socket() != null
                    && socketChannel.socket().getRemoteSocketAddress()
                    instanceof
                    InetSocketAddress) {
                InetSocketAddress remoteSocketAddress = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress();
                networkStatsListener.onHostPort(remoteSocketAddress.getHostName(),
                        remoteSocketAddress.getPort());
            }

            nc.networkStatsListener(networkStatsListener);
        }

        boolean firstTime = true;
        for (WriteMarshallable bootstrap : bootstraps) {
            wireOutPublisher.publish(bootstrap);

            // its only the uberhandler that we want to publish using TEXT_WIRE
            if (firstTime)
                wireOutPublisher.wireType(wireType);
        }

        nc.wireType(wireType);

        remoteConnector.connect(connectUri, eventLoop, nc, 1_000L);
    }

    synchronized void reconnect() {
        close();
        if (!nc.isAcceptor())
            HostConnector.this.connect();

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy