package me.prettyprint.cassandra.service.template; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import me.prettyprint.cassandra.model.ExecutingKeyspace; import me.prettyprint.cassandra.model.ExecutionResult; import me.prettyprint.cassandra.model.HSlicePredicate; import me.prettyprint.cassandra.model.thrift.ThriftConverter; import me.prettyprint.cassandra.service.Operation; import me.prettyprint.cassandra.service.OperationType; import me.prettyprint.hector.api.Keyspace; import me.prettyprint.hector.api.Serializer; import me.prettyprint.hector.api.exceptions.HectorException; import org.apache.cassandra.thrift.Cassandra; import org.apache.cassandra.thrift.Cassandra.Client; import org.apache.cassandra.thrift.ColumnOrSuperColumn; import org.apache.cassandra.thrift.KeySlice; import com.google.common.collect.Iterators; /** * Thrift specific implementation of {@link ColumnFamilyTemplate} * @author nate * * @param <K> * @param <N> */ public class ThriftColumnFamilyTemplate<K, N> extends ColumnFamilyTemplate<K, N> { public ThriftColumnFamilyTemplate(Keyspace keyspace, String columnFamily, Serializer<K> keySerializer, Serializer<N> topSerializer) { super(keyspace, columnFamily, keySerializer, topSerializer); } public <T> T doExecuteSlice(K key, HSlicePredicate<N> predicate, ColumnFamilyRowMapper<K, N, T> mapper) { return mapper.mapRow(doExecuteSlice(key,predicate)); } public ColumnFamilyResult<K, N> doExecuteSlice(final K key, final HSlicePredicate<N> workingSlicePredicate) { return new ColumnFamilyResultWrapper<K, N>(keySerializer, topSerializer, sliceInternal(key, workingSlicePredicate)); } public ColumnFamilyResult<K, N> doExecuteMultigetSlice(final Iterable<K> keys, final HSlicePredicate<N> workingSlicePredicate) { return new ColumnFamilyResultWrapper<K, N>(keySerializer, topSerializer, multigetSliceInternal(keys, workingSlicePredicate)); } public <V> MappedColumnFamilyResult<K, N, V> doExecuteMultigetSlice(final Iterable<K> keys, final HSlicePredicate<N> workingSlicePredicate, final ColumnFamilyRowMapper<K, N, V> mapper) { return new MappedColumnFamilyResultWrapper<K,N,V>(keySerializer, topSerializer, multigetSliceInternal(keys, workingSlicePredicate), mapper); } protected <V> ColumnFamilyResult<K, N> doExecuteIndexedSlices(final IndexedSlicesPredicate<K, N, V> predicate) { return new ColumnFamilyResultWrapper<K, N>(keySerializer, topSerializer, indexedSlicesInternal(predicate, activeSlicePredicate)); } protected <V> ColumnFamilyResult<K, N> doExecuteIndexedSlices(IndexedSlicesPredicate<K, N, V> predicate, HSlicePredicate<N> slicePredicate) { return new ColumnFamilyResultWrapper<K, N>(keySerializer, topSerializer, indexedSlicesInternal(predicate, slicePredicate)); } protected <R,V> MappedColumnFamilyResult<K, N, R> doExecuteIndexedSlices( IndexedSlicesPredicate<K, N, V> predicate, ColumnFamilyRowMapper<K, N, R> mapper) { return new MappedColumnFamilyResultWrapper<K,N,R>(keySerializer, topSerializer, indexedSlicesInternal(predicate, activeSlicePredicate), mapper); } protected <R, V> MappedColumnFamilyResult<K, N, R> doExecuteIndexedSlices(IndexedSlicesPredicate<K, N, V> predicate, HSlicePredicate<N> slicePredicate, ColumnFamilyRowMapper<K, N, R> mapper) { return new MappedColumnFamilyResultWrapper<K,N,R>(keySerializer, topSerializer, indexedSlicesInternal(predicate, slicePredicate), mapper); } private ExecutionResult<Map<ByteBuffer, List<ColumnOrSuperColumn>>> sliceInternal(final K key, final HSlicePredicate<N> workingSlicePredicate) { return ((ExecutingKeyspace)keyspace).doExecuteOperation(new Operation<Map<ByteBuffer,List<ColumnOrSuperColumn>>>(OperationType.READ) { @Override public Map<ByteBuffer,List<ColumnOrSuperColumn>> execute(Cassandra.Client cassandra) throws HectorException { Map<ByteBuffer,List<ColumnOrSuperColumn>> cosc = new LinkedHashMap<ByteBuffer, List<ColumnOrSuperColumn>>(); try { ByteBuffer sKey = keySerializer.toByteBuffer(key); cosc.put(sKey, cassandra.get_slice(sKey, columnParent, workingSlicePredicate.toThrift(), ThriftConverter.consistencyLevel(consistencyLevelPolicy.get(operationType, columnFamily)))); } catch (Exception e) { throw exceptionsTranslator.translate(e); } return cosc; } }); } private ExecutionResult<Map<ByteBuffer, List<ColumnOrSuperColumn>>> multigetSliceInternal(final Iterable<K> keys, final HSlicePredicate<N> workingSlicePredicate) { return ((ExecutingKeyspace)keyspace).doExecuteOperation(new Operation<Map<ByteBuffer,List<ColumnOrSuperColumn>>>(OperationType.READ) { @Override public Map<ByteBuffer,List<ColumnOrSuperColumn>> execute(Cassandra.Client cassandra) throws HectorException { try { List<K> keyList = new ArrayList<K>(); Iterators.addAll(keyList, keys.iterator()); return cassandra.multiget_slice(keySerializer.toBytesList(keyList), columnParent, (workingSlicePredicate == null ? activeSlicePredicate.setColumnNames(columnValueSerializers.keySet()).toThrift() : workingSlicePredicate.toThrift()), ThriftConverter.consistencyLevel(consistencyLevelPolicy.get(operationType, columnFamily))); } catch (Exception e) { throw exceptionsTranslator.translate(e); } } }); } private <V> ExecutionResult<Map<ByteBuffer, List<ColumnOrSuperColumn>>> indexedSlicesInternal( final IndexedSlicesPredicate<K, N, V> predicate, final HSlicePredicate<N> workingSlicePredicate) { return ((ExecutingKeyspace)keyspace).doExecuteOperation(new Operation<Map<ByteBuffer,List<ColumnOrSuperColumn>>>(OperationType.READ) { @Override public Map<ByteBuffer, List<ColumnOrSuperColumn>> execute(Client cassandra) throws HectorException { try { List<KeySlice> keySlices = cassandra.get_indexed_slices( columnParent, predicate.toThrift(), workingSlicePredicate.toThrift(), ThriftConverter.consistencyLevel(consistencyLevelPolicy.get(operationType, columnFamily))); if (keySlices == null || keySlices.isEmpty()) { return new LinkedHashMap<ByteBuffer, List<ColumnOrSuperColumn>>(0); } LinkedHashMap<ByteBuffer, List<ColumnOrSuperColumn>> ret = new LinkedHashMap<ByteBuffer, List<ColumnOrSuperColumn>>(keySlices.size()); for (KeySlice keySlice : keySlices) { ret.put(ByteBuffer.wrap(keySlice.getKey()), keySlice.getColumns()); } return ret; } catch (Exception e) { throw exceptionsTranslator.translate(e); } } }); } }