com.github.brandtg.switchboard.MysqlLogPuller.java Source code

Java tutorial

Introduction

Here is the source code for com.github.brandtg.switchboard.MysqlLogPuller.java

Source

/**
 * Copyright (C) 2015 Greg Brandt (brandt.greg@gmail.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 com.github.brandtg.switchboard;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class MysqlLogPuller {
    private static final String ENCODING = "UTF-8";
    private static final Logger LOG = LoggerFactory.getLogger(MysqlLogPuller.class);
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    protected final String database;
    protected final long lastIndex;
    protected final InetSocketAddress sourceAddress;
    protected final InetSocketAddress sinkAddress;
    protected final PipedInputStream inputStream;
    protected final PipedOutputStream outputStream;
    protected final AtomicBoolean isStarted;

    protected EventLoopGroup eventExecutors;
    protected ExecutorService callbackExecutor;
    protected ExecutorService refreshExecutor;
    protected LogReceiver logReceiver;
    protected LogPuller logPuller;

    public MysqlLogPuller(String database, InetSocketAddress sourceAddress, InetSocketAddress sinkAddress) {
        this(database, sourceAddress, sinkAddress, -1);
    }

    /**
     * Creates an agent to listen to MySQL changes (via binlog).
     *
     * @param database
     *  The MySQL database name
     * @param sourceAddress
     *  The switchboard server address from which to pull events
     * @param sinkAddress
     *  The local listener port to receive raw binlog data
     * @param lastIndex
     *  The last index that was processed by whoever is constructing this (if -1, processed none)
     */
    public MysqlLogPuller(String database, InetSocketAddress sourceAddress, InetSocketAddress sinkAddress,
            long lastIndex) {
        this.database = database;
        this.lastIndex = lastIndex;
        this.sourceAddress = sourceAddress;
        this.sinkAddress = sinkAddress;
        this.inputStream = new PipedInputStream();
        this.outputStream = new PipedOutputStream();
        this.isStarted = new AtomicBoolean();
    }

    protected abstract Runnable getCallback();

    /**
     * Starts pulling events from switchboard server.
     */
    public void start() throws Exception {
        if (!isStarted.getAndSet(true)) {
            outputStream.connect(inputStream);

            callbackExecutor = Executors.newSingleThreadExecutor();
            refreshExecutor = Executors.newSingleThreadExecutor();
            eventExecutors = new NioEventLoopGroup();

            // Start server to receive log segments
            logReceiver = new LogReceiver(sinkAddress, eventExecutors, outputStream);
            logReceiver.start();

            // Iterates through events and fires appropriate callbacks
            callbackExecutor.submit(getCallback());

            // Pulls log indexes
            logPuller = new LogPuller(sourceAddress, sinkAddress, database, lastIndex);
            logReceiver.registerListener(logPuller);
            refreshExecutor.submit(logPuller);
        }
    }

    /**
     * Stops pulling events from switchboard server.
     */
    public void shutdown() throws Exception {
        if (isStarted.getAndSet(false)) {
            logPuller.shutdown();
            try {
                logReceiver.shutdown();
            } catch (Exception e) {
                LOG.error("Exception while shutting down log receiver", e);
            }
            eventExecutors.shutdownGracefully();
            callbackExecutor.shutdown();
            refreshExecutor.shutdown();
        }
    }
}