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

com.github.brandtg.switchboard.MysqlLogPuller Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2015 Greg Brandt ([email protected])
 *
 * 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();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy