| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.tajo.client; |
| |
| import com.google.protobuf.ServiceException; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.hadoop.security.UserGroupInformation; |
| import org.apache.tajo.QueryId; |
| import org.apache.tajo.QueryIdFactory; |
| import org.apache.tajo.TajoIdProtos; |
| import org.apache.tajo.TajoProtos.QueryState; |
| import org.apache.tajo.annotation.Nullable; |
| import org.apache.tajo.annotation.ThreadSafe; |
| import org.apache.tajo.catalog.*; |
| import org.apache.tajo.catalog.proto.CatalogProtos; |
| import org.apache.tajo.cli.InvalidClientSessionException; |
| import org.apache.tajo.conf.TajoConf; |
| import org.apache.tajo.conf.TajoConf.ConfVars; |
| import org.apache.tajo.ipc.ClientProtos.*; |
| import org.apache.tajo.ipc.QueryMasterClientProtocol; |
| import org.apache.tajo.ipc.QueryMasterClientProtocol.QueryMasterClientProtocolService; |
| import org.apache.tajo.ipc.TajoMasterClientProtocol; |
| import org.apache.tajo.ipc.TajoMasterClientProtocol.TajoMasterClientProtocolService; |
| import org.apache.tajo.jdbc.SQLStates; |
| import org.apache.tajo.jdbc.TajoMemoryResultSet; |
| import org.apache.tajo.jdbc.TajoResultSet; |
| import org.apache.tajo.rpc.NettyClientBase; |
| import org.apache.tajo.rpc.RpcConnectionPool; |
| import org.apache.tajo.rpc.ServerCallable; |
| import org.apache.tajo.util.KeyValueSet; |
| import org.apache.tajo.util.NetUtils; |
| |
| import java.io.Closeable; |
| import java.io.IOException; |
| import java.net.InetSocketAddress; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| import static org.apache.tajo.ipc.ClientProtos.SubmitQueryResponse.SerializedResultSet; |
| |
| @ThreadSafe |
| public class TajoClient implements Closeable { |
| private final Log LOG = LogFactory.getLog(TajoClient.class); |
| |
| private final TajoConf conf; |
| |
| private final Map<QueryId, InetSocketAddress> queryMasterMap = new ConcurrentHashMap<QueryId, InetSocketAddress>(); |
| |
| private final InetSocketAddress tajoMasterAddr; |
| |
| private final RpcConnectionPool connPool; |
| |
| private final String baseDatabase; |
| |
| private final UserGroupInformation userInfo; |
| |
| private volatile TajoIdProtos.SessionIdProto sessionId; |
| |
| public TajoClient(TajoConf conf) throws IOException { |
| this(conf, NetUtils.createSocketAddr(conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS)), null); |
| } |
| |
| public TajoClient(TajoConf conf, @Nullable String baseDatabase) throws IOException { |
| this(conf, NetUtils.createSocketAddr(conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS)), baseDatabase); |
| } |
| |
| /** |
| * Connect to TajoMaster |
| * |
| * @param conf TajoConf |
| * @param addr TajoMaster address |
| * @param baseDatabase The base database name. It is case sensitive. If it is null, |
| * the 'default' database will be used. |
| * @throws IOException |
| */ |
| public TajoClient(TajoConf conf, InetSocketAddress addr, @Nullable String baseDatabase) throws IOException { |
| this.conf = conf; |
| this.conf.set("tajo.disk.scheduler.report.interval", "0"); |
| this.tajoMasterAddr = addr; |
| int workerNum = conf.getIntVar(TajoConf.ConfVars.RPC_CLIENT_WORKER_THREAD_NUM); |
| // Don't share connection pool per client |
| connPool = RpcConnectionPool.newPool(conf, getClass().getSimpleName(), workerNum); |
| userInfo = UserGroupInformation.getCurrentUser(); |
| this.baseDatabase = baseDatabase != null ? baseDatabase : null; |
| } |
| |
| public void setSessionId(TajoIdProtos.SessionIdProto sessionId) { |
| this.sessionId = sessionId; |
| } |
| |
| public boolean isConnected() { |
| try { |
| return connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false).isConnected(); |
| } catch (Exception e) { |
| return false; |
| } |
| } |
| |
| public TajoClient(InetSocketAddress addr) throws IOException { |
| this(new TajoConf(), addr, null); |
| } |
| |
| public TajoClient(String hostname, int port, String baseDatabase) throws IOException { |
| this(new TajoConf(), NetUtils.createSocketAddr(hostname, port), baseDatabase); |
| } |
| |
| public TajoIdProtos.SessionIdProto getSessionId() { |
| return sessionId; |
| } |
| |
| @Override |
| public void close() { |
| // remove session |
| try { |
| NettyClientBase client = connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false); |
| TajoMasterClientProtocolService.BlockingInterface tajoMaster = client.getStub(); |
| tajoMaster.removeSession(null, sessionId); |
| } catch (Exception e) { |
| LOG.error(e); |
| } |
| |
| if(connPool != null) { |
| connPool.shutdown(); |
| } |
| queryMasterMap.clear(); |
| } |
| |
| public TajoConf getConf() { |
| return conf; |
| } |
| |
| public UserGroupInformation getUserInfo() { |
| return userInfo; |
| } |
| |
| /** |
| * Call to QueryMaster closing query resources |
| * @param queryId |
| */ |
| public void closeQuery(final QueryId queryId) { |
| if(queryMasterMap.containsKey(queryId)) { |
| NettyClientBase qmClient = null; |
| try { |
| qmClient = connPool.getConnection(queryMasterMap.get(queryId), QueryMasterClientProtocol.class, false); |
| QueryMasterClientProtocolService.BlockingInterface queryMasterService = qmClient.getStub(); |
| queryMasterService.closeQuery(null, queryId.getProto()); |
| } catch (Exception e) { |
| LOG.warn("Fail to close a QueryMaster connection (qid=" + queryId + ", msg=" + e.getMessage() + ")", e); |
| } finally { |
| connPool.closeConnection(qmClient); |
| queryMasterMap.remove(queryId); |
| } |
| } |
| } |
| |
| private void checkSessionAndGet(NettyClientBase client) throws ServiceException { |
| if (sessionId == null) { |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| CreateSessionRequest.Builder builder = CreateSessionRequest.newBuilder(); |
| builder.setUsername(userInfo.getUserName()).build(); |
| if (baseDatabase != null) { |
| builder.setBaseDatabaseName(baseDatabase); |
| } |
| CreateSessionResponse response = tajoMasterService.createSession(null, builder.build()); |
| if (response.getState() == CreateSessionResponse.ResultState.SUCCESS) { |
| sessionId = response.getSessionId(); |
| if (LOG.isDebugEnabled()) { |
| LOG.debug(String.format("Got session %s as a user '%s'.", sessionId.getId(), userInfo.getUserName())); |
| } |
| } else { |
| throw new InvalidClientSessionException(response.getMessage()); |
| } |
| } |
| } |
| |
| private SessionedStringProto convertSessionedString(String str) { |
| SessionedStringProto.Builder builder = SessionedStringProto.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setValue(str); |
| return builder.build(); |
| } |
| |
| public String getCurrentDatabase() throws ServiceException { |
| return new ServerCallable<String>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| |
| public String call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.getCurrentDatabase(null, sessionId).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public Boolean selectDatabase(final String databaseName) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.selectDatabase(null, convertSessionedString(databaseName)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public Boolean updateSessionVariables(final Map<String, String> variables) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| KeyValueSet keyValueSet = new KeyValueSet(); |
| keyValueSet.putAll(variables); |
| UpdateSessionVariableRequest request = UpdateSessionVariableRequest.newBuilder() |
| .setSessionId(sessionId) |
| .setSetVariables(keyValueSet.getProto()).build(); |
| |
| return tajoMasterService.updateSessionVariables(null, request).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public Boolean unsetSessionVariables(final List<String> variables) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| UpdateSessionVariableRequest request = UpdateSessionVariableRequest.newBuilder() |
| .setSessionId(sessionId) |
| .addAllUnsetVariables(variables).build(); |
| return tajoMasterService.updateSessionVariables(null, request).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public String getSessionVariable(final String varname) throws ServiceException { |
| return new ServerCallable<String>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| |
| public String call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.getSessionVariable(null, convertSessionedString(varname)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public Boolean existSessionVariable(final String varname) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.existSessionVariable(null, convertSessionedString(varname)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public Map<String, String> getAllSessionVariables() throws ServiceException { |
| return new ServerCallable<Map<String, String>>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, |
| false, true) { |
| |
| public Map<String, String> call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| KeyValueSet keyValueSet = new KeyValueSet(tajoMasterService.getAllSessionVariables(null, sessionId)); |
| return keyValueSet.getAllKeyValus(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * It submits a query statement and get a response immediately. |
| * The response only contains a query id, and submission status. |
| * In order to get the result, you should use {@link #getQueryResult(org.apache.tajo.QueryId)} |
| * or {@link #getQueryResultAndWait(org.apache.tajo.QueryId)}. |
| */ |
| public SubmitQueryResponse executeQuery(final String sql) throws ServiceException { |
| return new ServerCallable<SubmitQueryResponse>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public SubmitQueryResponse call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| final QueryRequest.Builder builder = QueryRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setQuery(sql); |
| builder.setIsJson(false); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.submitQuery(null, builder.build()); |
| } |
| }.withRetries(); |
| } |
| |
| public SubmitQueryResponse executeQueryWithJson(final String json) throws ServiceException { |
| return new ServerCallable<SubmitQueryResponse>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public SubmitQueryResponse call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| final QueryRequest.Builder builder = QueryRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setQuery(json); |
| builder.setIsJson(true); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.submitQuery(null, builder.build()); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * It submits a query statement and get a response. |
| * The main difference from {@link #executeQuery(String)} |
| * is a blocking method. So, this method is wait for |
| * the finish of the submitted query. |
| * |
| * @return If failed, return null. |
| */ |
| public ResultSet executeQueryAndGetResult(final String sql) |
| throws ServiceException, IOException { |
| SubmitQueryResponse response = executeQuery(sql); |
| |
| QueryId queryId = new QueryId(response.getQueryId()); |
| if (response.getIsForwarded()) { |
| if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) { |
| return this.createNullResultSet(queryId); |
| } else { |
| return this.getQueryResultAndWait(queryId); |
| } |
| } else { |
| // If a non-forwarded insert into query |
| if (queryId.equals(QueryIdFactory.NULL_QUERY_ID) && response.getMaxRowNum() < 0) { |
| return this.createNullResultSet(queryId); |
| } else { |
| if (response.hasResultSet() || response.hasTableDesc()) { |
| return createResultSet(this, response); |
| } else { |
| return this.createNullResultSet(queryId); |
| } |
| } |
| } |
| } |
| |
| public ResultSet executeJsonQueryAndGetResult(final String json) throws ServiceException, IOException { |
| SubmitQueryResponse response = executeQueryWithJson(json); |
| |
| QueryId queryId = new QueryId(response.getQueryId()); |
| if (response.getIsForwarded()) { |
| if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) { |
| return this.createNullResultSet(queryId); |
| } else { |
| return this.getQueryResultAndWait(queryId); |
| } |
| } else { |
| if (response.hasResultSet() || response.hasTableDesc()) { |
| return createResultSet(this, response); |
| } else { |
| return this.createNullResultSet(queryId); |
| } |
| } |
| } |
| |
| public QueryStatus getQueryStatus(QueryId queryId) throws ServiceException { |
| GetQueryStatusRequest.Builder builder = GetQueryStatusRequest.newBuilder(); |
| builder.setQueryId(queryId.getProto()); |
| |
| GetQueryStatusResponse res = null; |
| if(queryMasterMap.containsKey(queryId)) { |
| NettyClientBase qmClient = null; |
| try { |
| qmClient = connPool.getConnection(queryMasterMap.get(queryId), |
| QueryMasterClientProtocol.class, false); |
| QueryMasterClientProtocolService.BlockingInterface queryMasterService = qmClient.getStub(); |
| res = queryMasterService.getQueryStatus(null, builder.build()); |
| } catch (Exception e) { |
| throw new ServiceException(e.getMessage(), e); |
| } finally { |
| connPool.releaseConnection(qmClient); |
| } |
| } else { |
| NettyClientBase tmClient = null; |
| try { |
| tmClient = connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false); |
| |
| checkSessionAndGet(tmClient); |
| builder.setSessionId(sessionId); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = tmClient.getStub(); |
| res = tajoMasterService.getQueryStatus(null, builder.build()); |
| |
| String queryMasterHost = res.getQueryMasterHost(); |
| if(queryMasterHost != null && !queryMasterHost.isEmpty()) { |
| NettyClientBase qmClient = null; |
| try { |
| InetSocketAddress qmAddr = NetUtils.createSocketAddr(queryMasterHost, res.getQueryMasterPort()); |
| qmClient = connPool.getConnection( |
| qmAddr, QueryMasterClientProtocol.class, false); |
| QueryMasterClientProtocolService.BlockingInterface queryMasterService = qmClient.getStub(); |
| res = queryMasterService.getQueryStatus(null, builder.build()); |
| |
| queryMasterMap.put(queryId, qmAddr); |
| } catch (Exception e) { |
| throw new ServiceException(e.getMessage(), e); |
| } finally { |
| connPool.releaseConnection(qmClient); |
| } |
| } |
| } catch (Exception e) { |
| throw new ServiceException(e.getMessage(), e); |
| } finally { |
| connPool.releaseConnection(tmClient); |
| } |
| } |
| return new QueryStatus(res); |
| } |
| |
| public static boolean isQueryRunnning(QueryState state) { |
| return state == QueryState.QUERY_NEW || |
| state == QueryState.QUERY_RUNNING || |
| state == QueryState.QUERY_MASTER_LAUNCHED || |
| state == QueryState.QUERY_MASTER_INIT || |
| state == QueryState.QUERY_NOT_ASSIGNED; |
| } |
| |
| public ResultSet getQueryResult(QueryId queryId) |
| throws ServiceException, IOException { |
| if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) { |
| return createNullResultSet(queryId); |
| } |
| GetQueryResultResponse response = getResultResponse(queryId); |
| TableDesc tableDesc = CatalogUtil.newTableDesc(response.getTableDesc()); |
| conf.setVar(ConfVars.USERNAME, response.getTajoUserName()); |
| return new TajoResultSet(this, queryId, conf, tableDesc); |
| } |
| |
| public static ResultSet createResultSet(TajoClient client, QueryId queryId, GetQueryResultResponse response) |
| throws IOException { |
| TableDesc desc = CatalogUtil.newTableDesc(response.getTableDesc()); |
| TajoConf conf = new TajoConf(client.getConf()); |
| conf.setVar(ConfVars.USERNAME, response.getTajoUserName()); |
| return new TajoResultSet(client, queryId, conf, desc); |
| } |
| |
| public static ResultSet createResultSet(TajoClient client, SubmitQueryResponse response) throws IOException { |
| if (response.hasTableDesc()) { |
| TajoConf conf = new TajoConf(client.getConf()); |
| conf.setVar(ConfVars.USERNAME, response.getUserName()); |
| if (response.hasMaxRowNum()) { |
| return new TajoResultSet( |
| client, |
| QueryIdFactory.NULL_QUERY_ID, |
| conf, |
| new TableDesc(response.getTableDesc()), |
| response.getMaxRowNum()); |
| } else { |
| return new TajoResultSet( |
| client, |
| QueryIdFactory.NULL_QUERY_ID, |
| conf, |
| new TableDesc(response.getTableDesc())); |
| } |
| } else { |
| SerializedResultSet serializedResultSet = response.getResultSet(); |
| return new TajoMemoryResultSet( |
| new Schema(serializedResultSet.getSchema()), |
| serializedResultSet.getSerializedTuplesList(), |
| response.getMaxRowNum()); |
| } |
| } |
| |
| private ResultSet getQueryResultAndWait(QueryId queryId) |
| throws ServiceException, IOException { |
| if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) { |
| return createNullResultSet(queryId); |
| } |
| QueryStatus status = getQueryStatus(queryId); |
| |
| while(status != null && isQueryRunnning(status.getState())) { |
| try { |
| Thread.sleep(500); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| |
| status = getQueryStatus(queryId); |
| } |
| |
| if (status.getState() == QueryState.QUERY_SUCCEEDED) { |
| if (status.hasResult()) { |
| return getQueryResult(queryId); |
| } else { |
| return createNullResultSet(queryId); |
| } |
| |
| } else { |
| LOG.warn("Query (" + status.getQueryId() + ") failed: " + status.getState()); |
| |
| //TODO throw SQLException(?) |
| return createNullResultSet(queryId); |
| } |
| } |
| |
| public ResultSet createNullResultSet(QueryId queryId) throws IOException { |
| return new TajoResultSet(this, queryId); |
| } |
| |
| public GetQueryResultResponse getResultResponse(QueryId queryId) throws ServiceException { |
| if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) { |
| return null; |
| } |
| |
| NettyClientBase client = null; |
| try { |
| InetSocketAddress queryMasterAddr = queryMasterMap.get(queryId); |
| if(queryMasterAddr == null) { |
| LOG.warn("No Connection to QueryMaster for " + queryId); |
| return null; |
| } |
| client = connPool.getConnection(queryMasterAddr, QueryMasterClientProtocol.class, false); |
| QueryMasterClientProtocolService.BlockingInterface queryMasterService = client.getStub(); |
| GetQueryResultRequest.Builder builder = GetQueryResultRequest.newBuilder(); |
| builder.setQueryId(queryId.getProto()); |
| GetQueryResultResponse response = queryMasterService.getQueryResult(null, |
| builder.build()); |
| |
| return response; |
| } catch (Exception e) { |
| throw new ServiceException(e.getMessage(), e); |
| } finally { |
| connPool.releaseConnection(client); |
| } |
| } |
| |
| public boolean updateQuery(final String sql) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| QueryRequest.Builder builder = QueryRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setQuery(sql); |
| builder.setIsJson(false); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| UpdateQueryResponse response = tajoMasterService.updateQuery(null, builder.build()); |
| if (response.getResultCode() == ResultCode.OK) { |
| return true; |
| } else { |
| if (response.hasErrorMessage()) { |
| System.err.println("ERROR: " + response.getErrorMessage()); |
| } |
| return false; |
| } |
| } |
| }.withRetries(); |
| } |
| |
| public boolean updateQueryWithJson(final String json) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| QueryRequest.Builder builder = QueryRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setQuery(json); |
| builder.setIsJson(true); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| UpdateQueryResponse response = tajoMasterService.updateQuery(null, builder.build()); |
| if (response.getResultCode() == ResultCode.OK) { |
| return true; |
| } else { |
| if (response.hasErrorMessage()) { |
| System.err.println("ERROR: " + response.getErrorMessage()); |
| } |
| return false; |
| } |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Create a database. |
| * |
| * @param databaseName The database name to be created. This name is case sensitive. |
| * @return True if created successfully. |
| * @throws ServiceException |
| */ |
| public boolean createDatabase(final String databaseName) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.createDatabase(null, convertSessionedString(databaseName)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Does the database exist? |
| * |
| * @param databaseName The database name to be checked. This name is case sensitive. |
| * @return True if so. |
| * @throws ServiceException |
| */ |
| public boolean existDatabase(final String databaseName) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.existDatabase(null, convertSessionedString(databaseName)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Drop the database |
| * |
| * @param databaseName The database name to be dropped. This name is case sensitive. |
| * @return True if the database is dropped successfully. |
| * @throws ServiceException |
| */ |
| public boolean dropDatabase(final String databaseName) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.dropDatabase(null, convertSessionedString(databaseName)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| public List<String> getAllDatabaseNames() throws ServiceException { |
| return new ServerCallable<List<String>>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) { |
| public List<String> call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.getAllDatabases(null, sessionId).getValuesList(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Does the table exist? |
| * |
| * @param tableName The table name to be checked. This name is case sensitive. |
| * @return True if so. |
| */ |
| public boolean existTable(final String tableName) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| return tajoMasterService.existTable(null, convertSessionedString(tableName)).getValue(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Create an external table. |
| * |
| * @param tableName The table name to be created. This name is case sensitive. This name can be qualified or not. |
| * If the table name is not qualified, the current database in the session will be used. |
| * @param schema The schema |
| * @param path The external table location |
| * @param meta Table meta |
| * @return the created table description. |
| * @throws SQLException |
| * @throws ServiceException |
| */ |
| public TableDesc createExternalTable(final String tableName, final Schema schema, final Path path, |
| final TableMeta meta) |
| throws SQLException, ServiceException { |
| return new ServerCallable<TableDesc>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public TableDesc call(NettyClientBase client) throws ServiceException, SQLException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| CreateTableRequest.Builder builder = CreateTableRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setName(tableName); |
| builder.setSchema(schema.getProto()); |
| builder.setMeta(meta.getProto()); |
| builder.setPath(path.toUri().toString()); |
| TableResponse res = tajoMasterService.createExternalTable(null, builder.build()); |
| if (res.getResultCode() == ResultCode.OK) { |
| return CatalogUtil.newTableDesc(res.getTableDesc()); |
| } else { |
| throw new SQLException(res.getErrorMessage(), SQLStates.ER_NO_SUCH_TABLE.getState()); |
| } |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Drop a table |
| * |
| * @param tableName The table name to be dropped. This name is case sensitive. |
| * @return True if the table is dropped successfully. |
| */ |
| public boolean dropTable(final String tableName) throws ServiceException { |
| return dropTable(tableName, false); |
| } |
| |
| /** |
| * Drop a table. |
| * |
| * @param tableName The table name to be dropped. This name is case sensitive. |
| * @param purge If purge is true, this call will remove the entry in catalog as well as the table contents. |
| * @return True if the table is dropped successfully. |
| */ |
| public boolean dropTable(final String tableName, final boolean purge) throws ServiceException { |
| return new ServerCallable<Boolean>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public Boolean call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| DropTableRequest.Builder builder = DropTableRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setName(tableName); |
| builder.setPurge(purge); |
| return tajoMasterService.dropTable(null, builder.build()).getValue(); |
| } |
| }.withRetries(); |
| |
| } |
| |
| public List<BriefQueryInfo> getRunningQueryList() throws ServiceException { |
| return new ServerCallable<List<BriefQueryInfo>>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public List<BriefQueryInfo> call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| GetQueryListRequest.Builder builder = GetQueryListRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| GetQueryListResponse res = tajoMasterService.getRunningQueryList(null, builder.build()); |
| return res.getQueryListList(); |
| } |
| }.withRetries(); |
| } |
| |
| public List<BriefQueryInfo> getFinishedQueryList() throws ServiceException { |
| return new ServerCallable<List<BriefQueryInfo>>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public List<BriefQueryInfo> call(NettyClientBase client) throws ServiceException { |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| GetQueryListRequest.Builder builder = GetQueryListRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| GetQueryListResponse res = tajoMasterService.getFinishedQueryList(null, builder.build()); |
| return res.getQueryListList(); |
| } |
| }.withRetries(); |
| } |
| |
| public List<WorkerResourceInfo> getClusterInfo() throws ServiceException { |
| return new ServerCallable<List<WorkerResourceInfo>>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public List<WorkerResourceInfo> call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| GetClusterInfoRequest.Builder builder = GetClusterInfoRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| GetClusterInfoResponse res = tajoMasterService.getClusterInfo(null, builder.build()); |
| return res.getWorkerListList(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Get a list of table names. |
| * |
| * @param databaseName The database name to show all tables. This name is case sensitive. |
| * If it is null, this method will show all tables |
| * in the current database of this session. |
| */ |
| public List<String> getTableList(@Nullable final String databaseName) throws ServiceException { |
| return new ServerCallable<List<String>>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public List<String> call(NettyClientBase client) throws ServiceException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| GetTableListRequest.Builder builder = GetTableListRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| if (databaseName != null) { |
| builder.setDatabaseName(databaseName); |
| } |
| GetTableListResponse res = tajoMasterService.getTableList(null, builder.build()); |
| return res.getTablesList(); |
| } |
| }.withRetries(); |
| } |
| |
| /** |
| * Get a table description |
| * |
| * @param tableName The table name to get. This name is case sensitive. |
| * @return Table description |
| */ |
| public TableDesc getTableDesc(final String tableName) throws ServiceException { |
| return new ServerCallable<TableDesc>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public TableDesc call(NettyClientBase client) throws ServiceException, SQLException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| |
| GetTableDescRequest.Builder builder = GetTableDescRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setTableName(tableName); |
| TableResponse res = tajoMasterService.getTableDesc(null, builder.build()); |
| if (res.getResultCode() == ResultCode.OK) { |
| return CatalogUtil.newTableDesc(res.getTableDesc()); |
| } else { |
| throw new SQLException(res.getErrorMessage(), SQLStates.ER_NO_SUCH_TABLE.getState()); |
| } |
| } |
| }.withRetries(); |
| } |
| |
| public boolean killQuery(final QueryId queryId) |
| throws ServiceException, IOException { |
| |
| QueryStatus status = getQueryStatus(queryId); |
| |
| NettyClientBase tmClient = null; |
| try { |
| /* send a kill to the TM */ |
| tmClient = connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false); |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = tmClient.getStub(); |
| |
| checkSessionAndGet(tmClient); |
| |
| KillQueryRequest.Builder builder = KillQueryRequest.newBuilder(); |
| builder.setSessionId(sessionId); |
| builder.setQueryId(queryId.getProto()); |
| tajoMasterService.killQuery(null, builder.build()); |
| |
| long currentTimeMillis = System.currentTimeMillis(); |
| long timeKillIssued = currentTimeMillis; |
| while ((currentTimeMillis < timeKillIssued + 10000L) && (status.getState() != QueryState.QUERY_KILLED)) { |
| try { |
| Thread.sleep(100L); |
| } catch(InterruptedException ie) { |
| break; |
| } |
| currentTimeMillis = System.currentTimeMillis(); |
| status = getQueryStatus(queryId); |
| } |
| return status.getState() == QueryState.QUERY_KILLED; |
| } catch(Exception e) { |
| LOG.debug("Error when checking for application status", e); |
| return false; |
| } finally { |
| connPool.releaseConnection(tmClient); |
| } |
| } |
| |
| public List<CatalogProtos.FunctionDescProto> getFunctions(final String functionName) throws ServiceException { |
| return new ServerCallable<List<CatalogProtos.FunctionDescProto>>(connPool, tajoMasterAddr, |
| TajoMasterClientProtocol.class, false, true) { |
| public List<CatalogProtos.FunctionDescProto> call(NettyClientBase client) throws ServiceException, SQLException { |
| checkSessionAndGet(client); |
| |
| TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub(); |
| String paramFunctionName = functionName == null ? "" : functionName; |
| FunctionResponse res = tajoMasterService.getFunctionList(null,convertSessionedString(paramFunctionName)); |
| if (res.getResultCode() == ResultCode.OK) { |
| return res.getFunctionsList(); |
| } else { |
| throw new SQLException(res.getErrorMessage()); |
| } |
| } |
| }.withRetries(); |
| } |
| } |