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;
+    }
 }


Reply via email to