cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jbel...@apache.org
Subject svn commit: r1100900 [1/2] - in /cassandra/trunk: ./ contrib/ drivers/java/src/org/apache/cassandra/cql/jdbc/ drivers/java/test/org/apache/cassandra/cql/ interface/thrift/gen-java/org/apache/cassandra/thrift/ src/java/org/apache/cassandra/config/ src/j...
Date Mon, 09 May 2011 07:05:57 GMT
Author: jbellis
Date: Mon May  9 07:05:55 2011
New Revision: 1100900

URL: http://svn.apache.org/viewvc?rev=1100900&view=rev
Log:
merge from 0.8

Added:
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/AbstractResultSet.java
      - copied unchanged from r1100898, cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/AbstractResultSet.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CResultSet.java
      - copied unchanged from r1100898, cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CResultSet.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
      - copied unchanged from r1100898, cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
    cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/ReplayPosition.java
      - copied unchanged from r1100898, cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/db/commitlog/ReplayPosition.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/AbstractUUIDType.java
      - copied unchanged from r1100898, cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/db/marshal/AbstractUUIDType.java
Removed:
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSetMetaData.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnMetaData.java
    cassandra/trunk/test/unit/org/apache/cassandra/db/commitlog/CommitLogHeaderTest.java
Modified:
    cassandra/trunk/   (props changed)
    cassandra/trunk/CHANGES.txt
    cassandra/trunk/NEWS.txt
    cassandra/trunk/contrib/   (props changed)
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
    cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Utils.java
    cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java   (props changed)
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java   (props changed)
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java   (props changed)
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java   (props changed)
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java   (props changed)
    cassandra/trunk/src/java/org/apache/cassandra/config/CFMetaData.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java
    cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java
    cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
    cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java
    cassandra/trunk/src/java/org/apache/cassandra/db/IFlushable.java
    cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java
    cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
    cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
    cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLogHeader.java
    cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLogSegment.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/AbstractCommutativeType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/AbstractType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/AsciiType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/BytesType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/IntegerType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/LocalByPartionerType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/LongType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/UTF8Type.java
    cassandra/trunk/src/java/org/apache/cassandra/db/marshal/UUIDType.java
    cassandra/trunk/src/java/org/apache/cassandra/io/sstable/Descriptor.java
    cassandra/trunk/src/java/org/apache/cassandra/io/sstable/SSTable.java
    cassandra/trunk/src/java/org/apache/cassandra/io/sstable/SSTableReader.java
    cassandra/trunk/src/java/org/apache/cassandra/io/sstable/SSTableWriter.java
    cassandra/trunk/test/system/test_cql.py
    cassandra/trunk/test/unit/org/apache/cassandra/db/CommitLogTest.java
    cassandra/trunk/test/unit/org/apache/cassandra/db/CompactionsPurgeTest.java
    cassandra/trunk/test/unit/org/apache/cassandra/db/RecoveryManager2Test.java

Propchange: cassandra/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6:922689-1052356,1052358-1053452,1053454,1053456-1081914,1083000
 /cassandra/branches/cassandra-0.7:1026516-1100465
 /cassandra/branches/cassandra-0.7.0:1053690-1055654
-/cassandra/branches/cassandra-0.8:1090935-1100470
+/cassandra/branches/cassandra-0.8:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3:774578-796573
 /incubator/cassandra/branches/cassandra-0.4:810145-834239,834349-834350

Modified: cassandra/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/CHANGES.txt (original)
+++ cassandra/trunk/CHANGES.txt Mon May  9 07:05:55 2011
@@ -12,6 +12,12 @@
  * fix returning null column values in the python cql driver (CASSANDRA-2593)
  * snapshot_before_compaction directory name fix (CASSANDRA-2598)
  
+ * fix CQL treatment of > and < operators in range slices (CASSANDRA-2592)
+ * fix potential double-application of counter updates on commitlog replay
+   (CASSANDRA-2419)
+ * JDBC CQL driver exposes getColumn for access to timestamp
+ * JDBC ResultSetMetadata properties added to AbstractType
+
 
 0.8.0-beta2
  * fix NPE compacting index CFs (CASSANDRA-2528)

Modified: cassandra/trunk/NEWS.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/NEWS.txt?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/NEWS.txt (original)
+++ cassandra/trunk/NEWS.txt Mon May  9 07:05:55 2011
@@ -6,6 +6,10 @@ Upgrading
     - Upgrading from version 0.7.1 or later can be done with a rolling
       restart, one node at a time.  You do not need to bring down the
       whole cluster.
+    - Running nodetool drain before shutting down the 0.7 node is
+      recommended but not required. (Skipping this will result in
+      replay of entire commitlog, so it will take longer to restart but
+      is otherwise harmless.)
     - Avro record classes used in map/reduce and Hadoop streaming code have
       moved from org.apache.cassandra.avro to org.apache.cassandra.hadoop.avro,
       applications using these classes will need to be updated accordingly.

Propchange: cassandra/trunk/contrib/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6/contrib:922689-1052356,1052358-1053452,1053454,1053456-1068009
 /cassandra/branches/cassandra-0.7/contrib:1026516-1100465
 /cassandra/branches/cassandra-0.7.0/contrib:1053690-1055654
-/cassandra/branches/cassandra-0.8/contrib:1090935-1100470
+/cassandra/branches/cassandra-0.8/contrib:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3/contrib:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3/contrib:774578-796573
 /incubator/cassandra/branches/cassandra-0.4/contrib:810145-810987,810994-834239,834349-834350

Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java Mon May  9 07:05:55 2011
@@ -72,21 +72,7 @@ public class CassandraPreparedStatement 
     }
     
     // impl specific methods start here.
-    
-    // determines which types need to be quoted.
-    private static boolean needsQuotes(AbstractType type) 
-    {
-        if (type instanceof ColumnMetaData)
-            return ((ColumnMetaData)type).needsQuotes();
-        else
-            return type == BytesType.instance ||
-                   type == AsciiType.instance ||
-                   type == UTF8Type.instance ||
-                   type == LexicalUUIDType.instance ||
-                   type == TimeUUIDType.instance ||
-                   type == UUIDType.instance;
-    }
-    
+
     // double quotes strings (in parameters)
     private static String makeCqlString(String s) 
     {
@@ -116,7 +102,7 @@ public class CassandraPreparedStatement 
                     Object param = params.nextParam();
                     String stringParam = type == null ? param.toString() : type.toString(param);
                     stringParam = makeCqlString(stringParam);
-                    if (type == null || needsQuotes(type))
+                    if (type == null || type.needsQuotes())
                         stringParam = "'" + stringParam + "'";
                     sb.append(stringParam);
                 }
@@ -153,7 +139,7 @@ public class CassandraPreparedStatement 
                     Object param = params.nextParam();
                     AbstractType type = left ? ltype : rtype;
                     String stringParam = makeCqlString(type.toString(param));
-                    if (needsQuotes(type))
+                    if (type.needsQuotes())
                         stringParam = "'" + stringParam + "'";
                     sb.append(stringParam);
                 }
@@ -194,12 +180,12 @@ public class CassandraPreparedStatement 
         String columnFamily = connection.getColumnFamily(cql);
         ParameterIterator params = new ParameterIterator();
         String left = cql.substring(0, pivot);
-        AbstractType leftType = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Comparator, null);
+        AbstractType leftType = connection.decoder.getComparator(keyspace, columnFamily);
         if (leftType == null)
             throw new SQLException("Could not find comparator for " + keyspace + "." + columnFamily);
         left = applySimpleBindings(left, leftType, params);
         String right = cql.substring(pivot);
-        AbstractType keyVald = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Key, null);
+        AbstractType keyVald = connection.decoder.getKeyValidator(keyspace, columnFamily);
         if (keyVald == null)
             throw new SQLException("Could not find key validator for " + keyspace + "." + columnFamily);
         right = applySimpleBindings(right, keyVald, params);
@@ -213,12 +199,12 @@ public class CassandraPreparedStatement 
         String columnFamily = connection.getColumnFamily(cql);
         ParameterIterator params = new ParameterIterator();
         String left = cql.substring(0, pivot);
-        AbstractType leftType = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Comparator, null);
+        AbstractType leftType = connection.decoder.getComparator(keyspace, columnFamily);
         if (leftType == null)
             throw new SQLException("Could not find comparator for " + keyspace + "." + columnFamily);
         left = applySimpleBindings(left, leftType, params);
         String right = cql.substring(pivot);
-        AbstractType keyVald = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Key, null);
+        AbstractType keyVald = connection.decoder.getKeyValidator(keyspace, columnFamily);
         if (keyVald == null)
             throw new SQLException("Could not find key validator for " + keyspace + "." + columnFamily);
         right = applySimpleBindings(right, keyVald, params);
@@ -234,15 +220,15 @@ public class CassandraPreparedStatement 
         String columnFamily = connection.getColumnFamily(cql);
         ParameterIterator params = new ParameterIterator();
         String left = cql.substring(0, pivot);
-        AbstractType leftComp = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Comparator, null);
+        AbstractType leftComp = connection.decoder.getComparator(keyspace, columnFamily);
         if (leftComp == null)
             throw new SQLException("Could not find comparator for " + keyspace + "." + columnFamily);
-        AbstractType leftVald = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Validator, null);
+        AbstractType leftVald = connection.decoder.getComparator(keyspace, columnFamily);
         if (leftVald == null)
             throw new SQLException("Could not find validator for " + keyspace + "." + columnFamily);
         left = applyDualBindings(left, leftComp, leftVald, params);
         String right = cql.substring(pivot);
-        AbstractType keyVald = connection.decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Key, null);
+        AbstractType keyVald = connection.decoder.getKeyValidator(keyspace, columnFamily);
         if (keyVald == null)
             throw new SQLException("Could not find key validator for " + keyspace + "." + columnFamily);
         right = applySimpleBindings(right, keyVald, params);

Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java Mon May  9 07:05:55 2011
@@ -235,7 +235,7 @@ class CassandraStatement implements Stat
         {
             CqlResult rSet = connection.execute(query);
             // todo: encapsulate.
-            return new CassandraResultSet(rSet, connection.decoder, connection.curKeyspace, connection.curColumnFamily);
+            return new CResultSet(rSet, connection.decoder, connection.curKeyspace, connection.curColumnFamily);
         }
         catch (InvalidRequestException e)
         {

Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java Mon May  9 07:05:55 2011
@@ -21,13 +21,14 @@ package org.apache.cassandra.cql.jdbc;
  */
 
 
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.config.ConfigurationException;
 import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.thrift.CfDef;
-import org.apache.cassandra.thrift.ColumnDef;
-import org.apache.cassandra.thrift.KsDef;
+import org.apache.cassandra.thrift.*;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,160 +37,76 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-/** Decodes columns from bytes into instances of their respective expected types. */
-class ColumnDecoder 
+/**
+ * Decodes columns from bytes into instances of their respective expected types.
+ */
+class ColumnDecoder
 {
     private static final Logger logger = LoggerFactory.getLogger(ColumnDecoder.class);
-    private static final String MapFormatString = "%s.%s.%s.%s";
-    
-    // basically denotes column or value.
-    enum Specifier
-    {
-        Comparator,
-        Validator,
-        Key,
-        ColumnSpecific
-    }
-    
-    private Map<String, CfDef> cfDefs = new HashMap<String, CfDef>();
-    
-    // cache the comparators for efficiency.
-    private Map<String, AbstractType> comparators = new HashMap<String, AbstractType>();
-    
-    /** is specific per set of keyspace definitions. */
+
+    private final Map<String, CFMetaData> metadata = new HashMap<String, CFMetaData>();
+
+    /**
+     * is specific per set of keyspace definitions.
+     */
     public ColumnDecoder(List<KsDef> defs)
     {
-        for (KsDef ks : defs) 
+        for (KsDef ks : defs)
         {
             for (CfDef cf : ks.getCf_defs())
             {
-                cfDefs.put(String.format("%s.%s", ks.getName(), cf.getName()), cf);
-                for (ColumnDef cd : cf.getColumn_metadata()) 
+                try
+                {
+                    metadata.put(String.format("%s.%s", ks.getName(), cf.getName()), CFMetaData.convertToCFMetaData(cf));
+                }
+                catch (InvalidRequestException e)
                 {
-                    try 
-                    {
-                        // prefill the validators (because they aren't kept in a convenient lookup map and we don't
-                        // want to iterate over the list for every miss in getComparator.
-                        comparators.put(String.format(MapFormatString, 
-                                ks.getName(), 
-                                cf.getName(),
-                                Specifier.ColumnSpecific.name(),
-                                ByteBufferUtil.bytesToHex(cd.bufferForName())), 
-                                   FBUtilities.getComparator(cd.getValidation_class()));
-                    } 
-                    catch (ConfigurationException ex) {
-                        throw new RuntimeException(ex);
-                    }
+                    throw new RuntimeException(e);
+                }
+                catch (ConfigurationException e)
+                {
+                    throw new RuntimeException(e);
                 }
             }
         }
     }
 
-    /**
-     * @param keyspace ALWAYS specify
-     * @param columnFamily ALWAYS specify
-     * @param specifier ALWAYS specify
-     * @param def avoids additional map lookup if specified. null is ok though.
-     * @return
-     */
-    AbstractType getComparator(String keyspace, String columnFamily, Specifier specifier, CfDef def)
+    AbstractType getComparator(String keyspace, String columnFamily)
     {
-        return getComparator(keyspace, columnFamily, null, specifier, def);
+        return metadata.get(String.format("%s.%s", keyspace, columnFamily)).comparator;
     }
-    
-    // same as above, but can get column-specific validators.
-    AbstractType getComparator(String keyspace, String columnFamily, byte[] column, Specifier specifier, CfDef def) 
-    {
-        // check cache first.
-        String key = String.format(MapFormatString, 
-                                   keyspace, 
-                                   columnFamily, 
-                                   specifier.name(), 
-                                   FBUtilities.bytesToHex(column == null ? new byte[] {} : column));
-        AbstractType comparator = comparators.get(key);
 
-        // make and put in cache.
-        if (comparator == null) 
-        {
-            if (def == null)
-                def = cfDefs.get(String.format("%s.%s", keyspace, columnFamily));
-            if (def == null)
-                // no point in proceeding. these values are bad.
-                return null;
-            try 
-            {
-                switch (specifier)
-                {
-                    case Key:
-                        comparator = FBUtilities.getComparator(def.getKey_validation_class());
-                        break;
-                    case ColumnSpecific:
-                        // if we get here this means there is no column-specific validator, so fall through to the default.
-                    case Validator:
-                        comparator = FBUtilities.getComparator(def.getDefault_validation_class());
-                        break;
-                    case Comparator:
-                    default:
-                        comparator = FBUtilities.getComparator(def.getComparator_type());
-                        break;
-                }
-                comparators.put(key, comparator);
-            }
-            catch (ConfigurationException ex)
-            {
-                throw new RuntimeException(ex);
-            }
-        }
-        return comparator;
+    AbstractType getNameType(String keyspace, String columnFamily, ByteBuffer name)
+    {
+
+        CFMetaData md = metadata.get(String.format("%s.%s", keyspace, columnFamily));
+        return md.comparator;
     }
 
-    /**
-     * uses the AbstractType to map a column name to a string.  Relies on AT.fromString() and AT.getString()
-     * @param keyspace
-     * @param columnFamily
-     * @param name
-     * @return
-     */
-    public String colNameAsString(String keyspace, String columnFamily, String name) 
+    AbstractType getValueType(String keyspace, String columnFamily, ByteBuffer name)
     {
-        AbstractType comparator = getComparator(keyspace, columnFamily, Specifier.Comparator, null);
-        ByteBuffer bb = comparator.fromString(name);
-        return comparator.getString(bb);
+        CFMetaData md = metadata.get(String.format("%s.%s", keyspace, columnFamily));
+        ColumnDefinition cd = md.getColumnDefinition(name);
+        return cd == null ? md.getDefaultValidator() : cd.getValidator();
     }
 
-    /**
-     * uses the AbstractType to map a column name to a string.
-     * @param keyspace
-     * @param columnFamily
-     * @param name
-     * @return
-     */
-    public String colNameAsString(String keyspace, String columnFamily, byte[] name) 
+    public AbstractType getKeyValidator(String keyspace, String columnFamily)
     {
-        AbstractType comparator = getComparator(keyspace, columnFamily, Specifier.Comparator, null);
-        return comparator.getString(ByteBuffer.wrap(name));
+        return metadata.get(String.format("%s.%s", keyspace, columnFamily)).getKeyValidator();
     }
 
-    /**
-     * converts a column value to a string.
-     * @param value
-     * @return
-     */
-    public static String colValueAsString(Object value) {
-        if (value instanceof String)
-            return (String)value;
-        else if (value instanceof byte[])
-            return ByteBufferUtil.bytesToHex(ByteBuffer.wrap((byte[])value));
-        else
-            return value == null ? null : value.toString();
+    /** uses the AbstractType to map a column name to a string. */
+    public String colNameAsString(String keyspace, String columnFamily, ByteBuffer name)
+    {
+        AbstractType comparator = getNameType(keyspace, columnFamily, name);
+        return comparator.getString(name);
     }
-    
+
     /** constructs a typed column */
-    public TypedColumn makeCol(String keyspace, String columnFamily, byte[] name, byte[] value)
+    public TypedColumn makeCol(String keyspace, String columnFamily, Column column)
     {
-        CfDef cfDef = cfDefs.get(String.format("%s.%s", keyspace, columnFamily));
-        AbstractType comparator = getComparator(keyspace, columnFamily, Specifier.Comparator, cfDef);
-        AbstractType validator = getComparator(keyspace, columnFamily, name, Specifier.ColumnSpecific, null);
-        return new TypedColumn(comparator, name, validator, value);
+        return new TypedColumn(column,
+                               getNameType(keyspace, columnFamily, column.name),
+                               getValueType(keyspace, columnFamily, column.name));
     }
 }

Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java Mon May  9 07:05:55 2011
@@ -22,37 +22,36 @@ package org.apache.cassandra.cql.jdbc;
 
 
 import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.thrift.Column;
 
 import java.nio.ByteBuffer;
 
-class TypedColumn<N, V>
+class TypedColumn
 {
-    private final N name;
-    private final V value;
-    
-    // we cache the string versions of the byte buffers here.  It turns out that {N|V}.toString() isn't always the same
-    // (a good example is byte buffers) as the stringified versions supplied by the AbstractTypes.
+    private final Column rawColumn;
+
+    // we cache the frequently-accessed forms: java object for value, String for name.
+    // Note that {N|V}.toString() isn't always the same as Type.getString
+    // (a good example is byte buffers).
+    private final Object value;
     private final String nameString;
-    private final String valueString;
-    private final AbstractType<V> validator;
-    
-    public TypedColumn(AbstractType<N> comparator, byte[] name, AbstractType<V> validator, byte[] value)
+    private final AbstractType nameType, valueType;
+
+    public TypedColumn(Column column, AbstractType comparator, AbstractType validator)
     {
-        ByteBuffer bbName = ByteBuffer.wrap(name);
-        ByteBuffer bbValue = value == null ? null : ByteBuffer.wrap(value);
-        this.name = comparator.compose(bbName);
-        this.value = value == null ? null : validator.compose(bbValue);
-        nameString = comparator.getString(bbName);
-        valueString = value == null ? null : validator.getString(bbValue);
-        this.validator = validator;
+        rawColumn = column;
+        this.value = column.value == null ? null : validator.compose(column.value);
+        nameString = comparator.getString(column.name);
+        nameType = comparator;
+        valueType = validator;
     }
-    
-    public N getName()
+
+    public Column getRawColumn()
     {
-        return name;
+        return rawColumn;
     }
     
-    public V getValue()
+    public Object getValue()
     {
         return value;
     }
@@ -64,11 +63,16 @@ class TypedColumn<N, V>
     
     public String getValueString()
     {
-        return valueString;
+        return valueType.getString(rawColumn.value);
     }
     
-    public AbstractType<V> getValidator()
+    public AbstractType getNameType()
+    {
+        return nameType;
+    }
+
+    public AbstractType getValueType()
     {
-        return validator;
+        return valueType;
     }
 }

Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Utils.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Utils.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Utils.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Utils.java Mon May  9 07:05:55 2011
@@ -63,40 +63,4 @@ class Utils
         
         return ByteBuffer.wrap(byteArray.toByteArray());
     }
-    
-    static int getJdbcType(AbstractType type) throws SQLException
-    {   
-        if (type instanceof ColumnMetaData)
-            return ((ColumnMetaData)type).getType();
-        else if (type == IntegerType.instance)
-            return Types.BIGINT;
-        else if (type.getType().equals(Long.class))
-            return Types.BIGINT; // not the best fit.
-        else if (type.getType().equals(String.class))
-            return Types.VARCHAR;
-        else if (type.getType().equals(UUID.class))
-            return Types.TIMESTAMP;
-        else if (type == BytesType.instance)
-            return Types.BINARY;
-        else
-            throw new SQLException("Uninterpretable JDBC type " + type.getClass().getName());
-    }
-    
-    static boolean isTypeSigned(AbstractType type)
-    {
-        if (type == IntegerType.instance || type == LongType.instance)
-            return true;
-        else if (type instanceof ColumnMetaData) 
-            return ((ColumnMetaData)type).isSigned();
-        else
-            return false;
-    }
-    
-    static int getTypeScale(AbstractType type) 
-    {
-        if (type instanceof ColumnMetaData)
-            return ((ColumnMetaData)type).getScale();
-        else
-            return 0;
-    }
 }

Modified: cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java (original)
+++ cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java Mon May  9 07:05:55 2011
@@ -25,27 +25,18 @@ import java.lang.reflect.InvocationTarge
 import java.lang.reflect.Method;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Types;
+import java.sql.*;
 import java.util.Arrays;
 
-import org.apache.cassandra.cql.jdbc.CassandraResultSetMetaData;
-import org.apache.cassandra.db.marshal.AsciiType;
-import org.apache.cassandra.db.marshal.BytesType;
-import org.apache.cassandra.db.marshal.IntegerType;
-import org.apache.cassandra.db.marshal.LongType;
-import org.apache.cassandra.db.marshal.UTF8Type;
-import org.apache.cassandra.utils.FBUtilities;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import org.apache.cassandra.db.marshal.*;
+import org.apache.cassandra.utils.FBUtilities;
+
+import static junit.framework.Assert.assertEquals;
+
 /**
  * Test case for unit test of various methods of JDBC implementation.
  */
@@ -71,9 +62,9 @@ public class JdbcDriverTest extends Embe
             "UPDATE JdbcInteger SET 1 = 11, 2 = 22, 42='fortytwo' WHERE KEY = '" + jsmith + "'",
             "UPDATE JdbcInteger SET 3 = 33, 4 = 44 WHERE KEY = '" + jsmith + "'",
             "UPDATE JdbcLong SET 1 = 11, 2 = 22 WHERE KEY = '" + jsmith + "'",
-            "UPDATE JdbcAscii SET 'first' = 'firstrec', 'last' = 'lastrec' WHERE key = '" + jsmith + "'",
+            "UPDATE JdbcAscii SET 'first' = 'firstrec', last = 'lastrec' WHERE key = '" + jsmith + "'",
             String.format("UPDATE JdbcBytes SET '%s' = '%s', '%s' = '%s' WHERE key = '%s'", first, firstrec, last, lastrec, jsmith),
-            "UPDATE JdbcUtf8 SET 'first' = 'firstrec', 'fortytwo' = '42', 'last' = 'lastrec' WHERE key = '" + jsmith + "'",
+            "UPDATE JdbcUtf8 SET 'first' = 'firstrec', fortytwo = '42', last = 'lastrec' WHERE key = '" + jsmith + "'",
         };
         for (String q : inserts)
         {
@@ -91,32 +82,25 @@ public class JdbcDriverTest extends Embe
     private static void expectedMetaData(ResultSetMetaData md, int col, String colClass, String table, String schema,
                                   String label, int type, String typeName, boolean signed, boolean caseSensitive) throws SQLException
     {
-        assert colClass.equals(md.getColumnClassName(col)); // full class name of type<T>
-        assert table.equals(md.getTableName(col));
-        assert schema.equals(md.getSchemaName(col));
-        assert label.equals(md.getColumnLabel(col)) : "expected " + label + " got " + md.getColumnLabel(col);
-        assert label.equals(md.getColumnName(col));
-        assert type == md.getColumnType(col);
-        assert typeName.equals(md.getColumnTypeName(col)) : "expected " + typeName + " got " + md.getColumnTypeName(col); // simple name of abstract type.
-        assert md.isSigned(col) == signed;
-        assert md.isCaseSensitive(col) == caseSensitive;
+        assertEquals(colClass, md.getColumnClassName(col)); // full class name of type<T>
+        assertEquals(table, md.getTableName(col));
+        assertEquals(schema, md.getSchemaName(col));
+        assertEquals(label, md.getColumnLabel(col));
+        assertEquals(label, md.getColumnName(col));
+        assertEquals(type, md.getColumnType(col));
+        assertEquals(typeName, md.getColumnTypeName(col));
+        assertEquals(signed, md.isSigned(col));
+        assertEquals(caseSensitive, md.isCaseSensitive(col));
     }
     
-    private static void expectedMetaData(CassandraResultSetMetaData md, int col,
-                                         String nameClass, int nameType, String nameTypeName, boolean nameSigned, boolean nameCaseSense,
+    private static void expectedMetaData(ResultSetMetaData md, int col,
                                          String valuClass, int valuType, String valuTypeName, boolean valuSigned, boolean valuCaseSense) throws SQLException
     {
-        assert nameClass.equals(md.getNameClassName(col));
-        assert nameType == md.getNameType(col);
-        assert nameTypeName.equals(md.getNameTypeName(col));
-        assert nameSigned == md.isNameSigned(col);
-        assert nameCaseSense == md.isNameCaseSensitive(col);
-        
-        assert valuClass.equals(md.getValueClassName(col));
-        assert valuType == md.getValueType(col);
-        assert valuTypeName.equals(md.getValueTypeName(col));
-        assert valuSigned == md.isValueSigned(col);
-        assert valuCaseSense == md.isValueCaseSensitive(col);
+        assertEquals(valuClass, md.getColumnClassName(col));
+        assertEquals(valuType, md.getColumnType(col));
+        assertEquals(valuTypeName, md.getColumnTypeName(col));
+        assertEquals(valuSigned, md.isSigned(col));
+        assertEquals(valuCaseSense, md.isCaseSensitive(col));
     }
     
     @Test
@@ -124,11 +108,10 @@ public class JdbcDriverTest extends Embe
     {
         String key = FBUtilities.bytesToHex("Integer".getBytes());
         Statement stmt = con.createStatement();
-        stmt.executeUpdate("update JdbcInteger set 1=1111, 2=2222, 42='fortytwofortytwo' where key='" + key + "'");
+        stmt.executeUpdate("update JdbcInteger set 1=36893488147419103232, 42='fortytwofortytwo' where key='" + key + "'");
         ResultSet rs = stmt.executeQuery("select 1, 2, 42 from JdbcInteger where key='" + key + "'");
         assert rs.next();
-        assert rs.getInt("1") == 1111;
-        assert rs.getInt("2") == 2222;
+        assert rs.getObject("1").equals(new BigInteger("36893488147419103232"));
         assert rs.getString("42").equals("fortytwofortytwo") : rs.getString("42");
         
         ResultSetMetaData md = rs.getMetaData();
@@ -137,8 +120,8 @@ public class JdbcDriverTest extends Embe
         expectedMetaData(md, 2, BigInteger.class.getName(), "JdbcInteger", "Keyspace1", "2", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
         expectedMetaData(md, 3, String.class.getName(), "JdbcInteger", "Keyspace1", "42", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
         
-        stmt.executeUpdate("update JdbcUtf8 set 'a'='aa', 'b'='bb', 'fortytwo'='4242' where key='" + key + "'");
-        rs = stmt.executeQuery("select 'a', 'b', 'fortytwo' from JdbcUtf8 where key='" + key + "'");
+        stmt.executeUpdate("update JdbcUtf8 set a='aa', b='bb', fortytwo='4242' where key='" + key + "'");
+        rs = stmt.executeQuery("select a, b, fortytwo from JdbcUtf8 where key='" + key + "'");
         assert rs.next();
         assert rs.getString("a").equals("aa");
         assert rs.getString("b").equals("bb");
@@ -149,32 +132,7 @@ public class JdbcDriverTest extends Embe
         expectedMetaData(md, 2, String.class.getName(), "JdbcUtf8", "Keyspace1", "b", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
         expectedMetaData(md, 3, BigInteger.class.getName(), "JdbcUtf8", "Keyspace1", "fortytwo", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
     }
-    
-    @Test 
-    public void testIntegerMetadata() throws SQLException
-    {
-        String key = FBUtilities.bytesToHex("Integer".getBytes());
-        Statement stmt = con.createStatement();
-        stmt.executeUpdate("UPDATE JdbcInteger SET 1=111, 2=222 WHERE KEY = '" + key + "'");
-        ResultSet rs = stmt.executeQuery("SELECT 1, 2 from JdbcInteger WHERE KEY = '" + key + "'");
-        assert rs.next();
-        assert rs.getInt("1") == 111;
-        assert rs.getInt("2") == 222;
         
-        ResultSetMetaData md = rs.getMetaData();
-        assert md.getColumnCount() == 2;
-        expectedMetaData(md, 1, BigInteger.class.getName(), "JdbcInteger", "Keyspace1", "1", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
-        expectedMetaData(md, 2, BigInteger.class.getName(), "JdbcInteger", "Keyspace1", "2", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
-
-        CassandraResultSetMetaData cmd = md.unwrap(CassandraResultSetMetaData.class);
-        for (int i = 0; i < md.getColumnCount(); i++)
-            expectedMetaData(
-                    cmd, i+1, 
-                    BigInteger.class.getName(), Types.BIGINT, IntegerType.class.getSimpleName(), true, false,
-                    BigInteger.class.getName(), Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
-        
-    }
-    
     @Test
     public void testLongMetadata() throws SQLException
     {
@@ -188,27 +146,23 @@ public class JdbcDriverTest extends Embe
         
         ResultSetMetaData md = rs.getMetaData();
         assert md.getColumnCount() == 2;
-        expectedMetaData(md, 1, Long.class.getName(), "JdbcLong", "Keyspace1", "1", Types.BIGINT, LongType.class.getSimpleName(), true, false);
-        expectedMetaData(md, 2, Long.class.getName(), "JdbcLong", "Keyspace1", "2", Types.BIGINT, LongType.class.getSimpleName(), true, false);
+        expectedMetaData(md, 1, Long.class.getName(), "JdbcLong", "Keyspace1", "1", Types.INTEGER, LongType.class.getSimpleName(), true, false);
+        expectedMetaData(md, 2, Long.class.getName(), "JdbcLong", "Keyspace1", "2", Types.INTEGER, LongType.class.getSimpleName(), true, false);
         
-        CassandraResultSetMetaData cmd = md.unwrap(CassandraResultSetMetaData.class);
         for (int i = 0; i < md.getColumnCount(); i++)
-            expectedMetaData(
-                    cmd, i+1,
-                    Long.class.getName(), Types.BIGINT, LongType.class.getSimpleName(), true, false,
-                    Long.class.getName(), Types.BIGINT, LongType.class.getSimpleName(), true, false);
+            expectedMetaData(md, i + 1, Long.class.getName(), Types.INTEGER, LongType.class.getSimpleName(), true, false);
     }
-    
+
     @Test
     public void testStringMetadata() throws SQLException
     {
         String aKey = FBUtilities.bytesToHex("ascii".getBytes());
         String uKey = FBUtilities.bytesToHex("utf8".getBytes());
         Statement stmt = con.createStatement();
-        stmt.executeUpdate("UPDATE JdbcAscii SET 'a'='aa', 'b'='bb' WHERE KEY = '" + aKey + "'");
-        stmt.executeUpdate("UPDATE JdbcUtf8 SET 'a'='aa', 'b'='bb' WHERE KEY = '" + uKey + "'");
-        ResultSet rs0 = stmt.executeQuery("SELECT 'a', 'b' FROM JdbcAscii WHERE KEY = '" + aKey + "'");
-        ResultSet rs1 = stmt.executeQuery("SELECT 'a', 'b' FROM JdbcUtf8 WHERE KEY = '" + uKey + "'");
+        stmt.executeUpdate("UPDATE JdbcAscii SET a='aa', b='bb' WHERE KEY = '" + aKey + "'");
+        stmt.executeUpdate("UPDATE JdbcUtf8 SET a='aa', b='bb' WHERE KEY = '" + uKey + "'");
+        ResultSet rs0 = stmt.executeQuery("SELECT a, b FROM JdbcAscii WHERE KEY = '" + aKey + "'");
+        ResultSet rs1 = stmt.executeQuery("SELECT a, b FROM JdbcUtf8 WHERE KEY = '" + uKey + "'");
         for (ResultSet rs : new ResultSet[] { rs0, rs1 }) 
         {
             assert rs.next();
@@ -224,18 +178,24 @@ public class JdbcDriverTest extends Embe
         assert md.getColumnCount() == 2;
         expectedMetaData(md, 1, String.class.getName(), "JdbcUtf8", "Keyspace1", "a", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
         expectedMetaData(md, 2, String.class.getName(), "JdbcUtf8", "Keyspace1", "b", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
-        
-        CassandraResultSetMetaData cmd0 = rs0.getMetaData().unwrap(CassandraResultSetMetaData.class);
-        CassandraResultSetMetaData cmd1 = rs1.getMetaData().unwrap(CassandraResultSetMetaData.class);
+
         for (int i = 0; i < 2; i++)
         {
-            expectedMetaData(cmd0, i+1,
-                    String.class.getName(), Types.VARCHAR, AsciiType.class.getSimpleName(), false, true,
-                    String.class.getName(), Types.VARCHAR, AsciiType.class.getSimpleName(), false, true);
-            expectedMetaData(cmd1, i+1,
-                    String.class.getName(), Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true,
-                    String.class.getName(), Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
-            
+            expectedMetaData(rs0.getMetaData(),
+                             i + 1,
+                             String.class.getName(),
+                             Types.VARCHAR,
+                             AsciiType.class.getSimpleName(),
+                             false,
+                             true);
+            expectedMetaData(rs1.getMetaData(),
+                             i + 1,
+                             String.class.getName(),
+                             Types.VARCHAR,
+                             UTF8Type.class.getSimpleName(),
+                             false,
+                             true);
+
         }
     }
     
@@ -268,13 +228,10 @@ public class JdbcDriverTest extends Embe
         expectedMetaData(md, 1, ByteBuffer.class.getName(), "JdbcBytes", "Keyspace1", FBUtilities.bytesToHex(a), Types.BINARY, BytesType.class.getSimpleName(), false, false);
         expectedMetaData(md, 2, ByteBuffer.class.getName(), "JdbcBytes", "Keyspace1", FBUtilities.bytesToHex(b), Types.BINARY, BytesType.class.getSimpleName(), false, false);
         
-        CassandraResultSetMetaData cmd = md.unwrap(CassandraResultSetMetaData.class);
         for (int i = 0; i < md.getColumnCount(); i++)
-            expectedMetaData(cmd, i+1,
-                    ByteBuffer.class.getName(), Types.BINARY, BytesType.class.getSimpleName(), false, false,
-                    ByteBuffer.class.getName(), Types.BINARY, BytesType.class.getSimpleName(), false, false);
+            expectedMetaData(md, i + 1, ByteBuffer.class.getName(), Types.BINARY, BytesType.class.getSimpleName(), false, false);
     }
-    
+
     @Test
     public void testWithStatementBytesType() throws SQLException
     {
@@ -305,13 +262,13 @@ public class JdbcDriverTest extends Embe
         selectQ = "SELECT 1, 2 FROM JdbcLong WHERE KEY='" + jsmith + "'";
         checkResultSet(stmt.executeQuery(selectQ), "Long", 1, "1", "2");
         
-        selectQ = "SELECT 'first', 'last' FROM JdbcAscii WHERE KEY='" + jsmith + "'";
+        selectQ = "SELECT 'first', last FROM JdbcAscii WHERE KEY='" + jsmith + "'";
         checkResultSet(stmt.executeQuery(selectQ), "String", 1, "first", "last");
         
         selectQ = String.format("SELECT '%s', '%s' FROM JdbcBytes WHERE KEY='%s'", first, last, jsmith);
         checkResultSet(stmt.executeQuery(selectQ), "Bytes", 1, first, last);
         
-        selectQ = "SELECT 'first', 'last' FROM JdbcUtf8 WHERE KEY='" + jsmith + "'";
+        selectQ = "SELECT 'first', last FROM JdbcUtf8 WHERE KEY='" + jsmith + "'";
         checkResultSet(stmt.executeQuery(selectQ), "String", 1, "first", "last");
     }
     
@@ -344,13 +301,13 @@ public class JdbcDriverTest extends Embe
         selectQ = "SELECT 1, 2 FROM JdbcLong WHERE KEY='" + jsmith + "'";
         checkResultSet(executePreparedStatementWithResults(con, selectQ), "Long", 1, "1", "2");
         
-        selectQ = "SELECT 'first', 'last' FROM JdbcAscii WHERE KEY='" + jsmith + "'";
+        selectQ = "SELECT 'first', last FROM JdbcAscii WHERE KEY='" + jsmith + "'";
         checkResultSet(executePreparedStatementWithResults(con, selectQ), "String", 1, "first", "last");
         
         selectQ = String.format("SELECT '%s', '%s' FROM JdbcBytes WHERE KEY='%s'", first, last, jsmith);
         checkResultSet(executePreparedStatementWithResults(con, selectQ), "Bytes", 1, first, last);
         
-        selectQ = "SELECT 'first', 'last' FROM JdbcUtf8 WHERE KEY='" + jsmith + "'";
+        selectQ = "SELECT 'first', last FROM JdbcUtf8 WHERE KEY='" + jsmith + "'";
         checkResultSet(executePreparedStatementWithResults(con, selectQ), "String", 1, "first", "last");
     }
 
@@ -383,7 +340,7 @@ public class JdbcDriverTest extends Embe
                 
                 "DELETE 'first' FROM JdbcAscii WHERE KEY='" + jsmith + "'",
                 "SELECT 'first' FROM JdbcAscii WHERE KEY='" + jsmith + "'",
-                "SELECT 'last' FROM JdbcAscii WHERE KEY='" + jsmith + "'",
+                "SELECT last FROM JdbcAscii WHERE KEY='" + jsmith + "'",
                 
                 String.format("DELETE '%s' FROM JdbcBytes WHERE KEY='%s'", first, jsmith),
                 String.format("SELECT '%s' FROM JdbcBytes WHERE KEY='%s'", first, jsmith),
@@ -391,7 +348,7 @@ public class JdbcDriverTest extends Embe
                 
                 "DELETE 'first' FROM JdbcUtf8 WHERE KEY='" + jsmith + "'",
                 "SELECT 'first' FROM JdbcUtf8 WHERE KEY='" + jsmith + "'",
-                "SELECT 'last' FROM JdbcUtf8 WHERE KEY='" + jsmith + "'",
+                "SELECT last FROM JdbcUtf8 WHERE KEY='" + jsmith + "'",
         };
         
         for (int i = 0; i < statements.length/3; i++) 
@@ -455,9 +412,7 @@ public class JdbcDriverTest extends Embe
             actualRows++;
             for (int c = 0; c < cols.length; c++)
             {
-                // getString and getObject should always work.
-                assert rs.getString(cols[c]) != null;
-                assert rs.getString(c+1) != null;
+                // getObject should always work.
                 assert rs.getObject(cols[c]) != null;
                 assert rs.getObject(c+1) != null;
                 

Propchange: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java:922689-1052356,1052358-1053452,1053454,1053456-1081914,1083000
 /cassandra/branches/cassandra-0.7/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java:1026516-1100465
 /cassandra/branches/cassandra-0.7.0/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java:1053690-1055654
-/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java:1090935-1100470
+/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3/interface/gen-java/org/apache/cassandra/service/Cassandra.java:774578-796573
 /incubator/cassandra/branches/cassandra-0.4/interface/gen-java/org/apache/cassandra/service/Cassandra.java:810145-834239,834349-834350

Propchange: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java:922689-1052356,1052358-1053452,1053454,1053456-1081914,1083000
 /cassandra/branches/cassandra-0.7/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java:1026516-1100465
 /cassandra/branches/cassandra-0.7.0/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java:1053690-1055654
-/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java:1090935-1100470
+/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3/interface/gen-java/org/apache/cassandra/service/column_t.java:774578-792198
 /incubator/cassandra/branches/cassandra-0.4/interface/gen-java/org/apache/cassandra/service/Column.java:810145-834239,834349-834350

Propchange: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java:922689-1052356,1052358-1053452,1053454,1053456-1081914,1083000
 /cassandra/branches/cassandra-0.7/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java:1026516-1100465
 /cassandra/branches/cassandra-0.7.0/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java:1053690-1055654
-/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java:1090935-1100470
+/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3/interface/thrift/gen-java/org/apache/cassandra/thrift/InvalidRequestException.java:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3/interface/gen-java/org/apache/cassandra/service/InvalidRequestException.java:774578-796573
 /incubator/cassandra/branches/cassandra-0.4/interface/gen-java/org/apache/cassandra/service/InvalidRequestException.java:810145-834239,834349-834350

Propchange: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java:922689-1052356,1052358-1053452,1053454,1053456-1081914,1083000
 /cassandra/branches/cassandra-0.7/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java:1026516-1100465
 /cassandra/branches/cassandra-0.7.0/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java:1053690-1055654
-/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java:1090935-1100470
+/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3/interface/thrift/gen-java/org/apache/cassandra/thrift/NotFoundException.java:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3/interface/gen-java/org/apache/cassandra/service/NotFoundException.java:774578-796573
 /incubator/cassandra/branches/cassandra-0.4/interface/gen-java/org/apache/cassandra/service/NotFoundException.java:810145-834239,834349-834350

Propchange: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon May  9 07:05:55 2011
@@ -1,7 +1,7 @@
 /cassandra/branches/cassandra-0.6/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java:922689-1052356,1052358-1053452,1053454,1053456-1081914,1083000
 /cassandra/branches/cassandra-0.7/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java:1026516-1100465
 /cassandra/branches/cassandra-0.7.0/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java:1053690-1055654
-/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java:1090935-1100470
+/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java:1090935-1100898
 /cassandra/tags/cassandra-0.7.0-rc3/interface/thrift/gen-java/org/apache/cassandra/thrift/SuperColumn.java:1051699-1053689
 /incubator/cassandra/branches/cassandra-0.3/interface/gen-java/org/apache/cassandra/service/superColumn_t.java:774578-792198
 /incubator/cassandra/branches/cassandra-0.4/interface/gen-java/org/apache/cassandra/service/SuperColumn.java:810145-834239,834349-834350

Modified: cassandra/trunk/src/java/org/apache/cassandra/config/CFMetaData.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/config/CFMetaData.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/config/CFMetaData.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/config/CFMetaData.java Mon May  9 07:05:55 2011
@@ -984,6 +984,11 @@ public final class CFMetaData
             comparator.validate(cf_def.key_alias);
     }
 
+    public ColumnDefinition getColumnDefinition(ByteBuffer name)
+    {
+        return column_metadata.get(name);
+    }
+
     @Override
     public String toString()
     {

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java Mon May  9 07:05:55 2011
@@ -80,6 +80,7 @@ public class QueryProcessor
         AbstractType<?> comparator = select.getComparator(keyspace);
         List<ReadCommand> commands = new ArrayList<ReadCommand>();
 
+        assert select.getKeys().size() == 1;
         CFMetaData metadata = validateColumnFamily(keyspace, select.getColumnFamily(), false);
 
         // ...of a list of column names
@@ -138,11 +139,20 @@ public class QueryProcessor
     private static List<org.apache.cassandra.db.Row> multiRangeSlice(String keyspace, SelectStatement select)
     throws TimedOutException, UnavailableException, InvalidRequestException
     {
+        List<org.apache.cassandra.db.Row> rows;
+        IPartitioner<?> p = StorageService.getPartitioner();
+
         AbstractType<?> keyType = DatabaseDescriptor.getCFMetaData(keyspace,
                                                                    select.getColumnFamily()).getKeyValidator();
-        ByteBuffer startKey = (select.getKeyStart() != null) ? select.getKeyStart().getByteBuffer(keyType) : (new Term()).getByteBuffer();
-        ByteBuffer finishKey = (select.getKeyFinish() != null) ? select.getKeyFinish().getByteBuffer(keyType) : (new Term()).getByteBuffer();
-        IPartitioner<?> p = StorageService.getPartitioner();
+
+        ByteBuffer startKey = (select.getKeyStart() != null)
+                               ? select.getKeyStart().getByteBuffer(keyType)
+                               : (new Term()).getByteBuffer();
+
+        ByteBuffer finishKey = (select.getKeyFinish() != null)
+                                ? select.getKeyFinish().getByteBuffer(keyType)
+                                : (new Term()).getByteBuffer();
+
         AbstractBounds bounds = new Bounds(p.getToken(startKey), p.getToken(finishKey));
         
         CFMetaData metadata = validateColumnFamily(keyspace, select.getColumnFamily(), false);
@@ -151,14 +161,18 @@ public class QueryProcessor
         SlicePredicate thriftSlicePredicate = slicePredicateFromSelect(select, comparator);
         validateSlicePredicate(metadata, thriftSlicePredicate);
 
+        int limit = select.isKeyRange() && select.getKeyStart() != null
+                  ? select.getNumRecords() + 1
+                  : select.getNumRecords();
+
         try
         {
-            return StorageProxy.getRangeSlice(new RangeSliceCommand(keyspace,
+            rows = StorageProxy.getRangeSlice(new RangeSliceCommand(keyspace,
                                                                     select.getColumnFamily(),
                                                                     null,
                                                                     thriftSlicePredicate,
                                                                     bounds,
-                                                                    select.getNumRecords()),
+                                                                    limit),
                                                                     select.getConsistencyLevel());
         }
         catch (IOException e)
@@ -173,6 +187,23 @@ public class QueryProcessor
         {
             throw new TimedOutException();
         }
+
+        // if start key was set and relation was "greater than"
+        if (select.getKeyStart() != null && !select.includeStartKey())
+        {
+            if (rows.get(0).key.key.equals(startKey))
+                rows.remove(0);
+        }
+
+        // if finish key was set and relation was "less than"
+        if (select.getKeyFinish() != null && !select.includeFinishKey())
+        {
+            int lastIndex = rows.size() - 1;
+            if (rows.get(lastIndex).key.key.equals(finishKey))
+                rows.remove(lastIndex);
+        }
+
+        return rows.subList(0, select.getNumRecords() < rows.size() ? select.getNumRecords() : rows.size());
     }
     
     private static List<org.apache.cassandra.db.Row> getIndexedSlices(String keyspace, SelectStatement select)

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java Mon May  9 07:05:55 2011
@@ -126,7 +126,17 @@ public class SelectStatement
     {
         return isCountOper;
     }
-    
+
+    public boolean includeStartKey()
+    {
+        return clause.includeStartKey();
+    }
+
+    public boolean includeFinishKey()
+    {
+        return clause.includeFinishKey();
+    }
+
     public AbstractType getComparator(String keyspace)
     {
         return DatabaseDescriptor.getComparator(keyspace, columnFamily);

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/WhereClause.java Mon May  9 07:05:55 2011
@@ -33,7 +33,8 @@ public class WhereClause
     private List<Term> keys = new ArrayList<Term>();
     private Term startKey, finishKey;
     private List<Relation> columns = new ArrayList<Relation>();
-    
+    private boolean includeStartKey = false, includeFinishKey = false;
+
     /**
      * Create a new WhereClause with the first parsed relation.
      * 
@@ -61,9 +62,15 @@ public class WhereClause
             if (relation.operator().equals(RelationType.EQ))
                 keys.add(relation.getValue());
             else if ((relation.operator().equals(RelationType.GT) || relation.operator().equals(RelationType.GTE)))
+            {
                 startKey = relation.getValue();
+                includeStartKey = relation.operator().equals(RelationType.GTE);
+            }
             else if ((relation.operator().equals(RelationType.LT) || relation.operator().equals(RelationType.LTE)))
+            {
                 finishKey = relation.getValue();
+                includeFinishKey = relation.operator().equals(RelationType.LTE);
+            }
             
         }
         else
@@ -108,4 +115,14 @@ public class WhereClause
     {
         return keys;
     }
+
+    public boolean includeStartKey()
+    {
+        return includeStartKey;
+    }
+
+    public boolean includeFinishKey()
+    {
+        return includeFinishKey;
+    }
 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java Mon May  9 07:05:55 2011
@@ -35,6 +35,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.db.commitlog.ReplayPosition;
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.io.sstable.SSTableReader;
 import org.apache.cassandra.io.sstable.SSTableWriter;
@@ -83,7 +84,7 @@ public class BinaryMemtable implements I
                 if (!isFrozen)
                 {
                     isFrozen = true;
-                    cfs.submitFlush(this, new CountDownLatch(1));
+                    cfs.submitFlush(this, new CountDownLatch(1), null);
                     cfs.switchBinaryMemtable(key, buffer);
                 }
                 else
@@ -122,10 +123,10 @@ public class BinaryMemtable implements I
         return keys;
     }
 
-    private SSTableReader writeSortedContents(List<DecoratedKey> sortedKeys) throws IOException
+    private SSTableReader writeSortedContents(List<DecoratedKey> sortedKeys, ReplayPosition context) throws IOException
     {
         logger.info("Writing " + this);
-        SSTableWriter writer = cfs.createFlushWriter(sortedKeys.size(), DatabaseDescriptor.getBMTThreshold());
+        SSTableWriter writer = cfs.createFlushWriter(sortedKeys.size(), DatabaseDescriptor.getBMTThreshold(), context);
 
         for (DecoratedKey key : sortedKeys)
         {
@@ -138,7 +139,7 @@ public class BinaryMemtable implements I
         return sstable;
     }
 
-    public void flushAndSignal(final CountDownLatch latch, ExecutorService sorter, final ExecutorService writer)
+    public void flushAndSignal(final CountDownLatch latch, ExecutorService sorter, final ExecutorService writer, final ReplayPosition context)
     {
         sorter.execute(new Runnable()
         {
@@ -149,7 +150,7 @@ public class BinaryMemtable implements I
                 {
                     public void runMayThrow() throws IOException
                     {
-                        cfs.addSSTable(writeSortedContents(sortedKeys));
+                        cfs.addSSTable(writeSortedContents(sortedKeys, context));
                         latch.countDown();
                     }
                 });

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Mon May  9 07:05:55 2011
@@ -52,7 +52,7 @@ import org.apache.cassandra.config.Confi
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.db.columniterator.IColumnIterator;
 import org.apache.cassandra.db.commitlog.CommitLog;
-import org.apache.cassandra.db.commitlog.CommitLogSegment;
+import org.apache.cassandra.db.commitlog.ReplayPosition;
 import org.apache.cassandra.db.filter.*;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.BytesType;
@@ -645,7 +645,7 @@ public class ColumnFamilyStore implement
 
             assert getMemtableThreadSafe() == oldMemtable;
             oldMemtable.freeze();
-            final CommitLogSegment.CommitLogContext ctx = writeCommitLog ? CommitLog.instance.getContext() : null;
+            final ReplayPosition ctx = writeCommitLog ? CommitLog.instance.getContext() : null;
 
             // submit the memtable for any indexed sub-cfses, and our own.
             List<ColumnFamilyStore> icc = new ArrayList<ColumnFamilyStore>(indexedColumns.size());
@@ -657,7 +657,7 @@ public class ColumnFamilyStore implement
             }
             final CountDownLatch latch = new CountDownLatch(icc.size());
             for (ColumnFamilyStore cfs : icc)
-                submitFlush(cfs.data.switchMemtable(), latch);
+                submitFlush(cfs.data.switchMemtable(), latch, ctx);
 
             // we marked our memtable as frozen as part of the concurrency control,
             // so even if there was nothing to flush we need to switch it out
@@ -739,7 +739,7 @@ public class ColumnFamilyStore implement
         if (binaryMemtable.get().isClean())
             return;
 
-        submitFlush(binaryMemtable.get(), new CountDownLatch(1));
+        submitFlush(binaryMemtable.get(), new CountDownLatch(1), null);
     }
 
     public void updateRowCache(DecoratedKey key, ColumnFamily columnFamily)
@@ -1006,10 +1006,10 @@ public class ColumnFamilyStore implement
      * flushing thread finishes sorting, which will almost always be longer than any of the flushSorter threads proper
      * (since, by definition, it started last).
      */
-    void submitFlush(IFlushable flushable, CountDownLatch latch)
+    void submitFlush(IFlushable flushable, CountDownLatch latch, ReplayPosition context)
     {
         logger.info("Enqueuing flush of {}", flushable);
-        flushable.flushAndSignal(latch, flushSorter, flushWriter);
+        flushable.flushAndSignal(latch, flushSorter, flushWriter, context);
     }
 
     public long getMemtableColumnsCount()
@@ -2116,14 +2116,15 @@ public class ColumnFamilyStore implement
         return intern(name);
     }
 
-    public SSTableWriter createFlushWriter(long estimatedRows, long estimatedSize) throws IOException
+    public SSTableWriter createFlushWriter(long estimatedRows, long estimatedSize, ReplayPosition context) throws IOException
     {
-        return new SSTableWriter(getFlushPath(estimatedSize, Descriptor.CURRENT_VERSION), estimatedRows, metadata, partitioner);
+        return new SSTableWriter(getFlushPath(estimatedSize, Descriptor.CURRENT_VERSION), estimatedRows, metadata, partitioner, context);
     }
 
-    public SSTableWriter createCompactionWriter(long estimatedRows, String location) throws IOException
+    public SSTableWriter createCompactionWriter(long estimatedRows, String location, Collection<SSTableReader> sstables) throws IOException
     {
-        return new SSTableWriter(getTempSSTablePath(location), estimatedRows, metadata, partitioner);
+        ReplayPosition rp = ReplayPosition.getReplayPosition(sstables);
+        return new SSTableWriter(getTempSSTablePath(location), estimatedRows, metadata, partitioner, rp);
     }
 
     public Iterable<ColumnFamilyStore> concatWithIndexes()

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/CompactionManager.java Mon May  9 07:05:55 2011
@@ -564,7 +564,7 @@ public class CompactionManager implement
                 return 0;
             }
 
-            writer = cfs.createCompactionWriter(expectedBloomFilterSize, compactionFileLocation);
+            writer = cfs.createCompactionWriter(expectedBloomFilterSize, compactionFileLocation, sstables);
             while (nni.hasNext())
             {
                 AbstractCompactedRow row = nni.next();
@@ -652,7 +652,7 @@ public class CompactionManager implement
                 assert firstRowPositionFromIndex == 0 : firstRowPositionFromIndex;
             }
 
-            SSTableWriter writer = maybeCreateWriter(cfs, compactionFileLocation, expectedBloomFilterSize, null);
+            SSTableWriter writer = maybeCreateWriter(cfs, compactionFileLocation, expectedBloomFilterSize, null, Collections.singletonList(sstable));
             executor.beginCompaction(new ScrubInfo(dataFile, sstable));
             int goodRows = 0, badRows = 0, emptyRows = 0;
 
@@ -840,7 +840,7 @@ public class CompactionManager implement
                         SSTableIdentityIterator row = (SSTableIdentityIterator) scanner.next();
                         if (Range.isTokenInRanges(row.getKey().token, ranges))
                         {
-                            writer = maybeCreateWriter(cfs, compactionFileLocation, expectedBloomFilterSize, writer);
+                            writer = maybeCreateWriter(cfs, compactionFileLocation, expectedBloomFilterSize, writer, Collections.singletonList(sstable));
                             writer.append(getCompactedRow(row, sstable.descriptor, false));
                             totalkeysWritten++;
                         }
@@ -921,13 +921,13 @@ public class CompactionManager implement
                : new PrecompactedRow(CompactionController.getBasicController(forceDeserialize), Arrays.asList(row));
     }
 
-    private SSTableWriter maybeCreateWriter(ColumnFamilyStore cfs, String compactionFileLocation, int expectedBloomFilterSize, SSTableWriter writer)
+    private SSTableWriter maybeCreateWriter(ColumnFamilyStore cfs, String compactionFileLocation, int expectedBloomFilterSize, SSTableWriter writer, Collection<SSTableReader> sstables)
             throws IOException
     {
         if (writer == null)
         {
             FileUtils.createDirectory(compactionFileLocation);
-            writer = cfs.createCompactionWriter(expectedBloomFilterSize, compactionFileLocation);
+            writer = cfs.createCompactionWriter(expectedBloomFilterSize, compactionFileLocation, sstables);
         }
         return writer;
     }

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/IFlushable.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/IFlushable.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/IFlushable.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/IFlushable.java Mon May  9 07:05:55 2011
@@ -24,7 +24,9 @@ package org.apache.cassandra.db;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 
+import org.apache.cassandra.db.commitlog.ReplayPosition;
+
 public interface IFlushable
 {
-    public void flushAndSignal(CountDownLatch condition, ExecutorService sorter, ExecutorService writer);
+    public void flushAndSignal(CountDownLatch condition, ExecutorService sorter, ExecutorService writer, ReplayPosition context);
 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java Mon May  9 07:05:55 2011
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.concurrent.DebuggableThreadPoolExecutor;
 import org.apache.cassandra.db.columniterator.IColumnIterator;
 import org.apache.cassandra.db.columniterator.SimpleAbstractColumnIterator;
+import org.apache.cassandra.db.commitlog.ReplayPosition;
 import org.apache.cassandra.db.filter.AbstractColumnIterator;
 import org.apache.cassandra.db.filter.NamesQueryFilter;
 import org.apache.cassandra.db.filter.SliceQueryFilter;
@@ -231,7 +232,7 @@ public class Memtable implements Compara
     }
 
 
-    private SSTableReader writeSortedContents() throws IOException
+    private SSTableReader writeSortedContents(ReplayPosition context) throws IOException
     {
         logger.info("Writing " + this);
 
@@ -242,7 +243,7 @@ public class Memtable implements Compara
                                       + keySize // keys in data file
                                       + currentThroughput.get()) // data
                                      * 1.2); // bloom filter and row index overhead
-        SSTableWriter writer = cfs.createFlushWriter(columnFamilies.size(), estimatedSize);
+        SSTableWriter writer = cfs.createFlushWriter(columnFamilies.size(), estimatedSize, context);
 
         // (we can't clear out the map as-we-go to free up memory,
         //  since the memtable is being used for queries in the "pending flush" category)
@@ -255,7 +256,7 @@ public class Memtable implements Compara
         return ssTable;
     }
 
-    public void flushAndSignal(final CountDownLatch latch, ExecutorService sorter, final ExecutorService writer)
+    public void flushAndSignal(final CountDownLatch latch, ExecutorService sorter, final ExecutorService writer, final ReplayPosition context)
     {
         writer.execute(new WrappedRunnable()
         {
@@ -266,7 +267,7 @@ public class Memtable implements Compara
                 {
                     if (!cfs.isDropped())
                     {
-                        SSTableReader sstable = writeSortedContents();
+                        SSTableReader sstable = writeSortedContents(context);
                         cfs.replaceFlushed(Memtable.this, sstable);
                     }
                 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Mon May  9 07:05:55 2011
@@ -36,6 +36,7 @@ import org.apache.cassandra.config.Confi
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.KSMetaData;
 import org.apache.cassandra.db.commitlog.CommitLog;
+import org.apache.cassandra.db.commitlog.ReplayPosition;
 import org.apache.cassandra.db.filter.QueryFilter;
 import org.apache.cassandra.db.filter.QueryPath;
 import org.apache.cassandra.dht.LocalToken;
@@ -748,7 +749,8 @@ public class Table
     }
 
     @Override
-    public String toString() {
+    public String toString()
+    {
         return getClass().getSimpleName() + "(name='" + name + "')";
     }
 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java?rev=1100900&r1=1100899&r2=1100900&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/commitlog/CommitLog.java Mon May  9 07:05:55 2011
@@ -27,6 +27,11 @@ import java.util.concurrent.atomic.Atomi
 import java.util.zip.CRC32;
 import java.util.zip.Checksum;
 
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Ordering;
+
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.io.sstable.SSTable;
 import org.apache.cassandra.net.MessagingService;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -37,10 +42,6 @@ import org.apache.cassandra.concurrent.S
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.Config;
 import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.db.ColumnFamily;
-import org.apache.cassandra.db.RowMutation;
-import org.apache.cassandra.db.Table;
-import org.apache.cassandra.db.UnserializableColumnFamilyException;
 import org.apache.cassandra.io.DeletionService;
 import org.apache.cassandra.io.util.BufferedRandomAccessFile;
 import org.apache.cassandra.io.util.FileUtils;
@@ -133,7 +134,7 @@ public class CommitLog
         return false;
     }
 
-    public static void recover() throws IOException
+    public static int recover() throws IOException
     {
         String directory = DatabaseDescriptor.getCommitLogLocation();
         File[] files = new File(directory).listFiles(new FilenameFilter()
@@ -149,49 +150,63 @@ public class CommitLog
         if (files.length == 0)
         {
             logger.info("No commitlog files found; skipping replay");
-            return;
+            return 0;
         }
 
         Arrays.sort(files, new FileUtils.FileComparator());
         logger.info("Replaying " + StringUtils.join(files, ", "));
-        recover(files);
+        int replayed = recover(files);
         for (File f : files)
         {
-            FileUtils.delete(CommitLogHeader.getHeaderPathFromSegmentPath(f.getAbsolutePath())); // may not actually exist
             if (!f.delete())
                 logger.error("Unable to remove " + f + "; you should remove it manually or next restart will replay it again (harmless, but time-consuming)");
         }
-        logger.info("Log replay complete");
+        logger.info("Log replay complete, " + replayed + " replayed mutations");
+        return replayed;
     }
 
-    public static void recover(File[] clogs) throws IOException
+    // returns the number of replayed mutation (useful for tests in particular)
+    public static int recover(File[] clogs) throws IOException
     {
         Set<Table> tablesRecovered = new HashSet<Table>();
         List<Future<?>> futures = new ArrayList<Future<?>>();
         byte[] bytes = new byte[4096];
         Map<Integer, AtomicInteger> invalidMutations = new HashMap<Integer, AtomicInteger>();
 
-        for (File file : clogs)
+        // count the number of replayed mutation. We don't really care about atomicity, but we need it to be a reference.
+        final AtomicInteger replayedCount = new AtomicInteger();
+
+        // compute per-CF and global replay positions
+        final Map<Integer, ReplayPosition> cfPositions = new HashMap<Integer, ReplayPosition>();
+        for (ColumnFamilyStore cfs : ColumnFamilyStore.all())
         {
+            // it's important to call RP.gRP per-cf, before aggregating all the positions w/ the Ordering.min call
+            // below: gRP will return NONE if there are no flushed sstables, which is important to have in the
+            // list (otherwise we'll just start replay from the first flush position that we do have, which is not correct).
+            ReplayPosition rp = ReplayPosition.getReplayPosition(cfs.getSSTables());
+            cfPositions.put(cfs.metadata.cfId, rp);
+        }
+        final ReplayPosition globalPosition = Ordering.from(ReplayPosition.comparator).min(cfPositions.values());
+
+        for (final File file : clogs)
+        {
+            final long segment = CommitLogSegment.idFromFilename(file.getName());
+
             int bufferSize = (int) Math.min(Math.max(file.length(), 1), 32 * 1024 * 1024);
             BufferedRandomAccessFile reader = new BufferedRandomAccessFile(new File(file.getAbsolutePath()), "r", bufferSize, true);
+            assert reader.length() <= Integer.MAX_VALUE;
 
             try
             {
-                CommitLogHeader clHeader = null;
-                int replayPosition = 0;
-                String headerPath = CommitLogHeader.getHeaderPathFromSegmentPath(file.getAbsolutePath());
-                try
-                {
-                    clHeader = CommitLogHeader.readCommitLogHeader(headerPath);
-                    replayPosition = clHeader.getReplayPosition();
-                }
-                catch (IOException ioe)
-                {
-                    logger.info(headerPath + " incomplete, missing or corrupt.  Everything is ok, don't panic.  CommitLog will be replayed from the beginning");
-                    logger.debug("exception was", ioe);
-                }
-                if (replayPosition < 0 || replayPosition > reader.length())
+                int replayPosition;
+                if (globalPosition.segment < segment)
+                    replayPosition = 0;
+                else if (globalPosition.segment == segment)
+                    replayPosition = globalPosition.position;
+                else
+                    replayPosition = (int) reader.length();
+
+                if (replayPosition < 0 || replayPosition >= reader.length())
                 {
                     // replayPosition > reader.length() can happen if some data gets flushed before it is written to the commitlog
                     // (see https://issues.apache.org/jira/browse/CASSANDRA-2285)
@@ -277,7 +292,6 @@ public class CommitLog
                     tablesRecovered.add(table);
                     final Collection<ColumnFamily> columnFamilies = new ArrayList<ColumnFamily>(rm.getColumnFamilies());
                     final long entryLocation = reader.getFilePointer();
-                    final CommitLogHeader finalHeader = clHeader;
                     final RowMutation frm = rm;
                     Runnable runnable = new WrappedRunnable()
                     {
@@ -294,8 +308,15 @@ public class CommitLog
                                     // null means the cf has been dropped
                                     continue;
 
-                                if (finalHeader == null || (finalHeader.isDirty(columnFamily.id()) && entryLocation > finalHeader.getPosition(columnFamily.id())))
+                                ReplayPosition rp = cfPositions.get(columnFamily.id());
+
+                                // replay if current segment is newer than last flushed one or, if it is the last known
+                                // segment, if we are after the replay position
+                                if (segment > rp.segment || (segment == rp.segment && entryLocation > rp.position))
+                                {
                                     newRm.add(columnFamily);
+                                    replayedCount.incrementAndGet();
+                                }
                             }
                             if (!newRm.isEmpty())
                             {
@@ -330,6 +351,8 @@ public class CommitLog
         for (Table table : tablesRecovered)
             futures.addAll(table.flush());
         FBUtilities.waitOnFutures(futures);
+
+        return replayedCount.get();
     }
 
     private CommitLogSegment currentSegment()
@@ -337,11 +360,11 @@ public class CommitLog
         return segments.getLast();
     }
     
-    public CommitLogSegment.CommitLogContext getContext()
+    public ReplayPosition getContext()
     {
-        Callable<CommitLogSegment.CommitLogContext> task = new Callable<CommitLogSegment.CommitLogContext>()
+        Callable<ReplayPosition> task = new Callable<ReplayPosition>()
         {
-            public CommitLogSegment.CommitLogContext call() throws Exception
+            public ReplayPosition call() throws Exception
             {
                 return currentSegment().getContext();
             }
@@ -377,7 +400,7 @@ public class CommitLog
      * The bit flag associated with this column family is set in the
      * header and this is used to decide if the log file can be deleted.
     */
-    public void discardCompletedSegments(final Integer cfId, final CommitLogSegment.CommitLogContext context) throws IOException
+    public void discardCompletedSegments(final Integer cfId, final ReplayPosition context) throws IOException
     {
         Callable task = new Callable()
         {
@@ -408,7 +431,7 @@ public class CommitLog
      * param @ id id of the columnFamily being flushed to disk.
      *
     */
-    private void discardCompletedSegmentsInternal(CommitLogSegment.CommitLogContext context, Integer id) throws IOException
+    private void discardCompletedSegmentsInternal(ReplayPosition context, Integer id) throws IOException
     {
         if (logger.isDebugEnabled())
             logger.debug("discard completed log segments for " + context + ", column family " + id + ".");
@@ -423,26 +446,20 @@ public class CommitLog
         while (iter.hasNext())
         {
             CommitLogSegment segment = iter.next();
-            CommitLogHeader header = segment.getHeader();
-            if (segment.equals(context.getSegment()))
+            if (segment.id == context.segment)
             {
                 // we can't just mark the segment where the flush happened clean,
                 // since there may have been writes to it between when the flush
-                // started and when it finished. so mark the flush position as
-                // the replay point for this CF, instead.
-                if (logger.isDebugEnabled())
-                    logger.debug("Marking replay position " + context.position + " on commit log " + segment);
-                header.turnOn(id, context.position);
-                segment.writeHeader();
+                // started and when it finished.
+                segment.turnOn(id);
                 break;
             }
 
-            header.turnOff(id);
-            if (header.isSafeToDelete() && iter.hasNext())
+            segment.turnOff(id);
+            if (segment.isSafeToDelete() && iter.hasNext())
             {
                 logger.info("Discarding obsolete commit log:" + segment);
                 segment.close();
-                DeletionService.executeDelete(segment.getHeaderPath());
                 DeletionService.executeDelete(segment.getPath());
                 // usually this will be the first (remaining) segment, but not always, if segment A contains
                 // writes to a CF that is unflushed but is followed by segment B whose CFs are all flushed.
@@ -451,8 +468,7 @@ public class CommitLog
             else
             {
                 if (logger.isDebugEnabled())
-                    logger.debug("Not safe to delete commit log " + segment + "; dirty is " + header.dirtyString());
-                segment.writeHeader();
+                    logger.debug("Not safe to delete commit log " + segment + "; dirty is " + segment.dirtyString() + "; hasNext: " + iter.hasNext());
             }
         }
     }



Mime
View raw message