keyS
/*
* (non-Javadoc)
- *
+ *
* @see java.io.OutputStream#write(int)
*/
public void write(int b) throws IOException {
@@ -64,7 +64,7 @@ public void flush() throws IOException {
/**
* Write the data to column if the configured chunk size is reached or if the
* stream should be closed
- *
+ *
* @param close
* @throws IOException
*/
diff --git a/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourceFactory.java b/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourceFactory.java
index 3f838abb1..2f70cbbc1 100644
--- a/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourceFactory.java
+++ b/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourceFactory.java
@@ -8,29 +8,50 @@
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
+import org.apache.commons.lang.BooleanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import me.prettyprint.cassandra.service.CassandraHostConfigurator;
+import me.prettyprint.hector.api.Cluster;
+import me.prettyprint.hector.api.Keyspace;
+import me.prettyprint.hector.api.factory.HFactory;
+
/**
* A factory for JNDI Resource managed objects. Responsible for creating a
- * {@link CassandraClientJndiResourcePool}. Relies on a supplied URL and
- * port which Cassandra is listening on. These parameters are defined in
- * a web application's context.xml file. For example:
+ * {@link Keyspace} references for passing to {@link HFactory}.
+ * A limited set of configuration parameters are supported.
+ * These parameters are defined in a web application's context.xml file.
+ * Parameter descriptions can be found in {@link CassandraHostConfigurator}
*
*
*
*
+ * hosts="cass1:9160,cass2:9160,cass3:9160"
+ * keyspace="Keyspace1"
+ * clusterName="Test Cluster"
+ * maxActive="20"
+ * maxWaitTimeWhenExhausted="10"
+ * autoDiscoverHosts="true"
+ * runAutoDiscoveryAtStartup="true"/>
*
*
* @author Perry Hoekstra (dutchman_mn@charter.net)
+ * @author zznate
*
* @since 0.5.1-8
*/
-public class CassandraClientJndiResourceFactory implements ObjectFactory
-{
+public class CassandraClientJndiResourceFactory implements ObjectFactory {
+ private Logger log = LoggerFactory.getLogger(CassandraClientJndiResourceFactory.class);
+
+ private CassandraHostConfigurator cassandraHostConfigurator;
+ private Cluster cluster;
+ private Keyspace keyspace;
+
/**
* Creates an object using the location or reference information specified.
*
@@ -57,16 +78,53 @@ public Object getObjectInstance(Object object, Name jndiName, Context context,
throw new Exception("Object provided is not a javax.naming.Reference type");
}
- RefAddr urlRefAddr = resourceRef.get("url");
-
- RefAddr portRefAddr = resourceRef.get("port");
+ // config CassandraHostConfigurator
+ if ( cluster == null ) {
+ configure(resourceRef);
+ }
+
+ return keyspace;
+ }
- if ((urlRefAddr != null) && (portRefAddr != null)) {
- return new CassandraClientJndiResourcePool((String)urlRefAddr.getContent(),
- Integer.parseInt((String)portRefAddr.getContent()));
- } else {
+ private void configure(Reference resourceRef) throws Exception {
+ // required
+ RefAddr hostsRefAddr = resourceRef.get("hosts");
+ RefAddr clusterNameRef = resourceRef.get("clusterName");
+ RefAddr keyspaceNameRef = resourceRef.get("keyspace");
+ // optional
+ RefAddr maxActiveRefAddr = resourceRef.get("maxActive");
+ RefAddr maxWaitTimeWhenExhausted = resourceRef.get("maxWaitTimeWhenExhausted");
+ RefAddr autoDiscoverHosts = resourceRef.get("autoDiscoverHosts");
+ RefAddr runAutoDiscoverAtStartup = resourceRef.get("runAutoDiscoveryAtStartup");
+ RefAddr retryDownedHostDelayInSeconds = resourceRef.get("retryDownedHostDelayInSeconds");
+
+ if ( hostsRefAddr == null || hostsRefAddr.getContent() == null) {
throw new Exception("A url and port on which Cassandra is installed and listening " +
- "on must be provided as a ResourceParams in the context.xml");
+ "on must be provided as a ResourceParams in the context.xml");
+ }
+
+ cassandraHostConfigurator = new CassandraHostConfigurator((String)hostsRefAddr.getContent());
+ if ( autoDiscoverHosts != null ) {
+ cassandraHostConfigurator.setAutoDiscoverHosts(Boolean.parseBoolean((String)autoDiscoverHosts.getContent()));
+ if ( runAutoDiscoverAtStartup != null )
+ cassandraHostConfigurator.setRunAutoDiscoveryAtStartup(Boolean.parseBoolean((String)autoDiscoverHosts.getContent()));
+ }
+ if ( retryDownedHostDelayInSeconds != null ) {
+ int retryDelay = Integer.parseInt((String)retryDownedHostDelayInSeconds.getContent());
+ // disable retry if less than 1
+ if ( retryDelay < 1 )
+ cassandraHostConfigurator.setRetryDownedHosts(false);
+ cassandraHostConfigurator.setRetryDownedHostsDelayInSeconds(retryDelay);
}
+ if ( maxActiveRefAddr != null )
+ cassandraHostConfigurator.setMaxActive(Integer.parseInt((String)maxActiveRefAddr.getContent()));
+ if ( maxWaitTimeWhenExhausted != null )
+ cassandraHostConfigurator.setMaxWaitTimeWhenExhausted(Integer.parseInt((String)maxWaitTimeWhenExhausted.getContent()));
+
+ if ( log.isDebugEnabled() )
+ log.debug("JNDI resource created with CassandraHostConfiguration: {}", cassandraHostConfigurator.getAutoDiscoverHosts());
+
+ cluster = HFactory.createCluster((String)clusterNameRef.getContent(), cassandraHostConfigurator);
+ keyspace = HFactory.createKeyspace((String)keyspaceNameRef.getContent(), cluster);
}
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourcePool.java b/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourcePool.java
index 36c6f2f11..e044c437d 100644
--- a/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourcePool.java
+++ b/core/src/main/java/me/prettyprint/cassandra/jndi/CassandraClientJndiResourcePool.java
@@ -9,20 +9,20 @@
* as Apache Tomcat.
*
* @see GenericObjectPool
- *
+ *
* @author Perry Hoekstra (dutchman_mn@charter.net)
*
*/
public class CassandraClientJndiResourcePool extends GenericObjectPool {
/**
* CassandraClientJndiResourcePool constructor.
- *
+ *
* @param url url of the host that contains Cassandra.
* @param port port number that Cassandra is listening on.
*/
-
+
public CassandraClientJndiResourcePool(String url, int port) {
// TODO fix this
- //super(new JndiCassandraClientFactory(url, port));
+ //super(new JndiCassandraClientFactory(url, port));
}
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/AbstractBasicQuery.java b/core/src/main/java/me/prettyprint/cassandra/model/AbstractBasicQuery.java
new file mode 100644
index 000000000..eff40fd53
--- /dev/null
+++ b/core/src/main/java/me/prettyprint/cassandra/model/AbstractBasicQuery.java
@@ -0,0 +1,55 @@
+package me.prettyprint.cassandra.model;
+
+import me.prettyprint.cassandra.utils.Assert;
+import me.prettyprint.hector.api.Keyspace;
+import me.prettyprint.hector.api.Serializer;
+import me.prettyprint.hector.api.query.Query;
+
+/**
+ *
+ * @author patricioe (Patricio Echague - patricio@datastax.com)
+ *
+ * @param Key type
+ * @param column name type
+ * @param return type
+ */
+public abstract class AbstractBasicQuery implements Query {
+
+ protected final ExecutingKeyspace keyspace;
+ protected String columnFamilyName;
+ protected Serializer keySerializer;
+ protected Serializer columnNameSerializer;
+ // add: FailoverPolicy, ConsistencyLevelPolicy, Credentials?
+
+ protected AbstractBasicQuery(Keyspace k, Serializer keySerializer,
+ Serializer nameSerializer) {
+ Assert.noneNull(k, keySerializer, nameSerializer);
+ keyspace = (ExecutingKeyspace) k;
+ this.keySerializer = keySerializer;
+ this.columnNameSerializer = nameSerializer;
+ }
+
+ public Query setColumnFamily(String cf) {
+ this.columnFamilyName = cf;
+ return this;
+ }
+
+ public Serializer getKeySerializer() {
+ return keySerializer;
+ }
+
+ public AbstractBasicQuery setKeySerializer(Serializer keySerializer) {
+ this.keySerializer = keySerializer;
+ return this;
+ }
+
+ public Serializer getColumnNameSerializer() {
+ return columnNameSerializer;
+ }
+
+ public AbstractBasicQuery setColumnNameSerializer(Serializer columnNameSerializer) {
+ this.columnNameSerializer = columnNameSerializer;
+ return this;
+ }
+
+}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/AbstractQuery.java b/core/src/main/java/me/prettyprint/cassandra/model/AbstractQuery.java
index b57fe0e7f..1566cbaf0 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/AbstractQuery.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/AbstractQuery.java
@@ -5,47 +5,18 @@
import me.prettyprint.hector.api.Serializer;
import me.prettyprint.hector.api.query.Query;
-public abstract class AbstractQuery implements Query {
+public abstract class AbstractQuery extends AbstractBasicQuery implements Query {
- protected final ExecutingKeyspace keyspace;
- protected String columnFamilyName;
- protected Serializer keySerializer;
- protected Serializer columnNameSerializer;
protected Serializer valueSerializer;
// add: FailoverPolicy, ConsistencyLevelPolicy, Credentials?
/*package*/ AbstractQuery(Keyspace k, Serializer keySerializer,
Serializer nameSerializer, Serializer valueSerializer) {
- Assert.noneNull(k, keySerializer, nameSerializer, valueSerializer);
- keyspace = (ExecutingKeyspace) k;
- this.keySerializer = keySerializer;
- this.columnNameSerializer = nameSerializer;
+ super(k, keySerializer, nameSerializer);
+ Assert.noneNull(valueSerializer);
this.valueSerializer = valueSerializer;
}
- public Query setColumnFamily(String cf) {
- this.columnFamilyName = cf;
- return this;
- }
-
- public Serializer getKeySerializer() {
- return keySerializer;
- }
-
- public AbstractQuery setKeySerializer(Serializer keySerializer) {
- this.keySerializer = keySerializer;
- return this;
- }
-
- public Serializer getColumnNameSerializer() {
- return columnNameSerializer;
- }
-
- public AbstractQuery setColumnNameSerializer(Serializer columnNameSerializer) {
- this.columnNameSerializer = columnNameSerializer;
- return this;
- }
-
public Serializer getValueSerializer() {
return valueSerializer;
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/AbstractSliceQuery.java b/core/src/main/java/me/prettyprint/cassandra/model/AbstractSliceQuery.java
index 9370982f1..c97f70d51 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/AbstractSliceQuery.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/AbstractSliceQuery.java
@@ -50,7 +50,7 @@ public Query setColumnNames(Collection columnNames) {
}
return this;
}
-
+
/**
* Wraps the underlying call to {@link HSlicePredicate#setKeysOnlyPredicate()}
* Use this for a substantial performance increase when you only need the keys returned
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/AbstractSubColumnQuery.java b/core/src/main/java/me/prettyprint/cassandra/model/AbstractSubColumnQuery.java
index 8c8bcb04a..84cabeaca 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/AbstractSubColumnQuery.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/AbstractSubColumnQuery.java
@@ -64,6 +64,6 @@ public QueryResult> execute() {
List> columns = slice.getColumns();
HColumn column = columns.size() == 0 ? null : columns.get(0);
return new QueryResultImpl>(
- new ExecutionResult>(column, r.getExecutionTimeMicro(), r.getHostUsed()), this);
+ new ExecutionResult>(column, r.getExecutionTimeNano(), r.getHostUsed()), this);
}
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/BasicColumnFamilyDefinition.java b/core/src/main/java/me/prettyprint/cassandra/model/BasicColumnFamilyDefinition.java
index 96527b38e..f4bbc6f44 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/BasicColumnFamilyDefinition.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/BasicColumnFamilyDefinition.java
@@ -25,10 +25,12 @@ public class BasicColumnFamilyDefinition implements ColumnFamilyDefinition {
private double readRepairChance;
private int gcGraceSeconds;
private String defaultValidationClass;
+ private String keyValidationClass;
private int id;
private int maxCompactionThreshold;
private int minCompactionThreshold;
private int rowCacheSavePeriodInSeconds;
+ private int keyCacheSavePeriodInSeconds;
private double memtableOperationsInMillions;
private int memtableThroughputInMb;
private int memtableFlushAfterMins;
@@ -39,7 +41,7 @@ public class BasicColumnFamilyDefinition implements ColumnFamilyDefinition {
public BasicColumnFamilyDefinition() {
this.columnDefinitions = new ArrayList();
}
-
+
/**
* Builds a {@link BasicColumnFamilyDefinition} based off the interface
*/
@@ -53,9 +55,10 @@ public BasicColumnFamilyDefinition(ColumnFamilyDefinition columnFamilyDefinition
rowCacheSize = columnFamilyDefinition.getRowCacheSize();
rowCacheSavePeriodInSeconds = columnFamilyDefinition.getRowCacheSavePeriodInSeconds();
keyCacheSize = columnFamilyDefinition.getKeyCacheSize();
+ keyCacheSavePeriodInSeconds = columnFamilyDefinition.getKeyCacheSavePeriodInSeconds();
readRepairChance = columnFamilyDefinition.getReadRepairChance();
- columnDefinitions = columnFamilyDefinition.getColumnMetadata() != null
- ? new ArrayList(columnFamilyDefinition.getColumnMetadata())
+ columnDefinitions = columnFamilyDefinition.getColumnMetadata() != null
+ ? new ArrayList(columnFamilyDefinition.getColumnMetadata())
: new ArrayList();
gcGraceSeconds = columnFamilyDefinition.getGcGraceSeconds();
defaultValidationClass = columnFamilyDefinition.getDefaultValidationClass();
@@ -121,7 +124,7 @@ public void setMaxCompactionThreshold(int maxCompactionThreshold) {
public void setMinCompactionThreshold(int minCompactionThreshold) {
this.minCompactionThreshold = minCompactionThreshold;
- }
+ }
public void setRowCacheSavePeriodInSeconds(int rowCacheSavePeriodInSeconds) {
this.rowCacheSavePeriodInSeconds = rowCacheSavePeriodInSeconds;
@@ -143,6 +146,14 @@ public void addColumnDefinition( ColumnDefinition columnDefinition){
this.columnDefinitions.add( columnDefinition );
}
+ public void setKeyCacheSavePeriodInSeconds(int keyCacheSavePeriodInSeconds) {
+ this.keyCacheSavePeriodInSeconds = keyCacheSavePeriodInSeconds;
+ }
+
+ public void setKeyValidationClass(String keyValidationClass){
+ this.keyValidationClass = keyValidationClass;
+ }
+
/**
* SHOULD THIS BE HERE? A COLUMN DEFINITION IS PART OF A KEYSPACE BY VIRTUE
* OF BEING IN A KEYSPACE LIST
@@ -242,5 +253,13 @@ public int getMemtableThroughputInMb() {
return this.memtableThroughputInMb;
}
+ public int getKeyCacheSavePeriodInSeconds() {
+ return keyCacheSavePeriodInSeconds;
+ }
+
+ @Override
+ public String getKeyValidationClass() {
+ return keyValidationClass;
+ }
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/CounterSliceImpl.java b/core/src/main/java/me/prettyprint/cassandra/model/CounterSliceImpl.java
new file mode 100644
index 000000000..6f648699c
--- /dev/null
+++ b/core/src/main/java/me/prettyprint/cassandra/model/CounterSliceImpl.java
@@ -0,0 +1,51 @@
+package me.prettyprint.cassandra.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import me.prettyprint.cassandra.utils.Assert;
+import me.prettyprint.hector.api.Serializer;
+import me.prettyprint.hector.api.beans.CounterSlice;
+import me.prettyprint.hector.api.beans.HCounterColumn;
+
+import org.apache.cassandra.thrift.CounterColumn;
+
+public final class CounterSliceImpl implements CounterSlice {
+
+ private final Map> columnsMap;
+ private final List> columnsList;
+
+ public CounterSliceImpl(List tColumns, Serializer nameSerializer) {
+
+ Assert.noneNull(tColumns, nameSerializer);
+ columnsMap = new HashMap>(tColumns.size());
+ List> list = new ArrayList>(tColumns.size());
+ for (CounterColumn c: tColumns) {
+ HCounterColumn column = new HCounterColumnImpl(c, nameSerializer);
+ columnsMap.put(column.getName(), column);
+ list.add(column);
+ }
+ columnsList = list;
+ }
+
+ /**
+ *
+ * @return an unmodifiable list of the columns
+ */
+ @Override
+ public List> getColumns() {
+ return columnsList;
+ }
+
+ @Override
+ public HCounterColumn getColumnByName(N columnName) {
+ return columnsMap.get(columnName);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ColumnSlice(%s)", columnsList.toString());
+ }
+}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/CqlQuery.java b/core/src/main/java/me/prettyprint/cassandra/model/CqlQuery.java
new file mode 100644
index 000000000..821286ea0
--- /dev/null
+++ b/core/src/main/java/me/prettyprint/cassandra/model/CqlQuery.java
@@ -0,0 +1,135 @@
+package me.prettyprint.cassandra.model;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import me.prettyprint.cassandra.serializers.StringSerializer;
+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 me.prettyprint.hector.api.query.QueryResult;
+
+import org.apache.cassandra.thrift.Column;
+import org.apache.cassandra.thrift.Compression;
+import org.apache.cassandra.thrift.CqlResult;
+import org.apache.cassandra.thrift.CqlRow;
+import org.apache.cassandra.thrift.Cassandra.Client;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * First cut at a CQL implementation. Not too much time has been spent here
+ * as this API is currently a moving target. We have a lot of experience with
+ * these hijinks by the Apache Cassandra team, so it was deemed prudent to do
+ * something simple initially until the dust settles.
+ *
+ * You are expected to know what you are getting into if you plan on using
+ * CQL queries in your application. Spend some time looking through the
+ * unit tests here in Hector and the Cassandra source tree. For a number of
+ * detailed examples, see test_cql.py in the test/system folder of the
+ * Apache Cassandra source distribution.
+ *
+ * Note: if you immediately get an exception such as:
+ * "InvalidRequestException(why:cannot parse 'foo' as hex bytes)"
+ * It means one of two things:
+ *
+ * - you have not formatted your query correct
+ * - You have not configured the correct validators on your column family
+ *
+ *
+ * In both cases, even though the query is most likely a string, it is up to you to format
+ * this query according to the comparator (used for the column name), key validator
+ * and value validator. This can be a little confusing as only the comparator is required.
+ * The other two default to BytesType.
+ *
+ * See the docs on {@link CqlRows} for additional details.
+ *
+ * @author zznate
+ *
+ */
+public class CqlQuery extends AbstractBasicQuery> {
+ private static Logger log = LoggerFactory.getLogger(CqlQuery.class);
+
+ private Serializer valueSerializer;
+ private ByteBuffer query;
+ private boolean useCompression;
+
+ public CqlQuery(Keyspace k, Serializer keySerializer,
+ Serializer nameSerializer, Serializer valueSerializer) {
+ super(k, keySerializer, nameSerializer);
+ this.valueSerializer = valueSerializer;
+ }
+
+ /**
+ * Set the query as a String. Here for convienience. See above for some
+ * caveats. Calls {@link StringSerializer#toByteBuffer(String)} directly.
+ * @param query
+ * @return
+ */
+ public CqlQuery setQuery(String query) {
+ this.query = StringSerializer.get().toByteBuffer(query);
+ return this;
+ }
+
+ public CqlQuery setQuery(ByteBuffer qeury) {
+ this.query = query;
+ return this;
+ }
+
+ public CqlQuery useCompression() {
+ useCompression = true;
+ return this;
+ }
+
+
+ @Override
+ public QueryResult> execute() {
+
+ return new QueryResultImpl>(
+ keyspace.doExecuteOperation(new Operation>(OperationType.READ) {
+
+ @Override
+ public CqlRows execute(Client cassandra) throws HectorException {
+ CqlRows rows = null;
+ try {
+ CqlResult result = cassandra.execute_cql_query(query,
+ useCompression ? Compression.GZIP : Compression.NONE);
+ if ( log.isDebugEnabled() ) {
+ log.debug("Found CqlResult: {}", result);
+ }
+ switch (result.getType()) {
+ case INT:
+ rows = new CqlRows(result.getNum());
+ break;
+ case VOID:
+ rows = new CqlRows();
+ break;
+
+ default:
+ if ( result.getRowsSize() > 0 ) {
+ LinkedHashMap> ret = new LinkedHashMap>(result.getRowsSize());
+
+ for (Iterator rowsIter = result.getRowsIterator(); rowsIter.hasNext(); ) {
+ CqlRow row = rowsIter.next();
+ ret.put(ByteBuffer.wrap(row.getKey()), row.getColumns());
+ }
+ Map> thriftRet = keySerializer.fromBytesMap(ret);
+ rows = new CqlRows((LinkedHashMap>)thriftRet, columnNameSerializer, valueSerializer);
+ }
+ break;
+ }
+ } catch (Exception ex) {
+ throw keyspace.getExceptionsTranslator().translate(ex);
+ }
+ return rows;
+ }
+
+ }), this);
+ }
+
+}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/CqlRows.java b/core/src/main/java/me/prettyprint/cassandra/model/CqlRows.java
new file mode 100644
index 000000000..a3fc58a12
--- /dev/null
+++ b/core/src/main/java/me/prettyprint/cassandra/model/CqlRows.java
@@ -0,0 +1,65 @@
+package me.prettyprint.cassandra.model;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import me.prettyprint.hector.api.Serializer;
+
+import org.apache.cassandra.thrift.Column;
+import org.apache.cassandra.thrift.CqlResultType;
+
+/**
+ * Row wrapper specific to the multi-type results capable from a CqlQuery.
+ * This is a bit more convoluted than I would like, put most of this API
+ * is still moving around, so we will stick with the overloading for now.
+ *
+ * @author zznate
+ */
+public final class CqlRows extends OrderedRowsImpl {
+
+ private final CqlResultType resultType;
+ private int count;
+
+ /**
+ * Constructed for {@link CqlResultType#ROWS}
+ * @param thriftRet
+ * @param nameSerializer
+ * @param valueSerializer
+ * @param resultType
+ */
+ public CqlRows(LinkedHashMap> thriftRet,
+ Serializer nameSerializer, Serializer valueSerializer) {
+ super(thriftRet, nameSerializer, valueSerializer);
+ this.resultType = CqlResultType.ROWS;
+ }
+
+ /**
+ * Constructed with only a count for {@link CqlResultType#INT}
+ * @param count
+ */
+ public CqlRows(int count) {
+ super();
+ this.resultType = CqlResultType.INT;
+ this.count = count;
+ }
+
+ /**
+ * Constructed as empty for {@link CqlResultType#VOID}
+ */
+ public CqlRows() {
+ super();
+ this.resultType = CqlResultType.VOID;
+ }
+
+ /**
+ * Will throw an IllegalArgumentException if called on a query that was not
+ * {@link CqlResultType#INT}
+ * @return
+ */
+ public int getAsCount() {
+ if ( !resultType.equals(CqlResultType.INT))
+ throw new IllegalArgumentException("Attempted to extract count from the wrong type of CQL query: " + resultType.toString());
+ return count;
+ }
+
+}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/ExecutingKeyspace.java b/core/src/main/java/me/prettyprint/cassandra/model/ExecutingKeyspace.java
index 4707eb1ae..1d2c32938 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/ExecutingKeyspace.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/ExecutingKeyspace.java
@@ -17,7 +17,7 @@
/**
* Thread Safe
- *
+ *
* @author Ran Tavory
* @author zznate
*/
@@ -59,8 +59,8 @@ public ExecutingKeyspace(String keyspace,
public void setConsistencyLevelPolicy(ConsistencyLevelPolicy cp) {
// TODO remove this method
consistencyLevelPolicy = cp;
- }
-
+ }
+
@Override
public String getKeyspaceName() {
return keyspace;
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/ExecutionResult.java b/core/src/main/java/me/prettyprint/cassandra/model/ExecutionResult.java
index d193bf38d..62a43519c 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/ExecutionResult.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/ExecutionResult.java
@@ -1,6 +1,7 @@
package me.prettyprint.cassandra.model;
import me.prettyprint.cassandra.service.CassandraHost;
+import me.prettyprint.hector.api.ResultStatus;
/**
@@ -11,12 +12,12 @@
* @author Ran
* @author zznate
*/
-public class ExecutionResult {
+public class ExecutionResult implements ResultStatus {
private final T value;
private final long execTime;
private final CassandraHost cassandraHost;
-
+
protected static final String BASE_MSG_FORMAT = "%s took (%dus) for query (%s) on host: %s";
private static final int MICRO_DENOM = 1000;
@@ -35,7 +36,14 @@ public T get() {
}
/**
- * Execution time is actually recorded in nanos, so we divide this by 1000
+ * @return the execution time, as already recorded, in nanos
+ */
+ public long getExecutionTimeNano() {
+ return execTime;
+ }
+
+ /**
+ * Execution time is actually recorded in nanos, so we divide this by 1000
* make the number more sensible
* @return
*/
@@ -43,11 +51,12 @@ public long getExecutionTimeMicro() {
return execTime / MICRO_DENOM;
}
+
@Override
public String toString() {
return formatMessage("ExecutionResult", "n/a");
}
-
+
protected String formatMessage(String resultName, String query) {
return String.format(BASE_MSG_FORMAT, resultName, getExecutionTimeMicro(), query, (cassandraHost != null ? cassandraHost.getName() : "[none]"));
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/HColumnImpl.java b/core/src/main/java/me/prettyprint/cassandra/model/HColumnImpl.java
index 9c0e7cb5f..048069e01 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/HColumnImpl.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/HColumnImpl.java
@@ -33,8 +33,15 @@ public HColumnImpl(N name, V value, long clock, Serializer nameSerializer,
notNull(name, "name is null");
notNull(value, "value is null");
- this.column = new Column(nameSerializer.toByteBuffer(name),
- valueSerializer.toByteBuffer(value), clock);
+ this.column = new Column(nameSerializer.toByteBuffer(name));
+ this.column.setValue(valueSerializer.toByteBuffer(value));
+ this.column.setTimestamp(clock);
+ }
+
+ public HColumnImpl(N name, V value, long clock, int ttl,
+ Serializer nameSerializer, Serializer valueSerializer) {
+ this(name, value, clock, nameSerializer, valueSerializer);
+ setTtl(ttl);
}
public HColumnImpl(Column thriftColumn, Serializer nameSerializer,
@@ -60,14 +67,14 @@ public HColumnImpl(N name, V value, long clock) {
@Override
public HColumn setName(N name) {
notNull(name, "name is null");
- this.column.name = nameSerializer.toByteBuffer(name);
+ this.column.setName(nameSerializer.toByteBuffer(name));
return this;
}
@Override
public HColumn setValue(V value) {
notNull(value, "value is null");
- this.column.value = valueSerializer.toByteBuffer(value);
+ this.column.setValue(valueSerializer.toByteBuffer(value));
return this;
}
@@ -78,7 +85,7 @@ public HColumn setClock(long clock) {
}
/**
- * Set the time-to-live value for this column in seconds.
+ * Set the time-to-live value for this column in seconds.
* The server will mark this column as deleted once the number of seconds has elapsed.
*/
@Override
@@ -94,20 +101,14 @@ public int getTtl() {
@Override
public N getName() {
- if ( column.name == null ) {
- return null;
- }
- return nameSerializer.fromByteBuffer(column.name.duplicate());
+ return column.isSetName() ? nameSerializer.fromByteBuffer(column.name.duplicate()) : null;
}
@Override
- public V getValue() {
- if ( column.value == null ) {
- return null;
- }
- return valueSerializer.fromByteBuffer(column.value.duplicate());
- }
-
+ public V getValue() {
+ return column.isSetValue() ? valueSerializer.fromByteBuffer(column.value.duplicate()) : null;
+ }
+
@Override
public long getClock() {
@@ -134,25 +135,35 @@ public Serializer getValueSerializer() {
return valueSerializer;
}
-
+ @Override
+ public ByteBuffer getNameBytes() {
+ return column.isSetName() ? column.name.duplicate() : null;
+ }
+
+ @Override
+ public ByteBuffer getValueBytes() {
+ return column.isSetValue() ? column.value.duplicate() : null;
+ }
+
/**
* Clear value, timestamp and ttl (the latter two set to '0') leaving only the column name
*/
@Override
- public HColumn clear() {
+ public HColumn clear() {
column.value = null;
column.timestamp = 0;
column.ttl = 0;
column.setTimestampIsSet(false);
column.setTtlIsSet(false);
+ column.setValueIsSet(false);
return this;
}
-
-
+
+
@Override
public HColumn apply(V value, long clock, int ttl) {
- column.value = valueSerializer.toByteBuffer(value);
+ setValue(value);
column.setTimestamp(clock);
column.setTtl(ttl);
return this;
@@ -162,7 +173,7 @@ public HColumn apply(Column c) {
this.column = c;
return this;
}
-
+
@Override
public String toString() {
return String.format("HColumn(%s=%s)",getName(), getValue());
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/HCounterColumnImpl.java b/core/src/main/java/me/prettyprint/cassandra/model/HCounterColumnImpl.java
new file mode 100644
index 000000000..db833b5f3
--- /dev/null
+++ b/core/src/main/java/me/prettyprint/cassandra/model/HCounterColumnImpl.java
@@ -0,0 +1,165 @@
+package me.prettyprint.cassandra.model;
+
+import static me.prettyprint.cassandra.utils.Assert.notNull;
+
+import java.nio.ByteBuffer;
+
+import me.prettyprint.cassandra.serializers.SerializerTypeInferer;
+import me.prettyprint.hector.api.Serializer;
+import me.prettyprint.hector.api.beans.HColumn;
+import me.prettyprint.hector.api.beans.HCounterColumn;
+
+import org.apache.cassandra.thrift.Column;
+import org.apache.cassandra.thrift.CounterColumn;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+/**
+ * Hector Counter Column definition.
+ *
+ * @param The type of the column name
+ *
+ * @author patricioe (patricioe@gmail.com)
+ */
+public final class HCounterColumnImpl implements HCounterColumn {
+
+ private CounterColumn counterColumn;
+ private Serializer nameSerializer;
+
+
+ public HCounterColumnImpl(N name, Long value, Serializer nameSerializer) {
+ this(nameSerializer);
+ notNull(name, "name is null");
+ notNull(value, "value is null");
+ this.counterColumn = new CounterColumn(nameSerializer.toByteBuffer(name), value);
+ }
+
+ public HCounterColumnImpl(CounterColumn thriftCounterColumn, Serializer nameSerializer) {
+ this(nameSerializer);
+ notNull(thriftCounterColumn, "thriftColumn is null");
+ this.counterColumn = thriftCounterColumn;
+ }
+
+ public HCounterColumnImpl(Serializer nameSerializer) {
+ notNull(nameSerializer, "nameSerializer is null");
+ this.nameSerializer = nameSerializer;
+ this.counterColumn = new CounterColumn();
+ }
+
+ public HCounterColumnImpl(N name, Long value) {
+ this(name, value, SerializerTypeInferer.getSerializer(name));
+ }
+
+ @Override
+ public HCounterColumn setName(N name) {
+ notNull(name, "name is null");
+ this.counterColumn.setName(nameSerializer.toByteBuffer(name));
+ return this;
+ }
+
+ @Override
+ public HCounterColumn setValue(Long value) {
+ notNull(value, "value is null");
+ this.counterColumn.setValue(value);
+ return this;
+ }
+
+ /**
+ * Set the time-to-live value for this column in seconds.
+ * The server will mark this column as deleted once the number of seconds has elapsed.
+ */
+ @Override
+ public HCounterColumn setTtl(int ttl) {
+ //this.counterColumn.setTtl(ttl);
+ // TODO (patricioe) Pending on Cassandra trunk
+ return this;
+ }
+
+ @Override
+ public int getTtl() {
+ //return this.counterColumn.ttl;
+ // TODO (patricioe) Pending on Cassandra trunk
+ return Integer.MAX_VALUE;
+ }
+
+ @Override
+ public N getName() {
+ return counterColumn.isSetName() ? nameSerializer.fromByteBuffer(counterColumn.name.duplicate()) : null;
+ }
+
+ @Override
+ public Long getValue() {
+ return counterColumn.value;
+ }
+
+ public CounterColumn toThrift() {
+ return counterColumn;
+ }
+
+ public HCounterColumn fromThrift(CounterColumn c) {
+ notNull(c, "column is null");
+ this.counterColumn = c;
+ return this;
+ }
+
+ @Override
+ public Serializer getNameSerializer() {
+ return nameSerializer;
+ }
+
+ @Override
+ public ByteBuffer getNameBytes() {
+ return counterColumn.isSetName() ? counterColumn.name.duplicate() : null;
+ }
+
+ /**
+ * Clear value, timestamp and ttl (the latter two set to '0') leaving only the column name
+ */
+ @Override
+ public HCounterColumn clear() {
+ counterColumn.value = 0; // TODO (patricioe) Is this ok?
+ //counterColumn.ttl = 0; TODO (patricioe) pending on trunk
+ //counterColumn.setTtlIsSet(false);
+ counterColumn.setValueIsSet(false);
+ return this;
+ }
+
+ @Override
+ public HCounterColumn apply(Long value, int ttl) {
+ setValue(value);
+ //counterColumn.setTtl(ttl);
+ return this;
+ }
+
+ public HCounterColumn apply(CounterColumn c) {
+ this.counterColumn = c;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("HCounterColumn(%s=%s)",getName(), getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder().append(getName()).append(getValue()).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ HCounterColumnImpl other = (HCounterColumnImpl) obj;
+ return new EqualsBuilder().appendSuper(super.equals(obj)).append(getName(), other.getName()).
+ append(getValue(), other.getValue()).isEquals();
+ }
+}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/HCounterSuperColumnImpl.java b/core/src/main/java/me/prettyprint/cassandra/model/HCounterSuperColumnImpl.java
new file mode 100644
index 000000000..9e8a411e6
--- /dev/null
+++ b/core/src/main/java/me/prettyprint/cassandra/model/HCounterSuperColumnImpl.java
@@ -0,0 +1,147 @@
+package me.prettyprint.cassandra.model;
+
+import static me.prettyprint.cassandra.utils.Assert.noneNull;
+import static me.prettyprint.cassandra.utils.Assert.notNull;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import me.prettyprint.hector.api.Serializer;
+import me.prettyprint.hector.api.beans.HCounterColumn;
+import me.prettyprint.hector.api.beans.HCounterSuperColumn;
+
+import org.apache.cassandra.thrift.CounterColumn;
+import org.apache.cassandra.thrift.CounterSuperColumn;
+
+/**
+ * Models a CounterSuperColumn in a protocol independent manner.
+ *
+ * @param
+ * CounterSuperColumn name type
+ * @param
+ * CounterColumn name type
+
+ *
+ * @author patricioe
+ */
+public final class HCounterSuperColumnImpl implements HCounterSuperColumn {
+
+ private SN superName;
+ private List> counterColumns;
+ private final Serializer superNameSerializer;
+ private final Serializer nameSerializer;
+
+ /**
+ * @param CounterSuperColumn name type
+ * @param List> CounterColumn values
+ * @param Serializer the serializer type
+ */
+ public HCounterSuperColumnImpl(SN sName, List> counterColumns,
+ Serializer sNameSerializer, Serializer nameSerializer) {
+ this(sNameSerializer, nameSerializer);
+ notNull(sName, "Name is null");
+ notNull(counterColumns, "Columns are null");
+ this.superName = sName;
+ this.counterColumns = counterColumns;
+ }
+
+ public HCounterSuperColumnImpl(CounterSuperColumn thriftCounterSuperColumn, Serializer sNameSerializer,
+ Serializer nameSerializer) {
+ this(sNameSerializer, nameSerializer);
+ noneNull(thriftCounterSuperColumn, sNameSerializer, nameSerializer);
+ superName = sNameSerializer.fromByteBuffer(ByteBuffer.wrap(thriftCounterSuperColumn.getName()));
+ counterColumns = fromThriftColumns(thriftCounterSuperColumn.getColumns());
+ }
+
+ /*package*/ HCounterSuperColumnImpl(Serializer sNameSerializer, Serializer nameSerializer) {
+ noneNull(sNameSerializer, nameSerializer);
+ this.superNameSerializer = sNameSerializer;
+ this.nameSerializer = nameSerializer;
+ }
+
+ @Override
+ public HCounterSuperColumn setName(SN name) {
+ notNull(name, "name is null");
+ this.superName = name;
+ return this;
+ }
+
+ @Override
+ public HCounterSuperColumn setSubcolumns(List> counterSubcolumns) {
+ notNull(counterSubcolumns, "subcolumns are null");
+ this.counterColumns = counterSubcolumns;
+ return this;
+ }
+
+ @Override
+ public int getSize() {
+ return counterColumns == null ? 0 : counterColumns.size();
+ }
+
+ @Override
+ public SN getName() {
+ return superName;
+ }
+
+ /**
+ *
+ * @return an unmodifiable list of counterColumns
+ */
+ @Override
+ public List> getColumns() {
+ return counterColumns;
+ }
+
+ @Override
+ public HCounterColumn get(int i) {
+ return counterColumns.get(i);
+ }
+
+ @Override
+ public Serializer getNameSerializer() {
+ return superNameSerializer;
+ }
+
+ @Override
+ public byte[] getNameBytes() {
+ return superNameSerializer.toByteBuffer(getName()).array();
+ }
+
+ public ByteBuffer getNameByteBuffer() {
+ return superNameSerializer.toByteBuffer(getName());
+ }
+
+ public CounterSuperColumn toThrift() {
+ if (superName == null || counterColumns == null) {
+ return null;
+ }
+ return new CounterSuperColumn(superNameSerializer.toByteBuffer(superName), toThriftColumn());
+ }
+
+ private List toThriftColumn() {
+ List ret = new ArrayList(counterColumns.size());
+ for (HCounterColumn c: counterColumns) {
+ ret.add(((HCounterColumnImpl) c).toThrift());
+ }
+ return ret;
+ }
+
+ private List> fromThriftColumns(List tcolumns) {
+ List> cs = new ArrayList>(tcolumns.size());
+ for (CounterColumn c: tcolumns) {
+ cs.add(new HCounterColumnImpl(c, nameSerializer));
+ }
+ return cs;
+ }
+
+ @Override
+ public Serializer getSuperNameSerializer() {
+ return superNameSerializer;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("HCounterSuperColumn(%s,%s)", superName, counterColumns);
+ }
+}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/HSlicePredicate.java b/core/src/main/java/me/prettyprint/cassandra/model/HSlicePredicate.java
index 96363e102..616e386f6 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/HSlicePredicate.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/HSlicePredicate.java
@@ -33,6 +33,8 @@ public final class HSlicePredicate {
protected enum PredicateType {Unknown, ColumnNames, Range};
protected PredicateType predicateType = PredicateType.Unknown;
+ private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]);
+
public HSlicePredicate(Serializer columnNameSerializer) {
Assert.notNull(columnNameSerializer, "columnNameSerializer can't be null");
this.columnNameSerializer = columnNameSerializer;
@@ -47,7 +49,7 @@ public HSlicePredicate(Serializer columnNameSerializer) {
public HSlicePredicate setColumnNames(N... columnNames) {
return setColumnNames(Arrays.asList(columnNames));
}
-
+
public HSlicePredicate addColumnName(N columnName) {
if ( columnNames == null )
columnNames = new ArrayList();
@@ -55,7 +57,7 @@ public HSlicePredicate addColumnName(N columnName) {
predicateType = PredicateType.ColumnNames;
return this;
}
-
+
/**
* Same as varargs signature, except we take a collection
*
@@ -80,28 +82,28 @@ public HSlicePredicate setKeysOnlyPredicate() {
}
/**
- * Set the columnName on which we will start.
- * Switches to {@link PredicateType#Range}
+ * Set the columnName on which we will start.
+ * Switches to {@link PredicateType#Range}
*/
public HSlicePredicate setStartOn(N start) {
this.start = start;
predicateType = PredicateType.Range;
return this;
}
-
+
/**
- * Set the columnName on which we will end.
- * Switches to {@link PredicateType#Range}
+ * Set the columnName on which we will end.
+ * Switches to {@link PredicateType#Range}
*/
public HSlicePredicate setEndOn(N finish) {
this.finish = finish;
predicateType = PredicateType.Range;
return this;
}
-
+
/**
* Set the number of columns to return for this slice
- * Switches to {@link PredicateType#Range}
+ * Switches to {@link PredicateType#Range}
*/
public HSlicePredicate setCount(int count) {
this.count = count;
@@ -111,19 +113,19 @@ public HSlicePredicate setCount(int count) {
}
/**
- * Sets the return order of the columns to be reversed.
- * NOTE: this is slightly less efficient than reading in comparator order.
- * Switches to {@link PredicateType#Range}
+ * Sets the return order of the columns to be reversed.
+ * NOTE: this is slightly less efficient than reading in comparator order.
+ * Switches to {@link PredicateType#Range}
*/
public HSlicePredicate setReversed(boolean reversed) {
this.reversed = reversed;
predicateType = PredicateType.Range;
return this;
}
-
-
-
-
+
+
+
+
/**
* Set a predicate of start/finish to retrieve a list of columns in this range.
* Either start and or finish can be null which will toggle the underlying predicate to
@@ -180,7 +182,7 @@ public SlicePredicate toThrift() {
private ByteBuffer findBytes(N val) {
ByteBuffer valBytes;
if (val == null) {
- valBytes = ByteBuffer.wrap(new byte[0]);
+ valBytes = EMPTY_BYTE_BUFFER;
} else {
valBytes = columnNameSerializer.toByteBuffer(val);
}
@@ -197,11 +199,11 @@ private List toThriftColumnNames(Collection clms) {
@Override
public String toString() {
- return String.format("HSlicePredicate(%s)", predicateType == PredicateType.ColumnNames ? columnNames : formatPredicate());
+ return String.format("HSlicePredicate(%s)", predicateType == PredicateType.ColumnNames ? columnNames : formatPredicate());
}
-
+
private String formatPredicate() {
- return String.format("start:[%s],end:[%s],count:%d,reversed:%b",
+ return String.format("start:[%s],end:[%s],count:%d,reversed:%b",
start != null ? start.toString() : "''",
finish != null ? finish.toString() : "''",
count, reversed);
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/HSuperColumnImpl.java b/core/src/main/java/me/prettyprint/cassandra/model/HSuperColumnImpl.java
index c4e1d47e6..48713c0a6 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/HSuperColumnImpl.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/HSuperColumnImpl.java
@@ -55,14 +55,14 @@ public HSuperColumnImpl(SN sName, List> columns, long clock,
public HSuperColumnImpl(SuperColumn thriftSuperColumn, Serializer sNameSerializer,
Serializer nameSerializer, Serializer valueSerializer) {
this(sNameSerializer, nameSerializer, valueSerializer);
- noneNull(thriftSuperColumn, sNameSerializer, nameSerializer, valueSerializer);
+ noneNull(thriftSuperColumn, sNameSerializer, nameSerializer);
superName = sNameSerializer.fromByteBuffer(ByteBuffer.wrap(thriftSuperColumn.getName()));
columns = fromThriftColumns(thriftSuperColumn.getColumns());
}
/*package*/ HSuperColumnImpl(Serializer sNameSerializer, Serializer nameSerializer,
Serializer valueSerializer) {
- noneNull(sNameSerializer, nameSerializer, valueSerializer);
+ noneNull(sNameSerializer, nameSerializer);
this.superNameSerializer = sNameSerializer;
this.nameSerializer = nameSerializer;
this.valueSerializer = valueSerializer;
@@ -126,7 +126,7 @@ public Serializer getNameSerializer() {
public byte[] getNameBytes() {
return superNameSerializer.toByteBuffer(getName()).array();
}
-
+
public ByteBuffer getNameByteBuffer() {
return superNameSerializer.toByteBuffer(getName());
}
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/IndexedSlicesQuery.java b/core/src/main/java/me/prettyprint/cassandra/model/IndexedSlicesQuery.java
index fb1cad03e..66ed268e0 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/IndexedSlicesQuery.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/IndexedSlicesQuery.java
@@ -23,7 +23,7 @@
* Uses new secondary indexes. Your CF must be configured for such to use this.
* The following creates an Indexed CF with the "birthday" column indexed (where
* birthdate represents a timestamp as it is validated by the LongType):
- *
+ *
*
* - name: Indexed1
* column_metadata:
@@ -31,7 +31,7 @@
* validator_class: LongType
* index_type: KEYS
*
- *
+ *
* @author zznate (nate@riptano.com)
*/
public class IndexedSlicesQuery extends
diff --git a/core/src/main/java/me/prettyprint/cassandra/model/MutatorImpl.java b/core/src/main/java/me/prettyprint/cassandra/model/MutatorImpl.java
index a06ea97ff..46fcb7374 100644
--- a/core/src/main/java/me/prettyprint/cassandra/model/MutatorImpl.java
+++ b/core/src/main/java/me/prettyprint/cassandra/model/MutatorImpl.java
@@ -9,11 +9,14 @@
import me.prettyprint.hector.api.Keyspace;
import me.prettyprint.hector.api.Serializer;
import me.prettyprint.hector.api.beans.HColumn;
+import me.prettyprint.hector.api.beans.HCounterColumn;
+import me.prettyprint.hector.api.beans.HCounterSuperColumn;
import me.prettyprint.hector.api.beans.HSuperColumn;
import me.prettyprint.hector.api.exceptions.HectorException;
import me.prettyprint.hector.api.mutation.MutationResult;
import me.prettyprint.hector.api.mutation.Mutator;
+import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.Deletion;
import org.apache.cassandra.thrift.SlicePredicate;
@@ -30,6 +33,7 @@
*
* @author Ran Tavory
* @author zznate
+ * @author patricioe
*/
public final class MutatorImpl implements Mutator {
@@ -69,10 +73,10 @@ public MutationResult delete(final K key, final String cf, final N columnNam
addDeletion(key, cf, columnName, nameSerializer);
return execute();
}
-
+
@Override
public MutationResult delete(K key, String cf, N columnName,
- Serializer nameSerializer, long clock) {
+ Serializer nameSerializer, long clock) {
addDeletion(key, cf, columnName, nameSerializer, clock);
return execute();
}
@@ -94,31 +98,46 @@ public Void doInKeyspace(KeyspaceService ks) throws HectorException {
return null;
}
}));
- }
-
+ }
+
+ @Override
+ public MutationResult superDelete(final K key, final String cf, final SN supercolumnName,
+ final Serializer sNameSerializer) {
+ return new MutationResultImpl(keyspace.doExecute(new KeyspaceOperationCallback() {
+ @Override
+ public Void doInKeyspace(KeyspaceService ks) throws HectorException {
+ // Remove a Super Column.
+ ks.remove(
+ keySerializer.toByteBuffer(key),
+ ThriftFactory.createSuperColumnPath(cf, supercolumnName, sNameSerializer));
+ return null;
+ }
+ }));
+ }
+
/**
* Deletes the columns defined in the HSuperColumn. If there are no HColumns attached,
- * we delete the whole thing.
- *
+ * we delete the whole thing.
+ *
*/
public Mutator addSubDelete(K key, String cf, HSuperColumn sc) {
return addSubDelete(key, cf, sc, keyspace.createClock());
}
-
+
public Mutator addSubDelete(K key, String cf, HSuperColumn sc, long clock) {
SlicePredicate pred = new SlicePredicate();
- Deletion d = new Deletion(clock);
- if ( sc.getColumns() != null ) {
+ Deletion d = new Deletion().setTimestamp(clock);
+ if ( sc.getColumns() != null ) {
for (HColumn col : sc.getColumns()) {
pred.addToColumn_names(col.getNameSerializer().toByteBuffer(col.getName()));
}
d.setPredicate(pred);
- }
+ }
d.setSuper_column(sc.getNameByteBuffer());
- getPendingMutations().addDeletion(key, Arrays.asList(cf), d);
+ getPendingMutations().addDeletion(key, Arrays.asList(cf), d);
return this;
}
-
+
// schedule an insertion to be executed in batch by the execute method
// CAVEAT: a large number of calls with a typo in one of them will leave things in an
// indeterminant state if we dont validate against LIVE (but cached of course)
@@ -149,7 +168,7 @@ public Mutator addDeletion(K key, String cf, N columnName, Serializer
addDeletion(key, cf, columnName, nameSerializer, keyspace.createClock());
return this;
}
-
+
/**
* {@inheritDoc}
*/
@@ -158,7 +177,7 @@ public Mutator addDeletion(K key, String cf) {
addDeletion(key, cf, null, null, keyspace.createClock());
return this;
}
-
+
/**
* {@inheritDoc}
*/
@@ -177,9 +196,9 @@ public Mutator addDeletion(K key, String cf, N columnName, Serializer
Deletion d;
if ( columnName != null ) {
sp.addToColumn_names(nameSerializer.toByteBuffer(columnName));
- d = new Deletion(clock).setPredicate(sp);
- } else {
- d = new Deletion(clock);
+ d = new Deletion().setTimestamp(clock).setPredicate(sp);
+ } else {
+ d = new Deletion().setTimestamp(clock);
}
getPendingMutations().addDeletion(key, Arrays.asList(cf), d);
return this;
@@ -227,4 +246,143 @@ private BatchMutation getPendingMutations() {
return pendingMutations;
}
+ // Counters support.
+
+ @Override
+ public MutationResult insertCounter(final K key, final String cf, final HCounterColumn c) {
+ return new MutationResultImpl(keyspace.doExecute(new KeyspaceOperationCallback() {
+ @Override
+ public Void doInKeyspace(KeyspaceService ks) throws HectorException {
+ ks.addCounter(keySerializer.toByteBuffer(key), new ColumnParent(cf), ((HCounterColumnImpl) c).toThrift());
+ return null;
+ }
+ }));
+ }
+
+ @Override
+ public MutationResult incrementCounter(final K key, final String cf, final N columnName, final long increment) {
+ return insertCounter(key, cf, new HCounterColumnImpl(columnName, increment, TypeInferringSerializer. get()));
+ }
+
+ @Override
+ public