Package com.linkedin.databus.bootstrap.common

Source Code of com.linkedin.databus.bootstrap.common.BootstrapDBCleanerQueryExecutor

package com.linkedin.databus.bootstrap.common;

import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.linkedin.databus.bootstrap.common.BootstrapCleanerStaticConfig.BootstrapDBType;
import com.linkedin.databus.core.DatabusRuntimeException;
import com.linkedin.databus.core.DbusEvent;
import com.linkedin.databus.core.DbusEventFactory;
import com.linkedin.databus2.util.DBHelper;

/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* 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.
*
*/

public class BootstrapDBCleanerQueryExecutor
{
  public static final String MODULE = BootstrapDBCleanerQueryExecutor.class.getName();
  public final Logger LOG;

  // Used for identifying the source in log4j
  private final String _name;
  private final Connection _conn;
  private final BootstrapDBCleanerQueryHelper _bootstrapDBCleanerQueryHelper;

  public BootstrapDBCleanerQueryExecutor(String name, Connection conn, BootstrapDBCleanerQueryHelper bootstrapDBCleanerQueryHelper)
  {
    _name = name;
    LOG = Logger.getLogger(MODULE + "." + name);
    if (null != conn)
    {
      _conn = conn;
    }
    else
    {
      throw new DatabusRuntimeException("Invalid to pass in a null connection object");
    }

    if (null != bootstrapDBCleanerQueryHelper)
    {
      _bootstrapDBCleanerQueryHelper = bootstrapDBCleanerQueryHelper;
    }
    else
    {
      throw new DatabusRuntimeException("Invalid to pass in a null for bootstrapDBCleanerQueryHelper");
    }

  }

  /*
   * @return the LogInfo(srcId,logId,windowSCN) for the entry in
   * bootstrap_applier_state with minimum SCN
   */
  public BootstrapLogInfo getThresholdWindowSCN(BootstrapDBType type, int srcId)
      throws SQLException
  {
    String sql = null;

    switch (type)
    {
    case BOOTSTRAP_CATCHUP_APPLIER_NOT_RUNNING:
      sql = getMinProducerSCNLogStmt(srcId);
      break;
    case BOOTSTRAP_CATCHUP_APPLIER_RUNNING:
    case BOOTSTRAP_FULL:
      sql = getMinApplierSCNLogStmt(srcId);
      break;
    }

    LOG.info("Threshold WindowScn fetch Query :" + sql);
    BootstrapLogInfo logInfo = new BootstrapLogInfo();
    ResultSet rs = null;
    PreparedStatement stmt = null;
    try
    {
      stmt = _conn.prepareStatement(sql);
      rs = stmt.executeQuery();
      if (!rs.next())
      {
        LOG.error("SQL :(" + sql + ") returned empty records");
        return null;
      }

      logInfo.setLogId(rs.getInt(1));
      logInfo.setSrcId(rs.getShort(2));
      logInfo.setMinWindowSCN(rs.getLong(3));
      logInfo.setMaxWindowSCN(rs.getLong(3));

    } finally
    {
      DBHelper.close(rs, stmt, null);
    }

    return logInfo;
  }

  /*
   * @param srcId : SourceId
   *
   * @param windowSCN : windowSCN to be checked
   *
   * @return the LogInfo(srcId,logId,minWindowSCN) for the entry in
   * bootstrap_loginfo with minimum SCN > passed SCN
   */
  public BootstrapLogInfo getFirstLogTableWithGreaterSCN(short srcId, long windowSCN)
      throws SQLException
  {
    String sql = _bootstrapDBCleanerQueryHelper.getFirstLogTableWithGreaterSCNStmt();
    ResultSet rs = null;
    PreparedStatement stmt = null;
    BootstrapLogInfo logInfo = new BootstrapLogInfo();

    try
    {
      stmt = _conn.prepareStatement(sql);
      stmt.setShort(1, srcId);
      stmt.setLong(2, windowSCN);
      rs = stmt.executeQuery();

      if (rs.next())
      {
        logInfo.setSrcId(srcId);
        logInfo.setLogId(rs.getInt(1));
        logInfo.setMinWindowSCN(rs.getLong(2));
        logInfo.setMaxWindowSCN(rs.getLong(3));
      }
      else
      {
        return null;
      }
    } finally
    {
      DBHelper.close(rs, stmt, null);
    }
    return logInfo;
  }

  /*
   * Find the list of logTables for a source that are candidates for cleanup
   *
   * @param windowSCN : MinimumSCN in bootstrap_applier_state table
   *
   * @param srcid : SourceId
   *
   * @return list of LogInfo for log tables for the source that can be removed
   * in descending order of logIds
   */
  public List<BootstrapLogInfo> getCandidateLogsInfo(long windowSCN, short srcId)
      throws SQLException
  {
    List<BootstrapLogInfo> logsInfo = new ArrayList<BootstrapLogInfo>();
    String sql = _bootstrapDBCleanerQueryHelper.getCandidateLogIdsForSrcStmt();
    LOG.info("SQL statement for fetching candidate logIds :" + sql);

    ResultSet rs = null;
    PreparedStatement stmt = null;
    try
    {
      stmt = _conn.prepareStatement(sql);
      stmt.setShort(1, srcId);
      stmt.setLong(2, windowSCN);
      stmt.setShort(3, srcId);
      rs = stmt.executeQuery();

      while (rs.next())
      {
        BootstrapLogInfo logInfo = new BootstrapLogInfo();
        logInfo.setSrcId(srcId);
        logInfo.setLogId(rs.getInt(1));
        logInfo.setMinWindowSCN(rs.getLong(2));
        logInfo.setMaxWindowSCN(rs.getLong(3));
        logsInfo.add(logInfo);
      }
    } finally
    {
      DBHelper.close(rs, stmt, null);
    }
    return logsInfo;
  }

  public void updateSource(BootstrapLogInfo logInfo) throws SQLException
  {
    LOG.info("Updating logStartSCN to " + logInfo.getMinWindowSCN()
        + " for srcid :" + logInfo.getSrcId());
    String sql = _bootstrapDBCleanerQueryHelper.getUpdateLogStartSCNStmt();
    PreparedStatement stmt = null;
    try
    {
      stmt = _conn.prepareStatement(sql);
      stmt.setLong(1, logInfo.getMinWindowSCN());
      stmt.setShort(2, logInfo.getSrcId());
      stmt.executeUpdate();
    } finally
    {
      DBHelper.close(stmt);
    }
  }

  /*
   * Drop Tables corresponding to the list of LogInfo
   *
   * @param logsInfo : LogInfo of the tables needed to be deleted
   *
   * @return the list of LogInfo corresponding to tables that have been
   * successfully dropped.
   */
  public List<BootstrapLogInfo> dropTables(List<BootstrapLogInfo> logsInfo)
  {
    List<BootstrapLogInfo> deletedLogsInfo = new ArrayList<BootstrapLogInfo>();

    for (BootstrapLogInfo logInfo : logsInfo)
    {
      try
      {
        dropTable(logInfo);
        deletedLogsInfo.add(logInfo);
      } catch (SQLException ex)
      {
        LOG.error("Unable to delete log table :" + logInfo.getLogTable(), ex);
      }
    }
    return deletedLogsInfo;
  }

  /*
   * Mark Tables deleted corresponding to the list of LogInfo
   *
   * @param logsInfo : LogInfo of the tables needed to be marked
   *
   * @return the list of LogInfo corresponding to tables that have been
   * successfully marked.
   */
  public List<BootstrapLogInfo> markDeleted(List<BootstrapLogInfo> logsInfo) throws SQLException
  {
    Connection conn = null;
    PreparedStatement stmt = null;
    List<BootstrapLogInfo> deletedLogsInfo = new ArrayList<BootstrapLogInfo>();
    String sql = _bootstrapDBCleanerQueryHelper.getMarkDeletedStmt();
    try
    {
      stmt = _conn.prepareStatement(sql);
      for (BootstrapLogInfo logInfo : logsInfo)
      {
        try
        {
          LOG.info("Marking table : " + logInfo.getLogTable() + " deleted !!");
          stmt.setShort(1, logInfo.getSrcId());
          stmt.setInt(2, logInfo.getLogId());
          stmt.executeUpdate();
          deletedLogsInfo.add(logInfo);
        } catch (SQLException ex)
        {
          LOG.error("Unable to mark delete log table :" + logInfo.getLogTable()
              + " in bootstrap_loginfo");
          throw ex;
        }
      }
    } finally
    {
      DBHelper.close(stmt);
    }
    return deletedLogsInfo;
  }

  public long getNanoTimestampOfLastEventinLog(BootstrapLogInfo logInfo, DbusEventFactory eventFactory)
  throws SQLException
  {
    long nanoTimestamp = Long.MAX_VALUE;
    BootstrapDBRow r = getLastEventinLog(logInfo, eventFactory);

    if ((null != r) && (null != r.getEvent()))
    {
      nanoTimestamp = r.getEvent().timestampInNanos();
    }
    return nanoTimestamp;
  }

  public long getSCNOfLastEventinLog(BootstrapLogInfo logInfo, DbusEventFactory eventFactory)
  throws SQLException
  {
    long scn = -1;
    BootstrapDBRow r = getLastEventinLog(logInfo, eventFactory);

    if (null != r)
    {
      scn = r.getScn();
    }
    return scn;
  }

  private BootstrapDBRow getLastEventinLog(BootstrapLogInfo logInfo, DbusEventFactory eventFactory)
  throws SQLException
  {
    Statement stmt = null;
    ResultSet rs = null;
    long id = -1;
    long scn = -1;
    String key = null;
    DbusEvent event = null;
    try
    {
      String tableName = logInfo.getLogTable();
      StringBuilder sql = new StringBuilder();
      sql.append("select id, srckey, scn, val from ");
      sql.append(tableName);
      sql.append(" where id = ( select max(id) from ");
      sql.append(tableName);
      sql.append(" )");
      stmt = _conn.createStatement();
      rs = stmt.executeQuery(sql.toString());
      if (rs.next())
      {
        int i = 1;
        id = rs.getLong(i++);
        String srcKey = rs.getString(i++);
        scn = rs.getLong(i++);
        ByteBuffer tmpBuffer = ByteBuffer.wrap(rs.getBytes(i));
        LOG.info("BUFFER SIZE:" + tmpBuffer.limit());
        event = eventFactory.createReadOnlyDbusEventFromBuffer(tmpBuffer,
            tmpBuffer.position());
        LOG.info("Last Row for log (" + logInfo + ") - ID :" + id
            + ", srcKey :" + srcKey + ", SCN :" + scn + ", Event :"
            + event.toString());
      }
      else
      {
        LOG.error("No ResultSet for query :" + sql.toString());
      }

    } finally
    {
      DBHelper.close(rs, stmt, null);
    }
    return new BootstrapDBRow(id, key, scn, event);
  }

  /*
   * Drops a table corresponding to the passed logInfo
   *
   * @param logInfo : LogInfo of the table to be dropped.
   */
  private void dropTable(BootstrapLogInfo logInfo)
  throws SQLException
  {
    String tableName = logInfo.getLogTable();
    String cmd = "drop table if exists " + tableName;
    Statement stmt = null;
    try
    {
      LOG.info("Dropping table :" + tableName);
      stmt = _conn.createStatement();
      stmt.executeUpdate(cmd);
    } finally
    {
      DBHelper.close(stmt);
    }
  }

  public int optimizeTable(String tableName)
  throws SQLException
  {
    final String cmd = "optimize table " + tableName;
    PreparedStatement stmt = null;
    int ret = -1;
    try
    {
      LOG.info("Optimizing table :" + tableName + ", CMD :(" + cmd + ")");
      stmt = _conn.prepareStatement(cmd);
      ret = stmt.executeUpdate();
    } finally
    {
      DBHelper.close(stmt);
    }
    return ret;
  }

  public int deleteTable(String tableName, long scn)
  throws SQLException
  {
    final String cmd = "delete from " + tableName + " where scn <= ?";
    int ret = -1;
    if (scn <= 0)
    {
      LOG.info("Trying to delete rows whose scn <=" + scn + ", skipping !!");
      return ret;
    }

    PreparedStatement stmt = null;
    try
    {
      LOG.info("Deleting events from table :" + tableName + ", CMD :(" + cmd
          + "), SCN :" + scn);
      stmt = _conn.prepareStatement(cmd);
      stmt.setLong(1, scn);
      ret = stmt.executeUpdate();
    } finally
    {
      DBHelper.close(stmt);
    }
    return ret;
  }

  private String getMinApplierSCNLogStmt(int srcId)
  {
    StringBuilder sql = new StringBuilder();
    sql.append("select logid,srcid,windowscn from bootstrap_applier_state ");
    sql.append("where srcid=");
    sql.append(srcId);
    sql.append(" order by windowscn asc limit 1");
    return sql.toString();
  }

  private String getMinProducerSCNLogStmt(int srcId)
  {
    StringBuilder sql = new StringBuilder();
    sql.append("select logid,srcid,windowscn from bootstrap_producer_state ");
    sql.append("where srcid=");
    sql.append(srcId);
    sql.append(" order by windowscn asc limit 1");
    return sql.toString();
  }
}
TOP

Related Classes of com.linkedin.databus.bootstrap.common.BootstrapDBCleanerQueryExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.