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

org.yamcs.replication.ReplicationClient Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.replication;

import static org.yamcs.replication.ReplicationServer.workerGroup;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import org.yamcs.logging.Log;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.ssl.SslContext;
import io.netty.util.concurrent.ScheduledFuture;

/**
 * Replication TCP client - works both on the master and on the slave side depending on the config
 * 
 */
public class ReplicationClient {
    final String host;
    final int port;
    final Supplier channelHandlerSupplier;
    final Log log;
    final long reconnectionInterval;
    final int maxTupleSize;
    Channel channel;
    ScheduledFuture reconnectFuture;
    Bootstrap bootstrap;
    volatile boolean quitting = false;
    SslContext sslCtx = null;

    public ReplicationClient(String yamcsInstance, String host, int port, SslContext sslCtx,
            long reconnectionInterval, int maxTupleSize,
            Supplier channelHandlerSupplier) {
        this.port = port;
        this.host = host;
        this.channelHandlerSupplier = channelHandlerSupplier;
        this.reconnectionInterval = reconnectionInterval;
        log = new Log(getClass(), yamcsInstance);
        this.sslCtx = sslCtx;
        this.maxTupleSize = maxTupleSize;
    }

    public void start() {
        bootstrap = new Bootstrap();
        bootstrap.group(workerGroup)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        if (sslCtx != null) {
                            ch.pipeline().addLast(sslCtx.newHandler(ch.alloc()));
                        }
                        ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(maxTupleSize, 1, 3));
                        ch.pipeline().addLast(channelHandlerSupplier.get());
                    }
                });
        doConnect();
    }

    private void doConnect() {
        log.debug("Connecting for replication to {}:{}", host, port);
        bootstrap.connect(host, port).addListener((ChannelFuture f) -> {
            if (f.isSuccess()) {
                channel = f.channel();
                log.info("Connected to server at {}:{}", host, port);
                channel.closeFuture().addListener(f1 -> {
                    scheduleReconnect();
                });
            } else {
                log.warn("Failed to connect: {}", f.cause().getMessage(), f.cause());
                scheduleReconnect();
            }
        });
    }

    void scheduleReconnect() {
        if (quitting || reconnectionInterval < 0) {
            return;
        }

        if (reconnectFuture != null) {
            reconnectFuture.cancel(true);
        }
        reconnectFuture = workerGroup.schedule(() -> doConnect(), reconnectionInterval, TimeUnit.MILLISECONDS);
    }

    public void stop() {
        quitting = true;
        if (reconnectFuture != null) {
            reconnectFuture.cancel(true);
        }
        if (channel != null) {
            channel.close();
        }
    }

    public Channel getChannel() {
        return channel;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy