All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.netflix.astyanax.thrift.ThriftSyncConnectionFactoryImpl Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2011 Netflix
*
* 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.netflix.astyanax.thrift;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.netflix.astyanax.AstyanaxConfiguration;
import com.netflix.astyanax.AuthenticationCredentials;
import com.netflix.astyanax.CassandraOperationTracer;
import com.netflix.astyanax.CassandraOperationType;
import com.netflix.astyanax.KeyspaceTracerFactory;
import com.netflix.astyanax.connectionpool.Connection;
import com.netflix.astyanax.connectionpool.ConnectionFactory;
import com.netflix.astyanax.connectionpool.ConnectionPoolConfiguration;
import com.netflix.astyanax.connectionpool.ConnectionPoolMonitor;
import com.netflix.astyanax.connectionpool.Host;
import com.netflix.astyanax.connectionpool.HostConnectionPool;
import com.netflix.astyanax.connectionpool.Operation;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.RateLimiter;
import com.netflix.astyanax.connectionpool.SSLConnectionContext;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.connectionpool.exceptions.IsTimeoutException;
import com.netflix.astyanax.connectionpool.exceptions.ThrottledException;
import com.netflix.astyanax.connectionpool.impl.OperationResultImpl;
import com.netflix.astyanax.connectionpool.impl.SimpleRateLimiterImpl;
import org.apache.cassandra.thrift.AuthenticationRequest;
import org.apache.cassandra.thrift.Cassandra;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
public class ThriftSyncConnectionFactoryImpl implements ConnectionFactory {
private static final String NAME_FORMAT = "ThriftConnection<%s-%d>";
private static final Logger LOG = LoggerFactory.getLogger(ThriftSyncConnectionFactoryImpl.class);
private final static ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setDaemon(true)
.build());
private final AtomicLong idCounter = new AtomicLong(0);
private final RateLimiter limiter;
private final ConnectionPoolConfiguration cpConfig;
private final KeyspaceTracerFactory tracerFactory;
private final ConnectionPoolMonitor monitor;
private final AstyanaxConfiguration asConfig;
public ThriftSyncConnectionFactoryImpl(AstyanaxConfiguration asConfig, ConnectionPoolConfiguration cpConfig, KeyspaceTracerFactory tracerFactory,
ConnectionPoolMonitor monitor) {
this.cpConfig = cpConfig;
this.asConfig = asConfig;
this.limiter = new SimpleRateLimiterImpl(cpConfig);
this.tracerFactory = tracerFactory;
this.monitor = monitor;
}
@Override
public Connection createConnection(final HostConnectionPool pool)
throws ThrottledException {
if (limiter.check() == false) {
throw new ThrottledException("Too many connection attempts");
}
return new ThriftConnection(pool, asConfig.getMaxThriftSize());
}
public class ThriftConnection implements Connection {
private final long id = idCounter.incrementAndGet();
private Cassandra.Client cassandraClient;
private TFramedTransport transport;
private TSocket socket;
private int timeout = 0;
private int maxThriftSize = 0;
private AtomicLong operationCounter = new AtomicLong();
private AtomicBoolean closed = new AtomicBoolean(false);
private volatile ConnectionException lastException = null;
private volatile String keyspaceName;
private final HostConnectionPool pool;
private Map metadata = Maps.newHashMap();
public ThriftConnection(HostConnectionPool pool, int maxThriftSizeVal) {
this.pool = pool;
this.maxThriftSize = maxThriftSizeVal;
}
@Override
public OperationResult execute(Operation op) throws ConnectionException {
long startTime = System.nanoTime();
long latency = 0;
setTimeout(cpConfig.getSocketTimeout()); // In case the configurationchanged
operationCounter.incrementAndGet();
// Set a new keyspace, if it changed
lastException = null;
if (op.getKeyspace() != null && (keyspaceName == null || !op.getKeyspace().equals(keyspaceName))) {
CassandraOperationTracer tracer = tracerFactory.newTracer(CassandraOperationType.SET_KEYSPACE)
.start();
try {
cassandraClient.set_keyspace(op.getKeyspace());
if (asConfig.getCqlVersion() != null)
cassandraClient.set_cql_version(asConfig.getCqlVersion());
keyspaceName = op.getKeyspace();
long now = System.nanoTime();
latency = now - startTime;
pool.addLatencySample(latency, now);
tracer.success();
}
catch (Exception e) {
long now = System.nanoTime();
latency = now - startTime;
lastException = ThriftConverter.ToConnectionPoolException(e).setLatency(latency);
if (e instanceof IsTimeoutException) {
pool.addLatencySample(TimeUnit.NANOSECONDS.convert(cpConfig.getSocketTimeout(), TimeUnit.MILLISECONDS), now);
}
tracer.failure(lastException);
throw lastException;
}
startTime = System.nanoTime(); // We don't want to include
// the set_keyspace in our
// latency calculation
}
// Execute the operation
try {
R result = op.execute(cassandraClient, this);
long now = System.nanoTime();
latency = now - startTime;
pool.addLatencySample(latency, now);
return new OperationResultImpl(getHost(), result, latency);
}
catch (Exception e) {
long now = System.nanoTime();
latency = now - startTime;
lastException = ThriftConverter.ToConnectionPoolException(e).setLatency(latency);
if (e instanceof IsTimeoutException) {
pool.addLatencySample(TimeUnit.NANOSECONDS.convert(cpConfig.getSocketTimeout(), TimeUnit.MILLISECONDS), now);
}
throw lastException;
}
}
@Override
public void open() throws ConnectionException {
if (cassandraClient != null) {
throw new IllegalStateException("Open called on already open connection");
}
long startTime = System.currentTimeMillis();
try {
final SSLConnectionContext sslCxt = cpConfig.getSSLConnectionContext();
if(sslCxt != null) {
TSSLTransportParameters params = new TSSLTransportParameters(sslCxt.getSslProtocol(), sslCxt.getSslCipherSuites().toArray(new String[0]));
params.setTrustStore(sslCxt.getSslTruststore(), sslCxt.getSslTruststorePassword());
//thrift's SSL implementation does not allow you set the socket connect timeout, only read timeout
socket = TSSLTransportFactory.getClientSocket(getHost().getIpAddress(), getHost().getPort(), cpConfig.getSocketTimeout(), params);
} else {
socket = new TSocket(getHost().getIpAddress(), getHost().getPort(), cpConfig.getConnectTimeout());
}
socket.getSocket().setTcpNoDelay(true);
socket.getSocket().setKeepAlive(true);
socket.getSocket().setSoLinger(false, 0);
setTimeout(cpConfig.getSocketTimeout());
transport = new TFramedTransport(socket, maxThriftSize);
if(!transport.isOpen())
transport.open();
cassandraClient = new Cassandra.Client(new TBinaryProtocol.Factory().getProtocol(transport));
monitor.incConnectionCreated(getHost());
AuthenticationCredentials credentials = cpConfig.getAuthenticationCredentials();
if (credentials != null) {
Map thriftCredentials = Maps.newHashMapWithExpectedSize(2);
thriftCredentials.put("username", credentials.getUsername());
thriftCredentials.put("password", credentials.getPassword());
cassandraClient.login(new AuthenticationRequest(thriftCredentials));
}
}
catch (Exception e) {
pool.addLatencySample(TimeUnit.NANOSECONDS.convert(cpConfig.getSocketTimeout(), TimeUnit.MILLISECONDS), System.nanoTime());
closeClient();
ConnectionException ce = ThriftConverter.ToConnectionPoolException(e).setHost(getHost())
.setLatency(System.currentTimeMillis() - startTime);
monitor.incConnectionCreateFailed(getHost(), ce);
throw ce;
}
catch (Throwable t) {
LOG.error("Error creating connection", t);
pool.addLatencySample(TimeUnit.NANOSECONDS.convert(cpConfig.getSocketTimeout(), TimeUnit.MILLISECONDS), System.nanoTime());
closeClient();
ConnectionException ce = ThriftConverter.ToConnectionPoolException(new RuntimeException("Error openning connection", t)).setHost(getHost())
.setLatency(System.currentTimeMillis() - startTime);
monitor.incConnectionCreateFailed(getHost(), ce);
throw ce;
}
}
@Override
public void openAsync(final AsyncOpenCallback callback) {
final Connection This = this;
executor.submit(new Runnable() {
@Override
public void run() {
try {
open();
callback.success(This);
}
catch (Exception e) {
pool.addLatencySample(TimeUnit.NANOSECONDS.convert(cpConfig.getSocketTimeout(), TimeUnit.MILLISECONDS), System.nanoTime());
callback.failure(This, ThriftConverter.ToConnectionPoolException(e));
}
}
});
}
@Override
public void close() {
if (closed.compareAndSet(false, true)) {
monitor.incConnectionClosed(getHost(), lastException);
executor.submit(new Runnable() {
@Override
public void run() {
try {
closeClient();
}
catch (Exception e) {
}
}
});
}
}
private void closeClient() {
if (transport != null) {
try {
transport.flush();
}
catch (TTransportException e) {
}
finally {
try {
transport.close();
}
catch (Exception e) {
}
finally {
transport = null;
}
}
}
if (socket != null) {
try {
socket.close();
}
catch (Exception e) {
}
finally {
socket = null;
}
}
}
@Override
public HostConnectionPool getHostConnectionPool() {
return pool;
}
@Override
public ConnectionException getLastException() {
return lastException;
}
@Override
public String toString() {
return String.format(NAME_FORMAT, getHost().getHostName(), id);
}
/**
* Compares the toString of these clients
*/
@Override
public boolean equals(Object obj) {
return toString().equals(obj.toString());
}
@Override
public long getOperationCount() {
return operationCounter.get();
}
@Override
public Host getHost() {
return pool.getHost();
}
public void setTimeout(int timeout) {
if (this.timeout != timeout) {
socket.setTimeout(timeout);
this.timeout = timeout;
}
}
@Override
public void setMetadata(String key, Object data) {
metadata.put(key, data);
}
@Override
public Object getMetadata(String key) {
return metadata.get(key);
}
@Override
public boolean hasMetadata(String key) {
return metadata.containsKey(key);
}
}
}