/**
* Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.linkedin.pinot.client;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A connection to Pinot, normally created through calls to the {@link ConnectionFactory}.
*/
public class Connection {
private static final Logger LOGGER = LoggerFactory.getLogger(Connection.class);
private final PinotClientTransport _transport;
private BrokerSelector _brokerSelector;
private List<String> _brokerList;
Connection(List<String> brokerList, PinotClientTransport transport) {
_brokerList = brokerList;
LOGGER.info("Creating connection to broker list {}", brokerList);
_brokerSelector = new SimpleBrokerSelector(brokerList);
_transport = transport;
}
Connection(BrokerSelector brokerSelector , PinotClientTransport transport) {
_brokerSelector = brokerSelector;
_transport = transport;
}
/**
* Creates a prepared statement, to escape query parameters.
*
* @param statement The statement for which to create a prepared statement.
* @return A prepared statement for this connection.
*/
public PreparedStatement prepareStatement(String statement) {
return new PreparedStatement(this, statement);
}
/**
* Executes a PQL statement.
* @param statement The statement to execute
* @return The result of the query
* @throws PinotClientException If an exception occurs while processing the query
*/
public ResultSetGroup execute(String statement) throws PinotClientException {
return execute(null, statement);
}
/**
* Executes a PQL statement.
*
* @param statement The statement to execute
* @return The result of the query
* @throws PinotClientException If an exception occurs while processing the query
*/
public ResultSetGroup execute(String tableName, String statement) throws PinotClientException {
String brokerHostPort = _brokerSelector.selectBroker(tableName);
if (brokerHostPort == null) {
throw new PinotClientException("Could not find broker to query for table: " +
(tableName == null ? "null" : tableName));
}
BrokerResponse response = _transport.executeQuery(brokerHostPort, statement);
if (response.hasExceptions()) {
throw new PinotClientException("Query had processing exceptions: \n" + response.getExceptions());
}
return new ResultSetGroup(response);
}
/**
* Executes a PQL statement asynchronously.
*
* @param statement The statement to execute
* @return A future containing the result of the query
* @throws PinotClientException If an exception occurs while processing the query
*/
public Future<ResultSetGroup> executeAsync(String statement) throws PinotClientException {
String brokerHostPort = _brokerSelector.selectBroker(null);
if (brokerHostPort == null) {
throw new PinotClientException("Could not find broker to query for statement: " +
(statement == null ? "null" : statement));
}
final Future<BrokerResponse> responseFuture = _transport.executeQueryAsync(brokerHostPort, statement);
return new ResultSetGroupFuture(responseFuture);
}
/**
* Returns the list of brokers to which this connection can connect to.
*
* @return The list of brokers to which this connection can connect to.
*/
List<String> getBrokerList() {
return _brokerList;
}
private static class ResultSetGroupFuture implements Future<ResultSetGroup> {
private final Future<BrokerResponse> _responseFuture;
public ResultSetGroupFuture(Future<BrokerResponse> responseFuture) {
_responseFuture = responseFuture;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return _responseFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return _responseFuture.isCancelled();
}
@Override
public boolean isDone() {
return _responseFuture.isDone();
}
@Override
public ResultSetGroup get() throws InterruptedException, ExecutionException {
try {
return get(1000L, TimeUnit.DAYS);
} catch (TimeoutException e) {
throw new ExecutionException(e);
}
}
@Override
public ResultSetGroup get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
BrokerResponse response = _responseFuture.get(timeout, unit);
return new ResultSetGroup(response);
}
}
}