Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alipay.oceanbase.rpc.location.LocationUtil Maven / Gradle / Ivy
/*-
* #%L
* OBKV Table Client Framework
* %%
* Copyright (C) 2021 OceanBase
* %%
* OBKV Table Client Framework is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* #L%
*/
package com.alipay.oceanbase.rpc.location;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alipay.oceanbase.rpc.ObClusterTableBatchOps;
import com.alipay.oceanbase.rpc.ObGlobal;
import com.alipay.oceanbase.rpc.constant.Constants;
import com.alipay.oceanbase.rpc.exception.*;
import com.alipay.oceanbase.rpc.location.model.*;
import com.alipay.oceanbase.rpc.location.model.partition.*;
import com.alipay.oceanbase.rpc.protocol.payload.ResultCodes;
import com.alipay.oceanbase.rpc.protocol.payload.impl.ObCollationType;
import com.alipay.oceanbase.rpc.protocol.payload.impl.ObColumn;
import com.alipay.oceanbase.rpc.protocol.payload.impl.ObObjType;
import com.alipay.oceanbase.rpc.protocol.payload.impl.column.ObGeneratedColumn;
import com.alipay.oceanbase.rpc.protocol.payload.impl.column.ObSimpleColumn;
import com.alipay.oceanbase.rpc.protocol.payload.impl.execute.ObIndexType;
import com.alipay.oceanbase.rpc.protocol.payload.impl.parser.ObGeneratedColumnExpressParser;
import com.alipay.oceanbase.rpc.util.TableClientLoggerFactory;
import org.slf4j.Logger;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.*;
import java.text.MessageFormat;
import java.util.*;
import static com.alipay.oceanbase.rpc.location.model.partition.ObPartitionKey.MAX_PARTITION_ELEMENT;
import static com.alipay.oceanbase.rpc.location.model.partition.ObPartitionKey.MIN_PARTITION_ELEMENT;
import static com.alipay.oceanbase.rpc.util.RandomUtil.getRandomNum;
import static com.alipay.oceanbase.rpc.util.TableClientLoggerFactory.*;
import static java.lang.String.format;
import static com.alipay.oceanbase.rpc.protocol.payload.Constants.INVALID_LS_ID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LocationUtil {
private static final Logger logger = TableClientLoggerFactory
.getLogger(LocationUtil.class);
static {
ParserConfig.getGlobalInstance().setSafeMode(true);
}
private static final String OB_VERSION_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ OB_VERSION() AS CLUSTER_VERSION;";
private static final String PROXY_INDEX_INFO_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ data_table_id, table_id, index_type FROM oceanbase.__all_virtual_table "
+ "where table_name = ?";
private static final String PROXY_TABLE_ID_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ table_id from oceanbase.__all_virtual_proxy_schema "
+ "where tenant_name = ? and database_name = ? and table_name = ? limit 1";
private static final String OB_TENANT_EXIST_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ tenant_id from __all_tenant where tenant_name = ?;";
@Deprecated
@SuppressWarnings("unused")
private static final String PROXY_PLAIN_SCHEMA_SQL_FORMAT = "SELECT /*+READ_CONSISTENCY(WEAK)*/ partition_id, svr_ip, sql_port, table_id, role, part_num, replica_num, schema_version, spare1 "
+ "FROM oceanbase.__all_virtual_proxy_schema "
+ "WHERE tenant_name = ? AND database_name = ? AND table_name = ? AND partition_id in ({0}) AND sql_port > 0 "
+ "ORDER BY role ASC LIMIT ?";
private static final String PROXY_PART_INFO_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_level, part_num, part_type, part_space, part_expr, "
+ "part_range_type, part_interval_bin, interval_start_bin, "
+ "sub_part_num, sub_part_type, sub_part_space, "
+ "sub_part_range_type, def_sub_part_interval_bin, def_sub_interval_start_bin, sub_part_expr, "
+ "part_key_name, part_key_type, part_key_idx, part_key_extra, spare1 "
+ "FROM oceanbase.__all_virtual_proxy_partition_info "
+ "WHERE table_id = ? group by part_key_name order by part_key_name LIMIT ?;";
@Deprecated
@SuppressWarnings("unused")
private static final String PROXY_TENANT_SCHEMA_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ svr_ip, sql_port, table_id, role, part_num, replica_num, spare1 "
+ "FROM oceanbase.__all_virtual_proxy_schema "
+ "WHERE tenant_name = ? AND database_name = ? AND table_name = ? AND sql_port > 0 "
+ "ORDER BY partition_id ASC, role ASC LIMIT ?";
private static final String PROXY_DUMMY_LOCATION_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ A.partition_id as partition_id, A.svr_ip as svr_ip, A.sql_port as sql_port, "
+ "A.table_id as table_id, A.role as role, A.replica_num as replica_num, A.part_num as part_num, B.svr_port as svr_port, B.status as status, B.stop_time as stop_time "
+ ", A.spare1 as replica_type "
+ "FROM oceanbase.__all_virtual_proxy_schema A inner join oceanbase.__all_server B on A.svr_ip = B.svr_ip and A.sql_port = B.inner_port "
+ "WHERE tenant_name = ? and database_name=? and table_name = ?";
private static final String PROXY_LOCATION_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ A.partition_id as partition_id, A.svr_ip as svr_ip, A.sql_port as sql_port, "
+ "A.table_id as table_id, A.role as role, A.replica_num as replica_num, A.part_num as part_num, B.svr_port as svr_port, B.status as status, B.stop_time as stop_time "
+ ", A.spare1 as replica_type "
+ "FROM oceanbase.__all_virtual_proxy_schema A inner join oceanbase.__all_server B on A.svr_ip = B.svr_ip and A.sql_port = B.inner_port "
+ "WHERE tenant_name = ? and database_name=? and table_name = ? and partition_id = 0";
private static final String PROXY_LOCATION_SQL_PARTITION = "SELECT /*+READ_CONSISTENCY(WEAK)*/ A.partition_id as partition_id, A.svr_ip as svr_ip, A.sql_port as sql_port, "
+ "A.table_id as table_id, A.role as role, A.replica_num as replica_num, A.part_num as part_num, B.svr_port as svr_port, B.status as status, B.stop_time as stop_time "
+ ", A.spare1 as replica_type "
+ "FROM oceanbase.__all_virtual_proxy_schema A inner join oceanbase.__all_server B on A.svr_ip = B.svr_ip and A.sql_port = B.inner_port "
+ "WHERE tenant_name = ? and database_name=? and table_name = ? and partition_id in ({0})";
private static final String PROXY_FIRST_PARTITION_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, part_name, high_bound_val "
+ "FROM oceanbase.__all_virtual_proxy_partition "
+ "WHERE table_id = ? LIMIT ?;";
private static final String PROXY_SUB_PARTITION_SQL = "SELECT /*+READ_CONSISTENCY(WEAK)*/ sub_part_id, part_name, high_bound_val "
+ "FROM oceanbase.__all_virtual_proxy_sub_partition "
+ "WHERE table_id = ? LIMIT ?;";
private static final String PROXY_SERVER_STATUS_INFO = "SELECT ss.svr_ip, ss.zone, zs.region, zs.spare4 as idc "
+ "FROM oceanbase.__all_virtual_proxy_server_stat ss, oceanbase.__all_virtual_zone_stat zs "
+ "WHERE zs.zone = ss.zone ;";
@Deprecated
@SuppressWarnings("unused")
private static final String PROXY_PLAIN_SCHEMA_SQL_FORMAT_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ tablet_id, svr_ip, sql_port, table_id, role, part_num, replica_num, schema_version, spare1 "
+ "FROM oceanbase.__all_virtual_proxy_schema "
+ "WHERE tenant_name = ? AND database_name = ? AND table_name = ? AND tablet_id in ({0}) AND sql_port > 0 "
+ "ORDER BY role ASC LIMIT ?";
private static final String PROXY_PART_INFO_SQL_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_level, part_num, part_type, part_space, part_expr, "
+ "part_range_type, sub_part_num, sub_part_type, sub_part_space, sub_part_range_type, sub_part_expr, "
+ "part_key_name, part_key_type, part_key_idx, part_key_extra, part_key_collation_type "
+ "FROM oceanbase.__all_virtual_proxy_partition_info "
+ "WHERE tenant_name = ? and table_id = ? group by part_key_name order by part_key_name LIMIT ?;";
@Deprecated
@SuppressWarnings("unused")
private static final String PROXY_TENANT_SCHEMA_SQL_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ svr_ip, sql_port, table_id, role, part_num, replica_num, spare1 "
+ "FROM oceanbase.__all_virtual_proxy_schema "
+ "WHERE tenant_name = ? AND database_name = ? AND table_name = ? AND sql_port > 0 "
+ "ORDER BY tablet_id ASC, role ASC LIMIT ?";
private static final String PROXY_DUMMY_LOCATION_SQL_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ A.tablet_id as tablet_id, A.svr_ip as svr_ip, A.sql_port as sql_port, "
+ "A.table_id as table_id, A.role as role, A.replica_num as replica_num, A.part_num as part_num, B.svr_port as svr_port, B.status as status, B.stop_time as stop_time "
+ ", A.spare1 as replica_type "
+ "FROM oceanbase.__all_virtual_proxy_schema A inner join oceanbase.__all_server B on A.svr_ip = B.svr_ip and A.sql_port = B.inner_port "
+ "WHERE tenant_name = ? and database_name=? and table_name = ?";
private static final String PROXY_LOCATION_SQL_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ A.tablet_id as tablet_id, A.svr_ip as svr_ip, A.sql_port as sql_port, "
+ "A.table_id as table_id, A.role as role, A.replica_num as replica_num, A.part_num as part_num, B.svr_port as svr_port, B.status as status, B.stop_time as stop_time "
+ ", A.spare1 as replica_type "
+ "FROM oceanbase.__all_virtual_proxy_schema A inner join oceanbase.__all_server B on A.svr_ip = B.svr_ip and A.sql_port = B.inner_port "
+ "WHERE tenant_name = ? and database_name=? and table_name = ? and tablet_id = 0";
private static final String PROXY_LOCATION_SQL_PARTITION_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ A.tablet_id as tablet_id, A.svr_ip as svr_ip, A.sql_port as sql_port, "
+ "A.table_id as table_id, A.role as role, A.replica_num as replica_num, A.part_num as part_num, B.svr_port as svr_port, B.status as status, B.stop_time as stop_time "
+ ", A.spare1 as replica_type, D.ls_id as ls_id "
+ "FROM oceanbase.__all_virtual_proxy_schema A inner join oceanbase.__all_server B on A.svr_ip = B.svr_ip and A.sql_port = B.inner_port "
+ "inner join oceanbase.DBA_OB_TENANTS C on C.tenant_name = A.tenant_name "
+ "left join oceanbase.CDB_OB_TABLET_TO_LS D on D.tenant_id = C.tenant_id and D.tablet_id = A.tablet_id "
+ "WHERE C.tenant_name = ? and database_name= ? and table_name = ? and A.tablet_id in ({0}) ";
private static final String PROXY_FIRST_PARTITION_SQL_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ part_id, part_name, tablet_id, high_bound_val, sub_part_num "
+ "FROM oceanbase.__all_virtual_proxy_partition "
+ "WHERE tenant_name = ? and table_id = ? LIMIT ?;";
private static final String PROXY_SUB_PARTITION_SQL_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ sub_part_id, part_name, tablet_id, high_bound_val "
+ "FROM oceanbase.__all_virtual_proxy_sub_partition "
+ "WHERE tenant_name = ? and table_id = ? LIMIT ?;";
private static final String PROXY_SERVER_STATUS_INFO_V4 = "SELECT ss.svr_ip, ss.zone, zs.region, zs.idc as idc "
+ "FROM DBA_OB_SERVERS ss, DBA_OB_ZONES zs "
+ "WHERE zs.zone = ss.zone ;";
private static final String home = System.getProperty("user.home",
"/home/admin");
private static final String TABLE_GROUP_GET_TABLE_NAME_V4 = "SELECT /*+READ_CONSISTENCY(WEAK)*/ table_name "
+ "FROM oceanbase.CDB_OB_TABLEGROUP_TABLES "
+ "WHERE tablegroup_name = ? and tenant_id = ? limit 1;";
private static final int TEMPLATE_PART_ID = -1;
// limit the size of get tableEntry location from remote each time
private static final int MAX_TABLET_NUMS_EPOCH = 300;
private abstract static class TableEntryRefreshWithPriorityCallback {
abstract T execute(ObServerAddr obServerAddr) throws ObTableEntryRefreshException;
}
private abstract static class TableEntryRefreshCallback {
abstract T execute(Connection connection) throws ObTableEntryRefreshException;
}
private static ObServerAddr randomObServers(List obServerAddrs) {
return obServerAddrs.get(getRandomNum(0, obServerAddrs.size()));
}
private static TableEntry callTableEntryRefreshWithPriority(ServerRoster serverRoster,
long priorityTimeout,
long cachingTimeout,
TableEntryRefreshWithPriorityCallback callable)
throws ObTableEntryRefreshException {
ObServerAddr addr = serverRoster.getServer(priorityTimeout, cachingTimeout);
try {
TableEntry tableEntry = callable.execute(addr);
serverRoster.resetPriority(addr);
return tableEntry;
} catch (ObTableEntryRefreshException e) {
RUNTIME.error("callTableEntryRefreshWithPriority meet exception", e);
serverRoster.downgradePriority(addr);
throw e;
} catch (Throwable t) {
RUNTIME.error("callTableEntryRefreshWithPriority meet exception", t);
throw t;
}
}
/*
* Get Server LDC info from OB system table.
*/
public static List getServerLdc(ServerRoster serverRoster,
final long connectTimeout,
final long socketTimeout,
final long priorityTimeout,
final long cachingTimeout,
final ObUserAuth sysUA)
throws ObTableEntryRefreshException {
ObServerAddr addr = serverRoster.getServer(priorityTimeout, cachingTimeout);
try {
List ss = callServerLdcRefresh(addr, connectTimeout, socketTimeout,
sysUA);
serverRoster.resetPriority(addr);
return ss;
} catch (ObTableEntryRefreshException e) {
RUNTIME.error("getServerLdc meet exception", e);
serverRoster.downgradePriority(addr);
throw e;
} catch (Throwable t) {
RUNTIME.error("callTableEntryRefreshWithPriority meet exception", t);
throw t;
}
}
/*
* Format ob server url with the tenant server.
*
* @param obServerAddr
* @param connectTimeout
* @param socketTimeout
* @return
*/
private static String formatObServerUrl(ObServerAddr obServerAddr, long connectTimeout,
long socketTimeout) {
return format(
"jdbc:mysql://%s/oceanbase?useUnicode=true&characterEncoding=utf-8&connectTimeout=%d&socketTimeout=%d",
obServerAddr.getIp() + ":" + obServerAddr.getSqlPort(), connectTimeout, socketTimeout);
}
/*
* Establish db connection to the given database URL, with proxy user/password.
*
* @param url
* @return
* @throws ObTableEntryRefreshException
*/
private static Connection getMetaRefreshConnection(String url, ObUserAuth sysUA)
throws ObTableEntryRefreshException {
loadJdbcDriver();
try {
return DriverManager.getConnection(url, sysUA.getUserName(), sysUA.getPassword());
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00005"), e.getMessage(), e);
throw new ObTableEntryRefreshException("fail to connect meta server", e);
}
}
private static void loadJdbcDriver() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return;
} catch (ClassNotFoundException e) {
RUNTIME.info("Class 'com.mysql.cj.jdbc.Driver' not found, "
+ "try to load legacy driver class 'com.mysql.jdbc.Driver'");
}
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
RUNTIME.error(LCD.convert("01-00006"), e.getMessage(), e);
throw new ObTableEntryRefreshException(format("fail to find jdbc driver, errMsg=%s",
e.getMessage()), e);
}
}
/*
* Refresh server LDC info.
*
* @param obServerAddr
* @param connectTimeout
* @param socketTimeout
* @return List
* @throws ObTableEntryRefreshException
*/
private static List callServerLdcRefresh(ObServerAddr obServerAddr,
long connectTimeout,
long socketTimeout, ObUserAuth sysUA)
throws ObTableEntryRefreshException {
String url = formatObServerUrl(obServerAddr, connectTimeout, socketTimeout);
List ss = new ArrayList();
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = getMetaRefreshConnection(url, sysUA);
if (ObGlobal.obVsnMajor() >= 4) {
ps = connection.prepareStatement(PROXY_SERVER_STATUS_INFO_V4);
} else {
ps = connection.prepareStatement(PROXY_SERVER_STATUS_INFO);
}
rs = ps.executeQuery();
while (rs.next()) {
String ip = rs.getString("svr_ip");
String zone = rs.getString("zone");
String idc = rs.getString("idc");
String region = rs.getString("region");
ss.add(new ObServerLdcItem(ip, zone, idc, region));
}
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00027"), url, e);
throw new ObTableEntryRefreshException(format(
"fail to refresh server LDC from remote url=%s", url), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
// ignore
}
}
return ss;
}
private static TableEntry callTableEntryRefresh(ObServerAddr obServerAddr, TableEntryKey key,
long connectTimeout, long socketTimeout,
ObUserAuth sysUA, boolean initialized,
TableEntryRefreshCallback callback)
throws ObTableEntryRefreshException {
String url = formatObServerUrl(obServerAddr, connectTimeout, socketTimeout);
Connection connection = null;
TableEntry entry;
try {
connection = getMetaRefreshConnection(url, sysUA);
entry = callback.execute(connection);
} catch (ObTableNotExistException e) {
// avoid to refresh meta for ObTableNotExistException
RUNTIME.error("callTableEntryRefresh meet exception", e);
throw e;
} catch (Exception e) {
if (!initialized) {
BOOT.error(LCD.convert("01-00007"), url, key, e);
} else {
RUNTIME.error(LCD.convert("01-00007"), url, key, e);
}
throw new ObTableEntryRefreshException(format(
"fail to refresh table entry from remote url=%s, key=%s", url, key), e);
} finally {
try {
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
// ignore
}
}
if (entry != null && entry.isValid()) {
entry.setRefreshTimeMills(System.currentTimeMillis());
return entry;
} else {
if (!initialized) {
BOOT.error(LCD.convert("01-00008"), obServerAddr, key, entry);
} else {
RUNTIME.error(LCD.convert("01-00008"), obServerAddr, key, entry);
RUNTIME.error("table entry is invalid");
}
throw new ObTableEntryRefreshException("table entry is invalid, addr = " + obServerAddr
+ " key =" + key + " entry =" + entry);
}
}
/*
* Load table entry with priority.
*/
public static TableEntry loadTableEntryWithPriority(final ServerRoster serverRoster,
final TableEntryKey key,
final long connectTimeout,
final long socketTimeout,
final long priorityTimeout,
final long cachingTimeout,
final ObUserAuth sysUA)
throws ObTableEntryRefreshException {
return callTableEntryRefreshWithPriority(serverRoster, priorityTimeout, cachingTimeout,
new TableEntryRefreshWithPriorityCallback() {
@Override
TableEntry execute(ObServerAddr obServerAddr) throws ObTableEntryRefreshException {
return callTableEntryRefresh(obServerAddr, key, connectTimeout, socketTimeout,
sysUA, true, new TableEntryRefreshCallback() {
@Override
TableEntry execute(Connection connection)
throws ObTableEntryRefreshException {
return getTableEntryFromRemote(connection, key, true);
}
});
}
});
}
/*
* Load table entry location with priority.
*/
public static TableEntry loadTableEntryLocationWithPriority(final ServerRoster serverRoster,
final TableEntryKey key,
final TableEntry tableEntry,
final long connectTimeout,
final long socketTimeout,
final long priorityTimeout,
final long cachingTimeout,
final ObUserAuth sysUA)
throws ObTableEntryRefreshException {
return callTableEntryRefreshWithPriority(serverRoster, priorityTimeout, cachingTimeout,
new TableEntryRefreshWithPriorityCallback() {
@Override
TableEntry execute(ObServerAddr obServerAddr) throws ObTableEntryRefreshException {
return callTableEntryRefresh(obServerAddr, key, connectTimeout, socketTimeout,
sysUA, true, new TableEntryRefreshCallback() {
@Override
TableEntry execute(Connection connection)
throws ObTablePartitionLocationRefreshException {
return getTableEntryLocationFromRemote(connection, key, tableEntry);
}
});
}
});
}
/*
* load Table Name With table Group
*/
public static String loadTableNameWithGroupName(final ServerRoster serverRoster,
final TableEntryKey key,
final long connectTimeout,
final long socketTimeout,
final long priorityTimeout,
final long cachingTimeout,
final ObUserAuth sysUA)
throws ObTableNotExistException {
Connection connection = null;
String realTableName = "";
String url = "";
ObServerAddr addr = serverRoster.getServer(priorityTimeout, cachingTimeout);
try {
url = formatObServerUrl(addr, connectTimeout, socketTimeout);
connection = getMetaRefreshConnection(url, sysUA);
realTableName = getTableNameByGroupNameFromRemote(connection, key);
serverRoster.resetPriority(addr);
} catch (ObTableNotExistException e) {
RUNTIME.error("callTableEntryNameWithPriority meet exception", e);
serverRoster.downgradePriority(addr);
throw e;
} catch (Exception e) {
throw new ObTableNotExistException(format(
"fail to get table name from remote url=%s, key=%s", url, key), e);
} catch (Throwable t) {
RUNTIME.error("callTableEntryNameWithPriority meet exception", t);
throw t;
} finally {
try {
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
// ignore
}
}
if (realTableName != null && !realTableName.isEmpty()) {
return realTableName;
} else {
throw new ObTableNotExistException("table name is invalid, addr = " + addr + " key ="
+ key + " tableName =" + realTableName);
}
}
/*
* get TableName From Remote with Group
*/
private static String getTableNameByGroupNameFromRemote(Connection connection, TableEntryKey key)
throws ObTableNotExistException {
PreparedStatement ps = null;
ResultSet rs = null;
String realTableName = "";
int tenantId = -1;
try {
if (ObGlobal.obVsnMajor() == 0) {
getObVersionFromRemote(connection);
}
tenantId = checkTenantExistFromRemote(connection, key);
if (ObGlobal.obVsnMajor() >= 4) {
ps = connection.prepareStatement(TABLE_GROUP_GET_TABLE_NAME_V4);
ps.setString(1, key.getTableName());
ps.setString(2, String.valueOf(tenantId));
} else {
throw new ObTableNotExistException(format(
"fail to get table name from remote in low version than 4, key=%s", key));
}
rs = ps.executeQuery();
while (rs.next()) {
realTableName = rs.getString("table_name");
}
} catch (ObTableNotExistException e) {
// avoid to refresh meta for ObTableNotExistException
RUNTIME.error("getTableNameByGroupNameFromRemote meet exception", e);
throw e;
} catch (Exception e) {
RUNTIME.error("getTableNameByGroupNameFromRemote meet exception", e);
throw new ObTableNotExistException(format("fail to get table name from remote, key=%s",
key), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
return realTableName;
}
/*
* Load table entry randomly.
*/
public static TableEntry loadTableEntryRandomly(final List rsList,//
final TableEntryKey key, //
final long connectTimeout,//
final long socketTimeout,
final ObUserAuth sysUA,
final boolean initialized)
throws ObTableEntryRefreshException {
return callTableEntryRefresh(randomObServers(rsList), key, connectTimeout, socketTimeout,
sysUA, initialized, new TableEntryRefreshCallback() {
@Override
TableEntry execute(Connection connection) throws ObTableEntryRefreshException {
return getTableEntryFromRemote(connection, key, initialized);
}
});
}
private static void getObVersionFromRemote(Connection connection)
throws ObTableEntryRefreshException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement(OB_VERSION_SQL);
rs = ps.executeQuery();
if (rs.next()) {
String versionString = rs.getString("CLUSTER_VERSION");
parseObVersionFromSQL(versionString);
} else {
throw new ObTableEntryRefreshException("fail to get ob version from remote");
}
} catch (Exception e) {
throw new ObTableEntryRefreshException("fail to get ob version from remote", e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
}
// check tenant exist or not
private static int checkTenantExistFromRemote(Connection connection, TableEntryKey key)
throws ObTableEntryRefreshException {
try (PreparedStatement ps = connection.prepareStatement(OB_TENANT_EXIST_SQL)) {
ps.setString(1, key.getTenantName());
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) {
throw new ObTableEntryRefreshException("fail to get tenant id from remote");
} else {
return rs.getInt("tenant_id");
}
} catch (Exception e) {
throw new ObTableEntryRefreshException("fail to get tenant id from remote", e);
}
} catch (Exception e) {
throw new ObTableEntryRefreshException("fail to get tenant id from remote", e);
}
}
private static TableEntry getTableEntryFromRemote(Connection connection, TableEntryKey key,
boolean initialized)
throws ObTableEntryRefreshException {
PreparedStatement ps = null;
ResultSet rs = null;
TableEntry tableEntry;
int tenantId = -1;
try {
if (ObGlobal.obVsnMajor() == 0) {
getObVersionFromRemote(connection);
}
tenantId = checkTenantExistFromRemote(connection, key);
if (ObGlobal.obVsnMajor() >= 4) {
if (key.getTableName().equals(Constants.ALL_DUMMY_TABLE)) {
ps = connection.prepareStatement(PROXY_DUMMY_LOCATION_SQL_V4);
ps.setString(1, key.getTenantName());
ps.setString(2, key.getDatabaseName());
ps.setString(3, key.getTableName());
} else {
ps = connection.prepareStatement(PROXY_LOCATION_SQL_V4);
ps.setString(1, key.getTenantName());
ps.setString(2, key.getDatabaseName());
ps.setString(3, key.getTableName());
}
} else {
if (key.getTableName().equals(Constants.ALL_DUMMY_TABLE)) {
ps = connection.prepareStatement(PROXY_DUMMY_LOCATION_SQL);
ps.setString(1, key.getTenantName());
ps.setString(2, key.getDatabaseName());
ps.setString(3, key.getTableName());
} else {
ps = connection.prepareStatement(PROXY_LOCATION_SQL);
ps.setString(1, key.getTenantName());
ps.setString(2, key.getDatabaseName());
ps.setString(3, key.getTableName());
}
}
rs = ps.executeQuery();
tableEntry = getTableEntryFromResultSet(key, rs);
if (null != tableEntry) {
tableEntry.setTableEntryKey(key);
// TODO: check capacity flag later
// fetch tablet ids when table is partition table
if (tableEntry.isPartitionTable()) {
// fetch partition info
fetchPartitionInfo(connection, tableEntry);
if (null != tableEntry.getPartitionInfo()) {
// fetch first range part
if (null != tableEntry.getPartitionInfo().getFirstPartDesc()) {
ObPartFuncType obPartFuncType = tableEntry.getPartitionInfo()
.getFirstPartDesc().getPartFuncType();
fetchFirstPart(connection, tableEntry, obPartFuncType);
}
// fetch sub range part
if (null != tableEntry.getPartitionInfo().getSubPartDesc()) {
ObPartFuncType subPartFuncType = tableEntry.getPartitionInfo()
.getSubPartDesc().getPartFuncType();
fetchSubPart(connection, tableEntry, subPartFuncType);
}
}
}
// get location info
getTableEntryLocationFromRemote(connection, key, tableEntry);
if (!initialized) {
if (BOOT.isInfoEnabled()) {
BOOT.info("get table entry from remote, entry={}", JSON.toJSON(tableEntry));
}
} else {
if (logger.isInfoEnabled()) {
logger.info("get table entry from remote");
}
}
}
} catch (ObTableNotExistException e) {
// avoid to refresh meta for ObTableNotExistException
RUNTIME.error("getTableEntryFromRemote meet exception", e);
throw e;
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00009"), key, e);
throw new ObTableEntryRefreshException(format(
"fail to get table entry from remote, key=%s", key), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
return tableEntry;
}
private static String genLocationSQLByOffset(TableEntry tableEntry, int offset, int size) {
StringBuilder sb = new StringBuilder();
String sql = null;
long endOffset = -1;
long allPartNum = tableEntry.getPartitionNum();
if (offset < 0 || offset >= allPartNum || size < 0) {
throw new IllegalArgumentException("Illegal arguement: offset: " + offset + ", size: "
+ size);
} else {
endOffset = Math.min(offset + size, allPartNum);
}
if (ObGlobal.obVsnMajor() >= 4) {
if (tableEntry.isPartitionTable()) {
Map partTabletIdMap = tableEntry.getPartitionInfo()
.getPartTabletIdMap();
Long[] tabletIds = partTabletIdMap.values().toArray(new Long[0]);
for (int i = offset; i < endOffset; i++) {
if (i > offset) {
sb.append(", ");
}
sb.append(tabletIds[i]);
}
} else {
for (int i = offset; i < endOffset; i++) {
if (i > offset) {
sb.append(", ");
}
sb.append(i);
}
}
sql = MessageFormat.format(PROXY_LOCATION_SQL_PARTITION_V4, sb.toString());
} else {
if (tableEntry.isPartitionTable()
&& null != tableEntry.getPartitionInfo().getSubPartDesc()) {
long subPartNum = tableEntry.getPartitionInfo().getSubPartDesc().getPartNum();
for (long i = offset; i < endOffset; ++i) {
if (i > offset) {
sb.append(", ");
}
Long firstPartId = i / subPartNum;
Long subPartId = i % subPartNum;
sb.append(ObPartIdCalculator.generatePartId(firstPartId, subPartId));
}
} else {
for (int i = offset; i < endOffset; i++) {
if (i > offset) {
sb.append(", ");
}
sb.append(i);
}
}
sql = MessageFormat.format(PROXY_LOCATION_SQL_PARTITION, sb.toString());
}
return sql;
}
/*
* Get table entry location from remote.
*/
public static TableEntry getTableEntryLocationFromRemote(Connection connection,
TableEntryKey key,
TableEntry tableEntry)
throws ObTablePartitionLocationRefreshException {
PreparedStatement ps = null;
ResultSet rs = null;
ObPartitionEntry partitionEntry = new ObPartitionEntry();
long partitionNum = tableEntry.getPartitionNum();
int epoch = (int) ((partitionNum / MAX_TABLET_NUMS_EPOCH) + 1);
for (int i = 0; i < epoch; i++) {
try {
int offset = i * MAX_TABLET_NUMS_EPOCH;
String sql = genLocationSQLByOffset(tableEntry, offset, MAX_TABLET_NUMS_EPOCH);
ps = connection.prepareStatement(sql);
ps.setString(1, key.getTenantName());
ps.setString(2, key.getDatabaseName());
ps.setString(3, key.getTableName());
rs = ps.executeQuery();
partitionEntry = getPartitionLocationFromResultSet(tableEntry, rs, partitionEntry);
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00010"), key, partitionNum, tableEntry, e);
throw new ObTablePartitionLocationRefreshException(format(
"fail to get partition location entry from remote entryKey = %s partNum = %d tableEntry =%s "
+ "offset =%d epoch =%d", key, partitionNum, tableEntry, i, epoch), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
} // end for
tableEntry.setPartitionEntry(partitionEntry);
tableEntry.setRefreshTimeMills(System.currentTimeMillis());
return tableEntry;
}
public static Long getTableIdFromRemote(ObServerAddr obServerAddr, ObUserAuth sysUA,
long connectTimeout, long socketTimeout,
String tenantName, String databaseName, String tableName)
throws ObTableEntryRefreshException {
Long tableId = null;
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String url = formatObServerUrl(obServerAddr, connectTimeout, socketTimeout);
connection = getMetaRefreshConnection(url, sysUA);
ps = connection.prepareStatement(PROXY_TABLE_ID_SQL);
ps.setString(1, tenantName);
ps.setString(2, databaseName);
ps.setString(3, tableName);
rs = ps.executeQuery();
if (rs.next()) {
tableId = rs.getLong("table_id");
} else {
throw new ObTableEntryRefreshException("fail to get " + tableName
+ " table_id from remote");
}
} catch (Exception e) {
throw new ObTableEntryRefreshException("fail to get " + tableName
+ " table_id from remote", e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
return tableId;
}
public static ObIndexInfo getIndexInfoFromRemote(ObServerAddr obServerAddr, ObUserAuth sysUA,
long connectTimeout, long socketTimeout,
String indexTableName)
throws ObTableEntryRefreshException {
ObIndexInfo indexInfo = null;
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String url = formatObServerUrl(obServerAddr, connectTimeout, socketTimeout);
connection = getMetaRefreshConnection(url, sysUA);
ps = connection.prepareStatement(PROXY_INDEX_INFO_SQL);
ps.setString(1, indexTableName);
rs = ps.executeQuery();
if (rs.next()) {
indexInfo = new ObIndexInfo();
indexInfo.setDataTableId(rs.getLong("data_table_id"));
indexInfo.setIndexTableId(rs.getLong("table_id"));
indexInfo.setIndexType(ObIndexType.valueOf(rs.getInt("index_type")));
} else {
throw new ObTableEntryRefreshException(
"fail to get index info from remote, result set is empty");
}
} catch (Exception e) {
throw new ObTableEntryRefreshException(format(
"fail to get index info from remote, indexTableName: %s", indexTableName), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
return indexInfo;
}
private static void fetchFirstPart(Connection connection, TableEntry tableEntry,
ObPartFuncType obPartFuncType)
throws ObTablePartitionInfoRefreshException {
String tableName = "";
TableEntryKey key = tableEntry.getTableEntryKey();
if (key != null) {
tableName = key.getDatabaseName() + "." + key.getTableName();
}
String uuid = UUID.randomUUID().toString();
PreparedStatement ps = null;
ResultSet rs = null;
try {
if (ObGlobal.obVsnMajor() >= 4) {
ps = connection.prepareStatement(PROXY_FIRST_PARTITION_SQL_V4);
ps.setString(1, key.getTenantName());
ps.setLong(2, tableEntry.getTableId());
ps.setInt(3, Integer.MAX_VALUE);
} else {
ps = connection.prepareStatement(PROXY_FIRST_PARTITION_SQL);
ps.setLong(1, tableEntry.getTableId());
ps.setInt(2, Integer.MAX_VALUE);
}
rs = ps.executeQuery();
if (obPartFuncType.isRangePart()) {
List> highBoundVals = new ArrayList<>();
List> bounds = parseFirstPartRange(rs,
tableEntry, highBoundVals);
((ObRangePartDesc) tableEntry.getPartitionInfo().getFirstPartDesc())
.setBounds(bounds);
((ObRangePartDesc) tableEntry.getPartitionInfo().getFirstPartDesc())
.setHighBoundValues(highBoundVals);
if (logger.isInfoEnabled()) {
logger.info(format("uuid:%s, get first ranges from remote for %s, bounds=%s",
uuid, tableName, JSON.toJSON(bounds)));
}
} else if (obPartFuncType.isListPart()) {
Map sets = parseFirstPartSets(rs, tableEntry);
((ObListPartDesc) tableEntry.getPartitionInfo().getFirstPartDesc()).setSets(sets);
if (logger.isInfoEnabled()) {
logger.info(format("uuid:%s, get first list sets from remote for %s, sets=%s",
uuid, tableName, JSON.toJSON(sets)));
}
} else if (ObGlobal.obVsnMajor() >= 4
&& (obPartFuncType.isKeyPart() || obPartFuncType.isHashPart())) {
tableEntry.getPartitionInfo().setPartTabletIdMap(
parseFirstPartKeyHash(rs, tableEntry));
}
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00011"), tableEntry, obPartFuncType, e);
throw new ObTablePartitionInfoRefreshException(format(
"fail to get first part from remote for %s, tableEntry=%s partFuncType=%s",
tableName, tableEntry, obPartFuncType), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
// ignore
}
}
}
private static void fetchSubPart(Connection connection, TableEntry tableEntry,
ObPartFuncType subPartFuncType)
throws ObTablePartitionInfoRefreshException {
String tableName = "";
TableEntryKey key = tableEntry.getTableEntryKey();
if (key != null) {
tableName = key.getDatabaseName() + "." + key.getTableName();
}
String uuid = UUID.randomUUID().toString();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
if (ObGlobal.obVsnMajor() >= 4) {
pstmt = connection.prepareStatement(PROXY_SUB_PARTITION_SQL_V4);
pstmt.setString(1, key.getTenantName());
pstmt.setLong(2, tableEntry.getTableId());
pstmt.setInt(3, Integer.MAX_VALUE);
} else {
pstmt = connection.prepareStatement(PROXY_SUB_PARTITION_SQL);
pstmt.setLong(1, tableEntry.getTableId());
pstmt.setInt(2, Integer.MAX_VALUE);
}
rs = pstmt.executeQuery();
if (subPartFuncType.isRangePart()) {
List> highBoundVals = new ArrayList<>();
List> bounds = parseSubPartRange(rs,
tableEntry, highBoundVals);
((ObRangePartDesc) tableEntry.getPartitionInfo().getSubPartDesc())
.setBounds(bounds);
((ObRangePartDesc) tableEntry.getPartitionInfo().getSubPartDesc())
.setHighBoundValues(highBoundVals);
if (logger.isInfoEnabled()) {
logger.info(format("uuid:%s, get sub ranges from remote for %s, bounds=%s",
uuid, tableName, JSON.toJSON(bounds)));
}
} else if (subPartFuncType.isListPart()) {
Map sets = parseSubPartSets(rs, tableEntry);
((ObListPartDesc) tableEntry.getPartitionInfo().getSubPartDesc()).setSets(sets);
if (logger.isInfoEnabled()) {
logger.info(format("uuid:%s, get sub list sets from remote, sets=%s", uuid,
JSON.toJSON(sets)));
}
} else if (ObGlobal.obVsnMajor() >= 4
&& (subPartFuncType.isKeyPart() || subPartFuncType.isHashPart())) {
tableEntry.getPartitionInfo().setPartTabletIdMap(
parseSubPartKeyHash(rs, tableEntry));
}
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00012"), tableEntry, subPartFuncType, e);
throw new ObTablePartitionInfoRefreshException(format(
"fail to get sub part from remote, tableEntry=%s partFuncType=%s", tableEntry,
subPartFuncType), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != pstmt) {
pstmt.close();
}
} catch (SQLException e) {
// ignore
}
}
}
private static TableEntry getTableEntryFromResultSet(TableEntryKey key, ResultSet rs)
throws SQLException,
ObTableEntryRefreshException {
TableEntry entry = new TableEntry();
Long replicaNum = null;
Long partitionNum = null;
Long tableId = null;
List replicaLocations = new ArrayList(3);
while (rs.next()) {
ReplicaLocation replica = buildReplicaLocation(rs);
tableId = rs.getLong("table_id");
replicaNum = rs.getLong("replica_num");
partitionNum = rs.getLong("part_num");
if (!replica.isValid()) {
logger
.warn(format("replica is invalid, continue, replica=%s, key=%s", replica, key));
} else if (replicaLocations.contains(replica)) {
logger.warn(format(
"replica is repeated, continue, replica=%s, key=%s, replicas=%s", replica, key,
replicaLocations));
} else {
replicaLocations.add(replica);
}
}
TableLocation tableLocation = new TableLocation();
tableLocation.setReplicaLocations(replicaLocations);
if (!replicaLocations.isEmpty()) {
entry.setTableId(tableId);
entry.setTableLocation(tableLocation);
entry.setPartitionNum(partitionNum);
entry.setReplicaNum(replicaNum);
} else {
RUNTIME.error("table not exist");
throw new ObTableNotExistException("table not exist: " + key.getTableName(),
ResultCodes.OB_ERR_UNKNOWN_TABLE.errorCode);
}
return entry;
}
private static ObPartitionEntry getPartitionLocationFromResultSet(TableEntry tableEntry,
ResultSet rs,
ObPartitionEntry partitionEntry)
throws SQLException,
ObTablePartitionLocationRefreshException {
if (partitionEntry == null || tableEntry == null) {
throw new IllegalArgumentException("partitionEntry: " + partitionEntry
+ " tableEntry: " + tableEntry);
}
Map partitionLocation = partitionEntry.getPartitionLocation();
Map tabletLsIdMap = partitionEntry.getTabletLsIdMap();
while (rs.next()) {
ReplicaLocation replica = buildReplicaLocation(rs);
long partitionId;
if (ObGlobal.obVsnMajor() >= 4) {
partitionId = rs.getLong("tablet_id");
long lsId = rs.getLong("ls_id");
if (!rs.wasNull()) {
tabletLsIdMap.put(partitionId, lsId);
} else {
tabletLsIdMap.put(partitionId, INVALID_LS_ID); // non-partitioned table
}
} else {
partitionId = rs.getLong("partition_id");
if (tableEntry.isPartitionTable()
&& null != tableEntry.getPartitionInfo().getSubPartDesc()) {
partitionId = ObPartIdCalculator.getPartIdx(partitionId, tableEntry
.getPartitionInfo().getSubPartDesc().getPartNum());
}
}
if (!replica.isValid()) {
RUNTIME
.warn(format(
"replica is invalid, continue, replica=%s, partitionId/tabletId=%d, tableId=%d",
replica, partitionId, tableEntry.getTableId()));
continue;
}
ObPartitionLocation location = partitionLocation.get(partitionId);
if (location == null) {
location = new ObPartitionLocation();
partitionLocation.put(partitionId, location);
}
location.addReplicaLocation(replica);
}
if (ObGlobal.obVsnMajor() < 4) {
for (long i = 0; i < tableEntry.getPartitionNum(); i++) {
ObPartitionLocation location = partitionEntry.getPartitionLocationWithPartId(i);
if (location == null) {
RUNTIME.error(LCD.convert("01-00013"), i, partitionEntry, tableEntry);
RUNTIME.error(format(
"partition num=%d is not exist partitionEntry=%s original tableEntry=%s",
i, partitionEntry, tableEntry));
throw new ObTablePartitionNotExistException(format(
"partition num=%d is not exist partitionEntry=%s original tableEntry=%s",
i, partitionEntry, tableEntry));
}
if (location.getLeader() == null) {
RUNTIME.error(LCD.convert("01-00028"), i, partitionEntry, tableEntry);
RUNTIME.error(format(
"partition num=%d has no leader partitionEntry=%s original tableEntry=%s",
i, partitionEntry, tableEntry));
throw new ObTablePartitionNoMasterException(format(
"partition num=%d has no leader partitionEntry=%s original tableEntry=%s",
i, partitionEntry, tableEntry));
}
}
}
return partitionEntry;
}
/*
* Get ReplicaLocation from the result row.
*
* @param rs
* @return
* @throws SQLException
*/
private static ReplicaLocation buildReplicaLocation(ResultSet rs) throws SQLException {
String ip = rs.getString("svr_ip");
int port = rs.getInt("sql_port");
int svrPort = rs.getInt("svr_port");
ObServerRole role = ObServerRole.getRole(rs.getInt("role"));
String status = rs.getString("status");
long stopTime = rs.getLong("stop_time");
ObReplicaType replicaType = ObReplicaType.getReplicaType(rs.getInt("replica_type"));
ReplicaLocation replica = new ReplicaLocation();
ObServerAddr obServerAddr = new ObServerAddr();
obServerAddr.setAddress(ip);
obServerAddr.setSqlPort(port);
obServerAddr.setSvrPort(svrPort);
ObServerInfo obServerInfo = new ObServerInfo();
obServerInfo.setStatus(status);
obServerInfo.setStopTime(stopTime);
replica.setAddr(obServerAddr);
replica.setInfo(obServerInfo);
replica.setRole(role);
replica.setReplicaType(replicaType);
return replica;
}
private static void fetchPartitionInfo(Connection connection, TableEntry tableEntry)
throws ObTablePartitionInfoRefreshException {
PreparedStatement pstmt = null;
ResultSet rs = null;
ObPartitionInfo info = null;
try {
if (ObGlobal.obVsnMajor() >= 4) {
pstmt = connection.prepareStatement(PROXY_PART_INFO_SQL_V4);
pstmt.setString(1, tableEntry.getTableEntryKey().getTenantName());
pstmt.setLong(2, tableEntry.getTableId());
pstmt.setLong(3, Long.MAX_VALUE);
} else {
pstmt = connection.prepareStatement(PROXY_PART_INFO_SQL);
pstmt.setLong(1, tableEntry.getTableId());
pstmt.setLong(2, Long.MAX_VALUE);
}
rs = pstmt.executeQuery();
info = parsePartitionInfo(rs);
if (logger.isInfoEnabled()) {
logger.info("get part info from remote info:{}", JSON.toJSON(info));
}
tableEntry.setPartitionInfo(info);
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00014"), tableEntry);
RUNTIME.error("fail to get part info from remote");
throw new ObTablePartitionInfoRefreshException(format(
"fail to get part info from remote, tableEntry=%s", tableEntry), e);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != pstmt) {
pstmt.close();
}
} catch (SQLException e) {
// ignore
}
}
}
private static ObPartitionInfo parsePartitionInfo(ResultSet rs)
throws IllegalArgumentException,
GenerateColumnParseException,
SQLException {
ObPartitionInfo info = new ObPartitionInfo();
boolean isFirstRow = true;
while (rs.next()) {
// get part info for the first loop
if (isFirstRow) {
isFirstRow = false;
// get part level
info.setLevel(ObPartitionLevel.valueOf(rs.getLong("part_level")));
// get first part
if (info.getLevel().getIndex() >= ObPartitionLevel.LEVEL_ONE.getIndex()) {
ObPartDesc partDesc = buildPartDesc(ObPartitionLevel.LEVEL_ONE, rs);
if (partDesc == null) {
logger.warn("fail to build first part");
} else {
info.setFirstPartDesc(partDesc);
}
}
// get sub part
if (info.getLevel().getIndex() == ObPartitionLevel.LEVEL_TWO.getIndex()) {
ObPartDesc partDesc = buildPartDesc(ObPartitionLevel.LEVEL_TWO, rs);
if (partDesc == null) {
logger.warn("fail to build sub part");
} else {
info.setSubPartDesc(partDesc);
}
}
}
// get part key for each loop
String partKeyExtra = rs.getString("part_key_extra");
partKeyExtra = partKeyExtra.replace("`", ""); // '`' is not supported by druid
partKeyExtra = partKeyExtra.replace(" ", ""); // ' ' should be removed
ObColumn column;
String collationTypeLabel = null;
if (ObGlobal.obVsnMajor() >= 4) {
collationTypeLabel = "part_key_collation_type";
} else {
collationTypeLabel = "spare1";
}
if (!partKeyExtra.isEmpty()) {
column = new ObGeneratedColumn(
rs.getString("part_key_name"),//
rs.getInt("part_key_idx"),//
ObObjType.valueOf(rs.getInt("part_key_type")),//
ObCollationType.valueOf(rs.getInt(collationTypeLabel)),
new ObGeneratedColumnExpressParser(getPlainString(partKeyExtra)).parse());
} else {
column = new ObSimpleColumn(rs.getString("part_key_name"),//
rs.getInt("part_key_idx"),//
ObObjType.valueOf(rs.getInt("part_key_type")),//
ObCollationType.valueOf(rs.getInt(collationTypeLabel)));
}
info.addColumn(column);
}
// get list partition column types here
List orderedPartedColumns1 = null;
if (null != info.getFirstPartDesc()) {
if (info.getFirstPartDesc().getPartFuncType().isListPart()
|| info.getFirstPartDesc().getPartFuncType().isRangePart()) {
orderedPartedColumns1 = getOrderedPartColumns(info.getPartColumns(),
info.getFirstPartDesc());
}
}
List orderedPartedColumns2 = null;
if (null != info.getSubPartDesc()) {
if (info.getSubPartDesc().getPartFuncType().isListPart()
|| info.getSubPartDesc().getPartFuncType().isRangePart()) {
orderedPartedColumns2 = getOrderedPartColumns(info.getPartColumns(),
info.getSubPartDesc());
}
}
// set the property of first part and sub part
List firstPartColumns = new ArrayList(), subPartColumns = new ArrayList();
if (null != info.getFirstPartDesc()) {
for (String partColumnNames : info.getFirstPartDesc().getOrderedPartColumnNames()) {
for (ObColumn curColumn : info.getPartColumns()) {
if (curColumn.getColumnName().equalsIgnoreCase(partColumnNames)) {
firstPartColumns.add(curColumn);
break;
}
}
}
}
if (null != info.getSubPartDesc()) {
for (String partColumnNames : info.getSubPartDesc().getOrderedPartColumnNames()) {
for (ObColumn curColumn : info.getPartColumns()) {
if (curColumn.getColumnName().equalsIgnoreCase(partColumnNames)) {
subPartColumns.add(curColumn);
break;
}
}
}
}
setPartDescProperty(info.getFirstPartDesc(), firstPartColumns, orderedPartedColumns1);
setPartDescProperty(info.getSubPartDesc(), subPartColumns, orderedPartedColumns2);
return info;
}
private static ObPartDesc buildPartDesc(ObPartitionLevel level, ResultSet rs)
throws SQLException {
ObPartDesc partDesc = null;
String partLevelPrefix = (level == ObPartitionLevel.LEVEL_TWO ? "sub_" : "");
ObPartFuncType partType = ObPartFuncType.getObPartFuncType(rs.getLong(partLevelPrefix
+ "part_type"));
String partExpr = rs.getString(partLevelPrefix + "part_expr");
partExpr = partExpr.replace("`", ""); // '`' is not supported by druid
if (partType.isRangePart()) {
ObRangePartDesc rangeDesc = new ObRangePartDesc();
rangeDesc.setPartFuncType(partType);
rangeDesc.setPartExpr(partExpr);
rangeDesc.setPartNum(rs.getInt(partLevelPrefix + "part_num"));
rangeDesc.setPartSpace(rs.getInt(partLevelPrefix + "part_space"));
ArrayList types = new ArrayList(1);
String objTypesStr = rs.getString(partLevelPrefix + "part_range_type");
for (String typeStr : objTypesStr.split(",")) {
types.add(ObObjType.valueOf(Integer.valueOf(typeStr)));
}
rangeDesc.setOrderedCompareColumnTypes(types);
partDesc = rangeDesc;
} else if (partType.isHashPart()) {
ObHashPartDesc hashDesc = new ObHashPartDesc();
hashDesc.setPartExpr(partExpr);
hashDesc.setPartFuncType(partType);
hashDesc.setPartNum(rs.getInt(partLevelPrefix + "part_num"));
hashDesc.setPartSpace(rs.getInt(partLevelPrefix + "part_space"));
if (ObGlobal.obVsnMajor() < 4) {
Map partNameIdMap = buildDefaultPartNameIdMap(hashDesc.getPartNum());
hashDesc.setPartNameIdMap(partNameIdMap);
}
partDesc = hashDesc;
} else if (partType.isKeyPart()) {
ObKeyPartDesc keyPartDesc = new ObKeyPartDesc();
keyPartDesc.setPartFuncType(partType);
keyPartDesc.setPartExpr(partExpr);
keyPartDesc.setPartNum(rs.getInt(partLevelPrefix + "part_num"));
keyPartDesc.setPartSpace(rs.getInt(partLevelPrefix + "part_space"));
if (ObGlobal.obVsnMajor() < 4) {
Map partNameIdMap = buildDefaultPartNameIdMap(keyPartDesc
.getPartNum());
keyPartDesc.setPartNameIdMap(partNameIdMap);
}
partDesc = keyPartDesc;
} else {
RUNTIME.error(LCD.convert("01-00015"), partType);
throw new IllegalArgumentException(format("not supported part type, type = %s",
partType));
}
return partDesc;
}
private static List getOrderedPartColumns(List partitionKeyColumns,
ObPartDesc partDesc) {
List columns = new ArrayList();
for (String partColName : partDesc.getOrderedPartColumnNames()) {
for (ObColumn keyColumn : partitionKeyColumns) {
if (partColName.equalsIgnoreCase(keyColumn.getColumnName())) {
columns.add(keyColumn);
}
}
}
return columns;
}
private static void setPartDescProperty(ObPartDesc partDesc, List partColumns,
List listPartColumns)
throws ObTablePartitionInfoRefreshException {
ObPartFuncType obPartFuncType = null;
if (null != partDesc) {
partDesc.setPartColumns(partColumns);
obPartFuncType = partDesc.getPartFuncType();
if (obPartFuncType.isKeyPart()) {
if (partColumns == null || partColumns.size() == 0) {
RUNTIME.error("key part desc need part ref columns but found " + partColumns);
throw new ObTablePartitionInfoRefreshException(
"key part desc need part ref columns but found " + partColumns);
}
} else if (obPartFuncType.isListPart()) {
((ObListPartDesc) partDesc).setOrderCompareColumns(listPartColumns);
} else if (obPartFuncType.isRangePart()) {
((ObRangePartDesc) partDesc).setOrderedCompareColumns(listPartColumns);
}
}
}
public static Map buildDefaultPartNameIdMap(int partNum) {
// the default partition name is 'p0,p1...'
Map partNameIdMap = new HashMap();
for (int i = 0; i < partNum; i++) {
partNameIdMap.put("p" + i, (long) i);
}
return partNameIdMap;
}
private static Map buildPartNameIdMap(ObPartitionInfo partitionInfo) {
Map partNameIdMap1 = partitionInfo.getFirstPartDesc().getPartNameIdMap();
Map partNameIdMap2 = Collections.EMPTY_MAP;
Map partNameIdMap = new HashMap();
for (String partName1 : partNameIdMap1.keySet()) {
Long partId1 = partNameIdMap1.get(partName1);
if (null != partitionInfo.getSubPartDesc()) {
partNameIdMap2 = partitionInfo.getSubPartDesc().getPartNameIdMap();
for (String partName2 : partNameIdMap2.keySet()) {
String comPartName = partName1 + "s" + partName2;
Long partId2 = partNameIdMap2.get(partName2);
Long partId = ObPartIdCalculator.generatePartId(partId1, partId2);
partNameIdMap.put(comPartName, partId);
}
} else {
partNameIdMap.put(partName1, partId1);
}
}
return partNameIdMap;
}
private static Map parseFirstPartKeyHash(ResultSet rs, TableEntry tableEntry)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
return parseKeyHashPart(rs, tableEntry, false);
}
private static List> parseFirstPartRange(ResultSet rs,
TableEntry tableEntry,
List> highBoundVals)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
return parseRangePart(rs, tableEntry, highBoundVals, false);
}
private static Map parseFirstPartSets(ResultSet rs, TableEntry tableEntry)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
return parseListPartSets(rs, tableEntry, false);
}
private static List> parseSubPartRange(ResultSet rs,
TableEntry tableEntry,
List> highBoundVals)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
return parseRangePart(rs, tableEntry, highBoundVals, true);
}
private static Map parseSubPartSets(ResultSet rs, TableEntry tableEntry)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
return parseListPartSets(rs, tableEntry, true);
}
private static Map parseSubPartKeyHash(ResultSet rs, TableEntry tableEntry)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
return parseKeyHashPart(rs, tableEntry, true);
}
private static Map parseKeyHashPart(ResultSet rs, TableEntry tableEntry,
boolean isSubPart) throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
long idx = 0L;
Map partTabletIdMap = new HashMap();
while (rs.next()) {
ObPartDesc subPartDesc = tableEntry.getPartitionInfo().getSubPartDesc();
if (null != subPartDesc) {
// client only support template partition table
// so the sub_part_num is a constant and will store in subPartDesc which is different from proxy
if (subPartDesc instanceof ObKeyPartDesc) {
ObKeyPartDesc subKeyPartDesc = (ObKeyPartDesc) subPartDesc;
if (!isSubPart && subKeyPartDesc.getPartNum() == 0) {
long subPartNum = rs.getLong("sub_part_num");
subKeyPartDesc.setPartNum((int) subPartNum);
}
} else if (subPartDesc instanceof ObHashPartDesc) {
ObHashPartDesc subHashPartDesc = (ObHashPartDesc) subPartDesc;
if (!isSubPart && subHashPartDesc.getPartNum() == 0) {
long subPartNum = rs.getLong("sub_part_num");
subHashPartDesc.setPartNum((int) subPartNum);
}
} else {
throw new IllegalArgumentException("sub part desc is not key or hash part desc");
}
}
Long tabletId = rs.getLong("tablet_id");
partTabletIdMap.put(idx++, tabletId);
}
return partTabletIdMap;
}
private static List> parseRangePart(ResultSet rs,
TableEntry tableEntry,
List> highBoundVals,
boolean isSubPart)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
String partIdColumnName = "part_id";
ObPartDesc partDesc = tableEntry.getPartitionInfo().getFirstPartDesc();
if (isSubPart) {
partIdColumnName = "sub_part_id";
partDesc = tableEntry.getPartitionInfo().getSubPartDesc();
}
List orderPartColumns = ((ObRangePartDesc) partDesc).getOrderedCompareColumns();
List> bounds = new ArrayList>();
Map partNameIdMap = new HashMap();
Map partTabletIdMap = new HashMap();
ObPartDesc subRangePartDesc = tableEntry.getPartitionInfo().getSubPartDesc();
long idx = 0L;
while (rs.next()) {
if (null != subRangePartDesc && !isSubPart && subRangePartDesc.getPartNum() == 0) {
// client only support template partition table
// so the sub_part_num is a constant and will store in subPartDesc which is different from proxy
long subPartNum = rs.getLong("sub_part_num");
subRangePartDesc.setPartNum((int) subPartNum);
}
String highBoundVal = rs.getString("high_bound_val");
String[] splits = highBoundVal.split(",");
List partElements = new ArrayList();
List singleHighBoundVal = new ArrayList();
for (int i = 0; i < splits.length; i++) {
String elementStr = getPlainString(splits[i]);
if (elementStr.equalsIgnoreCase("MAXVALUE")) {
singleHighBoundVal.add(new byte[0]); // like EMPTY_BYTE_ARRAY
partElements.add(MAX_PARTITION_ELEMENT);
} else if (elementStr.equalsIgnoreCase("MINVALUE")) {
singleHighBoundVal.add(new byte[0]); // like EMPTY_BYTE_ARRAY
partElements.add(MIN_PARTITION_ELEMENT);
} else {
ObObjType type = orderPartColumns.get(i).getObObjType();
partElements.add(type.parseToComparable(elementStr, orderPartColumns.get(i)
.getObCollationType()));
singleHighBoundVal.add(type.parseToBytes(elementStr, orderPartColumns.get(i)
.getObCollationType()));
}
}
ObPartitionKey partitionKey = new ObPartitionKey(orderPartColumns, partElements);
if (ObGlobal.obVsnMajor() >= 4) {
long tabletId = rs.getLong("tablet_id");
bounds.add(new ObComparableKV(partitionKey, idx));
highBoundVals.add(singleHighBoundVal);
partTabletIdMap.put(idx, tabletId);
idx++;
} else {
long partId = rs.getLong(partIdColumnName);
String partName = rs.getString("part_name");
bounds.add(new ObComparableKV(partitionKey, partId));
highBoundVals.add(singleHighBoundVal);
partNameIdMap.put(partName.toLowerCase(), partId);
}
}
if (ObGlobal.obVsnMajor() >= 4) {
//set single level partition tablet-id mapping
tableEntry.getPartitionInfo().setPartTabletIdMap(partTabletIdMap);
} else {
//set single level partition name-id mapping
partDesc.setPartNameIdMap(partNameIdMap);
}
Collections.sort(bounds);
return bounds;
}
private static String[] parseListPartSetsCommon(ResultSet rs, TableEntry tableEntry)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
// multi-columns: '(1,2),(1,3),(1,4),(default)'
// single-columns: '(1),(2),(3)' or '1,2,3'
String setsStr = rs.getString("high_bound_val");
setsStr = (null == setsStr) ? "" : setsStr.trim();
if (setsStr.length() < 2) {
RUNTIME.error(LCD.convert("01-00016"), setsStr, tableEntry.toString());
RUNTIME.error(format("high_bound_val value is error, high_bound_val=%s", setsStr));
// if partition value format is wrong, directly throw exception
throw new IllegalArgumentException(format(
"high_bound_val value is error, high_bound_val=%s, tableEntry=%s", setsStr,
tableEntry.toString()));
}
// skip the first character '(' and the last ')' if exist
if (setsStr.startsWith("(") && setsStr.endsWith(")")) {
setsStr = setsStr.substring(1, setsStr.length() - 1);
}
String[] setArray = null;
if (setsStr.contains("),(")) { // multi-column format
setArray = setsStr.split("\\),\\(");
} else { // single-column format
setArray = setsStr.split(",");
}
return setArray;
}
private static Map parseListPartSets(ResultSet rs, TableEntry tableEntry,
boolean isSubPart)
throws SQLException,
IllegalArgumentException,
FeatureNotSupportedException {
String partIdColumnName = "part_id";
// tableEntry.getPartInfo() will not be null
ObPartDesc partDesc = tableEntry.getPartitionInfo().getFirstPartDesc();
if (isSubPart) {
partIdColumnName = "sub_part_id";
partDesc = tableEntry.getPartitionInfo().getSubPartDesc();
}
List columns = ((ObListPartDesc) partDesc).getOrderCompareColumns();
Map sets = new HashMap();
if (ObGlobal.obVsnMajor() >= 4) {
Map partTabletIdMap = new HashMap();
long idx = 0L;
while (rs.next()) {
String[] setArray = parseListPartSetsCommon(rs, tableEntry);
ObPartitionKey key = null;
// setArray can not be null
for (String set : setArray) {
if ("default".equalsIgnoreCase(set)) {
key = ObPartDesc.DEFAULT_PART_KEY;
} else {
String[] splits = set.split(",");
List partElements = new ArrayList();
for (int i = 0; i < splits.length; i++) {
partElements.add(columns.get(i).getObObjType()
.parseToComparable(splits[i], columns.get(i).getObCollationType()));
}
key = new ObPartitionKey(columns, partElements);
}
sets.put(key, idx);
}
long tabletId = rs.getLong("tablet_id");
partTabletIdMap.put(idx++, tabletId);
}
//set single level partition tablet-id mapping
tableEntry.getPartitionInfo().setPartTabletIdMap(partTabletIdMap);
} else {
Map partNameIdMap = new HashMap();
while (rs.next()) {
String[] setArray = parseListPartSetsCommon(rs, tableEntry);
ObPartitionKey key = null;
Long partId = null;
String partName = null;
// setArray can not be null
for (String set : setArray) {
if ("default".equalsIgnoreCase(set)) {
key = ObPartDesc.DEFAULT_PART_KEY;
} else {
String[] splits = set.split(",");
List partElements = new ArrayList();
for (int i = 0; i < splits.length; i++) {
partElements.add(columns.get(i).getObObjType()
.parseToComparable(splits[i], columns.get(i).getObCollationType()));
}
key = new ObPartitionKey(columns, partElements);
}
partId = rs.getLong(partIdColumnName);
partName = rs.getString("part_name");
sets.put(key, partId);
partNameIdMap.put(partName.toLowerCase(), partId);
}
}
//set single level partition name-id mapping
partDesc.setPartNameIdMap(partNameIdMap);
}
return sets;
}
/*
* Load ocp model.
*/
public static OcpModel loadOcpModel(String paramURL, String dataSourceName, int connectTimeout,
int readTimeout, int retryTimes, long retryInternal)
throws Exception {
OcpModel ocpModel = new OcpModel();
List obServerAddrs = new ArrayList();
ocpModel.setObServerAddrs(obServerAddrs);
OcpResponse ocpResponse = getRemoteOcpResponseOrNull(paramURL, dataSourceName,
connectTimeout, readTimeout, retryTimes, retryInternal);
if (ocpResponse == null && (dataSourceName != null && !dataSourceName.isEmpty())) { // get config from local file
ocpResponse = getLocalOcpResponseOrNull(dataSourceName);
}
if (ocpResponse != null) {
OcpResponseData ocpResponseData = ocpResponse.getData();
ocpModel.setClusterId(ocpResponseData.getObRegionId());
for (OcpResponseDataRs responseRs : ocpResponseData.getRsList()) {
ObServerAddr obServerAddr = new ObServerAddr();
obServerAddr.setAddress(responseRs.getAddress());
obServerAddr.setSqlPort(responseRs.getSql_port());
obServerAddrs.add(obServerAddr);
}
}
if (obServerAddrs.isEmpty()) {
RUNTIME.error("load rs list failed dataSource: " + dataSourceName + " paramURL:"
+ paramURL + " response:" + ocpResponse);
throw new RuntimeException("load rs list failed dataSource: " + dataSourceName
+ " paramURL:" + paramURL + " response:" + ocpResponse);
}
// Get IDC -> Region map if any.
String obIdcRegionURL = paramURL.replace(Constants.OCP_ROOT_SERVICE_ACTION,
Constants.OCP_IDC_REGION_ACTION);
ocpResponse = getRemoteOcpIdcRegionOrNull(obIdcRegionURL, connectTimeout, readTimeout,
retryTimes, retryInternal);
if (ocpResponse != null) {
OcpResponseData ocpResponseData = ocpResponse.getData();
if (ocpResponseData != null && ocpResponseData.getIDCList() != null) {
for (OcpResponseDataIDC idcRegion : ocpResponseData.getIDCList()) {
ocpModel.addIdc2Region(idcRegion.getIdc(), idcRegion.getRegion());
}
}
}
return ocpModel;
}
private static OcpResponse getRemoteOcpResponseOrNull(String paramURL, String dataSourceName,
int connectTimeout, int readTimeout,
int tryTimes, long retryInternal)
throws InterruptedException {
OcpResponse ocpResponse = null;
String content = null;
int tries = 0;
Exception cause = null;
for (; tries < tryTimes; tries++) {
try {
content = loadStringFromUrl(paramURL, connectTimeout, readTimeout);
ocpResponse = JSONObject.parseObject(content, OcpResponse.class);
if (ocpResponse != null && ocpResponse.validate()) {
if (dataSourceName != null && !dataSourceName.isEmpty()) {
saveLocalContent(dataSourceName, content);
}
return ocpResponse;
}
} catch (Exception e) {
cause = e;
RUNTIME.error(LCD.convert("01-00017"), e);
Thread.sleep(retryInternal);
}
}
if (tries >= tryTimes) {
RUNTIME
.error("Fail to get OCP response after " + tryTimes + " tries from [" + paramURL);
throw new ObTableRetryExhaustedException("Fail to get OCP response after " + tryTimes
+ " tries from [" + paramURL
+ "], the content is [" + content + "]", cause);
}
return null;
}
/*
* Get IdcRegion info from OCP.
* Return null instead of throwing exception if get nothing, because the info is optional.
*
* @param paramURL
* @param connectTimeout
* @param readTimeout
* @param tryTimes
* @param retryInternal
* @return
* @throws InterruptedException
*/
private static OcpResponse getRemoteOcpIdcRegionOrNull(String paramURL, int connectTimeout,
int readTimeout, int tryTimes,
long retryInternal)
throws InterruptedException {
OcpResponse ocpResponse = null;
String content = null;
int tries = 0;
for (; tries < tryTimes; tries++) {
try {
content = loadStringFromUrl(paramURL, connectTimeout, readTimeout);
ocpResponse = JSONObject.parseObject(content, OcpResponse.class);
if (ocpResponse != null) {
return ocpResponse;
}
} catch (Exception e) {
RUNTIME.error(LCD.convert("01-00017"), e);
Thread.sleep(retryInternal);
}
}
if (tries >= tryTimes) {
RUNTIME.error(LCD.convert("01-00017"), "OCP IdcRegion after" + tryTimes
+ " tries from [" + paramURL
+ "], the content is [" + content + "]");
}
return null;
}
private static OcpResponse parseOcpResponse(String content) throws JSONException {
return JSONObject.parseObject(content, OcpResponse.class);
}
private static OcpResponse getLocalOcpResponseOrNull(String fileName) {
File file = new File(format("%s/conf/obtable//%s", home, fileName));
try {
BufferedInputStream inputStream = null;
try {
InputStream fileInputStream;
if (file.exists()) {
fileInputStream = new FileInputStream(file);
} else {
return null;
}
inputStream = new BufferedInputStream(fileInputStream);
byte[] bytes = new byte[inputStream.available()];
int read = inputStream.read(bytes);
if (read != bytes.length) {
throw new IOException("File bytes invalid: " + fileName);
}
String content = new String(bytes);
return parseOcpResponse(content);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
} catch (IOException e) {
RUNTIME.warn("load obtable file meet exception: " + file.getAbsolutePath(), e);
return null;
}
}
private static void saveLocalContent(String fileName, String content) {
File file = new File(format("%s/conf/obtable/%s", home, fileName));
// Format content
try {
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
BufferedOutputStream outputStream = null;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(file));
outputStream.write(content.getBytes());
} finally {
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
// 写配置失败需要删除文件,避免写入脏数据
file.delete();
RUNTIME.warn("Save obtable file meet exception: " + file.getAbsolutePath(), e);
}
}
private static String loadStringFromUrl(String url, int connectTimeout, int readTimeout)
throws Exception {
HttpURLConnection con = null;
String content;
try {
URL obj = new URL(url);
con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
con.setConnectTimeout(connectTimeout);
con.setReadTimeout(readTimeout);
con.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
content = response.toString();
} finally {
if (con != null) {
con.disconnect();
}
}
return content;
}
// trim single '
private static String getPlainString(String str) {
int start = str.length() > 0 && str.charAt(0) == '\'' ? 1 : 0;
int end = str.length() > 0 && str.charAt(str.length() - 1) == '\'' ? str.length() - 1 : str
.length();
return str.substring(start, end);
}
private static void parseObVersionFromSQL(String serverVersion) {
// serverVersion is like "4.2.1.0"
Pattern pattern = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)");
Matcher matcher = pattern.matcher(serverVersion);
if (matcher.find() && ObGlobal.OB_VERSION == 0) {
ObGlobal.OB_VERSION = ObGlobal.calcVersion(Integer.parseInt(matcher.group(1)),
(short) Integer.parseInt(matcher.group(2)),
(byte) Integer.parseInt(matcher.group(3)),
(byte) Integer.parseInt(matcher.group(4)));
}
}
public static void parseObVerionFromLogin(String serverVersion) {
Pattern pattern;
if (serverVersion.startsWith("OceanBase_CE")) {
// serverVersion in CE is like "OceanBase_CE 4.0.0.0"
pattern = Pattern.compile("OceanBase_CE\\s+(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)");
} else {
// serverVersion is like "OceanBase 4.0.0.0"
pattern = Pattern.compile("OceanBase\\s+(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)");
}
Matcher matcher = pattern.matcher(serverVersion);
if (matcher.find() && ObGlobal.OB_VERSION == 0) {
ObGlobal.OB_VERSION = ObGlobal.calcVersion(Integer.parseInt(matcher.group(1)),
(short) Integer.parseInt(matcher.group(2)),
(byte) Integer.parseInt(matcher.group(3)),
(byte) Integer.parseInt(matcher.group(4)));
}
}
}