Package com.dianping.cosmos.hive.server.queryengine.jdbc

Source Code of com.dianping.cosmos.hive.server.queryengine.jdbc.HiveJdbcClient

package com.dianping.cosmos.hive.server.queryengine.jdbc;

import java.io.BufferedWriter;
import java.security.PrivilegedAction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.security.Krb5Login;
import org.apache.hadoop.security.UserGroupInformation;
import org.springframework.stereotype.Service;

import com.dianping.cosmos.hive.client.bo.TableSchemaBo;
import com.dianping.cosmos.hive.server.queryengine.HiveQueryOutput;
import com.dianping.cosmos.hive.shared.util.ReflectUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;

@Service
public class HiveJdbcClient {
  private static final Log logger = LogFactory.getLog(HiveJdbcClient.class);

  private static final int USER_SHOW_ROW_MAXIMUM_COUNT = 300;

  private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";

  private static Cache<String, Connection> connCache = CacheBuilder
      .newBuilder().concurrencyLevel(4).maximumSize(100000)
      .expireAfterWrite(24, TimeUnit.HOURS)
      .removalListener(new RemovalListener<String, Connection>() {

        @Override
        public void onRemoval(RemovalNotification<String, Connection> rn) {
          logger.info(("tokenid:" + rn.getKey() + " Connection"
              + rn.getValue() + " was removed from connCache"));
        }

      }).build();

  private static Cache<String, UserGroupInformation> ugiCache = CacheBuilder
      .newBuilder()
      .concurrencyLevel(4)
      .maximumSize(100000)
      .expireAfterWrite(24, TimeUnit.HOURS)
      .removalListener(
          new RemovalListener<String, UserGroupInformation>() {

            @Override
            public void onRemoval(
                RemovalNotification<String, UserGroupInformation> rn) {
              logger.info(("tokenid:" + rn.getKey()
                  + " UserGroupInformation:" + rn.getValue() + " was removed from connCache"));
            }

          }).build();

  static {
    try {
      Class.forName(driverName);
    } catch (ClassNotFoundException cfe) {
      logger.error("Hive Driver Not Found " + driverName, cfe);
    }
  }

  public static void putTokenConn(String tokenid, Connection conn) {
    connCache.put(tokenid, conn);
  }

  public static Connection getTokenConn(String tokenid) {
    return connCache.getIfPresent(tokenid);
  }

  public static UserGroupInformation getUgiCache(String tokenid) {
    return ugiCache.getIfPresent(tokenid);
  }

  public static void putUgiCache(String tokenid, UserGroupInformation ugi) {
    ugiCache.put(tokenid, ugi);
  }

  public static void removeConnectionByTokenid(String tokenid) {
    connCache.invalidate(tokenid);
  }

  public static void removeUgiByTokenid(String tokenid) {
    ugiCache.invalidate(tokenid);
  }

  public List<String> getDatabases(String tokenid) {
    List<String> dbs = new ArrayList<String>();
    UserGroupInformation ugi = ugiCache.getIfPresent(tokenid);
    Connection conn = getConnection(ugi);
    Statement stmt;
    try {
      stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery("show databases");
      while (rs.next()) {
        if (rs.getString(1).equalsIgnoreCase("default")) {
          dbs.add(0, rs.getString(1));
        } else {
          dbs.add(rs.getString(1));
        }
      }
      rs.close();
      stmt.close();
    } catch (Exception e) {
      logger.error("getDatabases:" + e.getMessage());
    } finally {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return dbs;
  }

  public List<String> getTables(String tokenid, String database) {
    List<String> tables = new ArrayList<String>();
    UserGroupInformation ugi = ugiCache.getIfPresent(tokenid);
    Connection conn = getConnection(ugi);
    Statement stmt;
    try {
      stmt = conn.createStatement();
      stmt.execute("use " + database);
      ResultSet rs = stmt.executeQuery("show tables");
      while (rs.next()) {
        tables.add(rs.getString(1));
      }
      rs.close();
      stmt.close();
    } catch (Exception e) {
      logger.error("getTables failed :" + e.getMessage());
    } finally {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return tables;
  }

  public List<TableSchemaBo> getTableSchema(String tokenid, String database,
      String table) {
    List<TableSchemaBo> tsbs = new ArrayList<TableSchemaBo>();
    UserGroupInformation ugi = ugiCache.getIfPresent(tokenid);
    Connection conn = getConnection(ugi);
    Statement stmt;
    try {
      stmt = conn.createStatement();
      stmt.execute("use " + database);
      ResultSet rs = stmt.executeQuery("desc " + table);
      while (rs.next()) {
        TableSchemaBo tsb = new TableSchemaBo();
        tsb.setFieldName(rs.getString(1));
        tsb.setFieldType(rs.getString(2));
        tsb.setFieldComment(rs.getString(3));

        if (logger.isDebugEnabled()) {
          logger.debug("getTableSchema " + tsb);
        }
        tsbs.add(tsb);
      }
      rs.close();
      stmt.close();
    } catch (Exception e) {
      logger.error("getTableSchema failed", e);
    } finally {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return tsbs;
  }

  public String getTableSchemaDetail(String tokenid, String database,
      String table) {
    UserGroupInformation ugi = ugiCache.getIfPresent(tokenid);
    Connection conn = getConnection(ugi);
    StringBuilder sb = new StringBuilder(1000);
    Statement stmt;
    try {
      stmt = conn.createStatement();
      stmt.execute("use " + database);
      ResultSet rs = stmt.executeQuery("desc formatted " + table);
      ResultSetMetaData rsm = rs.getMetaData();
      int columnCount = rsm.getColumnCount();
      while (rs.next()) {
        for (int i = 1; i <= columnCount; i++) {
          if (StringUtils.isBlank(rs.getString(i))) {
            continue;
          } else {
            sb.append(rs.getString(i)).append('\t');
          }
        }
        sb.append('\n');
      }
      rs.close();
      stmt.close();
    } catch (Exception e) {
      logger.error(
          String.format(
              "getTableSchemaDetail failed , tokenid:%s, database:%s, table:%s",
              tokenid, database, table), e);
    } finally {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return sb.toString();
  }

  @SuppressWarnings({ "unchecked" })
  public String getQueryPlan(String tokenid, String hql, String database) {
    UserGroupInformation ugi = ugiCache.getIfPresent(tokenid);
    Connection conn = getConnection(ugi);
    StringBuilder sb = new StringBuilder(1000);
    Statement stmt;
    try {
      stmt = conn.createStatement();
      stmt.executeQuery("use " + database);
      stmt.setFetchSize(Integer.MAX_VALUE);
      ResultSet rs = stmt.executeQuery("explain " + hql);
      if (rs.next()) {
        Object value = ReflectUtils.getFieldValue(rs, "fetchedRows");
        List<String> fetchedRows = (List<String>) value;
        if (fetchedRows == null || fetchedRows.size() == 0) {
          sb.append("something wrong with hive query");
        } else {
          for (String row : fetchedRows) {
            sb.append(row).append("\n");
          }
        }
      } else {
        logger.error("execute 'explain hql' failed, hql:" + hql);
      }
      rs.close();
      stmt.close();
    } catch (Exception e) {
      sb.append(e.toString());
      logger.error("getQueryPlan failed, dbname:" + database + " hql:"
          + hql, e);
    } finally {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
   
    if (logger.isDebugEnabled()){
      logger.debug("dbname:" + database + " query plan for hql:" + hql
          + " is " + sb.toString());
    }
    return sb.toString();
  }

  public HiveQueryOutput getQueryResult(String tokenid, String username,
      String database, String hql, int resultLimit, Boolean isStoreFile,
      long timestamp) {
    HiveQueryOutput hqo = new HiveQueryOutput();
    UserGroupInformation ugi = ugiCache.getIfPresent(tokenid);
    Connection conn = getConnection(ugi);
    Statement stmt;
    try {
      stmt = conn.createStatement();
      stmt.executeQuery("use " + database);
      ResultSet rs = stmt.executeQuery(hql);
      ResultSetMetaData rsm = rs.getMetaData();
      int columnCount = rsm.getColumnCount();
      List<String> columnNames = new ArrayList<String>(columnCount);

      StringBuilder sb = new StringBuilder(200);
      for (int i = 1; i <= columnCount; i++) {
        columnNames.add(rsm.getColumnName(i));
        if (logger.isDebugEnabled()) {
          sb.append(rsm.getColumnName(i)).append("\t")
              .append(rsm.getColumnTypeName(i)).append("\n");
        }
      }

      if (logger.isDebugEnabled()) {
        logger.debug("resultset meta data is:" + sb.toString());
      }

      hqo.setTitleList(columnNames);
      int maxShowRowCount = resultLimit < USER_SHOW_ROW_MAXIMUM_COUNT ? resultLimit
          : USER_SHOW_ROW_MAXIMUM_COUNT;
      int currentRow = 0;

      String storeFilePath = "";
      BufferedWriter bw = null;
      if (isStoreFile) {
        storeFilePath = DataFileStore.getStoreFilePath(tokenid,
            username, database, hql, timestamp);
        bw = DataFileStore.openOutputStream(storeFilePath);
      }
      logger.info("isStoreFile:" + isStoreFile + " storeFilePath:"
          + storeFilePath);

      if (!StringUtils.isBlank(storeFilePath)) {
        hqo.setStoreFileLocation(storeFilePath);
      }

      while (rs.next()
          && currentRow < DataFileStore.FILE_STORE_LINE_LIMIT) {
        if (currentRow < maxShowRowCount) {
          List<String> oneRowData = new ArrayList<String>();
          for (int i = 1; i <= columnCount; i++) {
            String value = rs.getString(i) == null ? "" : rs
                .getString(i);
            oneRowData.add(value);
            if (isStoreFile) {
              bw.write(value);
              if (i < columnCount)
                bw.write('\t');
            }
          }
          hqo.addRow(oneRowData);

          if (isStoreFile) {
            bw.write('\n');
          }
        } else if (isStoreFile) {
          for (int i = 1; i <= columnCount; i++) {
            bw.write(rs.getString(i));
            if (i < columnCount)
              bw.write('\t');
          }
          bw.write('\n');
        } else {
          break;
        }
        currentRow++;
      }
      if (isStoreFile && bw != null) {
        bw.flush();
        IOUtils.closeQuietly(bw);
      }
      rs.close();
      stmt.close();
    } catch (Exception e) {
      hqo.setErrorMessage(e.toString());
      logger.error("getQueryResult failed, db:" + database + " hql:"
          + hql, e);
    } finally {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    return hqo;
  };

  public static Connection getConnection(final UserGroupInformation ugi) {
    Connection conn = null;
    if (ugi != null){
      conn = ugi.doAs(new PrivilegedAction<Connection>() {
        @Override
        public Connection run() {
          Connection c = null;
          try {
            if (logger.isDebugEnabled()) {
              logger.debug("start get connection ugi username:" + ugi.getUserName()) ;
            }
           
            c = DriverManager.getConnection(
                Krb5Login.HIVE_CONNECTION_URL, "", "");
           
            if (logger.isDebugEnabled()) {
              logger.debug("through get connection ugi username:" + ugi.getUserName()) ;
            }
          } catch (Exception e) {
            logger.error("get connection failed:" + e.getMessage());
          }
          return c;
        }
      });
    }
    return conn;
  }
}
TOP

Related Classes of com.dianping.cosmos.hive.server.queryengine.jdbc.HiveJdbcClient

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.