Author: jbellis
Date: Mon Sep 19 16:44:18 2011
New Revision: 1172693
URL: http://svn.apache.org/viewvc?rev=1172693&view=rev
Log:
Update CQL to generate microsecond timestamps by default
patch by jbellis; reviewed by slebresne for CASSANDRA-3227
Modified:
cassandra/branches/cassandra-1.0.0/CHANGES.txt
cassandra/branches/cassandra-1.0.0/NEWS.txt
cassandra/branches/cassandra-1.0.0/doc/cql/CQL.textile
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/AbstractModification.java
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/DeleteStatement.java
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/UpdateStatement.java
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/service/ClientState.java
Modified: cassandra/branches/cassandra-1.0.0/CHANGES.txt
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/CHANGES.txt?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
--- cassandra/branches/cassandra-1.0.0/CHANGES.txt (original)
+++ cassandra/branches/cassandra-1.0.0/CHANGES.txt Mon Sep 19 16:44:18 2011
@@ -1,4 +1,5 @@
1.0.0-rc1
+ * Update CQL to generate microsecond timestamps by default (CASSANDRA-3227)
* Fix counting CFMetadata towards Memtable liveRatio (CASSANDRA-3023)
* Kill server on wrapped OOME such as from FileChannel.map (CASSANDRA-3201)
* remove unnecessary copy when adding to row cache (CASSANDRA-3223)
Modified: cassandra/branches/cassandra-1.0.0/NEWS.txt
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/NEWS.txt?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
--- cassandra/branches/cassandra-1.0.0/NEWS.txt (original)
+++ cassandra/branches/cassandra-1.0.0/NEWS.txt Mon Sep 19 16:44:18 2011
@@ -3,6 +3,13 @@
Upgrading
---------
+ - CQL inserts/updates now generate microsecond resolution timestamps
+ by default, instead of millisecond. THIS MEANS A ROLLING UPGRADE COULD
+ MIX milliseconds and microseconds, with clients talking to servers
+ generating milliseconds unable to overwrite the larger microsecond
+ timestamps. If this is important for your application, you can either
+ perform a non-rolling upgrade to 1.0, or update your application first
+ to use explicit timestamps with the "USING timestamp=X" syntax.
- the BinaryMemtable bulk-load interface has been removed. Use the
sstableloader tool instead.
- the compaction_thread_priority setting has been removed from
Modified: cassandra/branches/cassandra-1.0.0/doc/cql/CQL.textile
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/doc/cql/CQL.textile?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
--- cassandra/branches/cassandra-1.0.0/doc/cql/CQL.textile (original)
+++ cassandra/branches/cassandra-1.0.0/doc/cql/CQL.textile Mon Sep 19 16:44:18
2011
@@ -96,6 +96,8 @@ INSERT INTO <COLUMN FAMILY> (<KEY>, <col
An @INSERT@ is used to write one or more columns to a record in a Cassandra
column family. No results are returned.
+If timestamp is unspecified, the server will generate a timestamp based on
microseconds since 1970.
+
Unlike SQL, the semantics of @INSERT@ and @UPDATE@ are identical, in either
case a record is created if none existed before, and updated when it does. For
information on modifiers and types, see the "@UPDATE@":#update section below.
h2(#update). UPDATE
Modified:
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/AbstractModification.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/AbstractModification.java?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
---
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/AbstractModification.java
(original)
+++
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/AbstractModification.java
Mon Sep 19 16:44:18 2011
@@ -71,9 +71,9 @@ public abstract class AbstractModificati
return cLevel != null;
}
- public long getTimestamp()
+ public long getTimestamp(ClientState clientState)
{
- return timestamp == null ? System.currentTimeMillis() : timestamp;
+ return timestamp == null ? clientState.getTimestamp() : timestamp;
}
public boolean isSetTimestamp()
Modified:
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/DeleteStatement.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/DeleteStatement.java?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
---
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/DeleteStatement.java
(original)
+++
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/DeleteStatement.java
Mon Sep 19 16:44:18 2011
@@ -81,41 +81,39 @@ public class DeleteStatement extends Abs
for (Term key : keys)
{
- rowMutations.add(mutationForKey(key.getByteBuffer(keyType),
keyspace, timestamp));
+ rowMutations.add(mutationForKey(key.getByteBuffer(keyType),
keyspace, timestamp, clientState));
}
return rowMutations;
}
/** {@inheritDoc} */
- public RowMutation mutationForKey(ByteBuffer key, String keyspace, Long
timestamp) throws InvalidRequestException
+ public RowMutation mutationForKey(ByteBuffer key, String keyspace, Long
timestamp, ClientState clientState) throws InvalidRequestException
{
RowMutation rm = new RowMutation(keyspace, key);
- mutationForKey(rm, keyspace, timestamp);
-
- return rm;
- }
-
- /** {@inheritDoc} */
- public void mutationForKey(RowMutation mutation, String keyspace, Long
timestamp) throws InvalidRequestException
- {
CFMetaData metadata = validateColumnFamily(keyspace, columnFamily);
QueryProcessor.validateKeyAlias(metadata, keyName);
AbstractType comparator = metadata.getComparatorFor(null);
- if (columns.size() < 1) // No columns, delete the row
- mutation.delete(new QueryPath(columnFamily), (timestamp == null) ?
getTimestamp() : timestamp);
- else // Delete specific columns
+ if (columns.size() < 1)
+ {
+ // No columns, delete the row
+ rm.delete(new QueryPath(columnFamily), (timestamp == null) ?
getTimestamp(clientState) : timestamp);
+ }
+ else
{
+ // Delete specific columns
for (Term column : columns)
{
ByteBuffer columnName = column.getByteBuffer(comparator);
validateColumnName(columnName);
- mutation.delete(new QueryPath(columnFamily, null, columnName),
(timestamp == null) ? getTimestamp() : timestamp);
+ rm.delete(new QueryPath(columnFamily, null, columnName),
(timestamp == null) ? getTimestamp(clientState) : timestamp);
}
}
+
+ return rm;
}
public String toString()
Modified:
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/UpdateStatement.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/UpdateStatement.java?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
---
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/UpdateStatement.java
(original)
+++
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/cql/UpdateStatement.java
Mon Sep 19 16:44:18 2011
@@ -159,7 +159,7 @@ public class UpdateStatement extends Abs
for (Term key: keys)
{
- rowMutations.add(mutationForKey(keyspace,
key.getByteBuffer(getKeyType(keyspace)), metadata, timestamp));
+ rowMutations.add(mutationForKey(keyspace,
key.getByteBuffer(getKeyType(keyspace)), metadata, timestamp, clientState));
}
return rowMutations;
@@ -168,16 +168,18 @@ public class UpdateStatement extends Abs
/**
* Compute a row mutation for a single key
*
+ *
* @param keyspace working keyspace
* @param key key to change
* @param metadata information about CF
* @param timestamp global timestamp to use for every key mutation
*
+ * @param clientState
* @return row mutation
*
* @throws InvalidRequestException on the wrong request
*/
- private IMutation mutationForKey(String keyspace, ByteBuffer key,
CFMetaData metadata, Long timestamp) throws InvalidRequestException
+ private IMutation mutationForKey(String keyspace, ByteBuffer key,
CFMetaData metadata, Long timestamp, ClientState clientState) throws
InvalidRequestException
{
AbstractType<?> comparator = getComparator(keyspace);
@@ -200,7 +202,7 @@ public class UpdateStatement extends Abs
validateColumn(metadata, colName, colValue);
rm.add(new QueryPath(columnFamily, null, colName),
colValue,
- (timestamp == null) ? getTimestamp() : timestamp,
+ (timestamp == null) ? getTimestamp(clientState) :
timestamp,
getTimeToLive());
}
else
Modified:
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/service/ClientState.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/service/ClientState.java?rev=1172693&r1=1172692&r2=1172693&view=diff
==============================================================================
---
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/service/ClientState.java
(original)
+++
cassandra/branches/cassandra-1.0.0/src/java/org/apache/cassandra/service/ClientState.java
Mon Sep 19 16:44:18 2011
@@ -48,6 +48,8 @@ public class ClientState
// Reusable array for authorization
private final List<Object> resource = new ArrayList<Object>();
+ private long clock;
+
/**
* Construct a new, empty ClientState: can be reused after logout() or
reset().
*/
@@ -180,4 +182,16 @@ public class ClientState
perm,
Resources.toString(resource)));
}
+
+ /**
+ * This clock guarantees that updates from a given client will be ordered
in the sequence seen,
+ * even if multiple updates happen in the same millisecond. This can be
useful when a client
+ * wants to perform multiple updates to a single column.
+ */
+ public long getTimestamp()
+ {
+ long current = System.currentTimeMillis() * 1000;
+ clock = clock >= current ? clock + 1 : current;
+ return clock;
+ }
}