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.
/*******************************************************************************
* 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 java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.Cassandra.Client;
import org.apache.cassandra.thrift.CfDef;
import org.apache.cassandra.thrift.CounterColumn;
import org.apache.cassandra.thrift.KsDef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.netflix.astyanax.AstyanaxConfiguration;
import com.netflix.astyanax.CassandraOperationType;
import com.netflix.astyanax.ColumnMutation;
import com.netflix.astyanax.Execution;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.KeyspaceTracerFactory;
import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.SerializerPackage;
import com.netflix.astyanax.WriteAheadEntry;
import com.netflix.astyanax.WriteAheadLog;
import com.netflix.astyanax.connectionpool.ConnectionContext;
import com.netflix.astyanax.connectionpool.ConnectionPool;
import com.netflix.astyanax.connectionpool.Host;
import com.netflix.astyanax.connectionpool.Operation;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.TokenRange;
import com.netflix.astyanax.connectionpool.exceptions.BadRequestException;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.connectionpool.exceptions.IsDeadConnectionException;
import com.netflix.astyanax.connectionpool.exceptions.NotFoundException;
import com.netflix.astyanax.connectionpool.exceptions.OperationException;
import com.netflix.astyanax.connectionpool.exceptions.SchemaDisagreementException;
import com.netflix.astyanax.connectionpool.impl.OperationResultImpl;
import com.netflix.astyanax.connectionpool.impl.TokenRangeImpl;
import com.netflix.astyanax.cql.CqlStatement;
import com.netflix.astyanax.ddl.ColumnFamilyDefinition;
import com.netflix.astyanax.ddl.KeyspaceDefinition;
import com.netflix.astyanax.ddl.SchemaChangeResult;
import com.netflix.astyanax.ddl.impl.SchemaChangeResponseImpl;
import com.netflix.astyanax.model.CfSplit;
import com.netflix.astyanax.model.ColumnFamily;
import com.netflix.astyanax.partitioner.Partitioner;
import com.netflix.astyanax.query.ColumnFamilyQuery;
import com.netflix.astyanax.retry.RetryPolicy;
import com.netflix.astyanax.retry.RunOnce;
import com.netflix.astyanax.serializers.SerializerPackageImpl;
import com.netflix.astyanax.serializers.UnknownComparatorException;
import com.netflix.astyanax.thrift.ddl.ThriftColumnFamilyDefinitionImpl;
import com.netflix.astyanax.thrift.ddl.ThriftKeyspaceDefinitionImpl;
import com.netflix.astyanax.thrift.model.ThriftCfSplitImpl;
/**
*
* @ThreadSafe
* Note that the same instances of this class can be used by multiple threads.
* Especially for reads and writes, the prepareQuery() and prepareMutationBatch() calls are thread safe
* but adding multiple mutations to the same mutation batch is NOT thread safe.
*
* Hence once a mutation batch is created by a thread, then that batch should be used by that thread only.
*
* @author elandau
*
*/
public final class ThriftKeyspaceImpl implements Keyspace {
private final static Logger LOG = LoggerFactory.getLogger(ThriftKeyspaceImpl.class);
final ConnectionPool connectionPool;
final AstyanaxConfiguration config;
final String ksName;
final ListeningExecutorService executor;
final KeyspaceTracerFactory tracerFactory;
final Cache cache;
final ThriftCqlFactory cqlStatementFactory;
private Host ddlHost = null;
private volatile Partitioner partitioner;
public ThriftKeyspaceImpl(
String ksName,
ConnectionPool pool,
AstyanaxConfiguration config,
final KeyspaceTracerFactory tracerFactory) {
this.connectionPool = pool;
this.config = config;
this.ksName = ksName;
this.executor = MoreExecutors.listeningDecorator(config.getAsyncExecutor());
this.tracerFactory = tracerFactory;
this.cache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build();
this.cqlStatementFactory = ThriftCqlFactoryResolver.createFactory(config);
}
@Override
public String getKeyspaceName() {
return this.ksName;
}
@Override
public MutationBatch prepareMutationBatch() {
return new AbstractThriftMutationBatchImpl(config.getClock(), config.getDefaultWriteConsistencyLevel(), config.getRetryPolicy().duplicate()) {
@Override
public OperationResult execute() throws ConnectionException {
WriteAheadLog wal = getWriteAheadLog();
WriteAheadEntry walEntry = null;
if (wal != null) {
walEntry = wal.createEntry();
walEntry.writeMutation(this);
}
try {
OperationResult result = executeOperation(
new AbstractKeyspaceOperationImpl(
tracerFactory.newTracer(useAtomicBatch() ? CassandraOperationType.ATOMIC_BATCH_MUTATE : CassandraOperationType.BATCH_MUTATE),
getPinnedHost(),
getKeyspaceName()) {
@Override
public Void internalExecute(Client client, ConnectionContext context) throws Exception {
// Mutation can be atomic or non-atomic.
// see http://www.datastax.com/dev/blog/atomic-batches-in-cassandra-1-2 for details on atomic batches
if (useAtomicBatch()) {
client.atomic_batch_mutate(getMutationMap(),
ThriftConverter.ToThriftConsistencyLevel(getConsistencyLevel()));
} else {
client.batch_mutate(getMutationMap(),
ThriftConverter.ToThriftConsistencyLevel(getConsistencyLevel()));
}
discardMutations();
return null;
}
@Override
public ByteBuffer getRowKey() {
if (getMutationMap().size() == 1)
return getMutationMap().keySet().iterator().next();
else
return null;
}
}, getRetryPolicy());
if (walEntry != null) {
wal.removeEntry(walEntry);
}
return result;
}
catch (ConnectionException exception) {
throw exception;
}
catch (Exception exception) {
throw ThriftConverter.ToConnectionPoolException(exception);
}
}
@Override
public ListenableFuture> executeAsync() throws ConnectionException {
return executor.submit(new Callable>() {
@Override
public OperationResult call() throws Exception {
return execute();
}
});
}
@Override
public MutationBatch withCaching(boolean condition) {
// This is a no-op when using Thrift
return this;
}
};
}
@Override
public List describeRing() throws ConnectionException {
return describeRing(null, null);
}
@Override
public List describeRing(final String dc) throws ConnectionException {
return describeRing(dc, null);
}
@Override
public List describeRing(final String dc, final String rack) throws ConnectionException {
return executeOperation(
new AbstractKeyspaceOperationImpl>(tracerFactory
.newTracer(CassandraOperationType.DESCRIBE_RING), getKeyspaceName()) {
@Override
public List internalExecute(Cassandra.Client client, ConnectionContext context) throws Exception {
List trs = client.describe_ring(getKeyspaceName());
List range = Lists.newArrayList();
for (org.apache.cassandra.thrift.TokenRange tr : trs) {
List endpoints = Lists.newArrayList();
for (org.apache.cassandra.thrift.EndpointDetails ed : tr.getEndpoint_details()) {
if (dc != null && !ed.getDatacenter().equals(dc)) {
continue;
}
else if (rack != null && !ed.getRack().equals(rack)) {
continue;
}
else {
endpoints.add(ed.getHost());
}
}
if (!endpoints.isEmpty()) {
range.add(new TokenRangeImpl(tr.getStart_token(), tr.getEnd_token(), endpoints));
}
}
return range;
}
}, getConfig().getRetryPolicy().duplicate()).getResult();
}
@SuppressWarnings("unchecked")
@Override
public List describeRing(boolean cached) throws ConnectionException {
if (cached) {
try {
return (List) this.cache.get(CassandraOperationType.DESCRIBE_RING.name(),
new Callable